@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,350 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scanAdoptionInventory = scanAdoptionInventory;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const SOURCE_ROOT_HINTS = ["src", "lib", "app", "packages", "services", "server", "client"];
7
+ const DOC_ROOT_HINTS = [
8
+ "docs",
9
+ "doc",
10
+ "wiki",
11
+ "adr",
12
+ "rfcs",
13
+ "architecture",
14
+ "design",
15
+ "spec",
16
+ "specs",
17
+ "guides",
18
+ ];
19
+ const GENERATED_ROOT_HINTS = ["dist", "build", "coverage", ".next", ".nuxt", "out", "generated"];
20
+ const CACHE_ROOT_HINTS = [".cache", ".turbo", ".parcel-cache", ".vite", "tmp", ".tmp"];
21
+ const FIXTURE_ROOT_HINTS = ["fixtures", "__fixtures__", "__mocks__", "test/data", "tests/data"];
22
+ const SKIP_TRAVERSAL = new Set([".git", "node_modules"]);
23
+ function toPosix(path) {
24
+ return path.replaceAll("\\", "/");
25
+ }
26
+ function withTrailingSlash(path) {
27
+ return path.endsWith("/") ? path : `${path}/`;
28
+ }
29
+ function uniqueSorted(values) {
30
+ return [...new Set(values)].sort();
31
+ }
32
+ function safeRead(path) {
33
+ try {
34
+ return (0, node_fs_1.readFileSync)(path, "utf-8");
35
+ }
36
+ catch {
37
+ return "";
38
+ }
39
+ }
40
+ function detectPackageManager(repoRoot) {
41
+ if ((0, node_fs_1.existsSync)((0, node_path_1.join)(repoRoot, "pnpm-lock.yaml")))
42
+ return "pnpm";
43
+ if ((0, node_fs_1.existsSync)((0, node_path_1.join)(repoRoot, "yarn.lock")))
44
+ return "yarn";
45
+ if ((0, node_fs_1.existsSync)((0, node_path_1.join)(repoRoot, "bun.lockb")) || (0, node_fs_1.existsSync)((0, node_path_1.join)(repoRoot, "bun.lock")))
46
+ return "bun";
47
+ if ((0, node_fs_1.existsSync)((0, node_path_1.join)(repoRoot, "package-lock.json")) || (0, node_fs_1.existsSync)((0, node_path_1.join)(repoRoot, "npm-shrinkwrap.json"))) {
48
+ return "npm";
49
+ }
50
+ if ((0, node_fs_1.existsSync)((0, node_path_1.join)(repoRoot, "package.json")))
51
+ return "npm";
52
+ return null;
53
+ }
54
+ function detectRepoState(repoRoot, topLevelEntries) {
55
+ if ((0, node_fs_1.existsSync)((0, node_path_1.join)(repoRoot, ".polaris"))) {
56
+ return "polaris-enabled";
57
+ }
58
+ const meaningfulEntries = topLevelEntries.filter((entry) => entry.path !== ".git" && entry.path !== ".gitignore");
59
+ if (meaningfulEntries.length === 0) {
60
+ return "empty";
61
+ }
62
+ const hasManifest = ["package.json", "pyproject.toml", "go.mod", "Cargo.toml"].some((file) => (0, node_fs_1.existsSync)((0, node_path_1.join)(repoRoot, file)));
63
+ const hasSourceRoots = topLevelEntries.some((entry) => SOURCE_ROOT_HINTS.includes(entry.path));
64
+ const hasDocsRoots = topLevelEntries.some((entry) => DOC_ROOT_HINTS.includes(entry.path));
65
+ if (hasManifest && !hasSourceRoots && !hasDocsRoots) {
66
+ return "new";
67
+ }
68
+ if (!hasManifest && (hasSourceRoots || hasDocsRoots)) {
69
+ return "partial";
70
+ }
71
+ return "existing";
72
+ }
73
+ function walkRepository(repoRoot, relativeDir = "") {
74
+ const currentDir = (0, node_path_1.join)(repoRoot, relativeDir);
75
+ let names = [];
76
+ try {
77
+ names = (0, node_fs_1.readdirSync)(currentDir);
78
+ }
79
+ catch {
80
+ return [];
81
+ }
82
+ const entries = [];
83
+ for (const name of names) {
84
+ const relPath = relativeDir ? `${relativeDir}/${name}` : name;
85
+ const absPath = (0, node_path_1.join)(repoRoot, relPath);
86
+ let stat;
87
+ try {
88
+ stat = (0, node_fs_1.statSync)(absPath);
89
+ }
90
+ catch {
91
+ continue;
92
+ }
93
+ const normalizedPath = toPosix(relPath);
94
+ const repoEntry = {
95
+ path: normalizedPath,
96
+ isDirectory: stat.isDirectory(),
97
+ sizeBytes: stat.size,
98
+ };
99
+ entries.push(repoEntry);
100
+ if (repoEntry.isDirectory && !SKIP_TRAVERSAL.has(name)) {
101
+ entries.push(...walkRepository(repoRoot, normalizedPath));
102
+ }
103
+ }
104
+ return entries;
105
+ }
106
+ function detectRoots(entries, hints) {
107
+ const roots = entries
108
+ .filter((entry) => entry.isDirectory)
109
+ .map((entry) => entry.path)
110
+ .filter((path) => hints.some((hint) => path === hint || path.includes(`/${hint}/`) || path.endsWith(`/${hint}`)))
111
+ .map(withTrailingSlash);
112
+ return uniqueSorted(roots);
113
+ }
114
+ function parsePackageScripts(repoRoot) {
115
+ const packageJsonPath = (0, node_path_1.join)(repoRoot, "package.json");
116
+ if (!(0, node_fs_1.existsSync)(packageJsonPath)) {
117
+ return {};
118
+ }
119
+ try {
120
+ const parsed = JSON.parse((0, node_fs_1.readFileSync)(packageJsonPath, "utf-8"));
121
+ if (!parsed.scripts || typeof parsed.scripts !== "object" || Array.isArray(parsed.scripts)) {
122
+ return {};
123
+ }
124
+ return Object.fromEntries(Object.entries(parsed.scripts).filter(([, value]) => typeof value === "string"));
125
+ }
126
+ catch {
127
+ return {};
128
+ }
129
+ }
130
+ function buildScriptCommands(scripts, mode) {
131
+ const matchers = mode === "test"
132
+ ? [/^test$/i, /test/i, /e2e/i, /integration/i]
133
+ : [/^build$/i, /build/i, /compile/i, /typecheck/i];
134
+ const commands = [];
135
+ for (const scriptName of Object.keys(scripts)) {
136
+ if (!matchers.some((matcher) => matcher.test(scriptName))) {
137
+ continue;
138
+ }
139
+ if (scriptName === "test") {
140
+ commands.push("npm test");
141
+ }
142
+ else {
143
+ commands.push(`npm run ${scriptName}`);
144
+ }
145
+ }
146
+ return uniqueSorted(commands);
147
+ }
148
+ const INSTRUCTION_PATTERNS = [
149
+ {
150
+ matcher: (entry) => entry.path === "CLAUDE.md",
151
+ provider: "claude",
152
+ },
153
+ {
154
+ matcher: (entry) => entry.path === "AGENTS.md",
155
+ provider: "openai",
156
+ },
157
+ {
158
+ matcher: (entry) => entry.path === ".github/copilot-instructions.md",
159
+ provider: "copilot",
160
+ },
161
+ {
162
+ matcher: (entry) => entry.path === ".cursorrules" || entry.path.startsWith(".cursor/rules/"),
163
+ provider: "cursor",
164
+ },
165
+ {
166
+ matcher: (entry) => entry.path === ".aider.conf.yml" || entry.path === "AIDER.md",
167
+ provider: "aider",
168
+ },
169
+ {
170
+ matcher: (entry) => (0, node_path_1.basename)(entry.path) === "GEMINI.md",
171
+ provider: "gemini",
172
+ },
173
+ ];
174
+ function recommendationForInstruction(hasDelegation, doctrineExists, sizeBytes) {
175
+ if (hasDelegation) {
176
+ return {
177
+ recommendation: "preserve",
178
+ reason: "Already delegates to Polaris doctrine.",
179
+ };
180
+ }
181
+ if (!doctrineExists) {
182
+ return {
183
+ recommendation: "preserve",
184
+ reason: "No POLARIS.md doctrine detected yet.",
185
+ };
186
+ }
187
+ if (sizeBytes < 500) {
188
+ return {
189
+ recommendation: "thin-adapter",
190
+ reason: "Short generic instruction file; convert to thin adapter.",
191
+ };
192
+ }
193
+ return {
194
+ recommendation: "migrate",
195
+ reason: "Substantive instruction file should be preserved in SmartDocs raw migration.",
196
+ };
197
+ }
198
+ function detectAgentInstructionFiles(repoRoot, entries, doctrineExists) {
199
+ return entries
200
+ .filter((entry) => !entry.isDirectory)
201
+ .map((entry) => {
202
+ const matched = INSTRUCTION_PATTERNS.find((pattern) => pattern.matcher(entry));
203
+ if (!matched) {
204
+ return null;
205
+ }
206
+ const content = safeRead((0, node_path_1.join)(repoRoot, entry.path));
207
+ const hasPolarisDelegation = content.includes("<!-- polaris:delegate") || content.toLowerCase().includes("polaris.md");
208
+ const recommendation = recommendationForInstruction(hasPolarisDelegation, doctrineExists, entry.sizeBytes);
209
+ return {
210
+ path: entry.path,
211
+ provider: matched.provider,
212
+ size_bytes: entry.sizeBytes,
213
+ has_polaris_delegation: hasPolarisDelegation,
214
+ recommendation: recommendation.recommendation,
215
+ reason: recommendation.reason,
216
+ };
217
+ })
218
+ .filter((entry) => entry !== null)
219
+ .sort((a, b) => a.path.localeCompare(b.path));
220
+ }
221
+ function classifyDocKind(path) {
222
+ const lowered = path.toLowerCase();
223
+ if (lowered.includes("spec"))
224
+ return "spec";
225
+ if (lowered.includes("adr") || lowered.includes("decision"))
226
+ return "decision";
227
+ if (lowered.includes("arch") || lowered.includes("design"))
228
+ return "architecture";
229
+ if (lowered.includes("integration"))
230
+ return "integration";
231
+ if (lowered.includes("doc") || lowered.endsWith(".md") || lowered.endsWith(".mdx"))
232
+ return "doc";
233
+ return "unknown";
234
+ }
235
+ function shouldSkipDoc(path) {
236
+ const lowered = path.toLowerCase();
237
+ const filename = (0, node_path_1.basename)(lowered);
238
+ if (lowered.startsWith("smartdocs/") ||
239
+ lowered.startsWith("node_modules/") ||
240
+ lowered.startsWith(".git/") ||
241
+ lowered.startsWith("dist/") ||
242
+ lowered.startsWith("build/") ||
243
+ lowered.startsWith("coverage/") ||
244
+ lowered.startsWith(".next/") ||
245
+ lowered.startsWith(".nuxt/") ||
246
+ lowered.startsWith("out/") ||
247
+ lowered.startsWith("generated/") ||
248
+ lowered.startsWith(".cache/") ||
249
+ lowered.startsWith(".turbo/") ||
250
+ lowered.startsWith("fixtures/") ||
251
+ lowered.includes("/fixtures/") ||
252
+ lowered.includes("/__fixtures__/") ||
253
+ lowered.includes("/test/data/") ||
254
+ lowered.includes("/tests/data/")) {
255
+ return true;
256
+ }
257
+ if (filename === "agents.md" ||
258
+ filename === "claude.md" ||
259
+ filename === "gemini.md" ||
260
+ filename === "aider.md" ||
261
+ lowered === ".github/copilot-instructions.md") {
262
+ return true;
263
+ }
264
+ return ["README.md", "CHANGELOG.md", "LICENSE", "CONTRIBUTING.md"].includes(path);
265
+ }
266
+ function detectSmartDocsCandidates(repoRoot, entries) {
267
+ const docs = entries
268
+ .filter((entry) => !entry.isDirectory)
269
+ .filter((entry) => entry.path.endsWith(".md") || entry.path.endsWith(".mdx"))
270
+ .filter((entry) => entry.sizeBytes > 100)
271
+ .filter((entry) => !shouldSkipDoc(entry.path))
272
+ .map((entry) => {
273
+ const content = safeRead((0, node_path_1.join)(repoRoot, entry.path));
274
+ const filename = (0, node_path_1.basename)(entry.path);
275
+ const hasFrontmatter = content.startsWith("---\n") || content.startsWith("---\r\n");
276
+ const kind = classifyDocKind(entry.path);
277
+ const estimatedRisk = kind === "architecture" || kind === "decision" ? "medium" : "low";
278
+ return {
279
+ path: entry.path,
280
+ kind,
281
+ suggested_destination: `smartdocs/raw/${filename}`,
282
+ confidence: hasFrontmatter ? 0.95 : 0.7,
283
+ has_frontmatter: hasFrontmatter,
284
+ estimated_risk: estimatedRisk,
285
+ };
286
+ });
287
+ return docs.sort((a, b) => a.path.localeCompare(b.path));
288
+ }
289
+ function detectArchitectureNotes(entries) {
290
+ return uniqueSorted(entries
291
+ .filter((entry) => !entry.isDirectory)
292
+ .filter((entry) => entry.path.endsWith(".md") || entry.path.endsWith(".mdx"))
293
+ .map((entry) => entry.path)
294
+ .filter((path) => {
295
+ const lowered = path.toLowerCase();
296
+ return (lowered.includes("adr") || lowered.includes("rfc") || lowered.includes("architecture") || lowered.includes("design"));
297
+ }));
298
+ }
299
+ function detectExistingSmartDocsDirs(entries) {
300
+ return uniqueSorted(entries
301
+ .filter((entry) => entry.isDirectory)
302
+ .map((entry) => entry.path)
303
+ .filter((path) => path === "smartdocs" || path.startsWith("smartdocs/"))
304
+ .map(withTrailingSlash));
305
+ }
306
+ function detectLikelyCanonicalFolders(sourceRoots, docsRoots) {
307
+ const folders = [...sourceRoots, ...docsRoots]
308
+ .map((path) => path.slice(0, -1))
309
+ .filter((path) => path !== "smartdocs" && !path.includes("fixtures"));
310
+ return uniqueSorted(folders);
311
+ }
312
+ function detectIgnoreCandidates(generatedRoots, cacheRoots) {
313
+ return uniqueSorted([...generatedRoots, ...cacheRoots, ".taskchain_artifacts/"]);
314
+ }
315
+ function scanAdoptionInventory(repoRoot, options = {}) {
316
+ const now = options.now ?? new Date();
317
+ const allEntries = walkRepository(repoRoot);
318
+ const topLevelEntries = allEntries.filter((entry) => !entry.path.includes("/"));
319
+ const packageScripts = parsePackageScripts(repoRoot);
320
+ const sourceRoots = detectRoots(topLevelEntries, SOURCE_ROOT_HINTS);
321
+ const docsRoots = detectRoots(topLevelEntries, DOC_ROOT_HINTS);
322
+ const generatedRoots = detectRoots(allEntries, GENERATED_ROOT_HINTS);
323
+ const cacheRoots = detectRoots(allEntries, CACHE_ROOT_HINTS);
324
+ const fixtureRoots = detectRoots(allEntries, FIXTURE_ROOT_HINTS);
325
+ const doctrineExists = (0, node_fs_1.existsSync)((0, node_path_1.join)(repoRoot, "POLARIS.md"));
326
+ const inventory = {
327
+ scan_date: now.toISOString(),
328
+ repo_state: detectRepoState(repoRoot, topLevelEntries),
329
+ package_manager: detectPackageManager(repoRoot),
330
+ source_roots: sourceRoots,
331
+ docs_roots: docsRoots,
332
+ test_commands: buildScriptCommands(packageScripts, "test"),
333
+ build_commands: buildScriptCommands(packageScripts, "build"),
334
+ package_scripts: packageScripts,
335
+ generated_roots: generatedRoots,
336
+ cache_roots: cacheRoots,
337
+ fixture_roots: fixtureRoots,
338
+ agent_instruction_files: detectAgentInstructionFiles(repoRoot, allEntries, doctrineExists),
339
+ existing_smartdocs_dirs: detectExistingSmartDocsDirs(allEntries),
340
+ architecture_notes: detectArchitectureNotes(allEntries),
341
+ likely_canonical_folders: detectLikelyCanonicalFolders(sourceRoots, docsRoots),
342
+ smartdocs_candidates: detectSmartDocsCandidates(repoRoot, allEntries),
343
+ ignore_candidates: detectIgnoreCandidates(generatedRoots, cacheRoots),
344
+ };
345
+ if (options.writeArtifact ?? true) {
346
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(repoRoot, ".polaris"), { recursive: true });
347
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(repoRoot, ".polaris", "adoption-inventory.json"), `${JSON.stringify(inventory, null, 2)}\n`, "utf-8");
348
+ }
349
+ return inventory;
350
+ }
@@ -0,0 +1,222 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateAdoptionPlan = generateAdoptionPlan;
4
+ exports.renderAdoptionPlanMarkdown = renderAdoptionPlanMarkdown;
5
+ exports.generateAdoptionPlanArtifacts = generateAdoptionPlanArtifacts;
6
+ const node_fs_1 = require("node:fs");
7
+ const node_path_1 = require("node:path");
8
+ function formatPlanId(isoTimestamp) {
9
+ return `adoption-${isoTimestamp.replaceAll(":", "-")}`;
10
+ }
11
+ function normalizePath(path) {
12
+ return path.endsWith("/") ? path.slice(0, -1) : path;
13
+ }
14
+ function createStep(order, partial) {
15
+ return {
16
+ ...partial,
17
+ order,
18
+ status: "pending",
19
+ };
20
+ }
21
+ function buildSteps(inventory) {
22
+ const steps = [];
23
+ let order = 1;
24
+ steps.push(createStep(order++, {
25
+ step_id: "provider-config-lock",
26
+ phase: "A",
27
+ category: "provider-config",
28
+ action: "modify",
29
+ dest_path: "polaris.config.json",
30
+ description: "Write minimal provider config lock before adoption scan/mutations.",
31
+ destructive: true,
32
+ requires_approval: false,
33
+ estimated_risk: "low",
34
+ }));
35
+ steps.push(createStep(order++, {
36
+ step_id: "adoption-scaffold",
37
+ phase: "A",
38
+ category: "scaffold",
39
+ action: "create",
40
+ dest_path: ".polaris/",
41
+ description: "Ensure Polaris scaffold files/folders required for adoption workflow exist.",
42
+ destructive: false,
43
+ requires_approval: false,
44
+ estimated_risk: "low",
45
+ }));
46
+ for (const candidate of inventory.smartdocs_candidates) {
47
+ steps.push(createStep(order++, {
48
+ step_id: `smartdocs-migrate-${order.toString().padStart(3, "0")}`,
49
+ phase: "C",
50
+ category: "smartdocs-migrate",
51
+ action: "move",
52
+ source_path: candidate.path,
53
+ dest_path: candidate.suggested_destination,
54
+ description: `Move ${candidate.path} to ${candidate.suggested_destination}.`,
55
+ destructive: true,
56
+ requires_approval: true,
57
+ estimated_risk: candidate.estimated_risk,
58
+ }));
59
+ }
60
+ for (const folder of inventory.likely_canonical_folders) {
61
+ const normalizedFolder = normalizePath(folder);
62
+ steps.push(createStep(order++, {
63
+ step_id: `cognition-generate-${order.toString().padStart(3, "0")}`,
64
+ phase: "C",
65
+ category: "cognition-generate",
66
+ action: "create",
67
+ dest_path: normalizedFolder,
68
+ description: `Generate ${normalizedFolder}/POLARIS.md and ${normalizedFolder}/SUMMARY.md templates if missing.`,
69
+ destructive: false,
70
+ requires_approval: true,
71
+ estimated_risk: "medium",
72
+ }));
73
+ }
74
+ for (const file of inventory.agent_instruction_files) {
75
+ const action = file.recommendation === "preserve" ? "skip" : "modify";
76
+ const destructive = action === "modify";
77
+ const risk = file.recommendation === "migrate"
78
+ ? "high"
79
+ : file.recommendation === "thin-adapter"
80
+ ? "medium"
81
+ : "low";
82
+ steps.push(createStep(order++, {
83
+ step_id: `instruction-refactor-${order.toString().padStart(3, "0")}`,
84
+ phase: "C",
85
+ category: "instruction-refactor",
86
+ action,
87
+ source_path: file.path,
88
+ dest_path: file.recommendation === "migrate"
89
+ ? `smartdocs/raw/migrated-instructions/${file.path.split("/").pop() ?? "instruction.md"}`
90
+ : file.path,
91
+ description: action === "skip"
92
+ ? `Preserve instruction file ${file.path} (${file.reason}).`
93
+ : `Apply ${file.recommendation} strategy to ${file.path} (${file.reason}).`,
94
+ destructive,
95
+ requires_approval: destructive,
96
+ estimated_risk: risk,
97
+ }));
98
+ }
99
+ for (const ignorePath of inventory.ignore_candidates) {
100
+ steps.push(createStep(order++, {
101
+ step_id: `ignore-rules-${order.toString().padStart(3, "0")}`,
102
+ phase: "C",
103
+ category: "ignore-rules",
104
+ action: "append",
105
+ dest_path: ".polarisignore",
106
+ description: `Append ${ignorePath} to .polarisignore.`,
107
+ destructive: true,
108
+ requires_approval: true,
109
+ estimated_risk: "low",
110
+ }));
111
+ }
112
+ steps.push(createStep(order++, {
113
+ step_id: "atlas-generate",
114
+ phase: "C",
115
+ category: "atlas-generate",
116
+ action: "modify",
117
+ dest_path: ".polaris/map/index.json",
118
+ description: "Run polaris map index and record adoption baseline coverage.",
119
+ destructive: true,
120
+ requires_approval: true,
121
+ estimated_risk: "medium",
122
+ }));
123
+ steps.push(createStep(order++, {
124
+ step_id: "stage-adoption",
125
+ phase: "C",
126
+ category: "stage",
127
+ action: "modify",
128
+ dest_path: ".git/index",
129
+ description: "Stage coherent adoption changes and prepare optional commit.",
130
+ destructive: true,
131
+ requires_approval: true,
132
+ estimated_risk: "medium",
133
+ }));
134
+ return steps;
135
+ }
136
+ function buildImpactSummary(steps, inventory) {
137
+ const filesToCreate = steps.filter((step) => step.action === "create").length;
138
+ const filesToMove = steps.filter((step) => step.action === "move").length;
139
+ const filesToModify = steps.filter((step) => step.action === "modify" || step.action === "append").length;
140
+ const instructionFilesAffected = steps.filter((step) => step.category === "instruction-refactor" && step.action !== "skip").length;
141
+ return {
142
+ files_to_create: filesToCreate,
143
+ files_to_move: filesToMove,
144
+ files_to_modify: filesToModify,
145
+ instruction_files_affected: instructionFilesAffected,
146
+ smartdocs_candidates_moved: inventory.smartdocs_candidates.length,
147
+ cognition_files_to_generate: inventory.likely_canonical_folders.length * 2,
148
+ };
149
+ }
150
+ function generateAdoptionPlan(inventory, options = {}) {
151
+ const generatedAt = (options.now ?? new Date()).toISOString();
152
+ const steps = buildSteps(inventory);
153
+ return {
154
+ plan_id: formatPlanId(generatedAt),
155
+ generated_at: generatedAt,
156
+ repo_state: inventory.repo_state,
157
+ approved: false,
158
+ approved_at: null,
159
+ dry_run: options.dryRun ?? false,
160
+ steps,
161
+ impact_summary: buildImpactSummary(steps, inventory),
162
+ };
163
+ }
164
+ function renderAdoptionPlanMarkdown(plan) {
165
+ const lines = [];
166
+ lines.push("# Adoption Plan");
167
+ lines.push("");
168
+ lines.push(`- Plan ID: \`${plan.plan_id}\``);
169
+ lines.push(`- Generated at: ${plan.generated_at}`);
170
+ lines.push(`- Repo state: ${plan.repo_state}`);
171
+ lines.push(`- Approved: ${plan.approved ? "yes" : "no"}`);
172
+ lines.push(`- Approved at: ${plan.approved_at ?? "n/a"}`);
173
+ lines.push(`- Dry run: ${plan.dry_run ? "yes" : "no"}`);
174
+ lines.push("");
175
+ lines.push("## Impact Summary");
176
+ lines.push("");
177
+ lines.push("| Metric | Value |");
178
+ lines.push("| --- | ---: |");
179
+ lines.push(`| Files to create | ${plan.impact_summary.files_to_create} |`);
180
+ lines.push(`| Files to move | ${plan.impact_summary.files_to_move} |`);
181
+ lines.push(`| Files to modify | ${plan.impact_summary.files_to_modify} |`);
182
+ lines.push(`| Instruction files affected | ${plan.impact_summary.instruction_files_affected} |`);
183
+ lines.push(`| SmartDocs candidates moved | ${plan.impact_summary.smartdocs_candidates_moved} |`);
184
+ lines.push(`| Cognition files to generate | ${plan.impact_summary.cognition_files_to_generate} |`);
185
+ lines.push("");
186
+ for (const phase of ["A", "B", "C"]) {
187
+ const phaseSteps = plan.steps.filter((step) => step.phase === phase);
188
+ lines.push(`## Phase ${phase}`);
189
+ lines.push("");
190
+ if (phaseSteps.length === 0) {
191
+ lines.push("_No steps._");
192
+ lines.push("");
193
+ continue;
194
+ }
195
+ for (const step of phaseSteps) {
196
+ const source = step.source_path ? ` source: \`${step.source_path}\`` : "";
197
+ const dest = step.dest_path ? ` destination: \`${step.dest_path}\`` : "";
198
+ lines.push(`- **${step.order}. ${step.step_id}** — ${step.category} / ${step.action} / approval ${step.requires_approval ? "required" : "not required"} / risk ${step.estimated_risk} / status ${step.status}${source}${dest}`);
199
+ lines.push(` - ${step.description}`);
200
+ }
201
+ lines.push("");
202
+ }
203
+ return lines.join("\n");
204
+ }
205
+ function generateAdoptionPlanArtifacts(repoRoot, inventory, options = {}) {
206
+ const plan = generateAdoptionPlan(inventory, options);
207
+ const jsonPath = (0, node_path_1.join)(repoRoot, ".polaris", "adoption-plan.json");
208
+ const markdownPath = (0, node_path_1.join)(repoRoot, ".polaris", "adoption-plan.md");
209
+ const json = `${JSON.stringify(plan, null, 2)}\n`;
210
+ const markdown = renderAdoptionPlanMarkdown(plan);
211
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(repoRoot, ".polaris"), { recursive: true });
212
+ (0, node_fs_1.writeFileSync)(jsonPath, json, "utf-8");
213
+ (0, node_fs_1.writeFileSync)(markdownPath, markdown, "utf-8");
214
+ return {
215
+ plan,
216
+ json,
217
+ markdown,
218
+ jsonPath,
219
+ markdownPath,
220
+ wroteFiles: true,
221
+ };
222
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseCliArgs = parseCliArgs;
4
+ function parseCliArgs(argv) {
5
+ const flags = {};
6
+ const positional = [];
7
+ let i = 0;
8
+ while (i < argv.length) {
9
+ const arg = argv[i];
10
+ if (arg.startsWith("--")) {
11
+ const key = arg.slice(2);
12
+ const next = argv[i + 1];
13
+ if (next !== undefined && !next.startsWith("--")) {
14
+ flags[key] = next;
15
+ i += 2;
16
+ }
17
+ else {
18
+ flags[key] = true;
19
+ i += 1;
20
+ }
21
+ }
22
+ else {
23
+ positional.push(arg);
24
+ i += 1;
25
+ }
26
+ }
27
+ return { flags, positional };
28
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const args_js_1 = require("./args.js");
5
+ (0, vitest_1.describe)("parseCliArgs", () => {
6
+ (0, vitest_1.it)("parses --state-file value", () => {
7
+ const r = (0, args_js_1.parseCliArgs)(["--state-file", "path/to/state.json"]);
8
+ (0, vitest_1.expect)(r.flags["state-file"]).toBe("path/to/state.json");
9
+ (0, vitest_1.expect)(r.positional).toEqual([]);
10
+ });
11
+ (0, vitest_1.it)("parses boolean flag", () => {
12
+ const r = (0, args_js_1.parseCliArgs)(["--json"]);
13
+ (0, vitest_1.expect)(r.flags["json"]).toBe(true);
14
+ (0, vitest_1.expect)(r.positional).toEqual([]);
15
+ });
16
+ (0, vitest_1.it)("parses --dry-run", () => {
17
+ const r = (0, args_js_1.parseCliArgs)(["--dry-run"]);
18
+ (0, vitest_1.expect)(r.flags["dry-run"]).toBe(true);
19
+ });
20
+ (0, vitest_1.it)("collects positional args before flags", () => {
21
+ const r = (0, args_js_1.parseCliArgs)(["continue", "--json"]);
22
+ (0, vitest_1.expect)(r.positional).toEqual(["continue"]);
23
+ (0, vitest_1.expect)(r.flags["json"]).toBe(true);
24
+ });
25
+ (0, vitest_1.it)("returns empty flags and positional for empty input", () => {
26
+ const r = (0, args_js_1.parseCliArgs)([]);
27
+ (0, vitest_1.expect)(r.flags).toEqual({});
28
+ (0, vitest_1.expect)(r.positional).toEqual([]);
29
+ });
30
+ });
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ /**
3
+ * Centralized Polaris CLO branding strings and terminal banner.
4
+ * All brand copy lives here — change once, applies everywhere.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.BRAND = void 0;
8
+ exports.getBanner = getBanner;
9
+ exports.BRAND = {
10
+ name: "Polaris CLO",
11
+ fullName: "POLARIS CLO",
12
+ subtitle: "Command Line Orchestrator",
13
+ tagline: "Navigate · Align · Orchestrate",
14
+ pkg: "@lsctech/polaris",
15
+ };
16
+ const ESC = "\x1b";
17
+ const RESET = `${ESC}[0m`;
18
+ const BOLD = `${ESC}[1m`;
19
+ const DIM = `${ESC}[2m`;
20
+ const CYAN = `${ESC}[36m`;
21
+ const BRIGHT_BLUE = `${ESC}[94m`;
22
+ /**
23
+ * Returns the startup banner string.
24
+ * Strips ANSI codes when stdout is not a TTY (e.g. pipes, CI).
25
+ */
26
+ function getBanner(forceColor = false) {
27
+ const color = forceColor || (process.stdout.isTTY ?? false);
28
+ const star = color ? `${BRIGHT_BLUE}✦${RESET}` : "✦";
29
+ const title = color ? `${BOLD}${CYAN}${exports.BRAND.fullName}${RESET}` : exports.BRAND.fullName;
30
+ const sub = color ? `${DIM}${exports.BRAND.subtitle}${RESET}` : exports.BRAND.subtitle;
31
+ const tag = color ? `${DIM}${exports.BRAND.tagline}${RESET}` : exports.BRAND.tagline;
32
+ const rule = color ? `${DIM}${"─".repeat(38)}${RESET}` : "─".repeat(38);
33
+ return [
34
+ "",
35
+ ` ${star} ${title}`,
36
+ ` ${rule}`,
37
+ ` ${sub}`,
38
+ ` ${tag}`,
39
+ "",
40
+ ].join("\n");
41
+ }