@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,623 @@
1
+ "use strict";
2
+ /**
3
+ * Tests for route-local cognition delta logic.
4
+ *
5
+ * Covers:
6
+ * - isCognitionSkippedFolder
7
+ * - detectOperationalReasons
8
+ * - findNearestRoutePolarismd
9
+ * - applyRouteCognitionDelta
10
+ * - detectSummaryReasons
11
+ * - applySummaryDelta
12
+ * - isSummaryOversized / hasDoctrineBled
13
+ * - validateCognitionSurfaces / validateSummaryFile
14
+ * - looksLikePolarisChurn
15
+ * - detectMissingCognitionSurfaces (map/update)
16
+ * - seedCognitionDrafts (map/update)
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ const vitest_1 = require("vitest");
20
+ const node_fs_1 = require("node:fs");
21
+ const node_path_1 = require("node:path");
22
+ const node_os_1 = require("node:os");
23
+ const route_cognition_delta_js_1 = require("./route-cognition-delta.js");
24
+ const summary_delta_js_1 = require("./summary-delta.js");
25
+ const validate_js_1 = require("./validate.js");
26
+ const archive_js_1 = require("./archive.js");
27
+ const update_js_1 = require("../map/update.js");
28
+ // ── Helpers ──────────────────────────────────────────────────────────────────
29
+ function makeTmp() {
30
+ const dir = (0, node_path_1.join)((0, node_os_1.tmpdir)(), `polaris-cognition-test-${Date.now()}`);
31
+ (0, node_fs_1.mkdirSync)(dir, { recursive: true });
32
+ return dir;
33
+ }
34
+ function cleanup(dir) {
35
+ try {
36
+ (0, node_fs_1.rmSync)(dir, { recursive: true, force: true });
37
+ }
38
+ catch { /* ignore */ }
39
+ }
40
+ // ── isCognitionSkippedFolder ──────────────────────────────────────────────────
41
+ (0, vitest_1.describe)("isCognitionSkippedFolder", () => {
42
+ (0, vitest_1.it)("skips .git", () => (0, vitest_1.expect)((0, route_cognition_delta_js_1.isCognitionSkippedFolder)(".git")).toBe(true));
43
+ (0, vitest_1.it)("skips .git/ prefix", () => (0, vitest_1.expect)((0, route_cognition_delta_js_1.isCognitionSkippedFolder)(".git/refs")).toBe(true));
44
+ (0, vitest_1.it)("skips node_modules", () => (0, vitest_1.expect)((0, route_cognition_delta_js_1.isCognitionSkippedFolder)("node_modules")).toBe(true));
45
+ (0, vitest_1.it)("skips dist/", () => (0, vitest_1.expect)((0, route_cognition_delta_js_1.isCognitionSkippedFolder)("dist/index.js")).toBe(true));
46
+ (0, vitest_1.it)("skips .taskchain_artifacts/", () => (0, vitest_1.expect)((0, route_cognition_delta_js_1.isCognitionSkippedFolder)(".taskchain_artifacts/polaris-run")).toBe(true));
47
+ (0, vitest_1.it)("allows .polaris root", () => (0, vitest_1.expect)((0, route_cognition_delta_js_1.isCognitionSkippedFolder)(".polaris")).toBe(false));
48
+ (0, vitest_1.it)("allows .polaris/bootstrap", () => (0, vitest_1.expect)((0, route_cognition_delta_js_1.isCognitionSkippedFolder)(".polaris/bootstrap")).toBe(false));
49
+ (0, vitest_1.it)("allows .polaris/clusters", () => (0, vitest_1.expect)((0, route_cognition_delta_js_1.isCognitionSkippedFolder)(".polaris/clusters")).toBe(false));
50
+ (0, vitest_1.it)("allows .polaris/map", () => (0, vitest_1.expect)((0, route_cognition_delta_js_1.isCognitionSkippedFolder)(".polaris/map")).toBe(false));
51
+ (0, vitest_1.it)("allows .polaris/runs", () => (0, vitest_1.expect)((0, route_cognition_delta_js_1.isCognitionSkippedFolder)(".polaris/runs")).toBe(false));
52
+ (0, vitest_1.it)("skips generated .polaris/clusters descendants", () => (0, vitest_1.expect)((0, route_cognition_delta_js_1.isCognitionSkippedFolder)(".polaris/clusters/POL-201")).toBe(true));
53
+ (0, vitest_1.it)("skips generated .polaris/runs descendants", () => (0, vitest_1.expect)((0, route_cognition_delta_js_1.isCognitionSkippedFolder)(".polaris/runs/polaris-run-1")).toBe(true));
54
+ (0, vitest_1.it)("skips .claude agent folder", () => (0, vitest_1.expect)((0, route_cognition_delta_js_1.isCognitionSkippedFolder)(".claude")).toBe(true));
55
+ (0, vitest_1.it)("does not skip src/", () => (0, vitest_1.expect)((0, route_cognition_delta_js_1.isCognitionSkippedFolder)("src")).toBe(false));
56
+ (0, vitest_1.it)("does not skip src/loop", () => (0, vitest_1.expect)((0, route_cognition_delta_js_1.isCognitionSkippedFolder)("src/loop")).toBe(false));
57
+ (0, vitest_1.it)("does not skip scripts/", () => (0, vitest_1.expect)((0, route_cognition_delta_js_1.isCognitionSkippedFolder)("scripts")).toBe(false));
58
+ });
59
+ // ── detectOperationalReasons ──────────────────────────────────────────────────
60
+ (0, vitest_1.describe)("detectOperationalReasons", () => {
61
+ (0, vitest_1.it)("detects folder-responsibilities-changed from index.ts", () => {
62
+ const reasons = (0, route_cognition_delta_js_1.detectOperationalReasons)(["src/loop/index.ts"]);
63
+ (0, vitest_1.expect)(reasons).toContain("folder-responsibilities-changed");
64
+ });
65
+ (0, vitest_1.it)("detects commands-workflows-changed from cli path", () => {
66
+ const reasons = (0, route_cognition_delta_js_1.detectOperationalReasons)(["src/cli/args.ts"]);
67
+ (0, vitest_1.expect)(reasons).toContain("commands-workflows-changed");
68
+ });
69
+ (0, vitest_1.it)("detects execution-constraints-changed from config/schema.ts", () => {
70
+ const reasons = (0, route_cognition_delta_js_1.detectOperationalReasons)(["src/config/schema.ts"]);
71
+ (0, vitest_1.expect)(reasons).toContain("execution-constraints-changed");
72
+ });
73
+ (0, vitest_1.it)("detects ownership-routing-changed from map/atlas.ts", () => {
74
+ const reasons = (0, route_cognition_delta_js_1.detectOperationalReasons)(["src/map/atlas.ts"]);
75
+ (0, vitest_1.expect)(reasons).toContain("ownership-routing-changed");
76
+ });
77
+ (0, vitest_1.it)("detects operational-behavior-changed from worker.ts", () => {
78
+ const reasons = (0, route_cognition_delta_js_1.detectOperationalReasons)(["src/loop/worker.ts"]);
79
+ (0, vitest_1.expect)(reasons).toContain("operational-behavior-changed");
80
+ });
81
+ (0, vitest_1.it)("returns empty for test files", () => {
82
+ const reasons = (0, route_cognition_delta_js_1.detectOperationalReasons)(["src/loop/worker.test.ts"]);
83
+ (0, vitest_1.expect)(reasons).toHaveLength(0);
84
+ });
85
+ (0, vitest_1.it)("returns empty for non-operational markdown", () => {
86
+ const reasons = (0, route_cognition_delta_js_1.detectOperationalReasons)(["docs/some-doc.md"]);
87
+ (0, vitest_1.expect)(reasons).toHaveLength(0);
88
+ });
89
+ (0, vitest_1.it)("returns empty for random json (non-config)", () => {
90
+ const reasons = (0, route_cognition_delta_js_1.detectOperationalReasons)(["data/fixtures.json"]);
91
+ (0, vitest_1.expect)(reasons).toHaveLength(0);
92
+ });
93
+ });
94
+ // ── findNearestRoutePolarismd ─────────────────────────────────────────────────
95
+ (0, vitest_1.describe)("findNearestRoutePolarismd", () => {
96
+ let tmp;
97
+ (0, vitest_1.beforeEach)(() => { tmp = makeTmp(); });
98
+ (0, vitest_1.afterEach)(() => cleanup(tmp));
99
+ (0, vitest_1.it)("finds POLARIS.md in parent dir when skipRoot=true", () => {
100
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src", "loop"), { recursive: true });
101
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "src", "loop", "POLARIS.md"), "# loop", "utf-8");
102
+ const result = (0, route_cognition_delta_js_1.findNearestRoutePolarismd)("src/loop/worker.ts", tmp, true);
103
+ (0, vitest_1.expect)(result).toBe("src/loop/POLARIS.md");
104
+ });
105
+ (0, vitest_1.it)("skips root POLARIS.md when skipRoot=true", () => {
106
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src"), { recursive: true });
107
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "POLARIS.md"), "# root", "utf-8");
108
+ const result = (0, route_cognition_delta_js_1.findNearestRoutePolarismd)("src/utils.ts", tmp, true);
109
+ (0, vitest_1.expect)(result).toBeNull();
110
+ });
111
+ (0, vitest_1.it)("returns root POLARIS.md when skipRoot=false", () => {
112
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src"), { recursive: true });
113
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "POLARIS.md"), "# root", "utf-8");
114
+ const result = (0, route_cognition_delta_js_1.findNearestRoutePolarismd)("src/utils.ts", tmp, false);
115
+ (0, vitest_1.expect)(result).toBe("POLARIS.md");
116
+ });
117
+ (0, vitest_1.it)("finds nearest ancestor POLARIS.md", () => {
118
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src", "deep", "nested"), { recursive: true });
119
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "src", "POLARIS.md"), "# src", "utf-8");
120
+ const result = (0, route_cognition_delta_js_1.findNearestRoutePolarismd)("src/deep/nested/file.ts", tmp, true);
121
+ (0, vitest_1.expect)(result).toBe("src/POLARIS.md");
122
+ });
123
+ (0, vitest_1.it)("skips skipped folder paths", () => {
124
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, ".git", "hooks"), { recursive: true });
125
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, ".git", "POLARIS.md"), "# git", "utf-8");
126
+ const result = (0, route_cognition_delta_js_1.findNearestRoutePolarismd)(".git/hooks/commit-msg", tmp, true);
127
+ (0, vitest_1.expect)(result).toBeNull();
128
+ });
129
+ });
130
+ // ── applyRouteCognitionDelta ──────────────────────────────────────────────────
131
+ (0, vitest_1.describe)("applyRouteCognitionDelta", () => {
132
+ let tmp;
133
+ (0, vitest_1.beforeEach)(() => { tmp = makeTmp(); });
134
+ (0, vitest_1.afterEach)(() => cleanup(tmp));
135
+ (0, vitest_1.it)("reports updateWarranted for operational files", () => {
136
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src", "loop"), { recursive: true });
137
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "src", "loop", "POLARIS.md"), "# loop", "utf-8");
138
+ const result = (0, route_cognition_delta_js_1.applyRouteCognitionDelta)({
139
+ repoRoot: tmp,
140
+ touchedFiles: ["src/loop/worker.ts", "src/loop/dispatch.ts"],
141
+ skipRoot: true,
142
+ });
143
+ (0, vitest_1.expect)(result.updateWarranted).toBe(true);
144
+ (0, vitest_1.expect)(result.reasons.length).toBeGreaterThan(0);
145
+ (0, vitest_1.expect)(result.routeLocalTargets).toContain("src/loop/POLARIS.md");
146
+ });
147
+ (0, vitest_1.it)("reports no update for test-only files", () => {
148
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src", "loop"), { recursive: true });
149
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "src", "loop", "POLARIS.md"), "# loop", "utf-8");
150
+ const result = (0, route_cognition_delta_js_1.applyRouteCognitionDelta)({
151
+ repoRoot: tmp,
152
+ touchedFiles: ["src/loop/worker.test.ts"],
153
+ skipRoot: true,
154
+ });
155
+ (0, vitest_1.expect)(result.updateWarranted).toBe(false);
156
+ });
157
+ (0, vitest_1.it)("detects missing POLARIS.md surfaces", () => {
158
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src", "newmod"), { recursive: true });
159
+ const result = (0, route_cognition_delta_js_1.applyRouteCognitionDelta)({
160
+ repoRoot: tmp,
161
+ touchedFiles: ["src/newmod/index.ts"],
162
+ skipRoot: true,
163
+ });
164
+ (0, vitest_1.expect)(result.missingCognitionSurfaces).toContain("src/newmod");
165
+ });
166
+ (0, vitest_1.it)("does not scan root when skipRoot=true", () => {
167
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "POLARIS.md"), "# root", "utf-8");
168
+ const result = (0, route_cognition_delta_js_1.applyRouteCognitionDelta)({
169
+ repoRoot: tmp,
170
+ touchedFiles: ["src/loop/worker.ts"],
171
+ skipRoot: true,
172
+ });
173
+ (0, vitest_1.expect)(result.routeLocalTargets).not.toContain("POLARIS.md");
174
+ });
175
+ (0, vitest_1.it)("detects missing top-level Polaris runtime surfaces", () => {
176
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, ".polaris", "map"), { recursive: true });
177
+ const result = (0, route_cognition_delta_js_1.applyRouteCognitionDelta)({
178
+ repoRoot: tmp,
179
+ touchedFiles: [".polaris/map/file-routes.json"],
180
+ skipRoot: true,
181
+ });
182
+ (0, vitest_1.expect)(result.missingCognitionSurfaces).toContain(".polaris/map");
183
+ });
184
+ });
185
+ // ── archiveCognitionNotes ──────────────────────────────────────────────────────
186
+ (0, vitest_1.describe)("archiveCognitionNotes", () => {
187
+ let tmp;
188
+ (0, vitest_1.beforeEach)(() => { tmp = makeTmp(); });
189
+ (0, vitest_1.afterEach)(() => cleanup(tmp));
190
+ (0, vitest_1.it)("moves reconciled notes into archive and writes provenance files", () => {
191
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, ".polaris", "cognition", "pending", "src", "loop"), { recursive: true });
192
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, ".polaris", "cognition", "pending", "src", "loop", "note.md"), "hello", "utf-8");
193
+ const result = (0, archive_js_1.archiveCognitionNotes)({
194
+ repoRoot: tmp,
195
+ reconcileId: "reconcile-1",
196
+ runId: "run-1",
197
+ notesConsumed: ["src/loop/note.md"],
198
+ polarisMdUpdated: true,
199
+ summaryMdUpdated: false,
200
+ result: { status: "success", applied: true },
201
+ });
202
+ (0, vitest_1.expect)(result.archivedNotes).toEqual([".polaris/cognition/archive/src/loop/note.md"]);
203
+ (0, vitest_1.expect)(result.missingNotes).toEqual([]);
204
+ (0, vitest_1.expect)((0, node_fs_1.existsSync)((0, node_path_1.join)(tmp, ".polaris", "cognition", "pending", "src", "loop", "note.md"))).toBe(false);
205
+ (0, vitest_1.expect)((0, node_fs_1.readFileSync)((0, node_path_1.join)(tmp, ".polaris", "cognition", "archive", "src", "loop", "note.md"), "utf-8")).toBe("hello");
206
+ (0, vitest_1.expect)(JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(tmp, ".polaris", "cognition", "archive", "src", "loop", ".reconcile-reconcile-1.json"), "utf-8"))).toEqual({
207
+ status: "success",
208
+ applied: true,
209
+ });
210
+ (0, vitest_1.expect)(JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(tmp, ".polaris", "cognition", "archive", "src", "loop", "cognition-index.json"), "utf-8"))).toEqual({
211
+ entries: [
212
+ {
213
+ reconcile_id: "reconcile-1",
214
+ run_id: "run-1",
215
+ reconciled_at: vitest_1.expect.any(String),
216
+ notes_consumed: ["note.md"],
217
+ polaris_md_updated: true,
218
+ summary_md_updated: false,
219
+ },
220
+ ],
221
+ });
222
+ });
223
+ (0, vitest_1.it)("keeps partial archive progress discoverable when some notes are missing", () => {
224
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, ".polaris", "cognition", "pending", "src", "loop"), { recursive: true });
225
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, ".polaris", "cognition", "pending", "src", "loop", "note.md"), "hello", "utf-8");
226
+ const result = (0, archive_js_1.archiveCognitionNotes)({
227
+ repoRoot: tmp,
228
+ reconcileId: "reconcile-2",
229
+ runId: "run-2",
230
+ notesConsumed: [
231
+ "src/loop/note.md",
232
+ "src/loop/missing.md",
233
+ ],
234
+ polarisMdUpdated: false,
235
+ summaryMdUpdated: true,
236
+ });
237
+ (0, vitest_1.expect)(result.archivedNotes).toEqual([".polaris/cognition/archive/src/loop/note.md"]);
238
+ (0, vitest_1.expect)(result.missingNotes).toEqual([".polaris/cognition/pending/src/loop/missing.md"]);
239
+ (0, vitest_1.expect)(JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(tmp, ".polaris", "cognition", "archive", "src", "loop", "cognition-index.json"), "utf-8"))).toEqual({
240
+ entries: [
241
+ {
242
+ reconcile_id: "reconcile-2",
243
+ run_id: "run-2",
244
+ reconciled_at: vitest_1.expect.any(String),
245
+ notes_consumed: ["note.md"],
246
+ polaris_md_updated: false,
247
+ summary_md_updated: true,
248
+ },
249
+ ],
250
+ });
251
+ });
252
+ (0, vitest_1.it)("keeps pending notes in place and records rejected librarian patches", () => {
253
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, ".polaris", "cognition", "pending", "src", "loop"), { recursive: true });
254
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, ".polaris", "cognition", "pending", "src", "loop", "note.md"), "hello", "utf-8");
255
+ const result = (0, archive_js_1.archiveCognitionNotes)({
256
+ repoRoot: tmp,
257
+ reconcileId: "reconcile-3",
258
+ runId: "run-3",
259
+ notesConsumed: ["src/loop/note.md"],
260
+ polarisMdUpdated: false,
261
+ summaryMdUpdated: false,
262
+ status: "rejected",
263
+ rejectionReason: "validation failed",
264
+ result: { status: "rejected" },
265
+ });
266
+ (0, vitest_1.expect)(result.archivedNotes).toEqual([]);
267
+ (0, vitest_1.expect)(result.resultFiles).toEqual([]);
268
+ (0, vitest_1.expect)((0, node_fs_1.existsSync)((0, node_path_1.join)(tmp, ".polaris", "cognition", "pending", "src", "loop", "note.md"))).toBe(true);
269
+ (0, vitest_1.expect)((0, node_fs_1.existsSync)((0, node_path_1.join)(tmp, ".polaris", "cognition", "archive", "src", "loop", "note.md"))).toBe(false);
270
+ (0, vitest_1.expect)(JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(tmp, ".polaris", "cognition", "pending", "src", "loop", "cognition-index.json"), "utf-8"))).toEqual({
271
+ entries: [
272
+ {
273
+ event: "cognition-librarian-patch-rejected",
274
+ reconcile_id: "reconcile-3",
275
+ run_id: "run-3",
276
+ rejected_at: vitest_1.expect.any(String),
277
+ notes_consumed: ["note.md"],
278
+ polaris_md_updated: false,
279
+ summary_md_updated: false,
280
+ reason: "validation failed",
281
+ },
282
+ ],
283
+ });
284
+ });
285
+ });
286
+ // ── detectSummaryReasons ──────────────────────────────────────────────────────
287
+ (0, vitest_1.describe)("detectSummaryReasons", () => {
288
+ (0, vitest_1.it)("detects linked-docs-changed for spec raw path", () => {
289
+ const reasons = (0, summary_delta_js_1.detectSummaryReasons)(["smartdocs/docs/specs/raw/arch.md"]);
290
+ (0, vitest_1.expect)(reasons).toContain("linked-docs-changed");
291
+ });
292
+ (0, vitest_1.it)("detects doctrine-spec-linkage-changed for AGENTS.md", () => {
293
+ const reasons = (0, summary_delta_js_1.detectSummaryReasons)(["AGENTS.md"]);
294
+ (0, vitest_1.expect)(reasons).toContain("canon-relationships-changed");
295
+ });
296
+ (0, vitest_1.it)("detects architecture-meaning-changed for architecture docs", () => {
297
+ const reasons = (0, summary_delta_js_1.detectSummaryReasons)(["smartdocs/docs/architecture/overview.md"]);
298
+ (0, vitest_1.expect)(reasons).toContain("architecture-meaning-changed");
299
+ });
300
+ (0, vitest_1.it)("returns empty for implementation source files", () => {
301
+ const reasons = (0, summary_delta_js_1.detectSummaryReasons)(["src/loop/worker.ts"]);
302
+ (0, vitest_1.expect)(reasons).toHaveLength(0);
303
+ });
304
+ (0, vitest_1.it)("detects config change as canon relationship", () => {
305
+ const reasons = (0, summary_delta_js_1.detectSummaryReasons)(["polaris.config.json"]);
306
+ (0, vitest_1.expect)(reasons).toContain("canon-relationships-changed");
307
+ });
308
+ });
309
+ // ── applySummaryDelta ─────────────────────────────────────────────────────────
310
+ (0, vitest_1.describe)("applySummaryDelta", () => {
311
+ let tmp;
312
+ (0, vitest_1.beforeEach)(() => { tmp = makeTmp(); });
313
+ (0, vitest_1.afterEach)(() => cleanup(tmp));
314
+ (0, vitest_1.it)("reports updateWarranted for spec changes", () => {
315
+ const result = (0, summary_delta_js_1.applySummaryDelta)({
316
+ repoRoot: tmp,
317
+ touchedFiles: ["smartdocs/docs/specs/raw/some-spec.md"],
318
+ skipRoot: true,
319
+ });
320
+ (0, vitest_1.expect)(result.updateWarranted).toBe(true);
321
+ });
322
+ (0, vitest_1.it)("reports no update for implementation source", () => {
323
+ const result = (0, summary_delta_js_1.applySummaryDelta)({
324
+ repoRoot: tmp,
325
+ touchedFiles: ["src/loop/checkpoint.ts"],
326
+ skipRoot: true,
327
+ });
328
+ (0, vitest_1.expect)(result.updateWarranted).toBe(false);
329
+ });
330
+ (0, vitest_1.it)("finds existing SUMMARY.md targets", () => {
331
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "smartdocs", "docs", "specs", "raw"), { recursive: true });
332
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "smartdocs", "docs", "specs"), { recursive: true });
333
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "smartdocs", "docs", "specs", "SUMMARY.md"), "# specs summary", "utf-8");
334
+ const result = (0, summary_delta_js_1.applySummaryDelta)({
335
+ repoRoot: tmp,
336
+ touchedFiles: ["smartdocs/docs/specs/raw/some.md"],
337
+ skipRoot: true,
338
+ });
339
+ (0, vitest_1.expect)(result.summaryTargets).toContain("smartdocs/docs/specs/SUMMARY.md");
340
+ });
341
+ (0, vitest_1.it)("detects folders with POLARIS.md but no SUMMARY.md", () => {
342
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src", "map"), { recursive: true });
343
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "src", "map", "POLARIS.md"), "# map", "utf-8");
344
+ const result = (0, summary_delta_js_1.applySummaryDelta)({
345
+ repoRoot: tmp,
346
+ touchedFiles: ["src/map/POLARIS.md"],
347
+ skipRoot: true,
348
+ });
349
+ (0, vitest_1.expect)(result.missingSummaries).toContain("src/map");
350
+ });
351
+ });
352
+ // ── detectPrecedenceLevel ─────────────────────────────────────────────────────
353
+ (0, vitest_1.describe)("detectPrecedenceLevel", () => {
354
+ (0, vitest_1.it)("returns promoted-doctrine for active doctrine path", () => {
355
+ (0, vitest_1.expect)((0, summary_delta_js_1.detectPrecedenceLevel)(["smartdocs/docs/doctrine/active/foo.md"])).toBe("promoted-doctrine");
356
+ });
357
+ (0, vitest_1.it)("returns spec-or-arch for active spec path", () => {
358
+ (0, vitest_1.expect)((0, summary_delta_js_1.detectPrecedenceLevel)(["smartdocs/docs/specs/active/bar.md"])).toBe("spec-or-arch");
359
+ });
360
+ (0, vitest_1.it)("returns spec-or-arch for architecture doc", () => {
361
+ (0, vitest_1.expect)((0, summary_delta_js_1.detectPrecedenceLevel)(["smartdocs/docs/architecture/overview.md"])).toBe("spec-or-arch");
362
+ });
363
+ (0, vitest_1.it)("returns spec-or-arch for specs/raw/ path", () => {
364
+ (0, vitest_1.expect)((0, summary_delta_js_1.detectPrecedenceLevel)(["smartdocs/docs/specs/raw/polaris-spec.md"])).toBe("spec-or-arch");
365
+ });
366
+ (0, vitest_1.it)("returns route-polaris-md when only a POLARIS.md is touched", () => {
367
+ (0, vitest_1.expect)((0, summary_delta_js_1.detectPrecedenceLevel)(["src/loop/POLARIS.md"])).toBe("route-polaris-md");
368
+ });
369
+ (0, vitest_1.it)("returns source-inference for plain source files", () => {
370
+ (0, vitest_1.expect)((0, summary_delta_js_1.detectPrecedenceLevel)(["src/loop/worker.ts"])).toBe("source-inference");
371
+ });
372
+ (0, vitest_1.it)("promoted-doctrine wins over spec-or-arch in same batch", () => {
373
+ (0, vitest_1.expect)((0, summary_delta_js_1.detectPrecedenceLevel)([
374
+ "smartdocs/docs/specs/raw/polaris-spec.md",
375
+ "smartdocs/docs/doctrine/active/core.md",
376
+ ])).toBe("promoted-doctrine");
377
+ });
378
+ (0, vitest_1.it)("spec-or-arch wins over route-polaris-md in same batch", () => {
379
+ (0, vitest_1.expect)((0, summary_delta_js_1.detectPrecedenceLevel)([
380
+ "src/map/POLARIS.md",
381
+ "smartdocs/docs/architecture/overview.md",
382
+ ])).toBe("spec-or-arch");
383
+ });
384
+ });
385
+ // ── isSummaryOversized / hasDoctrineBled ──────────────────────────────────────
386
+ (0, vitest_1.describe)("isSummaryOversized", () => {
387
+ (0, vitest_1.it)("returns false for short content", () => {
388
+ (0, vitest_1.expect)((0, summary_delta_js_1.isSummaryOversized)("# Summary\n\nShort.")).toBe(false);
389
+ });
390
+ (0, vitest_1.it)("returns true when content exceeds SUMMARY_MAX_BYTES", () => {
391
+ const oversized = "x".repeat(summary_delta_js_1.SUMMARY_MAX_BYTES + 1);
392
+ (0, vitest_1.expect)((0, summary_delta_js_1.isSummaryOversized)(oversized)).toBe(true);
393
+ });
394
+ });
395
+ (0, vitest_1.describe)("hasDoctrineBled", () => {
396
+ (0, vitest_1.it)("detects '## Editing rules' section heading as doctrine bleed", () => {
397
+ (0, vitest_1.expect)((0, summary_delta_js_1.hasDoctrineBled)("## Editing rules\n\nDo not add side effects.")).toBe(true);
398
+ });
399
+ (0, vitest_1.it)("detects '## Constraints' section heading as doctrine bleed", () => {
400
+ (0, vitest_1.expect)((0, summary_delta_js_1.hasDoctrineBled)("## Constraints\n\nMust not skip.")).toBe(true);
401
+ });
402
+ (0, vitest_1.it)("detects strong imperative 'must always' at line start as doctrine bleed", () => {
403
+ (0, vitest_1.expect)((0, summary_delta_js_1.hasDoctrineBled)("Workers must always stop after one child.")).toBe(true);
404
+ });
405
+ (0, vitest_1.it)("returns false for bare 'never' in prose (not imperative heading)", () => {
406
+ (0, vitest_1.expect)((0, summary_delta_js_1.hasDoctrineBled)("This module never directly writes to disk.")).toBe(false);
407
+ });
408
+ (0, vitest_1.it)("returns false for 'do not' in quoted context", () => {
409
+ (0, vitest_1.expect)((0, summary_delta_js_1.hasDoctrineBled)("The spec says \"do not skip validation\" in section 3.")).toBe(false);
410
+ });
411
+ (0, vitest_1.it)("returns false for normal informational content", () => {
412
+ (0, vitest_1.expect)((0, summary_delta_js_1.hasDoctrineBled)("# Summary\n\nThis module handles state management.")).toBe(false);
413
+ });
414
+ });
415
+ // ── validateCognitionSurfaces / validateSummaryFile ───────────────────────────
416
+ (0, vitest_1.describe)("validateCognitionSurfaces", () => {
417
+ let tmp;
418
+ (0, vitest_1.beforeEach)(() => { tmp = makeTmp(); });
419
+ (0, vitest_1.afterEach)(() => cleanup(tmp));
420
+ (0, vitest_1.it)("returns valid when no cognition files exist below root", () => {
421
+ const result = (0, validate_js_1.validateCognitionSurfaces)(tmp);
422
+ (0, vitest_1.expect)(result.valid).toBe(true);
423
+ (0, vitest_1.expect)(result.violations).toHaveLength(0);
424
+ });
425
+ (0, vitest_1.it)("detects oversized SUMMARY.md", () => {
426
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src", "loop"), { recursive: true });
427
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "src", "loop", "SUMMARY.md"), "x".repeat(summary_delta_js_1.SUMMARY_MAX_BYTES + 100), "utf-8");
428
+ const result = (0, validate_js_1.validateCognitionSurfaces)(tmp);
429
+ const oversized = result.violations.filter((v) => v.type === "summary-oversized");
430
+ (0, vitest_1.expect)(oversized).toHaveLength(1);
431
+ (0, vitest_1.expect)(oversized[0].file).toBe("src/loop/SUMMARY.md");
432
+ });
433
+ (0, vitest_1.it)("puts doctrine bleed in warnings (not violations) and does not fail valid", () => {
434
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src", "loop"), { recursive: true });
435
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "src", "loop", "SUMMARY.md"), "Workers must always stop after one child.", "utf-8");
436
+ const result = (0, validate_js_1.validateCognitionSurfaces)(tmp);
437
+ // Doctrine bleed is warn-only — must not fail validation
438
+ (0, vitest_1.expect)(result.valid).toBe(true);
439
+ (0, vitest_1.expect)(result.violations.filter((v) => v.type === "summary-doctrine-bleed")).toHaveLength(0);
440
+ (0, vitest_1.expect)(result.warnings.filter((v) => v.type === "summary-doctrine-bleed")).toHaveLength(1);
441
+ });
442
+ (0, vitest_1.it)("skips root-level POLARIS.md", () => {
443
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "POLARIS.md"), "# Root", "utf-8");
444
+ const result = (0, validate_js_1.validateCognitionSurfaces)(tmp);
445
+ (0, vitest_1.expect)(result.valid).toBe(true);
446
+ });
447
+ (0, vitest_1.it)("skips skipped folders (.git, node_modules, etc.)", () => {
448
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, ".git"), { recursive: true });
449
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, ".git", "SUMMARY.md"), "must always do X", "utf-8");
450
+ const result = (0, validate_js_1.validateCognitionSurfaces)(tmp);
451
+ (0, vitest_1.expect)(result.valid).toBe(true);
452
+ });
453
+ });
454
+ (0, vitest_1.describe)("validateSummaryFile", () => {
455
+ let tmp;
456
+ (0, vitest_1.beforeEach)(() => { tmp = makeTmp(); });
457
+ (0, vitest_1.afterEach)(() => cleanup(tmp));
458
+ (0, vitest_1.it)("returns no violations for a clean summary", () => {
459
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src", "loop"), { recursive: true });
460
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "src", "loop", "SUMMARY.md"), "# Summary\n\nContextual summary only.", "utf-8");
461
+ const violations = (0, validate_js_1.validateSummaryFile)("src/loop/SUMMARY.md", tmp);
462
+ (0, vitest_1.expect)(violations).toHaveLength(0);
463
+ });
464
+ (0, vitest_1.it)("returns warn-severity entry for doctrine bleed section heading", () => {
465
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src", "loop"), { recursive: true });
466
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "src", "loop", "SUMMARY.md"), "## Editing rules\nNever skip.", "utf-8");
467
+ const results = (0, validate_js_1.validateSummaryFile)("src/loop/SUMMARY.md", tmp);
468
+ const bleed = results.find((v) => v.type === "summary-doctrine-bleed");
469
+ (0, vitest_1.expect)(bleed).toBeDefined();
470
+ (0, vitest_1.expect)(bleed.severity).toBe("warn");
471
+ });
472
+ });
473
+ // ── looksLikePolarisChurn ─────────────────────────────────────────────────────
474
+ (0, vitest_1.describe)("looksLikePolarisChurn", () => {
475
+ (0, vitest_1.it)("detects identical content as churn", () => {
476
+ const content = "# Loop\n\nHandles session lifecycle.";
477
+ (0, vitest_1.expect)((0, validate_js_1.looksLikePolarisChurn)(content, content)).toBe(true);
478
+ });
479
+ (0, vitest_1.it)("detects whitespace-only diff as churn", () => {
480
+ (0, vitest_1.expect)((0, validate_js_1.looksLikePolarisChurn)("# Loop\n\nHandles sessions.", "# Loop\n\n\nHandles sessions.\n")).toBe(true);
481
+ });
482
+ (0, vitest_1.it)("does not flag substantive diff as churn", () => {
483
+ const before = "# Loop\n\nHandles sessions.";
484
+ const after = "# Loop\n\nHandles sessions.\n\n## New Section\n\nAdded new behavior.";
485
+ (0, vitest_1.expect)((0, validate_js_1.looksLikePolarisChurn)(before, after)).toBe(false);
486
+ });
487
+ });
488
+ // ── detectMissingCognitionSurfaces (map/update) ───────────────────────────────
489
+ (0, vitest_1.describe)("detectMissingCognitionSurfaces", () => {
490
+ let tmp;
491
+ (0, vitest_1.beforeEach)(() => { tmp = makeTmp(); });
492
+ (0, vitest_1.afterEach)(() => cleanup(tmp));
493
+ (0, vitest_1.it)("reports folder missing POLARIS.md for a touched file", () => {
494
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src", "newmod"), { recursive: true });
495
+ const { missingPolaris } = (0, update_js_1.detectMissingCognitionSurfaces)(["src/newmod/index.ts"], tmp);
496
+ (0, vitest_1.expect)(missingPolaris).toContain("src/newmod");
497
+ });
498
+ (0, vitest_1.it)("does not report a folder that already has POLARIS.md", () => {
499
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src", "loop"), { recursive: true });
500
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "src", "loop", "POLARIS.md"), "# loop", "utf-8");
501
+ const { missingPolaris } = (0, update_js_1.detectMissingCognitionSurfaces)(["src/loop/worker.ts"], tmp);
502
+ (0, vitest_1.expect)(missingPolaris).not.toContain("src/loop");
503
+ });
504
+ (0, vitest_1.it)("reports folder with POLARIS.md but no SUMMARY.md as missing summary", () => {
505
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src", "loop"), { recursive: true });
506
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "src", "loop", "POLARIS.md"), "# loop", "utf-8");
507
+ const { missingSummary } = (0, update_js_1.detectMissingCognitionSurfaces)(["src/loop/worker.ts"], tmp);
508
+ (0, vitest_1.expect)(missingSummary).toContain("src/loop");
509
+ });
510
+ (0, vitest_1.it)("does not report skipped folders", () => {
511
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, ".taskchain_artifacts", "polaris-run"), { recursive: true });
512
+ const { missingPolaris } = (0, update_js_1.detectMissingCognitionSurfaces)([".taskchain_artifacts/polaris-run/current-state.json"], tmp);
513
+ (0, vitest_1.expect)(missingPolaris).toHaveLength(0);
514
+ });
515
+ (0, vitest_1.it)("does not report root-level folder", () => {
516
+ const { missingPolaris } = (0, update_js_1.detectMissingCognitionSurfaces)(["README.md"], tmp);
517
+ (0, vitest_1.expect)(missingPolaris).not.toContain("");
518
+ });
519
+ });
520
+ // ── seedCognitionDrafts ───────────────────────────────────────────────────────
521
+ (0, vitest_1.describe)("seedCognitionDrafts", () => {
522
+ let tmp;
523
+ (0, vitest_1.beforeEach)(() => { tmp = makeTmp(); });
524
+ (0, vitest_1.afterEach)(() => cleanup(tmp));
525
+ (0, vitest_1.it)("creates draft POLARIS.md for eligible folders when seeding", () => {
526
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src", "newmod"), { recursive: true });
527
+ const seeded = (0, update_js_1.seedCognitionDrafts)({ polaris: ["src/newmod"], summary: [] }, tmp);
528
+ (0, vitest_1.expect)(seeded).toContain("src/newmod/POLARIS.md");
529
+ (0, vitest_1.expect)((0, node_fs_1.existsSync)((0, node_path_1.join)(tmp, "src", "newmod", "POLARIS.md"))).toBe(true);
530
+ const content = (0, node_fs_1.readFileSync)((0, node_path_1.join)(tmp, "src", "newmod", "POLARIS.md"), "utf-8");
531
+ // Draft only — scaffold headings with TODO placeholders, no filled content
532
+ (0, vitest_1.expect)(content).toContain("DRAFT");
533
+ (0, vitest_1.expect)(content).toContain("## Purpose");
534
+ (0, vitest_1.expect)(content).toContain("<!-- TODO -->");
535
+ });
536
+ (0, vitest_1.it)("creates draft SUMMARY.md for eligible folders when seeding", () => {
537
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src", "map"), { recursive: true });
538
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "src", "map", "POLARIS.md"), "# map", "utf-8");
539
+ const seeded = (0, update_js_1.seedCognitionDrafts)({ polaris: [], summary: ["src/map"] }, tmp);
540
+ (0, vitest_1.expect)(seeded).toContain("src/map/SUMMARY.md");
541
+ (0, vitest_1.expect)((0, node_fs_1.existsSync)((0, node_path_1.join)(tmp, "src", "map", "SUMMARY.md"))).toBe(true);
542
+ const content = (0, node_fs_1.readFileSync)((0, node_path_1.join)(tmp, "src", "map", "SUMMARY.md"), "utf-8");
543
+ // Draft only — no filled content, operator must complete
544
+ (0, vitest_1.expect)(content).toContain("DRAFT");
545
+ (0, vitest_1.expect)(content).toContain("Informational only");
546
+ });
547
+ (0, vitest_1.it)("does not overwrite existing files", () => {
548
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src", "loop"), { recursive: true });
549
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "src", "loop", "POLARIS.md"), "# existing content", "utf-8");
550
+ (0, update_js_1.seedCognitionDrafts)({ polaris: ["src/loop"], summary: [] }, tmp);
551
+ const content = (0, node_fs_1.readFileSync)((0, node_path_1.join)(tmp, "src", "loop", "POLARIS.md"), "utf-8");
552
+ (0, vitest_1.expect)(content).toBe("# existing content");
553
+ });
554
+ (0, vitest_1.it)("skips skipped folders", () => {
555
+ const seeded = (0, update_js_1.seedCognitionDrafts)({ polaris: [".taskchain_artifacts/polaris-run"], summary: [] }, tmp);
556
+ (0, vitest_1.expect)(seeded).toHaveLength(0);
557
+ (0, vitest_1.expect)((0, node_fs_1.existsSync)((0, node_path_1.join)(tmp, ".taskchain_artifacts", "polaris-run", "POLARIS.md"))).toBe(false);
558
+ });
559
+ (0, vitest_1.it)("does not create files during default map update (no seedCognition flag)", () => {
560
+ // This test verifies the integration contract: seedCognitionDrafts is only
561
+ // called when seedCognition=true is explicitly passed to runMapUpdate.
562
+ // Without that flag, detectMissingCognitionSurfaces runs but creates nothing.
563
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(tmp, "src", "newmod"), { recursive: true });
564
+ // Calling detectMissing but NOT seedCognitionDrafts simulates default behavior
565
+ const { missingPolaris } = (0, update_js_1.detectMissingCognitionSurfaces)(["src/newmod/index.ts"], tmp);
566
+ // Detection reports missing
567
+ (0, vitest_1.expect)(missingPolaris).toContain("src/newmod");
568
+ // But no files were created
569
+ (0, vitest_1.expect)((0, node_fs_1.existsSync)((0, node_path_1.join)(tmp, "src", "newmod", "POLARIS.md"))).toBe(false);
570
+ });
571
+ });
572
+ // ── --include-root behavior ───────────────────────────────────────────────────
573
+ (0, vitest_1.describe)("detectMissingCognitionSurfaces --include-root", () => {
574
+ let tmp;
575
+ (0, vitest_1.beforeEach)(() => { tmp = makeTmp(); });
576
+ (0, vitest_1.afterEach)(() => cleanup(tmp));
577
+ (0, vitest_1.it)("does NOT report root when includeRoot is false/omitted", () => {
578
+ // Root-level file with no POLARIS.md at root
579
+ const { missingPolaris } = (0, update_js_1.detectMissingCognitionSurfaces)(["README.md"], tmp);
580
+ (0, vitest_1.expect)(missingPolaris).not.toContain("");
581
+ });
582
+ (0, vitest_1.it)("reports root as missing when includeRoot=true and no root POLARIS.md", () => {
583
+ // A top-level file (no sub-folder ancestor to find)
584
+ const { missingPolaris } = (0, update_js_1.detectMissingCognitionSurfaces)(["README.md"], tmp, true);
585
+ (0, vitest_1.expect)(missingPolaris).toContain("");
586
+ });
587
+ (0, vitest_1.it)("does NOT report root when root already has POLARIS.md and includeRoot=true", () => {
588
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "POLARIS.md"), "# root", "utf-8");
589
+ const { missingPolaris } = (0, update_js_1.detectMissingCognitionSurfaces)(["README.md"], tmp, true);
590
+ (0, vitest_1.expect)(missingPolaris).not.toContain("");
591
+ });
592
+ (0, vitest_1.it)("reports root as missing SUMMARY.md when includeRoot=true and has POLARIS.md only", () => {
593
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "POLARIS.md"), "# root", "utf-8");
594
+ const { missingSummary } = (0, update_js_1.detectMissingCognitionSurfaces)(["README.md"], tmp, true);
595
+ (0, vitest_1.expect)(missingSummary).toContain("");
596
+ });
597
+ });
598
+ (0, vitest_1.describe)("seedCognitionDrafts --include-root", () => {
599
+ let tmp;
600
+ (0, vitest_1.beforeEach)(() => { tmp = makeTmp(); });
601
+ (0, vitest_1.afterEach)(() => cleanup(tmp));
602
+ (0, vitest_1.it)("skips root by default (includeRoot omitted)", () => {
603
+ const seeded = (0, update_js_1.seedCognitionDrafts)({ polaris: [""], summary: [] }, tmp);
604
+ (0, vitest_1.expect)(seeded).toHaveLength(0);
605
+ (0, vitest_1.expect)((0, node_fs_1.existsSync)((0, node_path_1.join)(tmp, "POLARIS.md"))).toBe(false);
606
+ });
607
+ (0, vitest_1.it)("seeds root POLARIS.md when includeRoot=true", () => {
608
+ const seeded = (0, update_js_1.seedCognitionDrafts)({ polaris: [""], summary: [] }, tmp, true);
609
+ (0, vitest_1.expect)(seeded).toContain("POLARIS.md");
610
+ (0, vitest_1.expect)((0, node_fs_1.existsSync)((0, node_path_1.join)(tmp, "POLARIS.md"))).toBe(true);
611
+ });
612
+ (0, vitest_1.it)("seeds root SUMMARY.md when includeRoot=true", () => {
613
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "POLARIS.md"), "# root", "utf-8");
614
+ const seeded = (0, update_js_1.seedCognitionDrafts)({ polaris: [], summary: [""] }, tmp, true);
615
+ (0, vitest_1.expect)(seeded).toContain("SUMMARY.md");
616
+ (0, vitest_1.expect)((0, node_fs_1.existsSync)((0, node_path_1.join)(tmp, "SUMMARY.md"))).toBe(true);
617
+ });
618
+ (0, vitest_1.it)("does not overwrite existing root POLARIS.md even with includeRoot=true", () => {
619
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(tmp, "POLARIS.md"), "# existing root", "utf-8");
620
+ (0, update_js_1.seedCognitionDrafts)({ polaris: [""], summary: [] }, tmp, true);
621
+ (0, vitest_1.expect)((0, node_fs_1.readFileSync)((0, node_path_1.join)(tmp, "POLARIS.md"), "utf-8")).toBe("# existing root");
622
+ });
623
+ });