@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
package/cli/ui-index.html CHANGED
@@ -795,7 +795,7 @@ const App = {
795
795
  <div class="xo-kpi__value" style="color:var(--xo-cyan);">{{ codebase.length }}</div>
796
796
  </div>
797
797
  <div class="xo-kpi">
798
- <div class="xo-kpi__label">Under 100L</div>
798
+ <div class="xo-kpi__label">Within line budget</div>
799
799
  <div class="xo-kpi__value" style="color:var(--xo-lime);">{{ compliantCount }}</div>
800
800
  </div>
801
801
  <div class="xo-kpi">
@@ -817,7 +817,7 @@ const App = {
817
817
  <div v-for="f in filteredCodebase" :key="f.path" class="xo-file-card">
818
818
  <div class="d-flex align-center gap-2 mb-1">
819
819
  <v-chip v-if="f.tier" size="x-small" :class="'tier-'+f.tier">{{ f.tier }}</v-chip>
820
- <v-chip v-if="f.lines>100" size="x-small" class="xo-hazard">{{ f.lines }}L ⚠</v-chip>
820
+ <v-chip v-if="f.isOverBudget" size="x-small" class="xo-hazard">{{ f.lines }}L ⚠</v-chip>
821
821
  <v-chip v-else-if="f.lines" size="x-small" variant="outlined" style="border-color:rgba(255,255,255,.12);color:rgba(255,255,255,.4);">{{ f.lines }}L</v-chip>
822
822
  <v-chip v-if="f.coverage!=null" size="x-small" color="success" variant="tonal">{{ f.coverage }}%</v-chip>
823
823
  </div>
@@ -1009,7 +1009,7 @@ const App = {
1009
1009
  });
1010
1010
  };
1011
1011
 
1012
- const compliantCount = computed(() => codebase.value.filter(f => !f.lines || f.lines <= 100).length);
1012
+ const compliantCount = computed(() => codebase.value.filter(f => !f.isOverBudget).length);
1013
1013
  const compliancePct = computed(() => !codebase.value.length ? 0 : Math.round(compliantCount.value / codebase.value.length * 100));
1014
1014
 
1015
1015
  const filteredCodebase = computed(() => {
@@ -0,0 +1,10 @@
1
+ export const sendJson = (res, status, payload, extraHeaders = {}, afterSend = null) => {
2
+ res.writeHead(status, { 'Content-Type': 'application/json', ...extraHeaders });
3
+ res.end(JSON.stringify(payload));
4
+ if (afterSend) afterSend();
5
+ return res;
6
+ };
7
+
8
+ export const runRoute = (handler) => {
9
+ try { return [handler(), null]; } catch (err) { return [null, err]; }
10
+ };
@@ -17,27 +17,29 @@ import {
17
17
  } from './ui-actions.js';
18
18
  import { getDatabaseMetrics, executeSqlQuery } from './ui-db-studio.js';
19
19
  import { scanAttentionItems, confirmAttentionItem } from './ui-attention.js';
20
+ import { withFreshIndex } from './ui-fresh-index.js';
20
21
 
21
- export const routeGet = (pathname, db, cwd = process.cwd(), queryParams = {}) => {
22
+ // db: team rows (coordination db, #2581); indexDb (default db): code index for codebase, metrics, db studio.
23
+ export const routeGet = (pathname, db, cwd = process.cwd(), queryParams = {}, { indexDb = db } = {}) => {
22
24
  const [cleanPath, search] = (pathname || '').split('?');
23
25
  const parsedParams = search ? Object.fromEntries(new URLSearchParams(search)) : queryParams;
24
26
  const normPath = cleanPath.replace(/^\/api\/swarm\//, '/api/');
25
27
 
26
28
  const routes = {
27
- '/api/status': () => handleSwarmStatus(db, cwd),
29
+ '/api/status': () => handleSwarmStatus(db, cwd, indexDb),
28
30
  '/api/feed': () => ({ success: true, feed: queryFeed(db, parsedParams) }),
29
31
  '/api/tasks': () => ({ success: true, tasks: listTasks(db, parsedParams) }),
30
32
  '/api/categories': () => ({ success: true, categories: getForumCategories(db) }),
31
- '/api/agents': () => ({ success: true, agents: handleSwarmStatus(db, cwd).agents }),
32
- '/api/codebase': () => handleCodebaseIndex(db),
33
- '/api/codebase/tree': () => handleCodebaseTree(db),
34
- '/api/codebase/file': () => handleCodebaseFile(db, parsedParams.path, cwd),
35
- '/api/database/metrics': () => getDatabaseMetrics(db, cwd),
33
+ '/api/agents': () => ({ success: true, agents: handleSwarmStatus(db, cwd, indexDb).agents }),
34
+ '/api/codebase': () => withFreshIndex(cwd, {}, () => handleCodebaseIndex(indexDb, cwd)),
35
+ '/api/codebase/tree': () => withFreshIndex(cwd, {}, () => handleCodebaseTree(indexDb, cwd)),
36
+ '/api/codebase/file': () => withFreshIndex(cwd, { paths: [parsedParams.path], scope: false }, () => handleCodebaseFile(indexDb, parsedParams.path, cwd)),
37
+ '/api/database/metrics': () => getDatabaseMetrics(indexDb, cwd),
36
38
  '/api/topics': () => handleGetTopics(db, parsedParams.category),
37
39
  '/api/topics/posts': () => handleGetTopicPosts(db, parsedParams.topicId || parsedParams.topic_id),
38
40
  '/api/attention': () => scanAttentionItems(db, cwd),
39
- '/api/db/tables': () => handleDbTables(db, cwd),
40
- '/api/db/browse': () => handleDbBrowse(db, parsedParams), '/api/db/structure': () => handleDbStructure(db, parsedParams)
41
+ '/api/db/tables': () => handleDbTables(indexDb, cwd),
42
+ '/api/db/browse': () => handleDbBrowse(indexDb, parsedParams), '/api/db/structure': () => handleDbStructure(indexDb, parsedParams)
41
43
  };
42
44
 
43
45
  const hasRoute = Object.prototype.hasOwnProperty.call(routes, normPath);
@@ -53,7 +55,7 @@ export const routeGet = (pathname, db, cwd = process.cwd(), queryParams = {}) =>
53
55
  return null;
54
56
  };
55
57
 
56
- export const routePost = (pathname, db, body, cwd = process.cwd()) => {
58
+ export const routePost = (pathname, db, body, cwd = process.cwd(), { consoleDb = null } = {}) => {
57
59
  const [cleanPath] = (pathname || '').split('?');
58
60
  const postFeedHandler = handleCreateFeedPost || handlePostFeed;
59
61
  const normPath = cleanPath.replace(/^\/api\/swarm\//, '/api/');
@@ -72,10 +74,10 @@ export const routePost = (pathname, db, body, cwd = process.cwd()) => {
72
74
  '/api/agents/signature': () => handleUpdateSignature(db, body),
73
75
  '/api/topics': () => handleCreateTopic(db, body),
74
76
  '/api/settings/action': () => handleSettingsAction(db, body),
75
- '/api/database/query': () => executeSqlQuery(db, body.query),
77
+ '/api/database/query': () => executeSqlQuery(consoleDb, body.query),
76
78
  '/api/attention/action': () => confirmAttentionItem(db, body.itemId, body.action),
77
79
  '/api/prompts/generate': () => handleGeneratePrompt(db, body, cwd),
78
- '/api/db/query': () => handleDbQuery(db, body)
80
+ '/api/db/query': () => handleDbQuery(consoleDb, body)
79
81
  };
80
82
 
81
83
  const hasRoute = Object.prototype.hasOwnProperty.call(routes, normPath);
@@ -88,11 +90,7 @@ export const parseJsonBody = (req) => {
88
90
  let raw = '';
89
91
  req.on('data', (chunk) => { raw += chunk; });
90
92
  req.on('end', () => {
91
- try {
92
- resolve(JSON.parse(raw || '{}'));
93
- } catch (err) {
94
- reject(err);
95
- }
93
+ Promise.resolve(raw || '{}').then(JSON.parse).then(resolve, reject);
96
94
  });
97
95
  req.on('error', reject);
98
96
  });
package/cli/ui-server.js CHANGED
@@ -1,77 +1,74 @@
1
1
  import http from 'node:http';
2
2
  import { openIndexDb } from './search-db.js';
3
+ import { openTeamContext, describeTeamDbFailure } from './team/coordination-db.js';
3
4
  import { handleSwarmStatus } from './ui-handlers.js';
4
5
  import { generateSwarmHtml } from './ui-html.js';
5
6
  import { routeGet, routePost, parseJsonBody } from './ui-server-routes.js';
6
7
  import { handleSseConnection, broadcastSseUpdate, broadcastSseReload, closeSseHub } from './ui-sse.js';
8
+ import { createUiAuth, checkUiRequest, createUiFetch, isLoopbackHost, resolveUiUrlHost, DEFAULT_UI_HOST } from './ui-auth.js';
9
+ import { openConsoleDb } from './ui-sql-guard.js';
10
+ import { sendJson, runRoute } from './ui-route-helpers.js';
7
11
 
8
- export const createUiServer = (cwd = process.cwd()) => {
9
- const db = openIndexDb(cwd);
12
+ export const createUiServer = (cwd = process.cwd(), options = {}) => {
13
+ const indexDb = openIndexDb(cwd);
14
+ const teamContext = openTeamContext(cwd);
15
+ const db = teamContext.db; // team rows: coordination db only (#2581), null when refused; code index, studio, console: indexDb
16
+ const auth = options.auth || createUiAuth();
17
+ const consoleDb = openConsoleDb(cwd);
10
18
  const server = http.createServer(async (req, res) => {
11
- const url = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);
19
+ const url = new URL(req.url || '/', 'http://chemx-ui.invalid');
12
20
  const { pathname } = url;
13
21
  const isGet = req.method === 'GET', isPost = req.method === 'POST';
14
- const isApi = pathname.startsWith('/api/'), isFavicon = pathname === '/favicon.ico';
15
- const shouldServeHtml = isGet && !isApi && !isFavicon;
16
- const shouldServeFavicon = isGet && isFavicon;
17
-
22
+ const isApi = pathname.startsWith('/api/'), isFaviconRequest = isGet && pathname === '/favicon.ico';
23
+ if (isFaviconRequest) return res.writeHead(204).end();
24
+ const gate = checkUiRequest(req, auth, url);
25
+ const isDenied = !gate.allowed;
26
+ if (isDenied) return sendJson(res, gate.status, { success: false, error: gate.error });
27
+ const hasSetCookie = Boolean(gate.setCookie);
28
+ const cookieHeaders = hasSetCookie ? { 'Set-Cookie': gate.setCookie } : {};
29
+ const isTeamUnavailable = !db;
30
+ if (isTeamUnavailable) return sendJson(res, 503, { success: false, error: describeTeamDbFailure(teamContext) }, cookieHeaders);
31
+ const shouldServeHtml = isGet && !isApi;
18
32
  if (shouldServeHtml) {
19
- res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
20
- res.end(generateSwarmHtml(handleSwarmStatus(db)));
21
- return;
33
+ return res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', ...cookieHeaders }).end(generateSwarmHtml(handleSwarmStatus(db, cwd, indexDb)));
22
34
  }
23
- if (shouldServeFavicon) { res.writeHead(204); res.end(); return; }
24
-
25
35
  if (isGet) {
26
36
  const isSse = pathname === '/api/swarm/events' || pathname === '/api/events';
27
- if (isSse) {
28
- handleSseConnection(req, res, db);
29
- return;
30
- }
31
- const result = routeGet(req.url, db, cwd);
32
- if (result) {
33
- res.writeHead(200, { 'Content-Type': 'application/json' });
34
- res.end(JSON.stringify(result));
35
- return;
36
- }
37
+ if (isSse) return handleSseConnection(req, res, db);
38
+ const [result, getError] = runRoute(() => routeGet(req.url, db, cwd, {}, { indexDb }));
39
+ if (getError) return sendJson(res, 500, { success: false, error: getError.message }, cookieHeaders);
40
+ if (result) return sendJson(res, 200, result, cookieHeaders);
37
41
  }
38
-
39
42
  if (isPost) {
40
- try {
41
- const body = await parseJsonBody(req);
42
- const result = routePost(req.url, db, body, cwd);
43
- if (result) {
44
- res.writeHead(200, { 'Content-Type': 'application/json' });
45
- res.end(JSON.stringify(result));
46
- broadcastSseUpdate(db);
47
- return;
48
- }
49
- } catch (err) {
50
- res.writeHead(400, { 'Content-Type': 'application/json' });
51
- res.end(JSON.stringify({ error: 'Invalid JSON payload' }));
52
- return;
53
- }
43
+ const [body, parseError] = await parseJsonBody(req).then((value) => [value, null], (err) => [null, err]);
44
+ if (parseError) return sendJson(res, 400, { error: 'Invalid JSON payload' });
45
+ const [result, routeError] = runRoute(() => routePost(req.url, db, body, cwd, { consoleDb }));
46
+ if (routeError) return sendJson(res, 500, { success: false, error: routeError.message });
47
+ if (result) return sendJson(res, 200, result, {}, () => broadcastSseUpdate(db));
54
48
  }
55
- res.writeHead(404, { 'Content-Type': 'application/json' });
56
- res.end(JSON.stringify({ error: 'Not found' }));
49
+ return sendJson(res, 404, { error: 'Not found' });
57
50
  });
58
51
 
59
- server.on('close', closeSseHub);
60
- return { server, db };
52
+ server.on('close', () => { closeSseHub(); consoleDb?.close(); });
53
+ return { server, db, indexDb, auth };
61
54
  };
62
55
 
56
+ const warnPublicBind = (host) => process.stderr.write(
57
+ `\x1b[33m⚠ chemx ui is bound to ${host}, reachable beyond this machine. Anyone with the token URL can drive the swarm.\x1b[0m\n`);
58
+
63
59
  export const startUiServer = async (options = {}) => {
64
60
  const port = options.port !== undefined ? options.port : 4173;
65
- const host = options.host || '0.0.0.0';
61
+ const host = options.host || DEFAULT_UI_HOST;
66
62
  const cwd = options.cwd || process.cwd();
67
- const { server, db } = createUiServer(cwd);
63
+ const auth = createUiAuth({ bindHost: host, token: options.token, allowHosts: options.allowHosts });
64
+ const { server, db } = createUiServer(cwd, { auth });
68
65
 
69
- if (options.dev) {
66
+ const isDevMode = Boolean(options.dev);
67
+ if (isDevMode) {
70
68
  const { startUiDevWatcher } = await import('./ui-dev-watcher.js');
71
69
  const watcher = startUiDevWatcher(cwd, () => broadcastSseReload());
72
70
  server.on('close', () => watcher.close());
73
71
  }
74
-
75
72
  return new Promise((resolve, reject) => {
76
73
  server.on('error', (err) => {
77
74
  if (options.isCli) process.stderr.write(`\x1b[31m✖ UI error: ${err.message}\x1b[0m\n`);
@@ -81,13 +78,15 @@ export const startUiServer = async (options = {}) => {
81
78
  server.listen(port, host, () => {
82
79
  const addr = server.address();
83
80
  const actualPort = typeof addr === 'object' && addr ? addr.port : port;
84
- const displayHost = host === '0.0.0.0' ? 'localhost' : host;
85
- const url = `http://${displayHost}:${actualPort}`;
81
+ auth.cookieName = `chemx_ui_${actualPort}`;
82
+ const urlHost = resolveUiUrlHost(host);
83
+ const url = `http://${urlHost}:${actualPort}/?token=${auth.token}`;
86
84
  if (options.isCli) {
87
- process.stdout.write(`\x1b[32m✔ Chemical X Live Swarm Web UI running at:\x1b[0m \x1b[36m${url}\x1b[0m\n`);
88
- if (options.dev) process.stdout.write(`\x1b[35m🔥 Dev Hot Reload: ENABLED (watching UI files for instant updates)\x1b[0m\n`);
85
+ if (!isLoopbackHost(host)) warnPublicBind(host);
86
+ process.stdout.write(`\x1b[32m✔ Chemical X Live Swarm Web UI listening on ${host}:${actualPort}:\x1b[0m \x1b[36m${url}\x1b[0m\n`);
87
+ if (isDevMode) process.stdout.write(`\x1b[35m🔥 Dev Hot Reload: ENABLED (watching UI files for instant updates)\x1b[0m\n`);
89
88
  }
90
- resolve({ server, port: actualPort, url, db });
89
+ resolve({ server, port: actualPort, url, db, token: auth.token, fetch: createUiFetch(auth.token) });
91
90
  });
92
91
  });
93
92
  };
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Chemical X UI SQL console guard.
3
+ * The DB Studio console is read-only: one SELECT/WITH/VALUES/EXPLAIN statement
4
+ * or a read-only PRAGMA. Everything else (ATTACH, DDL, DML, PRAGMA writes) is refused.
5
+ * The server also runs console SQL on a readOnly, query_only connection as a second wall.
6
+ */
7
+ import { createRequire } from 'node:module';
8
+ import fs from 'node:fs';
9
+ import { resolveIndexDbPath } from './search-schema.js';
10
+ import { maskSqlLiteralsAndComments } from './ui-sql-mask.js';
11
+
12
+ const READ_STATEMENT_START = /^(SELECT|WITH|VALUES|EXPLAIN|PRAGMA)\b/i;
13
+ const WRITE_KEYWORDS = /\b(ATTACH|DETACH|INSERT|UPDATE|DELETE|CREATE|DROP|ALTER|VACUUM|REINDEX|ANALYZE)\b|\bREPLACE\s+INTO\b/i;
14
+ const INTROSPECTION_PRAGMAS = new Set([
15
+ 'table_info', 'table_xinfo', 'index_list', 'index_info', 'index_xinfo',
16
+ 'foreign_key_list', 'foreign_key_check', 'integrity_check', 'quick_check'
17
+ ]);
18
+ const QUERY_ONLY_PRAGMAS = new Set([
19
+ ...INTROSPECTION_PRAGMAS, 'table_list', 'database_list', 'collation_list', 'function_list',
20
+ 'pragma_list', 'compile_options', 'page_size', 'page_count', 'freelist_count', 'journal_mode',
21
+ 'busy_timeout', 'user_version', 'schema_version', 'application_id', 'encoding', 'auto_vacuum',
22
+ 'cache_size', 'synchronous', 'foreign_keys', 'wal_autocheckpoint'
23
+ ]);
24
+ const PRAGMA_SHAPE = /^PRAGMA\s+(?:\w+\.)?(\w+)\s*(\(\s*[\w"'.]+\s*\))?\s*$/i;
25
+
26
+ export const CONSOLE_READ_ONLY_ERROR =
27
+ 'Only SELECT, WITH, VALUES, EXPLAIN or read-only PRAGMA statements are permitted, one per request: the SQL console is read-only.';
28
+
29
+ const isSingleStatement = (code) => {
30
+ const withoutTrailing = code.trim().replace(/;\s*$/, '');
31
+ return !withoutTrailing.includes(';');
32
+ };
33
+
34
+ const isReadOnlyPragma = (code) => {
35
+ const shape = code.trim().replace(/;\s*$/, '').match(PRAGMA_SHAPE);
36
+ if (!shape) return false;
37
+ const name = shape[1].toLowerCase();
38
+ const hasArgument = Boolean(shape[2]);
39
+ if (hasArgument) return INTROSPECTION_PRAGMAS.has(name);
40
+ return QUERY_ONLY_PRAGMAS.has(name);
41
+ };
42
+
43
+ /** Returns { allowed, reason } for a console statement. */
44
+ export const classifyConsoleSql = (sql = '') => {
45
+ const masked = maskSqlLiteralsAndComments(sql);
46
+ const code = masked.code.trim();
47
+ if (!masked.isWellFormed) return { allowed: false, reason: CONSOLE_READ_ONLY_ERROR };
48
+ if (!code) return { allowed: false, reason: 'Empty SQL statement' };
49
+ const startsAsRead = READ_STATEMENT_START.test(code);
50
+ const isPragma = /^PRAGMA\b/i.test(code);
51
+ const hasWriteKeyword = WRITE_KEYWORDS.test(code);
52
+ const isAllowed = startsAsRead && isSingleStatement(code) && !hasWriteKeyword && (!isPragma || isReadOnlyPragma(code));
53
+ return isAllowed ? { allowed: true } : { allowed: false, reason: CONSOLE_READ_ONLY_ERROR };
54
+ };
55
+
56
+ export const CONSOLE_UNAVAILABLE_ERROR =
57
+ 'SQL console unavailable: the read-only index connection could not be opened.';
58
+
59
+ const loadDatabaseSync = () => {
60
+ try { return createRequire(import.meta.url)('node:sqlite').DatabaseSync; } catch { return null; }
61
+ };
62
+
63
+ const openReadOnly = (DatabaseSync, dbPath) => {
64
+ const connection = new DatabaseSync(dbPath, { readOnly: true });
65
+ connection.exec('PRAGMA query_only = 1');
66
+ return connection;
67
+ };
68
+
69
+ /** Opens a readOnly, query_only connection to the project index for the SQL console, or null. */
70
+ export const openConsoleDb = (cwd = process.cwd()) => {
71
+ const DatabaseSync = loadDatabaseSync();
72
+ const dbPath = resolveIndexDbPath(cwd);
73
+ const hasIndex = Boolean(DatabaseSync) && fs.existsSync(dbPath);
74
+ if (!hasIndex) return null;
75
+ try { return openReadOnly(DatabaseSync, dbPath); } catch { return null; }
76
+ };
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Single-pass SQL masker for the UI console guard.
3
+ * Walks the input left to right the way the SQLite tokenizer does, so the guard
4
+ * sees the same statement boundaries SQLite sees. Comments become a space,
5
+ * quoted strings and identifiers become an empty placeholder of the same quote.
6
+ * Returns { code, isWellFormed }: unterminated quotes or a NUL byte are not well formed.
7
+ */
8
+
9
+ const QUOTE_CLOSERS = { "'": "'", '"': '"', '`': '`', '[': ']' };
10
+
11
+ const findQuoteEnd = (sql, start, closer) => {
12
+ const allowsDoubling = closer !== ']';
13
+ let i = start + 1;
14
+ while (i < sql.length) {
15
+ const isCloser = sql[i] === closer;
16
+ const isDoubled = isCloser && allowsDoubling && sql[i + 1] === closer;
17
+ if (isDoubled) { i += 2; continue; }
18
+ if (isCloser) return i;
19
+ i += 1;
20
+ }
21
+ return -1;
22
+ };
23
+
24
+ const findLineCommentEnd = (sql, start) => {
25
+ const newline = sql.indexOf('\n', start);
26
+ return newline === -1 ? sql.length : newline;
27
+ };
28
+
29
+ const findBlockCommentEnd = (sql, start) => {
30
+ const close = sql.indexOf('*/', start + 2);
31
+ return close === -1 ? sql.length : close + 2;
32
+ };
33
+
34
+ export const maskSqlLiteralsAndComments = (sql = '') => {
35
+ const text = String(sql);
36
+ const hasNul = text.includes('\u0000');
37
+ if (hasNul) return { code: '', isWellFormed: false };
38
+ let code = '';
39
+ let i = 0;
40
+ while (i < text.length) {
41
+ const ch = text[i];
42
+ const pair = text.slice(i, i + 2);
43
+ const isLineComment = pair === '--';
44
+ const isBlockComment = pair === '/*';
45
+ const closer = QUOTE_CLOSERS[ch];
46
+ const isQuoteStart = Boolean(closer);
47
+ if (isLineComment) { code += ' '; i = findLineCommentEnd(text, i); continue; }
48
+ if (isBlockComment) { code += ' '; i = findBlockCommentEnd(text, i); continue; }
49
+ if (isQuoteStart) {
50
+ const end = findQuoteEnd(text, i, closer);
51
+ const isUnterminated = end === -1;
52
+ if (isUnterminated) return { code, isWellFormed: false };
53
+ code += ch + closer;
54
+ i = end + 1;
55
+ continue;
56
+ }
57
+ code += ch;
58
+ i += 1;
59
+ }
60
+ return { code, isWellFormed: true };
61
+ };
package/cli/ui-sse.js CHANGED
@@ -6,8 +6,7 @@ export const handleSseConnection = (req, res, db) => {
6
6
  res.writeHead(200, {
7
7
  'Content-Type': 'text/event-stream',
8
8
  'Cache-Control': 'no-cache, no-transform',
9
- 'Connection': 'keep-alive',
10
- 'Access-Control-Allow-Origin': '*'
9
+ 'Connection': 'keep-alive'
11
10
  });
12
11
 
13
12
  try {
@@ -28,7 +27,8 @@ export const handleSseConnection = (req, res, db) => {
28
27
  };
29
28
 
30
29
  export const broadcastSseUpdate = (db) => {
31
- if (clients.size === 0 || !db) return;
30
+ const isNotReady = clients.size === 0 || !db;
31
+ if (isNotReady) return;
32
32
  try {
33
33
  const state = handleSwarmStatus(db);
34
34
  const payload = `data: ${JSON.stringify(state)}\n\n`;
@@ -45,7 +45,8 @@ export const broadcastSseUpdate = (db) => {
45
45
  };
46
46
 
47
47
  export const broadcastSseReload = () => {
48
- if (clients.size === 0) return;
48
+ const hasNoClients = clients.size === 0;
49
+ if (hasNoClients) return;
49
50
  const payload = `event: reload\ndata: ${JSON.stringify({ timestamp: Date.now() })}\n\n`;
50
51
  for (const client of clients) {
51
52
  try {
@@ -8,8 +8,8 @@ export const VIEW_FILETREE_TEMPLATE = `
8
8
  <div style="display:flex; gap:8px; align-items:center; flex-wrap:wrap;">
9
9
  <strong>🧬 Codebase AST Explorer & Inspector</strong>
10
10
  <span class="a-badge badge-primary">{{ codebaseFiles.length }} Files</span>
11
- <span class="a-badge badge-lime">{{ cleanFileCount }} &le;100L</span>
12
- <span class="a-badge badge-pink">{{ monolithFileCount }} &gt;100L</span>
11
+ <span class="a-badge badge-lime">{{ cleanFileCount }} within line budget</span>
12
+ <span class="a-badge badge-pink">{{ monolithFileCount }} over line budget</span>
13
13
  <span v-if="codebaseHazardCount > 0" class="badge-hazard">⚠️ {{ codebaseHazardCount }} Hazards</span>
14
14
  </div>
15
15
  <div style="display:flex; gap:6px; align-items:center;">
@@ -30,7 +30,7 @@ export const VIEW_FILETREE_TEMPLATE = `
30
30
  </div>
31
31
  <div v-else class="filetree-file" :class="{ 'filetree-file--selected': selectedFilePath === node.path }" @click="selectFile(node.path)">
32
32
  <span>📄</span><span style="flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:11px;" :title="node.path">{{ node.name }}</span>
33
- <span class="a-badge" :class="node.lines > 100 ? 'badge-pink' : 'badge-lime'">{{ node.lines }}L</span>
33
+ <span class="a-badge" :class="node.isOverBudget ? 'badge-pink' : 'badge-lime'">{{ node.lines }}L</span>
34
34
  <span class="a-badge badge-primary" style="font-size:9px;">{{ node.tier }}</span>
35
35
  <span class="a-badge" :class="node.healthScore < 80 ? 'badge-warning' : 'badge-lime'" style="font-size:9px;">{{ node.healthScore }}%</span>
36
36
  <span v-if="node.hazardCount > 0" class="badge-hazard" style="font-size:9px;">⚠️{{ node.hazardCount }}</span>
@@ -46,7 +46,7 @@ export const VIEW_FILETREE_TEMPLATE = `
46
46
  <div style="display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:6px;">
47
47
  <strong style="color:#62c9ff; font-size:12px; word-break:break-all;">{{ selectedFileDetail.file.path }}</strong>
48
48
  <div style="display:flex; gap:6px; align-items:center;">
49
- <span class="a-badge" :class="selectedFileDetail.file.lines > 100 ? 'badge-pink' : 'badge-lime'">{{ selectedFileDetail.file.lines }} Lines</span>
49
+ <span class="a-badge" :class="selectedFileDetail.file.isOverBudget ? 'badge-pink' : 'badge-lime'">{{ selectedFileDetail.file.lines }} Lines</span>
50
50
  <span class="a-badge badge-primary">{{ selectedFileDetail.file.tier }}</span>
51
51
  <span class="a-badge badge-lime">Health: {{ selectedFileDetail.file.healthScore }}%</span>
52
52
  <span v-if="selectedFileDetail.file.hazardCount > 0" class="badge-hazard">⚠️ {{ selectedFileDetail.file.hazardCount }} Hazards</span>
@@ -1,3 +1,4 @@
1
+ import { formatTaskTokenStamp } from './team/team-telemetry.js';
1
2
  import { TASK_DETAILS_SHEET_TEMPLATE } from './ui-template-task-sheet.js';
2
3
 
3
4
  export const KANBAN_COLUMNS = [
@@ -14,12 +15,8 @@ export const groupTasksByColumn = (tasks = []) => ({
14
15
  blocked: tasks.filter((t) => t.status === 'blocked' || t.status === 'failed')
15
16
  });
16
17
 
17
- export const formatKanbanTokenStamp = (t = {}) => {
18
- const p = Number(t.prompt_tokens || 250);
19
- const c = Number(t.completion_tokens || 45);
20
- const cost = t.cost_usd != null ? Number(t.cost_usd) : ((p * 0.000003) + (c * 0.000015));
21
- return `[P: ${p} | C: ${c} | Cost: $${cost.toFixed(4)}]`;
22
- };
18
+ // Never invent tokens for an unmeasured task; the stamp says unknown.
19
+ export const formatKanbanTokenStamp = (t = {}) => formatTaskTokenStamp(t);
23
20
 
24
21
  export const VIEW_KANBAN_TEMPLATE = `
25
22
  <!-- 5-Column Kanban: Queued, In Progress, Review, Completed, Blocked -->
@@ -67,7 +64,7 @@ export const VIEW_KANBAN_TEMPLATE = `
67
64
  <span class="a-badge badge-warning" style="font-size:9px;">{{ (t.vds_priority || 'medium').toUpperCase() }}</span>
68
65
  <span class="a-badge badge-primary" style="cursor:pointer;" title="Click to view agent profile" @click="openAgentProfile(t.assigned_agent_id || t.assignedAgentId)">{{ t.assigned_agent_id || t.assignedAgentId || '@unassigned' }}</span>
69
66
  </div>
70
- <span class="vb-token-stamp">{{ t.tokenStamp || ('[P: ' + (t.prompt_tokens || 250) + ' | C: ' + (t.completion_tokens || 45) + ' | Cost: $' + (Number(t.cost_usd || 0.0014)).toFixed(4) + ']') }}</span>
67
+ <span class="vb-token-stamp">{{ t.tokenStamp || '[tokens: unknown]' }}</span>
71
68
 
72
69
  <div v-if="taskRefusals && taskRefusals[t.id]" style="background:#450a0a; border:1px solid #dc2626; color:#fca5a5; padding:5px 6px; border-radius:3px; margin:4px 0; font-size:10px;">
73
70
  <strong>⛔ Verification Refused:</strong> {{ taskRefusals[t.id].message }}
@@ -0,0 +1,43 @@
1
+ // `chemx verify --changed`: the audit covers only the changed source files and the tests only
2
+ // the affected specs; typecheck stays whole-project (types cross every file) and says so.
3
+ import path from 'node:path';
4
+ import { listChangedFiles } from './test-changes.js';
5
+ import { isSourceFilePath } from './audit-preflight-git.js';
6
+ import { ANSI } from './theme.js';
7
+ import { STATUS } from './result-status.js';
8
+ import { changedPackages, runPerPackage, changeNotes, rootOrAllPackages } from './workspace-run.js';
9
+
10
+ // Returns { ok, base, files } (root-relative source files that still exist) or { ok: false, error }.
11
+ export const resolveVerifyChanges = (root, base = null) => {
12
+ const listing = listChangedFiles(root, { base });
13
+ const isListingFailed = !listing.ok;
14
+ if (isListingFailed) return { ok: false, error: listing.error };
15
+ const files = listing.files.filter((f) => f.status !== 'D' && isSourceFilePath(f.path)).map((f) => f.path);
16
+ return { ok: true, base: listing.base, files };
17
+ };
18
+
19
+ export const changedAuditOptions = (root, changes) => ({ fileList: changes.files.map((file) => path.join(root, file)) });
20
+
21
+ export const testArgsFor = (changes, base) => (changes ? ['--changed', ...(base ? [`--base=${base}`] : [])] : []);
22
+
23
+ // verify at a monorepo root: --changed verifies each package that owns a changed file,
24
+ // --all-packages verifies every package, anything else is refused with the package list.
25
+ // runInPackage(pkg, args) resolves to that package's own verify summary.
26
+ export const verifyWorkspace = async (workspace, { changed, base, allPackages }, runInPackage) => {
27
+ if (!changed) return rootOrAllPackages(workspace, 'verify', allPackages, (pkg) => runInPackage(pkg, []));
28
+ const changes = changedPackages(workspace, base);
29
+ const isChangesFailed = !changes.ok;
30
+ if (isChangesFailed) return { status: STATUS.INCONCLUSIVE, success: false, reason: 'NO_CHANGES', error: `cannot list changed files: ${changes.error}`, packages: [] };
31
+ const args = testArgsFor(changes, base);
32
+ const extraStatuses = changes.rootManifests.length > 0 || changes.packages.length === 0 ? [STATUS.INCONCLUSIVE] : [];
33
+ const units = changes.packages.map((pkg) => ({ pkg, args }));
34
+ return runPerPackage(units, (unit) => runInPackage(unit.pkg, unit.args), { base: changes.base, dependents: changes.dependents, rootFiles: changes.rootFiles, notes: changeNotes(changes), extraStatuses });
35
+ };
36
+
37
+ export const formatVerifyLine = (entry) => {
38
+ const steps = ['audit', 'typecheck', 'tests'].map((step) => `${step} ${entry[step]?.status ?? '-'}`).join(', ');
39
+ const icon = entry.status === STATUS.PASS ? `${ANSI.LIME}✔` : `${ANSI.RED}✖`;
40
+ const excluded = Array.isArray(entry.scope?.excluded) ? entry.scope.excluded : [];
41
+ const scopeLine = excluded.length > 0 ? ` ${ANSI.DIM}audited ${entry.scope.dir}/; not audited: ${excluded.join(", ")} (--all-packages runs their own audits)${ANSI.RESET}\n` : "";
42
+ return ` ${icon}${ANSI.RESET} ${entry.status} ${ANSI.DIM}(${steps})${ANSI.RESET}\n${scopeLine}`;
43
+ };