@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,109 @@
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 node_os_1 = require("node:os");
7
+ const dispatch_result_js_1 = require("./dispatch-result.js");
8
+ const originalCwd = process.cwd();
9
+ function makeTempRepo() {
10
+ return (0, node_path_1.join)((0, node_os_1.tmpdir)(), `polaris-dispatch-result-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
11
+ }
12
+ function writeState(repoRoot, artifactDir, state) {
13
+ const dir = (0, node_path_1.join)(repoRoot, ".taskchain_artifacts", artifactDir);
14
+ (0, node_fs_1.mkdirSync)(dir, { recursive: true });
15
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(dir, "current-state.json"), JSON.stringify(state, null, 2) + "\n", "utf-8");
16
+ }
17
+ function readState(repoRoot, artifactDir) {
18
+ return JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(repoRoot, ".taskchain_artifacts", artifactDir, "current-state.json"), "utf-8"));
19
+ }
20
+ (0, vitest_1.describe)("handlePolarisDispatchResult()", () => {
21
+ let repoRoot;
22
+ (0, vitest_1.beforeEach)(() => {
23
+ repoRoot = makeTempRepo();
24
+ (0, node_fs_1.mkdirSync)(repoRoot, { recursive: true });
25
+ process.chdir(repoRoot);
26
+ });
27
+ (0, vitest_1.afterEach)(() => {
28
+ process.chdir(originalCwd);
29
+ (0, node_fs_1.rmSync)(repoRoot, { recursive: true, force: true });
30
+ });
31
+ (0, vitest_1.it)("records a matching active_child result in state and telemetry", async () => {
32
+ writeState(repoRoot, "polaris-run", {
33
+ schema_version: "1.0",
34
+ run_id: "run-result",
35
+ cluster_id: "POL-105",
36
+ active_child: "POL-111",
37
+ open_children: ["POL-111", "POL-112"],
38
+ completed_children: ["POL-110"],
39
+ open_children_meta: {
40
+ "POL-111": { title: "Add MCP tools", status: "Backlog" },
41
+ "POL-112": { title: "Smoke test", status: "Backlog" },
42
+ },
43
+ context_budget: { children_completed: 5 },
44
+ status: "running",
45
+ step_cursor: "04-execute-child",
46
+ });
47
+ const result = await (0, dispatch_result_js_1.handlePolarisDispatchResult)({
48
+ child_id: "POL-111",
49
+ status: "completed",
50
+ commit: "abc1234",
51
+ validation: ["npm test -- src/mcp/tools/claim-child.test.ts src/mcp/tools/dispatch-result.test.ts"],
52
+ });
53
+ (0, vitest_1.expect)(result["ok"]).toBe(true);
54
+ const state = readState(repoRoot, "polaris-run");
55
+ (0, vitest_1.expect)(state["active_child"]).toBeNull();
56
+ (0, vitest_1.expect)(state["completed_children"]).toEqual(["POL-110", "POL-111"]);
57
+ (0, vitest_1.expect)(state["open_children"]).toEqual(["POL-112"]);
58
+ (0, vitest_1.expect)(state["next_open_child"]).toBe("POL-112");
59
+ (0, vitest_1.expect)(state["last_commit"]).toBe("abc1234");
60
+ (0, vitest_1.expect)(state["last_worker_result"]["child_id"]).toBe("POL-111");
61
+ const telemetry = (0, node_fs_1.readFileSync)((0, node_path_1.join)(repoRoot, ".taskchain_artifacts", "polaris-run", "runs", "run-result", "telemetry.jsonl"), "utf-8");
62
+ (0, vitest_1.expect)(telemetry).toContain("\"event\":\"mcp-dispatch-result\"");
63
+ (0, vitest_1.expect)(telemetry).toContain("\"commit\":\"abc1234\"");
64
+ });
65
+ (0, vitest_1.it)("returns error when run_id is missing from state", async () => {
66
+ writeState(repoRoot, "polaris-run", {
67
+ schema_version: "1.0",
68
+ cluster_id: "POL-105",
69
+ active_child: "POL-111",
70
+ open_children: ["POL-111"],
71
+ completed_children: [],
72
+ status: "running",
73
+ step_cursor: "04-execute-child",
74
+ });
75
+ const result = await (0, dispatch_result_js_1.handlePolarisDispatchResult)({
76
+ child_id: "POL-111",
77
+ status: "completed",
78
+ commit: "abc1234",
79
+ validation: "passed",
80
+ });
81
+ (0, vitest_1.expect)(result["ok"]).toBe(false);
82
+ (0, vitest_1.expect)(result["error"]).toBe("invalid_run_id");
83
+ (0, vitest_1.expect)(typeof result["message"]).toBe("string");
84
+ (0, vitest_1.expect)(result["message"]).toContain("run_id");
85
+ });
86
+ (0, vitest_1.it)("returns active_child_mismatch when the result does not match active_child", async () => {
87
+ writeState(repoRoot, "polaris-run", {
88
+ schema_version: "1.0",
89
+ run_id: "run-result",
90
+ cluster_id: "POL-105",
91
+ active_child: "POL-110",
92
+ open_children: ["POL-111"],
93
+ completed_children: [],
94
+ context_budget: { children_completed: 0 },
95
+ status: "running",
96
+ step_cursor: "04-execute-child",
97
+ });
98
+ const result = await (0, dispatch_result_js_1.handlePolarisDispatchResult)({
99
+ child_id: "POL-111",
100
+ status: "completed",
101
+ commit: "abc1234",
102
+ validation: "passed",
103
+ });
104
+ (0, vitest_1.expect)(result["ok"]).toBe(false);
105
+ (0, vitest_1.expect)(result["error"]).toBe("active_child_mismatch");
106
+ (0, vitest_1.expect)(result["expected"]).toBe("POL-110");
107
+ (0, vitest_1.expect)(readState(repoRoot, "polaris-run")["active_child"]).toBe("POL-110");
108
+ });
109
+ });
@@ -0,0 +1,222 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TOOLS = void 0;
4
+ exports.dispatchTool = dispatchTool;
5
+ const status_js_1 = require("./status.js");
6
+ const current_state_js_1 = require("./current-state.js");
7
+ const loop_dry_run_js_1 = require("./loop-dry-run.js");
8
+ const loop_continue_js_1 = require("./loop-continue.js");
9
+ const claim_child_js_1 = require("./claim-child.js");
10
+ const dispatch_result_js_1 = require("./dispatch-result.js");
11
+ const linear_js_1 = require("./linear.js");
12
+ exports.TOOLS = [
13
+ ...linear_js_1.LINEAR_TOOLS, // Add Linear tools here
14
+ {
15
+ name: "polaris_status",
16
+ description: "Return the current Polaris loop run state. Calls `polaris status --json` and returns compact structured output.",
17
+ inputSchema: {
18
+ type: "object",
19
+ properties: {},
20
+ required: [],
21
+ },
22
+ },
23
+ {
24
+ name: "polaris_loop_status",
25
+ description: "Return the current Polaris loop status, scoped to the loop subsystem. Calls `polaris loop status --json`.",
26
+ inputSchema: {
27
+ type: "object",
28
+ properties: {},
29
+ required: [],
30
+ },
31
+ },
32
+ {
33
+ name: "polaris_current_state",
34
+ description: "Return the raw parsed current-state.json for a Polaris artifact directory, with sensitive keys redacted.",
35
+ inputSchema: {
36
+ type: "object",
37
+ properties: {
38
+ artifact_dir: {
39
+ type: "string",
40
+ description: "Artifact directory name under .taskchain_artifacts/. Default: polaris-run",
41
+ },
42
+ },
43
+ required: [],
44
+ },
45
+ },
46
+ {
47
+ name: "polaris_loop_continue_dry_run",
48
+ description: "Preview what loop continue would do — returns eligibility status and approval template without mutating any state. Dry-run only: no bootstrap packets, no worker dispatch, no execution leases.",
49
+ inputSchema: {
50
+ type: "object",
51
+ properties: {
52
+ artifact_dir: {
53
+ type: "string",
54
+ description: "Artifact directory name under .taskchain_artifacts/. Default: polaris-run",
55
+ },
56
+ expected_step_cursor: {
57
+ type: "string",
58
+ description: "Expected current step cursor (e.g. '06-decide-continuation')",
59
+ },
60
+ },
61
+ required: ["expected_step_cursor"],
62
+ },
63
+ },
64
+ {
65
+ name: "polaris_loop_continue_confirmed",
66
+ description: "Submit a pre-approved continuation envelope to gate a loop continue action. Requires a valid ContinuationApprovalEnvelope from a prior dry-run call. Does not dispatch workers — returns approval status only.",
67
+ inputSchema: {
68
+ type: "object",
69
+ properties: {
70
+ artifact_dir: {
71
+ type: "string",
72
+ description: "Artifact directory name under .taskchain_artifacts/. Default: polaris-run",
73
+ },
74
+ run_id: {
75
+ type: "string",
76
+ description: "Run ID from the approval envelope",
77
+ },
78
+ expected_step_cursor: {
79
+ type: "string",
80
+ description: "Expected step cursor from the approval envelope",
81
+ },
82
+ fingerprint: {
83
+ type: "string",
84
+ description: "State fingerprint from the approval envelope",
85
+ },
86
+ runtime_generation: {
87
+ type: "number",
88
+ description: "Runtime generation counter from the approval envelope",
89
+ },
90
+ issued_at: {
91
+ type: "string",
92
+ description: "ISO 8601 timestamp when the envelope was issued",
93
+ },
94
+ expires_at: {
95
+ type: "string",
96
+ description: "ISO 8601 timestamp when the envelope expires",
97
+ },
98
+ nonce: {
99
+ type: "string",
100
+ description: "Unique nonce from the approval envelope",
101
+ },
102
+ requested_action: {
103
+ type: "string",
104
+ description: 'Must be "loop_continue"',
105
+ },
106
+ },
107
+ required: [
108
+ "run_id",
109
+ "expected_step_cursor",
110
+ "fingerprint",
111
+ "runtime_generation",
112
+ "issued_at",
113
+ "expires_at",
114
+ "nonce",
115
+ "requested_action",
116
+ ],
117
+ },
118
+ },
119
+ {
120
+ name: "polaris_claim_child",
121
+ description: "Atomically claim an open Polaris child issue by writing active_child in current-state.json. Mutates run state and appends telemetry.",
122
+ inputSchema: {
123
+ type: "object",
124
+ properties: {
125
+ artifact_dir: {
126
+ type: "string",
127
+ description: "Artifact directory name under .taskchain_artifacts/. Default: polaris-run",
128
+ },
129
+ child_id: {
130
+ type: "string",
131
+ description: "Open child issue ID to claim, e.g. POL-111",
132
+ },
133
+ },
134
+ required: ["child_id"],
135
+ },
136
+ annotations: {
137
+ readOnlyHint: false,
138
+ destructiveHint: false,
139
+ idempotentHint: false,
140
+ openWorldHint: false,
141
+ },
142
+ },
143
+ {
144
+ name: "polaris_dispatch_result",
145
+ description: "Record a Polaris worker result for the matching active_child in current-state.json and append dispatch-result telemetry.",
146
+ inputSchema: {
147
+ type: "object",
148
+ properties: {
149
+ artifact_dir: {
150
+ type: "string",
151
+ description: "Artifact directory name under .taskchain_artifacts/. Default: polaris-run",
152
+ },
153
+ child_id: {
154
+ type: "string",
155
+ description: "Active child issue ID whose result is being recorded",
156
+ },
157
+ status: {
158
+ type: "string",
159
+ description: "Worker status, such as completed, failed, or blocked",
160
+ },
161
+ commit: {
162
+ type: "string",
163
+ description: "Commit hash produced by the worker, when available",
164
+ },
165
+ validation: {
166
+ description: "Validation summary or structured validation evidence from the worker",
167
+ },
168
+ },
169
+ required: ["child_id", "status"],
170
+ },
171
+ annotations: {
172
+ readOnlyHint: false,
173
+ destructiveHint: false,
174
+ idempotentHint: false,
175
+ openWorldHint: false,
176
+ },
177
+ },
178
+ ];
179
+ const REGISTERED = new Set(exports.TOOLS.map((t) => t.name));
180
+ async function dispatchTool(name, args) {
181
+ if (!REGISTERED.has(name)) {
182
+ const result = {
183
+ ok: false,
184
+ error: "unknown_tool",
185
+ message: `Unknown tool: ${name}`,
186
+ };
187
+ return { content: [{ type: "text", text: JSON.stringify(result) }] };
188
+ }
189
+ let result;
190
+ switch (name) {
191
+ case "polaris_status":
192
+ result = await (0, status_js_1.handlePolarisStatus)();
193
+ break;
194
+ case "polaris_loop_status":
195
+ result = await (0, status_js_1.handlePolarisLoopStatus)();
196
+ break;
197
+ case "polaris_current_state":
198
+ result = await (0, current_state_js_1.handlePolarisCurrentState)(args);
199
+ break;
200
+ case "polaris_loop_continue_dry_run":
201
+ result = await (0, loop_dry_run_js_1.handleLoopContinueDryRun)(args);
202
+ break;
203
+ case "polaris_loop_continue_confirmed":
204
+ result = await (0, loop_continue_js_1.handleLoopContinueConfirmed)(args);
205
+ break;
206
+ case "polaris_claim_child":
207
+ result = await (0, claim_child_js_1.handlePolarisClaimChild)(args);
208
+ break;
209
+ case "polaris_dispatch_result":
210
+ result = await (0, dispatch_result_js_1.handlePolarisDispatchResult)(args);
211
+ break;
212
+ case "linear_list_issues":
213
+ result = await (0, linear_js_1.handleLinearListIssues)(args);
214
+ break;
215
+ case "linear_save_issue":
216
+ result = await (0, linear_js_1.handleLinearSaveIssue)(args);
217
+ break;
218
+ default:
219
+ result = { ok: false, error: "unknown_tool", message: `Unhandled tool: ${name}` };
220
+ }
221
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
222
+ }
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ /**
3
+ * Unit tests for src/mcp/tools/index.ts
4
+ *
5
+ * Covers:
6
+ * - dispatchTool() returns unknown_tool error for unregistered tool name
7
+ * - TOOLS array contains the expected tools
8
+ * - dispatchTool() result has content array with a text item containing valid JSON
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ const vitest_1 = require("vitest");
12
+ // Mock the handler modules before importing index.ts
13
+ vitest_1.vi.mock("./status.js", () => ({
14
+ handlePolarisStatus: vitest_1.vi.fn().mockResolvedValue({ ok: true, status: "running" }),
15
+ handlePolarisLoopStatus: vitest_1.vi.fn().mockResolvedValue({ ok: true, status: "idle" }),
16
+ }));
17
+ vitest_1.vi.mock("./current-state.js", () => ({
18
+ handlePolarisCurrentState: vitest_1.vi.fn().mockResolvedValue({
19
+ ok: true,
20
+ artifact_dir: "polaris-run",
21
+ state: { run_id: "test-run" },
22
+ }),
23
+ }));
24
+ vitest_1.vi.mock("./loop-dry-run.js", () => ({
25
+ handleLoopContinueDryRun: vitest_1.vi.fn().mockResolvedValue({ ok: true, eligible: true }),
26
+ }));
27
+ vitest_1.vi.mock("./loop-continue.js", () => ({
28
+ handleLoopContinueConfirmed: vitest_1.vi.fn().mockResolvedValue({
29
+ ok: true,
30
+ next_child: "POL-85",
31
+ message: "Continuation approved. Worker dispatch is not yet implemented.",
32
+ }),
33
+ }));
34
+ vitest_1.vi.mock("./linear.js", () => ({
35
+ LINEAR_TOOLS: [
36
+ { name: "linear_list_issues", description: "List Linear issues", inputSchema: { type: "object", properties: {}, required: [] } },
37
+ { name: "linear_save_issue", description: "Save a Linear issue", inputSchema: { type: "object", properties: {}, required: [] } },
38
+ ],
39
+ handleLinearListIssues: vitest_1.vi.fn().mockResolvedValue({ ok: true, issues: [] }),
40
+ handleLinearSaveIssue: vitest_1.vi.fn().mockResolvedValue({ ok: true }),
41
+ }));
42
+ const index_js_1 = require("./index.js");
43
+ const status_js_1 = require("./status.js");
44
+ const current_state_js_1 = require("./current-state.js");
45
+ const loop_continue_js_1 = require("./loop-continue.js");
46
+ const mockHandlePolarisStatus = vitest_1.vi.mocked(status_js_1.handlePolarisStatus);
47
+ const mockHandlePolarisLoopStatus = vitest_1.vi.mocked(status_js_1.handlePolarisLoopStatus);
48
+ const mockHandlePolarisCurrentState = vitest_1.vi.mocked(current_state_js_1.handlePolarisCurrentState);
49
+ const mockHandleLoopContinueConfirmed = vitest_1.vi.mocked(loop_continue_js_1.handleLoopContinueConfirmed);
50
+ (0, vitest_1.describe)("TOOLS array", () => {
51
+ (0, vitest_1.it)("has exactly 9 tools", () => {
52
+ (0, vitest_1.expect)(index_js_1.TOOLS).toHaveLength(9);
53
+ });
54
+ (0, vitest_1.it)("contains polaris_status", () => {
55
+ const names = index_js_1.TOOLS.map((t) => t.name);
56
+ (0, vitest_1.expect)(names).toContain("polaris_status");
57
+ });
58
+ (0, vitest_1.it)("contains polaris_loop_status", () => {
59
+ const names = index_js_1.TOOLS.map((t) => t.name);
60
+ (0, vitest_1.expect)(names).toContain("polaris_loop_status");
61
+ });
62
+ (0, vitest_1.it)("contains polaris_current_state", () => {
63
+ const names = index_js_1.TOOLS.map((t) => t.name);
64
+ (0, vitest_1.expect)(names).toContain("polaris_current_state");
65
+ });
66
+ (0, vitest_1.it)("contains polaris_loop_continue_dry_run", () => {
67
+ const names = index_js_1.TOOLS.map((t) => t.name);
68
+ (0, vitest_1.expect)(names).toContain("polaris_loop_continue_dry_run");
69
+ });
70
+ (0, vitest_1.it)("contains polaris_loop_continue_confirmed", () => {
71
+ const names = index_js_1.TOOLS.map((t) => t.name);
72
+ (0, vitest_1.expect)(names).toContain("polaris_loop_continue_confirmed");
73
+ });
74
+ (0, vitest_1.it)("has the exact set of tools", () => {
75
+ const names = index_js_1.TOOLS.map((t) => t.name).sort();
76
+ (0, vitest_1.expect)(names).toEqual([
77
+ "linear_list_issues",
78
+ "linear_save_issue",
79
+ "polaris_claim_child",
80
+ "polaris_current_state",
81
+ "polaris_dispatch_result",
82
+ "polaris_loop_continue_confirmed",
83
+ "polaris_loop_continue_dry_run",
84
+ "polaris_loop_status",
85
+ "polaris_status",
86
+ ]);
87
+ });
88
+ });
89
+ (0, vitest_1.describe)("dispatchTool()", () => {
90
+ (0, vitest_1.beforeEach)(() => {
91
+ vitest_1.vi.clearAllMocks();
92
+ });
93
+ (0, vitest_1.it)("returns an unknown_tool error for an unregistered tool name", async () => {
94
+ const response = await (0, index_js_1.dispatchTool)("nonexistent_tool", {});
95
+ (0, vitest_1.expect)(response.content).toHaveLength(1);
96
+ (0, vitest_1.expect)(response.content[0]?.type).toBe("text");
97
+ const parsed = JSON.parse(response.content[0].text);
98
+ (0, vitest_1.expect)(parsed["ok"]).toBe(false);
99
+ (0, vitest_1.expect)(parsed["error"]).toBe("unknown_tool");
100
+ });
101
+ (0, vitest_1.it)("result has a content array with at least one item", async () => {
102
+ const response = await (0, index_js_1.dispatchTool)("polaris_status", {});
103
+ (0, vitest_1.expect)(Array.isArray(response.content)).toBe(true);
104
+ (0, vitest_1.expect)(response.content.length).toBeGreaterThan(0);
105
+ });
106
+ (0, vitest_1.it)("result content item has type 'text'", async () => {
107
+ const response = await (0, index_js_1.dispatchTool)("polaris_status", {});
108
+ (0, vitest_1.expect)(response.content[0]?.type).toBe("text");
109
+ });
110
+ (0, vitest_1.it)("result content text item contains valid JSON", async () => {
111
+ const response = await (0, index_js_1.dispatchTool)("polaris_status", {});
112
+ (0, vitest_1.expect)(() => JSON.parse(response.content[0].text)).not.toThrow();
113
+ });
114
+ (0, vitest_1.it)("dispatches polaris_status to handlePolarisStatus", async () => {
115
+ mockHandlePolarisStatus.mockResolvedValue({ ok: true, run_id: "pol-test" });
116
+ const response = await (0, index_js_1.dispatchTool)("polaris_status", {});
117
+ (0, vitest_1.expect)(mockHandlePolarisStatus).toHaveBeenCalledOnce();
118
+ const parsed = JSON.parse(response.content[0].text);
119
+ (0, vitest_1.expect)(parsed["ok"]).toBe(true);
120
+ (0, vitest_1.expect)(parsed["run_id"]).toBe("pol-test");
121
+ });
122
+ (0, vitest_1.it)("dispatches polaris_loop_status to handlePolarisLoopStatus", async () => {
123
+ mockHandlePolarisLoopStatus.mockResolvedValue({ ok: true, status: "loop-running" });
124
+ const response = await (0, index_js_1.dispatchTool)("polaris_loop_status", {});
125
+ (0, vitest_1.expect)(mockHandlePolarisLoopStatus).toHaveBeenCalledOnce();
126
+ const parsed = JSON.parse(response.content[0].text);
127
+ (0, vitest_1.expect)(parsed["ok"]).toBe(true);
128
+ (0, vitest_1.expect)(parsed["status"]).toBe("loop-running");
129
+ });
130
+ (0, vitest_1.it)("dispatches polaris_current_state to handlePolarisCurrentState", async () => {
131
+ mockHandlePolarisCurrentState.mockResolvedValue({
132
+ ok: true,
133
+ artifact_dir: "polaris-run",
134
+ state: { run_id: "state-test" },
135
+ });
136
+ const response = await (0, index_js_1.dispatchTool)("polaris_current_state", { artifact_dir: "polaris-run" });
137
+ (0, vitest_1.expect)(mockHandlePolarisCurrentState).toHaveBeenCalledOnce();
138
+ (0, vitest_1.expect)(mockHandlePolarisCurrentState).toHaveBeenCalledWith({ artifact_dir: "polaris-run" });
139
+ const parsed = JSON.parse(response.content[0].text);
140
+ (0, vitest_1.expect)(parsed["ok"]).toBe(true);
141
+ (0, vitest_1.expect)(parsed["artifact_dir"]).toBe("polaris-run");
142
+ });
143
+ (0, vitest_1.it)("dispatches polaris_loop_continue_confirmed to handleLoopContinueConfirmed", async () => {
144
+ mockHandleLoopContinueConfirmed.mockResolvedValue({
145
+ ok: true,
146
+ next_child: "POL-85",
147
+ message: "Continuation approved. Worker dispatch is not yet implemented.",
148
+ });
149
+ const envelopeArgs = {
150
+ artifact_dir: "bootstrap-run",
151
+ run_id: "run-123",
152
+ expected_step_cursor: "06-decide-continuation",
153
+ fingerprint: "abc123",
154
+ runtime_generation: 1,
155
+ issued_at: "2026-05-25T00:00:00.000Z",
156
+ expires_at: "2026-05-25T01:00:00.000Z",
157
+ nonce: "nonce-xyz",
158
+ requested_action: "loop_continue",
159
+ };
160
+ const response = await (0, index_js_1.dispatchTool)("polaris_loop_continue_confirmed", envelopeArgs);
161
+ (0, vitest_1.expect)(mockHandleLoopContinueConfirmed).toHaveBeenCalledOnce();
162
+ (0, vitest_1.expect)(mockHandleLoopContinueConfirmed).toHaveBeenCalledWith(envelopeArgs);
163
+ const parsed = JSON.parse(response.content[0].text);
164
+ (0, vitest_1.expect)(parsed["ok"]).toBe(true);
165
+ (0, vitest_1.expect)(parsed["next_child"]).toBe("POL-85");
166
+ });
167
+ (0, vitest_1.it)("unknown_tool error message includes the tool name", async () => {
168
+ const response = await (0, index_js_1.dispatchTool)("made_up_tool", {});
169
+ const parsed = JSON.parse(response.content[0].text);
170
+ (0, vitest_1.expect)(parsed["message"]).toContain("made_up_tool");
171
+ });
172
+ });
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LINEAR_TOOLS = void 0;
4
+ exports.handleLinearListIssues = handleLinearListIssues;
5
+ exports.handleLinearSaveIssue = handleLinearSaveIssue;
6
+ async function loadLinearTools() {
7
+ return import("@tool-server/linear");
8
+ }
9
+ // Handler for listing Linear issues
10
+ async function handleLinearListIssues(args) {
11
+ try {
12
+ const { mcp_linear_list_issues } = await loadLinearTools();
13
+ const issues = await mcp_linear_list_issues({
14
+ team: args.team,
15
+ project: args.project,
16
+ assignee: args.assignee,
17
+ query: args.query,
18
+ });
19
+ return { ok: true, data: issues };
20
+ }
21
+ catch (error) {
22
+ return { ok: false, error: error instanceof Error ? error.message : String(error) };
23
+ }
24
+ }
25
+ // Handler for creating/updating Linear issues
26
+ async function handleLinearSaveIssue(args) {
27
+ try {
28
+ const { mcp_linear_save_issue } = await loadLinearTools();
29
+ const issue = await mcp_linear_save_issue(args);
30
+ return { ok: true, data: issue };
31
+ }
32
+ catch (error) {
33
+ return { ok: false, error: error instanceof Error ? error.message : String(error) };
34
+ }
35
+ }
36
+ exports.LINEAR_TOOLS = [
37
+ {
38
+ name: "linear_list_issues",
39
+ description: "List issues in Linear, with optional filters.",
40
+ inputSchema: {
41
+ type: "object",
42
+ properties: {
43
+ team: { type: "string", description: "Filter by team name or ID" },
44
+ project: { type: "string", description: "Filter by project name, ID, or slug" },
45
+ assignee: { type: "string", description: "Filter by assignee (user ID, name, email, or 'me')" },
46
+ query: { type: "string", description: "Search issue title or description" },
47
+ },
48
+ },
49
+ },
50
+ {
51
+ name: "linear_save_issue",
52
+ description: "Create or update a Linear issue.",
53
+ inputSchema: {
54
+ type: "object",
55
+ properties: {
56
+ id: { type: "string", description: "Issue ID for updating an existing issue" },
57
+ title: { type: "string", description: "Issue title (required when creating)" },
58
+ team: { type: "string", description: "Team name or ID (required when creating)" },
59
+ description: { type: "string", description: "Issue description as Markdown" },
60
+ project: { type: "string", description: "Project name, ID, or slug" },
61
+ assignee: { type: "string", description: "User ID, name, email, or 'me'" },
62
+ status: { type: "string", description: "State type, name, or ID" },
63
+ priority: { type: "number", description: "0=None, 1=Urgent, 2=High, 3=Medium, 4=Low" },
64
+ labels: { type: "array", items: { type: "string" }, description: "Label names or IDs" },
65
+ parentId: { type: "string", description: "Parent issue ID" },
66
+ blockedBy: { type: "array", items: { type: "string" }, description: "Issue IDs blocking this" },
67
+ blocks: { type: "array", items: { type: "string" }, description: "Issue IDs this blocks" },
68
+ relatedTo: { type: "array", items: { type: "string" }, description: "Related issue IDs" },
69
+ dueDate: { type: "string", format: "date", description: "Due date (ISO format)" },
70
+ },
71
+ oneOf: [{ required: ["id"] }, { required: ["title", "team"] }],
72
+ },
73
+ },
74
+ ];