@sightmap/react 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +15 -7
- package/dist/cli/index.js.map +1 -1
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -785,7 +785,7 @@ function normalize(s) {
|
|
|
785
785
|
}
|
|
786
786
|
|
|
787
787
|
// src/plugin/orchestrator.ts
|
|
788
|
-
import { loadDirectory } from "@sightmap/sightmap";
|
|
788
|
+
import { loadDirectory, canonicalize } from "@sightmap/sightmap";
|
|
789
789
|
async function runOnce(opts) {
|
|
790
790
|
const adapter = await resolveAdapter(opts.router, opts.projectRoot);
|
|
791
791
|
if (!adapter) {
|
|
@@ -888,9 +888,11 @@ async function runOnce(opts) {
|
|
|
888
888
|
emittedAnyView = true;
|
|
889
889
|
}
|
|
890
890
|
if (emittedAnyView && currentYaml !== null) {
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
891
|
+
const finalYaml = toCanonical(currentYaml, filePath);
|
|
892
|
+
const changed = anyChanged || finalYaml !== before;
|
|
893
|
+
changes.push({ path: filePath, before, after: finalYaml, changed });
|
|
894
|
+
if (changed && !opts.dryRun) {
|
|
895
|
+
await atomicWrite(filePath, finalYaml);
|
|
894
896
|
written.push(filePath);
|
|
895
897
|
}
|
|
896
898
|
}
|
|
@@ -906,9 +908,11 @@ async function runOnce(opts) {
|
|
|
906
908
|
components: sharedComponents
|
|
907
909
|
}
|
|
908
910
|
});
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
911
|
+
const finalYaml = toCanonical(merged.yaml, filePath);
|
|
912
|
+
const changed = merged.changed || finalYaml !== existing;
|
|
913
|
+
changes.push({ path: filePath, before: existing, after: finalYaml, changed });
|
|
914
|
+
if (changed && !opts.dryRun) {
|
|
915
|
+
await atomicWrite(filePath, finalYaml);
|
|
912
916
|
written.push(filePath);
|
|
913
917
|
}
|
|
914
918
|
}
|
|
@@ -956,6 +960,10 @@ async function readIfExists(path) {
|
|
|
956
960
|
throw e;
|
|
957
961
|
}
|
|
958
962
|
}
|
|
963
|
+
function toCanonical(yaml, file) {
|
|
964
|
+
const c = canonicalize(yaml, { file });
|
|
965
|
+
return c.kind === "canonical" ? c.text : yaml;
|
|
966
|
+
}
|
|
959
967
|
async function atomicWrite(path, contents) {
|
|
960
968
|
await fs5.mkdir(dirname3(path), { recursive: true });
|
|
961
969
|
const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/gen.ts","../../src/plugin/orchestrator.ts","../../src/plugin/adapters/index.ts","../../src/plugin/adapters/rr7-declarative.ts","../../src/plugin/router-adapter.ts","../../src/plugin/diagnostics.ts","../../src/plugin/adapters/rr7-framework.ts","../../src/plugin/ast/scan.ts","../../src/plugin/merge/smart-merge.ts","../../src/plugin/merge/todo-scaffolding.ts","../../src/cli/commands/gen-summary.ts","../../src/cli/commands/validate.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { genCommand } from \"./commands/gen.js\";\nimport { validateCommand } from \"./commands/validate.js\";\n\nconst program = new Command()\n .name(\"sightmap-react\")\n .description(\"CLI for @sightmap/react: regenerate, validate, and inspect React sightmaps offline.\")\n .version(\"0.1.0\");\n\nprogram\n .command(\"gen\")\n .description(\"Run the build pipeline once and write any changed feature files.\")\n .option(\"--cwd <path>\", \"project root\", process.cwd())\n .option(\"--router <name>\", \"router adapter\", \"react-router-7\")\n .option(\"--output <dir>\", \"output dir\", \".sightmap\")\n .option(\"--check\", \"dry-run; exit 1 if any .sightmap file would change\")\n .option(\"--diff\", \"dry-run; print unified diff of would-be changes to stdout\")\n .option(\n \"--live <url>\",\n \"ALSO fetch a runtime sightmap from a running dev server at <url> (e.g. http://localhost:5173/__sightmap__/sightmap.json) and surface live-only views as info diagnostics. Optional; when omitted, only static AST discovery runs.\",\n )\n .action(genCommand);\n\nprogram\n .command(\"validate\")\n .description(\"Validate the .sightmap/ directory; surface React-specific drift diagnostics.\")\n .option(\"--cwd <path>\", \"project root\", process.cwd())\n .option(\"--output <dir>\", \"output dir\", \".sightmap\")\n .option(\"--router <name>\", \"router adapter (used for drift checks)\", \"react-router-7\")\n .action(validateCommand);\n\nprogram.parseAsync(process.argv).catch((err) => {\n console.error(err);\n process.exit(1);\n});\n","// src/cli/commands/gen.ts\n//\n// `sightmap-react gen` — one-shot codegen for `.sightmap/`.\n//\n// Default: write any changed feature files.\n// `--check`: dry-run; exit 1 if any file would change. CI gate.\n// `--diff`: dry-run; print a unified diff of would-be changes to stdout.\n//\n// Both flags imply dry-run (no filesystem writes). They compose: `--check --diff`\n// prints diffs AND exits non-zero on drift.\n\nimport { relative } from \"node:path\";\nimport { createTwoFilesPatch } from \"diff\";\nimport { runOnce, type LiveSightmapSnapshot } from \"../../plugin/orchestrator.js\";\nimport type { RouterChoice } from \"../../plugin/adapters/index.js\";\nimport { formatSummary } from \"./gen-summary.js\";\n\nexport type GenCommandOptions = {\n cwd: string;\n router: string;\n output: string;\n check?: boolean;\n diff?: boolean;\n live?: string;\n};\n\nexport async function genCommand(opts: GenCommandOptions): Promise<void> {\n const dryRun = !!(opts.check || opts.diff);\n\n let liveSightmap: LiveSightmapSnapshot | undefined;\n if (opts.live) {\n try {\n const res = await fetch(opts.live);\n if (!res.ok) {\n console.error(\n `sightmap: --live fetch failed with HTTP ${res.status}; continuing without live snapshot`,\n );\n } else {\n liveSightmap = (await res.json()) as LiveSightmapSnapshot;\n }\n } catch (err) {\n console.error(\n `sightmap: --live fetch failed (${(err as Error).message}); continuing without live snapshot`,\n );\n }\n }\n\n const result = await runOnce({\n projectRoot: opts.cwd,\n router: opts.router as RouterChoice,\n outputDir: opts.output,\n sharedFile: \"shared.yaml\",\n prune: \"warn\",\n dryRun,\n ...(liveSightmap ? { liveSightmap } : {}),\n });\n\n const wouldChange = result.changes.filter((c) => c.changed);\n\n if (opts.diff) {\n for (const c of wouldChange) {\n const rel = relative(opts.cwd, c.path);\n const oldName = c.before == null ? \"/dev/null\" : `a/${rel}`;\n const newName = `b/${rel}`;\n const patch = createTwoFilesPatch(oldName, newName, c.before ?? \"\", c.after);\n process.stdout.write(patch);\n }\n }\n\n if (opts.check) {\n if (wouldChange.length > 0) {\n console.error(\n `sightmap: ${wouldChange.length} file(s) would change. Run \\`sightmap-react gen\\` to update.`,\n );\n for (const c of wouldChange) console.error(` - ${relative(opts.cwd, c.path)}`);\n reportDiagnostics(result.diagnostics);\n process.exit(1);\n }\n console.log(\"sightmap: up to date\");\n } else if (opts.diff) {\n if (wouldChange.length === 0) console.log(\"sightmap: no changes\");\n } else {\n // Default branch: print first-run / steady-state / structural-update summary.\n const summary = formatSummary({\n cwd: opts.cwd,\n changes: result.changes,\n written: result.written,\n });\n for (const line of summary.lines) console.log(line);\n }\n\n if (reportDiagnostics(result.diagnostics)) process.exit(1);\n}\n\nfunction reportDiagnostics(diagnostics: { severity: string; code: string; message: string; file?: string; path?: string }[]): boolean {\n let hadError = false;\n for (const d of diagnostics) {\n const tag = d.severity.toUpperCase();\n const loc = [d.file, d.path].filter(Boolean).join(\" :: \");\n console.error(`[${tag}] ${d.code}: ${d.message}${loc ? ` (${loc})` : \"\"}`);\n if (d.severity === \"error\") hadError = true;\n }\n return hadError;\n}\n","// src/plugin/orchestrator.ts\n//\n// One-shot pipeline used by `sightmap-react gen`:\n//\n// 1. Resolve the framework adapter for the project's router.\n// 2. Discover routes via the adapter.\n// 3. AST-scan each route's source files for `data-sightmap` selectors.\n// 4. Promote multi-route components into shared.yaml.\n// 5. For each feature (group of routes sharing a featureName), smart-merge\n// the freshly-derived skeleton into `<feature>.yaml`, preserving any\n// agent-authored fields already in the file.\n//\n// `runOnce` is the only emit path; there is no Vite-plugin watch loop. The\n// last-emit fingerprint cache (mode-C continuous-emit infrastructure) has been\n// removed.\n//\n// Dedup against existing non-feature-scoped layouts (e.g. a hand-curated\n// `views.yaml` that already contains a route) is preserved: it lets users keep\n// their own file layout and still re-run `gen` without producing duplicate\n// per-feature stubs. The dedup matches by view name AND route pattern.\n\nimport { promises as fs } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type { Diagnostic } from \"@sightmap/sightmap\";\nimport { resolveAdapter, type RouterChoice } from \"./adapters/index.js\";\nimport type { RouteDescriptor } from \"./router-adapter.js\";\nimport { deriveViewName } from \"./router-adapter.js\";\nimport { scanFile, type AstFinding } from \"./ast/scan.js\";\nimport { smartMerge, type ComponentDesired } from \"./merge/smart-merge.js\";\nimport { loadDirectory } from \"@sightmap/sightmap\";\nimport {\n REACT_LIVE_ONLY_VIEW,\n REACT_NO_ROUTES_DISCOVERED,\n REACT_UNKNOWN_ROUTER,\n REACT_VIEW_ALREADY_DEFINED,\n} from \"./diagnostics.js\";\n\n/**\n * Loose wire-shape of a sightmap fetched from the dev middleware\n * (`/__sightmap__/sightmap.json`). We only consume the `views` array's name +\n * route pair; richer fields (memory, components) are accepted but ignored.\n *\n * Kept structurally separate from `Sightmap` so the CLI does not have to\n * fully construct a brand-typed Sightmap to call `runOnce`.\n */\nexport type LiveSightmapSnapshot = {\n version?: 1;\n views?: Array<{ name: string; route: string; [k: string]: unknown }>;\n // Forward-compat: any other fields the endpoint may return.\n [k: string]: unknown;\n};\n\nexport type RunOptions = {\n projectRoot: string;\n router: RouterChoice;\n outputDir: string; // relative to projectRoot, e.g. \".sightmap\"\n sharedFile: string; // e.g. \"shared.yaml\"\n // v0.1 only emits warnings on removed components. The \"delete\" / \"preserve\" modes are\n // typed for forward compat but unused — the orchestrator does not yet detect or act on\n // removed-from-source entries. Track in v0.2 alongside the prune diagnostic emission.\n prune: \"warn\";\n // When true, compute changes but do not touch the filesystem. Powers\n // `sightmap-react gen --check` and `--diff`.\n dryRun?: boolean;\n // WI-7 task 8: optional live snapshot fetched from the dev middleware. When\n // provided, views present here but not in the static-discovery output are\n // surfaced as info diagnostics so the curator can hand-author them. We do\n // NOT auto-emit YAML for live-only views — that promotes the live surface\n // to a parallel codegen path, which the codegen spec explicitly rejected.\n liveSightmap?: LiveSightmapSnapshot;\n};\n\nexport type FileChange = {\n path: string; // absolute path of the target file\n before: string | null; // existing on-disk content, or null if new\n after: string; // content that gen would write\n changed: boolean; // true iff after !== before (modulo trailing-ws normalize)\n};\n\nexport type RunResult = {\n written: string[]; // absolute paths of files actually written (empty when dryRun)\n changes: FileChange[]; // every target file gen considered, write or no\n diagnostics: Diagnostic[];\n};\n\nexport async function runOnce(opts: RunOptions): Promise<RunResult> {\n const adapter = await resolveAdapter(opts.router, opts.projectRoot);\n if (!adapter) {\n return {\n written: [],\n changes: [],\n diagnostics: [\n {\n severity: \"warning\",\n code: REACT_UNKNOWN_ROUTER,\n message: `No supported router detected at ${opts.projectRoot}. Skipping sightmap generation.`,\n },\n ],\n };\n }\n const sightmapDir = join(opts.projectRoot, opts.outputDir);\n if (!opts.dryRun) await fs.mkdir(sightmapDir, { recursive: true });\n\n let existingViewNames = new Set<string>();\n let existingViewRoutes = new Set<string>();\n try {\n const existing = await loadDirectory(sightmapDir);\n for (const v of existing.views ?? []) {\n existingViewNames.add(v.name);\n existingViewRoutes.add(v.route);\n }\n } catch {\n // No existing sightmap (or directory unreadable) — fine, start fresh\n }\n\n const written: string[] = [];\n const changes: FileChange[] = [];\n const allDiagnostics: Diagnostic[] = [];\n\n const routes = await adapter.discoverRoutes({\n projectRoot: opts.projectRoot,\n resolveSource: (id) => join(opts.projectRoot, id),\n diagnostics: allDiagnostics,\n });\n\n // Adapter returned no routes. The most common causes are misconfiguration,\n // not \"this is intentional\" — surface them so the curator gets a hint\n // instead of a silent `sightmap: up to date` and an empty `.sightmap/`.\n if (routes.length === 0) {\n allDiagnostics.push({\n severity: \"warning\",\n code: REACT_NO_ROUTES_DISCOVERED,\n message:\n `No routes discovered by the ${adapter.name} adapter. ` +\n `Common causes: the entry file isn't where the adapter looks ` +\n `(declarative: \\`src/main.{tsx,ts,jsx,js}\\`; framework: \\`app/routes.ts\\`); ` +\n `the project uses RR7 data-mode (\\`createBrowserRouter\\`), not yet supported; ` +\n `the framework project uses \\`flatRoutes()\\` filesystem routing, not yet supported; ` +\n `the entry imports the app via a path alias defined outside tsconfig ` +\n `(e.g. only in \\`vite.config.ts\\`) so the adapter can't resolve it; or ` +\n `no \\`<Routes>\\` JSX / programmatic \\`route(...)\\` config is reachable from the entry. ` +\n `If your routes are real, surface them via \\`sightmap-react gen --live <url>\\`.`,\n });\n }\n\n // Build a map of (route → discovered components from its source files).\n const componentsByRoute = new Map<string, ComponentDesired[]>();\n const componentRouteCount = new Map<string, Set<string>>();\n\n for (const route of routes) {\n const findings = await collectFindings(route.sourceFiles, allDiagnostics);\n componentsByRoute.set(route.pattern, findings.map(toComponent));\n for (const f of findings) {\n if (!componentRouteCount.has(f.name)) componentRouteCount.set(f.name, new Set());\n componentRouteCount.get(f.name)!.add(route.pattern);\n }\n }\n\n // Promote multi-route components to shared.yaml.\n const sharedComponents: ComponentDesired[] = [];\n for (const [name, routesFor] of componentRouteCount) {\n if (routesFor.size > 1) {\n sharedComponents.push({\n name,\n selector: `[data-sightmap=\"${name}\"]`,\n });\n for (const r of routesFor) {\n const list = componentsByRoute.get(r) ?? [];\n const filtered = list.filter((c) => c.name !== name);\n componentsByRoute.set(r, filtered);\n }\n }\n }\n\n // Emit per-feature files (group routes by featureName).\n const byFeature = new Map<string, RouteDescriptor[]>();\n for (const r of routes) {\n if (!byFeature.has(r.featureName)) byFeature.set(r.featureName, []);\n byFeature.get(r.featureName)!.push(r);\n }\n\n for (const [featureName, featureRoutes] of byFeature) {\n const filePath = join(sightmapDir, `${featureName}.yaml`);\n const targetFileExists = await fs.access(filePath).then(() => true).catch(() => false);\n const before = await readIfExists(filePath);\n\n // Smart-merge each route's view in succession, threading the YAML through\n // each iteration. The first call may scaffold (HEADER + TODO block) when\n // `existing` is null; subsequent calls just add/update views in the\n // already-scaffolded document.\n let currentYaml: string | null = before;\n let anyChanged = false;\n let emittedAnyView = false;\n\n for (const route of featureRoutes) {\n const viewName = deriveViewName(route.pattern);\n const components = componentsByRoute.get(route.pattern) ?? [];\n\n const isAlreadyDefinedElsewhere =\n !targetFileExists &&\n (existingViewNames.has(viewName) || existingViewRoutes.has(route.pattern));\n\n if (isAlreadyDefinedElsewhere) {\n allDiagnostics.push({\n severity: \"info\",\n code: REACT_VIEW_ALREADY_DEFINED,\n message: `Route ${route.pattern} (view \"${viewName}\") is already defined in an existing YAML file outside the per-feature convention. Skipping stub emission. To migrate to the per-feature layout, move the view definition to ${featureName}.yaml.`,\n });\n continue;\n }\n\n const merged = smartMerge({\n existing: currentYaml,\n desired: {\n view: { name: viewName, route: route.pattern },\n components,\n },\n });\n currentYaml = merged.yaml;\n if (merged.changed) anyChanged = true;\n emittedAnyView = true;\n }\n\n // Only emit a FileChange when we actually processed at least one view for\n // this feature. If every route was skipped (all already-defined-elsewhere),\n // currentYaml still equals `before` and no change is recorded.\n if (emittedAnyView && currentYaml !== null) {\n changes.push({ path: filePath, before, after: currentYaml, changed: anyChanged });\n if (anyChanged && !opts.dryRun) {\n await atomicWrite(filePath, currentYaml);\n written.push(filePath);\n }\n }\n }\n\n // Emit shared.yaml if non-empty.\n if (sharedComponents.length > 0) {\n const filePath = join(sightmapDir, opts.sharedFile);\n const existing = await readIfExists(filePath);\n const merged = smartMerge({\n existing,\n desired: {\n view: { name: \"Shared\", route: \"/**\" }, // sentinel — `Shared` is global, route matches any\n components: sharedComponents,\n },\n });\n changes.push({ path: filePath, before: existing, after: merged.yaml, changed: merged.changed });\n if (merged.changed && !opts.dryRun) {\n await atomicWrite(filePath, merged.yaml);\n written.push(filePath);\n }\n }\n\n // WI-7 task 8: surface views present at runtime but missing from static\n // discovery. We do NOT auto-emit YAML for these — the curator hand-authors a\n // file per the diagnostic's hint, preserving the invariant that codegen\n // owns only what it can derive from source.\n if (opts.liveSightmap?.views?.length) {\n const staticViewNames = new Set<string>();\n const staticViewRoutes = new Set<string>();\n // Names already discovered from source...\n for (const r of routes) staticViewNames.add(deriveViewName(r.pattern));\n // ...plus any name/route already present in the existing per-feature output\n // (so a view defined in a hand-curated views.yaml does not produce a\n // false-positive live-only-view diagnostic).\n for (const n of existingViewNames) staticViewNames.add(n);\n for (const rt of existingViewRoutes) staticViewRoutes.add(rt);\n for (const c of changes) {\n // matchAll (not match) catches every view in a multi-view file —\n // post-#17, a feature can hold N views in one file.\n for (const m of c.after.matchAll(/^\\s*-\\s+name:\\s*(\\S+)/gm)) {\n staticViewNames.add(m[1]!);\n }\n }\n\n for (const liveView of opts.liveSightmap.views) {\n if (!liveView || typeof liveView.name !== \"string\") continue;\n if (staticViewNames.has(liveView.name) || staticViewRoutes.has(liveView.route)) continue;\n const safeFile = liveView.name.toLowerCase().replace(/[^a-z0-9-_]/g, \"-\");\n allDiagnostics.push({\n severity: \"info\",\n code: REACT_LIVE_ONLY_VIEW,\n message: `View \"${liveView.name}\" (route ${liveView.route}) appeared at runtime but was not discovered by the static AST scan. Add a data-sightmap attribute or hand-author a .sightmap/${safeFile}.yaml file.`,\n });\n }\n }\n\n return { written, changes, diagnostics: allDiagnostics };\n}\n\nasync function collectFindings(files: string[], diagnostics: Diagnostic[]): Promise<AstFinding[]> {\n const out: AstFinding[] = [];\n for (const f of files) {\n const result = await scanFile(f);\n out.push(...result.findings);\n diagnostics.push(...result.diagnostics);\n }\n return out;\n}\n\nfunction toComponent(f: AstFinding): ComponentDesired {\n return { name: f.name, selector: `[data-sightmap=\"${f.name}\"]` };\n}\n\nasync function readIfExists(path: string): Promise<string | null> {\n try {\n return await fs.readFile(path, \"utf-8\");\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw e;\n }\n}\n\nasync function atomicWrite(path: string, contents: string): Promise<void> {\n await fs.mkdir(dirname(path), { recursive: true });\n const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;\n await fs.writeFile(tmp, contents, \"utf-8\");\n await fs.rename(tmp, path);\n}\n\nfunction capitalize(s: string): string {\n return s.length > 0 ? s[0]!.toUpperCase() + s.slice(1) : s;\n}\n","// src/plugin/adapters/index.ts\nimport { promises as fs } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { RouterAdapter } from \"../router-adapter.js\";\nimport { rr7DeclarativeAdapter } from \"./rr7-declarative.js\";\nimport { rr7FrameworkAdapter } from \"./rr7-framework.js\";\n\nexport type RouterChoice =\n | \"react-router-7\"\n | \"react-router-7-framework\"\n | \"auto\"\n | RouterAdapter;\n\nexport async function resolveAdapter(choice: RouterChoice, projectRoot?: string): Promise<RouterAdapter | null> {\n if (typeof choice === \"string\") {\n if (choice === \"react-router-7\") return rr7DeclarativeAdapter();\n if (choice === \"react-router-7-framework\") return rr7FrameworkAdapter();\n if (choice === \"auto\") {\n // Prefer framework mode when an `app/routes.ts` config is present;\n // otherwise fall back to declarative if `react-router` is in deps.\n if (projectRoot) {\n const framework = rr7FrameworkAdapter();\n if (framework.detect(projectRoot)) return framework;\n }\n const pkg = await readPackageJson(projectRoot);\n if (pkg?.dependencies?.[\"react-router\"] || pkg?.devDependencies?.[\"react-router\"]) {\n return rr7DeclarativeAdapter();\n }\n return null;\n }\n }\n return choice;\n}\n\nasync function readPackageJson(projectRoot?: string): Promise<any | null> {\n if (!projectRoot) return null;\n try {\n const raw = await fs.readFile(join(projectRoot, \"package.json\"), \"utf-8\");\n return JSON.parse(raw);\n } catch {\n return null;\n }\n}\n","// src/plugin/adapters/rr7-declarative.ts\n//\n// React Router 7 \"declarative\" adapter — discovers routes from <Routes> / <Route> JSX.\n//\n// v0.1 limitations (intentional — deferred to v0.2):\n// - Only resolves explicit string `path` props. Template-expression paths are not supported.\n// - Only follows local (relative) imports. Bare-specifier or aliased imports are skipped.\n// - Does not discover routes added via `useRoutes(routesArray)` — that is the data-mode\n// adapter, planned for v0.2.\n//\n// Note: `require(\"fs\").accessSync` was avoided here because this package is ESM-only\n// (\"type\": \"module\"). `require` is not defined in ESM. `existsSync` from \"node:fs\" is\n// used instead — it is synchronous, does not throw on missing files, and returns a boolean.\n\nimport { promises as fs, existsSync } from \"node:fs\";\nimport { dirname, join, relative, resolve } from \"node:path\";\nimport { parse as parseAst } from \"@swc/core\";\nimport type { Diagnostic } from \"@sightmap/sightmap\";\nimport type { RouterAdapter, AdapterContext, RouteDescriptor } from \"../router-adapter.js\";\nimport { deriveFeatureName } from \"../router-adapter.js\";\nimport { REACT_DYNAMIC_ROUTE_PATH } from \"../diagnostics.js\";\n\nconst ENTRY_CANDIDATES = [\"src/main.tsx\", \"src/main.ts\", \"src/main.jsx\", \"src/main.js\"];\n\nexport function rr7DeclarativeAdapter(): RouterAdapter {\n return {\n name: \"react-router-7-declarative\",\n detect(_projectRoot: string): boolean {\n // Best-effort sniff: does the project have react-router as a dep AND a main.* with <Routes>?\n // Defer detection logic to v0.2; in v0.1 this adapter is selected explicitly.\n return true;\n },\n async discoverRoutes(ctx: AdapterContext): Promise<RouteDescriptor[]> {\n const entry = await findEntry(ctx.projectRoot);\n if (!entry) return [];\n const visited = new Set<string>();\n const routePatterns: string[] = [];\n const sourceFilesPerRoute = new Map<string, Set<string>>();\n const pathsConfig = await loadPathsConfig(ctx.projectRoot);\n\n await walkModule(entry, ctx, pathsConfig, visited, routePatterns, sourceFilesPerRoute);\n\n return routePatterns.map((pattern) => ({\n pattern,\n featureName: deriveFeatureName(pattern),\n sourceFiles: Array.from(sourceFilesPerRoute.get(pattern) ?? new Set()),\n }));\n },\n };\n}\n\nasync function findEntry(projectRoot: string): Promise<string | null> {\n for (const candidate of ENTRY_CANDIDATES) {\n const path = join(projectRoot, candidate);\n try {\n await fs.access(path);\n return path;\n } catch {\n /* not present */\n }\n }\n return null;\n}\n\nasync function walkModule(\n file: string,\n ctx: AdapterContext,\n pathsConfig: PathsConfig | null,\n visited: Set<string>,\n routePatterns: string[],\n sourceFilesPerRoute: Map<string, Set<string>>,\n): Promise<void> {\n if (visited.has(file)) return;\n visited.add(file);\n let source: string;\n try {\n source = await fs.readFile(file, \"utf-8\");\n } catch {\n return;\n }\n\n const ast = await parseAst(source, { syntax: \"typescript\", tsx: true, target: \"es2022\" });\n\n // Pass 1: collect local import bindings (local name → resolved absolute path).\n const localImports = new Map<string, string>();\n collectImports(ast, file, pathsConfig, localImports);\n\n // Pass 2: find <Route path=\"...\"> elements and record source files.\n // collectRoutes is synchronous; we capture results and process async below\n // so we can walk each element's component subtree.\n const routesFound: Array<{ path: string; elementSpecs: string[] }> = [];\n collectRoutes(\n ast,\n (path, elementSpecs) => {\n routesFound.push({ path, elementSpecs });\n },\n ctx.diagnostics ? (diag) => ctx.diagnostics!.push(diag) : undefined,\n file,\n ctx.projectRoot,\n );\n\n for (const { path, elementSpecs } of routesFound) {\n routePatterns.push(path);\n if (!sourceFilesPerRoute.has(path)) sourceFilesPerRoute.set(path, new Set());\n sourceFilesPerRoute.get(path)!.add(file);\n\n // Walk every locally-bound component referenced by the route's element\n // subtree. The visited set is shared across specs for one route so two\n // siblings sharing a sub-component don't re-walk it; it's per-route so\n // the same file can still appear under multiple routes (the orchestrator\n // promotes multi-route components to shared.yaml).\n const visitedForRoute = new Set<string>();\n for (const spec of elementSpecs) {\n const resolved = localImports.get(spec) ?? null;\n if (resolved) {\n await walkComponentTree(resolved, pathsConfig, sourceFilesPerRoute.get(path)!, visitedForRoute);\n }\n }\n }\n\n // Pass 3: recurse into other imports so nested route trees are discovered.\n for (const target of localImports.values()) {\n await walkModule(target, ctx, pathsConfig, visited, routePatterns, sourceFilesPerRoute);\n }\n}\n\n// Walks a component's import tree, adding every reachable file to `sourceFiles`.\n// Cycle-protected via `visited`. The visited set is per-call (per-route) so\n// the same component can appear in multiple routes' sourceFiles — the\n// orchestrator promotes multi-route components to shared.yaml.\nasync function walkComponentTree(\n file: string,\n pathsConfig: PathsConfig | null,\n sourceFiles: Set<string>,\n visited: Set<string>,\n): Promise<void> {\n if (visited.has(file)) return;\n visited.add(file);\n sourceFiles.add(file);\n\n let source: string;\n try {\n source = await fs.readFile(file, \"utf-8\");\n } catch {\n return;\n }\n\n const ast = await parseAst(source, { syntax: \"typescript\", tsx: true, target: \"es2022\" });\n const localImports = new Map<string, string>();\n collectImports(ast, file, pathsConfig, localImports);\n\n for (const target of localImports.values()) {\n await walkComponentTree(target, pathsConfig, sourceFiles, visited);\n }\n}\n\nfunction collectImports(\n ast: any,\n fromFile: string,\n pathsConfig: PathsConfig | null,\n into: Map<string, string>,\n): void {\n for (const stmt of ast.body ?? []) {\n if (stmt.type === \"ImportDeclaration\") {\n const sourcePath = stmt.source?.value as string | undefined;\n if (!sourcePath) continue;\n const resolved = resolveImport(fromFile, sourcePath, pathsConfig);\n if (!resolved) continue;\n for (const spec of stmt.specifiers ?? []) {\n const local = spec.local?.value;\n if (typeof local === \"string\") into.set(local, resolved);\n }\n continue;\n }\n // Recognize `const Foo = lazy(() => import(\"./Foo\"))` (and variants like\n // `lazy(() => import(\"./Foo\").then(m => m.Foo))`, `lazy(async () => ...)`).\n // Treats the variable's binding name as the local import name and the dynamic\n // `import(...)` argument as the source spec — so the same downstream walker\n // that handles static imports also walks lazy-loaded route components.\n if (stmt.type === \"VariableDeclaration\") {\n for (const decl of stmt.declarations ?? []) {\n const local = decl.id?.value;\n if (typeof local !== \"string\" || !decl.init) continue;\n const dynamicSpec = findFirstDynamicImportSpec(decl.init);\n if (!dynamicSpec) continue;\n const resolved = resolveImport(fromFile, dynamicSpec, pathsConfig);\n if (!resolved) continue;\n into.set(local, resolved);\n }\n }\n }\n}\n\n// Resolves an import specifier to an absolute file path, handling both\n// relative imports and tsconfig path-aliases. Returns null for bare-package\n// imports (`react`, `@sightmap/sightmap`, etc.) — those are out of scope for\n// route discovery and silently skipped, same as before.\nfunction resolveImport(\n fromFile: string,\n importSpec: string,\n pathsConfig: PathsConfig | null,\n): string | null {\n if (importSpec.startsWith(\".\")) {\n return resolveLocalImport(fromFile, importSpec);\n }\n if (!pathsConfig) return null;\n const candidates = expandAlias(importSpec, pathsConfig);\n if (!candidates) return null;\n // Each candidate is an absolute path stem (with or without extension); try\n // file-form, directory-form, and the .js-extension TS quirk in the same\n // order as `resolveLocalImport`.\n for (const candidate of candidates) {\n const stripped = candidate.replace(/\\.(js|jsx|mjs)$/, \"\");\n for (const ext of [\".tsx\", \".ts\", \".jsx\", \".js\"]) {\n const p = `${stripped}${ext}`;\n if (existsSync(p)) return p;\n }\n for (const indexBase of [\"index.tsx\", \"index.ts\", \"index.jsx\", \"index.js\"]) {\n const p = resolve(stripped, indexBase);\n if (existsSync(p)) return p;\n }\n if (stripped !== candidate && existsSync(candidate)) return candidate;\n }\n return null;\n}\n\n// Subtree search for the first `import(\"...\")` call inside a node, returning\n// the static-string argument or null. Handles the common shapes — `lazy(() =>\n// import(\"./X\"))`, `lazy(() => import(\"./X\").then(...))`, `lazy(async () =>\n// import(\"./X\"))` — without trying to model arbitrary control flow.\nfunction findFirstDynamicImportSpec(node: any): string | null {\n if (!node || typeof node !== \"object\") return null;\n if (\n node.type === \"CallExpression\" &&\n node.callee?.type === \"Import\" &&\n Array.isArray(node.arguments) &&\n node.arguments[0]?.expression?.type === \"StringLiteral\"\n ) {\n return node.arguments[0].expression.value as string;\n }\n for (const key of Object.keys(node)) {\n const v = node[key];\n if (Array.isArray(v)) {\n for (const c of v) {\n const found = findFirstDynamicImportSpec(c);\n if (found) return found;\n }\n } else if (v && typeof v === \"object\") {\n const found = findFirstDynamicImportSpec(v);\n if (found) return found;\n }\n }\n return null;\n}\n\n// Uses existsSync (not require(\"fs\").accessSync) because this package is ESM-only.\n// require is not available in ESM modules and would throw ReferenceError at runtime.\n//\n// Handles three import styles:\n// 1. Extensionless (\"./Login\") → tries ./Login.tsx, .ts, .jsx, .js\n// 2. TS verbatimModuleSyntax (\".js\" on\n// a .ts/.tsx source: \"./Login.js\") → strips the trailing .js/.jsx/.mjs\n// and tries ./Login.tsx, .ts, .jsx, .js\n// 3. Directory-style (\"./pages/login\") → tries ./pages/login/index.{tsx,ts,jsx,js}\n// after the file-form lookups fail. Order\n// matches Node/bundler precedence: a\n// sibling `./pages/login.tsx` wins over a\n// `./pages/login/index.tsx`.\nfunction resolveLocalImport(fromFile: string, importSpec: string): string | null {\n const dir = dirname(fromFile);\n const stripped = importSpec.replace(/\\.(js|jsx|mjs)$/, \"\");\n for (const ext of [\".tsx\", \".ts\", \".jsx\", \".js\"]) {\n const candidate = resolve(dir, `${stripped}${ext}`);\n if (existsSync(candidate)) return candidate;\n }\n for (const indexBase of [\"index.tsx\", \"index.ts\", \"index.jsx\", \"index.js\"]) {\n const candidate = resolve(dir, stripped, indexBase);\n if (existsSync(candidate)) return candidate;\n }\n // Fall back to the original spec in case it's a real .js/.mjs file\n // (the strip-and-retry above won't hit it because we already tried `${stripped}.js`).\n if (stripped !== importSpec) {\n const original = resolve(dir, importSpec);\n if (existsSync(original)) return original;\n }\n return null;\n}\n\nfunction collectRoutes(\n ast: any,\n onRoute: (path: string, elementSpecs: string[]) => void,\n onDiagnostic?: (d: Diagnostic) => void,\n fromFile?: string,\n projectRoot?: string,\n): void {\n function visit(node: any, parentPath: string): void {\n if (!node || typeof node !== \"object\") return;\n let here = parentPath;\n if (node.type === \"JSXElement\" && node.opening?.name?.value === \"Route\") {\n let pathValue: string | null = null;\n let pathAttrIsNonLiteral = false;\n let outerElementName: string | null = null;\n const elementSpecs: string[] = [];\n for (const attr of node.opening.attributes ?? []) {\n if (attr.type !== \"JSXAttribute\") continue;\n if (attr.name?.value === \"path\") {\n if (attr.value?.type === \"StringLiteral\") {\n pathValue = attr.value.value;\n } else if (attr.value) {\n // Any other shape (template literal, identifier, expression, member\n // access) — emit a diagnostic so the curator knows we saw the route\n // but couldn't resolve its path.\n pathAttrIsNonLiteral = true;\n }\n }\n if (attr.name?.value === \"element\" && attr.value?.type === \"JSXExpressionContainer\") {\n const inner = attr.value.expression;\n if (inner?.type === \"JSXElement\") {\n // The outermost element name is often a cross-cutting wrapper\n // (`Suspense`, `ErrorBoundary`, `RequireAuth`, …) that lives in a\n // bare-package import, not a local binding. Collect every\n // JSXElement name in the subtree so the caller can resolve all\n // of them against `localImports` and walk the matches. The\n // canonical RR7 lazy-route pattern is\n // `element={<Suspense><Foo /></Suspense>}`, where `Foo` is the\n // local binding we actually care about.\n collectJsxElementNames(inner, elementSpecs);\n outerElementName = inner.opening?.name?.value ?? null;\n }\n }\n // RR7's `<Route Component={X} />` prop is functionally equivalent to\n // `element={<X />}` but takes the component reference directly. Real-world\n // apps mix the two freely (often using `Component` with `React.lazy(...)`).\n if (attr.name?.value === \"Component\" && attr.value?.type === \"JSXExpressionContainer\") {\n const inner = attr.value.expression;\n if (inner?.type === \"Identifier\" && typeof inner.value === \"string\") {\n elementSpecs.push(inner.value);\n }\n }\n }\n if (pathValue) {\n const joined = pathValue.startsWith(\"/\") ? pathValue : `${parentPath.replace(/\\/$/, \"\")}/${pathValue}`;\n // Skip pure-redirect routes — `<Route element={<Navigate ... />} />` doesn't\n // render a user-facing surface and only adds noise as an empty-components\n // view in the YAML. Match only when `Navigate` is the *outermost* element\n // (the redirect form); a `Navigate` rendered inside a real wrapper is\n // unusual but still a real route.\n if (outerElementName !== \"Navigate\") {\n onRoute(joined, elementSpecs);\n }\n here = joined;\n } else if (pathAttrIsNonLiteral && onDiagnostic) {\n const where = fromFile && projectRoot ? relative(projectRoot, fromFile) : fromFile ?? \"<unknown>\";\n onDiagnostic({\n severity: \"info\",\n code: REACT_DYNAMIC_ROUTE_PATH,\n message: `Route in ${where} uses a non-literal \\`path\\` (template literal / identifier / expression). Static AST discovery cannot resolve dynamic paths; hand-author this view in a feature YAML or refactor to a literal string.`,\n });\n }\n }\n for (const key of Object.keys(node)) {\n const v = (node as any)[key];\n if (Array.isArray(v)) v.forEach((c) => visit(c, here));\n else if (v && typeof v === \"object\") visit(v, here);\n }\n }\n visit(ast, \"\");\n}\n\n// Recursively walks a JSX expression subtree, pushing every JSXElement\n// opening name we encounter into `into`. Caller filters by `localImports`,\n// so package-level wrappers (`Suspense`, `ErrorBoundary`, …) drop out\n// naturally without needing a name-based denylist.\nfunction collectJsxElementNames(node: any, into: string[]): void {\n if (!node || typeof node !== \"object\") return;\n if (node.type === \"JSXElement\") {\n const name = node.opening?.name?.value;\n if (typeof name === \"string\") into.push(name);\n }\n for (const key of Object.keys(node)) {\n const v = (node as any)[key];\n if (Array.isArray(v)) v.forEach((c) => collectJsxElementNames(c, into));\n else if (v && typeof v === \"object\") collectJsxElementNames(v, into);\n }\n}\n\n/**\n * Resolved alias-resolution context derived from the project's tsconfig(s).\n *\n * `baseUrl` is absolute. `paths` keys are kept verbatim from the tsconfig\n * (e.g. `\"@/*\"`); each value is the array of substitution targets from the\n * tsconfig (e.g. `[\"./src/*\"]`), themselves relative to `baseUrl`.\n */\ntype PathsConfig = {\n baseUrl: string;\n paths: Record<string, string[]>;\n};\n\n// Loads tsconfig path-alias config from the project. Reads tsconfig.json AND\n// tsconfig.app.json (the typical Vite layout where the root config is just a\n// `references` shell and the alias-bearing config lives in tsconfig.app.json).\n// Returns null if neither defines `paths`. Tolerates JSON-with-comments —\n// tsconfig is JSON-with-comments by convention and TypeScript's own parser\n// is more lenient than `JSON.parse`. We don't try to model `extends`; the\n// flat case covers the dominant idiom.\nasync function loadPathsConfig(projectRoot: string): Promise<PathsConfig | null> {\n const merged: Record<string, string[]> = {};\n let baseUrl: string | null = null;\n for (const name of [\"tsconfig.json\", \"tsconfig.app.json\"]) {\n const fp = join(projectRoot, name);\n let raw: string;\n try {\n raw = await fs.readFile(fp, \"utf-8\");\n } catch {\n continue;\n }\n const json = parseTsconfigJson(raw);\n const co = json?.compilerOptions;\n if (!co) continue;\n if (!baseUrl && typeof co.baseUrl === \"string\") {\n baseUrl = resolve(dirname(fp), co.baseUrl);\n }\n if (co.paths && typeof co.paths === \"object\") {\n for (const [k, v] of Object.entries(co.paths)) {\n if (Array.isArray(v)) merged[k] = v as string[];\n }\n }\n }\n if (Object.keys(merged).length === 0) return null;\n return { baseUrl: baseUrl ?? projectRoot, paths: merged };\n}\n\n// Strip the two tsconfig-style \"JSON with comments\" extensions: `// line`\n// comments and `/* block */` comments. Trailing commas before `}` / `]` are\n// also tolerated. Conservative — it doesn't try to be a full JSON5 parser,\n// just enough to handle the conventions tsconfig templates use.\nfunction parseTsconfigJson(raw: string): any | null {\n const stripped = raw\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n .replace(/(^|[^:])\\/\\/.*$/gm, \"$1\")\n .replace(/,(\\s*[}\\]])/g, \"$1\");\n try {\n return JSON.parse(stripped);\n } catch {\n return null;\n }\n}\n\n// Expand a non-relative import spec against the configured aliases. Returns\n// the array of absolute candidate paths to try (one per alias target), or\n// null if no alias matched. Bare-package imports return null and stay\n// silently skipped — same as before path-alias support landed.\nfunction expandAlias(importSpec: string, cfg: PathsConfig): string[] | null {\n for (const [alias, targets] of Object.entries(cfg.paths)) {\n if (alias.endsWith(\"/*\")) {\n const prefix = alias.slice(0, -1); // includes trailing slash, e.g. \"@/\"\n if (importSpec.startsWith(prefix)) {\n const rest = importSpec.slice(prefix.length);\n return targets.map((t) => {\n const tnorm = t.endsWith(\"/*\") ? t.slice(0, -2) : t;\n return resolve(cfg.baseUrl, tnorm, rest);\n });\n }\n } else if (importSpec === alias) {\n return targets.map((t) => resolve(cfg.baseUrl, t));\n }\n }\n return null;\n}\n","// src/plugin/router-adapter.ts\nimport type { Diagnostic } from \"@sightmap/sightmap\";\n\nexport type RouteDescriptor = {\n pattern: string; // normalized to spec route grammar\n featureName: string; // chunking key — derives the YAML filename\n sourceFiles: string[]; // absolute paths reachable from this route's tree\n meta?: Record<string, unknown>; // raw router metadata; informational only in v1\n};\n\nexport type AdapterContext = {\n projectRoot: string;\n resolveSource: (id: string) => string | null;\n /**\n * Optional sink the adapter can push diagnostics into during discovery — e.g.\n * a `<Route>` it found but couldn't fully process. Adapters MUST tolerate\n * this being absent (callers from tests may not pass one). The orchestrator\n * always provides it and forwards the contents into its own diagnostic\n * stream so they reach the CLI summary.\n */\n diagnostics?: Diagnostic[];\n};\n\nexport interface RouterAdapter {\n name: string;\n detect(projectRoot: string): boolean;\n discoverRoutes(ctx: AdapterContext): Promise<RouteDescriptor[]>;\n /** Optional client-side helper. Falls back to `location.pathname` if absent. */\n currentRoute?(): string;\n}\n\n/** Derive the feature name from a route pattern. First non-parameter segment, or \"home\" for \"/\". */\nexport function deriveFeatureName(pattern: string): string {\n const segments = pattern.split(\"/\").filter(Boolean);\n for (const seg of segments) {\n if (!seg.startsWith(\":\") && !seg.startsWith(\"*\")) return sanitize(seg);\n }\n return \"home\";\n}\n\n/**\n * Derive a view name from a route pattern.\n *\n * Picks the LAST non-parameter segment, capitalized — so `/app/dashboard` →\n * `Dashboard`, `/settings/billing` → `Billing`, `/login` → `Login`.\n *\n * Routes ending in a parameter (`/users/:id`) get the preceding segment with\n * `Detail` appended (`UsersDetail`) so they don't collide with the list view.\n *\n * Routes ending in a wildcard (`/files/*`, `/*`) get `Catchall` appended —\n * a different concept from `:param` (catch-all matches multiple segments;\n * named params match one).\n *\n * Falls back to `Home` for `/`.\n */\nexport function deriveViewName(pattern: string): string {\n const segments = pattern.split(\"/\").filter(Boolean);\n if (segments.length === 0) return \"Home\";\n\n const last = segments[segments.length - 1]!;\n const lastIsParam = last.startsWith(\":\");\n const lastIsWildcard = last.startsWith(\"*\");\n\n if (lastIsParam || lastIsWildcard) {\n const suffix = lastIsWildcard ? \"Catchall\" : \"Detail\";\n // Walk back to the last static segment and append the suffix.\n for (let i = segments.length - 2; i >= 0; i--) {\n const seg = segments[i]!;\n if (!seg.startsWith(\":\") && !seg.startsWith(\"*\")) {\n return capitalize(sanitize(seg)) + suffix;\n }\n }\n return suffix;\n }\n return capitalize(sanitize(last));\n}\n\nfunction sanitize(s: string): string {\n return s.replace(/[^a-zA-Z0-9_-]/g, \"-\").toLowerCase();\n}\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n","// React-specific diagnostic codes. Stable, kebab-case. Renames require a minor bump and a deprecation note.\n\nexport const REACT_DYNAMIC_DATA_SIGHTMAP = \"react.dynamic-data-sightmap\";\nexport const REACT_DYNAMIC_ROUTE_PATH = \"react.dynamic-route-path\";\nexport const REACT_NO_ROUTES_DISCOVERED = \"react.no-routes-discovered\";\nexport const REACT_REMOVED_COMPONENT_STILL_IN_YAML = \"react.removed-component-still-in-yaml\";\nexport const REACT_UNKNOWN_ROUTER = \"react.unknown-router\";\nexport const REACT_ROUTE_NO_VIEW_IN_YAML = \"react.route-no-view-in-yaml\";\nexport const REACT_VIEW_ALREADY_DEFINED = \"react.view-already-defined\";\nexport const REACT_LIVE_ONLY_VIEW = \"react.live-only-view\";\n","// src/plugin/adapters/rr7-framework.ts\n//\n// React Router 7 \"framework mode\" adapter — discovers routes from the\n// programmatic config in `app/routes.ts` (the API exported by\n// `@react-router/dev/routes`: `route`, `index`, `layout`, `prefix`).\n//\n// v0.1 scope:\n// - Reads `app/routes.ts` (or `.tsx`/`.js`/`.jsx`); the `app/` directory is\n// hardcoded. Custom `appDirectory` from `react-router.config.ts` is not yet\n// honored — projects using a different app-dir name fall through to \"no\n// supported router\".\n// - Recognizes top-level helpers by direct identifier name: `route`,\n// `index`, `layout`, `prefix`. Namespaced (`routes.route(...)`) or\n// re-exported / aliased helpers are not parsed.\n// - String-literal arguments only. Template-expression paths or computed\n// file specs are ignored.\n// - `flatRoutes()` (filesystem-based routing) is not supported in v0.1 —\n// projects relying on it will return zero routes.\n//\n// Layout semantics: `layout(file, [children])` adds the layout's component\n// tree to every descendant route's `sourceFiles`, so markers inside a layout\n// surface on every child route. The orchestrator's multi-route promotion then\n// hoists those markers into `shared.yaml`, matching the runtime where the\n// layout wraps each child via `<Outlet />`.\n\nimport { promises as fs, existsSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { parse as parseAst } from \"@swc/core\";\nimport type { RouterAdapter, AdapterContext, RouteDescriptor } from \"../router-adapter.js\";\nimport { deriveFeatureName } from \"../router-adapter.js\";\n\nconst ROUTES_CONFIG_CANDIDATES = [\n \"app/routes.ts\",\n \"app/routes.tsx\",\n \"app/routes.js\",\n \"app/routes.jsx\",\n];\n\nconst APP_DIR = \"app\";\n\nexport function rr7FrameworkAdapter(): RouterAdapter {\n return {\n name: \"react-router-7-framework\",\n detect(projectRoot: string): boolean {\n return findRoutesConfigSync(projectRoot) !== null;\n },\n async discoverRoutes(ctx: AdapterContext): Promise<RouteDescriptor[]> {\n const routesFile = await findRoutesConfig(ctx.projectRoot);\n if (!routesFile) return [];\n const appDir = join(ctx.projectRoot, APP_DIR);\n\n const source = await fs.readFile(routesFile, \"utf-8\");\n const ast = await parseAst(source, { syntax: \"typescript\", tsx: true, target: \"es2022\" });\n\n const defaultArray = findDefaultExportArray(ast);\n if (!defaultArray) return [];\n\n const collected: Array<{ pattern: string; sourceFiles: Set<string> }> = [];\n await walkRouteArray(defaultArray, { parentPattern: \"\", inheritedFiles: new Set() }, appDir, collected);\n\n return collected.map(({ pattern, sourceFiles }) => ({\n pattern,\n featureName: deriveFeatureName(pattern),\n sourceFiles: Array.from(sourceFiles),\n }));\n },\n };\n}\n\nfunction findRoutesConfigSync(projectRoot: string): string | null {\n for (const candidate of ROUTES_CONFIG_CANDIDATES) {\n const path = join(projectRoot, candidate);\n if (existsSync(path)) return path;\n }\n return null;\n}\n\nasync function findRoutesConfig(projectRoot: string): Promise<string | null> {\n for (const candidate of ROUTES_CONFIG_CANDIDATES) {\n const path = join(projectRoot, candidate);\n try {\n await fs.access(path);\n return path;\n } catch {\n /* not present */\n }\n }\n return null;\n}\n\n// Locate `export default [ ... ]` and return the inner ArrayExpression node.\n// Also handles `export default [...] satisfies RouteConfig` (TS satisfies wraps\n// the array in a TsSatisfiesExpression / TsAsExpression in swc) and the\n// `export default <expr>` -> ArrayExpression direct case.\nfunction findDefaultExportArray(ast: any): any | null {\n for (const stmt of ast.body ?? []) {\n if (stmt.type === \"ExportDefaultExpression\") {\n return unwrapArray(stmt.expression);\n }\n if (stmt.type === \"ExportDefaultDeclaration\") {\n const decl = stmt.decl ?? stmt.declaration;\n if (decl) return unwrapArray(decl);\n }\n }\n return null;\n}\n\nfunction unwrapArray(node: any): any | null {\n if (!node) return null;\n if (node.type === \"ArrayExpression\") return node;\n // Unwrap `satisfies` / `as` casts and parens.\n if (node.type === \"TsSatisfiesExpression\" || node.type === \"TsAsExpression\" || node.type === \"TsTypeAssertion\") {\n return unwrapArray(node.expression);\n }\n if (node.type === \"ParenthesisExpression\") return unwrapArray(node.expression);\n return null;\n}\n\ntype Frame = {\n parentPattern: string;\n inheritedFiles: Set<string>;\n};\n\nasync function walkRouteArray(\n arrayNode: any,\n frame: Frame,\n appDir: string,\n out: Array<{ pattern: string; sourceFiles: Set<string> }>,\n): Promise<void> {\n for (const elem of arrayNode.elements ?? []) {\n if (!elem) continue;\n // ArrayExpression elements in swc are wrapped: `{ spread: null, expression: <expr> }`\n // when in array literal context. Spread elements have `spread` set to a span.\n const expr = elem.expression ?? elem;\n const isSpread = !!elem.spread;\n if (isSpread) {\n // Only spread of a `prefix(...)` call is meaningful in v0.1.\n if (expr?.type === \"CallExpression\" && callName(expr) === \"prefix\") {\n const args = expr.arguments ?? [];\n const prefixArg = stringArg(args[0]);\n const childrenArr = arrayArg(args[1]);\n if (prefixArg !== null && childrenArr) {\n const childFrame: Frame = {\n parentPattern: joinPath(frame.parentPattern, prefixArg),\n inheritedFiles: frame.inheritedFiles,\n };\n await walkRouteArray(childrenArr, childFrame, appDir, out);\n }\n }\n continue;\n }\n if (expr?.type !== \"CallExpression\") continue;\n await processRouteCall(expr, frame, appDir, out);\n }\n}\n\nasync function processRouteCall(\n call: any,\n frame: Frame,\n appDir: string,\n out: Array<{ pattern: string; sourceFiles: Set<string> }>,\n): Promise<void> {\n const name = callName(call);\n const args = call.arguments ?? [];\n\n if (name === \"route\") {\n const pathArg = stringArg(args[0]);\n const fileArg = stringArg(args[1]);\n if (pathArg === null || fileArg === null) return;\n const pattern = joinPath(frame.parentPattern, pathArg);\n const sourceFiles = new Set<string>(frame.inheritedFiles);\n const resolvedFile = resolveAppFile(appDir, fileArg);\n if (resolvedFile) await walkComponentTree(resolvedFile, sourceFiles, new Set());\n out.push({ pattern, sourceFiles });\n\n // Children inherit the parent route's component tree. At runtime, child\n // routes render inside the parent's `<Outlet />`, so markers in the\n // parent's component tree appear on every descendant view.\n const childrenArr = arrayArg(args[2]);\n if (childrenArr) {\n const childFrame: Frame = {\n parentPattern: pattern,\n inheritedFiles: union(frame.inheritedFiles, sourceFiles),\n };\n await walkRouteArray(childrenArr, childFrame, appDir, out);\n }\n return;\n }\n\n if (name === \"index\") {\n const fileArg = stringArg(args[0]);\n if (fileArg === null) return;\n // Index routes match the parent pattern exactly. At the top level that's \"/\".\n const pattern = frame.parentPattern || \"/\";\n const sourceFiles = new Set<string>(frame.inheritedFiles);\n const resolvedFile = resolveAppFile(appDir, fileArg);\n if (resolvedFile) await walkComponentTree(resolvedFile, sourceFiles, new Set());\n out.push({ pattern, sourceFiles });\n return;\n }\n\n if (name === \"layout\") {\n const fileArg = stringArg(args[0]);\n const childrenArr = arrayArg(args[1]);\n if (fileArg === null || !childrenArr) return;\n const layoutFiles = new Set<string>();\n const resolvedFile = resolveAppFile(appDir, fileArg);\n if (resolvedFile) await walkComponentTree(resolvedFile, layoutFiles, new Set());\n const childFrame: Frame = {\n parentPattern: frame.parentPattern,\n inheritedFiles: union(frame.inheritedFiles, layoutFiles),\n };\n await walkRouteArray(childrenArr, childFrame, appDir, out);\n return;\n }\n\n // Unknown helper — silently skip. v0.2 may add `flatRoutes()` etc.\n}\n\nfunction callName(call: any): string | null {\n const callee = call?.callee;\n if (!callee) return null;\n if (callee.type === \"Identifier\") return callee.value ?? null;\n return null;\n}\n\nfunction stringArg(arg: any): string | null {\n // ArrayExpression-style argument wrapper: `{ spread: null, expression: <expr> }`.\n const expr = arg?.expression ?? arg;\n if (expr?.type === \"StringLiteral\") return expr.value ?? null;\n return null;\n}\n\nfunction arrayArg(arg: any): any | null {\n const expr = arg?.expression ?? arg;\n if (expr?.type === \"ArrayExpression\") return expr;\n return null;\n}\n\n// Join a child path onto a parent pattern using RR7 semantics:\n// - child starting with \"/\" is absolute and replaces the parent\n// - empty child returns the parent (used for pathless `route(\"\", ...)`)\n// - otherwise the child is appended with a single \"/\" separator\nexport function joinPath(parent: string, child: string): string {\n if (child.startsWith(\"/\")) return child;\n if (!child) return parent || \"/\";\n const base = (parent || \"\").replace(/\\/+$/, \"\");\n const tail = child.replace(/^\\/+/, \"\");\n return base === \"\" ? `/${tail}` : `${base}/${tail}`;\n}\n\nfunction resolveAppFile(appDir: string, fileSpec: string): string | null {\n // RR7 file specs are relative to the app directory and may omit the extension.\n const base = resolve(appDir, fileSpec);\n if (existsSync(base)) return base;\n const stripped = base.replace(/\\.(js|jsx|mjs)$/, \"\");\n for (const ext of [\".tsx\", \".ts\", \".jsx\", \".js\"]) {\n const candidate = `${stripped}${ext}`;\n if (existsSync(candidate)) return candidate;\n }\n return null;\n}\n\nfunction union<T>(a: Set<T>, b: Set<T>): Set<T> {\n const out = new Set<T>(a);\n for (const v of b) out.add(v);\n return out;\n}\n\n// Walks a route file's local-import tree, adding every reachable file to\n// `sourceFiles`. Mirrors the declarative adapter's walker so marker scanning\n// in the orchestrator finds `data-sightmap` attributes inside imported\n// components, not just the route file itself.\nasync function walkComponentTree(\n file: string,\n sourceFiles: Set<string>,\n visited: Set<string>,\n): Promise<void> {\n if (visited.has(file)) return;\n visited.add(file);\n sourceFiles.add(file);\n\n let source: string;\n try {\n source = await fs.readFile(file, \"utf-8\");\n } catch {\n return;\n }\n\n const ast = await parseAst(source, { syntax: \"typescript\", tsx: true, target: \"es2022\" });\n for (const stmt of ast.body ?? []) {\n if (stmt.type !== \"ImportDeclaration\") continue;\n const sourcePath = stmt.source?.value as string | undefined;\n if (!sourcePath || !sourcePath.startsWith(\".\")) continue;\n const resolved = resolveLocalImport(file, sourcePath);\n if (!resolved) continue;\n await walkComponentTree(resolved, sourceFiles, visited);\n }\n}\n\nfunction resolveLocalImport(fromFile: string, importSpec: string): string | null {\n const dir = dirname(fromFile);\n const stripped = importSpec.replace(/\\.(js|jsx|mjs)$/, \"\");\n for (const ext of [\".tsx\", \".ts\", \".jsx\", \".js\"]) {\n const candidate = resolve(dir, `${stripped}${ext}`);\n if (existsSync(candidate)) return candidate;\n }\n if (stripped !== importSpec) {\n const original = resolve(dir, importSpec);\n if (existsSync(original)) return original;\n }\n return null;\n}\n","import { promises as fs } from \"node:fs\";\nimport { parse } from \"@swc/core\";\nimport type { Diagnostic } from \"@sightmap/sightmap\";\nimport { REACT_DYNAMIC_DATA_SIGHTMAP } from \"../diagnostics.js\";\n\nexport type AstFinding = {\n name: string;\n file: string;\n line: number;\n col: number;\n};\n\nexport type ScanResult = {\n findings: AstFinding[];\n diagnostics: Diagnostic[];\n};\n\nexport async function scanFile(file: string): Promise<ScanResult> {\n const source = await fs.readFile(file, \"utf-8\");\n const ast = await parse(source, {\n syntax: \"typescript\",\n tsx: true,\n target: \"es2022\",\n });\n\n const findings: AstFinding[] = [];\n const diagnostics: Diagnostic[] = [];\n\n walk(ast, (node: any) => {\n if (node?.type === \"JSXOpeningElement\" && Array.isArray(node.attributes)) {\n for (const attr of node.attributes) {\n if (attr?.type !== \"JSXAttribute\") continue;\n const nameNode = attr.name;\n if (!nameNode || nameNode.value !== \"data-sightmap\") continue;\n const valueNode = attr.value;\n if (valueNode?.type === \"StringLiteral\") {\n findings.push({\n name: valueNode.value,\n file,\n line: attr.span?.start ?? 0, // SWC byte offset — converted to line in caller if needed\n col: 0,\n });\n } else if (valueNode?.type === \"JSXExpressionContainer\") {\n diagnostics.push({\n severity: \"warning\",\n code: REACT_DYNAMIC_DATA_SIGHTMAP,\n message:\n `data-sightmap value must be a static string. Skipping.\\n` +\n ` Consider one of:\\n` +\n ` - Split into separate components with static markers (e.g. LoginForm + SignupForm)\\n` +\n ` - Use a static marker on the parent and target via descendant selector:\\n` +\n ` [data-sightmap=\"LoginPage\"] form\\n` +\n ` - If you genuinely need dynamic markers, hand-author the entries in extras.yaml`,\n file,\n });\n }\n }\n }\n });\n\n return { findings, diagnostics };\n}\n\nfunction walk(node: any, visit: (n: any) => void): void {\n if (!node || typeof node !== \"object\") return;\n visit(node);\n for (const key of Object.keys(node)) {\n const v = (node as any)[key];\n if (Array.isArray(v)) v.forEach((c) => walk(c, visit));\n else if (v && typeof v === \"object\") walk(v, visit);\n }\n}\n","// src/plugin/merge/smart-merge.ts\n//\n// One-shot smart merge for `sightmap-react gen`.\n//\n// Given an existing YAML file (if any) and a freshly-derived structural skeleton\n// (view + components from the router adapter and AST scan), produce a YAML output\n// that:\n//\n// 1. Replaces the structural fields (view name, route, component name, selector)\n// with the freshly-derived values.\n// 2. Preserves agent-authored fields not in the structural skeleton: `memory`,\n// intent labels, request mappings, and any unknown forward-compat fields.\n// 3. Preserves YAML comments, ordering, and blank lines.\n// 4. Is idempotent: re-running with the same desired skeleton against the same\n// existing file produces `changed=false`.\n//\n// This module is invoked exclusively from `sightmap-react gen` — there is no\n// continuous-mode emit path. Conflict-fingerprint diagnostics from the previous\n// design (mode C) have been removed alongside the last-emit cache.\n\nimport { Document, parseDocument, isMap, isSeq, YAMLMap, YAMLSeq, Scalar } from \"yaml\";\nimport { renderTodoScaffolding } from \"./todo-scaffolding.js\";\n\nexport type ComponentDesired = {\n name: string;\n selector: string;\n children?: ComponentDesired[];\n};\n\nexport type ViewDesired = {\n name: string;\n route: string;\n};\n\nexport type SmartMergeInput = {\n existing: string | null;\n desired: {\n view: ViewDesired;\n components: ComponentDesired[];\n };\n};\n\nexport type SmartMergeResult = {\n changed: boolean;\n yaml: string;\n};\n\nconst HEADER = `# This file is co-maintained by @sightmap/react and your agent.\n# Plugin updates: name, route, selector, children.\n# Agent curates: memory, intent, requests, and any unknown fields.\n# See https://sightmap.org/react for the full convention.\n`;\n\nexport function smartMerge(input: SmartMergeInput): SmartMergeResult {\n const { existing, desired } = input;\n\n const isNew = existing == null;\n const doc: Document = isNew\n ? new Document({ version: 1, views: [] })\n : parseDocument(existing);\n\n ensureScalar(doc, \"version\", 1);\n const viewsSeq = ensureSeq(doc, \"views\");\n reconcileView(viewsSeq, desired);\n\n let yaml = doc.toString();\n if (isNew) {\n // First-run scaffolding for a brand-new view file:\n // <plugin header>\n // <structural YAML>\n // <commented TODO blocks for memory / intent / requests>\n //\n // The TODO block is a YAML comment so the file still parses. We only emit\n // it on file creation; if the agent later deletes the block, re-running\n // `gen` does not bring it back — idempotency per the codegen spec.\n yaml = HEADER + yaml;\n if (!yaml.endsWith(\"\\n\")) yaml += \"\\n\";\n // The blank line separator before the scaffolding makes the file\n // round-trip stable through `parseDocument` — without it, the YAML lib\n // re-inserts a blank line on the next run, breaking byte-identity.\n yaml += \"\\n\";\n yaml += renderTodoScaffolding();\n }\n\n const changed = isNew || normalize(yaml) !== normalize(existing!);\n return { changed, yaml };\n}\n\nfunction ensureScalar(doc: Document, key: string, value: unknown): void {\n doc.set(key, value);\n}\n\nfunction ensureSeq(doc: Document, key: string): YAMLSeq {\n const node = doc.get(key, true);\n if (node && isSeq(node)) return node;\n const seq = new YAMLSeq();\n doc.set(key, seq);\n return seq;\n}\n\nfunction reconcileView(viewsSeq: YAMLSeq, desired: SmartMergeInput[\"desired\"]): void {\n const { view, components } = desired;\n // Match existing view by name first, then fall back to route. Route fallback\n // catches the rename-in-YAML case: agent renamed `name: Login` → `name: SignIn`\n // but kept `route: /login`. Without it, smart-merge would append a fresh\n // \"Login\" view next to \"SignIn\", duplicating the route.\n //\n // When matched by route, the existing name is treated as agent-owned (the\n // rename was intentional) and is preserved. Components are still reconciled.\n let existingView: YAMLMap | null = null;\n let matchedBy: \"name\" | \"route\" | null = null;\n for (const item of viewsSeq.items) {\n if (isMap(item) && getString(item, \"name\") === view.name) {\n existingView = item;\n matchedBy = \"name\";\n break;\n }\n }\n if (!existingView) {\n for (const item of viewsSeq.items) {\n if (isMap(item) && getString(item, \"route\") === view.route) {\n existingView = item;\n matchedBy = \"route\";\n break;\n }\n }\n }\n if (!existingView) {\n existingView = new YAMLMap();\n viewsSeq.add(existingView);\n }\n\n // Plugin-owned: overwrite. Agent-authored fields (memory, intent, requests,\n // unknown keys) are left untouched because we never call .delete() on them.\n // Exception: if matched by route, the existing name was agent-renamed — leave it.\n if (matchedBy !== \"route\") setMapEntry(existingView, \"name\", view.name);\n setMapEntry(existingView, \"route\", view.route);\n\n // Components: reconcile by name\n let componentsSeq = existingView.get(\"components\", true) as YAMLSeq | undefined;\n if (!componentsSeq || !isSeq(componentsSeq)) {\n componentsSeq = new YAMLSeq();\n existingView.set(\"components\", componentsSeq);\n }\n reconcileComponents(componentsSeq, components);\n}\n\nfunction reconcileComponents(seq: YAMLSeq, desired: ComponentDesired[]): void {\n for (const desiredComp of desired) {\n let existing: YAMLMap | null = null;\n for (const item of seq.items) {\n if (isMap(item) && getString(item, \"name\") === desiredComp.name) {\n existing = item;\n break;\n }\n }\n if (!existing) {\n existing = new YAMLMap();\n seq.add(existing);\n }\n setMapEntry(existing, \"name\", desiredComp.name);\n setMapEntry(existing, \"selector\", desiredComp.selector);\n if (desiredComp.children && desiredComp.children.length > 0) {\n let childSeq = existing.get(\"children\", true) as YAMLSeq | undefined;\n if (!childSeq || !isSeq(childSeq)) {\n childSeq = new YAMLSeq();\n existing.set(\"children\", childSeq);\n }\n reconcileComponents(childSeq, desiredComp.children);\n }\n // Components not in `desired` are NOT removed here; that's handled in a later\n // task with `react.removed-component-still-in-yaml` diagnostics.\n }\n}\n\nfunction getString(map: YAMLMap, key: string): string | null {\n const v = map.get(key, true);\n if (v instanceof Scalar && typeof v.value === \"string\") return v.value;\n return null;\n}\n\nfunction setMapEntry(map: YAMLMap, key: string, value: unknown): void {\n map.set(key, value);\n}\n\nfunction normalize(s: string): string {\n // Trailing-newline-only normalization; do not mangle inner whitespace.\n return s.replace(/\\s+$/, \"\");\n}\n","// src/plugin/merge/todo-scaffolding.ts\n//\n// Emits commented TODO scaffolding for the agent-authored fields of a freshly\n// generated view file: `memory`, `intent`, `requests`. Output is YAML-comment\n// only — the file still parses cleanly until the agent uncomments and fills\n// in real values.\n//\n// This module is invoked exclusively from `smartMerge` when the target file\n// did not previously exist on disk (`existing == null`). Re-running `gen` on a\n// populated `.sightmap/` does NOT re-emit this scaffolding — preserving\n// idempotency per the codegen spec.\n\nconst SCAFFOLDING = `#\n# Agent-authored fields below — uncomment and fill in.\n#\n# TODO: capture observed runtime behavior the agent should know about\n# (one short sentence per entry; no marketing copy).\n# memory:\n# - \"Form auto-submits on Enter; verify disabled-button logic.\"\n# - \"Submit returns 401 on bad credentials.\"\n#\n# TODO: describe what this view is for in one sentence.\n# intent: \"Authenticate the user before entering the dashboard.\"\n#\n# TODO: list HTTP requests this view fires (method + path).\n# requests:\n# - method: POST\n# path: /api/login\n#\n`;\n\nexport function renderTodoScaffolding(): string {\n return SCAFFOLDING;\n}\n","// src/cli/commands/gen-summary.ts\n//\n// Pure formatter for `sightmap-react gen` console output. Three output shapes:\n//\n// - \"first-run\": every reported change has before === null. Print\n// views written, components linked, alphabetized\n// suggested first-edit targets, and a pointer at\n// /sightmap:audit.\n// - \"up-to-date\": no changes; one-line.\n// - \"structural-update\": at least one file existed AND at least one\n// changed. List only the changed files.\n//\n// Pure: no I/O, no `process.cwd()` lookups, no clock reads. Take cwd as input.\n// All paths in the output are cwd-relative for portable copy/paste.\n\nimport { relative } from \"node:path\";\nimport { parse as yamlParse } from \"yaml\";\n\nexport type FileChange = {\n path: string;\n before: string | null;\n after: string;\n changed: boolean;\n};\n\nexport interface SummaryInput {\n cwd: string;\n changes: FileChange[];\n written: string[];\n}\n\nexport type SummaryKind = \"first-run\" | \"up-to-date\" | \"structural-update\";\n\nexport interface SummaryOutput {\n kind: SummaryKind;\n lines: string[];\n}\n\nconst AUDIT_HINT =\n \"Run /sightmap:audit (Claude Code plugin) to surface missing memory and broken selectors.\";\n\nexport function formatSummary(input: SummaryInput): SummaryOutput {\n const { cwd, changes, written } = input;\n\n const allChanged = changes.filter((c) => c.changed);\n const anyChanged = allChanged.length > 0;\n const everyChangeIsNew = changes.length > 0 && changes.every((c) => c.before === null);\n\n if (!anyChanged) {\n return { kind: \"up-to-date\", lines: [\"sightmap: up to date\"] };\n }\n\n if (everyChangeIsNew) {\n return formatFirstRun(input);\n }\n\n // Structural update: at least one pre-existing file changed.\n const lines: string[] = [];\n lines.push(`sightmap: wrote ${written.length} file(s):`);\n for (const c of allChanged) {\n lines.push(` - ${relative(cwd, c.path)}`);\n }\n return { kind: \"structural-update\", lines };\n}\n\nfunction formatFirstRun(input: SummaryInput): SummaryOutput {\n const { cwd, changes, written } = input;\n const lines: string[] = [];\n\n // Total views and total components, derived by parsing the `after` content.\n // Names list preserves input order (the orchestrator's discovery order, which\n // mirrors the agent's mental model of the app).\n let viewCount = 0;\n let componentCount = 0;\n const viewNames: string[] = [];\n for (const c of changes) {\n try {\n const parsed = yamlParse(c.after) as\n | { views?: Array<{ name?: string; components?: unknown[] }> }\n | null;\n const views = parsed?.views ?? [];\n for (const v of views) {\n viewCount++;\n if (typeof v.name === \"string\") viewNames.push(v.name);\n const comps = Array.isArray(v.components) ? v.components : [];\n componentCount += comps.length;\n }\n } catch {\n // Malformed YAML in `after` is a defect we surface elsewhere; here we just skip counting.\n }\n }\n\n // Suggested-edit list is alphabetized by relative path so curators get a\n // deterministic, copy-pasteable ordering regardless of orchestrator order.\n const sortedForEdit = [...changes].sort((a, b) =>\n relative(cwd, a.path).localeCompare(relative(cwd, b.path)),\n );\n\n lines.push(`sightmap: wrote ${written.length} file(s) (first run on empty .sightmap/)`);\n lines.push(\"\");\n lines.push(`Views (${viewCount} total)`);\n lines.push(` views: ${viewNames.join(\", \")}`);\n lines.push(`Components linked: ${componentCount}`);\n lines.push(\"\");\n lines.push(\"Next steps — open these files and replace the TODO blocks with real values:\");\n // Exclude shared.yaml from the suggested first-edit list — it's not a view file.\n const editTargets = sortedForEdit.filter((c) => !c.path.endsWith(\"shared.yaml\"));\n for (const c of editTargets) {\n lines.push(` - ${relative(cwd, c.path)}`);\n }\n lines.push(\"\");\n lines.push(AUDIT_HINT);\n\n return { kind: \"first-run\", lines };\n}\n","// src/cli/commands/validate.ts\nimport { join } from \"node:path\";\nimport { loadDirectory } from \"@sightmap/sightmap\";\nimport { resolveAdapter, type RouterChoice } from \"../../plugin/adapters/index.js\";\nimport { REACT_ROUTE_NO_VIEW_IN_YAML } from \"../../plugin/diagnostics.js\";\n\nexport async function validateCommand(opts: { cwd: string; router: string; output: string }): Promise<void> {\n const dir = join(opts.cwd, opts.output);\n const sightmap = await loadDirectory(dir);\n\n let exitCode = 0;\n for (const diag of sightmap.diagnostics) {\n if (diag.severity === \"error\") {\n console.error(`[ERROR] ${diag.code}: ${diag.message}${diag.path ? ` (${diag.path})` : \"\"}`);\n exitCode = 1;\n }\n }\n\n // React-specific drift check: every router-discovered route should have a view in the YAML.\n const adapter = await resolveAdapter(opts.router as RouterChoice, opts.cwd);\n if (!adapter) {\n console.error(`[ERROR] react.unknown-router: No supported router detected at ${opts.cwd}. Cannot validate.`);\n process.exit(1);\n }\n const routes = await adapter.discoverRoutes({\n projectRoot: opts.cwd,\n resolveSource: (id) => join(opts.cwd, id),\n });\n const viewRoutes = new Set<string>();\n for (const v of sightmap.views ?? []) viewRoutes.add(v.route);\n for (const r of routes) {\n if (!viewRoutes.has(r.pattern)) {\n console.error(`[WARNING] ${REACT_ROUTE_NO_VIEW_IN_YAML}: route ${r.pattern} exists in router but no view in YAML`);\n }\n }\n\n if (exitCode !== 0) process.exit(exitCode);\n}\n"],"mappings":"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","names":["relative","fs","dirname","join","fs","join","fs","existsSync","dirname","join","resolve","parseAst","join","fs","parseAst","existsSync","walkComponentTree","resolve","resolveLocalImport","dirname","fs","join","fs","fs","join","fs","dirname","relative","relative","join","loadDirectory","join","loadDirectory"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/gen.ts","../../src/plugin/orchestrator.ts","../../src/plugin/adapters/index.ts","../../src/plugin/adapters/rr7-declarative.ts","../../src/plugin/router-adapter.ts","../../src/plugin/diagnostics.ts","../../src/plugin/adapters/rr7-framework.ts","../../src/plugin/ast/scan.ts","../../src/plugin/merge/smart-merge.ts","../../src/plugin/merge/todo-scaffolding.ts","../../src/cli/commands/gen-summary.ts","../../src/cli/commands/validate.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { genCommand } from \"./commands/gen.js\";\nimport { validateCommand } from \"./commands/validate.js\";\n\nconst program = new Command()\n .name(\"sightmap-react\")\n .description(\"CLI for @sightmap/react: regenerate, validate, and inspect React sightmaps offline.\")\n .version(\"0.1.0\");\n\nprogram\n .command(\"gen\")\n .description(\"Run the build pipeline once and write any changed feature files.\")\n .option(\"--cwd <path>\", \"project root\", process.cwd())\n .option(\"--router <name>\", \"router adapter\", \"react-router-7\")\n .option(\"--output <dir>\", \"output dir\", \".sightmap\")\n .option(\"--check\", \"dry-run; exit 1 if any .sightmap file would change\")\n .option(\"--diff\", \"dry-run; print unified diff of would-be changes to stdout\")\n .option(\n \"--live <url>\",\n \"ALSO fetch a runtime sightmap from a running dev server at <url> (e.g. http://localhost:5173/__sightmap__/sightmap.json) and surface live-only views as info diagnostics. Optional; when omitted, only static AST discovery runs.\",\n )\n .action(genCommand);\n\nprogram\n .command(\"validate\")\n .description(\"Validate the .sightmap/ directory; surface React-specific drift diagnostics.\")\n .option(\"--cwd <path>\", \"project root\", process.cwd())\n .option(\"--output <dir>\", \"output dir\", \".sightmap\")\n .option(\"--router <name>\", \"router adapter (used for drift checks)\", \"react-router-7\")\n .action(validateCommand);\n\nprogram.parseAsync(process.argv).catch((err) => {\n console.error(err);\n process.exit(1);\n});\n","// src/cli/commands/gen.ts\n//\n// `sightmap-react gen` — one-shot codegen for `.sightmap/`.\n//\n// Default: write any changed feature files.\n// `--check`: dry-run; exit 1 if any file would change. CI gate.\n// `--diff`: dry-run; print a unified diff of would-be changes to stdout.\n//\n// Both flags imply dry-run (no filesystem writes). They compose: `--check --diff`\n// prints diffs AND exits non-zero on drift.\n\nimport { relative } from \"node:path\";\nimport { createTwoFilesPatch } from \"diff\";\nimport { runOnce, type LiveSightmapSnapshot } from \"../../plugin/orchestrator.js\";\nimport type { RouterChoice } from \"../../plugin/adapters/index.js\";\nimport { formatSummary } from \"./gen-summary.js\";\n\nexport type GenCommandOptions = {\n cwd: string;\n router: string;\n output: string;\n check?: boolean;\n diff?: boolean;\n live?: string;\n};\n\nexport async function genCommand(opts: GenCommandOptions): Promise<void> {\n const dryRun = !!(opts.check || opts.diff);\n\n let liveSightmap: LiveSightmapSnapshot | undefined;\n if (opts.live) {\n try {\n const res = await fetch(opts.live);\n if (!res.ok) {\n console.error(\n `sightmap: --live fetch failed with HTTP ${res.status}; continuing without live snapshot`,\n );\n } else {\n liveSightmap = (await res.json()) as LiveSightmapSnapshot;\n }\n } catch (err) {\n console.error(\n `sightmap: --live fetch failed (${(err as Error).message}); continuing without live snapshot`,\n );\n }\n }\n\n const result = await runOnce({\n projectRoot: opts.cwd,\n router: opts.router as RouterChoice,\n outputDir: opts.output,\n sharedFile: \"shared.yaml\",\n prune: \"warn\",\n dryRun,\n ...(liveSightmap ? { liveSightmap } : {}),\n });\n\n const wouldChange = result.changes.filter((c) => c.changed);\n\n if (opts.diff) {\n for (const c of wouldChange) {\n const rel = relative(opts.cwd, c.path);\n const oldName = c.before == null ? \"/dev/null\" : `a/${rel}`;\n const newName = `b/${rel}`;\n const patch = createTwoFilesPatch(oldName, newName, c.before ?? \"\", c.after);\n process.stdout.write(patch);\n }\n }\n\n if (opts.check) {\n if (wouldChange.length > 0) {\n console.error(\n `sightmap: ${wouldChange.length} file(s) would change. Run \\`sightmap-react gen\\` to update.`,\n );\n for (const c of wouldChange) console.error(` - ${relative(opts.cwd, c.path)}`);\n reportDiagnostics(result.diagnostics);\n process.exit(1);\n }\n console.log(\"sightmap: up to date\");\n } else if (opts.diff) {\n if (wouldChange.length === 0) console.log(\"sightmap: no changes\");\n } else {\n // Default branch: print first-run / steady-state / structural-update summary.\n const summary = formatSummary({\n cwd: opts.cwd,\n changes: result.changes,\n written: result.written,\n });\n for (const line of summary.lines) console.log(line);\n }\n\n if (reportDiagnostics(result.diagnostics)) process.exit(1);\n}\n\nfunction reportDiagnostics(diagnostics: { severity: string; code: string; message: string; file?: string; path?: string }[]): boolean {\n let hadError = false;\n for (const d of diagnostics) {\n const tag = d.severity.toUpperCase();\n const loc = [d.file, d.path].filter(Boolean).join(\" :: \");\n console.error(`[${tag}] ${d.code}: ${d.message}${loc ? ` (${loc})` : \"\"}`);\n if (d.severity === \"error\") hadError = true;\n }\n return hadError;\n}\n","// src/plugin/orchestrator.ts\n//\n// One-shot pipeline used by `sightmap-react gen`:\n//\n// 1. Resolve the framework adapter for the project's router.\n// 2. Discover routes via the adapter.\n// 3. AST-scan each route's source files for `data-sightmap` selectors.\n// 4. Promote multi-route components into shared.yaml.\n// 5. For each feature (group of routes sharing a featureName), smart-merge\n// the freshly-derived skeleton into `<feature>.yaml`, preserving any\n// agent-authored fields already in the file.\n//\n// `runOnce` is the only emit path; there is no Vite-plugin watch loop. The\n// last-emit fingerprint cache (mode-C continuous-emit infrastructure) has been\n// removed.\n//\n// Dedup against existing non-feature-scoped layouts (e.g. a hand-curated\n// `views.yaml` that already contains a route) is preserved: it lets users keep\n// their own file layout and still re-run `gen` without producing duplicate\n// per-feature stubs. The dedup matches by view name AND route pattern.\n\nimport { promises as fs } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type { Diagnostic } from \"@sightmap/sightmap\";\nimport { resolveAdapter, type RouterChoice } from \"./adapters/index.js\";\nimport type { RouteDescriptor } from \"./router-adapter.js\";\nimport { deriveViewName } from \"./router-adapter.js\";\nimport { scanFile, type AstFinding } from \"./ast/scan.js\";\nimport { smartMerge, type ComponentDesired } from \"./merge/smart-merge.js\";\nimport { loadDirectory, canonicalize } from \"@sightmap/sightmap\";\nimport {\n REACT_LIVE_ONLY_VIEW,\n REACT_NO_ROUTES_DISCOVERED,\n REACT_UNKNOWN_ROUTER,\n REACT_VIEW_ALREADY_DEFINED,\n} from \"./diagnostics.js\";\n\n/**\n * Loose wire-shape of a sightmap fetched from the dev middleware\n * (`/__sightmap__/sightmap.json`). We only consume the `views` array's name +\n * route pair; richer fields (memory, components) are accepted but ignored.\n *\n * Kept structurally separate from `Sightmap` so the CLI does not have to\n * fully construct a brand-typed Sightmap to call `runOnce`.\n */\nexport type LiveSightmapSnapshot = {\n version?: 1;\n views?: Array<{ name: string; route: string; [k: string]: unknown }>;\n // Forward-compat: any other fields the endpoint may return.\n [k: string]: unknown;\n};\n\nexport type RunOptions = {\n projectRoot: string;\n router: RouterChoice;\n outputDir: string; // relative to projectRoot, e.g. \".sightmap\"\n sharedFile: string; // e.g. \"shared.yaml\"\n // v0.1 only emits warnings on removed components. The \"delete\" / \"preserve\" modes are\n // typed for forward compat but unused — the orchestrator does not yet detect or act on\n // removed-from-source entries. Track in v0.2 alongside the prune diagnostic emission.\n prune: \"warn\";\n // When true, compute changes but do not touch the filesystem. Powers\n // `sightmap-react gen --check` and `--diff`.\n dryRun?: boolean;\n // WI-7 task 8: optional live snapshot fetched from the dev middleware. When\n // provided, views present here but not in the static-discovery output are\n // surfaced as info diagnostics so the curator can hand-author them. We do\n // NOT auto-emit YAML for live-only views — that promotes the live surface\n // to a parallel codegen path, which the codegen spec explicitly rejected.\n liveSightmap?: LiveSightmapSnapshot;\n};\n\nexport type FileChange = {\n path: string; // absolute path of the target file\n before: string | null; // existing on-disk content, or null if new\n after: string; // content that gen would write\n changed: boolean; // true iff after !== before (modulo trailing-ws normalize)\n};\n\nexport type RunResult = {\n written: string[]; // absolute paths of files actually written (empty when dryRun)\n changes: FileChange[]; // every target file gen considered, write or no\n diagnostics: Diagnostic[];\n};\n\nexport async function runOnce(opts: RunOptions): Promise<RunResult> {\n const adapter = await resolveAdapter(opts.router, opts.projectRoot);\n if (!adapter) {\n return {\n written: [],\n changes: [],\n diagnostics: [\n {\n severity: \"warning\",\n code: REACT_UNKNOWN_ROUTER,\n message: `No supported router detected at ${opts.projectRoot}. Skipping sightmap generation.`,\n },\n ],\n };\n }\n const sightmapDir = join(opts.projectRoot, opts.outputDir);\n if (!opts.dryRun) await fs.mkdir(sightmapDir, { recursive: true });\n\n let existingViewNames = new Set<string>();\n let existingViewRoutes = new Set<string>();\n try {\n const existing = await loadDirectory(sightmapDir);\n for (const v of existing.views ?? []) {\n existingViewNames.add(v.name);\n existingViewRoutes.add(v.route);\n }\n } catch {\n // No existing sightmap (or directory unreadable) — fine, start fresh\n }\n\n const written: string[] = [];\n const changes: FileChange[] = [];\n const allDiagnostics: Diagnostic[] = [];\n\n const routes = await adapter.discoverRoutes({\n projectRoot: opts.projectRoot,\n resolveSource: (id) => join(opts.projectRoot, id),\n diagnostics: allDiagnostics,\n });\n\n // Adapter returned no routes. The most common causes are misconfiguration,\n // not \"this is intentional\" — surface them so the curator gets a hint\n // instead of a silent `sightmap: up to date` and an empty `.sightmap/`.\n if (routes.length === 0) {\n allDiagnostics.push({\n severity: \"warning\",\n code: REACT_NO_ROUTES_DISCOVERED,\n message:\n `No routes discovered by the ${adapter.name} adapter. ` +\n `Common causes: the entry file isn't where the adapter looks ` +\n `(declarative: \\`src/main.{tsx,ts,jsx,js}\\`; framework: \\`app/routes.ts\\`); ` +\n `the project uses RR7 data-mode (\\`createBrowserRouter\\`), not yet supported; ` +\n `the framework project uses \\`flatRoutes()\\` filesystem routing, not yet supported; ` +\n `the entry imports the app via a path alias defined outside tsconfig ` +\n `(e.g. only in \\`vite.config.ts\\`) so the adapter can't resolve it; or ` +\n `no \\`<Routes>\\` JSX / programmatic \\`route(...)\\` config is reachable from the entry. ` +\n `If your routes are real, surface them via \\`sightmap-react gen --live <url>\\`.`,\n });\n }\n\n // Build a map of (route → discovered components from its source files).\n const componentsByRoute = new Map<string, ComponentDesired[]>();\n const componentRouteCount = new Map<string, Set<string>>();\n\n for (const route of routes) {\n const findings = await collectFindings(route.sourceFiles, allDiagnostics);\n componentsByRoute.set(route.pattern, findings.map(toComponent));\n for (const f of findings) {\n if (!componentRouteCount.has(f.name)) componentRouteCount.set(f.name, new Set());\n componentRouteCount.get(f.name)!.add(route.pattern);\n }\n }\n\n // Promote multi-route components to shared.yaml.\n const sharedComponents: ComponentDesired[] = [];\n for (const [name, routesFor] of componentRouteCount) {\n if (routesFor.size > 1) {\n sharedComponents.push({\n name,\n selector: `[data-sightmap=\"${name}\"]`,\n });\n for (const r of routesFor) {\n const list = componentsByRoute.get(r) ?? [];\n const filtered = list.filter((c) => c.name !== name);\n componentsByRoute.set(r, filtered);\n }\n }\n }\n\n // Emit per-feature files (group routes by featureName).\n const byFeature = new Map<string, RouteDescriptor[]>();\n for (const r of routes) {\n if (!byFeature.has(r.featureName)) byFeature.set(r.featureName, []);\n byFeature.get(r.featureName)!.push(r);\n }\n\n for (const [featureName, featureRoutes] of byFeature) {\n const filePath = join(sightmapDir, `${featureName}.yaml`);\n const targetFileExists = await fs.access(filePath).then(() => true).catch(() => false);\n const before = await readIfExists(filePath);\n\n // Smart-merge each route's view in succession, threading the YAML through\n // each iteration. The first call may scaffold (HEADER + TODO block) when\n // `existing` is null; subsequent calls just add/update views in the\n // already-scaffolded document.\n let currentYaml: string | null = before;\n let anyChanged = false;\n let emittedAnyView = false;\n\n for (const route of featureRoutes) {\n const viewName = deriveViewName(route.pattern);\n const components = componentsByRoute.get(route.pattern) ?? [];\n\n const isAlreadyDefinedElsewhere =\n !targetFileExists &&\n (existingViewNames.has(viewName) || existingViewRoutes.has(route.pattern));\n\n if (isAlreadyDefinedElsewhere) {\n allDiagnostics.push({\n severity: \"info\",\n code: REACT_VIEW_ALREADY_DEFINED,\n message: `Route ${route.pattern} (view \"${viewName}\") is already defined in an existing YAML file outside the per-feature convention. Skipping stub emission. To migrate to the per-feature layout, move the view definition to ${featureName}.yaml.`,\n });\n continue;\n }\n\n const merged = smartMerge({\n existing: currentYaml,\n desired: {\n view: { name: viewName, route: route.pattern },\n components,\n },\n });\n currentYaml = merged.yaml;\n if (merged.changed) anyChanged = true;\n emittedAnyView = true;\n }\n\n // Only emit a FileChange when we actually processed at least one view for\n // this feature. If every route was skipped (all already-defined-elsewhere),\n // currentYaml still equals `before` and no change is recorded.\n if (emittedAnyView && currentYaml !== null) {\n const finalYaml = toCanonical(currentYaml, filePath);\n const changed = anyChanged || finalYaml !== before;\n changes.push({ path: filePath, before, after: finalYaml, changed });\n if (changed && !opts.dryRun) {\n await atomicWrite(filePath, finalYaml);\n written.push(filePath);\n }\n }\n }\n\n // Emit shared.yaml if non-empty.\n if (sharedComponents.length > 0) {\n const filePath = join(sightmapDir, opts.sharedFile);\n const existing = await readIfExists(filePath);\n const merged = smartMerge({\n existing,\n desired: {\n view: { name: \"Shared\", route: \"/**\" }, // sentinel — `Shared` is global, route matches any\n components: sharedComponents,\n },\n });\n const finalYaml = toCanonical(merged.yaml, filePath);\n const changed = merged.changed || finalYaml !== existing;\n changes.push({ path: filePath, before: existing, after: finalYaml, changed });\n if (changed && !opts.dryRun) {\n await atomicWrite(filePath, finalYaml);\n written.push(filePath);\n }\n }\n\n // WI-7 task 8: surface views present at runtime but missing from static\n // discovery. We do NOT auto-emit YAML for these — the curator hand-authors a\n // file per the diagnostic's hint, preserving the invariant that codegen\n // owns only what it can derive from source.\n if (opts.liveSightmap?.views?.length) {\n const staticViewNames = new Set<string>();\n const staticViewRoutes = new Set<string>();\n // Names already discovered from source...\n for (const r of routes) staticViewNames.add(deriveViewName(r.pattern));\n // ...plus any name/route already present in the existing per-feature output\n // (so a view defined in a hand-curated views.yaml does not produce a\n // false-positive live-only-view diagnostic).\n for (const n of existingViewNames) staticViewNames.add(n);\n for (const rt of existingViewRoutes) staticViewRoutes.add(rt);\n for (const c of changes) {\n // matchAll (not match) catches every view in a multi-view file —\n // post-#17, a feature can hold N views in one file.\n for (const m of c.after.matchAll(/^\\s*-\\s+name:\\s*(\\S+)/gm)) {\n staticViewNames.add(m[1]!);\n }\n }\n\n for (const liveView of opts.liveSightmap.views) {\n if (!liveView || typeof liveView.name !== \"string\") continue;\n if (staticViewNames.has(liveView.name) || staticViewRoutes.has(liveView.route)) continue;\n const safeFile = liveView.name.toLowerCase().replace(/[^a-z0-9-_]/g, \"-\");\n allDiagnostics.push({\n severity: \"info\",\n code: REACT_LIVE_ONLY_VIEW,\n message: `View \"${liveView.name}\" (route ${liveView.route}) appeared at runtime but was not discovered by the static AST scan. Add a data-sightmap attribute or hand-author a .sightmap/${safeFile}.yaml file.`,\n });\n }\n }\n\n return { written, changes, diagnostics: allDiagnostics };\n}\n\nasync function collectFindings(files: string[], diagnostics: Diagnostic[]): Promise<AstFinding[]> {\n const out: AstFinding[] = [];\n for (const f of files) {\n const result = await scanFile(f);\n out.push(...result.findings);\n diagnostics.push(...result.diagnostics);\n }\n return out;\n}\n\nfunction toComponent(f: AstFinding): ComponentDesired {\n return { name: f.name, selector: `[data-sightmap=\"${f.name}\"]` };\n}\n\nasync function readIfExists(path: string): Promise<string | null> {\n try {\n return await fs.readFile(path, \"utf-8\");\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw e;\n }\n}\n\n// Pipe smart-merge output through the canonical formatter so emitted YAML\n// passes `sightmap fmt --check` (per-entry-type key order, top-level seq sort,\n// blank-line separators, universal quoting). Falls back to the input bytes if\n// the document fails to parse or schema-validate — those failure modes mean\n// smart-merge produced something we can't safely rewrite, which is a bug we'd\n// rather surface via the schema/parse diagnostics from `validate`/`loadDirectory`.\nfunction toCanonical(yaml: string, file: string): string {\n const c = canonicalize(yaml, { file });\n return c.kind === \"canonical\" ? c.text : yaml;\n}\n\nasync function atomicWrite(path: string, contents: string): Promise<void> {\n await fs.mkdir(dirname(path), { recursive: true });\n const tmp = `${path}.tmp-${process.pid}-${Date.now()}`;\n await fs.writeFile(tmp, contents, \"utf-8\");\n await fs.rename(tmp, path);\n}\n\nfunction capitalize(s: string): string {\n return s.length > 0 ? s[0]!.toUpperCase() + s.slice(1) : s;\n}\n","// src/plugin/adapters/index.ts\nimport { promises as fs } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { RouterAdapter } from \"../router-adapter.js\";\nimport { rr7DeclarativeAdapter } from \"./rr7-declarative.js\";\nimport { rr7FrameworkAdapter } from \"./rr7-framework.js\";\n\nexport type RouterChoice =\n | \"react-router-7\"\n | \"react-router-7-framework\"\n | \"auto\"\n | RouterAdapter;\n\nexport async function resolveAdapter(choice: RouterChoice, projectRoot?: string): Promise<RouterAdapter | null> {\n if (typeof choice === \"string\") {\n if (choice === \"react-router-7\") return rr7DeclarativeAdapter();\n if (choice === \"react-router-7-framework\") return rr7FrameworkAdapter();\n if (choice === \"auto\") {\n // Prefer framework mode when an `app/routes.ts` config is present;\n // otherwise fall back to declarative if `react-router` is in deps.\n if (projectRoot) {\n const framework = rr7FrameworkAdapter();\n if (framework.detect(projectRoot)) return framework;\n }\n const pkg = await readPackageJson(projectRoot);\n if (pkg?.dependencies?.[\"react-router\"] || pkg?.devDependencies?.[\"react-router\"]) {\n return rr7DeclarativeAdapter();\n }\n return null;\n }\n }\n return choice;\n}\n\nasync function readPackageJson(projectRoot?: string): Promise<any | null> {\n if (!projectRoot) return null;\n try {\n const raw = await fs.readFile(join(projectRoot, \"package.json\"), \"utf-8\");\n return JSON.parse(raw);\n } catch {\n return null;\n }\n}\n","// src/plugin/adapters/rr7-declarative.ts\n//\n// React Router 7 \"declarative\" adapter — discovers routes from <Routes> / <Route> JSX.\n//\n// v0.1 limitations (intentional — deferred to v0.2):\n// - Only resolves explicit string `path` props. Template-expression paths are not supported.\n// - Only follows local (relative) imports. Bare-specifier or aliased imports are skipped.\n// - Does not discover routes added via `useRoutes(routesArray)` — that is the data-mode\n// adapter, planned for v0.2.\n//\n// Note: `require(\"fs\").accessSync` was avoided here because this package is ESM-only\n// (\"type\": \"module\"). `require` is not defined in ESM. `existsSync` from \"node:fs\" is\n// used instead — it is synchronous, does not throw on missing files, and returns a boolean.\n\nimport { promises as fs, existsSync } from \"node:fs\";\nimport { dirname, join, relative, resolve } from \"node:path\";\nimport { parse as parseAst } from \"@swc/core\";\nimport type { Diagnostic } from \"@sightmap/sightmap\";\nimport type { RouterAdapter, AdapterContext, RouteDescriptor } from \"../router-adapter.js\";\nimport { deriveFeatureName } from \"../router-adapter.js\";\nimport { REACT_DYNAMIC_ROUTE_PATH } from \"../diagnostics.js\";\n\nconst ENTRY_CANDIDATES = [\"src/main.tsx\", \"src/main.ts\", \"src/main.jsx\", \"src/main.js\"];\n\nexport function rr7DeclarativeAdapter(): RouterAdapter {\n return {\n name: \"react-router-7-declarative\",\n detect(_projectRoot: string): boolean {\n // Best-effort sniff: does the project have react-router as a dep AND a main.* with <Routes>?\n // Defer detection logic to v0.2; in v0.1 this adapter is selected explicitly.\n return true;\n },\n async discoverRoutes(ctx: AdapterContext): Promise<RouteDescriptor[]> {\n const entry = await findEntry(ctx.projectRoot);\n if (!entry) return [];\n const visited = new Set<string>();\n const routePatterns: string[] = [];\n const sourceFilesPerRoute = new Map<string, Set<string>>();\n const pathsConfig = await loadPathsConfig(ctx.projectRoot);\n\n await walkModule(entry, ctx, pathsConfig, visited, routePatterns, sourceFilesPerRoute);\n\n return routePatterns.map((pattern) => ({\n pattern,\n featureName: deriveFeatureName(pattern),\n sourceFiles: Array.from(sourceFilesPerRoute.get(pattern) ?? new Set()),\n }));\n },\n };\n}\n\nasync function findEntry(projectRoot: string): Promise<string | null> {\n for (const candidate of ENTRY_CANDIDATES) {\n const path = join(projectRoot, candidate);\n try {\n await fs.access(path);\n return path;\n } catch {\n /* not present */\n }\n }\n return null;\n}\n\nasync function walkModule(\n file: string,\n ctx: AdapterContext,\n pathsConfig: PathsConfig | null,\n visited: Set<string>,\n routePatterns: string[],\n sourceFilesPerRoute: Map<string, Set<string>>,\n): Promise<void> {\n if (visited.has(file)) return;\n visited.add(file);\n let source: string;\n try {\n source = await fs.readFile(file, \"utf-8\");\n } catch {\n return;\n }\n\n const ast = await parseAst(source, { syntax: \"typescript\", tsx: true, target: \"es2022\" });\n\n // Pass 1: collect local import bindings (local name → resolved absolute path).\n const localImports = new Map<string, string>();\n collectImports(ast, file, pathsConfig, localImports);\n\n // Pass 2: find <Route path=\"...\"> elements and record source files.\n // collectRoutes is synchronous; we capture results and process async below\n // so we can walk each element's component subtree.\n const routesFound: Array<{ path: string; elementSpecs: string[] }> = [];\n collectRoutes(\n ast,\n (path, elementSpecs) => {\n routesFound.push({ path, elementSpecs });\n },\n ctx.diagnostics ? (diag) => ctx.diagnostics!.push(diag) : undefined,\n file,\n ctx.projectRoot,\n );\n\n for (const { path, elementSpecs } of routesFound) {\n routePatterns.push(path);\n if (!sourceFilesPerRoute.has(path)) sourceFilesPerRoute.set(path, new Set());\n sourceFilesPerRoute.get(path)!.add(file);\n\n // Walk every locally-bound component referenced by the route's element\n // subtree. The visited set is shared across specs for one route so two\n // siblings sharing a sub-component don't re-walk it; it's per-route so\n // the same file can still appear under multiple routes (the orchestrator\n // promotes multi-route components to shared.yaml).\n const visitedForRoute = new Set<string>();\n for (const spec of elementSpecs) {\n const resolved = localImports.get(spec) ?? null;\n if (resolved) {\n await walkComponentTree(resolved, pathsConfig, sourceFilesPerRoute.get(path)!, visitedForRoute);\n }\n }\n }\n\n // Pass 3: recurse into other imports so nested route trees are discovered.\n for (const target of localImports.values()) {\n await walkModule(target, ctx, pathsConfig, visited, routePatterns, sourceFilesPerRoute);\n }\n}\n\n// Walks a component's import tree, adding every reachable file to `sourceFiles`.\n// Cycle-protected via `visited`. The visited set is per-call (per-route) so\n// the same component can appear in multiple routes' sourceFiles — the\n// orchestrator promotes multi-route components to shared.yaml.\nasync function walkComponentTree(\n file: string,\n pathsConfig: PathsConfig | null,\n sourceFiles: Set<string>,\n visited: Set<string>,\n): Promise<void> {\n if (visited.has(file)) return;\n visited.add(file);\n sourceFiles.add(file);\n\n let source: string;\n try {\n source = await fs.readFile(file, \"utf-8\");\n } catch {\n return;\n }\n\n const ast = await parseAst(source, { syntax: \"typescript\", tsx: true, target: \"es2022\" });\n const localImports = new Map<string, string>();\n collectImports(ast, file, pathsConfig, localImports);\n\n for (const target of localImports.values()) {\n await walkComponentTree(target, pathsConfig, sourceFiles, visited);\n }\n}\n\nfunction collectImports(\n ast: any,\n fromFile: string,\n pathsConfig: PathsConfig | null,\n into: Map<string, string>,\n): void {\n for (const stmt of ast.body ?? []) {\n if (stmt.type === \"ImportDeclaration\") {\n const sourcePath = stmt.source?.value as string | undefined;\n if (!sourcePath) continue;\n const resolved = resolveImport(fromFile, sourcePath, pathsConfig);\n if (!resolved) continue;\n for (const spec of stmt.specifiers ?? []) {\n const local = spec.local?.value;\n if (typeof local === \"string\") into.set(local, resolved);\n }\n continue;\n }\n // Recognize `const Foo = lazy(() => import(\"./Foo\"))` (and variants like\n // `lazy(() => import(\"./Foo\").then(m => m.Foo))`, `lazy(async () => ...)`).\n // Treats the variable's binding name as the local import name and the dynamic\n // `import(...)` argument as the source spec — so the same downstream walker\n // that handles static imports also walks lazy-loaded route components.\n if (stmt.type === \"VariableDeclaration\") {\n for (const decl of stmt.declarations ?? []) {\n const local = decl.id?.value;\n if (typeof local !== \"string\" || !decl.init) continue;\n const dynamicSpec = findFirstDynamicImportSpec(decl.init);\n if (!dynamicSpec) continue;\n const resolved = resolveImport(fromFile, dynamicSpec, pathsConfig);\n if (!resolved) continue;\n into.set(local, resolved);\n }\n }\n }\n}\n\n// Resolves an import specifier to an absolute file path, handling both\n// relative imports and tsconfig path-aliases. Returns null for bare-package\n// imports (`react`, `@sightmap/sightmap`, etc.) — those are out of scope for\n// route discovery and silently skipped, same as before.\nfunction resolveImport(\n fromFile: string,\n importSpec: string,\n pathsConfig: PathsConfig | null,\n): string | null {\n if (importSpec.startsWith(\".\")) {\n return resolveLocalImport(fromFile, importSpec);\n }\n if (!pathsConfig) return null;\n const candidates = expandAlias(importSpec, pathsConfig);\n if (!candidates) return null;\n // Each candidate is an absolute path stem (with or without extension); try\n // file-form, directory-form, and the .js-extension TS quirk in the same\n // order as `resolveLocalImport`.\n for (const candidate of candidates) {\n const stripped = candidate.replace(/\\.(js|jsx|mjs)$/, \"\");\n for (const ext of [\".tsx\", \".ts\", \".jsx\", \".js\"]) {\n const p = `${stripped}${ext}`;\n if (existsSync(p)) return p;\n }\n for (const indexBase of [\"index.tsx\", \"index.ts\", \"index.jsx\", \"index.js\"]) {\n const p = resolve(stripped, indexBase);\n if (existsSync(p)) return p;\n }\n if (stripped !== candidate && existsSync(candidate)) return candidate;\n }\n return null;\n}\n\n// Subtree search for the first `import(\"...\")` call inside a node, returning\n// the static-string argument or null. Handles the common shapes — `lazy(() =>\n// import(\"./X\"))`, `lazy(() => import(\"./X\").then(...))`, `lazy(async () =>\n// import(\"./X\"))` — without trying to model arbitrary control flow.\nfunction findFirstDynamicImportSpec(node: any): string | null {\n if (!node || typeof node !== \"object\") return null;\n if (\n node.type === \"CallExpression\" &&\n node.callee?.type === \"Import\" &&\n Array.isArray(node.arguments) &&\n node.arguments[0]?.expression?.type === \"StringLiteral\"\n ) {\n return node.arguments[0].expression.value as string;\n }\n for (const key of Object.keys(node)) {\n const v = node[key];\n if (Array.isArray(v)) {\n for (const c of v) {\n const found = findFirstDynamicImportSpec(c);\n if (found) return found;\n }\n } else if (v && typeof v === \"object\") {\n const found = findFirstDynamicImportSpec(v);\n if (found) return found;\n }\n }\n return null;\n}\n\n// Uses existsSync (not require(\"fs\").accessSync) because this package is ESM-only.\n// require is not available in ESM modules and would throw ReferenceError at runtime.\n//\n// Handles three import styles:\n// 1. Extensionless (\"./Login\") → tries ./Login.tsx, .ts, .jsx, .js\n// 2. TS verbatimModuleSyntax (\".js\" on\n// a .ts/.tsx source: \"./Login.js\") → strips the trailing .js/.jsx/.mjs\n// and tries ./Login.tsx, .ts, .jsx, .js\n// 3. Directory-style (\"./pages/login\") → tries ./pages/login/index.{tsx,ts,jsx,js}\n// after the file-form lookups fail. Order\n// matches Node/bundler precedence: a\n// sibling `./pages/login.tsx` wins over a\n// `./pages/login/index.tsx`.\nfunction resolveLocalImport(fromFile: string, importSpec: string): string | null {\n const dir = dirname(fromFile);\n const stripped = importSpec.replace(/\\.(js|jsx|mjs)$/, \"\");\n for (const ext of [\".tsx\", \".ts\", \".jsx\", \".js\"]) {\n const candidate = resolve(dir, `${stripped}${ext}`);\n if (existsSync(candidate)) return candidate;\n }\n for (const indexBase of [\"index.tsx\", \"index.ts\", \"index.jsx\", \"index.js\"]) {\n const candidate = resolve(dir, stripped, indexBase);\n if (existsSync(candidate)) return candidate;\n }\n // Fall back to the original spec in case it's a real .js/.mjs file\n // (the strip-and-retry above won't hit it because we already tried `${stripped}.js`).\n if (stripped !== importSpec) {\n const original = resolve(dir, importSpec);\n if (existsSync(original)) return original;\n }\n return null;\n}\n\nfunction collectRoutes(\n ast: any,\n onRoute: (path: string, elementSpecs: string[]) => void,\n onDiagnostic?: (d: Diagnostic) => void,\n fromFile?: string,\n projectRoot?: string,\n): void {\n function visit(node: any, parentPath: string): void {\n if (!node || typeof node !== \"object\") return;\n let here = parentPath;\n if (node.type === \"JSXElement\" && node.opening?.name?.value === \"Route\") {\n let pathValue: string | null = null;\n let pathAttrIsNonLiteral = false;\n let outerElementName: string | null = null;\n const elementSpecs: string[] = [];\n for (const attr of node.opening.attributes ?? []) {\n if (attr.type !== \"JSXAttribute\") continue;\n if (attr.name?.value === \"path\") {\n if (attr.value?.type === \"StringLiteral\") {\n pathValue = attr.value.value;\n } else if (attr.value) {\n // Any other shape (template literal, identifier, expression, member\n // access) — emit a diagnostic so the curator knows we saw the route\n // but couldn't resolve its path.\n pathAttrIsNonLiteral = true;\n }\n }\n if (attr.name?.value === \"element\" && attr.value?.type === \"JSXExpressionContainer\") {\n const inner = attr.value.expression;\n if (inner?.type === \"JSXElement\") {\n // The outermost element name is often a cross-cutting wrapper\n // (`Suspense`, `ErrorBoundary`, `RequireAuth`, …) that lives in a\n // bare-package import, not a local binding. Collect every\n // JSXElement name in the subtree so the caller can resolve all\n // of them against `localImports` and walk the matches. The\n // canonical RR7 lazy-route pattern is\n // `element={<Suspense><Foo /></Suspense>}`, where `Foo` is the\n // local binding we actually care about.\n collectJsxElementNames(inner, elementSpecs);\n outerElementName = inner.opening?.name?.value ?? null;\n }\n }\n // RR7's `<Route Component={X} />` prop is functionally equivalent to\n // `element={<X />}` but takes the component reference directly. Real-world\n // apps mix the two freely (often using `Component` with `React.lazy(...)`).\n if (attr.name?.value === \"Component\" && attr.value?.type === \"JSXExpressionContainer\") {\n const inner = attr.value.expression;\n if (inner?.type === \"Identifier\" && typeof inner.value === \"string\") {\n elementSpecs.push(inner.value);\n }\n }\n }\n if (pathValue) {\n const joined = pathValue.startsWith(\"/\") ? pathValue : `${parentPath.replace(/\\/$/, \"\")}/${pathValue}`;\n // Skip pure-redirect routes — `<Route element={<Navigate ... />} />` doesn't\n // render a user-facing surface and only adds noise as an empty-components\n // view in the YAML. Match only when `Navigate` is the *outermost* element\n // (the redirect form); a `Navigate` rendered inside a real wrapper is\n // unusual but still a real route.\n if (outerElementName !== \"Navigate\") {\n onRoute(joined, elementSpecs);\n }\n here = joined;\n } else if (pathAttrIsNonLiteral && onDiagnostic) {\n const where = fromFile && projectRoot ? relative(projectRoot, fromFile) : fromFile ?? \"<unknown>\";\n onDiagnostic({\n severity: \"info\",\n code: REACT_DYNAMIC_ROUTE_PATH,\n message: `Route in ${where} uses a non-literal \\`path\\` (template literal / identifier / expression). Static AST discovery cannot resolve dynamic paths; hand-author this view in a feature YAML or refactor to a literal string.`,\n });\n }\n }\n for (const key of Object.keys(node)) {\n const v = (node as any)[key];\n if (Array.isArray(v)) v.forEach((c) => visit(c, here));\n else if (v && typeof v === \"object\") visit(v, here);\n }\n }\n visit(ast, \"\");\n}\n\n// Recursively walks a JSX expression subtree, pushing every JSXElement\n// opening name we encounter into `into`. Caller filters by `localImports`,\n// so package-level wrappers (`Suspense`, `ErrorBoundary`, …) drop out\n// naturally without needing a name-based denylist.\nfunction collectJsxElementNames(node: any, into: string[]): void {\n if (!node || typeof node !== \"object\") return;\n if (node.type === \"JSXElement\") {\n const name = node.opening?.name?.value;\n if (typeof name === \"string\") into.push(name);\n }\n for (const key of Object.keys(node)) {\n const v = (node as any)[key];\n if (Array.isArray(v)) v.forEach((c) => collectJsxElementNames(c, into));\n else if (v && typeof v === \"object\") collectJsxElementNames(v, into);\n }\n}\n\n/**\n * Resolved alias-resolution context derived from the project's tsconfig(s).\n *\n * `baseUrl` is absolute. `paths` keys are kept verbatim from the tsconfig\n * (e.g. `\"@/*\"`); each value is the array of substitution targets from the\n * tsconfig (e.g. `[\"./src/*\"]`), themselves relative to `baseUrl`.\n */\ntype PathsConfig = {\n baseUrl: string;\n paths: Record<string, string[]>;\n};\n\n// Loads tsconfig path-alias config from the project. Reads tsconfig.json AND\n// tsconfig.app.json (the typical Vite layout where the root config is just a\n// `references` shell and the alias-bearing config lives in tsconfig.app.json).\n// Returns null if neither defines `paths`. Tolerates JSON-with-comments —\n// tsconfig is JSON-with-comments by convention and TypeScript's own parser\n// is more lenient than `JSON.parse`. We don't try to model `extends`; the\n// flat case covers the dominant idiom.\nasync function loadPathsConfig(projectRoot: string): Promise<PathsConfig | null> {\n const merged: Record<string, string[]> = {};\n let baseUrl: string | null = null;\n for (const name of [\"tsconfig.json\", \"tsconfig.app.json\"]) {\n const fp = join(projectRoot, name);\n let raw: string;\n try {\n raw = await fs.readFile(fp, \"utf-8\");\n } catch {\n continue;\n }\n const json = parseTsconfigJson(raw);\n const co = json?.compilerOptions;\n if (!co) continue;\n if (!baseUrl && typeof co.baseUrl === \"string\") {\n baseUrl = resolve(dirname(fp), co.baseUrl);\n }\n if (co.paths && typeof co.paths === \"object\") {\n for (const [k, v] of Object.entries(co.paths)) {\n if (Array.isArray(v)) merged[k] = v as string[];\n }\n }\n }\n if (Object.keys(merged).length === 0) return null;\n return { baseUrl: baseUrl ?? projectRoot, paths: merged };\n}\n\n// Strip the two tsconfig-style \"JSON with comments\" extensions: `// line`\n// comments and `/* block */` comments. Trailing commas before `}` / `]` are\n// also tolerated. Conservative — it doesn't try to be a full JSON5 parser,\n// just enough to handle the conventions tsconfig templates use.\nfunction parseTsconfigJson(raw: string): any | null {\n const stripped = raw\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n .replace(/(^|[^:])\\/\\/.*$/gm, \"$1\")\n .replace(/,(\\s*[}\\]])/g, \"$1\");\n try {\n return JSON.parse(stripped);\n } catch {\n return null;\n }\n}\n\n// Expand a non-relative import spec against the configured aliases. Returns\n// the array of absolute candidate paths to try (one per alias target), or\n// null if no alias matched. Bare-package imports return null and stay\n// silently skipped — same as before path-alias support landed.\nfunction expandAlias(importSpec: string, cfg: PathsConfig): string[] | null {\n for (const [alias, targets] of Object.entries(cfg.paths)) {\n if (alias.endsWith(\"/*\")) {\n const prefix = alias.slice(0, -1); // includes trailing slash, e.g. \"@/\"\n if (importSpec.startsWith(prefix)) {\n const rest = importSpec.slice(prefix.length);\n return targets.map((t) => {\n const tnorm = t.endsWith(\"/*\") ? t.slice(0, -2) : t;\n return resolve(cfg.baseUrl, tnorm, rest);\n });\n }\n } else if (importSpec === alias) {\n return targets.map((t) => resolve(cfg.baseUrl, t));\n }\n }\n return null;\n}\n","// src/plugin/router-adapter.ts\nimport type { Diagnostic } from \"@sightmap/sightmap\";\n\nexport type RouteDescriptor = {\n pattern: string; // normalized to spec route grammar\n featureName: string; // chunking key — derives the YAML filename\n sourceFiles: string[]; // absolute paths reachable from this route's tree\n meta?: Record<string, unknown>; // raw router metadata; informational only in v1\n};\n\nexport type AdapterContext = {\n projectRoot: string;\n resolveSource: (id: string) => string | null;\n /**\n * Optional sink the adapter can push diagnostics into during discovery — e.g.\n * a `<Route>` it found but couldn't fully process. Adapters MUST tolerate\n * this being absent (callers from tests may not pass one). The orchestrator\n * always provides it and forwards the contents into its own diagnostic\n * stream so they reach the CLI summary.\n */\n diagnostics?: Diagnostic[];\n};\n\nexport interface RouterAdapter {\n name: string;\n detect(projectRoot: string): boolean;\n discoverRoutes(ctx: AdapterContext): Promise<RouteDescriptor[]>;\n /** Optional client-side helper. Falls back to `location.pathname` if absent. */\n currentRoute?(): string;\n}\n\n/** Derive the feature name from a route pattern. First non-parameter segment, or \"home\" for \"/\". */\nexport function deriveFeatureName(pattern: string): string {\n const segments = pattern.split(\"/\").filter(Boolean);\n for (const seg of segments) {\n if (!seg.startsWith(\":\") && !seg.startsWith(\"*\")) return sanitize(seg);\n }\n return \"home\";\n}\n\n/**\n * Derive a view name from a route pattern.\n *\n * Picks the LAST non-parameter segment, capitalized — so `/app/dashboard` →\n * `Dashboard`, `/settings/billing` → `Billing`, `/login` → `Login`.\n *\n * Routes ending in a parameter (`/users/:id`) get the preceding segment with\n * `Detail` appended (`UsersDetail`) so they don't collide with the list view.\n *\n * Routes ending in a wildcard (`/files/*`, `/*`) get `Catchall` appended —\n * a different concept from `:param` (catch-all matches multiple segments;\n * named params match one).\n *\n * Falls back to `Home` for `/`.\n */\nexport function deriveViewName(pattern: string): string {\n const segments = pattern.split(\"/\").filter(Boolean);\n if (segments.length === 0) return \"Home\";\n\n const last = segments[segments.length - 1]!;\n const lastIsParam = last.startsWith(\":\");\n const lastIsWildcard = last.startsWith(\"*\");\n\n if (lastIsParam || lastIsWildcard) {\n const suffix = lastIsWildcard ? \"Catchall\" : \"Detail\";\n // Walk back to the last static segment and append the suffix.\n for (let i = segments.length - 2; i >= 0; i--) {\n const seg = segments[i]!;\n if (!seg.startsWith(\":\") && !seg.startsWith(\"*\")) {\n return capitalize(sanitize(seg)) + suffix;\n }\n }\n return suffix;\n }\n return capitalize(sanitize(last));\n}\n\nfunction sanitize(s: string): string {\n return s.replace(/[^a-zA-Z0-9_-]/g, \"-\").toLowerCase();\n}\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n","// React-specific diagnostic codes. Stable, kebab-case. Renames require a minor bump and a deprecation note.\n\nexport const REACT_DYNAMIC_DATA_SIGHTMAP = \"react.dynamic-data-sightmap\";\nexport const REACT_DYNAMIC_ROUTE_PATH = \"react.dynamic-route-path\";\nexport const REACT_NO_ROUTES_DISCOVERED = \"react.no-routes-discovered\";\nexport const REACT_REMOVED_COMPONENT_STILL_IN_YAML = \"react.removed-component-still-in-yaml\";\nexport const REACT_UNKNOWN_ROUTER = \"react.unknown-router\";\nexport const REACT_ROUTE_NO_VIEW_IN_YAML = \"react.route-no-view-in-yaml\";\nexport const REACT_VIEW_ALREADY_DEFINED = \"react.view-already-defined\";\nexport const REACT_LIVE_ONLY_VIEW = \"react.live-only-view\";\n","// src/plugin/adapters/rr7-framework.ts\n//\n// React Router 7 \"framework mode\" adapter — discovers routes from the\n// programmatic config in `app/routes.ts` (the API exported by\n// `@react-router/dev/routes`: `route`, `index`, `layout`, `prefix`).\n//\n// v0.1 scope:\n// - Reads `app/routes.ts` (or `.tsx`/`.js`/`.jsx`); the `app/` directory is\n// hardcoded. Custom `appDirectory` from `react-router.config.ts` is not yet\n// honored — projects using a different app-dir name fall through to \"no\n// supported router\".\n// - Recognizes top-level helpers by direct identifier name: `route`,\n// `index`, `layout`, `prefix`. Namespaced (`routes.route(...)`) or\n// re-exported / aliased helpers are not parsed.\n// - String-literal arguments only. Template-expression paths or computed\n// file specs are ignored.\n// - `flatRoutes()` (filesystem-based routing) is not supported in v0.1 —\n// projects relying on it will return zero routes.\n//\n// Layout semantics: `layout(file, [children])` adds the layout's component\n// tree to every descendant route's `sourceFiles`, so markers inside a layout\n// surface on every child route. The orchestrator's multi-route promotion then\n// hoists those markers into `shared.yaml`, matching the runtime where the\n// layout wraps each child via `<Outlet />`.\n\nimport { promises as fs, existsSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { parse as parseAst } from \"@swc/core\";\nimport type { RouterAdapter, AdapterContext, RouteDescriptor } from \"../router-adapter.js\";\nimport { deriveFeatureName } from \"../router-adapter.js\";\n\nconst ROUTES_CONFIG_CANDIDATES = [\n \"app/routes.ts\",\n \"app/routes.tsx\",\n \"app/routes.js\",\n \"app/routes.jsx\",\n];\n\nconst APP_DIR = \"app\";\n\nexport function rr7FrameworkAdapter(): RouterAdapter {\n return {\n name: \"react-router-7-framework\",\n detect(projectRoot: string): boolean {\n return findRoutesConfigSync(projectRoot) !== null;\n },\n async discoverRoutes(ctx: AdapterContext): Promise<RouteDescriptor[]> {\n const routesFile = await findRoutesConfig(ctx.projectRoot);\n if (!routesFile) return [];\n const appDir = join(ctx.projectRoot, APP_DIR);\n\n const source = await fs.readFile(routesFile, \"utf-8\");\n const ast = await parseAst(source, { syntax: \"typescript\", tsx: true, target: \"es2022\" });\n\n const defaultArray = findDefaultExportArray(ast);\n if (!defaultArray) return [];\n\n const collected: Array<{ pattern: string; sourceFiles: Set<string> }> = [];\n await walkRouteArray(defaultArray, { parentPattern: \"\", inheritedFiles: new Set() }, appDir, collected);\n\n return collected.map(({ pattern, sourceFiles }) => ({\n pattern,\n featureName: deriveFeatureName(pattern),\n sourceFiles: Array.from(sourceFiles),\n }));\n },\n };\n}\n\nfunction findRoutesConfigSync(projectRoot: string): string | null {\n for (const candidate of ROUTES_CONFIG_CANDIDATES) {\n const path = join(projectRoot, candidate);\n if (existsSync(path)) return path;\n }\n return null;\n}\n\nasync function findRoutesConfig(projectRoot: string): Promise<string | null> {\n for (const candidate of ROUTES_CONFIG_CANDIDATES) {\n const path = join(projectRoot, candidate);\n try {\n await fs.access(path);\n return path;\n } catch {\n /* not present */\n }\n }\n return null;\n}\n\n// Locate `export default [ ... ]` and return the inner ArrayExpression node.\n// Also handles `export default [...] satisfies RouteConfig` (TS satisfies wraps\n// the array in a TsSatisfiesExpression / TsAsExpression in swc) and the\n// `export default <expr>` -> ArrayExpression direct case.\nfunction findDefaultExportArray(ast: any): any | null {\n for (const stmt of ast.body ?? []) {\n if (stmt.type === \"ExportDefaultExpression\") {\n return unwrapArray(stmt.expression);\n }\n if (stmt.type === \"ExportDefaultDeclaration\") {\n const decl = stmt.decl ?? stmt.declaration;\n if (decl) return unwrapArray(decl);\n }\n }\n return null;\n}\n\nfunction unwrapArray(node: any): any | null {\n if (!node) return null;\n if (node.type === \"ArrayExpression\") return node;\n // Unwrap `satisfies` / `as` casts and parens.\n if (node.type === \"TsSatisfiesExpression\" || node.type === \"TsAsExpression\" || node.type === \"TsTypeAssertion\") {\n return unwrapArray(node.expression);\n }\n if (node.type === \"ParenthesisExpression\") return unwrapArray(node.expression);\n return null;\n}\n\ntype Frame = {\n parentPattern: string;\n inheritedFiles: Set<string>;\n};\n\nasync function walkRouteArray(\n arrayNode: any,\n frame: Frame,\n appDir: string,\n out: Array<{ pattern: string; sourceFiles: Set<string> }>,\n): Promise<void> {\n for (const elem of arrayNode.elements ?? []) {\n if (!elem) continue;\n // ArrayExpression elements in swc are wrapped: `{ spread: null, expression: <expr> }`\n // when in array literal context. Spread elements have `spread` set to a span.\n const expr = elem.expression ?? elem;\n const isSpread = !!elem.spread;\n if (isSpread) {\n // Only spread of a `prefix(...)` call is meaningful in v0.1.\n if (expr?.type === \"CallExpression\" && callName(expr) === \"prefix\") {\n const args = expr.arguments ?? [];\n const prefixArg = stringArg(args[0]);\n const childrenArr = arrayArg(args[1]);\n if (prefixArg !== null && childrenArr) {\n const childFrame: Frame = {\n parentPattern: joinPath(frame.parentPattern, prefixArg),\n inheritedFiles: frame.inheritedFiles,\n };\n await walkRouteArray(childrenArr, childFrame, appDir, out);\n }\n }\n continue;\n }\n if (expr?.type !== \"CallExpression\") continue;\n await processRouteCall(expr, frame, appDir, out);\n }\n}\n\nasync function processRouteCall(\n call: any,\n frame: Frame,\n appDir: string,\n out: Array<{ pattern: string; sourceFiles: Set<string> }>,\n): Promise<void> {\n const name = callName(call);\n const args = call.arguments ?? [];\n\n if (name === \"route\") {\n const pathArg = stringArg(args[0]);\n const fileArg = stringArg(args[1]);\n if (pathArg === null || fileArg === null) return;\n const pattern = joinPath(frame.parentPattern, pathArg);\n const sourceFiles = new Set<string>(frame.inheritedFiles);\n const resolvedFile = resolveAppFile(appDir, fileArg);\n if (resolvedFile) await walkComponentTree(resolvedFile, sourceFiles, new Set());\n out.push({ pattern, sourceFiles });\n\n // Children inherit the parent route's component tree. At runtime, child\n // routes render inside the parent's `<Outlet />`, so markers in the\n // parent's component tree appear on every descendant view.\n const childrenArr = arrayArg(args[2]);\n if (childrenArr) {\n const childFrame: Frame = {\n parentPattern: pattern,\n inheritedFiles: union(frame.inheritedFiles, sourceFiles),\n };\n await walkRouteArray(childrenArr, childFrame, appDir, out);\n }\n return;\n }\n\n if (name === \"index\") {\n const fileArg = stringArg(args[0]);\n if (fileArg === null) return;\n // Index routes match the parent pattern exactly. At the top level that's \"/\".\n const pattern = frame.parentPattern || \"/\";\n const sourceFiles = new Set<string>(frame.inheritedFiles);\n const resolvedFile = resolveAppFile(appDir, fileArg);\n if (resolvedFile) await walkComponentTree(resolvedFile, sourceFiles, new Set());\n out.push({ pattern, sourceFiles });\n return;\n }\n\n if (name === \"layout\") {\n const fileArg = stringArg(args[0]);\n const childrenArr = arrayArg(args[1]);\n if (fileArg === null || !childrenArr) return;\n const layoutFiles = new Set<string>();\n const resolvedFile = resolveAppFile(appDir, fileArg);\n if (resolvedFile) await walkComponentTree(resolvedFile, layoutFiles, new Set());\n const childFrame: Frame = {\n parentPattern: frame.parentPattern,\n inheritedFiles: union(frame.inheritedFiles, layoutFiles),\n };\n await walkRouteArray(childrenArr, childFrame, appDir, out);\n return;\n }\n\n // Unknown helper — silently skip. v0.2 may add `flatRoutes()` etc.\n}\n\nfunction callName(call: any): string | null {\n const callee = call?.callee;\n if (!callee) return null;\n if (callee.type === \"Identifier\") return callee.value ?? null;\n return null;\n}\n\nfunction stringArg(arg: any): string | null {\n // ArrayExpression-style argument wrapper: `{ spread: null, expression: <expr> }`.\n const expr = arg?.expression ?? arg;\n if (expr?.type === \"StringLiteral\") return expr.value ?? null;\n return null;\n}\n\nfunction arrayArg(arg: any): any | null {\n const expr = arg?.expression ?? arg;\n if (expr?.type === \"ArrayExpression\") return expr;\n return null;\n}\n\n// Join a child path onto a parent pattern using RR7 semantics:\n// - child starting with \"/\" is absolute and replaces the parent\n// - empty child returns the parent (used for pathless `route(\"\", ...)`)\n// - otherwise the child is appended with a single \"/\" separator\nexport function joinPath(parent: string, child: string): string {\n if (child.startsWith(\"/\")) return child;\n if (!child) return parent || \"/\";\n const base = (parent || \"\").replace(/\\/+$/, \"\");\n const tail = child.replace(/^\\/+/, \"\");\n return base === \"\" ? `/${tail}` : `${base}/${tail}`;\n}\n\nfunction resolveAppFile(appDir: string, fileSpec: string): string | null {\n // RR7 file specs are relative to the app directory and may omit the extension.\n const base = resolve(appDir, fileSpec);\n if (existsSync(base)) return base;\n const stripped = base.replace(/\\.(js|jsx|mjs)$/, \"\");\n for (const ext of [\".tsx\", \".ts\", \".jsx\", \".js\"]) {\n const candidate = `${stripped}${ext}`;\n if (existsSync(candidate)) return candidate;\n }\n return null;\n}\n\nfunction union<T>(a: Set<T>, b: Set<T>): Set<T> {\n const out = new Set<T>(a);\n for (const v of b) out.add(v);\n return out;\n}\n\n// Walks a route file's local-import tree, adding every reachable file to\n// `sourceFiles`. Mirrors the declarative adapter's walker so marker scanning\n// in the orchestrator finds `data-sightmap` attributes inside imported\n// components, not just the route file itself.\nasync function walkComponentTree(\n file: string,\n sourceFiles: Set<string>,\n visited: Set<string>,\n): Promise<void> {\n if (visited.has(file)) return;\n visited.add(file);\n sourceFiles.add(file);\n\n let source: string;\n try {\n source = await fs.readFile(file, \"utf-8\");\n } catch {\n return;\n }\n\n const ast = await parseAst(source, { syntax: \"typescript\", tsx: true, target: \"es2022\" });\n for (const stmt of ast.body ?? []) {\n if (stmt.type !== \"ImportDeclaration\") continue;\n const sourcePath = stmt.source?.value as string | undefined;\n if (!sourcePath || !sourcePath.startsWith(\".\")) continue;\n const resolved = resolveLocalImport(file, sourcePath);\n if (!resolved) continue;\n await walkComponentTree(resolved, sourceFiles, visited);\n }\n}\n\nfunction resolveLocalImport(fromFile: string, importSpec: string): string | null {\n const dir = dirname(fromFile);\n const stripped = importSpec.replace(/\\.(js|jsx|mjs)$/, \"\");\n for (const ext of [\".tsx\", \".ts\", \".jsx\", \".js\"]) {\n const candidate = resolve(dir, `${stripped}${ext}`);\n if (existsSync(candidate)) return candidate;\n }\n if (stripped !== importSpec) {\n const original = resolve(dir, importSpec);\n if (existsSync(original)) return original;\n }\n return null;\n}\n","import { promises as fs } from \"node:fs\";\nimport { parse } from \"@swc/core\";\nimport type { Diagnostic } from \"@sightmap/sightmap\";\nimport { REACT_DYNAMIC_DATA_SIGHTMAP } from \"../diagnostics.js\";\n\nexport type AstFinding = {\n name: string;\n file: string;\n line: number;\n col: number;\n};\n\nexport type ScanResult = {\n findings: AstFinding[];\n diagnostics: Diagnostic[];\n};\n\nexport async function scanFile(file: string): Promise<ScanResult> {\n const source = await fs.readFile(file, \"utf-8\");\n const ast = await parse(source, {\n syntax: \"typescript\",\n tsx: true,\n target: \"es2022\",\n });\n\n const findings: AstFinding[] = [];\n const diagnostics: Diagnostic[] = [];\n\n walk(ast, (node: any) => {\n if (node?.type === \"JSXOpeningElement\" && Array.isArray(node.attributes)) {\n for (const attr of node.attributes) {\n if (attr?.type !== \"JSXAttribute\") continue;\n const nameNode = attr.name;\n if (!nameNode || nameNode.value !== \"data-sightmap\") continue;\n const valueNode = attr.value;\n if (valueNode?.type === \"StringLiteral\") {\n findings.push({\n name: valueNode.value,\n file,\n line: attr.span?.start ?? 0, // SWC byte offset — converted to line in caller if needed\n col: 0,\n });\n } else if (valueNode?.type === \"JSXExpressionContainer\") {\n diagnostics.push({\n severity: \"warning\",\n code: REACT_DYNAMIC_DATA_SIGHTMAP,\n message:\n `data-sightmap value must be a static string. Skipping.\\n` +\n ` Consider one of:\\n` +\n ` - Split into separate components with static markers (e.g. LoginForm + SignupForm)\\n` +\n ` - Use a static marker on the parent and target via descendant selector:\\n` +\n ` [data-sightmap=\"LoginPage\"] form\\n` +\n ` - If you genuinely need dynamic markers, hand-author the entries in extras.yaml`,\n file,\n });\n }\n }\n }\n });\n\n return { findings, diagnostics };\n}\n\nfunction walk(node: any, visit: (n: any) => void): void {\n if (!node || typeof node !== \"object\") return;\n visit(node);\n for (const key of Object.keys(node)) {\n const v = (node as any)[key];\n if (Array.isArray(v)) v.forEach((c) => walk(c, visit));\n else if (v && typeof v === \"object\") walk(v, visit);\n }\n}\n","// src/plugin/merge/smart-merge.ts\n//\n// One-shot smart merge for `sightmap-react gen`.\n//\n// Given an existing YAML file (if any) and a freshly-derived structural skeleton\n// (view + components from the router adapter and AST scan), produce a YAML output\n// that:\n//\n// 1. Replaces the structural fields (view name, route, component name, selector)\n// with the freshly-derived values.\n// 2. Preserves agent-authored fields not in the structural skeleton: `memory`,\n// intent labels, request mappings, and any unknown forward-compat fields.\n// 3. Preserves YAML comments, ordering, and blank lines.\n// 4. Is idempotent: re-running with the same desired skeleton against the same\n// existing file produces `changed=false`.\n//\n// This module is invoked exclusively from `sightmap-react gen` — there is no\n// continuous-mode emit path. Conflict-fingerprint diagnostics from the previous\n// design (mode C) have been removed alongside the last-emit cache.\n\nimport { Document, parseDocument, isMap, isSeq, YAMLMap, YAMLSeq, Scalar } from \"yaml\";\nimport { renderTodoScaffolding } from \"./todo-scaffolding.js\";\n\nexport type ComponentDesired = {\n name: string;\n selector: string;\n children?: ComponentDesired[];\n};\n\nexport type ViewDesired = {\n name: string;\n route: string;\n};\n\nexport type SmartMergeInput = {\n existing: string | null;\n desired: {\n view: ViewDesired;\n components: ComponentDesired[];\n };\n};\n\nexport type SmartMergeResult = {\n changed: boolean;\n yaml: string;\n};\n\nconst HEADER = `# This file is co-maintained by @sightmap/react and your agent.\n# Plugin updates: name, route, selector, children.\n# Agent curates: memory, intent, requests, and any unknown fields.\n# See https://sightmap.org/react for the full convention.\n`;\n\nexport function smartMerge(input: SmartMergeInput): SmartMergeResult {\n const { existing, desired } = input;\n\n const isNew = existing == null;\n const doc: Document = isNew\n ? new Document({ version: 1, views: [] })\n : parseDocument(existing);\n\n ensureScalar(doc, \"version\", 1);\n const viewsSeq = ensureSeq(doc, \"views\");\n reconcileView(viewsSeq, desired);\n\n let yaml = doc.toString();\n if (isNew) {\n // First-run scaffolding for a brand-new view file:\n // <plugin header>\n // <structural YAML>\n // <commented TODO blocks for memory / intent / requests>\n //\n // The TODO block is a YAML comment so the file still parses. We only emit\n // it on file creation; if the agent later deletes the block, re-running\n // `gen` does not bring it back — idempotency per the codegen spec.\n yaml = HEADER + yaml;\n if (!yaml.endsWith(\"\\n\")) yaml += \"\\n\";\n // The blank line separator before the scaffolding makes the file\n // round-trip stable through `parseDocument` — without it, the YAML lib\n // re-inserts a blank line on the next run, breaking byte-identity.\n yaml += \"\\n\";\n yaml += renderTodoScaffolding();\n }\n\n const changed = isNew || normalize(yaml) !== normalize(existing!);\n return { changed, yaml };\n}\n\nfunction ensureScalar(doc: Document, key: string, value: unknown): void {\n doc.set(key, value);\n}\n\nfunction ensureSeq(doc: Document, key: string): YAMLSeq {\n const node = doc.get(key, true);\n if (node && isSeq(node)) return node;\n const seq = new YAMLSeq();\n doc.set(key, seq);\n return seq;\n}\n\nfunction reconcileView(viewsSeq: YAMLSeq, desired: SmartMergeInput[\"desired\"]): void {\n const { view, components } = desired;\n // Match existing view by name first, then fall back to route. Route fallback\n // catches the rename-in-YAML case: agent renamed `name: Login` → `name: SignIn`\n // but kept `route: /login`. Without it, smart-merge would append a fresh\n // \"Login\" view next to \"SignIn\", duplicating the route.\n //\n // When matched by route, the existing name is treated as agent-owned (the\n // rename was intentional) and is preserved. Components are still reconciled.\n let existingView: YAMLMap | null = null;\n let matchedBy: \"name\" | \"route\" | null = null;\n for (const item of viewsSeq.items) {\n if (isMap(item) && getString(item, \"name\") === view.name) {\n existingView = item;\n matchedBy = \"name\";\n break;\n }\n }\n if (!existingView) {\n for (const item of viewsSeq.items) {\n if (isMap(item) && getString(item, \"route\") === view.route) {\n existingView = item;\n matchedBy = \"route\";\n break;\n }\n }\n }\n if (!existingView) {\n existingView = new YAMLMap();\n viewsSeq.add(existingView);\n }\n\n // Plugin-owned: overwrite. Agent-authored fields (memory, intent, requests,\n // unknown keys) are left untouched because we never call .delete() on them.\n // Exception: if matched by route, the existing name was agent-renamed — leave it.\n if (matchedBy !== \"route\") setMapEntry(existingView, \"name\", view.name);\n setMapEntry(existingView, \"route\", view.route);\n\n // Components: reconcile by name\n let componentsSeq = existingView.get(\"components\", true) as YAMLSeq | undefined;\n if (!componentsSeq || !isSeq(componentsSeq)) {\n componentsSeq = new YAMLSeq();\n existingView.set(\"components\", componentsSeq);\n }\n reconcileComponents(componentsSeq, components);\n}\n\nfunction reconcileComponents(seq: YAMLSeq, desired: ComponentDesired[]): void {\n for (const desiredComp of desired) {\n let existing: YAMLMap | null = null;\n for (const item of seq.items) {\n if (isMap(item) && getString(item, \"name\") === desiredComp.name) {\n existing = item;\n break;\n }\n }\n if (!existing) {\n existing = new YAMLMap();\n seq.add(existing);\n }\n setMapEntry(existing, \"name\", desiredComp.name);\n setMapEntry(existing, \"selector\", desiredComp.selector);\n if (desiredComp.children && desiredComp.children.length > 0) {\n let childSeq = existing.get(\"children\", true) as YAMLSeq | undefined;\n if (!childSeq || !isSeq(childSeq)) {\n childSeq = new YAMLSeq();\n existing.set(\"children\", childSeq);\n }\n reconcileComponents(childSeq, desiredComp.children);\n }\n // Components not in `desired` are NOT removed here; that's handled in a later\n // task with `react.removed-component-still-in-yaml` diagnostics.\n }\n}\n\nfunction getString(map: YAMLMap, key: string): string | null {\n const v = map.get(key, true);\n if (v instanceof Scalar && typeof v.value === \"string\") return v.value;\n return null;\n}\n\nfunction setMapEntry(map: YAMLMap, key: string, value: unknown): void {\n map.set(key, value);\n}\n\nfunction normalize(s: string): string {\n // Trailing-newline-only normalization; do not mangle inner whitespace.\n return s.replace(/\\s+$/, \"\");\n}\n","// src/plugin/merge/todo-scaffolding.ts\n//\n// Emits commented TODO scaffolding for the agent-authored fields of a freshly\n// generated view file: `memory`, `intent`, `requests`. Output is YAML-comment\n// only — the file still parses cleanly until the agent uncomments and fills\n// in real values.\n//\n// This module is invoked exclusively from `smartMerge` when the target file\n// did not previously exist on disk (`existing == null`). Re-running `gen` on a\n// populated `.sightmap/` does NOT re-emit this scaffolding — preserving\n// idempotency per the codegen spec.\n\nconst SCAFFOLDING = `#\n# Agent-authored fields below — uncomment and fill in.\n#\n# TODO: capture observed runtime behavior the agent should know about\n# (one short sentence per entry; no marketing copy).\n# memory:\n# - \"Form auto-submits on Enter; verify disabled-button logic.\"\n# - \"Submit returns 401 on bad credentials.\"\n#\n# TODO: describe what this view is for in one sentence.\n# intent: \"Authenticate the user before entering the dashboard.\"\n#\n# TODO: list HTTP requests this view fires (method + path).\n# requests:\n# - method: POST\n# path: /api/login\n#\n`;\n\nexport function renderTodoScaffolding(): string {\n return SCAFFOLDING;\n}\n","// src/cli/commands/gen-summary.ts\n//\n// Pure formatter for `sightmap-react gen` console output. Three output shapes:\n//\n// - \"first-run\": every reported change has before === null. Print\n// views written, components linked, alphabetized\n// suggested first-edit targets, and a pointer at\n// /sightmap:audit.\n// - \"up-to-date\": no changes; one-line.\n// - \"structural-update\": at least one file existed AND at least one\n// changed. List only the changed files.\n//\n// Pure: no I/O, no `process.cwd()` lookups, no clock reads. Take cwd as input.\n// All paths in the output are cwd-relative for portable copy/paste.\n\nimport { relative } from \"node:path\";\nimport { parse as yamlParse } from \"yaml\";\n\nexport type FileChange = {\n path: string;\n before: string | null;\n after: string;\n changed: boolean;\n};\n\nexport interface SummaryInput {\n cwd: string;\n changes: FileChange[];\n written: string[];\n}\n\nexport type SummaryKind = \"first-run\" | \"up-to-date\" | \"structural-update\";\n\nexport interface SummaryOutput {\n kind: SummaryKind;\n lines: string[];\n}\n\nconst AUDIT_HINT =\n \"Run /sightmap:audit (Claude Code plugin) to surface missing memory and broken selectors.\";\n\nexport function formatSummary(input: SummaryInput): SummaryOutput {\n const { cwd, changes, written } = input;\n\n const allChanged = changes.filter((c) => c.changed);\n const anyChanged = allChanged.length > 0;\n const everyChangeIsNew = changes.length > 0 && changes.every((c) => c.before === null);\n\n if (!anyChanged) {\n return { kind: \"up-to-date\", lines: [\"sightmap: up to date\"] };\n }\n\n if (everyChangeIsNew) {\n return formatFirstRun(input);\n }\n\n // Structural update: at least one pre-existing file changed.\n const lines: string[] = [];\n lines.push(`sightmap: wrote ${written.length} file(s):`);\n for (const c of allChanged) {\n lines.push(` - ${relative(cwd, c.path)}`);\n }\n return { kind: \"structural-update\", lines };\n}\n\nfunction formatFirstRun(input: SummaryInput): SummaryOutput {\n const { cwd, changes, written } = input;\n const lines: string[] = [];\n\n // Total views and total components, derived by parsing the `after` content.\n // Names list preserves input order (the orchestrator's discovery order, which\n // mirrors the agent's mental model of the app).\n let viewCount = 0;\n let componentCount = 0;\n const viewNames: string[] = [];\n for (const c of changes) {\n try {\n const parsed = yamlParse(c.after) as\n | { views?: Array<{ name?: string; components?: unknown[] }> }\n | null;\n const views = parsed?.views ?? [];\n for (const v of views) {\n viewCount++;\n if (typeof v.name === \"string\") viewNames.push(v.name);\n const comps = Array.isArray(v.components) ? v.components : [];\n componentCount += comps.length;\n }\n } catch {\n // Malformed YAML in `after` is a defect we surface elsewhere; here we just skip counting.\n }\n }\n\n // Suggested-edit list is alphabetized by relative path so curators get a\n // deterministic, copy-pasteable ordering regardless of orchestrator order.\n const sortedForEdit = [...changes].sort((a, b) =>\n relative(cwd, a.path).localeCompare(relative(cwd, b.path)),\n );\n\n lines.push(`sightmap: wrote ${written.length} file(s) (first run on empty .sightmap/)`);\n lines.push(\"\");\n lines.push(`Views (${viewCount} total)`);\n lines.push(` views: ${viewNames.join(\", \")}`);\n lines.push(`Components linked: ${componentCount}`);\n lines.push(\"\");\n lines.push(\"Next steps — open these files and replace the TODO blocks with real values:\");\n // Exclude shared.yaml from the suggested first-edit list — it's not a view file.\n const editTargets = sortedForEdit.filter((c) => !c.path.endsWith(\"shared.yaml\"));\n for (const c of editTargets) {\n lines.push(` - ${relative(cwd, c.path)}`);\n }\n lines.push(\"\");\n lines.push(AUDIT_HINT);\n\n return { kind: \"first-run\", lines };\n}\n","// src/cli/commands/validate.ts\nimport { join } from \"node:path\";\nimport { loadDirectory } from \"@sightmap/sightmap\";\nimport { resolveAdapter, type RouterChoice } from \"../../plugin/adapters/index.js\";\nimport { REACT_ROUTE_NO_VIEW_IN_YAML } from \"../../plugin/diagnostics.js\";\n\nexport async function validateCommand(opts: { cwd: string; router: string; output: string }): Promise<void> {\n const dir = join(opts.cwd, opts.output);\n const sightmap = await loadDirectory(dir);\n\n let exitCode = 0;\n for (const diag of sightmap.diagnostics) {\n if (diag.severity === \"error\") {\n console.error(`[ERROR] ${diag.code}: ${diag.message}${diag.path ? ` (${diag.path})` : \"\"}`);\n exitCode = 1;\n }\n }\n\n // React-specific drift check: every router-discovered route should have a view in the YAML.\n const adapter = await resolveAdapter(opts.router as RouterChoice, opts.cwd);\n if (!adapter) {\n console.error(`[ERROR] react.unknown-router: No supported router detected at ${opts.cwd}. Cannot validate.`);\n process.exit(1);\n }\n const routes = await adapter.discoverRoutes({\n projectRoot: opts.cwd,\n resolveSource: (id) => join(opts.cwd, id),\n });\n const viewRoutes = new Set<string>();\n for (const v of sightmap.views ?? []) viewRoutes.add(v.route);\n for (const r of routes) {\n if (!viewRoutes.has(r.pattern)) {\n console.error(`[WARNING] ${REACT_ROUTE_NO_VIEW_IN_YAML}: route ${r.pattern} exists in router but no view in YAML`);\n }\n }\n\n if (exitCode !== 0) process.exit(exitCode);\n}\n"],"mappings":"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","names":["relative","fs","dirname","join","fs","join","fs","existsSync","dirname","join","resolve","parseAst","join","fs","parseAst","existsSync","walkComponentTree","resolve","resolveLocalImport","dirname","fs","join","fs","fs","join","fs","dirname","relative","relative","join","loadDirectory","join","loadDirectory"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sightmap/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "React framework adapter for the Sightmap spec — SightmapProvider, runtime introspection hook, Vite plugin, and CLI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"typescript": "~5.7.3",
|
|
82
82
|
"vite": "^5.4.0",
|
|
83
83
|
"vitest": "^2.1.9",
|
|
84
|
-
"@sightmap/sightmap": "^0.
|
|
84
|
+
"@sightmap/sightmap": "^0.4.0"
|
|
85
85
|
},
|
|
86
86
|
"scripts": {
|
|
87
87
|
"build": "tsup",
|