@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,358 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createGraphCommand = createGraphCommand;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const commander_1 = require("commander");
7
+ const loader_js_1 = require("../config/loader.js");
8
+ const pipeline_js_1 = require("../graph/parser/pipeline.js");
9
+ const index_js_1 = require("../graph/query/index.js");
10
+ const index_js_2 = require("../graph/resolver/index.js");
11
+ const adapter_js_1 = require("../graph/store/adapter.js");
12
+ function createGraphCommand(options) {
13
+ const graphCommand = new commander_1.Command("graph")
14
+ .description("Build and inspect the repository function graph")
15
+ .showHelpAfterError()
16
+ .showSuggestionAfterError();
17
+ graphCommand.action(() => failMissingSubcommand(graphCommand, "polaris graph"));
18
+ graphCommand
19
+ .command("build")
20
+ .description("Build graph artifacts from configured source roots")
21
+ .option("-r, --repo-root <path>", "Repository root", options.repoRoot)
22
+ .option("--dry-run", "Print the build plan and skip writes")
23
+ .option("--json", "Emit JSON output")
24
+ .action(async (commandOptions) => {
25
+ const repoRoot = (0, node_path_1.resolve)(commandOptions.repoRoot ?? options.repoRoot);
26
+ const dryRun = commandOptions.dryRun ?? false;
27
+ const json = commandOptions.json ?? false;
28
+ const plan = createBuildPlan(repoRoot);
29
+ if (dryRun) {
30
+ const output = {
31
+ mode: "dry-run",
32
+ ...plan,
33
+ };
34
+ if (json) {
35
+ console.log(JSON.stringify(output, null, 2));
36
+ }
37
+ else {
38
+ printBuildPlan(output);
39
+ }
40
+ return;
41
+ }
42
+ const store = new adapter_js_1.GraphStoreAdapter({
43
+ repoRoot,
44
+ graphOutputPath: plan.outputPathRelative,
45
+ dbPath: plan.dbPathRelative,
46
+ });
47
+ try {
48
+ store.open();
49
+ const extraction = await (0, pipeline_js_1.runExtractionPipeline)(plan.sourceFiles, {
50
+ graphStore: store,
51
+ logger: { warn: (message) => process.stderr.write(`${message}\n`) },
52
+ });
53
+ const resolver = (0, index_js_2.runGraphResolver)({ graphStore: store });
54
+ const output = {
55
+ mode: "build",
56
+ outputPath: plan.outputPathAbsolute,
57
+ dbPath: plan.dbPathAbsolute,
58
+ sourceRoots: plan.sourceRootsAbsolute,
59
+ sourceFileCount: plan.sourceFiles.length,
60
+ extraction,
61
+ resolver,
62
+ };
63
+ if (json) {
64
+ console.log(JSON.stringify(output, null, 2));
65
+ }
66
+ else {
67
+ printBuildSummary(output);
68
+ }
69
+ }
70
+ catch (error) {
71
+ const message = error instanceof Error ? error.message : String(error);
72
+ process.stderr.write(`graph build failed: ${message}\n`);
73
+ process.exit(1);
74
+ }
75
+ finally {
76
+ store.close();
77
+ }
78
+ });
79
+ graphCommand
80
+ .command("query <symbol>")
81
+ .description("Lookup a symbol and print callers/callees")
82
+ .option("-r, --repo-root <path>", "Repository root", options.repoRoot)
83
+ .option("--file <path>", "Optional file path filter for symbol lookup")
84
+ .option("--json", "Emit JSON output")
85
+ .option("--dry-run", "Print the query plan and skip execution")
86
+ .action((symbol, commandOptions) => {
87
+ const repoRoot = (0, node_path_1.resolve)(commandOptions.repoRoot ?? options.repoRoot);
88
+ const plan = createBuildPlan(repoRoot);
89
+ const fileFilter = commandOptions.file ? (0, node_path_1.resolve)(repoRoot, commandOptions.file) : undefined;
90
+ const json = commandOptions.json ?? false;
91
+ const dryRun = commandOptions.dryRun ?? false;
92
+ if (dryRun) {
93
+ const output = {
94
+ mode: "dry-run",
95
+ command: "query",
96
+ symbol,
97
+ file: fileFilter ?? null,
98
+ outputPath: plan.outputPathAbsolute,
99
+ dbPath: plan.dbPathAbsolute,
100
+ };
101
+ if (json) {
102
+ console.log(JSON.stringify(output, null, 2));
103
+ }
104
+ else {
105
+ printDryRunPlan(output);
106
+ }
107
+ return;
108
+ }
109
+ const store = new adapter_js_1.GraphStoreAdapter({
110
+ repoRoot,
111
+ graphOutputPath: plan.outputPathRelative,
112
+ dbPath: plan.dbPathRelative,
113
+ });
114
+ try {
115
+ store.open();
116
+ (0, index_js_1.configureGraphQuery)({ graphStore: store });
117
+ const target = (0, index_js_1.lookupSymbol)(symbol, fileFilter);
118
+ if (!target) {
119
+ process.stderr.write(`symbol not found: ${symbol}\n`);
120
+ process.exit(1);
121
+ }
122
+ const output = {
123
+ symbol: target,
124
+ callers: (0, index_js_1.getCallers)(target.id),
125
+ callees: (0, index_js_1.getCallees)(target.id),
126
+ outputPath: plan.outputPathAbsolute,
127
+ dbPath: plan.dbPathAbsolute,
128
+ };
129
+ if (json) {
130
+ console.log(JSON.stringify(output, null, 2));
131
+ }
132
+ else {
133
+ printQueryTable(output.symbol, output.callers, output.callees);
134
+ }
135
+ }
136
+ catch (error) {
137
+ const message = error instanceof Error ? error.message : String(error);
138
+ process.stderr.write(`graph query failed: ${message}\n`);
139
+ process.exit(1);
140
+ }
141
+ finally {
142
+ (0, index_js_1.configureGraphQuery)({ graphStore: null });
143
+ store.close();
144
+ }
145
+ });
146
+ graphCommand
147
+ .command("impact <symbol>")
148
+ .description("Compute transitively impacted files for a symbol")
149
+ .option("-r, --repo-root <path>", "Repository root", options.repoRoot)
150
+ .option("--file <path>", "Optional file path filter for symbol lookup")
151
+ .option("--json", "Emit JSON output")
152
+ .option("--dry-run", "Print the impact plan and skip execution")
153
+ .action((symbol, commandOptions) => {
154
+ const repoRoot = (0, node_path_1.resolve)(commandOptions.repoRoot ?? options.repoRoot);
155
+ const plan = createBuildPlan(repoRoot);
156
+ const fileFilter = commandOptions.file ? (0, node_path_1.resolve)(repoRoot, commandOptions.file) : undefined;
157
+ const json = commandOptions.json ?? false;
158
+ const dryRun = commandOptions.dryRun ?? false;
159
+ if (dryRun) {
160
+ const output = {
161
+ mode: "dry-run",
162
+ command: "impact",
163
+ symbol,
164
+ file: fileFilter ?? null,
165
+ outputPath: plan.outputPathAbsolute,
166
+ dbPath: plan.dbPathAbsolute,
167
+ };
168
+ if (json) {
169
+ console.log(JSON.stringify(output, null, 2));
170
+ }
171
+ else {
172
+ printDryRunPlan(output);
173
+ }
174
+ return;
175
+ }
176
+ const store = new adapter_js_1.GraphStoreAdapter({
177
+ repoRoot,
178
+ graphOutputPath: plan.outputPathRelative,
179
+ dbPath: plan.dbPathRelative,
180
+ });
181
+ try {
182
+ store.open();
183
+ (0, index_js_1.configureGraphQuery)({ graphStore: store });
184
+ const target = (0, index_js_1.lookupSymbol)(symbol, fileFilter);
185
+ if (!target) {
186
+ process.stderr.write(`symbol not found: ${symbol}\n`);
187
+ process.exit(1);
188
+ }
189
+ const files = (0, index_js_1.getImpactedFiles)(target.id);
190
+ const output = {
191
+ symbol: target,
192
+ impactedFiles: files,
193
+ outputPath: plan.outputPathAbsolute,
194
+ dbPath: plan.dbPathAbsolute,
195
+ };
196
+ if (json) {
197
+ console.log(JSON.stringify(output, null, 2));
198
+ }
199
+ else {
200
+ printImpactTable(output.symbol, output.impactedFiles);
201
+ }
202
+ }
203
+ catch (error) {
204
+ const message = error instanceof Error ? error.message : String(error);
205
+ process.stderr.write(`graph impact failed: ${message}\n`);
206
+ process.exit(1);
207
+ }
208
+ finally {
209
+ (0, index_js_1.configureGraphQuery)({ graphStore: null });
210
+ store.close();
211
+ }
212
+ });
213
+ return graphCommand;
214
+ }
215
+ function createBuildPlan(repoRoot) {
216
+ const config = (0, loader_js_1.loadConfig)(repoRoot);
217
+ const outputPathRelative = config.graph.outputPath ?? ".polaris/graph";
218
+ const outputPathAbsolute = (0, node_path_1.resolve)(repoRoot, outputPathRelative);
219
+ const dbPathRelative = (0, node_path_1.join)(outputPathRelative, "graph.sqlite");
220
+ const dbPathAbsolute = (0, node_path_1.resolve)(repoRoot, dbPathRelative);
221
+ const sourceRoots = (config.repo.sourceRoots ?? ["src"])
222
+ .filter((root) => typeof root === "string" && root.length > 0)
223
+ .map((root) => (0, node_path_1.resolve)(repoRoot, root));
224
+ const sourceFiles = collectSourceFiles(sourceRoots);
225
+ return {
226
+ outputPathRelative,
227
+ outputPathAbsolute,
228
+ dbPathRelative,
229
+ dbPathAbsolute,
230
+ sourceRootsAbsolute: sourceRoots,
231
+ sourceFiles,
232
+ };
233
+ }
234
+ function collectSourceFiles(sourceRoots) {
235
+ const files = [];
236
+ for (const root of sourceRoots) {
237
+ if (!(0, node_fs_1.existsSync)(root)) {
238
+ continue;
239
+ }
240
+ for (const filePath of walkDirectory(root)) {
241
+ files.push(filePath);
242
+ }
243
+ }
244
+ return Array.from(new Set(files)).sort((left, right) => left.localeCompare(right));
245
+ }
246
+ function* walkDirectory(root, visited = new Set()) {
247
+ const realRoot = (0, node_fs_1.realpathSync)(root);
248
+ if (visited.has(realRoot))
249
+ return;
250
+ visited.add(realRoot);
251
+ const entries = (0, node_fs_1.readdirSync)(root, { withFileTypes: true });
252
+ for (const entry of entries) {
253
+ const fullPath = (0, node_path_1.join)(root, entry.name);
254
+ if (entry.isDirectory()) {
255
+ yield* walkDirectory(fullPath, visited);
256
+ continue;
257
+ }
258
+ yield fullPath;
259
+ }
260
+ }
261
+ function failMissingSubcommand(command, commandName) {
262
+ const unknownSubcommand = command.args[0];
263
+ const message = unknownSubcommand
264
+ ? `error: unknown command '${unknownSubcommand}' for '${commandName}'. Run '${commandName} --help'.`
265
+ : `error: missing command for '${commandName}'. Run '${commandName} --help'.`;
266
+ command.error(message, {
267
+ code: "commander.missingCommand",
268
+ exitCode: 1,
269
+ });
270
+ }
271
+ function printBuildPlan(plan) {
272
+ console.log("graph build plan (dry-run)");
273
+ console.log(`output path: ${plan.outputPathAbsolute}`);
274
+ console.log(`db path: ${plan.dbPathAbsolute}`);
275
+ console.log(`source roots: ${plan.sourceRootsAbsolute.length}`);
276
+ for (const root of plan.sourceRootsAbsolute) {
277
+ console.log(` - ${root}`);
278
+ }
279
+ console.log(`source files: ${plan.sourceFiles.length}`);
280
+ }
281
+ function printBuildSummary(output) {
282
+ console.log("graph build complete");
283
+ console.log(`output path: ${output.outputPath}`);
284
+ console.log(`db path: ${output.dbPath}`);
285
+ console.log(`source roots: ${output.sourceRoots.length}`);
286
+ console.log(`source files: ${output.sourceFileCount}`);
287
+ console.log(`extraction: processed=${output.extraction.processedFiles} succeeded=${output.extraction.succeededFiles} failed=${output.extraction.failedFiles}`);
288
+ console.log(`resolver: imports=${output.resolver.importsEdges} calls=${output.resolver.callsEdges} defined-in=${output.resolver.definedInEdges} unresolved-imports=${output.resolver.unresolvedImports} unresolved-calls=${output.resolver.unresolvedCalls}`);
289
+ printCapabilityReport(output.extraction.capability);
290
+ }
291
+ function printCapabilityReport(report) {
292
+ const rows = Object.entries(report.coverage).sort(([left], [right]) => left.localeCompare(right));
293
+ const languageWidth = Math.max("Language".length, ...rows.map(([language]) => language.length));
294
+ const filesWidth = Math.max("Files".length, ...rows.map(([, entry]) => String(entry.filesDiscovered).length), String(rows.reduce((total, [, entry]) => total + entry.filesDiscovered, 0)).length);
295
+ const symbolWidth = Math.max("Symbol-Level".length, ...rows.map(([, entry]) => String(entry.filesSymbolLevel).length), String(rows.reduce((total, [, entry]) => total + entry.filesSymbolLevel, 0)).length);
296
+ const fileWidth = Math.max("File-Level".length, ...rows.map(([, entry]) => String(entry.filesFileLevel).length), String(rows.reduce((total, [, entry]) => total + entry.filesFileLevel, 0)).length);
297
+ const failedWidth = Math.max("Failed".length, ...rows.map(([, entry]) => String(entry.filesFailed).length), String(rows.reduce((total, [, entry]) => total + entry.filesFailed, 0)).length);
298
+ const totalFiles = rows.reduce((total, [, entry]) => total + entry.filesDiscovered, 0);
299
+ const totalSymbolLevel = rows.reduce((total, [, entry]) => total + entry.filesSymbolLevel, 0);
300
+ const totalFileLevel = rows.reduce((total, [, entry]) => total + entry.filesFileLevel, 0);
301
+ const totalFailed = rows.reduce((total, [, entry]) => total + entry.filesFailed, 0);
302
+ console.log("");
303
+ console.log("Graph Build - Coverage Report");
304
+ console.log("-".repeat(languageWidth + filesWidth + symbolWidth + fileWidth + failedWidth + 16));
305
+ console.log(`${"Language".padEnd(languageWidth)} ${"Files".padStart(filesWidth)} ${"Symbol-Level".padStart(symbolWidth)} ${"File-Level".padStart(fileWidth)} ${"Failed".padStart(failedWidth)}`);
306
+ for (const [language, entry] of rows) {
307
+ console.log(`${language.padEnd(languageWidth)} ${String(entry.filesDiscovered).padStart(filesWidth)} ${String(entry.filesSymbolLevel).padStart(symbolWidth)} ${String(entry.filesFileLevel).padStart(fileWidth)} ${String(entry.filesFailed).padStart(failedWidth)}`);
308
+ }
309
+ console.log("-".repeat(languageWidth + filesWidth + symbolWidth + fileWidth + failedWidth + 16));
310
+ console.log(`${"Total".padEnd(languageWidth)} ${String(totalFiles).padStart(filesWidth)} ${String(totalSymbolLevel).padStart(symbolWidth)} ${String(totalFileLevel).padStart(fileWidth)} ${String(totalFailed).padStart(failedWidth)}`);
311
+ console.log(`Symbol-level coverage: ${report.symbolLevelPercent.toFixed(1)}%`);
312
+ console.log(`Total file coverage: ${report.totalCoveragePercent.toFixed(1)}%`);
313
+ }
314
+ function printDryRunPlan(plan) {
315
+ console.log(`graph ${plan.command} plan (dry-run)`);
316
+ console.log(`symbol: ${plan.symbol}`);
317
+ if (plan.file) {
318
+ console.log(`file filter: ${plan.file}`);
319
+ }
320
+ console.log(`output path: ${plan.outputPath}`);
321
+ console.log(`db path: ${plan.dbPath}`);
322
+ }
323
+ function printQueryTable(symbol, callers, callees) {
324
+ console.log(`symbol: ${symbol.name} (${symbol.kind})`);
325
+ console.log(`id: ${symbol.id}`);
326
+ console.log(`file: ${symbol.filePath}`);
327
+ if (symbol.signature) {
328
+ console.log(`signature: ${symbol.signature}`);
329
+ }
330
+ console.log("");
331
+ printSymbolRows("callers", callers);
332
+ console.log("");
333
+ printSymbolRows("callees", callees);
334
+ }
335
+ function printImpactTable(symbol, impactedFiles) {
336
+ console.log(`symbol: ${symbol.name} (${symbol.kind})`);
337
+ console.log(`id: ${symbol.id}`);
338
+ console.log(`file: ${symbol.filePath}`);
339
+ console.log("");
340
+ console.log(`impacted files (${impactedFiles.length})`);
341
+ if (impactedFiles.length === 0) {
342
+ console.log(" none");
343
+ return;
344
+ }
345
+ for (const file of impactedFiles) {
346
+ console.log(` ${file.path} (${file.language})`);
347
+ }
348
+ }
349
+ function printSymbolRows(title, symbols) {
350
+ console.log(`${title} (${symbols.length})`);
351
+ if (symbols.length === 0) {
352
+ console.log(" none");
353
+ return;
354
+ }
355
+ for (const symbol of symbols) {
356
+ console.log(` ${symbol.name.padEnd(24)} ${symbol.kind.padEnd(10)} ${symbol.filePath}`);
357
+ }
358
+ }
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.createPolarisCommand = createPolarisCommand;
5
+ const node_fs_1 = require("node:fs");
6
+ const node_path_1 = require("node:path");
7
+ const commander_1 = require("commander");
8
+ const version_js_1 = require("./version.js");
9
+ const branding_js_1 = require("./branding.js");
10
+ const index_js_1 = require("../loop/index.js");
11
+ const status_js_1 = require("../loop/status.js");
12
+ const index_js_2 = require("../map/index.js");
13
+ const index_js_3 = require("../finalize/index.js");
14
+ const index_js_4 = require("../finalize/index.js");
15
+ const index_js_5 = require("../runs/index.js");
16
+ const init_js_1 = require("./init.js");
17
+ const index_js_6 = require("../smartdocs-engine/index.js");
18
+ const show_js_1 = require("../config/show.js");
19
+ const cli_subtask_bridge_js_1 = require("../loop/adapters/cli-subtask-bridge.js");
20
+ const finalize_evidence_js_1 = require("../loop/finalize-evidence.js");
21
+ const tracker_js_1 = require("./tracker.js");
22
+ const worker_js_1 = require("./worker.js");
23
+ const graph_js_1 = require("./graph.js");
24
+ const index_js_7 = require("../skill-packet/index.js");
25
+ const librarian_js_1 = require("./librarian.js");
26
+ const medic_js_1 = require("./medic.js");
27
+ const welfare_js_1 = require("../map/welfare.js");
28
+ function resolveStateFile(repoRoot, explicit) {
29
+ if (explicit)
30
+ return (0, node_path_1.resolve)(explicit);
31
+ const taskchainPath = (0, node_path_1.join)(repoRoot, ".taskchain_artifacts", "polaris-run", "current-state.json");
32
+ const polarisPath = (0, node_path_1.join)(repoRoot, ".polaris", "runs", "current-state.json");
33
+ if ((0, node_fs_1.existsSync)(taskchainPath))
34
+ return taskchainPath;
35
+ if ((0, node_fs_1.existsSync)(polarisPath))
36
+ return polarisPath;
37
+ return taskchainPath;
38
+ }
39
+ function createPolarisCommand(options = {}) {
40
+ const repoRoot = options.repoRoot ?? (0, node_path_1.resolve)(process.cwd());
41
+ (0, cli_subtask_bridge_js_1.installCliSubtaskBridge)(repoRoot);
42
+ const statusHandler = options.runLoopStatus ?? status_js_1.runLoopStatus;
43
+ const finalizeHandler = options.runFinalize ?? (async (finalizeOptions) => {
44
+ (0, finalize_evidence_js_1.assertFinalizeEvidenceOrThrow)(finalizeOptions.repoRoot, finalizeOptions.stateFile);
45
+ await (0, index_js_4.runFinalize)(finalizeOptions);
46
+ });
47
+ const program = new commander_1.Command("polaris")
48
+ .description("Polaris taskchain operator CLI")
49
+ .version((0, version_js_1.getVersion)())
50
+ .showHelpAfterError()
51
+ .showSuggestionAfterError();
52
+ program.addHelpText("before", (0, branding_js_1.getBanner)());
53
+ program
54
+ .command("status")
55
+ .description("safe/read-only: print current loop run state summary")
56
+ .option("--state-file <path>", "Override path to current-state.json")
57
+ .option("--json", "Emit JSON output instead of human-readable text")
58
+ .action((commandOptions) => {
59
+ statusHandler({
60
+ repoRoot,
61
+ stateFile: resolveStateFile(repoRoot, commandOptions.stateFile),
62
+ json: commandOptions.json,
63
+ });
64
+ });
65
+ program.addCommand((0, index_js_1.createLoopCommand)({
66
+ repoRoot,
67
+ runLoopStatus: statusHandler,
68
+ runLoopContinue: options.runLoopContinue,
69
+ }));
70
+ program.addCommand((0, index_js_2.createMapCommand)({
71
+ repoRoot,
72
+ runMapQuery: options.runMapQuery,
73
+ }));
74
+ program.addCommand((0, index_js_3.createFinalizeCommand)({
75
+ repoRoot,
76
+ runFinalize: finalizeHandler,
77
+ }));
78
+ program.addCommand((0, index_js_5.createRunsCommand)({ repoRoot }));
79
+ program.addCommand((0, init_js_1.createInitCommand)({
80
+ repoRoot,
81
+ detectProviders: undefined,
82
+ }));
83
+ program.addCommand((0, index_js_6.createDocsCommand)({ repoRoot }));
84
+ program.addCommand((0, index_js_6.createDoctrineCommand)());
85
+ program.addCommand((0, show_js_1.createConfigCommand)({
86
+ repoRoot,
87
+ runConfigShow: options.runConfigShow,
88
+ runConfigDoctor: options.runConfigDoctor,
89
+ }));
90
+ program.addCommand((0, tracker_js_1.createTrackerCommand)({
91
+ repoRoot,
92
+ }));
93
+ program.addCommand((0, worker_js_1.createWorkerCommand)({
94
+ repoRoot,
95
+ }));
96
+ program.addCommand((0, graph_js_1.createGraphCommand)({
97
+ repoRoot,
98
+ }));
99
+ program.addCommand((0, index_js_7.createSkillCommand)({
100
+ repoRoot,
101
+ }));
102
+ program.addCommand((0, librarian_js_1.createLibrarianCommand)({
103
+ repoRoot,
104
+ }));
105
+ program.addCommand((0, medic_js_1.createMedicCommand)({
106
+ repoRoot,
107
+ }));
108
+ program
109
+ .command("welfare-check")
110
+ .description("safe/read-only: run route welfare checks and report per-route health")
111
+ .option("-r, --repo-root <path>", "Repository root", repoRoot)
112
+ .option("--route <path>", "Scope to a single route domain")
113
+ .action((options) => {
114
+ const report = (0, welfare_js_1.runWelfareCheck)(options.repoRoot, options.route);
115
+ (0, welfare_js_1.printWelfareCheckReport)(report);
116
+ if (report.needsReview > 0) {
117
+ process.exit(1);
118
+ }
119
+ });
120
+ return program;
121
+ }
122
+ if (require.main === module) {
123
+ createPolarisCommand().parseAsync(process.argv).catch((err) => {
124
+ process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
125
+ process.exit(1);
126
+ });
127
+ }
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const node_path_1 = require("node:path");
5
+ const index_js_1 = require("./index.js");
6
+ function configureForTest(program, output) {
7
+ program.exitOverride();
8
+ program.configureOutput({
9
+ writeOut: (value) => {
10
+ output.stdout += value;
11
+ },
12
+ writeErr: (value) => {
13
+ output.stderr += value;
14
+ },
15
+ });
16
+ for (const command of program.commands) {
17
+ configureForTest(command, output);
18
+ }
19
+ }
20
+ async function runCommand(argv) {
21
+ const output = { stdout: "", stderr: "" };
22
+ let exitCode = 0;
23
+ const status = vitest_1.vi.fn();
24
+ const continueLoop = vitest_1.vi.fn();
25
+ const queryMap = vitest_1.vi.fn();
26
+ const finalize = vitest_1.vi.fn();
27
+ const configShow = vitest_1.vi.fn();
28
+ const program = (0, index_js_1.createPolarisCommand)({
29
+ repoRoot: "/repo",
30
+ runLoopStatus: status,
31
+ runLoopContinue: continueLoop,
32
+ runMapQuery: queryMap,
33
+ runFinalize: finalize,
34
+ runConfigShow: configShow,
35
+ });
36
+ configureForTest(program, output);
37
+ try {
38
+ await program.parseAsync(["node", "polaris", ...argv], { from: "node" });
39
+ }
40
+ catch (error) {
41
+ if (error instanceof Error && "exitCode" in error) {
42
+ exitCode = Number(error.exitCode);
43
+ }
44
+ else {
45
+ throw error;
46
+ }
47
+ }
48
+ return { ...output, exitCode, status, continueLoop, queryMap, finalize, configShow };
49
+ }
50
+ (0, vitest_1.describe)("polaris public CLI", () => {
51
+ (0, vitest_1.it)("prints root help through Commander", async () => {
52
+ const result = await runCommand(["--help"]);
53
+ (0, vitest_1.expect)(result.stdout).toContain("Usage: polaris");
54
+ (0, vitest_1.expect)(result.stdout).toContain("status");
55
+ (0, vitest_1.expect)(result.stdout).toContain("loop");
56
+ (0, vitest_1.expect)(result.stdout).toContain("map");
57
+ (0, vitest_1.expect)(result.stdout).toContain("finalize");
58
+ (0, vitest_1.expect)(result.stdout).toContain("docs");
59
+ (0, vitest_1.expect)(result.stdout).toContain("doctrine");
60
+ (0, vitest_1.expect)(result.stdout).toContain("safe/read-only");
61
+ (0, vitest_1.expect)(result.stdout).toContain("config");
62
+ });
63
+ (0, vitest_1.it)("exposes docs ingest command with expected flags", async () => {
64
+ const result = await runCommand(["docs", "ingest", "--help"]);
65
+ (0, vitest_1.expect)(result.exitCode).toBe(0);
66
+ (0, vitest_1.expect)(result.stdout).toContain("Usage: polaris docs ingest");
67
+ (0, vitest_1.expect)(result.stdout).toContain("--file");
68
+ (0, vitest_1.expect)(result.stdout).toContain("--batch");
69
+ (0, vitest_1.expect)(result.stdout).toContain("--dry-run");
70
+ (0, vitest_1.expect)(result.stdout).toContain("smartdocs/docs");
71
+ });
72
+ vitest_1.it.each(["draft", "promote", "deprecate"])("exposes doctrine %s command through the public entrypoint", async (subcommand) => {
73
+ const result = await runCommand(["doctrine", subcommand, "--help"]);
74
+ (0, vitest_1.expect)(result.exitCode).toBe(0);
75
+ (0, vitest_1.expect)(result.stderr).not.toContain("unknown command");
76
+ (0, vitest_1.expect)(result.stdout).toContain(`Usage: polaris doctrine ${subcommand}`);
77
+ });
78
+ (0, vitest_1.it)("prints the package version", async () => {
79
+ const result = await runCommand(["--version"]);
80
+ (0, vitest_1.expect)(result.stdout.trim()).toMatch(/^\d+\.\d+\.\d+/);
81
+ });
82
+ (0, vitest_1.it)("keeps status as a top-level alias for loop status", async () => {
83
+ const result = await runCommand(["status", "--json"]);
84
+ (0, vitest_1.expect)(result.status).toHaveBeenCalledWith({
85
+ repoRoot: "/repo",
86
+ stateFile: (0, node_path_1.join)("/repo", ".taskchain_artifacts", "polaris-run", "current-state.json"),
87
+ json: true,
88
+ });
89
+ });
90
+ (0, vitest_1.it)("routes loop status through the loop command", async () => {
91
+ const result = await runCommand(["loop", "status", "--json"]);
92
+ (0, vitest_1.expect)(result.status).toHaveBeenCalledWith({
93
+ repoRoot: "/repo",
94
+ stateFile: (0, node_path_1.join)("/repo", ".taskchain_artifacts", "polaris-run", "current-state.json"),
95
+ json: true,
96
+ });
97
+ });
98
+ (0, vitest_1.it)("routes map query through the public entrypoint", async () => {
99
+ const result = await runCommand(["map", "query", "src/cli/index.ts"]);
100
+ (0, vitest_1.expect)(result.queryMap).toHaveBeenCalledWith("/repo", "src/cli/index.ts", undefined, undefined, false, false);
101
+ });
102
+ (0, vitest_1.it)("exposes finalize run help", async () => {
103
+ const result = await runCommand(["finalize", "run", "--help"]);
104
+ (0, vitest_1.expect)(result.stdout).toContain("Usage: polaris finalize run");
105
+ (0, vitest_1.expect)(result.stdout).toContain("--dry-run");
106
+ (0, vitest_1.expect)(result.stdout).toContain("--skip-delivery");
107
+ });
108
+ (0, vitest_1.it)("prints config help without failing", async () => {
109
+ const result = await runCommand(["config"]);
110
+ (0, vitest_1.expect)(result.exitCode).toBe(0);
111
+ (0, vitest_1.expect)(result.stdout).toContain("Usage: polaris config");
112
+ (0, vitest_1.expect)(result.stdout).toContain("show");
113
+ (0, vitest_1.expect)(result.stderr).not.toContain("deferred");
114
+ });
115
+ (0, vitest_1.it)("routes config show through the public entrypoint", async () => {
116
+ const result = await runCommand(["config", "show"]);
117
+ (0, vitest_1.expect)(result.exitCode).toBe(0);
118
+ (0, vitest_1.expect)(result.configShow).toHaveBeenCalledWith({
119
+ repoRoot: "/repo",
120
+ });
121
+ });
122
+ (0, vitest_1.it)("marks safe previews and mutating commands in subsystem help", async () => {
123
+ const loop = await runCommand(["loop", "--help"]);
124
+ const map = await runCommand(["map", "--help"]);
125
+ const finalize = await runCommand(["finalize", "--help"]);
126
+ (0, vitest_1.expect)(loop.exitCode).toBe(0);
127
+ (0, vitest_1.expect)(loop.stdout).toContain("status");
128
+ (0, vitest_1.expect)(loop.stdout).toContain("safe/read-only");
129
+ (0, vitest_1.expect)(loop.stdout).toContain("continue");
130
+ (0, vitest_1.expect)(loop.stdout).toContain("mutating");
131
+ (0, vitest_1.expect)(loop.stdout).toContain("not a smoke test");
132
+ (0, vitest_1.expect)(map.exitCode).toBe(0);
133
+ (0, vitest_1.expect)(map.stdout).toContain("--dry-run");
134
+ (0, vitest_1.expect)(map.stdout).toContain("non-mutating preview");
135
+ (0, vitest_1.expect)(finalize.exitCode).toBe(0);
136
+ (0, vitest_1.expect)(finalize.stdout).toContain("manual/operator-triggered");
137
+ (0, vitest_1.expect)(finalize.stdout).toContain("performs delivery");
138
+ (0, vitest_1.expect)(finalize.stdout).toContain("--dry-run");
139
+ (0, vitest_1.expect)(finalize.stdout).toContain("--skip-delivery");
140
+ });
141
+ (0, vitest_1.it)("fails unknown commands with actionable help", async () => {
142
+ const result = await runCommand(["not-a-command"]);
143
+ (0, vitest_1.expect)(result.exitCode).toBeGreaterThan(0);
144
+ (0, vitest_1.expect)(result.stderr).toContain("unknown command");
145
+ (0, vitest_1.expect)(result.stderr).toContain("Usage: polaris");
146
+ (0, vitest_1.expect)(result.stderr).toContain("Commands:");
147
+ });
148
+ (0, vitest_1.it)("fails missing subsystem subcommands with actionable help", async () => {
149
+ const result = await runCommand(["loop"]);
150
+ (0, vitest_1.expect)(result.exitCode).toBeGreaterThan(0);
151
+ (0, vitest_1.expect)(result.stderr).toContain("missing command");
152
+ (0, vitest_1.expect)(result.stderr).toContain("Usage: polaris loop");
153
+ (0, vitest_1.expect)(result.stderr).toContain("Commands:");
154
+ });
155
+ (0, vitest_1.it)("fails unknown subsystem subcommands with actionable help", async () => {
156
+ const result = await runCommand(["loop", "not-a-subcommand"]);
157
+ (0, vitest_1.expect)(result.exitCode).toBeGreaterThan(0);
158
+ (0, vitest_1.expect)(result.stderr).toContain("unknown command 'not-a-subcommand'");
159
+ (0, vitest_1.expect)(result.stderr).toContain("Usage: polaris loop");
160
+ (0, vitest_1.expect)(result.stderr).toContain("Commands:");
161
+ });
162
+ });