@chemx/starter-kit 26.10.8-344 → 26.10.10-75

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 (805) hide show
  1. package/AGENTS.md +135 -32
  2. package/README.md +253 -199
  3. package/blueprints/atoms/a-button.svelte +11 -9
  4. package/blueprints/atoms/a-button.vue +2 -1
  5. package/blueprints/molecule-capsule/m-chemx-badge/m-chemx-badge.svelte +8 -4
  6. package/blueprints/molecule-capsule/m-chemx-badge/m-chemx-badge.tsx +8 -4
  7. package/blueprints/molecule-capsule/m-chemx-badge/m-chemx-badge.vue +8 -4
  8. package/blueprints/molecule-capsule/m-sample-card.svelte +2 -1
  9. package/blueprints/molecule-capsule/m-sample-card.tsx +2 -1
  10. package/blueprints/molecule-capsule/m-sample-card.vue +4 -2
  11. package/blueprints/workflows/chemx-audit.yml +15 -46
  12. package/cli/agent-json.js +40 -0
  13. package/cli/apply-edits.js +195 -0
  14. package/cli/audit/ai-slop-detector.js +62 -35
  15. package/cli/audit/ast-passes.js +52 -0
  16. package/cli/audit/ast-visitors.js +142 -83
  17. package/cli/audit/audit-plain.js +26 -0
  18. package/cli/audit/audit-summary.js +16 -3
  19. package/cli/audit/autofix-content.js +122 -0
  20. package/cli/audit/autofix.js +74 -159
  21. package/cli/audit/budget-rules.js +84 -0
  22. package/cli/audit/catch-predicates.js +51 -0
  23. package/cli/audit/chemx-dir.js +76 -0
  24. package/cli/audit/clone-detector.js +4 -2
  25. package/cli/audit/comment-regions.js +83 -0
  26. package/cli/audit/coverage.js +48 -0
  27. package/cli/audit/csharp-analyzer.js +47 -22
  28. package/cli/audit/discussion-store.js +9 -4
  29. package/cli/audit/extended-text-patterns.js +104 -54
  30. package/cli/audit/extended-visitors.js +26 -12
  31. package/cli/audit/feed.d.ts +77 -0
  32. package/cli/audit/feed.js +146 -0
  33. package/cli/audit/gate-delta.js +91 -0
  34. package/cli/audit/gate-verdict.js +25 -3
  35. package/cli/audit/history.d.ts +14 -2
  36. package/cli/audit/history.js +89 -101
  37. package/cli/audit/hook-shape-validator.js +18 -9
  38. package/cli/audit/lexicon-predicates.js +125 -0
  39. package/cli/audit/lifecycle-predicates.js +106 -0
  40. package/cli/audit/line-budgets.js +154 -0
  41. package/cli/audit/metrics.js +56 -37
  42. package/cli/audit/mutable-ref-predicate.js +54 -0
  43. package/cli/audit/parseable-code.js +11 -0
  44. package/cli/audit/pattern-detector.js +56 -28
  45. package/cli/audit/project-figures.js +28 -0
  46. package/cli/audit/prompt-rule-lines.js +46 -0
  47. package/cli/audit/prompts.js +74 -46
  48. package/cli/audit/prop-surface.js +74 -0
  49. package/cli/audit/ratchet.js +112 -23
  50. package/cli/audit/render-depth.js +79 -0
  51. package/cli/audit/reporter-banner.js +7 -4
  52. package/cli/audit/reporter-grades.js +52 -34
  53. package/cli/audit/reporter-grouping.js +10 -5
  54. package/cli/audit/reporter-markdown.js +16 -8
  55. package/cli/audit/reporter-sections.js +31 -16
  56. package/cli/audit/reporter-summary.js +28 -16
  57. package/cli/audit/reporter-utils.js +54 -30
  58. package/cli/audit/roadmap.js +20 -15
  59. package/cli/audit/rule-overrides.js +78 -0
  60. package/cli/audit/rule-pillars.js +43 -0
  61. package/cli/audit/rule-revisions.js +42 -0
  62. package/cli/audit/rules-helpers.js +13 -63
  63. package/cli/audit/rules-predicates.d.ts +1 -0
  64. package/cli/audit/rules-predicates.js +84 -64
  65. package/cli/audit/rules-registry.js +94 -10
  66. package/cli/audit/rules.js +92 -171
  67. package/cli/audit/shallow-catch-csharp.js +49 -0
  68. package/cli/audit/shallow-catch-escalation.js +157 -0
  69. package/cli/audit/shallow-catch-reads.js +116 -0
  70. package/cli/audit/social-gh.js +18 -9
  71. package/cli/audit/social-git.js +82 -40
  72. package/cli/audit/social-http.js +17 -9
  73. package/cli/audit/social-publisher.js +14 -7
  74. package/cli/audit/social.js +39 -30
  75. package/cli/audit/staged-delta.js +67 -0
  76. package/cli/audit/status-file.js +67 -0
  77. package/cli/audit/structural-weight-evaluator.js +17 -29
  78. package/cli/audit/structural-weight.js +30 -13
  79. package/cli/audit/suppressions.js +130 -0
  80. package/cli/audit/template-rules.js +82 -0
  81. package/cli/audit/types.d.ts +24 -1
  82. package/cli/audit-engine.js +128 -0
  83. package/cli/audit-preflight-git.js +15 -1
  84. package/cli/audit-preflight.js +6 -4
  85. package/cli/audit-scan.js +180 -0
  86. package/cli/audit-scope.js +31 -14
  87. package/cli/audit.js +6 -201
  88. package/cli/babel-lazy.js +41 -0
  89. package/cli/badge.js +9 -6
  90. package/cli/banner.js +37 -0
  91. package/cli/build/child-registry.js +57 -0
  92. package/cli/build/executor.js +122 -48
  93. package/cli/build.js +75 -25
  94. package/cli/cli-args.js +107 -0
  95. package/cli/columnar.js +6 -3
  96. package/cli/commands/cmd-audit-each.js +164 -0
  97. package/cli/commands/cmd-audit-feed.js +78 -0
  98. package/cli/commands/cmd-audit.js +136 -57
  99. package/cli/commands/cmd-batch.js +60 -0
  100. package/cli/commands/cmd-check.js +74 -0
  101. package/cli/commands/cmd-project.js +18 -9
  102. package/cli/commands/cmd-router.js +148 -32
  103. package/cli/commands/cmd-show.js +56 -0
  104. package/cli/commands/cmd-staged-delta.js +27 -0
  105. package/cli/commands/cmd-wrappers-files.js +77 -0
  106. package/cli/commands/cmd-wrappers-git.js +122 -0
  107. package/cli/commands/cmd-wrappers-json.js +101 -0
  108. package/cli/commands/cmd-wrappers.js +7 -322
  109. package/cli/commands/unknown-flags.js +228 -0
  110. package/cli/commands-schema-badge.js +73 -0
  111. package/cli/commands-schema-commit.js +21 -0
  112. package/cli/commands-schema-edit.js +106 -0
  113. package/cli/commands-schema-host.js +65 -0
  114. package/cli/commands-schema-ops.js +127 -0
  115. package/cli/commands-schema-patterns.js +69 -0
  116. package/cli/commands-schema-report.js +18 -0
  117. package/cli/commands-schema-search.js +121 -0
  118. package/cli/commands-schema-setup.js +30 -0
  119. package/cli/commands-schema-verify.js +89 -0
  120. package/cli/commands-schema-wrappers.js +131 -0
  121. package/cli/commands-schema.js +26 -408
  122. package/cli/comment-ranges.js +108 -0
  123. package/cli/commit/commit-args.js +73 -0
  124. package/cli/commit/commit-cli.js +25 -0
  125. package/cli/commit/commit-facts.js +49 -0
  126. package/cli/commit/commit-git.js +98 -0
  127. package/cli/commit/commit-index.js +35 -0
  128. package/cli/commit/commit-message.js +52 -0
  129. package/cli/commit/commit-record.js +68 -0
  130. package/cli/commit/commit-run.js +160 -0
  131. package/cli/commit/commit-validate.js +62 -0
  132. package/cli/config/index.js +54 -8
  133. package/cli/config/loader.js +77 -8
  134. package/cli/config/profiles.js +7 -0
  135. package/cli/conflicts-cli.js +118 -0
  136. package/cli/conflicts.js +104 -0
  137. package/cli/create.js +11 -6
  138. package/cli/db-project-stamp.js +124 -0
  139. package/cli/docs-check/command-tree.js +27 -0
  140. package/cli/docs-check/extract.js +151 -0
  141. package/cli/docs-check/resolve.js +85 -0
  142. package/cli/docs-check/run.js +88 -0
  143. package/cli/doctor/check-env.js +43 -0
  144. package/cli/doctor/check-host.js +115 -0
  145. package/cli/doctor/check-index.js +93 -0
  146. package/cli/doctor/check-mcp.js +78 -0
  147. package/cli/doctor/doctor-cli.js +60 -0
  148. package/cli/doctor/kit-locate.js +40 -0
  149. package/cli/doctor/proc-scan.js +66 -0
  150. package/cli/edit-atomic.js +75 -0
  151. package/cli/edit-diff.js +98 -0
  152. package/cli/edit-guardrails.js +77 -0
  153. package/cli/edit-locks.js +128 -0
  154. package/cli/embeddings/vectorizer.js +9 -5
  155. package/cli/errors/catcher.js +45 -52
  156. package/cli/errors/formatter.js +14 -10
  157. package/cli/errors/policy.js +26 -0
  158. package/cli/errors/publisher.js +5 -1
  159. package/cli/errors/report-output.js +67 -0
  160. package/cli/errors/sanitizer.js +52 -3
  161. package/cli/errors/storage.js +17 -5
  162. package/cli/explode-importers.js +102 -0
  163. package/cli/explode-path-args.js +115 -0
  164. package/cli/explode-plan.js +153 -0
  165. package/cli/explode-prologue.js +43 -0
  166. package/cli/explode-relocate.js +73 -0
  167. package/cli/exploder.js +205 -193
  168. package/cli/forge/anchors.js +50 -0
  169. package/cli/forge/audit-forge.js +58 -0
  170. package/cli/forge/binding-walk.js +84 -0
  171. package/cli/forge/bindings.js +238 -0
  172. package/cli/forge/blueprint-cli.js +153 -0
  173. package/cli/forge/blueprint-context.js +69 -0
  174. package/cli/forge/blueprint-members.js +82 -0
  175. package/cli/forge/blueprint-store.js +106 -0
  176. package/cli/forge/blueprint-target.js +44 -0
  177. package/cli/forge/blueprint.js +276 -0
  178. package/cli/forge/body-end-cache.js +34 -0
  179. package/cli/forge/body-ends.js +86 -0
  180. package/cli/forge/canon-inline.js +342 -0
  181. package/cli/forge/canon-logic.js +106 -0
  182. package/cli/forge/canon-nodes.js +270 -0
  183. package/cli/forge/canon-print.js +120 -0
  184. package/cli/forge/canonicalize.js +49 -0
  185. package/cli/forge/conventions.js +51 -0
  186. package/cli/forge/drift.js +120 -0
  187. package/cli/forge/exclusions.js +21 -0
  188. package/cli/forge/exits.js +76 -0
  189. package/cli/forge/facets.js +86 -0
  190. package/cli/forge/file-units.js +53 -0
  191. package/cli/forge/fingerprint-file.js +52 -0
  192. package/cli/forge/fingerprint-session.js +215 -0
  193. package/cli/forge/fingerprint-sync.js +74 -0
  194. package/cli/forge/fingerprint-visitors.js +66 -0
  195. package/cli/forge/fixtures/heal/a7-dry-run.diff.txt +179 -0
  196. package/cli/forge/fixtures/heal/cli/commit/commit-facts.js.txt +49 -0
  197. package/cli/forge/fixtures/heal/cli/doctor/check-host.js.txt +117 -0
  198. package/cli/forge/fixtures/heal/cli/doctor/kit-locate.js.txt +42 -0
  199. package/cli/forge/fixtures/heal/cli/hooks/guard-paths.js.txt +80 -0
  200. package/cli/forge/fixtures/heal/cli/hooks/project-status.js.txt +62 -0
  201. package/cli/forge/fixtures/heal/cli/main.js.txt +169 -0
  202. package/cli/forge/fixtures/heal/cli/mcp/context.js.txt +81 -0
  203. package/cli/forge/fixtures/heal/cli/mcp/installer-report.js.txt +47 -0
  204. package/cli/forge/fixtures/heal/cli/path-scope.js.txt +169 -0
  205. package/cli/forge/fixtures/heal/cli/project-detector.js.txt +364 -0
  206. package/cli/forge/fixtures/heal/cli/project-markers.js.txt +42 -0
  207. package/cli/forge/fixtures/heal/cli/team/coordination-root.js.txt +161 -0
  208. package/cli/forge/fixtures/heal/cli/team/usage-reader.js.txt +109 -0
  209. package/cli/forge/fixtures/heal/cli/test-slots.js.txt +129 -0
  210. package/cli/forge/fixtures/social-gh.js.txt +131 -0
  211. package/cli/forge/fixtures/team-flags.js.txt +214 -0
  212. package/cli/forge/fold.js +199 -0
  213. package/cli/forge/forge-groups.js +200 -0
  214. package/cli/forge/forge-report.js +73 -0
  215. package/cli/forge/fuzz/binding-hook.js +36 -0
  216. package/cli/forge/fuzz/choices.js +40 -0
  217. package/cli/forge/fuzz/classes.js +41 -0
  218. package/cli/forge/fuzz/coverage.js +26 -0
  219. package/cli/forge/fuzz/gen-alias.js +61 -0
  220. package/cli/forge/fuzz/gen-control.js +73 -0
  221. package/cli/forge/fuzz/gen-kit.js +75 -0
  222. package/cli/forge/fuzz/gen-logic.js +77 -0
  223. package/cli/forge/fuzz/gen-mixed.js +204 -0
  224. package/cli/forge/fuzz/gen-modules.js +80 -0
  225. package/cli/forge/fuzz/gen-objects.js +92 -0
  226. package/cli/forge/fuzz/gen-scope.js +131 -0
  227. package/cli/forge/fuzz/gen-templates.js +87 -0
  228. package/cli/forge/fuzz/harness.js +314 -0
  229. package/cli/forge/fuzz/pair-check.js +115 -0
  230. package/cli/forge/fuzz/resolve.js +32 -0
  231. package/cli/forge/fuzz/run.js +121 -0
  232. package/cli/forge/fuzz/sandbox.js +108 -0
  233. package/cli/forge/fuzz/seeds.js +119 -0
  234. package/cli/forge/fuzz/slow-shard.js +60 -0
  235. package/cli/forge/fuzz/template-oracle.js +148 -0
  236. package/cli/forge/fuzz/transpile.js +61 -0
  237. package/cli/forge/gates.js +115 -0
  238. package/cli/forge/group-shape.js +137 -0
  239. package/cli/forge/group-store.js +160 -0
  240. package/cli/forge/group.js +280 -0
  241. package/cli/forge/gt-sandbox.js +83 -0
  242. package/cli/forge/gt-scaffold.js +110 -0
  243. package/cli/forge/hash-labels.js +117 -0
  244. package/cli/forge/hash.js +119 -0
  245. package/cli/forge/heal-apply.js +170 -0
  246. package/cli/forge/heal-cli.js +132 -0
  247. package/cli/forge/heal-leases.js +52 -0
  248. package/cli/forge/heal-locate.js +70 -0
  249. package/cli/forge/heal-match.js +208 -0
  250. package/cli/forge/heal-ops.js +197 -0
  251. package/cli/forge/heal-plan.js +143 -0
  252. package/cli/forge/heal-sandbox.js +126 -0
  253. package/cli/forge/heal-specs.js +80 -0
  254. package/cli/forge/heal-store.js +80 -0
  255. package/cli/forge/heal-text.js +60 -0
  256. package/cli/forge/heal-typecheck.js +108 -0
  257. package/cli/forge/heal-undo.js +74 -0
  258. package/cli/forge/heal-verify.js +148 -0
  259. package/cli/forge/hole-kinds.js +126 -0
  260. package/cli/forge/inline-mode.js +6 -0
  261. package/cli/forge/inline-on.setup.js +4 -0
  262. package/cli/forge/lgg-stage.js +125 -0
  263. package/cli/forge/lgg.js +197 -0
  264. package/cli/forge/library-match.js +74 -0
  265. package/cli/forge/murmur.js +86 -0
  266. package/cli/forge/naming.js +101 -0
  267. package/cli/forge/pattern-schema-ddl.js +157 -0
  268. package/cli/forge/placement.js +165 -0
  269. package/cli/forge/rank.js +174 -0
  270. package/cli/forge/refine.js +93 -0
  271. package/cli/forge/rejected-members.js +92 -0
  272. package/cli/forge/rejects.js +77 -0
  273. package/cli/forge/root-shapes.js +84 -0
  274. package/cli/forge/run-cache.js +145 -0
  275. package/cli/forge/sibling-blocks.js +41 -0
  276. package/cli/forge/siblings.js +140 -0
  277. package/cli/forge/store.js +180 -0
  278. package/cli/forge/template-normalize.js +209 -0
  279. package/cli/forge/template-roles.js +86 -0
  280. package/cli/forge/template-units.js +148 -0
  281. package/cli/forge/templates.js +42 -0
  282. package/cli/forge/unify-step.js +65 -0
  283. package/cli/forge/unit-floor.js +74 -0
  284. package/cli/forge/unit-hash.js +229 -0
  285. package/cli/forge/unit-trees.js +153 -0
  286. package/cli/forge/units.js +261 -0
  287. package/cli/forge/windows.js +129 -0
  288. package/cli/friction/friction-cli.js +71 -0
  289. package/cli/friction/friction-export.js +54 -0
  290. package/cli/friction/friction-log.js +54 -0
  291. package/cli/friction/usage-classify.js +56 -0
  292. package/cli/friction/usage-report.js +86 -0
  293. package/cli/friction/wrong-call.js +12 -0
  294. package/cli/fs-json.js +17 -0
  295. package/cli/generator-compact.js +55 -0
  296. package/cli/generator-help.js +16 -15
  297. package/cli/generator-indexer.js +2 -1
  298. package/cli/generator-jig-cli.js +11 -7
  299. package/cli/generator-jig.js +38 -33
  300. package/cli/generator-templates/archetypes/index.js +30 -13
  301. package/cli/generator-templates/archetypes/vector-matcher.js +8 -4
  302. package/cli/generator-templates/compact.js +4 -2
  303. package/cli/generator-templates/controller-converters.js +23 -14
  304. package/cli/generator-templates/controller.js +10 -5
  305. package/cli/generator-templates/hooks.js +4 -2
  306. package/cli/generator-templates/naming.js +2 -1
  307. package/cli/generator-templates/react.js +2 -1
  308. package/cli/generator-templates/specs.js +4 -2
  309. package/cli/generator-templates/svelte.js +4 -2
  310. package/cli/generator-templates/types.js +6 -3
  311. package/cli/generator-templates/views.js +4 -2
  312. package/cli/generator-templates/vue.js +4 -2
  313. package/cli/generator-writes.js +24 -0
  314. package/cli/generator.d.ts +1 -1
  315. package/cli/generator.js +86 -127
  316. package/cli/git-file-listing.js +69 -0
  317. package/cli/help-args.js +18 -0
  318. package/cli/help.d.ts +7 -3
  319. package/cli/help.js +94 -149
  320. package/cli/hooks/bypass-log.js +44 -0
  321. package/cli/hooks/claude-post-edit.js +79 -0
  322. package/cli/hooks/claude-pre-tool.js +178 -0
  323. package/cli/hooks/claude-settings-merge.js +101 -0
  324. package/cli/hooks/dispatch-identity.js +125 -0
  325. package/cli/hooks/entry.js +181 -0
  326. package/cli/hooks/foreign-identity.js +60 -0
  327. package/cli/hooks/guard-args.js +55 -0
  328. package/cli/hooks/guard-cases.js +94 -0
  329. package/cli/hooks/guard-config.js +43 -0
  330. package/cli/hooks/guard-invocation.js +106 -0
  331. package/cli/hooks/guard-paths.js +80 -0
  332. package/cli/hooks/guard-route.js +211 -0
  333. package/cli/hooks/guard-rules-nudge.js +37 -0
  334. package/cli/hooks/guard-rules-reads.js +66 -0
  335. package/cli/hooks/guard-rules-shell.js +239 -0
  336. package/cli/hooks/guard-rules.js +114 -0
  337. package/cli/hooks/hook-commands.js +21 -0
  338. package/cli/hooks/install-hooks-apply.js +36 -0
  339. package/cli/hooks/install-hooks-cli.js +100 -0
  340. package/cli/hooks/install-hooks-config.js +48 -0
  341. package/cli/hooks/install-hooks-pins.js +66 -0
  342. package/cli/hooks/install-hooks-plan.js +56 -0
  343. package/cli/hooks/install-hooks-status.js +7 -0
  344. package/cli/hooks/interpreter-writes.js +195 -0
  345. package/cli/hooks/launcher.js +60 -0
  346. package/cli/hooks/mcp-json-merge.js +39 -0
  347. package/cli/hooks/native-edit-lock.js +40 -0
  348. package/cli/hooks/native-tool-policy.js +152 -0
  349. package/cli/hooks/out-of-band-edits.js +141 -0
  350. package/cli/hooks/post-edit-scope.js +43 -0
  351. package/cli/hooks/project-status.js +59 -0
  352. package/cli/hooks/repo-membership.js +32 -0
  353. package/cli/hooks/run-hook.js +79 -0
  354. package/cli/hooks/session-identity.js +153 -0
  355. package/cli/hooks/session-start.js +50 -0
  356. package/cli/hooks/shell-lexer-readers.js +76 -0
  357. package/cli/hooks/shell-lexer-state.js +59 -0
  358. package/cli/hooks/shell-lexer.js +110 -0
  359. package/cli/hooks/shell-parse.js +232 -0
  360. package/cli/hooks/statusline.js +27 -0
  361. package/cli/hooks/xatoms-hints.js +38 -0
  362. package/cli/host-protocol.js +109 -0
  363. package/cli/host-shims.js +9 -8
  364. package/cli/index-admission.js +41 -0
  365. package/cli/index-freshness.js +83 -0
  366. package/cli/index-row-check.js +58 -0
  367. package/cli/index.js +52 -150
  368. package/cli/installer-templates.js +67 -75
  369. package/cli/installer.d.ts +16 -1
  370. package/cli/installer.js +159 -58
  371. package/cli/languages.js +8 -4
  372. package/cli/lattice-directives.js +24 -0
  373. package/cli/lattice-payload.js +34 -0
  374. package/cli/{tesseract-state.js → lattice-state.js} +8 -4
  375. package/cli/lease-view.js +48 -0
  376. package/cli/library/entry-fp.js +42 -0
  377. package/cli/library/entry-schema.js +90 -0
  378. package/cli/library/library-tasks.js +25 -0
  379. package/cli/library/registry.js +56 -0
  380. package/cli/library/reverify.js +56 -0
  381. package/cli/library/verify-checks.js +89 -0
  382. package/cli/library/verify.js +81 -0
  383. package/cli/license-config.js +124 -0
  384. package/cli/license.js +168 -135
  385. package/cli/line-count.js +23 -0
  386. package/cli/literal-replace.js +107 -0
  387. package/cli/main.js +166 -0
  388. package/cli/mcp/antigravity.js +11 -9
  389. package/cli/mcp/batch.js +59 -0
  390. package/cli/mcp/call-args.js +75 -0
  391. package/cli/mcp/call-effects.js +57 -0
  392. package/cli/mcp/call-scope.js +70 -62
  393. package/cli/mcp/context.js +81 -0
  394. package/cli/mcp/envelope.js +62 -0
  395. package/cli/mcp/fingerprint.js +26 -0
  396. package/cli/mcp/fresh-entry.js +34 -0
  397. package/cli/mcp/fresh-protocol.js +37 -0
  398. package/cli/mcp/fresh-runner.js +40 -0
  399. package/cli/mcp/help.js +53 -0
  400. package/cli/mcp/index.js +9 -5
  401. package/cli/mcp/inflight.js +47 -0
  402. package/cli/mcp/installer-jsonc.js +64 -0
  403. package/cli/mcp/installer-package.js +54 -0
  404. package/cli/mcp/installer-report.js +47 -0
  405. package/cli/mcp/installer-write.js +117 -0
  406. package/cli/mcp/installer.js +88 -187
  407. package/cli/mcp/manifests-analysis.js +156 -0
  408. package/cli/mcp/manifests-runners.js +48 -0
  409. package/cli/mcp/manifests-team.js +100 -0
  410. package/cli/mcp/manifests.js +69 -309
  411. package/cli/mcp/offload-worker.js +11 -0
  412. package/cli/mcp/offload.js +18 -0
  413. package/cli/mcp/patterns-cli.js +76 -0
  414. package/cli/mcp/patterns-forge-cli.js +120 -0
  415. package/cli/mcp/prompts.js +13 -10
  416. package/cli/mcp/resources.js +8 -35
  417. package/cli/mcp/roots.js +46 -0
  418. package/cli/mcp/scorecard-worker.js +7 -0
  419. package/cli/mcp/scorecard.js +42 -0
  420. package/cli/mcp/server-info.js +28 -0
  421. package/cli/mcp/server.js +91 -291
  422. package/cli/mcp/spec-harness.js +62 -0
  423. package/cli/mcp/stale-exec.js +48 -0
  424. package/cli/mcp/staleness.js +26 -0
  425. package/cli/mcp/stdio.js +141 -0
  426. package/cli/mcp/tool-call.js +73 -0
  427. package/cli/mcp/tools-audit-feed.js +33 -0
  428. package/cli/mcp/tools-audit.js +13 -7
  429. package/cli/mcp/tools-generate.js +3 -3
  430. package/cli/mcp/tools-lazy.js +39 -0
  431. package/cli/mcp/tools-patch.js +93 -21
  432. package/cli/mcp/tools-patterns.js +6 -3
  433. package/cli/mcp/tools-project.js +8 -4
  434. package/cli/mcp/tools-q-modes.js +15 -14
  435. package/cli/mcp/tools-q.js +94 -33
  436. package/cli/mcp/tools-read.js +30 -80
  437. package/cli/mcp/tools-team-feed.js +10 -8
  438. package/cli/mcp/tools-team-locks.js +22 -10
  439. package/cli/mcp/tools-team-mailbox.js +8 -7
  440. package/cli/mcp/tools-team-tasks.js +125 -38
  441. package/cli/mcp/tools-team.js +14 -7
  442. package/cli/mcp/tools-verify.js +44 -15
  443. package/cli/mcp/tools-write.js +11 -16
  444. package/cli/mcp/tools.js +202 -68
  445. package/cli/mcp/worker-run.js +24 -0
  446. package/cli/missing-imports.js +52 -0
  447. package/cli/mutation-args.js +96 -0
  448. package/cli/mutators.js +164 -61
  449. package/cli/navigator-actions.js +19 -13
  450. package/cli/navigator-banner-helpers.js +1 -26
  451. package/cli/navigator-banner.js +5 -3
  452. package/cli/navigator-conversion.js +23 -12
  453. package/cli/navigator-grades.js +70 -35
  454. package/cli/navigator-guide.js +13 -11
  455. package/cli/navigator-menu.js +80 -166
  456. package/cli/navigator-paged.js +15 -8
  457. package/cli/navigator-sections.js +32 -0
  458. package/cli/navigator-share.js +53 -39
  459. package/cli/navigator.d.ts +25 -5
  460. package/cli/navigator.js +14 -41
  461. package/cli/network-policy.js +72 -0
  462. package/cli/network-recorder.fixture.mjs +35 -0
  463. package/cli/outline/ast-outline.js +120 -0
  464. package/cli/outline/style-outline.js +42 -0
  465. package/cli/outline/vue-outline.js +88 -0
  466. package/cli/patcher-cli.js +255 -0
  467. package/cli/patcher.d.ts +55 -24
  468. package/cli/patcher.js +167 -358
  469. package/cli/path-scope.js +78 -22
  470. package/cli/patterns/fixtures/gt/A1.txt +109 -0
  471. package/cli/patterns/fixtures/gt/A10.txt +13 -0
  472. package/cli/patterns/fixtures/gt/A11.txt +10 -0
  473. package/cli/patterns/fixtures/gt/A12.txt +29 -0
  474. package/cli/patterns/fixtures/gt/A13.txt +39 -0
  475. package/cli/patterns/fixtures/gt/A14.txt +45 -0
  476. package/cli/patterns/fixtures/gt/A15.txt +70 -0
  477. package/cli/patterns/fixtures/gt/A16.txt +59 -0
  478. package/cli/patterns/fixtures/gt/A17.txt +29 -0
  479. package/cli/patterns/fixtures/gt/A18.txt +9 -0
  480. package/cli/patterns/fixtures/gt/A19.txt +29 -0
  481. package/cli/patterns/fixtures/gt/A2.txt +28 -0
  482. package/cli/patterns/fixtures/gt/A20.txt +83 -0
  483. package/cli/patterns/fixtures/gt/A21.txt +138 -0
  484. package/cli/patterns/fixtures/gt/A22.txt +32 -0
  485. package/cli/patterns/fixtures/gt/A23.txt +37 -0
  486. package/cli/patterns/fixtures/gt/A24.txt +67 -0
  487. package/cli/patterns/fixtures/gt/A25.txt +41 -0
  488. package/cli/patterns/fixtures/gt/A26.txt +29 -0
  489. package/cli/patterns/fixtures/gt/A3.txt +17 -0
  490. package/cli/patterns/fixtures/gt/A4.txt +44 -0
  491. package/cli/patterns/fixtures/gt/A5.txt +32 -0
  492. package/cli/patterns/fixtures/gt/A6.txt +15 -0
  493. package/cli/patterns/fixtures/gt/A7.txt +79 -0
  494. package/cli/patterns/fixtures/gt/A8.txt +41 -0
  495. package/cli/patterns/fixtures/gt/A9.txt +42 -0
  496. package/cli/patterns/fixtures/gt/B1.txt +11 -0
  497. package/cli/patterns/fixtures/gt/B10.txt +41 -0
  498. package/cli/patterns/fixtures/gt/B11.txt +7 -0
  499. package/cli/patterns/fixtures/gt/B2.txt +19 -0
  500. package/cli/patterns/fixtures/gt/B3.txt +70 -0
  501. package/cli/patterns/fixtures/gt/B4.txt +55 -0
  502. package/cli/patterns/fixtures/gt/B5.txt +21 -0
  503. package/cli/patterns/fixtures/gt/B6.txt +15 -0
  504. package/cli/patterns/fixtures/gt/B7.txt +24 -0
  505. package/cli/patterns/fixtures/gt/B8.txt +40 -0
  506. package/cli/patterns/fixtures/gt/B9.txt +18 -0
  507. package/cli/patterns/fixtures/gt/C1.txt +26 -0
  508. package/cli/patterns/fixtures/gt/C2.txt +33 -0
  509. package/cli/patterns/fixtures/gt/C3.txt +26 -0
  510. package/cli/patterns/fixtures/gt/C4.txt +7 -0
  511. package/cli/patterns/fixtures/gt/C5.txt +29 -0
  512. package/cli/patterns/fixtures/gt/C6.txt +7 -0
  513. package/cli/patterns/fixtures/gt/C7.txt +18 -0
  514. package/cli/patterns/fixtures/gt/labels.json +1837 -0
  515. package/cli/patterns/gt-build.js +55 -0
  516. package/cli/patterns/gt-locations.js +76 -0
  517. package/cli/patterns/gt-resolve.js +66 -0
  518. package/cli/patterns/gt-score-cli.js +80 -0
  519. package/cli/patterns/gt-score.js +188 -0
  520. package/cli/patterns/gt-text.js +79 -0
  521. package/cli/pillars-wizard.js +53 -24
  522. package/cli/pillars-write-guard.js +4 -1
  523. package/cli/postinstall.js +22 -19
  524. package/cli/project-detector.js +60 -35
  525. package/cli/project-markers.js +42 -0
  526. package/cli/project-scope.js +20 -0
  527. package/cli/read-revision.js +70 -0
  528. package/cli/reader-cards-gate.js +29 -0
  529. package/cli/reader-cards.js +153 -0
  530. package/cli/reader-cli.js +45 -18
  531. package/cli/reader-format.js +48 -0
  532. package/cli/reader-logic.js +128 -250
  533. package/cli/reader.js +210 -221
  534. package/cli/request-context.js +9 -0
  535. package/cli/result-status.js +23 -0
  536. package/cli/rules.js +81 -0
  537. package/cli/scaffold.js +80 -51
  538. package/cli/scan-ignore.js +12 -0
  539. package/cli/search-args.js +102 -0
  540. package/cli/search-ast-module.js +103 -0
  541. package/cli/search-ast.js +75 -112
  542. package/cli/search-commands-blast.js +70 -0
  543. package/cli/search-commands-graph.js +57 -105
  544. package/cli/search-commands-hazards.js +105 -0
  545. package/cli/search-commands-literal.js +102 -0
  546. package/cli/search-commands-semantic.js +39 -27
  547. package/cli/search-commands.js +93 -186
  548. package/cli/search-db.js +52 -252
  549. package/cli/search-debug.js +13 -0
  550. package/cli/search-graph-edges.js +112 -0
  551. package/cli/search-index-meta.js +66 -0
  552. package/cli/search-index-write.js +153 -0
  553. package/cli/search-literal-files.js +64 -0
  554. package/cli/search-literal.js +150 -0
  555. package/cli/search-output.js +88 -0
  556. package/cli/search-queries-graph.js +120 -193
  557. package/cli/search-queries-semantic.js +41 -14
  558. package/cli/search-queries-similar.js +2 -1
  559. package/cli/search-queries.js +46 -21
  560. package/cli/search-query-view.js +67 -0
  561. package/cli/search-rank.js +54 -0
  562. package/cli/search-replace-blocks.js +120 -0
  563. package/cli/search-resolve.js +52 -0
  564. package/cli/search-root.js +78 -0
  565. package/cli/search-scan.js +102 -0
  566. package/cli/search-schema-ddl.js +172 -0
  567. package/cli/search-schema.js +135 -220
  568. package/cli/search-session.js +11 -0
  569. package/cli/search-sync-paths.js +78 -0
  570. package/cli/search-sync-plan.js +63 -0
  571. package/cli/search-sync-rows.js +96 -0
  572. package/cli/search-sync.js +128 -0
  573. package/cli/search-tokenizer.js +8 -4
  574. package/cli/search.d.ts +26 -5
  575. package/cli/search.js +156 -410
  576. package/cli/sfc/component-resolver.js +96 -0
  577. package/cli/sfc/import-coverage.js +24 -0
  578. package/cli/sfc/module-aliases.js +102 -0
  579. package/cli/sfc/script-asts.js +51 -0
  580. package/cli/sfc/sfc-metadata.js +104 -0
  581. package/cli/sfc/sfc-parse.js +101 -0
  582. package/cli/sfc/svelte-parse.js +46 -0
  583. package/cli/sfc/template-walk.js +78 -0
  584. package/cli/sfc-scripts.js +60 -0
  585. package/cli/share-consent.js +49 -0
  586. package/cli/share-outcome.js +57 -0
  587. package/cli/silence-warnings.js +2 -1
  588. package/cli/source-parse.js +130 -0
  589. package/cli/spec-isolated-home.js +17 -0
  590. package/cli/spec-support/import-trace.mjs +22 -0
  591. package/cli/spec-support/run-cli.js +58 -0
  592. package/cli/sqlite-memory.js +47 -0
  593. package/cli/status-command.js +107 -0
  594. package/cli/symbol-locator.js +121 -0
  595. package/cli/team/agent-identity.js +58 -0
  596. package/cli/team/audit-run-adoption.js +117 -0
  597. package/cli/team/audit-run-bypass.js +177 -0
  598. package/cli/team/audit-run-calls.js +108 -0
  599. package/cli/team/audit-run-db.js +181 -0
  600. package/cli/team/audit-run-identity.js +80 -0
  601. package/cli/team/audit-run-invocations.js +130 -0
  602. package/cli/team/audit-run-protocol.js +258 -0
  603. package/cli/team/audit-run-render.js +107 -0
  604. package/cli/team/audit-run-shas.js +179 -0
  605. package/cli/team/audit-run.js +203 -0
  606. package/cli/team/claim-ignore-deps.js +16 -0
  607. package/cli/team/coordination-busy.js +164 -0
  608. package/cli/team/coordination-db.js +85 -0
  609. package/cli/team/coordination-fixture.js +53 -0
  610. package/cli/team/coordination-repos.js +72 -0
  611. package/cli/team/coordination-root.js +161 -0
  612. package/cli/team/coordination-target.js +114 -0
  613. package/cli/team/dispatch-templates/dispatch-v1.js +228 -0
  614. package/cli/team/edit-shas.js +45 -0
  615. package/cli/team/lease-activity.js +130 -0
  616. package/cli/team/lease-cap.js +67 -0
  617. package/cli/team/lease-contention.js +30 -0
  618. package/cli/team/lease-key.js +46 -0
  619. package/cli/team/lease-lapse.js +83 -0
  620. package/cli/team/lease-reacquire.js +99 -0
  621. package/cli/team/lease-renew.js +97 -0
  622. package/cli/team/lease-roots.js +30 -0
  623. package/cli/team/lease-waiter-notice.js +48 -0
  624. package/cli/team/staged-leases.js +64 -0
  625. package/cli/team/task-completion-output.js +78 -0
  626. package/cli/team/task-detail-sections.js +86 -0
  627. package/cli/team/task-list-view.js +10 -1
  628. package/cli/team/task-ref.js +73 -0
  629. package/cli/team/task-target.js +53 -0
  630. package/cli/team/task-tier.js +17 -0
  631. package/cli/team/team-brief.js +78 -0
  632. package/cli/team/team-commands-board.js +118 -0
  633. package/cli/team/team-commands-dispatch.js +85 -0
  634. package/cli/team/team-commands-lock-staged.js +87 -0
  635. package/cli/team/team-commands-lock-views.js +144 -0
  636. package/cli/team/team-commands-lock.js +115 -26
  637. package/cli/team/team-commands-migrate.js +171 -0
  638. package/cli/team/team-commands-profile.js +44 -0
  639. package/cli/team/team-commands-repo.js +114 -0
  640. package/cli/team/team-commands-task.js +312 -0
  641. package/cli/team/team-commands-tokens.js +57 -0
  642. package/cli/team/team-commands-triage.js +43 -0
  643. package/cli/team/team-commands-vds.js +2 -1
  644. package/cli/team/team-commands.js +108 -463
  645. package/cli/team/team-db-agents.js +12 -6
  646. package/cli/team/team-db-feed.js +25 -13
  647. package/cli/team/team-db-lock-promotion.js +95 -51
  648. package/cli/team/team-db-locks.js +167 -35
  649. package/cli/team/team-db-mailbox.js +15 -8
  650. package/cli/team/team-db-readonly.js +76 -0
  651. package/cli/team/team-db-task-helpers.js +68 -19
  652. package/cli/team/team-db-tasks.js +21 -9
  653. package/cli/team/team-db-transaction.js +20 -5
  654. package/cli/team/team-db.js +11 -4
  655. package/cli/team/team-dispatch-batches.js +271 -0
  656. package/cli/team/team-dispatch-prompts.js +152 -0
  657. package/cli/team/team-dispatch-render.js +154 -0
  658. package/cli/team/team-dispatch-run-cli.js +154 -0
  659. package/cli/team/team-dispatch-runs.js +155 -0
  660. package/cli/team/team-dispatch-script.js +67 -0
  661. package/cli/team/team-dispatch-select.js +220 -0
  662. package/cli/team/team-dispatch-v2-fixture.js +62 -0
  663. package/cli/team/team-dispatch-v2.js +207 -0
  664. package/cli/team/team-dispatch.js +229 -0
  665. package/cli/team/team-dispatcher-authority.js +43 -0
  666. package/cli/team/team-flags.js +222 -48
  667. package/cli/team/team-format.js +80 -26
  668. package/cli/team/team-handoff-hint.js +9 -0
  669. package/cli/team/team-migrate-agents.js +52 -0
  670. package/cli/team/team-migrate-apply.js +178 -0
  671. package/cli/team/team-migrate-junk.js +55 -0
  672. package/cli/team/team-migrate-metadata.js +80 -0
  673. package/cli/team/team-migrate-paths.js +50 -0
  674. package/cli/team/team-migrate-plan.js +85 -0
  675. package/cli/team/team-migrate-report.js +89 -0
  676. package/cli/team/team-migrate-tables.js +85 -0
  677. package/cli/team/team-migrate.js +193 -0
  678. package/cli/team/team-needs.js +99 -0
  679. package/cli/team/team-profile-format.js +126 -0
  680. package/cli/team/team-profile.js +144 -0
  681. package/cli/team/team-projects-coordinator.js +54 -33
  682. package/cli/team/team-projects-format.js +8 -4
  683. package/cli/team/team-projects-memory.js +6 -3
  684. package/cli/team/team-projects.js +2 -1
  685. package/cli/team/team-release-train.js +2 -1
  686. package/cli/team/team-route.js +132 -0
  687. package/cli/team/team-schema-repo.js +48 -0
  688. package/cli/team/team-schema-usage.js +25 -0
  689. package/cli/team/team-schema-vds.js +7 -3
  690. package/cli/team/team-schema.js +24 -4
  691. package/cli/team/team-task-close.js +132 -0
  692. package/cli/team/team-task-guard.js +24 -0
  693. package/cli/team/team-task-handoff.js +122 -0
  694. package/cli/team/team-task-ownership.js +74 -0
  695. package/cli/team/team-task-rules.js +21 -0
  696. package/cli/team/team-task-uncommitted.js +49 -0
  697. package/cli/team/team-telemetry.js +44 -32
  698. package/cli/team/team-tokens.js +4 -1
  699. package/cli/team/team-triage-generate.js +212 -0
  700. package/cli/team/team-triage-log.js +11 -0
  701. package/cli/team/team-triage-verify.js +153 -0
  702. package/cli/team/team-triage.js +92 -339
  703. package/cli/team/team-vds.js +2 -1
  704. package/cli/team/usage-compute.js +70 -0
  705. package/cli/team/usage-pricing.js +62 -0
  706. package/cli/team/usage-reader.js +106 -0
  707. package/cli/team/usage-render.js +72 -0
  708. package/cli/team/usage-store.js +56 -0
  709. package/cli/team/usage-transcript.js +127 -0
  710. package/cli/team/write-lock-guard.js +48 -0
  711. package/cli/telemetry/call-ledger.js +264 -0
  712. package/cli/telemetry/call-schema.js +53 -0
  713. package/cli/telemetry/savings-dbs.js +111 -0
  714. package/cli/telemetry/savings-render.js +68 -0
  715. package/cli/telemetry/savings-report.js +101 -0
  716. package/cli/telemetry/savings-routing.js +66 -0
  717. package/cli/telemetry/savings-tooling.js +140 -0
  718. package/cli/terminal.js +38 -40
  719. package/cli/tesseract-manifesto.js +2 -17
  720. package/cli/tesseract.js +8 -21
  721. package/cli/test-audit.js +218 -0
  722. package/cli/test-changes.js +60 -0
  723. package/cli/test-command.js +201 -0
  724. package/cli/test-depth.js +43 -0
  725. package/cli/test-failures.js +170 -0
  726. package/cli/test-graph-open.js +150 -0
  727. package/cli/test-graph.js +188 -0
  728. package/cli/test-lanes.js +117 -0
  729. package/cli/test-output.js +155 -0
  730. package/cli/test-paths.js +51 -0
  731. package/cli/test-profile.js +64 -0
  732. package/cli/test-report.js +112 -0
  733. package/cli/test-run.js +53 -0
  734. package/cli/test-scope.js +55 -0
  735. package/cli/test-select.js +107 -0
  736. package/cli/test-slots.js +276 -0
  737. package/cli/test-workers.js +45 -0
  738. package/cli/test-workspace.js +83 -0
  739. package/cli/theme.js +6 -3
  740. package/cli/timers.js +6 -0
  741. package/cli/trend.js +10 -5
  742. package/cli/tsconfig-shape.js +20 -0
  743. package/cli/tty-banner.js +11 -0
  744. package/cli/typecheck-audit.js +146 -0
  745. package/cli/typecheck-command.js +94 -0
  746. package/cli/typecheck-sandbox.js +93 -0
  747. package/cli/ui-actions-codebase.js +20 -7
  748. package/cli/ui-actions-helpers.js +9 -0
  749. package/cli/ui-actions-studio.js +11 -7
  750. package/cli/ui-actions-tasks.js +3 -2
  751. package/cli/ui-actions-vds.js +2 -1
  752. package/cli/ui-actions.js +4 -2
  753. package/cli/ui-attention.js +28 -12
  754. package/cli/ui-auth-hosts.js +46 -0
  755. package/cli/ui-auth.js +89 -0
  756. package/cli/ui-client-cert.js +2 -1
  757. package/cli/ui-client-filetree.js +2 -2
  758. package/cli/ui-db-studio.js +23 -33
  759. package/cli/ui-dev-watcher.js +2 -1
  760. package/cli/ui-forum-data.js +45 -46
  761. package/cli/ui-forum-topics.js +6 -3
  762. package/cli/ui-fresh-index.js +11 -0
  763. package/cli/ui-handlers.js +6 -6
  764. package/cli/ui-html.js +6 -12
  765. package/cli/ui-index.html +3 -3
  766. package/cli/ui-route-helpers.js +10 -0
  767. package/cli/ui-server-routes.js +15 -17
  768. package/cli/ui-server.js +49 -50
  769. package/cli/ui-sql-guard.js +76 -0
  770. package/cli/ui-sql-mask.js +61 -0
  771. package/cli/ui-sse.js +5 -4
  772. package/cli/ui-template-filetree.js +4 -4
  773. package/cli/ui-template-kanban.js +4 -7
  774. package/cli/verify-changed.js +43 -0
  775. package/cli/verify-helpers.js +21 -207
  776. package/cli/verify-lint.js +54 -20
  777. package/cli/verify-report.js +117 -0
  778. package/cli/verify-steps.js +71 -0
  779. package/cli/verify.js +111 -372
  780. package/cli/wait-command.js +147 -0
  781. package/cli/workspace-run.js +153 -0
  782. package/cli/workspace.js +147 -0
  783. package/cli/write-append.js +28 -0
  784. package/library/node-js/is-path-inside/entry.json +57 -0
  785. package/library/node-js/is-path-inside/negative/path-scope.js.txt +13 -0
  786. package/library/node-js/is-path-inside/piece.js +15 -0
  787. package/library/node-js/is-path-inside/piece.spec.js +38 -0
  788. package/library/node-js/read-json-or/entry.json +70 -0
  789. package/library/node-js/read-json-or/negative/ratchet.js.txt +14 -0
  790. package/library/node-js/read-json-or/negative/workspace.js.txt +8 -0
  791. package/library/node-js/read-json-or/piece.js +17 -0
  792. package/library/node-js/read-json-or/piece.spec.js +36 -0
  793. package/library/vue-ts/nullable-timer-handle/ambient.d.ts +5 -0
  794. package/library/vue-ts/nullable-timer-handle/entry.json +84 -0
  795. package/library/vue-ts/nullable-timer-handle/negative/const-alias.ts.txt +17 -0
  796. package/library/vue-ts/nullable-timer-handle/negative/inline-guard.ts.txt +15 -0
  797. package/library/vue-ts/nullable-timer-handle/piece.spec.js +48 -0
  798. package/library/vue-ts/nullable-timer-handle/piece.ts +41 -0
  799. package/package.json +9 -3
  800. package/scripts/check-framework-generation.mjs +32 -12
  801. package/scripts/direct-run.mjs +9 -0
  802. package/scripts/pre-commit.sh +48 -74
  803. package/scripts/publish-both.mjs +24 -16
  804. package/scripts/publish-summary.mjs +14 -0
  805. package/scripts/postinstall.mjs +0 -27
@@ -0,0 +1,364 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ export const loadProjectConfig = (cwd = process.cwd()) => {
5
+ const cfgPath = path.resolve(cwd, '.chemx', 'config.json');
6
+ const hasConfig = fs.existsSync(cfgPath);
7
+ if (!hasConfig) return {};
8
+ try {
9
+ return JSON.parse(fs.readFileSync(cfgPath, 'utf-8'));
10
+ } catch {
11
+ return {};
12
+ }
13
+ };
14
+
15
+ export const normalizeFramework = (val) => {
16
+ if (!val) return null;
17
+ const str = String(val).toLowerCase().trim();
18
+ const isReact = ['react', 'tsx', 'jsx'].includes(str);
19
+ if (isReact) return 'react';
20
+ const isVue = ['vue', 'vue3', 'nuxt'].includes(str);
21
+ if (isVue) return 'vue';
22
+ const isSvelte = ['svelte', 'svelte5', 'kit'].includes(str);
23
+ if (isSvelte) return 'svelte';
24
+ return null;
25
+ };
26
+
27
+ export const resolveFramework = ({ frameworkArg = null, cwd = process.cwd() } = {}) => {
28
+ // 1. Explicit flag
29
+ const explicit = normalizeFramework(frameworkArg);
30
+ if (explicit) return explicit;
31
+
32
+ // 2. Project config in .chemx/config.json
33
+ const config = loadProjectConfig(cwd);
34
+ const hasConfiguredFramework = Boolean(config.framework);
35
+ if (hasConfiguredFramework) {
36
+ const fromConfig = normalizeFramework(config.framework);
37
+ if (fromConfig) return fromConfig;
38
+ }
39
+
40
+ // 3. Auto-detect from package.json dependencies
41
+ const pkgPath = path.resolve(cwd, 'package.json');
42
+ const hasPackageJson = fs.existsSync(pkgPath);
43
+ if (hasPackageJson) {
44
+ try {
45
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
46
+ const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
47
+
48
+ const usesVue = Boolean(deps.vue || deps.nuxt || deps['@nuxt/kit']);
49
+ if (usesVue) return 'vue';
50
+ const usesSvelte = Boolean(deps.svelte || deps['@sveltejs/kit']);
51
+ if (usesSvelte) return 'svelte';
52
+ const usesReact = Boolean(deps.react || deps.next);
53
+ if (usesReact) return 'react';
54
+ } catch {
55
+ // chemx-allow: best-effort an unreadable package.json falls through to the hard default framework
56
+ }
57
+ }
58
+
59
+ // 4. Hard default
60
+ return 'react';
61
+ };
62
+
63
+ export const detectFramework = (cwd = process.cwd()) => {
64
+ return resolveFramework({ cwd });
65
+ };
66
+
67
+ export const detectTestRunner = (startDir = process.cwd()) => {
68
+ let curr = path.resolve(startDir);
69
+ for (;;) {
70
+ const hasParentDir = Boolean(curr && curr !== path.dirname(curr));
71
+ if (!hasParentDir) break;
72
+ const pkgPath = path.join(curr, 'package.json');
73
+ const hasPackageJson = fs.existsSync(pkgPath);
74
+ if (hasPackageJson) {
75
+ try {
76
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
77
+ const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
78
+ const usesVitest = Boolean(deps.vitest || (pkg.scripts?.test && pkg.scripts.test.includes('vitest')));
79
+ if (usesVitest) return 'vitest';
80
+ const usesJest = Boolean(deps.jest || (pkg.scripts?.test && pkg.scripts.test.includes('jest')));
81
+ if (usesJest) return 'jest';
82
+ } catch {
83
+ // chemx-allow: best-effort an unreadable package.json falls back to the node:test runner
84
+ }
85
+ break;
86
+ }
87
+ curr = path.dirname(curr);
88
+ }
89
+
90
+ return 'node:test';
91
+ };
92
+
93
+ const ATOMS_PACKAGES = ['@chemx/x-atoms', '@chemx/atoms', 'x-atoms', '@chem-x/x-atoms'];
94
+ const PALETTE_PACKAGES = ['@chemx/o-command-palette', '@chemx/command-palette', 'o-command-palette', '@chem-x/o-command-palette'];
95
+
96
+ const resolveLocalAtomsCandidate = (cwd) => {
97
+ const componentAtomsPath = path.resolve(cwd, 'src/components/atoms');
98
+ const hasComponentAtoms = fs.existsSync(componentAtomsPath);
99
+ if (hasComponentAtoms) {
100
+ return '@/components/atoms';
101
+ }
102
+
103
+ const directAtomsPath = path.resolve(cwd, 'src/atoms');
104
+ const hasDirectAtoms = fs.existsSync(directAtomsPath);
105
+ if (hasDirectAtoms) {
106
+ return '@/atoms';
107
+ }
108
+
109
+ return null;
110
+ };
111
+
112
+ export const detectInstalledFamily = (cwd = process.cwd()) => {
113
+ const pkgPath = path.resolve(cwd, 'package.json');
114
+ const hasPackageJson = fs.existsSync(pkgPath);
115
+ if (!hasPackageJson) {
116
+ return { hasAtoms: false, atomsPackage: null, hasPalette: false, palettePackage: null };
117
+ }
118
+
119
+ try {
120
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
121
+ const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
122
+
123
+ const atomsCandidate = ATOMS_PACKAGES.find((name) => Boolean(deps[name]));
124
+ const paletteCandidate = PALETTE_PACKAGES.find((name) => Boolean(deps[name]));
125
+
126
+ const localAtomsCandidate = resolveLocalAtomsCandidate(cwd);
127
+
128
+ const resolvedAtomsPackage = atomsCandidate || localAtomsCandidate || null;
129
+
130
+ return {
131
+ hasAtoms: Boolean(resolvedAtomsPackage),
132
+ atomsPackage: resolvedAtomsPackage,
133
+ hasPalette: Boolean(paletteCandidate),
134
+ palettePackage: paletteCandidate || null
135
+ };
136
+ } catch {
137
+ return { hasAtoms: false, atomsPackage: null, hasPalette: false, palettePackage: null };
138
+ }
139
+ };
140
+
141
+ const TIER_DIRECTORY_MAPS = {
142
+ hook: [
143
+ 'src/hooks',
144
+ 'src/composables',
145
+ 'composables',
146
+ 'hooks',
147
+ 'src/lib/hooks',
148
+ 'src'
149
+ ],
150
+ view: [
151
+ 'src/views',
152
+ 'src/pages',
153
+ 'src/routes',
154
+ 'src/app',
155
+ 'app',
156
+ 'pages',
157
+ 'views',
158
+ 'src'
159
+ ],
160
+ molecule: [
161
+ 'src/components/molecules',
162
+ 'src/components',
163
+ 'src/lib/components',
164
+ 'components',
165
+ 'src'
166
+ ],
167
+ atom: [
168
+ 'src/components/atoms',
169
+ 'src/components',
170
+ 'src/lib/components',
171
+ 'components',
172
+ 'src'
173
+ ],
174
+ organism: [
175
+ 'src/components/organisms',
176
+ 'src/components',
177
+ 'src/lib/components',
178
+ 'components',
179
+ 'src'
180
+ ],
181
+ template: [
182
+ 'src/components/templates',
183
+ 'src/components',
184
+ 'src/lib/components',
185
+ 'components',
186
+ 'src'
187
+ ]
188
+ };
189
+
190
+ export const PRESET_DIRECTORY_MAPS = {
191
+ src: {
192
+ molecule: 'src/components/molecules',
193
+ atom: 'src/components/atoms',
194
+ organism: 'src/components/organisms',
195
+ template: 'src/components/templates',
196
+ hook: 'src/hooks',
197
+ view: 'src/views',
198
+ service: 'src/services',
199
+ route: 'src/routes',
200
+ store: 'src/stores',
201
+ repo: 'src/repos',
202
+ util: 'src/utils',
203
+ spec: 'test/unit'
204
+ },
205
+ app: {
206
+ molecule: 'app/components/molecules',
207
+ atom: 'app/components/atoms',
208
+ organism: 'app/components/organisms',
209
+ template: 'app/components/templates',
210
+ hook: 'app/composables',
211
+ view: 'app/pages',
212
+ service: 'app/services',
213
+ route: 'server/api',
214
+ store: 'app/stores',
215
+ repo: 'server/repos',
216
+ util: 'app/utils',
217
+ spec: 'test/unit'
218
+ },
219
+ root: {
220
+ molecule: 'components/molecules',
221
+ atom: 'components/atoms',
222
+ organism: 'components/organisms',
223
+ template: 'components/templates',
224
+ hook: 'hooks',
225
+ view: 'pages',
226
+ service: 'services',
227
+ route: 'routes',
228
+ store: 'stores',
229
+ repo: 'repos',
230
+ util: 'utils',
231
+ spec: 'test'
232
+ },
233
+ lib: {
234
+ molecule: 'src/lib/components/molecules',
235
+ atom: 'src/lib/components/atoms',
236
+ organism: 'src/lib/components/organisms',
237
+ template: 'src/lib/components/templates',
238
+ hook: 'src/lib/hooks',
239
+ view: 'src/routes',
240
+ service: 'src/lib/services',
241
+ route: 'src/routes/api',
242
+ store: 'src/lib/stores',
243
+ repo: 'src/lib/repos',
244
+ util: 'src/lib/utils',
245
+ spec: 'test'
246
+ }
247
+ };
248
+
249
+ export const detectTierBaseDir = (tier, cwd = process.cwd(), presetOverride = null) => {
250
+ const config = loadProjectConfig(cwd);
251
+ const activePreset = presetOverride || config.preset;
252
+
253
+ const hasPresetDir = Boolean(activePreset && PRESET_DIRECTORY_MAPS[activePreset]?.[tier]);
254
+ if (hasPresetDir) {
255
+ return PRESET_DIRECTORY_MAPS[activePreset][tier];
256
+ }
257
+
258
+ const hasConfiguredDir = Boolean(config.dirs && config.dirs[tier]);
259
+ if (hasConfiguredDir) {
260
+ const configuredPath = path.resolve(cwd, config.dirs[tier]);
261
+ const isConfiguredDirPresent = fs.existsSync(configuredPath);
262
+ if (isConfiguredDirPresent) return config.dirs[tier];
263
+ }
264
+
265
+ const candidates = TIER_DIRECTORY_MAPS[tier] || TIER_DIRECTORY_MAPS.molecule;
266
+ for (const c of candidates) {
267
+ const isCandidatePresent = fs.existsSync(path.resolve(cwd, c));
268
+ if (isCandidatePresent) return c;
269
+ }
270
+
271
+ const hasAppComponents = fs.existsSync(path.resolve(cwd, 'app/components'));
272
+ if (hasAppComponents) {
273
+ return PRESET_DIRECTORY_MAPS.app[tier] || 'app/components';
274
+ }
275
+
276
+ return PRESET_DIRECTORY_MAPS.src[tier] || '.';
277
+ };
278
+
279
+ export const detectJigBaseDir = (kind, { cwd = process.cwd(), preset = null } = {}) => {
280
+ const config = loadProjectConfig(cwd);
281
+ const activePreset = preset || config.preset;
282
+
283
+ const hasPresetDir = Boolean(activePreset && PRESET_DIRECTORY_MAPS[activePreset]?.[kind]);
284
+ if (hasPresetDir) {
285
+ return PRESET_DIRECTORY_MAPS[activePreset][kind];
286
+ }
287
+
288
+ const hasConfiguredDir = Boolean(config.dirs && config.dirs[kind]);
289
+ if (hasConfiguredDir) {
290
+ const configuredPath = path.resolve(cwd, config.dirs[kind]);
291
+ const isConfiguredDirPresent = fs.existsSync(configuredPath);
292
+ if (isConfiguredDirPresent) return config.dirs[kind];
293
+ }
294
+
295
+ const defaultDirMap = {
296
+ service: ['src/services', 'app/services', 'services', 'src/lib/services'],
297
+ route: ['src/routes', 'server/api', 'routes', 'src/routes/api'],
298
+ store: ['src/stores', 'app/stores', 'stores', 'src/lib/stores'],
299
+ repo: ['src/repos', 'server/repos', 'repos', 'src/lib/repos'],
300
+ util: ['src/utils', 'app/utils', 'utils', 'src/lib/utils'],
301
+ spec: ['test/unit', 'tests/unit', 'test', 'tests']
302
+ };
303
+
304
+ const candidates = defaultDirMap[kind] || [`src/${kind}s`];
305
+ for (const c of candidates) {
306
+ const isCandidatePresent = fs.existsSync(path.resolve(cwd, c));
307
+ if (isCandidatePresent) return c;
308
+ }
309
+
310
+ const hasAppDir = fs.existsSync(path.resolve(cwd, 'app'));
311
+ if (hasAppDir) {
312
+ return PRESET_DIRECTORY_MAPS.app[kind] || `app/${kind}s`;
313
+ }
314
+
315
+ return PRESET_DIRECTORY_MAPS.src[kind] || `src/${kind}s`;
316
+ };
317
+
318
+ const TAILWIND_PACKAGES = [
319
+ 'tailwindcss',
320
+ '@tailwindcss/vite',
321
+ '@tailwindcss/postcss',
322
+ '@tailwindcss/cli'
323
+ ];
324
+
325
+ const SCSS_PACKAGES = ['sass', 'sass-embedded'];
326
+
327
+ const TAILWIND_CONFIG_NAMES = [
328
+ 'tailwind.config.js',
329
+ 'tailwind.config.ts',
330
+ 'tailwind.config.cjs',
331
+ 'tailwind.config.mjs'
332
+ ];
333
+
334
+ export const detectStylingStack = (cwd = process.cwd()) => {
335
+ const pkgPath = path.resolve(cwd, 'package.json');
336
+ let hasTailwind = false;
337
+ let hasScss = false;
338
+
339
+ const hasPackageJson = fs.existsSync(pkgPath);
340
+ if (hasPackageJson) {
341
+ try {
342
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
343
+ const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
344
+
345
+ hasTailwind = TAILWIND_PACKAGES.some((pkgName) => Boolean(deps[pkgName]));
346
+ hasScss = SCSS_PACKAGES.some((pkgName) => Boolean(deps[pkgName]));
347
+ } catch {
348
+ // chemx-allow: best-effort an unreadable package.json leaves styling detection to the tailwind config probe
349
+ }
350
+ }
351
+
352
+ if (!hasTailwind) {
353
+ hasTailwind = TAILWIND_CONFIG_NAMES.some((cfg) => fs.existsSync(path.resolve(cwd, cfg)));
354
+ }
355
+
356
+ let styleFlavor = 'css';
357
+ if (hasTailwind) {
358
+ styleFlavor = 'tailwind';
359
+ } else if (hasScss) {
360
+ styleFlavor = 'scss';
361
+ }
362
+
363
+ return { hasTailwind, hasScss, styleFlavor };
364
+ };
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Chemical X Protocol: where a walk for a project root may stop (#2570, #2581).
3
+ * A project marker (.git, package.json, .chemxrc) ends an upward search. The filesystem root and
4
+ * the OS temp dir (with its ancestors) are never a project root: a stray /tmp/.chemx or /.chemx
5
+ * must not capture a temp project that has no marker of its own.
6
+ */
7
+ import fs from 'node:fs';
8
+ import os from 'node:os';
9
+ import path from 'node:path';
10
+
11
+ export const PROJECT_MARKERS = Object.freeze(['.git', 'package.json', '.chemxrc']);
12
+
13
+ const realDir = (dir) => {
14
+ try {
15
+ return fs.realpathSync(dir);
16
+ } catch {
17
+ return path.resolve(dir);
18
+ }
19
+ };
20
+
21
+ export const hasProjectMarker = (dir) => PROJECT_MARKERS.some((marker) => fs.existsSync(path.join(dir, marker)));
22
+
23
+ /** True for the filesystem root, the OS temp dir and every ancestor of the temp dir. */
24
+ export const isForbiddenRoot = (dir) => {
25
+ const resolved = realDir(dir);
26
+ const isFsRoot = path.dirname(resolved) === resolved;
27
+ const rel = path.relative(resolved, realDir(os.tmpdir()));
28
+ const holdsTempDir = !rel.startsWith('..') && !path.isAbsolute(rel);
29
+ return isFsRoot || holdsTempDir;
30
+ };
31
+
32
+ /** True when dir is the OS temp dir or inside it. */
33
+ export const isInsideTempDir = (dir) => {
34
+ const rel = path.relative(realDir(os.tmpdir()), realDir(dir));
35
+ return !rel.startsWith('..') && !path.isAbsolute(rel);
36
+ };
37
+
38
+ /** Text for a refused root, or null when dir may hold a .chemx. */
39
+ export const forbiddenRootRefusal = (dir) => {
40
+ const isForbidden = isForbiddenRoot(dir);
41
+ return isForbidden ? `chemx will not use ${dir} as a project root (it is the OS temp dir, an ancestor of it, or the filesystem root); run from a project directory` : null;
42
+ };
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Chemical X Protocol: the coordination root (#2488).
3
+ * Team tables (tasks, comments, feed, DMs, agents, leases, lock queue, projects) belong in one db per
4
+ * monorepo, <root>/.chemx/index.db, where root is, from the start directory:
5
+ * 1. the outermost git superproject, climbing only through registered submodules (.gitmodules
6
+ * path or a .git/modules pointer) and from a linked worktree to its main checkout; else
7
+ * 2. the outermost workspace root (pnpm-workspace.yaml or package.json workspaces) inside the
8
+ * nearest checkout; else
9
+ * 3. the package itself: the nearest checkout, else the first dir on the way up with a project
10
+ * marker (.git, package.json, .chemxrc) or an existing .chemx/index.db (the dir the code index
11
+ * would use too), else the start dir.
12
+ * No walk climbs into the OS temp dir, its ancestors or the filesystem root, and a root that lands
13
+ * there is refused (#2570): a stray /tmp/.chemx never captures a temp project.
14
+ * CHEMX_PROJECT_ROOT and an MCP projectRoot only choose the start directory; they never move the
15
+ * root. The code index keeps resolving per project (search-schema.js); package scoping of the
16
+ * index is part B of #2488.
17
+ * A spec process (node --test sets NODE_TEST_CONTEXT) is refused any root outside the OS temp dir,
18
+ * so specs never resolve a real db.
19
+ */
20
+ import fs from 'node:fs';
21
+ import os from 'node:os';
22
+ import path from 'node:path';
23
+ import { readWorkspaceGlobs } from '../workspace.js';
24
+ import { hasProjectMarker, isForbiddenRoot, forbiddenRootRefusal } from '../project-markers.js';
25
+
26
+ const realDir = (dir) => {
27
+ try {
28
+ return fs.realpathSync(dir);
29
+ } catch {
30
+ return path.resolve(dir);
31
+ }
32
+ };
33
+
34
+ export const ancestorsOf = (startDir) => {
35
+ const dirs = [];
36
+ let dir = path.resolve(startDir);
37
+ while (true) {
38
+ dirs.push(dir);
39
+ const parent = path.dirname(dir);
40
+ const isTop = parent === dir;
41
+ if (isTop) return dirs;
42
+ dir = parent;
43
+ }
44
+ };
45
+
46
+ export const isInsideOrEqual = (outer, inner) => {
47
+ const rel = path.relative(outer, inner);
48
+ const isOutside = rel.startsWith('..') || path.isAbsolute(rel);
49
+ return !isOutside;
50
+ };
51
+
52
+ // The ancestors a root search may visit: never the temp dir, its ancestors or the filesystem root.
53
+ const searchableAncestors = (startDir) => ancestorsOf(startDir).filter((dir) => !isForbiddenRoot(dir));
54
+
55
+ const hasGit = (dir) => fs.existsSync(path.join(dir, '.git'));
56
+ const nearestCheckout = (startDir) => searchableAncestors(startDir).find(hasGit) ?? null;
57
+
58
+ // The gitdir a `.git` FILE points at (submodule or linked worktree), or null for a real .git dir.
59
+ const readGitPointer = (dir) => {
60
+ try {
61
+ const gitPath = path.join(dir, '.git');
62
+ const isPointerFile = fs.statSync(gitPath).isFile();
63
+ const match = isPointerFile ? /^gitdir:\s*(.+)$/m.exec(fs.readFileSync(gitPath, 'utf-8')) : null;
64
+ return match ? path.resolve(dir, match[1].trim()) : null;
65
+ } catch {
66
+ return null;
67
+ }
68
+ };
69
+
70
+ export const listedSubmodulePaths = (dir) => {
71
+ try {
72
+ const text = fs.readFileSync(path.join(dir, '.gitmodules'), 'utf-8');
73
+ return [...text.matchAll(/^\s*path\s*=\s*(.+?)\s*$/gm)].map((match) => match[1].replace(/\\/g, '/'));
74
+ } catch {
75
+ return [];
76
+ }
77
+ };
78
+
79
+ const WORKTREE_POINTER = /^(.*)[\\/]\.git[\\/]worktrees[\\/][^\\/]+$/;
80
+
81
+ // A linked worktree coordinates with its main checkout: <main>/.git/worktrees/<name> -> <main>.
82
+ const worktreeMain = (checkout) => {
83
+ const pointer = readGitPointer(checkout) || '';
84
+ const match = WORKTREE_POINTER.exec(pointer);
85
+ return match ? match[1] : null;
86
+ };
87
+
88
+ const toPosix = (p) => p.split(path.sep).join('/');
89
+
90
+ // The checkout that registers `checkout` as a submodule, or null. An unrelated repo above (a
91
+ // dotfiles repo in $HOME) is never a superproject.
92
+ const superprojectOf = (checkout) => {
93
+ const parent = path.dirname(checkout);
94
+ const outer = parent === checkout ? null : nearestCheckout(parent);
95
+ if (!outer) return null;
96
+ const isListed = listedSubmodulePaths(outer).includes(toPosix(path.relative(outer, checkout)));
97
+ const pointer = readGitPointer(checkout) || '';
98
+ const isAbsorbed = pointer.startsWith(path.join(outer, '.git', 'modules') + path.sep);
99
+ const isSubmodule = isListed || isAbsorbed;
100
+ return isSubmodule ? outer : null;
101
+ };
102
+
103
+ const outermostSuperproject = (checkout) => {
104
+ let current = worktreeMain(checkout) ?? checkout;
105
+ let outer = superprojectOf(current);
106
+ while (outer) {
107
+ current = outer;
108
+ outer = superprojectOf(current);
109
+ }
110
+ return current;
111
+ };
112
+
113
+ const isWorkspaceRoot = (dir) => Boolean(readWorkspaceGlobs(dir));
114
+
115
+ // Outermost workspace root among the ancestors, never above the nearest checkout's boundary.
116
+ const outermostWorkspace = (startDir, boundary) => {
117
+ const candidates = searchableAncestors(startDir).filter((dir) => !boundary || isInsideOrEqual(boundary, dir));
118
+ return candidates.filter(isWorkspaceRoot).pop() ?? null;
119
+ };
120
+
121
+ const isProjectStop = (dir) => hasProjectMarker(dir) || fs.existsSync(path.join(dir, '.chemx', 'index.db'));
122
+ const firstMarker = (startDir) => searchableAncestors(startDir).find(isProjectStop) ?? null;
123
+
124
+ const locateRoot = (startDir) => {
125
+ const checkout = nearestCheckout(startDir);
126
+ const superproject = checkout ? outermostSuperproject(checkout) : null;
127
+ const hasSuperproject = Boolean(superproject) && superproject !== checkout;
128
+ if (hasSuperproject) return { root: superproject, mode: 'superproject' };
129
+ const workspace = outermostWorkspace(startDir, superproject);
130
+ if (workspace) return { root: workspace, mode: 'workspace' };
131
+ const own = superproject || firstMarker(startDir) || path.resolve(startDir);
132
+ return { root: own, mode: 'standalone' };
133
+ };
134
+
135
+ export const isSpecProcess = (env = process.env) => Boolean(env.NODE_TEST_CONTEXT);
136
+
137
+ const specRefusal = (root, env) => {
138
+ const isSpec = isSpecProcess(env);
139
+ const isTemp = isInsideOrEqual(realDir(os.tmpdir()), realDir(root));
140
+ const isRefused = isSpec && !isTemp;
141
+ return isRefused ? `spec process refused the coordination db under ${root}: specs must build their project in a temp dir` : null;
142
+ };
143
+
144
+ /**
145
+ * Why no team db may be opened at root, or null. Every opener of team rows asks this (#2581):
146
+ * the temp dir and the filesystem root are never a root, and a spec process (node --test) never
147
+ * opens a db outside the OS temp dir, whichever path it took to get there.
148
+ */
149
+ export const teamDbRefusal = (root, env = process.env) => forbiddenRootRefusal(root) || specRefusal(root, env);
150
+
151
+ /**
152
+ * @param {string} startDir Where the caller runs (cwd, MCP projectRoot, hook root).
153
+ * @param {{ env?: object }} [options]
154
+ * @returns {{ root: string, mode: 'superproject'|'workspace'|'standalone', refused: string|null }}
155
+ */
156
+ export const resolveCoordinationRoot = (startDir = process.cwd(), options = {}) => {
157
+ const env = options.env || process.env;
158
+ const located = locateRoot(realDir(startDir));
159
+ const root = realDir(located.root);
160
+ return { root, mode: located.mode, refused: teamDbRefusal(root, env) };
161
+ };
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Chemical X Protocol: read a Claude Code workflow run from disk and measure each agent's usage (#2497).
3
+ * A run lives at ~/.claude/projects/<project>/<session>/subagents/workflows/<wf_id>/ with a journal.jsonl,
4
+ * agent-<id>.jsonl transcripts and agent-<id>.meta.json files. Guarantee: tokens are exactly what the
5
+ * transcripts record, counted once per message.id. Not guaranteed: transcripts of agents the host never
6
+ * wrote (killed before the first reply) are absent, so they are absent here too.
7
+ */
8
+ import fs from 'node:fs';
9
+ import os from 'node:os';
10
+ import path from 'node:path';
11
+ import { parseTranscript } from './usage-transcript.js';
12
+
13
+ const AGENT_FILE_RE = /^agent-(.+)\.jsonl$/;
14
+
15
+ const isDir = (p) => {
16
+ try {
17
+ return fs.statSync(p).isDirectory();
18
+ } catch {
19
+ return false;
20
+ }
21
+ };
22
+
23
+ const listDirs = (p) => {
24
+ try {
25
+ return fs.readdirSync(p).map((name) => path.join(p, name)).filter(isDir);
26
+ } catch {
27
+ return [];
28
+ }
29
+ };
30
+
31
+ /** Find a run dir from a path or a wf_ id. projectsRoot defaults to ~/.claude/projects. */
32
+ export const findRunDir = (idOrDir, projectsRoot = path.join(os.homedir(), '.claude', 'projects')) => {
33
+ const given = path.resolve(String(idOrDir || ''));
34
+ const isGivenDir = Boolean(idOrDir) && isDir(given);
35
+ if (isGivenDir) return given;
36
+ for (const project of listDirs(projectsRoot)) {
37
+ for (const session of listDirs(project)) {
38
+ const candidate = path.join(session, 'subagents', 'workflows', String(idOrDir));
39
+ if (isDir(candidate)) return candidate;
40
+ }
41
+ }
42
+ return null;
43
+ };
44
+
45
+ const readJsonLines = (file) => {
46
+ let text = '';
47
+ try {
48
+ text = fs.readFileSync(file, 'utf8');
49
+ } catch {
50
+ return [];
51
+ }
52
+ return text.split('\n').filter(Boolean).map((line) => {
53
+ try {
54
+ return JSON.parse(line);
55
+ } catch {
56
+ return null;
57
+ }
58
+ }).filter(Boolean);
59
+ };
60
+
61
+ const readJson = (file) => {
62
+ try {
63
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
64
+ } catch {
65
+ return {};
66
+ }
67
+ };
68
+
69
+ const readJournalLabels = (dir) => {
70
+ const labels = new Map();
71
+ for (const event of readJsonLines(path.join(dir, 'journal.jsonl'))) {
72
+ const isStart = event.type === 'started' && Boolean(event.agentId);
73
+ if (isStart) labels.set(event.agentId, { label: event.label || '', phase: event.phase || '' });
74
+ }
75
+ return labels;
76
+ };
77
+
78
+ const primaryModel = (buckets) => {
79
+ const ranked = Object.entries(buckets).sort((a, b) => b[1].calls - a[1].calls);
80
+ return ranked.length ? ranked[0][0] : 'unknown';
81
+ };
82
+
83
+ const readAgent = (dir, file, labels) => {
84
+ const agentId = AGENT_FILE_RE.exec(file)[1];
85
+ const parsed = parseTranscript(fs.readFileSync(path.join(dir, file), 'utf8'));
86
+ const meta = readJson(path.join(dir, `agent-${agentId}.meta.json`));
87
+ const journal = labels.get(agentId) || {};
88
+ return {
89
+ agentId,
90
+ handle: parsed.handle,
91
+ label: journal.label || meta.description || '',
92
+ phase: journal.phase || meta.workflowPhase || '',
93
+ model: primaryModel(parsed.buckets),
94
+ requestedModel: meta.model || null,
95
+ ...parsed
96
+ };
97
+ };
98
+
99
+ /** Read every agent of a run. Returns null when the run cannot be found. */
100
+ export const readRun = (idOrDir, projectsRoot) => {
101
+ const dir = findRunDir(idOrDir, projectsRoot);
102
+ if (!dir) return null;
103
+ const labels = readJournalLabels(dir);
104
+ const files = fs.readdirSync(dir).filter((f) => AGENT_FILE_RE.test(f)).sort();
105
+ const agents = files.map((file) => readAgent(dir, file, labels));
106
+ const launched = [...labels.keys()];
107
+ const missing = launched.filter((id) => !agents.some((a) => a.agentId === id));
108
+ return { runId: path.basename(dir), dir, agents, journalAgents: launched.length, missingTranscripts: missing };
109
+ };