@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
@@ -1,4 +1,14 @@
1
1
  <script lang="ts">
2
+ export interface AtomButtonProps {
3
+ type?: 'button' | 'submit' | 'reset';
4
+ disabled?: boolean;
5
+ ariaLabel?: string;
6
+ variant?: 'primary' | 'ghost' | 'glass';
7
+ class?: string;
8
+ onclick?: (e: MouseEvent) => void;
9
+ children?: import('svelte').Snippet;
10
+ }
11
+
2
12
  let {
3
13
  type = 'button',
4
14
  disabled = false,
@@ -7,15 +17,7 @@
7
17
  class: className = '',
8
18
  onclick,
9
19
  children
10
- } = $props<{
11
- type?: 'button' | 'submit' | 'reset';
12
- disabled?: boolean;
13
- ariaLabel?: string;
14
- variant?: 'primary' | 'ghost' | 'glass';
15
- class?: string;
16
- onclick?: (e: MouseEvent) => void;
17
- children?: import('svelte').Snippet;
18
- }>();
20
+ } = $props<AtomButtonProps>();
19
21
  </script>
20
22
 
21
23
  <button
@@ -22,7 +22,8 @@ const emit = defineEmits<{
22
22
  }>();
23
23
 
24
24
  const handleClick = (event: MouseEvent) => {
25
- if (props.disabled) return;
25
+ const isDisabled = Boolean(props.disabled);
26
+ if (isDisabled) return;
26
27
  emit('click', event);
27
28
  };
28
29
  </script>
@@ -3,10 +3,14 @@
3
3
 
4
4
  export const resolveGradeClass = (grade: string): string => {
5
5
  const g = grade.toUpperCase();
6
- if (g.startsWith('A')) return 'm-chemx-badge__grade--a';
7
- if (g.startsWith('B')) return 'm-chemx-badge__grade--b';
8
- if (g.startsWith('C')) return 'm-chemx-badge__grade--c';
9
- if (g.startsWith('D')) return 'm-chemx-badge__grade--d';
6
+ const isGradeA = Boolean(g.startsWith('A'));
7
+ if (isGradeA) return 'm-chemx-badge__grade--a';
8
+ const isGradeB = Boolean(g.startsWith('B'));
9
+ if (isGradeB) return 'm-chemx-badge__grade--b';
10
+ const isGradeC = Boolean(g.startsWith('C'));
11
+ if (isGradeC) return 'm-chemx-badge__grade--c';
12
+ const isGradeD = Boolean(g.startsWith('D'));
13
+ if (isGradeD) return 'm-chemx-badge__grade--d';
10
14
  return 'm-chemx-badge__grade--f';
11
15
  };
12
16
 
@@ -3,10 +3,14 @@ import type { MChemxBadgeProps } from './types';
3
3
 
4
4
  export const resolveGradeClass = (grade: string): string => {
5
5
  const g = grade.toUpperCase();
6
- if (g.startsWith('A')) return 'm-chemx-badge__grade--a';
7
- if (g.startsWith('B')) return 'm-chemx-badge__grade--b';
8
- if (g.startsWith('C')) return 'm-chemx-badge__grade--c';
9
- if (g.startsWith('D')) return 'm-chemx-badge__grade--d';
6
+ const isGradeA = g.startsWith('A');
7
+ if (isGradeA) return 'm-chemx-badge__grade--a';
8
+ const isGradeB = g.startsWith('B');
9
+ if (isGradeB) return 'm-chemx-badge__grade--b';
10
+ const isGradeC = g.startsWith('C');
11
+ if (isGradeC) return 'm-chemx-badge__grade--c';
12
+ const isGradeD = g.startsWith('D');
13
+ if (isGradeD) return 'm-chemx-badge__grade--d';
10
14
  return 'm-chemx-badge__grade--f';
11
15
  };
12
16
 
@@ -18,10 +18,14 @@ const props = withDefaults(defineProps<MChemxBadgeProps>(), {
18
18
  const targetHref = computed(() => props.reportUrl || props.href);
19
19
  const gradeClass = computed(() => {
20
20
  const g = props.grade.toUpperCase();
21
- if (g.startsWith('A')) return 'm-chemx-badge__grade--a';
22
- if (g.startsWith('B')) return 'm-chemx-badge__grade--b';
23
- if (g.startsWith('C')) return 'm-chemx-badge__grade--c';
24
- if (g.startsWith('D')) return 'm-chemx-badge__grade--d';
21
+ const isGradeA = g.startsWith('A');
22
+ if (isGradeA) return 'm-chemx-badge__grade--a';
23
+ const isGradeB = g.startsWith('B');
24
+ if (isGradeB) return 'm-chemx-badge__grade--b';
25
+ const isGradeC = g.startsWith('C');
26
+ if (isGradeC) return 'm-chemx-badge__grade--c';
27
+ const isGradeD = g.startsWith('D');
28
+ if (isGradeD) return 'm-chemx-badge__grade--d';
25
29
  return 'm-chemx-badge__grade--f';
26
30
  });
27
31
  </script>
@@ -13,7 +13,8 @@
13
13
  const isHighValue = $derived(value > 1000);
14
14
 
15
15
  const badge = $derived.by((): SampleCardBadgeDescriptor => {
16
- if (status !== 'active') {
16
+ const isArchived = status !== 'active';
17
+ if (isArchived) {
17
18
  return {
18
19
  text: status,
19
20
  className: 'm-sample-card__badge m-sample-card__badge--archived'
@@ -6,7 +6,8 @@ export const resolveBadgeDescriptor = (
6
6
  status: 'active' | 'archived',
7
7
  isHighValue: boolean
8
8
  ): SampleCardBadgeDescriptor => {
9
- if (status !== 'active') {
9
+ const isArchived = status !== 'active';
10
+ if (isArchived) {
10
11
  return {
11
12
  text: status,
12
13
  className: 'm-sample-card__badge m-sample-card__badge--archived'
@@ -12,7 +12,8 @@ const props = withDefaults(defineProps<MSampleCardProps>(), {
12
12
  const isHighValue = computed(() => props.value > 1000);
13
13
 
14
14
  const badge = computed((): SampleCardBadgeDescriptor => {
15
- if (props.status !== 'active') {
15
+ const isArchived = props.status !== 'active';
16
+ if (isArchived) {
16
17
  return {
17
18
  text: props.status,
18
19
  className: 'm-sample-card__badge m-sample-card__badge--archived'
@@ -31,7 +32,8 @@ const badge = computed((): SampleCardBadgeDescriptor => {
31
32
  });
32
33
 
33
34
  const handleActionClick = () => {
34
- if (props.onAction) props.onAction();
35
+ const onActionHandler = props.onAction;
36
+ if (onActionHandler) onActionHandler();
35
37
  };
36
38
  </script>
37
39
 
@@ -31,13 +31,19 @@ jobs:
31
31
  npm install
32
32
  fi
33
33
 
34
+ # Gate on the ratchet (chemx-ratchet.json): fail only when a rule rises above its recorded
35
+ # baseline. Without a ratchet file the gate fails on any CRITICAL/HIGH finding; record one with
36
+ # `npx chemx audit --rebaseline` (full scan). Set the CHEMX_MIN_GRADE / CHEMX_MIN_SCORE repo
37
+ # variables to add absolute floors.
34
38
  - name: Run Chemical X Architectural Audit
39
+ env:
40
+ CHEMX_MIN_GRADE: ${{ vars.CHEMX_MIN_GRADE }}
41
+ CHEMX_MIN_SCORE: ${{ vars.CHEMX_MIN_SCORE }}
35
42
  run: |
36
- npx --yes chemx audit \
37
- --min-grade=${{ vars.CHEMX_MIN_GRADE || 'B' }} \
38
- --min-score=${{ vars.CHEMX_MIN_SCORE || 80 }} \
39
- --markdown \
40
- --output=AUDIT_REPORT.md
43
+ set -- --markdown --output=AUDIT_REPORT.md
44
+ if [ -n "$CHEMX_MIN_GRADE" ]; then set -- "$@" "--min-grade=$CHEMX_MIN_GRADE"; fi
45
+ if [ -n "$CHEMX_MIN_SCORE" ]; then set -- "$@" "--min-score=$CHEMX_MIN_SCORE"; fi
46
+ npx --yes chemx audit "$@"
41
47
 
42
48
  - name: Upload Audit Scorecard Artifact
43
49
  if: always()
@@ -62,53 +68,16 @@ jobs:
62
68
  {
63
69
  echo "<!-- chemical-x-audit-pr-comment -->"
64
70
  if [ -n "$DISCUSSION_URL" ]; then
65
- echo "> 💬 **Architectural Discussion Topic:** [View Discussion & Community Showcase](\${DISCUSSION_URL})"
71
+ echo "> 💬 **Architectural Discussion Topic:** [View Discussion & Community Showcase]($DISCUSSION_URL)"
66
72
  echo ""
67
73
  fi
68
74
  cat AUDIT_REPORT.md
69
75
  } > PR_COMMENT.md
70
76
 
71
- EXISTING_COMMENT_ID=$(gh api "repos/\${REPO}/issues/\${PR_NUMBER}/comments" --jq '.[] | select(.body | contains("<!-- chemical-x-audit-pr-comment -->")) | .id' | head -n 1)
77
+ EXISTING_COMMENT_ID=$(gh api "repos/$REPO/issues/$PR_NUMBER/comments" --jq '.[] | select(.body | contains("<!-- chemical-x-audit-pr-comment -->")) | .id' | head -n 1)
72
78
 
73
79
  if [ -n "$EXISTING_COMMENT_ID" ]; then
74
- gh api --method PATCH "repos/\${REPO}/issues/comments/\${EXISTING_COMMENT_ID}" -F body=@PR_COMMENT.md
80
+ gh api --method PATCH "repos/$REPO/issues/comments/$EXISTING_COMMENT_ID" -F body=@PR_COMMENT.md
75
81
  else
76
- gh pr comment "\${PR_NUMBER}" --body-file PR_COMMENT.md
82
+ gh pr comment "$PR_NUMBER" --body-file PR_COMMENT.md
77
83
  fi
78
-
79
- scaffold-smoke-test:
80
- name: Framework Scaffolding Smoke Test
81
- runs-on: ubuntu-latest
82
- steps:
83
- - name: Checkout Code
84
- uses: actions/checkout@v4
85
- - name: Setup Node.js
86
- uses: actions/setup-node@v4
87
- with:
88
- node-version: 22
89
- - name: Install Dependencies
90
- run: npm install
91
- - name: Run Test Suite
92
- run: npm test
93
- - name: Multi-Framework Scaffolding Smoke Test
94
- run: |
95
- for fw in react vue svelte; do
96
- echo "Smoke testing scaffolding for framework: $fw"
97
- node cli/create.js test-app-$fw --framework=$fw --yes --skip-install
98
- if [ "$fw" = "react" ]; then
99
- test -f test-app-react/src/components/m-sample-card/m-sample-card.tsx
100
- ! ls test-app-react/src/components/m-sample-card/*.vue 2>/dev/null
101
- ! ls test-app-react/src/components/m-sample-card/*.svelte 2>/dev/null
102
- elif [ "$fw" = "vue" ]; then
103
- test -f test-app-vue/src/components/m-sample-card/m-sample-card.vue
104
- ! ls test-app-vue/src/components/m-sample-card/*.tsx 2>/dev/null
105
- ! ls test-app-vue/src/components/m-sample-card/*.svelte 2>/dev/null
106
- elif [ "$fw" = "svelte" ]; then
107
- test -f test-app-svelte/src/components/m-sample-card/m-sample-card.svelte
108
- ! ls test-app-svelte/src/components/m-sample-card/*.vue 2>/dev/null
109
- ! ls test-app-svelte/src/components/m-sample-card/*.tsx 2>/dev/null
110
- fi
111
- echo "Framework $fw scaffolded cleanly."
112
- done
113
-
114
-
@@ -0,0 +1,40 @@
1
+ import { stripAnsi } from './terminal.js';
2
+
3
+ // One serializer for every --json payload an agent reads (CLI and, via G3, MCP):
4
+ // minified, ANSI-free, no null fields. Diagnostic lists stay arrays (so `.errors|length`
5
+ // counts diagnostics whether there are none or many) of "file:line:col CODE message"
6
+ // strings, each shorter than the raw tool line it replaces. A report costs at most the raw
7
+ // output plus a fixed envelope (success, exitCode, command, durationMs, errorCount);
8
+ // cli/agent-json.spec.js pins both bounds.
9
+
10
+ const isDiagnosticRow = (item) =>
11
+ Boolean(item) && typeof item === 'object' && typeof item.file === 'string' && 'line' in item && 'message' in item;
12
+
13
+ const isDiagnosticList = (value) => Array.isArray(value) && value.length > 0 && value.every(isDiagnosticRow);
14
+
15
+ export const formatDiagnosticRow = (row) => {
16
+ const isWarning = String(row.severity ?? '').toUpperCase() === 'WARNING';
17
+ const position = [stripAnsi(row.file), row.line, row.column].filter((part) => part !== undefined && part !== null && part !== '').join(':');
18
+ const code = row.code ?? row.ruleId ?? row.rule ?? null;
19
+ const parts = [position, isWarning ? 'warning' : null, code, stripAnsi(String(row.message))];
20
+ return parts.filter(Boolean).join(' ');
21
+ };
22
+
23
+ const compactValue = (value) => {
24
+ const isString = typeof value === 'string';
25
+ if (isString) return stripAnsi(value);
26
+ if (isDiagnosticList(value)) return value.map(formatDiagnosticRow);
27
+ if (Array.isArray(value)) return value.map(compactValue);
28
+ const isPlainObject = Boolean(value) && typeof value === 'object';
29
+ if (!isPlainObject) return value;
30
+ const compacted = {};
31
+ for (const [key, entry] of Object.entries(value)) {
32
+ const isAbsent = entry === null || entry === undefined;
33
+ if (!isAbsent) compacted[key] = compactValue(entry);
34
+ }
35
+ return compacted;
36
+ };
37
+
38
+ export const compactAgentPayload = (payload) => compactValue(payload);
39
+
40
+ export const formatAgentJson = (payload) => JSON.stringify(compactValue(payload));
@@ -0,0 +1,195 @@
1
+ /**
2
+ * applyEdits: the single mutation gate for write, patch, autofix, explode and add:*.
3
+ *
4
+ * Every edit is validated before anything touches disk:
5
+ * - the path stays inside the workspace (realpath containment, symlinked parents included);
6
+ * - the new text parses (Babel / SFC script blocks / JSON) unless the old text was already broken;
7
+ * - no top-level declaration disappears unless the caller named it in allowRemoved;
8
+ * - no other agent holds a team lock on the file.
9
+ * A dry run returns the same result (with an uncapped unified diff) and writes nothing.
10
+ * A real run writes each file atomically with a backup and rolls back the batch on failure.
11
+ */
12
+ import fs from 'node:fs';
13
+ import os from 'node:os';
14
+ import path from 'node:path';
15
+ import { spawnSync } from 'node:child_process';
16
+ import { resolveSafePath } from './path-scope.js';
17
+ import { parseSource } from './source-parse.js';
18
+ import { buildUnifiedDiff } from './edit-diff.js';
19
+ import { writeAtomic, removeWithBackup, restoreFromBackup } from './edit-atomic.js';
20
+ import { findForeignLease } from './edit-locks.js';
21
+ import { syncLeasesAfterEdit } from './team/lease-renew.js';
22
+ import { countLines } from './line-count.js';
23
+
24
+ export class EditRefusedError extends Error {
25
+ constructor(issues) {
26
+ super(issues.map((i) => `${i.file}: ${i.reason}`).join('\n'));
27
+ this.name = 'EditRefusedError';
28
+ this.issues = issues;
29
+ }
30
+ }
31
+
32
+ /**
33
+ * Declaration delta between two parses. Every top-level declaration that disappears must be
34
+ * named in allowRemoved (or allowRemoved === true), renames included: a patch that removes A
35
+ * and adds an unrelated B is exactly the wrong-block replace this gate exists to catch.
36
+ */
37
+ const declarationDelta = (beforeParse, afterParse, allowRemoved) => {
38
+ const isComparable = beforeParse.ok && afterParse.ok && beforeParse.kind === 'babel';
39
+ if (!isComparable) return { removed: [], added: [], blocked: [] };
40
+ const beforeSet = new Set(beforeParse.declarations);
41
+ const afterSet = new Set(afterParse.declarations);
42
+ const removed = beforeParse.declarations.filter((name) => !afterSet.has(name));
43
+ const added = afterParse.declarations.filter((name) => !beforeSet.has(name));
44
+ const isAllAllowed = allowRemoved === true;
45
+ const allowed = new Set(Array.isArray(allowRemoved) ? allowRemoved : []);
46
+ const unallowed = isAllAllowed ? [] : removed.filter((name) => !allowed.has(name));
47
+ return { removed, added, blocked: unallowed };
48
+ };
49
+
50
+ const V8_CHECKED_EXTENSIONS = new Set(['.js', '.mjs', '.cjs']);
51
+
52
+ /**
53
+ * V8's own syntax check (node --check on a temp copy). Babel's parse does not report every
54
+ * early error V8 raises at import (redeclarations, duplicate exports, bad regex flags).
55
+ * Returns the first SyntaxError line, or null when V8 accepts the text or the check could not run
56
+ * (a failure to spawn node is not treated as a syntax error).
57
+ */
58
+ const v8SyntaxError = (text, absPath, parse) => {
59
+ const ext = path.extname(absPath);
60
+ const isCheckedExtension = V8_CHECKED_EXTENSIONS.has(ext);
61
+ if (!isCheckedExtension) return null;
62
+ let dir = null;
63
+ try {
64
+ dir = fs.mkdtempSync(path.join(os.tmpdir(), 'chemx-v8check-'));
65
+ // node --check on a .js file holding module syntax skips regex early errors, so the copy
66
+ // gets the extension that matches how Babel read the text.
67
+ const isModule = ext === '.mjs' || parse.programs?.[0]?.sourceType === 'module';
68
+ const isCommonJs = ext === '.cjs' || !isModule;
69
+ const checkExt = isCommonJs ? '.cjs' : '.mjs';
70
+ const tmp = path.join(dir, `check${checkExt}`);
71
+ fs.writeFileSync(tmp, text);
72
+ const res = spawnSync(process.execPath, ['--check', tmp], { encoding: 'utf-8', timeout: 15000 });
73
+ const isAccepted = Boolean(res.error) || res.status === 0;
74
+ if (isAccepted) return null;
75
+ const lines = String(res.stderr).split('\n');
76
+ const found = lines.find((l) => /^\w*Error: /.test(l));
77
+ return found || lines.find((l) => l.trim()) || 'unknown syntax error';
78
+ } catch {
79
+ return null;
80
+ } finally {
81
+ if (dir) fs.rmSync(dir, { recursive: true, force: true });
82
+ }
83
+ };
84
+
85
+ const lapsedIssue = (file, lease) => {
86
+ const at = new Date(lease.expiresAt).toISOString();
87
+ return `your lease on ${file} lapsed at ${at} and ${lease.queue.join(', ')} ${lease.queue.length > 1 ? 'are' : 'is'} queued for it, so it is theirs next and this edit was not made (queue: ${lease.queue.join(' > ')}; see: chemx team lock status ${file})`;
88
+ };
89
+
90
+ const lockedIssue = (file, lease) => {
91
+ const isLapsedOwn = Boolean(lease.lapsedOwn);
92
+ if (isLapsedOwn) return lapsedIssue(file, lease);
93
+ const purpose = lease.purpose ? ` (${lease.purpose})` : '';
94
+ const until = new Date(lease.expiresAt).toISOString();
95
+ return `locked by ${lease.lockedBy}${purpose} until ${until}; wait until ${lease.lockedBy} releases it or the lease expires (check: chemx team lock check ${file}; all locks: chemx team lock list)`;
96
+ };
97
+
98
+ const planEdit = (edit, root, options) => {
99
+ const absPath = resolveSafePath(edit.path, root);
100
+ const file = path.relative(root, absPath);
101
+ const isExisting = fs.existsSync(absPath);
102
+ const isDirectory = isExisting && fs.statSync(absPath).isDirectory();
103
+ if (isDirectory) return { file, absPath, issue: 'path is a directory' };
104
+
105
+ const before = isExisting ? fs.readFileSync(absPath, 'utf-8') : null;
106
+ const isDelete = Boolean(edit.delete);
107
+ const plan = { file, absPath, before, isDelete, created: !isExisting, deleted: isDelete };
108
+ const isDeletingNothing = isDelete && !isExisting;
109
+ if (isDeletingNothing) return { ...plan, issue: 'cannot delete a file that does not exist' };
110
+ const isMissingContent = !isDelete && typeof edit.content !== 'string';
111
+ if (isMissingContent) return { ...plan, issue: 'no content given' };
112
+
113
+ const after = isDelete ? '' : edit.content;
114
+ const lease = findForeignLease(root, absPath, options.agentId);
115
+ const isLocked = Boolean(lease);
116
+ if (isLocked) return { ...plan, issue: lockedIssue(file, lease) };
117
+ if (isDelete) return { ...plan, after, parse: { kind: 'n/a', ok: true }, declarations: { removed: [], added: [] } };
118
+
119
+ const afterParse = parseSource(after, absPath);
120
+ const beforeParse = before === null ? null : parseSource(before, absPath);
121
+ const wasBroken = Boolean(beforeParse) && !beforeParse.ok;
122
+ const isNewlyBroken = !afterParse.ok && !wasBroken;
123
+ if (isNewlyBroken) return { ...plan, after, issue: `result does not parse (${afterParse.error}); nothing was written` };
124
+
125
+ const v8Error = wasBroken ? null : v8SyntaxError(after, absPath, afterParse);
126
+ if (v8Error) return { ...plan, after, issue: `V8 rejects the result (${v8Error}); nothing was written` };
127
+
128
+ const delta = beforeParse ? declarationDelta(beforeParse, afterParse, edit.allowRemoved) : { removed: [], added: [], blocked: [] };
129
+ const hasBlockedRemovals = delta.blocked.length > 0;
130
+ if (hasBlockedRemovals) {
131
+ const hasAdded = delta.added.length > 0;
132
+ const addedNote = hasAdded ? ` (and would add ${delta.added.join(', ')})` : '';
133
+ return { ...plan, after, issue: `would remove top-level declaration(s) ${delta.blocked.join(', ')}${addedNote}; name them in allowRemoved (CLI: --allow-remove=${delta.blocked.join(',')}) if intended` };
134
+ }
135
+
136
+ const parse = { kind: afterParse.kind, ok: afterParse.ok, ...(wasBroken ? { note: 'file did not parse before this edit either, so the parse and declaration-removal checks could not run' } : {}) };
137
+ return { ...plan, after, parse, declarations: { removed: delta.removed, added: delta.added } };
138
+ };
139
+
140
+ const commitPlans = (plans, root) => {
141
+ const done = [];
142
+ try {
143
+ for (const plan of plans) {
144
+ const isUnchanged = !plan.isDelete && plan.before === plan.after;
145
+ if (isUnchanged) continue;
146
+ const { backup } = plan.isDelete ? removeWithBackup(plan.absPath, root) : writeAtomic(plan.absPath, plan.after, root);
147
+ plan.backup = backup;
148
+ done.push(plan);
149
+ }
150
+ } catch (err) {
151
+ for (const plan of done.reverse()) restoreFromBackup(plan.absPath, plan.backup);
152
+ throw err;
153
+ }
154
+ };
155
+
156
+ /**
157
+ * @param {Array<{ path: string, content?: string, delete?: boolean, allowRemoved?: string[]|true }>} edits
158
+ * @param {object} [options] { cwd, dryRun, agentId }
159
+ * @returns {{ dryRun: boolean, files: object[], diff: string }}
160
+ * @throws {EditRefusedError} When any edit is refused (nothing is written).
161
+ */
162
+ export const applyEdits = (edits, options = {}) => {
163
+ const rawRoot = options.cwd || process.cwd();
164
+ const root = fs.existsSync(rawRoot) ? fs.realpathSync(rawRoot) : path.resolve(rawRoot);
165
+ const dryRun = Boolean(options.dryRun);
166
+ const plans = edits.map((edit) => planEdit(edit, root, options));
167
+ const issues = plans.filter((p) => p.issue).map((p) => ({ file: p.file, reason: p.issue }));
168
+ const hasIssues = issues.length > 0;
169
+ if (hasIssues) throw new EditRefusedError(issues);
170
+
171
+ const isPreview = dryRun;
172
+ let leaseNotes = [];
173
+ if (!isPreview) {
174
+ commitPlans(plans, root);
175
+ // Renew-on-edit: a live lease of the caller's on a written file gets one more TTL; a lapsed,
176
+ // untaken one is re-acquired and the result says so.
177
+ leaseNotes = syncLeasesAfterEdit(root, plans.map((p) => p.absPath), options.agentId).notes;
178
+ }
179
+
180
+ const files = plans.map((p) => ({
181
+ file: p.file,
182
+ absPath: p.absPath,
183
+ created: p.created,
184
+ deleted: p.deleted,
185
+ changed: p.isDelete || p.before !== p.after,
186
+ originalLines: p.before === null ? 0 : countLines(p.before),
187
+ newLines: p.isDelete ? 0 : countLines(p.after),
188
+ parse: p.parse,
189
+ declarations: p.declarations,
190
+ backup: p.backup ? path.relative(root, p.backup) : null,
191
+ diff: buildUnifiedDiff(p.before ?? '', p.after, { path: p.file, isNew: p.created, isDeleted: p.isDelete })
192
+ }));
193
+ const noteField = leaseNotes.length > 0 ? { leaseNotes } : {};
194
+ return { dryRun, files, diff: files.map((f) => f.diff).filter(Boolean).join('\n'), ...noteField };
195
+ };
@@ -1,4 +1,5 @@
1
1
  import * as t from '@babel/types';
2
+ import { ruleTree } from '../rules.js';
2
3
  import { RULE_REGISTRY } from './rules-registry.js';
3
4
  import {
4
5
  isComponentPath,
@@ -7,12 +8,17 @@ import {
7
8
  hasAnyTypeAnnotation,
8
9
  isRedundantPassthroughReturn
9
10
  } from './rules-predicates.js';
11
+ import { resolveCatchEscalation, resolveCatchSpan } from './shallow-catch-escalation.js';
10
12
 
11
13
  const RESIDUE_PATTERNS = [
12
14
  ['hope this', 'helps'].join(' '),
13
15
  ['feel free', 'to tweak'].join(' '),
14
16
  ['let me know', 'if you need'].join(' '),
15
- ['as', 'requested'].join(' '),
17
+ // Assistant framing only (the phrase followed by a pause and "here"/"I"/"below",
18
+ // or addressed to "you"). The bare phrase in a sentence about an API client is
19
+ // ordinary engineering prose.
20
+ ['as you', 'requested'].join(' '),
21
+ ['as', 'requested[,.!:]\\s*(?:here|i\\b|below)'].join(' '),
16
22
  ['as an ai', 'language model'].join(' ')
17
23
  ];
18
24
 
@@ -81,19 +87,24 @@ const normalizeWords = (text) => {
81
87
  const COMMENT_LINE_START = /^\s*(?:\/\/|#|\*|--)/;
82
88
 
83
89
  const isInsideStringLiteral = (lineText, matchIndex) => {
84
- if (matchIndex <= 0) return false;
85
- if (COMMENT_LINE_START.test(lineText)) return false;
90
+ const isAtLineStart = matchIndex <= 0;
91
+ if (isAtLineStart) return false;
92
+ const isCommentLine = COMMENT_LINE_START.test(lineText);
93
+ if (isCommentLine) return false;
86
94
 
87
95
  let quote = null;
88
96
  for (let i = 0; i < matchIndex; i += 1) {
89
97
  const ch = lineText[i];
90
- if (ch === '\\') {
98
+ const isEscape = ch === '\\';
99
+ if (isEscape) {
91
100
  i += 1;
92
101
  continue;
93
102
  }
103
+ const closesQuote = ch === quote;
104
+ const opensQuote = ch === '"' || ch === "'" || ch === '`';
94
105
  if (quote) {
95
- if (ch === quote) quote = null;
96
- } else if (ch === '"' || ch === "'" || ch === '`') {
106
+ if (closesQuote) quote = null;
107
+ } else if (opensQuote) {
97
108
  quote = ch;
98
109
  }
99
110
  }
@@ -104,7 +115,8 @@ export const checkSlopTextPatterns = (content, lines, relativePath, violations)
104
115
  lines.forEach((lineText, idx) => {
105
116
  for (const pat of CONVERSATIONAL_PATTERNS) {
106
117
  const hit = pat.regex.exec(lineText);
107
- if (hit && !isInsideStringLiteral(lineText, hit.index)) {
118
+ const isRealHit = Boolean(hit && !isInsideStringLiteral(lineText, hit.index));
119
+ if (isRealHit) {
108
120
  const meta = RULE_REGISTRY[pat.rule];
109
121
  violations.push({
110
122
  filePath: relativePath,
@@ -122,11 +134,13 @@ export const checkSlopTextPatterns = (content, lines, relativePath, violations)
122
134
  }
123
135
 
124
136
  const trimmed = lineText.trim();
125
- if (trimmed.startsWith('//') && !trimmed.startsWith('///')) {
137
+ const isLineComment = trimmed.startsWith('//') && !trimmed.startsWith('///');
138
+ if (isLineComment) {
126
139
  const commentBody = trimmed.replace(/^\/\/\s*/, '');
127
140
  const commentWords = normalizeWords(commentBody);
128
141
 
129
- if (commentWords.length >= 2 && commentWords.length <= 6) {
142
+ const isShortComment = commentWords.length >= 2 && commentWords.length <= 6;
143
+ if (isShortComment) {
130
144
  let nextIdx = idx + 1;
131
145
  while (nextIdx < lines.length) {
132
146
  const nextTrim = lines[nextIdx].trim();
@@ -134,10 +148,12 @@ export const checkSlopTextPatterns = (content, lines, relativePath, violations)
134
148
  const nextWords = new Set(normalizeWords(nextTrim));
135
149
  let matchCount = 0;
136
150
  for (const cw of commentWords) {
137
- if (nextWords.has(cw)) matchCount += 1;
151
+ const isEchoedWord = nextWords.has(cw);
152
+ if (isEchoedWord) matchCount += 1;
138
153
  }
139
154
  const matchRatio = matchCount / commentWords.length;
140
- if (matchRatio >= 0.75) {
155
+ const isEcho = matchRatio >= 0.75;
156
+ if (isEcho) {
141
157
  const meta = RULE_REGISTRY.AI_SLOP_ECHO_COMMENT;
142
158
  violations.push({
143
159
  filePath: relativePath,
@@ -169,15 +185,16 @@ export const createAiSlopVisitors = ({ relativePath, violations }) => {
169
185
  const isShallowCatch = isShallowCatchBody(body, t);
170
186
 
171
187
  if (isShallowCatch) {
172
- const line = astPath.node.loc?.start.line || 1;
173
188
  const meta = RULE_REGISTRY.AI_SLOP_SHALLOW_CATCH;
189
+ const { severity, binding } = resolveCatchEscalation(astPath);
174
190
  violations.push({
175
191
  filePath: relativePath,
176
- line,
177
- column: astPath.node.loc?.start.column || 1,
178
- hazard: 'Shallow catch paranoia wrapper (silent suppression without handling)',
192
+ ...resolveCatchSpan(astPath),
193
+ hazard: binding
194
+ ? `Shallow catch leaves "${binding}" unset; it is read after the try (silent undefined propagation)`
195
+ : 'Shallow catch paranoia wrapper (silent suppression without handling)',
179
196
  rule: 'AI_SLOP_SHALLOW_CATCH',
180
- severity: meta.severity,
197
+ severity,
181
198
  pillar: meta.pillar,
182
199
  directive: meta.directive,
183
200
  isAiSlop: true
@@ -203,7 +220,8 @@ export const createAiSlopVisitors = ({ relativePath, violations }) => {
203
220
 
204
221
  BlockStatement(astPath) {
205
222
  const stmts = astPath.node.body;
206
- if (stmts.length >= 2) {
223
+ const hasMultipleStatements = stmts.length >= 2;
224
+ if (hasMultipleStatements) {
207
225
  for (let i = 0; i < stmts.length - 1; i++) {
208
226
  const curr = stmts[i];
209
227
  const next = stmts[i + 1];
@@ -230,7 +248,8 @@ export const createAiSlopVisitors = ({ relativePath, violations }) => {
230
248
  FunctionDeclaration(astPath) {
231
249
  if (!isComponentFile) return;
232
250
  const fnName = astPath.node.id?.name?.toLowerCase();
233
- if (fnName && REINVENTED_UTILS.has(fnName)) {
251
+ const isReinventedFn = Boolean(fnName && REINVENTED_UTILS.has(fnName));
252
+ if (isReinventedFn) {
234
253
  const line = astPath.node.loc?.start.line || 1;
235
254
  const meta = RULE_REGISTRY.AI_SLOP_UTILITY_REINVENTION;
236
255
  violations.push({
@@ -248,27 +267,35 @@ export const createAiSlopVisitors = ({ relativePath, violations }) => {
248
267
  },
249
268
 
250
269
  VariableDeclarator(astPath) {
251
- if (!isComponentFile) return;
252
270
  const idName = astPath.node.id?.name?.toLowerCase();
253
- if (!idName || !REINVENTED_UTILS.has(idName)) return;
254
-
271
+ const isReinventedName = Boolean(idName && REINVENTED_UTILS.has(idName));
255
272
  const initNode = astPath.node.init;
256
- const isFunction = t.isArrowFunctionExpression(initNode) || t.isFunctionExpression(initNode);
257
- if (!isFunction) return;
273
+ const isFunction = Boolean(initNode && (t.isArrowFunctionExpression(initNode) || t.isFunctionExpression(initNode)));
274
+
275
+ const gate = ruleTree({
276
+ declarator: {
277
+ notComponent: !isComponentFile,
278
+ notReinvented: !isReinventedName,
279
+ notFunction: !isFunction
280
+ }
281
+ }, { failFast: true });
282
+
283
+ const isReinvented = gate.ok;
284
+ if (!isReinvented) return;
258
285
 
259
286
  const line = astPath.node.loc?.start.line || 1;
260
- const meta = RULE_REGISTRY.AI_SLOP_UTILITY_REINVENTION;
261
- violations.push({
262
- filePath: relativePath,
263
- line,
264
- column: astPath.node.loc?.start.column || 1,
265
- hazard: `Inline utility reinvention "${astPath.node.id.name}" in component capsule`,
266
- rule: 'AI_SLOP_UTILITY_REINVENTION',
267
- severity: meta.severity,
268
- pillar: meta.pillar,
269
- directive: meta.directive,
270
- isAiSlop: true
271
- });
287
+ const meta = RULE_REGISTRY.AI_SLOP_UTILITY_REINVENTION;
288
+ violations.push({
289
+ filePath: relativePath,
290
+ line,
291
+ column: astPath.node.loc?.start.column || 1,
292
+ hazard: `Inline utility reinvention "${astPath.node.id.name}" in component capsule`,
293
+ rule: 'AI_SLOP_UTILITY_REINVENTION',
294
+ severity: meta.severity,
295
+ pillar: meta.pillar,
296
+ directive: meta.directive,
297
+ isAiSlop: true
298
+ });
272
299
  }
273
300
  };
274
301
  };