@lsctech/polaris 0.1.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.
Files changed (316) hide show
  1. package/README.md +87 -0
  2. package/dist/__mocks__/tool-server-linear.js +34 -0
  3. package/dist/cli/adopt-approve.js +60 -0
  4. package/dist/cli/adopt-cognition.js +199 -0
  5. package/dist/cli/adopt-instructions.js +143 -0
  6. package/dist/cli/adopt-rules.js +169 -0
  7. package/dist/cli/adopt-scan.js +25 -0
  8. package/dist/cli/adopt-smartdocs.js +192 -0
  9. package/dist/cli/adoption-inventory.js +350 -0
  10. package/dist/cli/adoption-plan.js +222 -0
  11. package/dist/cli/args.js +28 -0
  12. package/dist/cli/args.test.js +30 -0
  13. package/dist/cli/branding.js +41 -0
  14. package/dist/cli/graph.js +358 -0
  15. package/dist/cli/index.js +127 -0
  16. package/dist/cli/index.test.js +162 -0
  17. package/dist/cli/init-detect.js +61 -0
  18. package/dist/cli/init.js +492 -0
  19. package/dist/cli/init.test.js +259 -0
  20. package/dist/cli/librarian.js +32 -0
  21. package/dist/cli/medic.js +96 -0
  22. package/dist/cli/startup.test.js +23 -0
  23. package/dist/cli/tracker.js +130 -0
  24. package/dist/cli/tracker.test.js +126 -0
  25. package/dist/cli/version.js +10 -0
  26. package/dist/cli/version.test.js +11 -0
  27. package/dist/cli/worker.js +287 -0
  28. package/dist/cluster-state/fixtures/test-clusters.json +19 -0
  29. package/dist/cluster-state/store.js +302 -0
  30. package/dist/cluster-state/store.test.js +145 -0
  31. package/dist/cluster-state/types.js +2 -0
  32. package/dist/cognition/archive.js +158 -0
  33. package/dist/cognition/closeout-librarian-types.js +161 -0
  34. package/dist/cognition/cognition.test.js +623 -0
  35. package/dist/cognition/index.js +41 -0
  36. package/dist/cognition/librarian-dispatch.js +391 -0
  37. package/dist/cognition/librarian-dispatch.test.js +247 -0
  38. package/dist/cognition/librarian-packet.js +313 -0
  39. package/dist/cognition/librarian-types.js +57 -0
  40. package/dist/cognition/route-cognition-delta.js +350 -0
  41. package/dist/cognition/summary-delta.js +279 -0
  42. package/dist/cognition/validate.js +162 -0
  43. package/dist/config/defaults.js +98 -0
  44. package/dist/config/doctor.js +273 -0
  45. package/dist/config/index.js +14 -0
  46. package/dist/config/loader.js +58 -0
  47. package/dist/config/provider-detect.js +60 -0
  48. package/dist/config/provider-detect.test.js +119 -0
  49. package/dist/config/schema.js +2 -0
  50. package/dist/config/show.js +44 -0
  51. package/dist/config/show.test.js +42 -0
  52. package/dist/config/validator.js +675 -0
  53. package/dist/config/validator.test.js +77 -0
  54. package/dist/docs/canon-check.js +334 -0
  55. package/dist/docs/canon-check.test.js +207 -0
  56. package/dist/docs/doctrine.js +133 -0
  57. package/dist/docs/doctrine.test.js +139 -0
  58. package/dist/docs/index.js +168 -0
  59. package/dist/docs/index.test.js +83 -0
  60. package/dist/docs/ingest.js +295 -0
  61. package/dist/docs/ingest.test.js +71 -0
  62. package/dist/docs/migrate.js +165 -0
  63. package/dist/docs/migrate.test.js +136 -0
  64. package/dist/docs/seed-instructions.js +147 -0
  65. package/dist/docs/seed-instructions.test.js +137 -0
  66. package/dist/docs/validate-instructions.js +267 -0
  67. package/dist/docs/validate-instructions.test.js +238 -0
  68. package/dist/finalize/artifact-policy.js +214 -0
  69. package/dist/finalize/artifact-policy.test.js +84 -0
  70. package/dist/finalize/delivery-integrity.js +141 -0
  71. package/dist/finalize/finalize.test.js +210 -0
  72. package/dist/finalize/github.js +41 -0
  73. package/dist/finalize/index.js +474 -0
  74. package/dist/finalize/linear.js +213 -0
  75. package/dist/finalize/run-report.js +47 -0
  76. package/dist/finalize/steps/01-map-update.js +11 -0
  77. package/dist/finalize/steps/02-map-validate.js +11 -0
  78. package/dist/finalize/steps/03-schema-validate.js +11 -0
  79. package/dist/finalize/steps/04-run-checks.js +118 -0
  80. package/dist/finalize/steps/05-generate-report.js +14 -0
  81. package/dist/finalize/steps/06-commit.js +39 -0
  82. package/dist/finalize/steps/07-push.js +10 -0
  83. package/dist/finalize/steps/08-create-pr.js +9 -0
  84. package/dist/finalize/steps/09-update-state.js +9 -0
  85. package/dist/finalize/steps/10-append-jsonl.js +23 -0
  86. package/dist/finalize/steps/11-update-linear.js +22 -0
  87. package/dist/finalize/steps/12-archive.js +21 -0
  88. package/dist/graph/adapter/c/adapter.js +45 -0
  89. package/dist/graph/adapter/c/extract.js +135 -0
  90. package/dist/graph/adapter/c/index.js +10 -0
  91. package/dist/graph/adapter/c/runtime.js +67 -0
  92. package/dist/graph/adapter/cpp/adapter.js +45 -0
  93. package/dist/graph/adapter/cpp/extract.js +159 -0
  94. package/dist/graph/adapter/cpp/index.js +10 -0
  95. package/dist/graph/adapter/cpp/runtime.js +61 -0
  96. package/dist/graph/adapter/csharp/adapter.js +45 -0
  97. package/dist/graph/adapter/csharp/extract.js +127 -0
  98. package/dist/graph/adapter/csharp/index.js +10 -0
  99. package/dist/graph/adapter/csharp/runtime.js +61 -0
  100. package/dist/graph/adapter/dart/adapter.js +56 -0
  101. package/dist/graph/adapter/dart/extract.js +130 -0
  102. package/dist/graph/adapter/dart/index.js +10 -0
  103. package/dist/graph/adapter/dart/runtime.js +61 -0
  104. package/dist/graph/adapter/go/adapter.js +45 -0
  105. package/dist/graph/adapter/go/extract.js +112 -0
  106. package/dist/graph/adapter/go/index.js +10 -0
  107. package/dist/graph/adapter/go/runtime.js +58 -0
  108. package/dist/graph/adapter/kotlin-java/extract-common.js +83 -0
  109. package/dist/graph/adapter/kotlin-java/index.js +15 -0
  110. package/dist/graph/adapter/kotlin-java/java-adapter.js +45 -0
  111. package/dist/graph/adapter/kotlin-java/java-extract.js +42 -0
  112. package/dist/graph/adapter/kotlin-java/kotlin-adapter.js +48 -0
  113. package/dist/graph/adapter/kotlin-java/kotlin-extract.js +58 -0
  114. package/dist/graph/adapter/kotlin-java/runtime.js +75 -0
  115. package/dist/graph/adapter/python/adapter.js +45 -0
  116. package/dist/graph/adapter/python/extract.js +121 -0
  117. package/dist/graph/adapter/python/index.js +10 -0
  118. package/dist/graph/adapter/python/runtime.js +70 -0
  119. package/dist/graph/adapter/registry.js +82 -0
  120. package/dist/graph/adapter/rust/adapter.js +45 -0
  121. package/dist/graph/adapter/rust/extract.js +110 -0
  122. package/dist/graph/adapter/rust/index.js +10 -0
  123. package/dist/graph/adapter/rust/runtime.js +74 -0
  124. package/dist/graph/adapter/shell/adapter.js +34 -0
  125. package/dist/graph/adapter/shell/extract.js +98 -0
  126. package/dist/graph/adapter/shell/index.js +8 -0
  127. package/dist/graph/adapter/svelte/adapter.js +91 -0
  128. package/dist/graph/adapter/svelte/extract.js +41 -0
  129. package/dist/graph/adapter/svelte/index.js +8 -0
  130. package/dist/graph/adapter/swift/adapter.js +45 -0
  131. package/dist/graph/adapter/swift/extract.js +120 -0
  132. package/dist/graph/adapter/swift/index.js +10 -0
  133. package/dist/graph/adapter/swift/runtime.js +70 -0
  134. package/dist/graph/adapter/types.js +2 -0
  135. package/dist/graph/adapter/typescript-javascript/adapter.js +72 -0
  136. package/dist/graph/adapter/typescript-javascript/extract.js +115 -0
  137. package/dist/graph/adapter/typescript-javascript/index.js +10 -0
  138. package/dist/graph/adapter/typescript-javascript/runtime.js +97 -0
  139. package/dist/graph/capability/index.js +105 -0
  140. package/dist/graph/governance.js +104 -0
  141. package/dist/graph/parser/extract.js +5 -0
  142. package/dist/graph/parser/loader.js +2 -0
  143. package/dist/graph/parser/pipeline.js +194 -0
  144. package/dist/graph/query/index.js +277 -0
  145. package/dist/graph/query/types.js +5 -0
  146. package/dist/graph/resolver/build-edges.js +211 -0
  147. package/dist/graph/resolver/index.js +23 -0
  148. package/dist/graph/resolver/resolve-imports.js +168 -0
  149. package/dist/graph/store/adapter.js +132 -0
  150. package/dist/graph/store/queries.js +124 -0
  151. package/dist/graph/store/types.js +4 -0
  152. package/dist/ignore/defaults.js +41 -0
  153. package/dist/ignore/parser.js +39 -0
  154. package/dist/lint/map-reference-validator.js +72 -0
  155. package/dist/loop/abort.js +188 -0
  156. package/dist/loop/abort.test.js +151 -0
  157. package/dist/loop/adapters/__tests__/terminal-cli.test.js +92 -0
  158. package/dist/loop/adapters/agent-subtask.js +137 -0
  159. package/dist/loop/adapters/agent-subtask.test.js +151 -0
  160. package/dist/loop/adapters/cli-subtask-bridge.js +108 -0
  161. package/dist/loop/adapters/index.js +9 -0
  162. package/dist/loop/adapters/registry.js +17 -0
  163. package/dist/loop/adapters/terminal-cli.js +403 -0
  164. package/dist/loop/adapters/types.js +2 -0
  165. package/dist/loop/adapters/worker-instructions.js +85 -0
  166. package/dist/loop/body-parser.js +226 -0
  167. package/dist/loop/bootstrap-packet.js +97 -0
  168. package/dist/loop/bootstrap-packet.test.js +171 -0
  169. package/dist/loop/branch-governance.js +54 -0
  170. package/dist/loop/budget.js +63 -0
  171. package/dist/loop/budget.test.js +163 -0
  172. package/dist/loop/checkpoint.js +325 -0
  173. package/dist/loop/compact-return.js +59 -0
  174. package/dist/loop/continue.js +645 -0
  175. package/dist/loop/continue.test.js +337 -0
  176. package/dist/loop/dispatch-boundary.js +335 -0
  177. package/dist/loop/dispatch-state.js +223 -0
  178. package/dist/loop/dispatch-state.test.js +186 -0
  179. package/dist/loop/dispatch.js +1236 -0
  180. package/dist/loop/dispatch.test.js +499 -0
  181. package/dist/loop/ephemeral-smoke.test.js +160 -0
  182. package/dist/loop/evidence-backfill.js +216 -0
  183. package/dist/loop/execution-adapter.js +141 -0
  184. package/dist/loop/execution-adapter.test.js +66 -0
  185. package/dist/loop/finalize-evidence.js +169 -0
  186. package/dist/loop/git-custody.js +250 -0
  187. package/dist/loop/impl-packet-input.js +38 -0
  188. package/dist/loop/index.js +270 -0
  189. package/dist/loop/ledger.js +49 -0
  190. package/dist/loop/ledger.test.js +127 -0
  191. package/dist/loop/lifecycle-dispatch.js +348 -0
  192. package/dist/loop/lifecycle-dispatch.test.js +318 -0
  193. package/dist/loop/lifecycle.js +93 -0
  194. package/dist/loop/lifecycle.test.js +150 -0
  195. package/dist/loop/orphan-recovery.js +276 -0
  196. package/dist/loop/orphan-recovery.test.js +236 -0
  197. package/dist/loop/parent.js +1566 -0
  198. package/dist/loop/parent.test.js +738 -0
  199. package/dist/loop/provider-sealed-packet.test.js +164 -0
  200. package/dist/loop/resume.js +295 -0
  201. package/dist/loop/resume.test.js +172 -0
  202. package/dist/loop/run-bootstrap.js +234 -0
  203. package/dist/loop/run-preflight.js +203 -0
  204. package/dist/loop/status.js +665 -0
  205. package/dist/loop/status.test.js +235 -0
  206. package/dist/loop/wait.js +86 -0
  207. package/dist/loop/worker-packet.js +406 -0
  208. package/dist/loop/worker-packet.test.js +243 -0
  209. package/dist/loop/worker-prompt.js +260 -0
  210. package/dist/loop/worker-prompt.test.js +247 -0
  211. package/dist/loop/worker.js +498 -0
  212. package/dist/loop/worker.test.js +372 -0
  213. package/dist/map/atlas.js +77 -0
  214. package/dist/map/backfill.js +171 -0
  215. package/dist/map/backfill.test.js +120 -0
  216. package/dist/map/index.js +255 -0
  217. package/dist/map/inference.js +73 -0
  218. package/dist/map/inference.test.js +35 -0
  219. package/dist/map/query.js +157 -0
  220. package/dist/map/query.test.js +174 -0
  221. package/dist/map/update.js +355 -0
  222. package/dist/map/update.test.js +67 -0
  223. package/dist/map/validate.js +153 -0
  224. package/dist/map/validate.test.js +90 -0
  225. package/dist/map/welfare.js +86 -0
  226. package/dist/mcp/lib/invoke.js +35 -0
  227. package/dist/mcp/lib/redact.js +24 -0
  228. package/dist/mcp/lib/redact.test.js +112 -0
  229. package/dist/mcp/lib/root.js +41 -0
  230. package/dist/mcp/lib/root.test.js +114 -0
  231. package/dist/mcp/server.js +15 -0
  232. package/dist/mcp/tools/claim-child.js +119 -0
  233. package/dist/mcp/tools/claim-child.test.js +69 -0
  234. package/dist/mcp/tools/current-state.js +73 -0
  235. package/dist/mcp/tools/current-state.test.js +114 -0
  236. package/dist/mcp/tools/dispatch-result.js +186 -0
  237. package/dist/mcp/tools/dispatch-result.test.js +109 -0
  238. package/dist/mcp/tools/index.js +222 -0
  239. package/dist/mcp/tools/index.test.js +172 -0
  240. package/dist/mcp/tools/linear.js +74 -0
  241. package/dist/mcp/tools/loop-continue.js +159 -0
  242. package/dist/mcp/tools/loop-continue.test.js +186 -0
  243. package/dist/mcp/tools/loop-dry-run.js +15 -0
  244. package/dist/mcp/tools/status.js +65 -0
  245. package/dist/medic/chart-id.js +75 -0
  246. package/dist/medic/chart-schema.js +139 -0
  247. package/dist/runs/index.js +119 -0
  248. package/dist/runs/index.test.js +184 -0
  249. package/dist/runs/ledger-tail.js +15 -0
  250. package/dist/runs/list.js +29 -0
  251. package/dist/runs/reconcile.js +74 -0
  252. package/dist/runs/show.js +10 -0
  253. package/dist/runtime/audit/logger.js +15 -0
  254. package/dist/runtime/audit/reader.js +42 -0
  255. package/dist/runtime/checkpoint.js +89 -0
  256. package/dist/runtime/continuation/confirmed.js +225 -0
  257. package/dist/runtime/continuation/confirmed.test.js +421 -0
  258. package/dist/runtime/continuation/dry-run.js +74 -0
  259. package/dist/runtime/execution-window.js +106 -0
  260. package/dist/runtime/scheduling/child-selector.js +16 -0
  261. package/dist/runtime/state.js +43 -0
  262. package/dist/runtime/status.js +46 -0
  263. package/dist/runtime/verification/envelope.js +80 -0
  264. package/dist/runtime/verification/fingerprint.js +26 -0
  265. package/dist/skill-packet/cli.test.js +105 -0
  266. package/dist/skill-packet/generator.js +225 -0
  267. package/dist/skill-packet/generator.test.js +159 -0
  268. package/dist/skill-packet/index.js +49 -0
  269. package/dist/skill-packet/types.js +2 -0
  270. package/dist/smartdocs-engine/audit.js +194 -0
  271. package/dist/smartdocs-engine/audit.test.js +122 -0
  272. package/dist/smartdocs-engine/canon-check.js +340 -0
  273. package/dist/smartdocs-engine/canon-check.test.js +234 -0
  274. package/dist/smartdocs-engine/doctrine.js +633 -0
  275. package/dist/smartdocs-engine/doctrine.test.js +374 -0
  276. package/dist/smartdocs-engine/index.js +456 -0
  277. package/dist/smartdocs-engine/index.test.js +82 -0
  278. package/dist/smartdocs-engine/ingest.js +495 -0
  279. package/dist/smartdocs-engine/ingest.test.js +163 -0
  280. package/dist/smartdocs-engine/migrate.js +217 -0
  281. package/dist/smartdocs-engine/migrate.test.js +200 -0
  282. package/dist/smartdocs-engine/seed-instructions.js +335 -0
  283. package/dist/smartdocs-engine/seed-instructions.test.js +275 -0
  284. package/dist/smartdocs-engine/smartdoc-ignore.js +258 -0
  285. package/dist/smartdocs-engine/smartdoc-ignore.test.js +146 -0
  286. package/dist/smartdocs-engine/validate-instructions.js +366 -0
  287. package/dist/smartdocs-engine/validate-instructions.test.js +283 -0
  288. package/dist/tracker/adapters/github/index.js +305 -0
  289. package/dist/tracker/adapters/jira/index.js +293 -0
  290. package/dist/tracker/adapters/linear/http-errors.test.js +51 -0
  291. package/dist/tracker/adapters/linear/index.js +621 -0
  292. package/dist/tracker/adapters/linear/index.test.js +238 -0
  293. package/dist/tracker/adapters/linear.js +50 -0
  294. package/dist/tracker/adapters/local/index.js +10 -0
  295. package/dist/tracker/adapters/local-file/index.js +159 -0
  296. package/dist/tracker/adapters/mcp-bridge.js +158 -0
  297. package/dist/tracker/adapters/mcp-bridge.test.js +12 -0
  298. package/dist/tracker/adapters/spec/index.js +146 -0
  299. package/dist/tracker/capabilities.js +2 -0
  300. package/dist/tracker/index.js +49 -0
  301. package/dist/tracker/lifecycle-policy.js +139 -0
  302. package/dist/tracker/lifecycle-transition.js +164 -0
  303. package/dist/tracker/local-graph.js +98 -0
  304. package/dist/tracker/migration.js +56 -0
  305. package/dist/tracker/schema.js +86 -0
  306. package/dist/tracker/sync/index.js +404 -0
  307. package/dist/tracker/sync/queue-store.js +95 -0
  308. package/dist/tracker/sync/queue-store.test.js +104 -0
  309. package/dist/tracker/types.js +11 -0
  310. package/dist/types/linear.js +3 -0
  311. package/dist/types/result-packet.js +12 -0
  312. package/dist/types/runtime-state.js +2 -0
  313. package/dist/types/work-contract.js +2 -0
  314. package/dist/utils/monotonic-timestamp.js +13 -0
  315. package/dist/utils/monotonic-timestamp.test.js +19 -0
  316. package/package.json +64 -0
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const backfill_js_1 = require("./backfill.js");
7
+ const TMP = (0, node_path_1.join)(process.cwd(), ".test-backfill-tmp");
8
+ const EXISTING_ROUTES = {
9
+ "src/cli/index.ts": {
10
+ domain: "cli",
11
+ route: "src/cli",
12
+ taskchain: "polaris-cli",
13
+ confidence: 0.95,
14
+ classification: "indexed",
15
+ last_updated: "2026-05-22T20:00:00Z",
16
+ updated_by: "polaris-map-index",
17
+ tags: ["cli", "entry-point"],
18
+ },
19
+ };
20
+ const POLARIS_CONFIG = {
21
+ repo: { sourceRoots: ["src"], docsRoots: [], sidecarOutputPath: ".polaris/map" },
22
+ map: { autoWriteAbove: 0.85, confidenceThreshold: 0.75 },
23
+ };
24
+ function setup() {
25
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(TMP, ".polaris/map"), { recursive: true });
26
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(TMP, "src/cli"), { recursive: true });
27
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(TMP, "src/map"), { recursive: true });
28
+ // Pre-existing file already in atlas
29
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, "src/cli/index.ts"), "");
30
+ // New unmapped file — should be backfilled
31
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, "src/cli/version.ts"), "");
32
+ // New file in a different domain
33
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, "src/map/backfill.ts"), "");
34
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, ".polaris/map/file-routes.json"), JSON.stringify(EXISTING_ROUTES));
35
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, ".polaris/map/needs-review.json"), JSON.stringify({}));
36
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, ".polaris/map/exemptions.json"), JSON.stringify({}));
37
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, ".polaris/map/index.json"), JSON.stringify({ scan_date: "", file_count: 0, coverage_pct: 0, entries: {} }));
38
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, "polaris.config.json"), JSON.stringify(POLARIS_CONFIG));
39
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, ".polarisignore"), "*.log\n");
40
+ }
41
+ function teardown() {
42
+ (0, node_fs_1.rmSync)(TMP, { recursive: true, force: true });
43
+ }
44
+ function captureOutput(fn) {
45
+ const stdoutLines = [];
46
+ const stderrLines = [];
47
+ const origLog = console.log.bind(console);
48
+ const origError = console.error.bind(console);
49
+ const origStdout = process.stdout.write.bind(process.stdout);
50
+ const origStderr = process.stderr.write.bind(process.stderr);
51
+ console.log = (...args) => { stdoutLines.push(args.map(String).join(" ")); };
52
+ console.error = (...args) => { stderrLines.push(args.map(String).join(" ")); };
53
+ process.stdout.write = (chunk) => { stdoutLines.push(String(chunk)); return true; };
54
+ process.stderr.write = (chunk) => { stderrLines.push(String(chunk)); return true; };
55
+ try {
56
+ fn();
57
+ }
58
+ finally {
59
+ console.log = origLog;
60
+ console.error = origError;
61
+ process.stdout.write = origStdout;
62
+ process.stderr.write = origStderr;
63
+ }
64
+ return { stdout: stdoutLines.join(""), stderr: stderrLines.join("") };
65
+ }
66
+ (0, vitest_1.describe)("runMapBackfill", () => {
67
+ (0, vitest_1.beforeEach)(setup);
68
+ (0, vitest_1.afterEach)(teardown);
69
+ (0, vitest_1.it)("adds unmapped files to file-routes.json without touching existing entries", () => {
70
+ captureOutput(() => (0, backfill_js_1.runMapBackfill)(TMP, false, undefined, false));
71
+ const routes = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(TMP, ".polaris/map/file-routes.json"), "utf-8"));
72
+ // Existing entry preserved
73
+ (0, vitest_1.expect)(routes["src/cli/index.ts"].confidence).toBe(0.95);
74
+ (0, vitest_1.expect)(routes["src/cli/index.ts"].updated_by).toBe("polaris-map-index");
75
+ // New entry added
76
+ (0, vitest_1.expect)(routes["src/cli/version.ts"] || routes["src/map/backfill.ts"]).toBeTruthy();
77
+ });
78
+ (0, vitest_1.it)("reports correct summary counts", () => {
79
+ const { stdout } = captureOutput(() => (0, backfill_js_1.runMapBackfill)(TMP, false, undefined, false));
80
+ (0, vitest_1.expect)(stdout).toMatch(/Backfilled \d+ files\. Added \d+\. Queued \d+ for review\. Skipped \d+/);
81
+ // src/cli/index.ts should be counted as skipped
82
+ (0, vitest_1.expect)(stdout).toContain("Skipped 1");
83
+ });
84
+ (0, vitest_1.it)("does not write files when --dry-run is set", () => {
85
+ const beforeRoutes = (0, node_fs_1.readFileSync)((0, node_path_1.join)(TMP, ".polaris/map/file-routes.json"), "utf-8");
86
+ const { stdout } = captureOutput(() => (0, backfill_js_1.runMapBackfill)(TMP, true, undefined, false));
87
+ const afterRoutes = (0, node_fs_1.readFileSync)((0, node_path_1.join)(TMP, ".polaris/map/file-routes.json"), "utf-8");
88
+ (0, vitest_1.expect)(afterRoutes).toBe(beforeRoutes);
89
+ (0, vitest_1.expect)(stdout).toContain("dry-run");
90
+ });
91
+ (0, vitest_1.it)("limits backfill to --domain when specified", () => {
92
+ captureOutput(() => (0, backfill_js_1.runMapBackfill)(TMP, false, "cli", false));
93
+ const routes = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(TMP, ".polaris/map/file-routes.json"), "utf-8"));
94
+ // cli domain file added
95
+ (0, vitest_1.expect)(routes["src/cli/version.ts"]).toBeTruthy();
96
+ // map domain file NOT added (filtered out)
97
+ (0, vitest_1.expect)(routes["src/map/backfill.ts"]).toBeUndefined();
98
+ });
99
+ (0, vitest_1.it)("never overwrites an existing entry in a second run", () => {
100
+ captureOutput(() => (0, backfill_js_1.runMapBackfill)(TMP, false, undefined, false));
101
+ const routesAfterFirst = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(TMP, ".polaris/map/file-routes.json"), "utf-8"));
102
+ const versionEntry = routesAfterFirst["src/cli/version.ts"];
103
+ captureOutput(() => (0, backfill_js_1.runMapBackfill)(TMP, false, undefined, false));
104
+ const routesAfterSecond = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(TMP, ".polaris/map/file-routes.json"), "utf-8"));
105
+ (0, vitest_1.expect)(routesAfterSecond["src/cli/version.ts"]).toEqual(versionEntry);
106
+ });
107
+ (0, vitest_1.it)("errors if atlas is not initialized", () => {
108
+ (0, node_fs_1.rmSync)((0, node_path_1.join)(TMP, ".polaris/map/file-routes.json"));
109
+ let exited = false;
110
+ const origExit = process.exit.bind(process);
111
+ process.exit = (() => { exited = true; });
112
+ try {
113
+ captureOutput(() => (0, backfill_js_1.runMapBackfill)(TMP, false, undefined, false));
114
+ }
115
+ finally {
116
+ process.exit = origExit;
117
+ }
118
+ (0, vitest_1.expect)(exited).toBe(true);
119
+ });
120
+ });
@@ -0,0 +1,255 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runMapIndex = runMapIndex;
4
+ exports.createMapCommand = createMapCommand;
5
+ const node_fs_1 = require("node:fs");
6
+ const node_path_1 = require("node:path");
7
+ const node_child_process_1 = require("node:child_process");
8
+ const commander_1 = require("commander");
9
+ const loader_js_1 = require("../config/loader.js");
10
+ const update_js_1 = require("./update.js");
11
+ const validate_js_1 = require("./validate.js");
12
+ const query_js_1 = require("./query.js");
13
+ const backfill_js_1 = require("./backfill.js");
14
+ const welfare_js_1 = require("./welfare.js");
15
+ const parser_js_1 = require("../ignore/parser.js");
16
+ const defaults_js_1 = require("../ignore/defaults.js");
17
+ const inference_js_1 = require("./inference.js");
18
+ const atlas_js_1 = require("./atlas.js");
19
+ const SECRET_REGEXES = defaults_js_1.SECRET_PATTERNS.map((p) => new RegExp("^" + p.replace(/\./g, "\\.").replace(/\*/g, ".*") + "$"));
20
+ function isSecretFile(filePath) {
21
+ const parts = filePath.split("/");
22
+ const base = parts[parts.length - 1];
23
+ return SECRET_REGEXES.some((re) => re.test(base) || re.test(filePath));
24
+ }
25
+ function* walkDir(dir, root, ig) {
26
+ for (const entry of (0, node_fs_1.readdirSync)(dir, { withFileTypes: true })) {
27
+ const full = (0, node_path_1.join)(dir, entry.name);
28
+ const rel = (0, node_path_1.relative)(root, full).replace(/\\/g, "/");
29
+ if (entry.isDirectory()) {
30
+ if (ig?.ignores(rel + "/"))
31
+ continue;
32
+ yield* walkDir(full, root, ig);
33
+ }
34
+ else {
35
+ yield rel;
36
+ }
37
+ }
38
+ }
39
+ function getBranchName(repoRoot) {
40
+ try {
41
+ return (0, node_child_process_1.execFileSync)("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
42
+ cwd: repoRoot,
43
+ stdio: ["pipe", "pipe", "pipe"],
44
+ })
45
+ .toString()
46
+ .trim();
47
+ }
48
+ catch {
49
+ return "";
50
+ }
51
+ }
52
+ function loadIgnoreFilter(repoRoot) {
53
+ let userPatterns = [];
54
+ try {
55
+ const raw = (0, node_fs_1.readFileSync)((0, node_path_1.resolve)(repoRoot, ".polarisignore"), "utf-8");
56
+ userPatterns = raw.split(/\r?\n/).filter((line) => line.trim() !== "" && !line.startsWith("#"));
57
+ }
58
+ catch (err) {
59
+ if (typeof err === "object" && err !== null && "code" in err && err.code !== "ENOENT") {
60
+ throw err;
61
+ }
62
+ }
63
+ return (0, parser_js_1.parsePolarisIgnore)(userPatterns);
64
+ }
65
+ function runMapIndex(repoRoot, dryRun, verbose, _options = {}) {
66
+ if (!(0, node_fs_1.existsSync)(repoRoot)) {
67
+ console.error(`Repo root not found: ${repoRoot}`);
68
+ process.exit(1);
69
+ }
70
+ const config = (0, loader_js_1.loadConfig)(repoRoot);
71
+ const outputPath = (0, node_path_1.resolve)(repoRoot, config.repo.sidecarOutputPath ?? ".polaris/map");
72
+ const branchName = getBranchName(repoRoot);
73
+ const ig = loadIgnoreFilter(repoRoot);
74
+ const existingRoutes = (0, atlas_js_1.readFileRoutes)(outputPath);
75
+ const existingExemptions = (0, atlas_js_1.readExemptions)(outputPath);
76
+ const newRoutes = {};
77
+ const newNeedsReview = {};
78
+ const newExemptions = { ...existingExemptions };
79
+ let scanned = 0;
80
+ let mapped = 0;
81
+ let trackedNotIndexed = 0;
82
+ let needsReview = 0;
83
+ let ignored = 0;
84
+ const now = new Date().toISOString();
85
+ for (const filePath of walkDir(repoRoot, repoRoot, ig)) {
86
+ scanned++;
87
+ // Security check — never process secret files
88
+ if (isSecretFile(filePath)) {
89
+ console.error(`[HIGH] Secret file pattern matched, skipping: ${filePath}`);
90
+ ignored++;
91
+ continue;
92
+ }
93
+ // 1. .polarisignore
94
+ if (ig.ignores(filePath)) {
95
+ ignored++;
96
+ if (verbose)
97
+ console.log(` ignored: ${filePath}`);
98
+ continue;
99
+ }
100
+ // 2. exemptions.json
101
+ if (existingExemptions[filePath]) {
102
+ trackedNotIndexed++;
103
+ if (verbose)
104
+ console.log(` tracked-not-indexed (exemption): ${filePath}`);
105
+ continue;
106
+ }
107
+ // 3. generatedRoots
108
+ const isGenerated = (config.repo.generatedRoots ?? []).some((root) => {
109
+ const prefix = root.endsWith("/") ? root : `${root}/`;
110
+ return filePath.startsWith(prefix);
111
+ });
112
+ if (isGenerated) {
113
+ newExemptions[filePath] = { classification: "tracked-not-indexed", reason: "generatedRoots" };
114
+ trackedNotIndexed++;
115
+ if (verbose)
116
+ console.log(` tracked-not-indexed (generated): ${filePath}`);
117
+ continue;
118
+ }
119
+ // 4. Route inference
120
+ const inferred = (0, inference_js_1.inferRoute)(filePath, repoRoot, config, existingRoutes, branchName);
121
+ const entry = {
122
+ domain: inferred.domain,
123
+ route: inferred.route,
124
+ taskchain: inferred.taskchain,
125
+ confidence: inferred.confidence,
126
+ classification: inferred.confidence >= (config.map.autoWriteAbove ?? 0.85) ? "indexed" : "needs-review",
127
+ last_updated: now,
128
+ updated_by: "polaris-map-index",
129
+ tags: inferred.tags,
130
+ instructionFile: (0, atlas_js_1.resolveInstructionFile)(filePath, repoRoot),
131
+ };
132
+ if (inferred.confidence >= (config.map.autoWriteAbove ?? 0.85)) {
133
+ newRoutes[filePath] = entry;
134
+ mapped++;
135
+ if (verbose)
136
+ console.log(` indexed (${inferred.confidence.toFixed(2)}): ${filePath}`);
137
+ }
138
+ else {
139
+ newNeedsReview[filePath] = entry;
140
+ needsReview++;
141
+ if (verbose)
142
+ console.log(` needs-review (${inferred.confidence.toFixed(2)}): ${filePath}`);
143
+ }
144
+ }
145
+ const coveragePct = scanned > 0 ? Math.round((mapped / scanned) * 100) : 0;
146
+ if (!dryRun) {
147
+ (0, atlas_js_1.writeFileRoutes)(outputPath, newRoutes);
148
+ (0, atlas_js_1.writeNeedsReview)(outputPath, newNeedsReview);
149
+ (0, atlas_js_1.writeExemptions)(outputPath, newExemptions);
150
+ const allEntries = { ...newRoutes, ...newNeedsReview };
151
+ (0, atlas_js_1.writeAtlasIndex)(outputPath, {
152
+ scan_date: now,
153
+ file_count: scanned,
154
+ coverage_pct: coveragePct,
155
+ instructionCoverage: (0, atlas_js_1.computeInstructionCoverage)(allEntries),
156
+ entries: allEntries,
157
+ });
158
+ }
159
+ console.log(`Scanned ${scanned} files. Mapped ${mapped}. Tracked-not-indexed ${trackedNotIndexed}. Needs-review ${needsReview}. Ignored ${ignored}.`);
160
+ if (dryRun)
161
+ console.log("(dry-run: no files written)");
162
+ }
163
+ function failMissingSubcommand(command, commandName) {
164
+ const unknownSubcommand = command.args[0];
165
+ const message = unknownSubcommand
166
+ ? `error: unknown command '${unknownSubcommand}' for '${commandName}'. Run '${commandName} --help'.`
167
+ : `error: missing command for '${commandName}'. Run '${commandName} --help'.`;
168
+ command.error(message, {
169
+ code: "commander.missingCommand",
170
+ exitCode: 1,
171
+ });
172
+ }
173
+ function createMapCommand(handlers = {}) {
174
+ const indexHandler = handlers.runMapIndex ?? runMapIndex;
175
+ const updateHandler = handlers.runMapUpdate ?? update_js_1.runMapUpdate;
176
+ const validateHandler = handlers.runMapValidate ?? validate_js_1.runMapValidate;
177
+ const backfillHandler = handlers.runMapBackfill ?? backfill_js_1.runMapBackfill;
178
+ const queryHandler = handlers.runMapQuery ?? query_js_1.runMapQuery;
179
+ const repoRootDefault = handlers.repoRoot ?? process.cwd();
180
+ const map = new commander_1.Command("map")
181
+ .description("Polaris atlas map commands: --dry-run is a non-mutating preview")
182
+ .showHelpAfterError()
183
+ .showSuggestionAfterError();
184
+ map.action(() => failMissingSubcommand(map, "polaris map"));
185
+ map
186
+ .command("index")
187
+ .description("mutating: full first-pass atlas generation")
188
+ .option("-r, --repo-root <path>", "Repository root", repoRootDefault)
189
+ .option("--dry-run", "non-mutating preview: print results without writing files")
190
+ .option("-v, --verbose", "Show per-file classification")
191
+ .action((options) => {
192
+ indexHandler(options.repoRoot, options.dryRun ?? false, options.verbose ?? false);
193
+ });
194
+ map
195
+ .command("update")
196
+ .description("mutating: incremental changed-file mapping")
197
+ .option("-r, --repo-root <path>", "Repository root", repoRootDefault)
198
+ .option("--changed [files...]", "Changed files (omit to detect from git diff)")
199
+ .option("--from-commit <sha>", "Start commit for diff (default: HEAD~1)")
200
+ .option("--to-commit <sha>", "End commit for diff (default: HEAD)")
201
+ .option("--seed-cognition", "Create draft POLARIS.md and SUMMARY.md for newly eligible folders (default: report only)")
202
+ .option("--include-root", "Include root folder in cognition surface detection/seeding (skipped by default)")
203
+ .action((options) => {
204
+ const files = Array.isArray(options.changed) ? options.changed : [];
205
+ const { hasNeedsReview } = updateHandler(options.repoRoot, files, options.fromCommit, options.toCommit, options.seedCognition, options.includeRoot);
206
+ const onLowConfidence = (0, loader_js_1.loadConfig)(options.repoRoot).map.onLowConfidence ?? "warn";
207
+ if (hasNeedsReview && onLowConfidence === "fail")
208
+ process.exit(1);
209
+ });
210
+ map
211
+ .command("validate")
212
+ .description("safe/read-only by default: atlas integrity check and needs-review reporting")
213
+ .option("-r, --repo-root <path>", "Repository root", repoRootDefault)
214
+ .option("--stale-threshold <days>", "Days before an entry is considered stale", "30")
215
+ .option("--fix <path>", "Show and optionally fix entry for a specific file")
216
+ .action((options) => {
217
+ const { hasError } = validateHandler(options.repoRoot, parseInt(options.staleThreshold, 10), options.fix);
218
+ if (hasError)
219
+ process.exit(1);
220
+ });
221
+ map
222
+ .command("backfill")
223
+ .description("mutating unless --dry-run: incremental gap-fill for an already-indexed repo")
224
+ .option("-r, --repo-root <path>", "Repository root", repoRootDefault)
225
+ .option("--dry-run", "non-mutating preview: print results without writing files")
226
+ .option("--domain <domain>", "Limit backfill to a specific domain")
227
+ .option("-v, --verbose", "Show per-file classification")
228
+ .action((options) => {
229
+ backfillHandler(options.repoRoot, options.dryRun ?? false, options.domain, options.verbose ?? false);
230
+ });
231
+ map
232
+ .command("query [path]")
233
+ .description("safe/read-only: sidecar metadata lookup by path, glob, or filter")
234
+ .option("-r, --repo-root <path>", "Repository root", repoRootDefault)
235
+ .option("--domain <domain>", "All files in a domain")
236
+ .option("--taskchain <taskchain>", "All files in a taskchain")
237
+ .option("--text", "Human-readable output instead of JSON")
238
+ .option("--include-instructions", "Include POLARIS.md instruction file path and content in output")
239
+ .action((pathArg, options) => {
240
+ queryHandler(options.repoRoot, pathArg, options.domain, options.taskchain, options.text ?? false, options.includeInstructions ?? false);
241
+ });
242
+ map
243
+ .command("welfare-check")
244
+ .description("safe/read-only: run route welfare checks and report per-route health")
245
+ .option("-r, --repo-root <path>", "Repository root", repoRootDefault)
246
+ .option("--route <path>", "Scope to a single route domain")
247
+ .action((options) => {
248
+ const report = (0, welfare_js_1.runWelfareCheck)(options.repoRoot, options.route);
249
+ (0, welfare_js_1.printWelfareCheckReport)(report);
250
+ if (report.needsReview > 0) {
251
+ process.exit(1);
252
+ }
253
+ });
254
+ return map;
255
+ }
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.inferRoute = inferRoute;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ function inferRoute(filePath, repoRoot, config, knownRoutes, branchName) {
7
+ let confidence = 0;
8
+ let domain = "";
9
+ let route = "";
10
+ let taskchain = "";
11
+ const tags = [];
12
+ // Signal 1: file path prefix matching sourceRoots
13
+ for (const sourceRoot of (config.repo.sourceRoots ?? [])) {
14
+ const prefix = sourceRoot.endsWith("/") ? sourceRoot : `${sourceRoot}/`;
15
+ if (filePath.startsWith(prefix)) {
16
+ const rest = filePath.slice(prefix.length);
17
+ const subdir = rest.split("/")[0];
18
+ if (subdir && rest.includes("/")) {
19
+ domain = subdir;
20
+ route = `${sourceRoot}/${subdir}`;
21
+ taskchain = `polaris-${subdir}`;
22
+ confidence += 0.85;
23
+ tags.push(subdir);
24
+ }
25
+ break;
26
+ }
27
+ }
28
+ // Signal 2: nearby mapped files in same directory (corroborating)
29
+ if (domain) {
30
+ const dir = (0, node_path_1.dirname)(filePath);
31
+ const nearbyAgreement = Object.entries(knownRoutes).some(([p, e]) => (0, node_path_1.dirname)(p) === dir && e.domain === domain);
32
+ if (nearbyAgreement) {
33
+ confidence = Math.min(confidence + 0.05, 0.99);
34
+ }
35
+ }
36
+ // Signal 3: branch name contains domain slug (corroborating)
37
+ if (domain && branchName) {
38
+ const slugParts = branchName.toLowerCase().split(/[-/]/);
39
+ if (slugParts.includes(domain.toLowerCase())) {
40
+ confidence = Math.min(confidence + 0.05, 0.99);
41
+ }
42
+ }
43
+ // Signal 4: file imports from paths in the same domain (corroborating)
44
+ if (domain) {
45
+ try {
46
+ const fullPath = (0, node_path_1.resolve)(repoRoot, filePath);
47
+ if ((0, node_fs_1.existsSync)(fullPath)) {
48
+ const content = (0, node_fs_1.readFileSync)(fullPath, "utf-8");
49
+ const escapedDomain = domain.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
50
+ const sameDomainImport = new RegExp(`from\\s+['"](?:\\.\\.?/)*${escapedDomain}/`);
51
+ if (sameDomainImport.test(content)) {
52
+ confidence = Math.min(confidence + 0.05, 0.99);
53
+ }
54
+ }
55
+ }
56
+ catch {
57
+ // ignore read errors
58
+ }
59
+ }
60
+ // Tags: entry-point and test detection
61
+ const file = (0, node_path_1.basename)(filePath);
62
+ if (file === "index.ts" || file === "index.js")
63
+ tags.push("entry-point");
64
+ if (file.includes(".test.") || file.includes(".spec."))
65
+ tags.push("test");
66
+ return {
67
+ domain: domain || "unknown",
68
+ route: route || filePath,
69
+ taskchain: taskchain || "polaris-core",
70
+ confidence,
71
+ tags,
72
+ };
73
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const inference_js_1 = require("./inference.js");
5
+ const defaults_js_1 = require("../config/defaults.js");
6
+ const config = defaults_js_1.DEFAULT_CONFIG;
7
+ (0, vitest_1.describe)("inferRoute", () => {
8
+ (0, vitest_1.it)("classifies a file under a sourceRoot subdirectory", () => {
9
+ const result = (0, inference_js_1.inferRoute)("src/cli/index.ts", "/repo", config, {}, "");
10
+ (0, vitest_1.expect)(result.domain).toBe("cli");
11
+ (0, vitest_1.expect)(result.route).toBe("src/cli");
12
+ (0, vitest_1.expect)(result.taskchain).toBe("polaris-cli");
13
+ (0, vitest_1.expect)(result.confidence).toBeGreaterThanOrEqual(0.85);
14
+ (0, vitest_1.expect)(result.tags).toContain("cli");
15
+ (0, vitest_1.expect)(result.tags).toContain("entry-point");
16
+ });
17
+ (0, vitest_1.it)("classifies a map domain file", () => {
18
+ const result = (0, inference_js_1.inferRoute)("src/map/atlas.ts", "/repo", config, {}, "");
19
+ (0, vitest_1.expect)(result.domain).toBe("map");
20
+ (0, vitest_1.expect)(result.confidence).toBeGreaterThanOrEqual(0.85);
21
+ });
22
+ (0, vitest_1.it)("returns low confidence for files outside sourceRoots", () => {
23
+ const result = (0, inference_js_1.inferRoute)("package.json", "/repo", config, {}, "");
24
+ (0, vitest_1.expect)(result.confidence).toBeLessThan(0.85);
25
+ });
26
+ (0, vitest_1.it)("tags test files", () => {
27
+ const result = (0, inference_js_1.inferRoute)("src/cli/version.test.ts", "/repo", config, {}, "");
28
+ (0, vitest_1.expect)(result.tags).toContain("test");
29
+ });
30
+ (0, vitest_1.it)("boosts confidence from branch name", () => {
31
+ const base = (0, inference_js_1.inferRoute)("src/map/index.ts", "/repo", config, {}, "");
32
+ const withBranch = (0, inference_js_1.inferRoute)("src/map/index.ts", "/repo", config, {}, "philmeaux/pol-4-cluster-3-polaris-map");
33
+ (0, vitest_1.expect)(withBranch.confidence).toBeGreaterThanOrEqual(base.confidence);
34
+ });
35
+ });
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runMapQuery = runMapQuery;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const loader_js_1 = require("../config/loader.js");
7
+ const parser_js_1 = require("../ignore/parser.js");
8
+ const atlas_js_1 = require("./atlas.js");
9
+ function globToRegex(pattern) {
10
+ let regStr = "";
11
+ let i = 0;
12
+ while (i < pattern.length) {
13
+ const c = pattern[i];
14
+ if (c === "*" && pattern[i + 1] === "*") {
15
+ regStr += ".*";
16
+ i += 2;
17
+ if (pattern[i] === "/")
18
+ i++;
19
+ }
20
+ else if (c === "*") {
21
+ regStr += "[^/]*";
22
+ i++;
23
+ }
24
+ else if (c === "?") {
25
+ regStr += "[^/]";
26
+ i++;
27
+ }
28
+ else if (".+^${}[]|()\\".includes(c)) {
29
+ regStr += "\\" + c;
30
+ i++;
31
+ }
32
+ else {
33
+ regStr += c;
34
+ i++;
35
+ }
36
+ }
37
+ return new RegExp("^" + regStr + "$");
38
+ }
39
+ function loadIgnoreFilter(repoRoot) {
40
+ let userPatterns = [];
41
+ try {
42
+ const raw = (0, node_fs_1.readFileSync)((0, node_path_1.resolve)(repoRoot, ".polarisignore"), "utf-8");
43
+ userPatterns = raw.split(/\r?\n/).filter((line) => line.trim() !== "" && !line.startsWith("#"));
44
+ }
45
+ catch (err) {
46
+ if (typeof err === "object" && err !== null && "code" in err && err.code !== "ENOENT") {
47
+ throw err;
48
+ }
49
+ }
50
+ return (0, parser_js_1.parsePolarisIgnore)(userPatterns);
51
+ }
52
+ function toQueryEntry(entry, repoRoot, includeInstructions) {
53
+ const base = {
54
+ domain: entry.domain,
55
+ route: entry.route,
56
+ taskchain: entry.taskchain,
57
+ confidence: entry.confidence,
58
+ classification: entry.classification === "needs-review" ? "needs-review" : "indexed",
59
+ last_updated: entry.last_updated,
60
+ tags: entry.tags,
61
+ };
62
+ if (entry.instructionFile !== undefined) {
63
+ base.instructionFile = entry.instructionFile;
64
+ if (includeInstructions && repoRoot !== undefined) {
65
+ try {
66
+ base.instructionContent = (0, node_fs_1.readFileSync)((0, node_path_1.resolve)(repoRoot, entry.instructionFile), "utf-8");
67
+ }
68
+ catch {
69
+ // file missing — omit content silently
70
+ }
71
+ }
72
+ }
73
+ return base;
74
+ }
75
+ function resolveEntry(filePath, routes, needsReview, exemptions, ig, repoRoot, includeInstructions) {
76
+ if (routes[filePath])
77
+ return toQueryEntry(routes[filePath], repoRoot, includeInstructions);
78
+ if (needsReview[filePath])
79
+ return toQueryEntry(needsReview[filePath], repoRoot, includeInstructions);
80
+ if (exemptions[filePath])
81
+ return { classification: exemptions[filePath].classification };
82
+ if (ig.ignores(filePath))
83
+ return { classification: "ignored" };
84
+ return { classification: "unmapped" };
85
+ }
86
+ function printText(result) {
87
+ for (const [filePath, entry] of Object.entries(result)) {
88
+ const parts = [filePath, entry.classification];
89
+ if ("domain" in entry) {
90
+ parts.push(`domain:${entry.domain}`, `route:${entry.route}`, `taskchain:${entry.taskchain}`, `conf:${entry.confidence.toFixed(2)}`);
91
+ if (entry.instructionFile !== undefined)
92
+ parts.push(`instructions:${entry.instructionFile}`);
93
+ }
94
+ console.log(parts.join(" "));
95
+ }
96
+ }
97
+ function runMapQuery(repoRoot, pathArg, domain, taskchain, textMode, includeInstructions = false) {
98
+ const config = (0, loader_js_1.loadConfig)(repoRoot);
99
+ const outputPath = (0, node_path_1.resolve)(repoRoot, config.repo.sidecarOutputPath ?? ".polaris/map");
100
+ if (!(0, node_fs_1.existsSync)((0, node_path_1.resolve)(outputPath, "file-routes.json"))) {
101
+ console.error("atlas not initialized — run `polaris map index` first");
102
+ process.exit(1);
103
+ }
104
+ const routes = (0, atlas_js_1.readFileRoutes)(outputPath);
105
+ const needsReview = (0, atlas_js_1.readNeedsReview)(outputPath);
106
+ const exemptions = (0, atlas_js_1.readExemptions)(outputPath);
107
+ const ig = loadIgnoreFilter(repoRoot);
108
+ const result = {};
109
+ if (domain !== undefined) {
110
+ for (const [filePath, entry] of [...Object.entries(routes), ...Object.entries(needsReview)]) {
111
+ if (entry.domain === domain)
112
+ result[filePath] = toQueryEntry(entry, repoRoot, includeInstructions);
113
+ }
114
+ }
115
+ else if (taskchain !== undefined) {
116
+ for (const [filePath, entry] of [...Object.entries(routes), ...Object.entries(needsReview)]) {
117
+ if (entry.taskchain === taskchain)
118
+ result[filePath] = toQueryEntry(entry, repoRoot, includeInstructions);
119
+ }
120
+ }
121
+ else if (pathArg !== undefined) {
122
+ const isGlobPattern = pathArg.includes("*") || pathArg.includes("?");
123
+ const isDir = !isGlobPattern && pathArg.endsWith("/");
124
+ if (isGlobPattern) {
125
+ const re = globToRegex(pathArg);
126
+ const allPaths = new Set([...Object.keys(routes), ...Object.keys(needsReview), ...Object.keys(exemptions)]);
127
+ for (const filePath of allPaths) {
128
+ if (re.test(filePath))
129
+ result[filePath] = resolveEntry(filePath, routes, needsReview, exemptions, ig, repoRoot, includeInstructions);
130
+ }
131
+ }
132
+ else if (isDir) {
133
+ const prefix = pathArg;
134
+ const allPaths = new Set([...Object.keys(routes), ...Object.keys(needsReview), ...Object.keys(exemptions)]);
135
+ for (const filePath of allPaths) {
136
+ if (filePath.startsWith(prefix))
137
+ result[filePath] = resolveEntry(filePath, routes, needsReview, exemptions, ig, repoRoot, includeInstructions);
138
+ }
139
+ }
140
+ else {
141
+ if (!(0, node_fs_1.existsSync)((0, node_path_1.resolve)(repoRoot, pathArg))) {
142
+ process.stderr.write(`warn: file does not exist in repo: ${pathArg}\n`);
143
+ }
144
+ result[pathArg] = resolveEntry(pathArg, routes, needsReview, exemptions, ig, repoRoot, includeInstructions);
145
+ }
146
+ }
147
+ else {
148
+ console.error("polaris map query: specify a path, glob, or --domain/--taskchain filter");
149
+ process.exit(1);
150
+ }
151
+ if (textMode) {
152
+ printText(result);
153
+ }
154
+ else {
155
+ console.log(JSON.stringify(result, null, 2));
156
+ }
157
+ }