<!-- SOLIDABILITY-WORLD · part 22 -->
y than OBSERVED evidence for specific symptoms
          _priority: 2,
        });
      });
    }

    // Pattern: login/auth issues → auth-related files/routes
    // Evidence: OBSERVED (route definitions directly seen in source)
    if (/login|auth|password|session|sign.?in/.test(s)) {
      layout.rooms.forEach(room => {
        const authRoutes = room.routes.filter(r => /login|auth|session/i.test(r.name));
        const isAuth = (room.filePath && /auth|login|session/i.test(room.filePath)) || authRoutes.length > 0;
        if (isAuth) {
          const displayName = room.filePath && room.filePath !== room.label
            ? `${room.label} (${room.filePath})` : room.label;
          candidates.push({
            room: displayName,
            file: room.filePath,
            evidence: `Contains ${authRoutes.length} auth routes (directly observed in source).`,
            evidenceState: 'OBSERVED',
            evidenceNote: 'Route definitions verified in analyzed source.',
            key: room.key,
            // OBSERVED evidence outranks INFERRED for symptom-specific queries
            _priority: 1,
          });
        }
      });
    }

    // Pattern: specific route → find it
    // Evidence: VERIFIED (exact string match in route table)
    const routeMatch = s.match(/(\/[a-z0-9\-_\/:]+)/);
    if (routeMatch) {
      const routePath = routeMatch[1];
      layout.rooms.forEach(room => {
        const match = room.routes.find(r =>
          r.name.toLowerCase().includes(routePath));
        if (match) {
          candidates.push({
            room: room.label,
            file: room.filePath,
            evidence: `Defines route ${match.name} at line ${match.line}.`,
            evidenceState: 'VERIFIED',
            evidenceNote: 'Exact match in analyzed route table.',
            key: room.key,
          });
        }
      });
    }

    // Pattern: error/500/crash → high-branching files
    // Evidence: INFERRED (more paths = more failure modes, not observed)
    if (/error|500|crash|broken|fail/.test(s)) {
      const sorted = [...layout.rooms]
        .filter(r => r.complexity > 200)
        .sort((a, b) => b.complexity - a.complexity)
        .slice(0, 3);
      sorted.forEach(room => {
        candidates.push({
          room: room.label,
          file: room.filePath,
          evidence: `Complexity ${room.complexity} with high branching.`,
          evidenceState: 'INFERRED',
          evidenceNote: 'More code paths means more failure modes, but specific error not traced.',
          key: room.key,
        });
      });
    }

    // Sort: OBSERVED evidence first (directly relevant), then INFERRED
    candidates.sort((a, b) => (a._priority || 3) - (b._priority || 3));
    const result = {
      symptom,
      candidates: candidates.slice(0, 8),
      timestamp: new Date().toISOString(),
    };
    logInvestigation('problem-locate', `Located candidates for: "${symptom}"`, result);
    return result;
  }

  // Change Impact Engine
  // "What breaks if I change X?"
  function analyzeImpact(roomKey) {
    const layout = SWWorld.getLayout();
    if (!layout) return null;
    const room = layout.rooms.find(r => r.key === roomKey);
    if (!room) return null;

    const impacted = {
      file: room.filePath,
      directDependents: [],
      routesAffected: room.routes.length,
      estimatedBlast: 'unknown',
    };

    // Find files that depend on this one
    layout.rooms.forEach(other => {
      if (other.key === roomKey) return;
      const deps = other.dependencies || [];
      const dependsOn = deps.some(d => {
        const depName = d.replace('./', '').replace('../', '');
        return room.filePath && room.filePath.includes(depName);
      });
      if (dependsOn) {
        impacted.directDependents.push({
          file: other.filePath,
          label: other.label,
        });
      }
    });

    // Blast radius estimate
    const depCount = impacted.directDependents.length;
    const routeCount = impacted.routesAffected;
    if (depCount === 0 && routeCount === 0) impacted.estimatedBlast = 'isolated';
    else if (depCount <= 3 && routeCount <= 10) impacted.estimatedBlast = 'contained';
    else if (depCount <= 10 || routeCount <= 50) impacted.estimatedBlast = 'moderate';
    else impacted.estimatedBlast = 'wide';

    const result = {
      ...impacted,
      timestamp: new Date().toISOString(),
      note: 'Based on static dependency analysis. Runtime coupling may differ.',
    };
    logInvestigation('impact-analysis', `Impact for changing ${room.filePath}`, result);
    return result;
  }

  // Investigation history
  function logInvestigation(type, summary, data) {
    investigationHistory.push({
      id: 'inv_' + Date.now(),
      timestamp: new Date().toISOString(),
      type,
      summary,
      dataSummary: JSON.stringify(data).slice(0, 500),
    });
    if (investigationHistory.length > 50) investigationHistory.shift();
  }

