@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,238 @@
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 validate_instructions_js_1 = require("./validate-instructions.js");
7
+ const TMP = (0, node_path_1.join)(process.cwd(), ".test-validate-instructions-tmp");
8
+ function makeEntry(overrides = {}) {
9
+ return {
10
+ domain: "test-domain",
11
+ route: "test-route",
12
+ taskchain: "test-chain",
13
+ confidence: 0.9,
14
+ classification: "indexed",
15
+ last_updated: "2026-01-01T00:00:00Z",
16
+ updated_by: "test",
17
+ tags: [],
18
+ ...overrides,
19
+ };
20
+ }
21
+ function setup() {
22
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(TMP, "src/map"), { recursive: true });
23
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(TMP, ".polaris/map"), { recursive: true });
24
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, "polaris.config.json"), JSON.stringify({ repo: {}, map: {} }));
25
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, ".polaris/map/file-routes.json"), JSON.stringify({}));
26
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, ".polaris/map/needs-review.json"), JSON.stringify({}));
27
+ }
28
+ function teardown() {
29
+ (0, node_fs_1.rmSync)(TMP, { recursive: true, force: true });
30
+ }
31
+ // ---------------------------------------------------------------------------
32
+ // parseReadBeforeEditingLinks
33
+ // ---------------------------------------------------------------------------
34
+ (0, vitest_1.describe)("parseReadBeforeEditingLinks", () => {
35
+ (0, vitest_1.it)("returns empty array when no section present", () => {
36
+ const content = "# Title\n\n## Purpose\nsome text";
37
+ (0, vitest_1.expect)((0, validate_instructions_js_1.parseReadBeforeEditingLinks)(content)).toEqual([]);
38
+ });
39
+ (0, vitest_1.it)("extracts local markdown links from section", () => {
40
+ const content = [
41
+ "# Title",
42
+ "",
43
+ "## Read before editing",
44
+ "",
45
+ "- [Design spec](../docs/spec.md)",
46
+ "- [Atlas](../map/atlas.ts)",
47
+ "",
48
+ "## Other section",
49
+ ].join("\n");
50
+ const links = (0, validate_instructions_js_1.parseReadBeforeEditingLinks)(content);
51
+ (0, vitest_1.expect)(links).toContain("../docs/spec.md");
52
+ (0, vitest_1.expect)(links).toContain("../map/atlas.ts");
53
+ });
54
+ (0, vitest_1.it)("ignores external URLs", () => {
55
+ const content = [
56
+ "## Read before editing",
57
+ "",
58
+ "- [External](https://example.com/doc)",
59
+ "- [Local](./local.md)",
60
+ ].join("\n");
61
+ const links = (0, validate_instructions_js_1.parseReadBeforeEditingLinks)(content);
62
+ (0, vitest_1.expect)(links).not.toContain("https://example.com/doc");
63
+ (0, vitest_1.expect)(links).toContain("./local.md");
64
+ });
65
+ (0, vitest_1.it)("does not bleed into next section", () => {
66
+ const content = [
67
+ "## Read before editing",
68
+ "",
69
+ "- [Good](./good.md)",
70
+ "",
71
+ "## Related routes",
72
+ "",
73
+ "- [Other](./other.md)",
74
+ ].join("\n");
75
+ const links = (0, validate_instructions_js_1.parseReadBeforeEditingLinks)(content);
76
+ (0, vitest_1.expect)(links).toContain("./good.md");
77
+ (0, vitest_1.expect)(links).not.toContain("./other.md");
78
+ });
79
+ });
80
+ // ---------------------------------------------------------------------------
81
+ // validateDir — MISSING
82
+ // ---------------------------------------------------------------------------
83
+ (0, vitest_1.describe)("validateDir - MISSING", () => {
84
+ (0, vitest_1.beforeEach)(setup);
85
+ (0, vitest_1.afterEach)(teardown);
86
+ (0, vitest_1.it)("returns MISSING when no POLARIS.md exists", () => {
87
+ const result = (0, validate_instructions_js_1.validateDir)("src/map", TMP, {});
88
+ (0, vitest_1.expect)(result.status).toBe("MISSING");
89
+ (0, vitest_1.expect)(result.polarisFile).toBeNull();
90
+ });
91
+ });
92
+ // ---------------------------------------------------------------------------
93
+ // validateDir — OK
94
+ // ---------------------------------------------------------------------------
95
+ (0, vitest_1.describe)("validateDir - OK", () => {
96
+ (0, vitest_1.beforeEach)(setup);
97
+ (0, vitest_1.afterEach)(teardown);
98
+ (0, vitest_1.it)("returns OK for a POLARIS.md with no issues (no git history, no links, no atlas)", () => {
99
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, "src/map/POLARIS.md"), "# map\n\n## Purpose\nSome text.\n");
100
+ const result = (0, validate_instructions_js_1.validateDir)("src/map", TMP, {});
101
+ (0, vitest_1.expect)(result.status).toBe("OK");
102
+ (0, vitest_1.expect)(result.findings).toHaveLength(0);
103
+ });
104
+ });
105
+ // ---------------------------------------------------------------------------
106
+ // validateDir — broken links (ERROR)
107
+ // ---------------------------------------------------------------------------
108
+ (0, vitest_1.describe)("validateDir - broken links", () => {
109
+ (0, vitest_1.beforeEach)(setup);
110
+ (0, vitest_1.afterEach)(teardown);
111
+ (0, vitest_1.it)("reports ERROR for a broken link in Read before editing", () => {
112
+ const content = [
113
+ "# map",
114
+ "",
115
+ "## Read before editing",
116
+ "",
117
+ "- [Missing spec](../nonexistent/spec.md)",
118
+ ].join("\n");
119
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, "src/map/POLARIS.md"), content);
120
+ const result = (0, validate_instructions_js_1.validateDir)("src/map", TMP, {});
121
+ (0, vitest_1.expect)(result.status).toBe("ERROR");
122
+ const errorFinding = result.findings.find((f) => f.severity === "ERROR");
123
+ (0, vitest_1.expect)(errorFinding?.message).toContain("Broken link");
124
+ (0, vitest_1.expect)(errorFinding?.message).toContain("../nonexistent/spec.md");
125
+ });
126
+ (0, vitest_1.it)("does not report error for an existing linked file", () => {
127
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, "src/map/atlas.ts"), "// file");
128
+ const content = [
129
+ "# map",
130
+ "",
131
+ "## Read before editing",
132
+ "",
133
+ "- [Atlas](./atlas.ts)",
134
+ ].join("\n");
135
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, "src/map/POLARIS.md"), content);
136
+ const result = (0, validate_instructions_js_1.validateDir)("src/map", TMP, {});
137
+ (0, vitest_1.expect)(result.status).toBe("OK");
138
+ });
139
+ });
140
+ // ---------------------------------------------------------------------------
141
+ // validateDir — instructionFile pointer (ERROR)
142
+ // ---------------------------------------------------------------------------
143
+ (0, vitest_1.describe)("validateDir - instructionFile pointer", () => {
144
+ (0, vitest_1.beforeEach)(setup);
145
+ (0, vitest_1.afterEach)(teardown);
146
+ (0, vitest_1.it)("reports ERROR when atlas instructionFile pointer references a non-existent file", () => {
147
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, "src/map/POLARIS.md"), "# map\n\n## Purpose\nText.\n");
148
+ const routes = {
149
+ "src/map/atlas.ts": makeEntry({ instructionFile: "src/map/POLARIS.md" }),
150
+ "src/map/update.ts": makeEntry({ instructionFile: "src/map/GHOST.md" }),
151
+ };
152
+ const result = (0, validate_instructions_js_1.validateDir)("src/map", TMP, routes);
153
+ (0, vitest_1.expect)(result.status).toBe("ERROR");
154
+ const errorFinding = result.findings.find((f) => f.severity === "ERROR");
155
+ (0, vitest_1.expect)(errorFinding?.message).toContain("src/map/GHOST.md");
156
+ });
157
+ (0, vitest_1.it)("does not report error when instructionFile exists", () => {
158
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, "src/map/POLARIS.md"), "# map\n\n## Purpose\nText.\n");
159
+ const routes = {
160
+ "src/map/atlas.ts": makeEntry({ instructionFile: "src/map/POLARIS.md" }),
161
+ };
162
+ const result = (0, validate_instructions_js_1.validateDir)("src/map", TMP, routes);
163
+ (0, vitest_1.expect)(result.status).toBe("OK");
164
+ });
165
+ (0, vitest_1.it)("ignores atlas entries for other directories", () => {
166
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, "src/map/POLARIS.md"), "# map\n\n## Purpose\nText.\n");
167
+ const routes = {
168
+ "src/cli/index.ts": makeEntry({ instructionFile: "src/cli/GHOST.md" }),
169
+ };
170
+ const result = (0, validate_instructions_js_1.validateDir)("src/map", TMP, routes);
171
+ (0, vitest_1.expect)(result.status).toBe("OK");
172
+ });
173
+ });
174
+ // ---------------------------------------------------------------------------
175
+ // validateInstructions — overall
176
+ // ---------------------------------------------------------------------------
177
+ (0, vitest_1.describe)("validateInstructions", () => {
178
+ (0, vitest_1.beforeEach)(setup);
179
+ (0, vitest_1.afterEach)(teardown);
180
+ (0, vitest_1.it)("returns hasErrors=false when all checks pass", () => {
181
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, "src/map/POLARIS.md"), "# map\n\n## Purpose\nText.\n");
182
+ const report = (0, validate_instructions_js_1.validateInstructions)({ repoRoot: TMP, path: "src/map" });
183
+ (0, vitest_1.expect)(report.hasErrors).toBe(false);
184
+ });
185
+ (0, vitest_1.it)("returns hasErrors=true when there is an ERROR", () => {
186
+ const content = [
187
+ "# map",
188
+ "",
189
+ "## Read before editing",
190
+ "",
191
+ "- [Missing](./nonexistent.md)",
192
+ ].join("\n");
193
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, "src/map/POLARIS.md"), content);
194
+ const report = (0, validate_instructions_js_1.validateInstructions)({ repoRoot: TMP, path: "src/map" });
195
+ (0, vitest_1.expect)(report.hasErrors).toBe(true);
196
+ });
197
+ (0, vitest_1.it)("reports MISSING for a dir without POLARIS.md", () => {
198
+ const report = (0, validate_instructions_js_1.validateInstructions)({ repoRoot: TMP, path: "src/map" });
199
+ (0, vitest_1.expect)(report.results[0]?.status).toBe("MISSING");
200
+ });
201
+ (0, vitest_1.it)("--fix writes POLARIS.draft.md for MISSING dir", () => {
202
+ const report = (0, validate_instructions_js_1.validateInstructions)({ repoRoot: TMP, path: "src/map", fix: true });
203
+ const result = report.results[0];
204
+ (0, vitest_1.expect)(result?.status).toBe("MISSING");
205
+ (0, vitest_1.expect)((0, node_fs_1.existsSync)((0, node_path_1.join)(TMP, "src/map/POLARIS.draft.md"))).toBe(true);
206
+ const draftFinding = result?.findings.find((f) => f.message === "Draft written to POLARIS.draft.md");
207
+ (0, vitest_1.expect)(draftFinding).toBeDefined();
208
+ });
209
+ (0, vitest_1.it)("--fix does not overwrite existing POLARIS.md", () => {
210
+ const original = "# Original\n";
211
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(TMP, "src/map/POLARIS.md"), original);
212
+ (0, validate_instructions_js_1.validateInstructions)({ repoRoot: TMP, path: "src/map", fix: true });
213
+ // POLARIS.md should be untouched — only POLARIS.draft.md is written
214
+ (0, vitest_1.expect)((0, node_fs_1.readFileSync)((0, node_path_1.join)(TMP, "src/map/POLARIS.md"), "utf-8")).toBe(original);
215
+ });
216
+ (0, vitest_1.it)("scopes validation to --path", () => {
217
+ // Only src/map checked; other dirs are irrelevant
218
+ const report = (0, validate_instructions_js_1.validateInstructions)({ repoRoot: TMP, path: "src/map" });
219
+ (0, vitest_1.expect)(report.results).toHaveLength(1);
220
+ (0, vitest_1.expect)(report.results[0]?.dir).toBe("src/map");
221
+ });
222
+ });
223
+ // ---------------------------------------------------------------------------
224
+ // getLastGitModDate / getFilesChangedAfter — graceful fallback
225
+ // ---------------------------------------------------------------------------
226
+ (0, vitest_1.describe)("getLastGitModDate", () => {
227
+ (0, vitest_1.it)("returns null for a non-existent path in a real repo (graceful)", () => {
228
+ const result = (0, validate_instructions_js_1.getLastGitModDate)("/tmp/nonexistent-file.md", "/tmp");
229
+ (0, vitest_1.expect)(result).toBeNull();
230
+ });
231
+ });
232
+ (0, vitest_1.describe)("getFilesChangedAfter", () => {
233
+ (0, vitest_1.it)("returns empty array when no files changed (graceful)", () => {
234
+ const futureDate = new Date(Date.now() + 1_000_000_000);
235
+ const result = (0, validate_instructions_js_1.getFilesChangedAfter)("/tmp", futureDate, "/tmp");
236
+ (0, vitest_1.expect)(result).toEqual([]);
237
+ });
238
+ });
@@ -0,0 +1,214 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.classifyArtifactPath = classifyArtifactPath;
7
+ exports.isPromotedArtifactPath = isPromotedArtifactPath;
8
+ exports.explainArtifactPolicy = explainArtifactPolicy;
9
+ exports.findArtifactPromotionViolations = findArtifactPromotionViolations;
10
+ exports.getArtifactPromotionPolicy = getArtifactPromotionPolicy;
11
+ exports.getArtifactPromotionStageTargets = getArtifactPromotionStageTargets;
12
+ exports.getGitignorePatterns = getGitignorePatterns;
13
+ exports.formatGitignoreBlock = formatGitignoreBlock;
14
+ exports.isPathBlockedFromStaging = isPathBlockedFromStaging;
15
+ exports.filterStageablePaths = filterStageablePaths;
16
+ const node_path_1 = __importDefault(require("node:path"));
17
+ const PROMOTED_RUN_LEDGER = ".polaris/runs/ledger.jsonl";
18
+ const PROMOTED_COGNITION_ARCHIVE_PREFIX = ".polaris/cognition/archive/";
19
+ const PROMOTED_MAP_PREFIX = ".polaris/map/";
20
+ const WORKSPACE_SCRATCH_PREFIX = ".taskchain_artifacts/";
21
+ const LEGACY_RUN_ARTIFACTS = new Set([
22
+ ".polaris/runs/mutation-queue.json",
23
+ ".polaris/runs/current-state.pre-pol-198.json",
24
+ ]);
25
+ function normalizeArtifactPath(filePath) {
26
+ const normalized = node_path_1.default.posix.normalize(filePath.replace(/\\/g, "/"));
27
+ return normalized.startsWith("./") ? normalized.slice(2) : normalized;
28
+ }
29
+ function getActiveClusterPrefix(activeClusterId) {
30
+ return `.polaris/clusters/${activeClusterId}/`;
31
+ }
32
+ function isPromotedClusterArtifact(relativePath, activeClusterId) {
33
+ const activeClusterPrefix = getActiveClusterPrefix(activeClusterId);
34
+ if (!relativePath.startsWith(activeClusterPrefix)) {
35
+ return false;
36
+ }
37
+ const suffix = relativePath.slice(activeClusterPrefix.length);
38
+ return (suffix === "clusters.json"
39
+ || suffix === "cluster-state.json"
40
+ || suffix.startsWith("packets/")
41
+ || suffix.startsWith("results/"));
42
+ }
43
+ function classifyArtifactPath(filePath, activeClusterId) {
44
+ const relativePath = normalizeArtifactPath(filePath);
45
+ if (relativePath.endsWith(".bak")) {
46
+ return "workspace-scratch";
47
+ }
48
+ if (!relativePath.startsWith(".polaris/") && !relativePath.startsWith(WORKSPACE_SCRATCH_PREFIX)) {
49
+ return "non-artifact";
50
+ }
51
+ if (relativePath.startsWith(WORKSPACE_SCRATCH_PREFIX)) {
52
+ return "workspace-scratch";
53
+ }
54
+ if (LEGACY_RUN_ARTIFACTS.has(relativePath) || relativePath.startsWith(".polaris/runs/evo-run-archive/")) {
55
+ return "legacy-run-artifact";
56
+ }
57
+ if (relativePath === PROMOTED_RUN_LEDGER) {
58
+ return "promoted-run-ledger";
59
+ }
60
+ if (relativePath.startsWith(PROMOTED_COGNITION_ARCHIVE_PREFIX)) {
61
+ return "promoted-cognition-archive";
62
+ }
63
+ if (relativePath.startsWith(PROMOTED_MAP_PREFIX)) {
64
+ return "promoted-map-artifact";
65
+ }
66
+ if (isPromotedClusterArtifact(relativePath, activeClusterId)) {
67
+ return "promoted-cluster-artifact";
68
+ }
69
+ if (relativePath.startsWith(".polaris/clusters/")) {
70
+ return "foreign-cluster-artifact";
71
+ }
72
+ if (relativePath.startsWith(".polaris/runs/")) {
73
+ return "legacy-run-artifact";
74
+ }
75
+ return "non-artifact";
76
+ }
77
+ function isPromotedArtifactPath(filePath, activeClusterId) {
78
+ const classification = classifyArtifactPath(filePath, activeClusterId);
79
+ return (classification === "promoted-cluster-artifact"
80
+ || classification === "promoted-run-ledger"
81
+ || classification === "promoted-cognition-archive"
82
+ || classification === "promoted-map-artifact");
83
+ }
84
+ function explainArtifactPolicy(filePath, activeClusterId) {
85
+ const relativePath = normalizeArtifactPath(filePath);
86
+ const classification = classifyArtifactPath(relativePath, activeClusterId);
87
+ switch (classification) {
88
+ case "promoted-cluster-artifact":
89
+ return "active cluster evidence is eligible for promotion into finalize commits";
90
+ case "promoted-run-ledger":
91
+ return "the run ledger is durable audit evidence and stays commit-eligible";
92
+ case "promoted-cognition-archive":
93
+ return "archived cognition reconciliation notes are durable provenance and stay commit-eligible";
94
+ case "promoted-map-artifact":
95
+ return "atlas outputs under .polaris/map/ are durable derived artifacts";
96
+ case "workspace-scratch":
97
+ return "workspace scratch under .taskchain_artifacts/ and backup files must never be promoted into delivery commits";
98
+ case "foreign-cluster-artifact":
99
+ return "only the active cluster's durable evidence may be promoted during finalize";
100
+ case "legacy-run-artifact":
101
+ return "legacy or workspace-run artifacts under .polaris/runs/ stay out of delivery commits unless explicitly promoted by newer policy";
102
+ case "non-artifact":
103
+ default:
104
+ return "this path is not a Polaris-managed artifact and should be evaluated by the normal source/document review flow";
105
+ }
106
+ }
107
+ function findArtifactPromotionViolations(stagedPaths, activeClusterId) {
108
+ const violations = [];
109
+ for (const stagedPath of stagedPaths) {
110
+ const relativePath = normalizeArtifactPath(stagedPath);
111
+ const classification = classifyArtifactPath(relativePath, activeClusterId);
112
+ if (classification === "non-artifact"
113
+ || classification === "promoted-cluster-artifact"
114
+ || classification === "promoted-run-ledger"
115
+ || classification === "promoted-cognition-archive"
116
+ || classification === "promoted-map-artifact") {
117
+ continue;
118
+ }
119
+ violations.push({
120
+ path: relativePath,
121
+ classification,
122
+ message: explainArtifactPolicy(relativePath, activeClusterId),
123
+ });
124
+ }
125
+ return violations;
126
+ }
127
+ function getArtifactPromotionPolicy(activeClusterId) {
128
+ const activeClusterPrefix = getActiveClusterPrefix(activeClusterId);
129
+ return {
130
+ promoted: [
131
+ `${activeClusterPrefix}clusters.json`,
132
+ `${activeClusterPrefix}cluster-state.json`,
133
+ `${activeClusterPrefix}packets/**`,
134
+ `${activeClusterPrefix}results/**`,
135
+ PROMOTED_RUN_LEDGER,
136
+ `${PROMOTED_COGNITION_ARCHIVE_PREFIX}**`,
137
+ `${PROMOTED_MAP_PREFIX}**`,
138
+ ],
139
+ blocked: [
140
+ `${WORKSPACE_SCRATCH_PREFIX}**`,
141
+ "*.bak",
142
+ ".polaris/runs/mutation-queue.json",
143
+ ".polaris/runs/current-state.pre-pol-198.json",
144
+ ".polaris/runs/evo-run-archive/**",
145
+ ".polaris/clusters/<other-cluster>/**",
146
+ ],
147
+ };
148
+ }
149
+ function getArtifactPromotionStageTargets(activeClusterId) {
150
+ return getArtifactPromotionPolicy(activeClusterId).promoted.map((pattern) => (pattern.endsWith("/**") ? pattern.slice(0, -3) : pattern));
151
+ }
152
+ /**
153
+ * Returns gitignore patterns for runtime and crash-recovery artifact classes.
154
+ * These patterns should be added to .gitignore to prevent accidental staging.
155
+ */
156
+ function getGitignorePatterns() {
157
+ return [
158
+ "# Polaris workspace scratch — never commit",
159
+ ".taskchain_artifacts/**",
160
+ "*.bak",
161
+ ".polaris/runs/mutation-queue.json",
162
+ ".polaris/runs/current-state.pre-pol-198.json",
163
+ ".polaris/runs/evo-run-archive/**",
164
+ ".polaris/bootstrap/**",
165
+ ".polaris/session-type",
166
+ "# Cognition staging — ephemeral, not committed",
167
+ ".polaris/cognition/pending/**",
168
+ ];
169
+ }
170
+ /**
171
+ * Formats gitignore patterns as a block suitable for appending to .gitignore.
172
+ */
173
+ function formatGitignoreBlock() {
174
+ return getGitignorePatterns().join("\n");
175
+ }
176
+ /**
177
+ * Returns true if the given path should be blocked from staging by adoption.
178
+ * This is a stricter check than promotion violations — it blocks all runtime/crash-recovery
179
+ * classes, not just violations during finalize.
180
+ */
181
+ function isPathBlockedFromStaging(filePath) {
182
+ const relativePath = normalizeArtifactPath(filePath);
183
+ // Block workspace scratch
184
+ if (relativePath.startsWith(WORKSPACE_SCRATCH_PREFIX)) {
185
+ return true;
186
+ }
187
+ // Block backup files
188
+ if (relativePath.endsWith(".bak")) {
189
+ return true;
190
+ }
191
+ // Block legacy run artifacts
192
+ if (LEGACY_RUN_ARTIFACTS.has(relativePath) || relativePath.startsWith(".polaris/runs/evo-run-archive/")) {
193
+ return true;
194
+ }
195
+ // Block runtime crash-recovery artifacts
196
+ if (relativePath === ".polaris/runs/mutation-queue.json" ||
197
+ relativePath === ".polaris/runs/current-state.pre-pol-198.json" ||
198
+ relativePath.startsWith(".polaris/bootstrap/") ||
199
+ relativePath === ".polaris/session-type") {
200
+ return true;
201
+ }
202
+ // Block cognition pending staging
203
+ if (relativePath.startsWith(".polaris/cognition/pending/")) {
204
+ return true;
205
+ }
206
+ return false;
207
+ }
208
+ /**
209
+ * Filters a list of paths to return only those that are safe to stage.
210
+ * This is used by adoption to ensure runtime artifacts are not staged.
211
+ */
212
+ function filterStageablePaths(paths) {
213
+ return paths.filter((path) => !isPathBlockedFromStaging(path));
214
+ }
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const artifact_policy_js_1 = require("./artifact-policy.js");
5
+ (0, vitest_1.describe)("artifact promotion policy", () => {
6
+ (0, vitest_1.it)("promotes only durable evidence for the active cluster", () => {
7
+ (0, vitest_1.expect)((0, artifact_policy_js_1.isPromotedArtifactPath)(".polaris/clusters/POL-242/clusters.json", "POL-242")).toBe(true);
8
+ (0, vitest_1.expect)((0, artifact_policy_js_1.isPromotedArtifactPath)(".polaris/clusters/POL-242/cluster-state.json", "POL-242")).toBe(true);
9
+ (0, vitest_1.expect)((0, artifact_policy_js_1.isPromotedArtifactPath)(".polaris/clusters/POL-242/packets/worker.json", "POL-242")).toBe(true);
10
+ (0, vitest_1.expect)((0, artifact_policy_js_1.isPromotedArtifactPath)(".polaris/clusters/POL-242/results/worker.json", "POL-242")).toBe(true);
11
+ (0, vitest_1.expect)((0, artifact_policy_js_1.isPromotedArtifactPath)(".polaris/runs/ledger.jsonl", "POL-242")).toBe(true);
12
+ (0, vitest_1.expect)((0, artifact_policy_js_1.isPromotedArtifactPath)(".polaris/cognition/archive/src/loop/cognition-index.json", "POL-242")).toBe(true);
13
+ (0, vitest_1.expect)((0, artifact_policy_js_1.isPromotedArtifactPath)(".polaris/map/file-routes.json", "POL-242")).toBe(true);
14
+ });
15
+ (0, vitest_1.it)("flags workspace scratch, legacy run files, and foreign cluster evidence", () => {
16
+ (0, vitest_1.expect)((0, artifact_policy_js_1.classifyArtifactPath)(".taskchain_artifacts/polaris-run/current-state.json", "POL-242")).toBe("workspace-scratch");
17
+ (0, vitest_1.expect)((0, artifact_policy_js_1.classifyArtifactPath)(".taskchain_artifacts/polaris-run/runs/run-1/telemetry.jsonl", "POL-242")).toBe("workspace-scratch");
18
+ (0, vitest_1.expect)((0, artifact_policy_js_1.classifyArtifactPath)(".polaris/runs/mutation-queue.json", "POL-242")).toBe("legacy-run-artifact");
19
+ (0, vitest_1.expect)((0, artifact_policy_js_1.classifyArtifactPath)(".polaris/clusters/POL-240/cluster-state.json", "POL-242")).toBe("foreign-cluster-artifact");
20
+ (0, vitest_1.expect)((0, artifact_policy_js_1.classifyArtifactPath)("src/finalize/steps/06-commit.ts", "POL-242")).toBe("non-artifact");
21
+ });
22
+ (0, vitest_1.it)("reports actionable commit-hygiene violations without blocking non-artifact files", () => {
23
+ (0, vitest_1.expect)((0, artifact_policy_js_1.findArtifactPromotionViolations)([
24
+ "src/finalize/index.ts",
25
+ ".taskchain_artifacts/polaris-run/current-state.json",
26
+ ".polaris/runs/mutation-queue.json",
27
+ ".polaris/clusters/POL-240/results/POL-240.json",
28
+ ".taskchain_artifacts/polaris-run/current-state.json.backup.bak",
29
+ ], "POL-242")).toEqual([
30
+ {
31
+ path: ".taskchain_artifacts/polaris-run/current-state.json",
32
+ classification: "workspace-scratch",
33
+ message: (0, artifact_policy_js_1.explainArtifactPolicy)(".taskchain_artifacts/polaris-run/current-state.json", "POL-242"),
34
+ },
35
+ {
36
+ path: ".polaris/runs/mutation-queue.json",
37
+ classification: "legacy-run-artifact",
38
+ message: (0, artifact_policy_js_1.explainArtifactPolicy)(".polaris/runs/mutation-queue.json", "POL-242"),
39
+ },
40
+ {
41
+ path: ".polaris/clusters/POL-240/results/POL-240.json",
42
+ classification: "foreign-cluster-artifact",
43
+ message: (0, artifact_policy_js_1.explainArtifactPolicy)(".polaris/clusters/POL-240/results/POL-240.json", "POL-242"),
44
+ },
45
+ {
46
+ path: ".taskchain_artifacts/polaris-run/current-state.json.backup.bak",
47
+ classification: "workspace-scratch",
48
+ message: (0, artifact_policy_js_1.explainArtifactPolicy)(".taskchain_artifacts/polaris-run/current-state.json.backup.bak", "POL-242"),
49
+ },
50
+ ]);
51
+ });
52
+ (0, vitest_1.it)("exposes promoted and blocked policy patterns for finalize consumers", () => {
53
+ (0, vitest_1.expect)((0, artifact_policy_js_1.getArtifactPromotionPolicy)("POL-242")).toEqual({
54
+ promoted: [
55
+ ".polaris/clusters/POL-242/clusters.json",
56
+ ".polaris/clusters/POL-242/cluster-state.json",
57
+ ".polaris/clusters/POL-242/packets/**",
58
+ ".polaris/clusters/POL-242/results/**",
59
+ ".polaris/runs/ledger.jsonl",
60
+ ".polaris/cognition/archive/**",
61
+ ".polaris/map/**",
62
+ ],
63
+ blocked: [
64
+ ".taskchain_artifacts/**",
65
+ "*.bak",
66
+ ".polaris/runs/mutation-queue.json",
67
+ ".polaris/runs/current-state.pre-pol-198.json",
68
+ ".polaris/runs/evo-run-archive/**",
69
+ ".polaris/clusters/<other-cluster>/**",
70
+ ],
71
+ });
72
+ });
73
+ (0, vitest_1.it)("derives git-add stage targets from promoted policy patterns", () => {
74
+ (0, vitest_1.expect)((0, artifact_policy_js_1.getArtifactPromotionStageTargets)("POL-242")).toEqual([
75
+ ".polaris/clusters/POL-242/clusters.json",
76
+ ".polaris/clusters/POL-242/cluster-state.json",
77
+ ".polaris/clusters/POL-242/packets",
78
+ ".polaris/clusters/POL-242/results",
79
+ ".polaris/runs/ledger.jsonl",
80
+ ".polaris/cognition/archive",
81
+ ".polaris/map",
82
+ ]);
83
+ });
84
+ });