@event4u/agent-config 14.12.0 → 14.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (521) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +118 -155
  5. package/CONTRIBUTING.md +38 -0
  6. package/CREDITS.md +135 -0
  7. package/NOTICE +13 -0
  8. package/README.md +8 -6
  9. package/dist/agent-src/commands/analyze/inbox.md +145 -2
  10. package/dist/agent-src/commands/feature/dev.md +7 -2
  11. package/dist/agent-src/commands/ghostwriter/write.md +5 -1
  12. package/dist/agent-src/commands/implement-ticket.md +1 -1
  13. package/dist/agent-src/commands/mission/upgrade.md +1 -1
  14. package/dist/agent-src/commands/orchestrate.md +2 -2
  15. package/dist/agent-src/commands/post-as/me.md +5 -1
  16. package/dist/agent-src/commands/pr/merge.md +19 -6
  17. package/dist/agent-src/commands/roadmap/process-full.md +19 -5
  18. package/dist/agent-src/commands/tdd/red.md +12 -2
  19. package/dist/agent-src/commands/work.md +1 -1
  20. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +40 -0
  21. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +5 -2
  22. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +21 -0
  23. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +1 -0
  24. package/dist/agent-src/contexts/execution/subagent-response-contract.md +40 -0
  25. package/dist/agent-src/contexts/execution/subagent-steering.md +13 -1
  26. package/dist/agent-src/contexts/execution/terminal-states.md +96 -0
  27. package/dist/agent-src/rules/artifact-drafting-protocol.md +1 -1
  28. package/dist/agent-src/rules/broken-access-control.md +4 -0
  29. package/dist/agent-src/rules/code-comment-discipline.md +6 -0
  30. package/dist/agent-src/rules/code-provenance.md +4 -0
  31. package/dist/agent-src/rules/design-fidelity.md +1 -1
  32. package/dist/agent-src/rules/domain-safety-pii.md +4 -0
  33. package/dist/agent-src/rules/domain-safety-retention.md +4 -0
  34. package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
  35. package/dist/agent-src/rules/external-code-graph-interop.md +14 -12
  36. package/dist/agent-src/rules/improve-before-implement.md +6 -8
  37. package/dist/agent-src/rules/laravel-routing.md +1 -1
  38. package/dist/agent-src/rules/lethal-trifecta-guard.md +4 -0
  39. package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
  40. package/dist/agent-src/rules/security-sensitive-stop.md +2 -0
  41. package/dist/agent-src/rules/source-confidentiality.md +12 -34
  42. package/dist/agent-src/rules/symfony-routing.md +1 -1
  43. package/dist/agent-src/rules/token-efficiency.md +14 -0
  44. package/dist/agent-src/rules/tool-safety.md +4 -0
  45. package/dist/agent-src/rules/untrusted-input-defense.md +4 -0
  46. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +252 -8
  47. package/dist/agent-src/scripts/guarded_baseline.ts +343 -0
  48. package/dist/agent-src/scripts/roadmap_set_step.ts +253 -0
  49. package/dist/agent-src/scripts/stub_queue.ts +82 -0
  50. package/dist/agent-src/scripts/stubs_due.ts +516 -0
  51. package/dist/agent-src/scripts/ticket_bundles.ts +84 -0
  52. package/dist/agent-src/scripts/update_roadmap_progress.ts +16 -12
  53. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +17 -4
  54. package/dist/agent-src/skills/brand-audit/SKILL.md +33 -0
  55. package/dist/agent-src/skills/code-intelligence/SKILL.md +57 -0
  56. package/dist/agent-src/skills/database/SKILL.md +8 -0
  57. package/dist/agent-src/skills/dependency-upgrade/SKILL.md +27 -0
  58. package/dist/agent-src/skills/design-review/SKILL.md +1 -1
  59. package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
  60. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +17 -1
  61. package/dist/agent-src/skills/feature-planning/SKILL.md +9 -2
  62. package/dist/agent-src/skills/frontend-render-security/SKILL.md +44 -0
  63. package/dist/agent-src/skills/git-workflow/SKILL.md +1 -1
  64. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +38 -4
  65. package/dist/agent-src/skills/judge-artifact-completeness/rubrics/ticket-quality-score.json +2 -2
  66. package/dist/agent-src/skills/laravel/SKILL.md +35 -0
  67. package/dist/agent-src/skills/laravel-migration/SKILL.md +57 -3
  68. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +26 -0
  69. package/dist/agent-src/skills/playbook-authoring/SKILL.md +28 -1
  70. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
  71. package/dist/agent-src/skills/skill-writing/references/procedure.md +5 -5
  72. package/dist/agent-src/skills/sql-writing/SKILL.md +7 -1
  73. package/dist/agent-src/skills/standards-from-config/SKILL.md +27 -4
  74. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +11 -4
  75. package/dist/agent-src/skills/symfony-workflow/SKILL.md +35 -0
  76. package/dist/agent-src/skills/test-case-discovery/SKILL.md +85 -0
  77. package/dist/agent-src/skills/test-driven-development/SKILL.md +33 -9
  78. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  79. package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +37 -0
  80. package/dist/agent-src/skills/ui-component-architect/SKILL.md +45 -2
  81. package/dist/agent-src/skills/upstream-contribute/SKILL.md +38 -1
  82. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +9 -4
  83. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  84. package/dist/agent-src/templates/roadmaps.md +97 -3
  85. package/dist/agent-src/templates/scripts/check_memory.ts +258 -17
  86. package/dist/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  87. package/dist/agent-src/templates/scripts/memory_lookup.ts +86 -0
  88. package/dist/agent-src/templates/scripts/memory_signal.ts +44 -0
  89. package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  90. package/dist/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  91. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  92. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  93. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  94. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  95. package/dist/cli/commands/uiAudit.js +124 -5
  96. package/dist/cli/registry.js +2 -0
  97. package/dist/cli-delegate/{chunk-HYWSRNUX.js → chunk-2DK2VJWG.js} +3 -3
  98. package/dist/cli-delegate/{chunk-JCW7ZLHK.js → chunk-4FS4WRXP.js} +5 -0
  99. package/dist/cli-delegate/{chunk-OMIVVCG2.js → chunk-A4QJ6ENT.js} +24 -0
  100. package/dist/cli-delegate/{chunk-JJA2QEWA.js → chunk-AKJGUQNO.js} +466 -285
  101. package/dist/cli-delegate/{chunk-E46KPN6K.js → chunk-BTWUYDGN.js} +424 -363
  102. package/dist/cli-delegate/{chunk-K4FFODTS.js → chunk-ILMUPLGW.js} +1227 -316
  103. package/dist/cli-delegate/{chunk-FF7WAFMR.js → chunk-KPBWFOPZ.js} +5 -1
  104. package/dist/cli-delegate/cmd_adr_effective.js +102 -0
  105. package/dist/cli-delegate/cmd_conformance.js +80 -11
  106. package/dist/cli-delegate/cmd_doctor.js +3 -3
  107. package/dist/cli-delegate/cmd_export.js +3 -2
  108. package/dist/cli-delegate/cmd_fleet.js +2 -2
  109. package/dist/cli-delegate/cmd_handoff.js +1 -1
  110. package/dist/cli-delegate/cmd_preflight.js +2 -2
  111. package/dist/cli-delegate/cmd_prune.js +3 -2
  112. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  113. package/dist/cli-delegate/cmd_settings_migrate.js +3 -2
  114. package/dist/cli-delegate/cmd_settings_set.js +2 -2
  115. package/dist/cli-delegate/cmd_sync.js +3 -2
  116. package/dist/cli-delegate/cmd_uninstall.js +3 -2
  117. package/dist/cli-delegate/cmd_validate.js +3 -2
  118. package/dist/discovery/deprecation-report.md +1 -1
  119. package/dist/discovery/discovery-manifest.json +58 -58
  120. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  121. package/dist/discovery/discovery-manifest.summary.md +1 -1
  122. package/dist/discovery/dormancy-report.md +1 -1
  123. package/dist/discovery/orphan-report.md +1 -1
  124. package/dist/discovery/packs.json +2 -2
  125. package/dist/discovery/trust-report.md +1 -1
  126. package/dist/discovery/workspaces.json +2 -2
  127. package/dist/hooks/dispatch.js +2900 -1049
  128. package/dist/install/claudeRuleRewrite.js +254 -0
  129. package/dist/install/detect.js +29 -16
  130. package/dist/install/detect_php_shape.js +159 -0
  131. package/dist/install/install.mjs +634 -428
  132. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  133. package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
  134. package/dist/mcp/registry-manifest.json +3 -3
  135. package/dist/mcp/server.json +3 -3
  136. package/dist/mcp/server.mjs +4895 -2627
  137. package/dist/server/schemas/settings.js +3 -0
  138. package/dist/ui/assets/index-D0jaCRPM.js +29 -0
  139. package/dist/ui/index.html +1 -1
  140. package/docs/MIGRATION.md +1 -1
  141. package/docs/THIRD-PARTY-NOTICES.md +25 -0
  142. package/docs/contracts/provider-lifecycle.md +1 -1
  143. package/docs/contracts/settings-classes.md +10 -4
  144. package/docs/guidelines/agent-infra/5w2h-analysis.md +3 -3
  145. package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -0
  146. package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +58 -3
  147. package/docs/guidelines/agent-infra/ask-when-uncertain-demos.md +2 -2
  148. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +3 -3
  149. package/docs/guidelines/agent-infra/break-glass-usage.md +7 -7
  150. package/docs/guidelines/agent-infra/carve-out-predicates.md +3 -3
  151. package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
  152. package/docs/guidelines/agent-infra/critical-thinking.md +4 -4
  153. package/docs/guidelines/agent-infra/direct-answers-demos.md +2 -2
  154. package/docs/guidelines/agent-infra/domain-eval-anti-pattern.md +1 -1
  155. package/docs/guidelines/agent-infra/engineering-memory-data-format.md +3 -3
  156. package/docs/guidelines/agent-infra/existence-question-verdicts.md +80 -0
  157. package/docs/guidelines/agent-infra/first-principles.md +2 -2
  158. package/docs/guidelines/agent-infra/framework-neutrality-patterns.md +2 -2
  159. package/docs/guidelines/agent-infra/guarded-baseline.md +39 -0
  160. package/docs/guidelines/agent-infra/inversion-thinking.md +5 -5
  161. package/docs/guidelines/agent-infra/language-and-tone-examples.md +1 -1
  162. package/docs/guidelines/agent-infra/layered-settings.md +10 -10
  163. package/docs/guidelines/agent-infra/memory-access.md +1 -1
  164. package/docs/guidelines/agent-infra/mental-models.md +3 -3
  165. package/docs/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
  166. package/docs/guidelines/agent-infra/review-routing-data-format.md +7 -7
  167. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +13 -7
  168. package/docs/guidelines/agent-infra/role-contracts.md +2 -2
  169. package/docs/guidelines/agent-infra/role-mode-router.md +3 -3
  170. package/docs/guidelines/agent-infra/rule-type-governance.md +2 -2
  171. package/docs/guidelines/agent-infra/scqa-framework.md +5 -5
  172. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +6 -6
  173. package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +2 -2
  174. package/docs/guidelines/agent-infra/six-hats.md +3 -3
  175. package/docs/guidelines/agent-infra/skill-quality-checklist.md +6 -6
  176. package/docs/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
  177. package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
  178. package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
  179. package/docs/guidelines/augment-portability-patterns.md +6 -4
  180. package/docs/guidelines/code-clarity.md +18 -0
  181. package/docs/guidelines/component-oriented-and-oop-development.md +3 -2
  182. package/docs/guidelines/cross-role-handoff.md +2 -2
  183. package/docs/guidelines/design-fidelity-mechanics.md +1 -1
  184. package/docs/guidelines/docs/readme-size-and-splitting.md +3 -3
  185. package/docs/guidelines/php/database.md +90 -7
  186. package/docs/guidelines/prompt-templates.md +7 -7
  187. package/llms.txt +2 -2
  188. package/package.json +5 -2
  189. package/src/agent-src/scripts/archive_completed_roadmaps.ts +252 -8
  190. package/src/agent-src/scripts/guarded_baseline.ts +343 -0
  191. package/src/agent-src/scripts/roadmap_set_step.ts +253 -0
  192. package/src/agent-src/scripts/stub_queue.ts +82 -0
  193. package/src/agent-src/scripts/stubs_due.ts +516 -0
  194. package/src/agent-src/scripts/ticket_bundles.ts +84 -0
  195. package/src/agent-src/scripts/update_roadmap_progress.ts +16 -12
  196. package/src/agent-src/templates/scripts/check_memory.ts +258 -17
  197. package/src/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  198. package/src/agent-src/templates/scripts/memory_lookup.ts +86 -0
  199. package/src/agent-src/templates/scripts/memory_signal.ts +44 -0
  200. package/src/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  201. package/src/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  202. package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  203. package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  204. package/src/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  205. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  206. package/src/config/agent-settings.template.yml +32 -3
  207. package/src/config/assurance-capability-registry.json +21 -9
  208. package/src/config/canonical-terms.yml +119 -0
  209. package/src/config/capability-native-outcome-bars.json +81 -0
  210. package/src/config/ci-local-parity.yml +80 -0
  211. package/src/config/drafting-channels.yml +43 -0
  212. package/src/config/estate-count-budget.json +57 -36
  213. package/src/config/evaluator-budgets.json +14 -14
  214. package/src/config/gate-coverage.yml +729 -63
  215. package/src/config/gate-reachability-exemptions.json +21 -0
  216. package/src/config/gate-violation-baselines.json +42 -19
  217. package/src/config/harness-evolution-budget.json +25 -0
  218. package/src/config/lapsed-beta-baseline.json +96 -0
  219. package/src/config/memory-twin-verdicts.yml +129 -0
  220. package/src/config/metric-registry.yml +124 -0
  221. package/src/config/pack-size-budget.json +16 -15
  222. package/src/config/preamble-payload-budget.json +12 -4
  223. package/src/config/profiles/balanced.ini +27 -0
  224. package/src/config/profiles/full.ini +27 -0
  225. package/src/config/profiles/minimal.ini +27 -0
  226. package/src/config/publish-surface.json +9 -2
  227. package/src/config/routing-coverage-seed.json +16 -2
  228. package/src/config/rule-stub-ceilings.json +133 -112
  229. package/src/config/turnaround-budget.json +66 -0
  230. package/src/install/claudeRuleRewrite.ts +288 -0
  231. package/src/install/detect.ts +60 -17
  232. package/src/install/detect_php_shape.ts +191 -0
  233. package/src/scripts/_cli/cmd_doctor.ts +27 -112
  234. package/src/scripts/_dispatch.bash +23 -0
  235. package/src/scripts/_lib/activation_ladder.ts +255 -0
  236. package/src/scripts/_lib/activation_receipt_producer.ts +341 -0
  237. package/src/scripts/_lib/activation_states.ts +88 -0
  238. package/src/scripts/_lib/adherence_detectors.ts +143 -0
  239. package/src/scripts/_lib/adr_frontmatter.ts +26 -0
  240. package/src/scripts/_lib/arith_claims.ts +181 -0
  241. package/src/scripts/_lib/arm_ranking.ts +62 -0
  242. package/src/scripts/_lib/asset_delivery_ledger.ts +303 -0
  243. package/src/scripts/_lib/audit_field_provenance.ts +54 -0
  244. package/src/scripts/_lib/auto_dispatch.ts +32 -3
  245. package/src/scripts/_lib/bench_ab_size_claim.ts +98 -4
  246. package/src/scripts/_lib/benchmark_cache_fields.ts +158 -0
  247. package/src/scripts/_lib/candidate_pair_delta.ts +349 -0
  248. package/src/scripts/_lib/candidate_proposer.ts +402 -0
  249. package/src/scripts/_lib/candidate_record.ts +601 -0
  250. package/src/scripts/_lib/capture_rate.ts +319 -0
  251. package/src/scripts/_lib/carrier_status.ts +118 -0
  252. package/src/scripts/_lib/cascade_stage_enumeration.ts +92 -0
  253. package/src/scripts/_lib/collector_denominator.ts +771 -0
  254. package/src/scripts/_lib/collector_record.ts +340 -0
  255. package/src/scripts/_lib/collector_store.ts +664 -0
  256. package/src/scripts/_lib/collector_supervision.ts +827 -0
  257. package/src/scripts/_lib/concern_estate.ts +77 -0
  258. package/src/scripts/_lib/config_chain.ts +477 -0
  259. package/src/scripts/_lib/config_cost.ts +209 -0
  260. package/src/scripts/_lib/corpus_manifest.ts +726 -0
  261. package/src/scripts/_lib/council_settings_block.ts +6 -0
  262. package/src/scripts/_lib/curator_ops.ts +172 -0
  263. package/src/scripts/_lib/delivery_arm_experiment.ts +282 -0
  264. package/src/scripts/_lib/delivery_criticality.ts +126 -0
  265. package/src/scripts/_lib/doctor_runtime_checks.ts +70 -0
  266. package/src/scripts/_lib/empty_cycles.ts +88 -0
  267. package/src/scripts/_lib/estate_carrier_cases.ts +72 -0
  268. package/src/scripts/_lib/eval_publication.ts +354 -0
  269. package/src/scripts/_lib/evaluation_cascade.ts +452 -0
  270. package/src/scripts/_lib/evaluation_vector.ts +283 -0
  271. package/src/scripts/_lib/evaluator_promotion.ts +225 -0
  272. package/src/scripts/_lib/evidence_basis.ts +118 -0
  273. package/src/scripts/_lib/evolution_roi.ts +562 -0
  274. package/src/scripts/_lib/exec_evidence.ts +8 -0
  275. package/src/scripts/_lib/experience_card.ts +272 -0
  276. package/src/scripts/_lib/experience_report.ts +151 -0
  277. package/src/scripts/_lib/experiment_freeze.ts +112 -0
  278. package/src/scripts/_lib/generated_by.ts +66 -0
  279. package/src/scripts/_lib/harness_evolution_guards.ts +239 -0
  280. package/src/scripts/_lib/hook_effect_probe.ts +141 -0
  281. package/src/scripts/_lib/host_denominator.ts +687 -0
  282. package/src/scripts/_lib/host_projection_reach.ts +157 -0
  283. package/src/scripts/_lib/ignored_blocker.ts +148 -0
  284. package/src/scripts/_lib/install_reach_checks.ts +495 -0
  285. package/src/scripts/_lib/json_duplicate_keys.ts +150 -0
  286. package/src/scripts/_lib/judge_hygiene.ts +228 -0
  287. package/src/scripts/_lib/legacy_boundary_map.ts +228 -0
  288. package/src/scripts/_lib/lexical_shortlist.ts +215 -0
  289. package/src/scripts/_lib/llm_candidate_proposer.ts +461 -0
  290. package/src/scripts/_lib/llm_proposer_transport.ts +153 -0
  291. package/src/scripts/_lib/loop_guards.ts +299 -0
  292. package/src/scripts/_lib/loss_class.ts +129 -0
  293. package/src/scripts/_lib/machine_wake.ts +51 -0
  294. package/src/scripts/_lib/md_prose_lines.ts +177 -0
  295. package/src/scripts/_lib/minimality_tiebreak.ts +168 -0
  296. package/src/scripts/_lib/one_resolver_invariant.ts +449 -0
  297. package/src/scripts/_lib/orchestration_record.ts +253 -5
  298. package/src/scripts/_lib/outcome_envelope.ts +227 -0
  299. package/src/scripts/_lib/outcome_vocabularies.ts +125 -0
  300. package/src/scripts/_lib/paired_stats.ts +245 -0
  301. package/src/scripts/_lib/paired_verdict.ts +226 -0
  302. package/src/scripts/_lib/pathology_archive.ts +393 -0
  303. package/src/scripts/_lib/prefix_stable_surfaces.ts +123 -0
  304. package/src/scripts/_lib/privacy_class.ts +47 -0
  305. package/src/scripts/_lib/promotion_capability.ts +315 -0
  306. package/src/scripts/_lib/promotion_evidence.ts +414 -0
  307. package/src/scripts/_lib/promotion_review.ts +294 -0
  308. package/src/scripts/_lib/prompt_shape.ts +92 -0
  309. package/src/scripts/_lib/regression_neighbourhood.ts +259 -0
  310. package/src/scripts/_lib/release_highlights.ts +70 -1
  311. package/src/scripts/_lib/release_material.ts +125 -2
  312. package/src/scripts/_lib/repeated_failure.ts +105 -0
  313. package/src/scripts/_lib/repo_root.ts +111 -0
  314. package/src/scripts/_lib/review_skipped_record.ts +37 -0
  315. package/src/scripts/_lib/role_split.ts +338 -0
  316. package/src/scripts/_lib/routing_corpus.ts +307 -0
  317. package/src/scripts/_lib/routing_index_input.ts +104 -0
  318. package/src/scripts/_lib/rule_injection.ts +22 -1
  319. package/src/scripts/_lib/runtime_journal.ts +1499 -0
  320. package/src/scripts/_lib/runtime_wiring_checks.ts +430 -0
  321. package/src/scripts/_lib/semantic_noop.ts +167 -0
  322. package/src/scripts/_lib/skill_catalogue.ts +11 -1
  323. package/src/scripts/_lib/source_digest.ts +200 -0
  324. package/src/scripts/_lib/source_redact.ts +260 -0
  325. package/src/scripts/_lib/source_shape.ts +502 -0
  326. package/src/scripts/_lib/source_snapshot_dedup.ts +199 -0
  327. package/src/scripts/_lib/strip_comments.d.mts +8 -0
  328. package/src/scripts/_lib/strip_comments.mjs +65 -0
  329. package/src/scripts/_lib/test_red_state.ts +154 -0
  330. package/src/scripts/_lib/trigger_shift.ts +144 -0
  331. package/src/scripts/_lib/untrusted_content.ts +82 -7
  332. package/src/scripts/activation_receipt.ts +258 -0
  333. package/src/scripts/adoption_report.ts +1 -1
  334. package/src/scripts/adr/evidence_census.ts +1 -1
  335. package/src/scripts/adr/regenerate_index.ts +26 -2
  336. package/src/scripts/adr_cite_check.ts +164 -1
  337. package/src/scripts/ai_council/blind_review.ts +11 -1
  338. package/src/scripts/ai_council/clients.ts +4 -0
  339. package/src/scripts/ai_council/config.ts +3 -0
  340. package/src/scripts/ai_council/consensus.ts +28 -8
  341. package/src/scripts/ai_council/consensus_round.ts +226 -0
  342. package/src/scripts/ai_council/cross_exam.ts +128 -0
  343. package/src/scripts/ai_council/disagreement_signal.ts +338 -0
  344. package/src/scripts/ai_council/explain_route.ts +157 -0
  345. package/src/scripts/ai_council/information_gain.ts +293 -0
  346. package/src/scripts/ai_council/inline_findings.ts +340 -0
  347. package/src/scripts/ai_council/judge_position_bias.ts +197 -0
  348. package/src/scripts/ai_council/leakage_corpus.ts +385 -0
  349. package/src/scripts/ai_council/leakage_patterns.ts +453 -0
  350. package/src/scripts/ai_council/minority_retention.ts +171 -0
  351. package/src/scripts/ai_council/orchestrator.ts +16 -203
  352. package/src/scripts/ai_council/orchestrator_results.ts +23 -3
  353. package/src/scripts/ai_council/pricing.ts +106 -0
  354. package/src/scripts/ai_council/prompts.ts +74 -7
  355. package/src/scripts/ai_council/provider_leakage_bench.ts +327 -0
  356. package/src/scripts/ai_council/py_format.ts +14 -3
  357. package/src/scripts/ai_council/recouncil_guard.ts +293 -0
  358. package/src/scripts/ai_council/recouncil_savings.ts +299 -0
  359. package/src/scripts/ai_council/replay_route.ts +223 -0
  360. package/src/scripts/ai_council/response_record.ts +50 -0
  361. package/src/scripts/ai_council/reviewer_assignment.ts +279 -0
  362. package/src/scripts/ai_council/routing_training_row.ts +197 -0
  363. package/src/scripts/ai_council/synthesis_strategy.ts +159 -0
  364. package/src/scripts/ai_council/topology_bench_manifest.ts +860 -0
  365. package/src/scripts/ai_council/topology_vocabulary.ts +175 -0
  366. package/src/scripts/asset_delivery_ledger.ts +157 -0
  367. package/src/scripts/attest_artifact.ts +193 -0
  368. package/src/scripts/audit_auto_rules.ts +2 -1
  369. package/src/scripts/audit_command_surface.ts +1 -1
  370. package/src/scripts/audit_mcp_tools.ts +2 -2
  371. package/src/scripts/audit_skill_overlap_allowlist.json +6 -1
  372. package/src/scripts/audit_user_type_axis.ts +2 -1
  373. package/src/scripts/bench_ab_clone.ts +215 -10
  374. package/src/scripts/bench_ab_integrity.ts +119 -5
  375. package/src/scripts/bench_ab_v2_stats.ts +40 -213
  376. package/src/scripts/build_archive_index.ts +1 -1
  377. package/src/scripts/build_linear_digest.ts +1 -1
  378. package/src/scripts/build_proof.ts +11 -4
  379. package/src/scripts/build_rule_trigger_matrix.ts +1 -1
  380. package/src/scripts/build_source_digests.ts +157 -0
  381. package/src/scripts/cache_realization_report.ts +103 -0
  382. package/src/scripts/check_adr_frontmatter.ts +131 -10
  383. package/src/scripts/check_benchmark_report_fields.ts +207 -0
  384. package/src/scripts/check_beta_review_markers.ts +235 -6
  385. package/src/scripts/check_bundle_path_leakage.ts +34 -1
  386. package/src/scripts/check_claims.ts +576 -6
  387. package/src/scripts/check_composite_arming.ts +35 -0
  388. package/src/scripts/check_concern_admissions.ts +365 -0
  389. package/src/scripts/check_enforcement_coverage.ts +28 -0
  390. package/src/scripts/check_estate_count.ts +347 -25
  391. package/src/scripts/check_gate_reachability.ts +383 -0
  392. package/src/scripts/check_host_loadability.ts +104 -0
  393. package/src/scripts/check_loss_class_declared.ts +308 -0
  394. package/src/scripts/check_md_language.ts +15 -98
  395. package/src/scripts/check_memory_proposal.ts +18 -11
  396. package/src/scripts/check_no_currency_in_cost_surfaces.ts +225 -0
  397. package/src/scripts/check_no_external_sources.ts +281 -6
  398. package/src/scripts/check_pack_conformance_fixture.ts +11 -1
  399. package/src/scripts/check_pack_size.ts +59 -2
  400. package/src/scripts/check_preamble_payload_budget.ts +114 -3
  401. package/src/scripts/check_prefix_stable_mutation.ts +372 -0
  402. package/src/scripts/check_publish_surface.ts +10 -1
  403. package/src/scripts/check_references.ts +24 -1
  404. package/src/scripts/check_release_highlights.ts +96 -13
  405. package/src/scripts/check_roadmap_trackable.ts +17 -2
  406. package/src/scripts/check_rule_evidence_declaration.ts +316 -0
  407. package/src/scripts/check_rule_projection_integrity.ts +14 -4
  408. package/src/scripts/check_score_contract.ts +26 -3
  409. package/src/scripts/check_static_parity.ts +285 -0
  410. package/src/scripts/check_supervision_claim_atomicity.ts +498 -0
  411. package/src/scripts/check_suppression_hygiene.ts +15 -0
  412. package/src/scripts/ci_settle.ts +39 -2
  413. package/src/scripts/code_graph/build.ts +60 -3
  414. package/src/scripts/code_graph/extract.ts +44 -0
  415. package/src/scripts/code_graph/types.ts +24 -0
  416. package/src/scripts/collector_daemon.ts +714 -0
  417. package/src/scripts/config_cost_report.ts +302 -0
  418. package/src/scripts/consumer_matrix.ts +74 -1
  419. package/src/scripts/corpus_manifest.ts +235 -0
  420. package/src/scripts/cost/budget.mjs +10 -3
  421. package/src/scripts/cost/track.mjs +10 -3
  422. package/src/scripts/council_cli.ts +37 -54
  423. package/src/scripts/dispatch_r2_reviewer.ts +46 -5
  424. package/src/scripts/evolution_lab.ts +1153 -0
  425. package/src/scripts/external_sources_denylist.json +5 -18
  426. package/src/scripts/extract_audit_patterns.ts +21 -0
  427. package/src/scripts/fold_intake.ts +12 -1
  428. package/src/scripts/gen_discovery_baseline.ts +1 -1
  429. package/src/scripts/generate_capabilities_index.ts +12 -5
  430. package/src/scripts/generate_capability_matrix.ts +3 -3
  431. package/src/scripts/generate_command_flows.ts +2 -2
  432. package/src/scripts/generate_cookbook.ts +2 -2
  433. package/src/scripts/generate_index.ts +8 -1
  434. package/src/scripts/generate_knowledge_index.ts +2 -1
  435. package/src/scripts/generate_ownership_matrix.ts +2 -1
  436. package/src/scripts/generate_pack_manifests.ts +10 -2
  437. package/src/scripts/generate_role_experiences_catalog.ts +2 -2
  438. package/src/scripts/generate_settings_reference.ts +1 -1
  439. package/src/scripts/git_authorization_hook.ts +22 -1
  440. package/src/scripts/grade_target_readiness.ts +48 -5
  441. package/src/scripts/hook_effect_doctor.ts +261 -0
  442. package/src/scripts/hook_manifest.json +1 -1
  443. package/src/scripts/hook_manifest.yaml +125 -16
  444. package/src/scripts/hooks/block_speaking_inbox_dir.ts +271 -0
  445. package/src/scripts/hooks/block_unauthorized_git.ts +18 -0
  446. package/src/scripts/hooks/comment_discipline_hook.ts +146 -0
  447. package/src/scripts/hooks/concern_registry.ts +6 -0
  448. package/src/scripts/hooks/dispatch_hook.ts +32 -0
  449. package/src/scripts/hooks/journal_record_hook.ts +345 -0
  450. package/src/scripts/hooks/prepush_metadata_sources.sh +110 -0
  451. package/src/scripts/hooks/run_continuation_hook.ts +44 -9
  452. package/src/scripts/hooks/shims/install.sh +61 -0
  453. package/src/scripts/hooks/shims/php +101 -0
  454. package/src/scripts/hooks/suggestion_capture_hook.ts +10 -0
  455. package/src/scripts/hooks/turn_end_gate_hook.ts +9 -1
  456. package/src/scripts/hot_context_hook.ts +16 -0
  457. package/src/scripts/install-hooks.sh +20 -5
  458. package/src/scripts/install.ts +17 -35
  459. package/src/scripts/inventory_frontmatter.ts +2 -1
  460. package/src/scripts/language_mirror_hook.ts +14 -2
  461. package/src/scripts/lint_adr_sweep_routing.ts +12 -0
  462. package/src/scripts/lint_canonical_terms.ts +604 -0
  463. package/src/scripts/lint_carrier_integrity.ts +820 -0
  464. package/src/scripts/lint_code_comments.ts +643 -0
  465. package/src/scripts/lint_composition_review.ts +619 -0
  466. package/src/scripts/lint_consolidation_lineage.ts +666 -0
  467. package/src/scripts/lint_eval_specs.ts +593 -0
  468. package/src/scripts/lint_hook_manifest.ts +19 -0
  469. package/src/scripts/lint_host_portability.ts +373 -0
  470. package/src/scripts/lint_judge_prompt_expectation.ts +27 -1
  471. package/src/scripts/lint_memory_twin_parity.ts +335 -0
  472. package/src/scripts/lint_metric_consumers.ts +355 -0
  473. package/src/scripts/lint_plan_risk_register.ts +39 -19
  474. package/src/scripts/lint_promotion_paths.ts +779 -0
  475. package/src/scripts/lint_skill_descriptions.ts +18 -1
  476. package/src/scripts/lint_skill_frontmatter_safety.ts +58 -0
  477. package/src/scripts/lint_skill_link_reach.ts +252 -0
  478. package/src/scripts/lint_skill_trigger_corpus.ts +426 -23
  479. package/src/scripts/lint_ticket_buildable.ts +17 -1
  480. package/src/scripts/llm_propose.ts +256 -0
  481. package/src/scripts/mcp_server/consumer_tool_catalog.json +1 -1
  482. package/src/scripts/mcp_server/tool_catalog_source.ts +1 -1
  483. package/src/scripts/measure_delivery_sets.ts +361 -0
  484. package/src/scripts/measure_docs_dead_links.ts +348 -0
  485. package/src/scripts/measure_host_capture.ts +461 -0
  486. package/src/scripts/measure_routing_signal.ts +307 -0
  487. package/src/scripts/migration_status.ts +3 -3
  488. package/src/scripts/model_rule_injection.ts +76 -0
  489. package/src/scripts/orchestration_record.ts +14 -0
  490. package/src/scripts/preamble_byte_census.ts +139 -10
  491. package/src/scripts/prepack-check.mjs +4 -1
  492. package/src/scripts/probe_council_retention.ts +495 -0
  493. package/src/scripts/probe_turnaround.ts +384 -0
  494. package/src/scripts/probe_unblocked_ask.ts +279 -0
  495. package/src/scripts/release.ts +21 -37
  496. package/src/scripts/release_drill.ts +143 -0
  497. package/src/scripts/release_env.ts +35 -0
  498. package/src/scripts/release_publication.ts +84 -0
  499. package/src/scripts/render_benchmark_md.ts +1 -1
  500. package/src/scripts/rule_activation_census.ts +70 -9
  501. package/src/scripts/rule_backlinks.ts +1 -1
  502. package/src/scripts/run_lifecycle_suite.ts +208 -0
  503. package/src/scripts/run_skill_evals.ts +40 -0
  504. package/src/scripts/schemas/delivery-manifest.schema.json +43 -0
  505. package/src/scripts/schemas/drafting-channels.schema.json +43 -0
  506. package/src/scripts/schemas/evals.schema.json +24 -1
  507. package/src/scripts/schemas/rule.schema.json +52 -1
  508. package/src/scripts/schemas/skill.schema.json +17 -2
  509. package/src/scripts/skill_overlap.ts +7 -1
  510. package/src/scripts/skill_tools/run_block_d_eval.ts +8 -1
  511. package/src/scripts/skill_tools/score_skill_relevance.ts +84 -3
  512. package/src/scripts/skill_tools/suggest_skill_for_task.ts +8 -1
  513. package/src/scripts/skill_usage_report.ts +2 -1
  514. package/src/scripts/stubs_due.ts +211 -0
  515. package/src/scripts/sweep_source_surfaces.ts +678 -0
  516. package/src/scripts/sync_pr_branch.ts +3 -3
  517. package/src/scripts/trigger_eval_grandfather.json +202 -222
  518. package/src/scripts/utilization_report.ts +22 -2
  519. package/src/server/schemas/settings.ts +5 -0
  520. package/src/templates/marketing-copy.yml +1 -1
  521. package/dist/ui/assets/index-Cxgy63kz.js +0 -26
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Count hook concerns in `src/scripts/hook_manifest.yaml`.
3
+ *
4
+ * ONE parser, used for both the HEAD reading and the base-ref floor — the same
5
+ * discipline `_lib/skill_estate.ts` follows for skills, and for the same
6
+ * reason: two readings of one corpus is how a ratchet comes to compare a
7
+ * number against a differently-derived number and calls the difference growth.
8
+ *
9
+ * ## Why this is not the roadmap's grep
10
+ *
11
+ * `road-to-concern-admission-ratchet` reproduces its series with
12
+ * `grep -cE '^ [a-z][a-z0-9_-]*:$'` over the whole manifest. That command is a
13
+ * PROXY and it over-counts: the manifest carries three further top-level maps —
14
+ * `roles:`, `platforms:` and `native_event_aliases:` — whose members sit at the
15
+ * same two-space indent and match the same pattern.
16
+ *
17
+ * Measured across the roadmap's own six pins, the over-count is **exactly 16 at
18
+ * every one of them**:
19
+ *
20
+ * | pin | grep | concerns |
21
+ * |---|---|---|
22
+ * | `7c6a71d` | 63 | 47 |
23
+ * | `1dba34c8` | 65 | 49 |
24
+ * | `40791536` | 65 | 49 |
25
+ * | `0f7c26ee9` | 68 | 52 |
26
+ * | `2bcefb8b1` | 69 | 53 |
27
+ * | `6e37584a1` | 71 | 55 |
28
+ *
29
+ * Two consequences, and they point in opposite directions, so both are stated.
30
+ * **The roadmap's FINDING survives untouched**: the delta is constant, so the
31
+ * series climbs by +8 either way and the concern axis is growing exactly as it
32
+ * says. **Its ABSOLUTE FIGURES do not**: the axis stands at 55, not 71. A
33
+ * ratchet seeded with 71 would have a floor its own parser could never
34
+ * reproduce, which is a gate that fails on its first honest run.
35
+ *
36
+ * This module is therefore scoped to the `concerns:` block and stops at the
37
+ * next top-level key.
38
+ */
39
+
40
+ /** A top-level YAML key at column 0 — where the `concerns:` block ends. */
41
+ const TOP_LEVEL_KEY = /^[A-Za-z_][A-Za-z0-9_-]*:/;
42
+ /** The `concerns:` map itself. */
43
+ const CONCERNS_KEY = /^concerns:\s*$/;
44
+ /**
45
+ * One concern id: two-space indent, a bare key, nothing after the colon.
46
+ *
47
+ * A trailing value (`foo: bar`) is not a concern — concerns are maps. Matching
48
+ * the bare form is what keeps a scalar setting inside the block from counting.
49
+ */
50
+ const CONCERN_ID = /^ {2}([a-z][a-z0-9_-]*):\s*$/;
51
+
52
+ /** The ids, in file order. Exported so a caller can report WHICH, not only how many. */
53
+ export function concernIds(manifestText: string): string[] {
54
+ const out: string[] = [];
55
+ let inBlock = false;
56
+ for (const line of manifestText.split('\n')) {
57
+ if (CONCERNS_KEY.test(line)) {
58
+ inBlock = true;
59
+ continue;
60
+ }
61
+ if (!inBlock) continue;
62
+ // Any other column-0 key closes the block. Checked BEFORE the id match
63
+ // so a top-level key can never be read as a concern.
64
+ if (TOP_LEVEL_KEY.test(line)) break;
65
+ const m = CONCERN_ID.exec(line);
66
+ if (m !== null) out.push(m[1] as string);
67
+ }
68
+ return out;
69
+ }
70
+
71
+ /** How many concerns the manifest declares. */
72
+ export function countConcerns(manifestText: string): number {
73
+ return concernIds(manifestText).length;
74
+ }
75
+
76
+ /** Repo-relative POSIX path of the manifest, for both the HEAD read and the `git show`. */
77
+ export const CONCERN_MANIFEST_POSIX = 'src/scripts/hook_manifest.yaml';
@@ -0,0 +1,477 @@
1
+ /**
2
+ * Resolve a configuration file's `extends` / `includes` chain, and answer which
3
+ * config governs a given path, before anything digests either one.
4
+ *
5
+ * WHY THIS EXISTS
6
+ * ---------------
7
+ * `standards-from-config` derives a project's enforced standards from its real
8
+ * tooling config. Read literally — one file, one parse — that produces a null on
9
+ * a repository whose root config is a single directive pointing somewhere else.
10
+ * A fourteen-line linter config whose only load-bearing line is an `extends` into
11
+ * a package in the same workspace is not a project without standards; it is a
12
+ * project whose standards are one hop away. Reporting "no enforced standard
13
+ * found" there is a false negative that reads exactly like a true one.
14
+ *
15
+ * `extends` is a specified directive in TypeScript, ESLint, Biome and Stylelint;
16
+ * `includes` plays the same role in PHPStan's NEON. `workspace:`-linked packages
17
+ * are a documented protocol in npm, yarn, pnpm and bun. Those are published
18
+ * mechanisms, which is why chain-following is a general capability rather than
19
+ * one repository's convention.
20
+ *
21
+ * AN EXTERNAL HOP IS LABELLED, NEVER MERGED
22
+ * -----------------------------------------
23
+ * A chain can leave the repository — into `node_modules`, into a vendor
24
+ * directory, or above the repository root entirely. Presenting a third-party
25
+ * preset as *the project's own* standard is worse than reporting nothing: the
26
+ * reader cannot tell which rules the project chose. So every hop carries its
27
+ * origin, and only `project` and `workspace-package` hops appear in
28
+ * `digestible`. An `external` hop is reported, with its path, and excluded from
29
+ * the digest.
30
+ *
31
+ * AN UNRESOLVABLE HOP IS A NAMED GAP, NEVER AN ABSENCE
32
+ * ---------------------------------------------------
33
+ * Three failures are indistinguishable to a caller that only sees "nothing came
34
+ * back": the file is missing, the file is there but unparsable, and the
35
+ * directive is expressed in a language this reader does not evaluate (a Rector
36
+ * config building its set list from PHP expressions). All three are recorded as
37
+ * a hop with `origin: 'unresolved'` and a `reason`, and any one of them sets
38
+ * `complete: false`. A partial digest that says which hop it could not follow is
39
+ * usable; a null is not, and a null that looks like "no standards" is a lie.
40
+ * This is the same three-outcome posture the install diagnostic takes: present,
41
+ * dangling, and unresolvable-for-a-stated-reason — never a silent absence.
42
+ *
43
+ * WHY A LOCAL JSONC READER
44
+ * ------------------------
45
+ * `linked_projects.ts` carries a private tolerant JSON reader that returns
46
+ * `null` on both "absent" and "malformed". That collapse is correct for its
47
+ * input domain and wrong here for the reason above: this module has to attribute
48
+ * a parse failure to itself rather than report it as a missing config. So
49
+ * `readConfigObject` returns a discriminated result instead of a nullable one.
50
+ */
51
+ import * as fs from 'node:fs';
52
+ import * as path from 'node:path';
53
+ import * as yaml from 'yaml';
54
+
55
+ /** Where a hop's file lives relative to the repository — the digest gate. */
56
+ export type HopOrigin = 'project' | 'workspace-package' | 'external' | 'unresolved';
57
+
58
+ export interface ConfigHop {
59
+ /** The directive text as written. `''` for the chain's starting file. */
60
+ specifier: string;
61
+ /** Repository-relative path when resolved, `null` when not. */
62
+ path: string | null;
63
+ origin: HopOrigin;
64
+ /**
65
+ * Present on every non-`project` hop. On `unresolved` it names WHY, which is
66
+ * the whole point — an unnamed gap is an absence wearing a label.
67
+ */
68
+ reason?: string;
69
+ }
70
+
71
+ export interface ChainResolution {
72
+ /** Every hop, in resolution order, starting with the file asked about. */
73
+ hops: ConfigHop[];
74
+ /** `false` when any hop is `unresolved`. A partial digest, never a null. */
75
+ complete: boolean;
76
+ /** The hops a digest may read: `project` + `workspace-package` only. */
77
+ digestible: ConfigHop[];
78
+ /** Hops outside the repository. Reported, never merged into the digest. */
79
+ externals: ConfigHop[];
80
+ /** The named gaps. Non-empty exactly when `complete` is `false`. */
81
+ unresolved: ConfigHop[];
82
+ }
83
+
84
+ export interface WorkspacePackage {
85
+ /** Repository-relative directory. */
86
+ dir: string;
87
+ /** The manifest's `name` — the key a bare specifier matches on. */
88
+ name: string;
89
+ }
90
+
91
+ /** Bounds the walk. A chain this long is a finding, not a configuration. */
92
+ const MAX_HOPS = 16;
93
+
94
+ /** Directory names a chain crosses only to leave the repository. */
95
+ const EXTERNAL_DIRS = new Set(['node_modules', 'vendor']);
96
+
97
+ /** Extensions tried when a specifier names no file extension of its own. */
98
+ const EXT_CANDIDATES = ['', '.json', '.jsonc', '.neon', '.yaml', '.yml'];
99
+
100
+ /** Filenames tried when a specifier resolves to a directory. */
101
+ const DIR_CANDIDATES = [
102
+ 'tsconfig.json',
103
+ 'biome.json',
104
+ 'eslint.config.js',
105
+ '.eslintrc.json',
106
+ '.stylelintrc.json',
107
+ 'phpstan.neon',
108
+ 'index.json',
109
+ ];
110
+
111
+ type ReadResult =
112
+ | { kind: 'ok'; value: Record<string, unknown> }
113
+ | { kind: 'absent' }
114
+ | { kind: 'unparsable'; reason: string }
115
+ | { kind: 'opaque'; reason: string };
116
+
117
+ /**
118
+ * Read one config file into an object, keeping the four outcomes distinct.
119
+ *
120
+ * `opaque` is the case a null would hide: a `.php` config states its directives
121
+ * as executable expressions, so a static reader cannot follow them and must say
122
+ * so rather than report the file as carrying none.
123
+ */
124
+ export function readConfigObject(absPath: string): ReadResult {
125
+ if (!fs.existsSync(absPath)) return { kind: 'absent' };
126
+ const ext = path.extname(absPath).toLowerCase();
127
+ if (ext === '.php' || ext === '.js' || ext === '.cjs' || ext === '.mjs' || ext === '.ts') {
128
+ return {
129
+ kind: 'opaque',
130
+ reason: `${ext} config: directives are expressed as executable code and are not statically resolvable`,
131
+ };
132
+ }
133
+ let text: string;
134
+ try {
135
+ text = fs.readFileSync(absPath, 'utf-8');
136
+ } catch (err) {
137
+ return { kind: 'unparsable', reason: `unreadable: ${(err as Error).message}` };
138
+ }
139
+ if (ext === '.neon' || ext === '.yaml' || ext === '.yml') {
140
+ // NEON's `includes:` list and YAML's `extends:` are both a top-level key
141
+ // holding a scalar or a sequence, which YAML parses for both formats.
142
+ try {
143
+ const parsed = yaml.parse(text) as unknown;
144
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
145
+ return { kind: 'unparsable', reason: 'top level is not a mapping' };
146
+ }
147
+ return { kind: 'ok', value: parsed as Record<string, unknown> };
148
+ } catch (err) {
149
+ return { kind: 'unparsable', reason: `parse error: ${(err as Error).message}` };
150
+ }
151
+ }
152
+ const strict = tryJson(text);
153
+ if (strict) return { kind: 'ok', value: strict };
154
+ // tsconfig.json and its family carry `//` comments and trailing commas by
155
+ // convention, so a strict parse failure is not yet a finding.
156
+ const tolerant = tryJson(text.replace(/^\s*\/\/.*$/gm, '').replace(/,(\s*[}\]])/g, '$1'));
157
+ if (tolerant) return { kind: 'ok', value: tolerant };
158
+ return { kind: 'unparsable', reason: 'not valid JSON, even allowing comments and trailing commas' };
159
+ }
160
+
161
+ function tryJson(text: string): Record<string, unknown> | null {
162
+ try {
163
+ const parsed = JSON.parse(text) as unknown;
164
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) return null;
165
+ return parsed as Record<string, unknown>;
166
+ } catch {
167
+ return null;
168
+ }
169
+ }
170
+
171
+ /** Pull the chain directives out of a parsed config, in declaration order. */
172
+ function directives(config: Record<string, unknown>): string[] {
173
+ const out: string[] = [];
174
+ for (const key of ['extends', 'includes']) {
175
+ const raw = config[key];
176
+ if (typeof raw === 'string') out.push(raw);
177
+ else if (Array.isArray(raw)) {
178
+ for (const item of raw) if (typeof item === 'string') out.push(item);
179
+ }
180
+ }
181
+ return out;
182
+ }
183
+
184
+ /**
185
+ * Enumerate the repository's workspace packages from its declarative source.
186
+ *
187
+ * `pnpm-workspace.yaml` wins when present because it is the more specific
188
+ * declaration; otherwise `package.json#workspaces`. Conventional directories are
189
+ * never used as a substitute — a declaration and a convention can disagree, and
190
+ * the declaration is what the package manager obeys.
191
+ */
192
+ export function listWorkspacePackages(repoRoot: string): WorkspacePackage[] {
193
+ const patterns = workspacePatterns(repoRoot);
194
+ const seen = new Set<string>();
195
+ const out: WorkspacePackage[] = [];
196
+ for (const pattern of patterns) {
197
+ for (const dir of expandPattern(repoRoot, pattern)) {
198
+ if (seen.has(dir)) continue;
199
+ seen.add(dir);
200
+ const manifest = readConfigObject(path.join(repoRoot, dir, 'package.json'));
201
+ if (manifest.kind !== 'ok') continue;
202
+ const name = manifest.value.name;
203
+ if (typeof name === 'string' && name.length > 0) out.push({ dir, name });
204
+ }
205
+ }
206
+ return out;
207
+ }
208
+
209
+ function workspacePatterns(repoRoot: string): string[] {
210
+ const pnpm = path.join(repoRoot, 'pnpm-workspace.yaml');
211
+ if (fs.existsSync(pnpm)) {
212
+ const parsed = readConfigObject(pnpm);
213
+ if (parsed.kind === 'ok' && Array.isArray(parsed.value.packages)) {
214
+ return (parsed.value.packages as unknown[]).filter((p): p is string => typeof p === 'string');
215
+ }
216
+ }
217
+ const rootManifest = readConfigObject(path.join(repoRoot, 'package.json'));
218
+ if (rootManifest.kind === 'ok') {
219
+ const ws = rootManifest.value.workspaces;
220
+ if (Array.isArray(ws)) return ws.filter((p): p is string => typeof p === 'string');
221
+ if (ws && typeof ws === 'object' && Array.isArray((ws as Record<string, unknown>).packages)) {
222
+ return ((ws as Record<string, unknown>).packages as unknown[]).filter(
223
+ (p): p is string => typeof p === 'string',
224
+ );
225
+ }
226
+ }
227
+ return [];
228
+ }
229
+
230
+ /**
231
+ * Expand one workspace glob to the directories that actually carry a manifest.
232
+ *
233
+ * Only `*` and `**` as whole path segments are supported, which is what every
234
+ * workspace declaration in the wild uses. A pattern this cannot express returns
235
+ * nothing rather than a guess — a wrong workspace list would misclassify an
236
+ * external hop as the project's own, which is the one error this module exists
237
+ * to prevent.
238
+ */
239
+ function expandPattern(repoRoot: string, pattern: string): string[] {
240
+ const segments = pattern.replace(/^\.\//, '').split('/').filter((s) => s.length > 0);
241
+ let frontier: string[] = [''];
242
+ for (const segment of segments) {
243
+ const next: string[] = [];
244
+ for (const base of frontier) {
245
+ if (segment === '*') next.push(...childDirs(repoRoot, base));
246
+ else if (segment === '**') next.push(base, ...recursiveDirs(repoRoot, base, 4));
247
+ else {
248
+ const candidate = base ? `${base}/${segment}` : segment;
249
+ if (isDir(path.join(repoRoot, candidate))) next.push(candidate);
250
+ }
251
+ }
252
+ frontier = next;
253
+ }
254
+ return frontier.filter((d) => d.length > 0);
255
+ }
256
+
257
+ function childDirs(repoRoot: string, base: string): string[] {
258
+ const abs = path.join(repoRoot, base);
259
+ if (!isDir(abs)) return [];
260
+ return fs
261
+ .readdirSync(abs, { withFileTypes: true })
262
+ .filter((e) => e.isDirectory() && !e.name.startsWith('.') && !EXTERNAL_DIRS.has(e.name))
263
+ .map((e) => (base ? `${base}/${e.name}` : e.name));
264
+ }
265
+
266
+ function recursiveDirs(repoRoot: string, base: string, depth: number): string[] {
267
+ if (depth <= 0) return [];
268
+ const out: string[] = [];
269
+ for (const child of childDirs(repoRoot, base)) {
270
+ out.push(child, ...recursiveDirs(repoRoot, child, depth - 1));
271
+ }
272
+ return out;
273
+ }
274
+
275
+ function isDir(abs: string): boolean {
276
+ try {
277
+ return fs.statSync(abs).isDirectory();
278
+ } catch {
279
+ return false;
280
+ }
281
+ }
282
+
283
+ /** Classify a resolved absolute path by where it sits relative to the repo. */
284
+ function classify(repoRoot: string, abs: string): { origin: HopOrigin; reason?: string } {
285
+ const rel = path.relative(repoRoot, abs);
286
+ if (rel.startsWith('..') || path.isAbsolute(rel)) {
287
+ return { origin: 'external', reason: 'resolves above the repository root' };
288
+ }
289
+ const crossed = rel.split(path.sep).find((seg) => EXTERNAL_DIRS.has(seg));
290
+ if (crossed) return { origin: 'external', reason: `resolves inside \`${crossed}/\`` };
291
+ return { origin: 'project' };
292
+ }
293
+
294
+ /** Try a specifier as a file, then with each extension, then as a directory. */
295
+ function firstExistingFile(base: string): string | null {
296
+ for (const ext of EXT_CANDIDATES) {
297
+ const candidate = base + ext;
298
+ if (fs.existsSync(candidate) && !isDir(candidate)) return candidate;
299
+ }
300
+ if (isDir(base)) {
301
+ for (const name of DIR_CANDIDATES) {
302
+ const candidate = path.join(base, name);
303
+ if (fs.existsSync(candidate)) return candidate;
304
+ }
305
+ }
306
+ return null;
307
+ }
308
+
309
+ function resolveSpecifier(
310
+ repoRoot: string,
311
+ fromDir: string,
312
+ specifier: string,
313
+ workspaces: WorkspacePackage[],
314
+ ): ConfigHop {
315
+ const hop = (patch: Partial<ConfigHop>): ConfigHop => ({ specifier, path: null, origin: 'unresolved', ...patch });
316
+
317
+ if (specifier.startsWith('.') || path.isAbsolute(specifier)) {
318
+ const base = path.isAbsolute(specifier) ? specifier : path.resolve(fromDir, specifier);
319
+ const found = firstExistingFile(base);
320
+ if (!found) return hop({ reason: 'relative target does not exist' });
321
+ const { origin, reason } = classify(repoRoot, found);
322
+ return hop({ path: path.relative(repoRoot, found), origin, ...(reason === undefined ? {} : { reason }) });
323
+ }
324
+
325
+ // A bare specifier is a workspace package before it is a dependency: a
326
+ // `workspace:`-linked config package is INSIDE the repository, so its rules
327
+ // are the project's own and belong in the digest.
328
+ const match = workspaces
329
+ .filter((ws) => specifier === ws.name || specifier.startsWith(`${ws.name}/`))
330
+ .sort((a, b) => b.name.length - a.name.length)[0];
331
+ if (match) {
332
+ const subpath = specifier.slice(match.name.length).replace(/^\//, '');
333
+ const wsDir = path.join(repoRoot, match.dir);
334
+ const found = subpath ? firstExistingFile(path.join(wsDir, subpath)) : workspaceEntry(wsDir);
335
+ if (!found) {
336
+ return hop({ reason: `workspace package \`${match.name}\` has no config at \`${subpath || 'its entry point'}\`` });
337
+ }
338
+ return hop({ path: path.relative(repoRoot, found), origin: 'workspace-package', reason: `workspace package \`${match.name}\`` });
339
+ }
340
+
341
+ const installed = firstExistingFile(path.join(repoRoot, 'node_modules', specifier));
342
+ if (installed) {
343
+ return hop({ path: path.relative(repoRoot, installed), origin: 'external', reason: 'resolves inside `node_modules/`' });
344
+ }
345
+ return hop({ reason: 'bare specifier matches no workspace package and is not installed' });
346
+ }
347
+
348
+ /** A config package's entry: its manifest `main`, else a conventional filename. */
349
+ function workspaceEntry(wsDir: string): string | null {
350
+ const manifest = readConfigObject(path.join(wsDir, 'package.json'));
351
+ if (manifest.kind === 'ok' && typeof manifest.value.main === 'string') {
352
+ const viaMain = firstExistingFile(path.join(wsDir, manifest.value.main));
353
+ if (viaMain) return viaMain;
354
+ }
355
+ return firstExistingFile(wsDir);
356
+ }
357
+
358
+ /**
359
+ * Follow `extends` / `includes` from one config file and report the whole chain.
360
+ *
361
+ * The returned `hops` always contain at least the starting file, so a caller
362
+ * that finds `digestible` empty can still say WHICH file it read and why nothing
363
+ * came of it. `startPath` is repository-relative.
364
+ */
365
+ export function resolveConfigChain(repoRoot: string, startPath: string): ChainResolution {
366
+ const workspaces = listWorkspacePackages(repoRoot);
367
+ const hops: ConfigHop[] = [];
368
+ const seen = new Set<string>();
369
+ const queue: ConfigHop[] = [];
370
+
371
+ const startAbs = path.resolve(repoRoot, startPath);
372
+ if (!fs.existsSync(startAbs)) {
373
+ hops.push({ specifier: '', path: startPath, origin: 'unresolved', reason: 'starting config does not exist' });
374
+ } else {
375
+ const { origin, reason } = classify(repoRoot, startAbs);
376
+ queue.push({
377
+ specifier: '',
378
+ path: path.relative(repoRoot, startAbs),
379
+ origin,
380
+ ...(reason === undefined ? {} : { reason }),
381
+ });
382
+ }
383
+
384
+ while (queue.length > 0) {
385
+ const hop = queue.shift() as ConfigHop;
386
+ if (hops.length >= MAX_HOPS) {
387
+ hops.push({ ...hop, origin: 'unresolved', reason: `chain exceeds ${MAX_HOPS} hops` });
388
+ break;
389
+ }
390
+ const abs = path.resolve(repoRoot, hop.path as string); // non-null: unresolved hops are never queued
391
+ if (seen.has(abs)) {
392
+ hops.push({ ...hop, origin: 'unresolved', reason: 'cycle: this file is already in the chain' });
393
+ continue;
394
+ }
395
+ seen.add(abs);
396
+
397
+ const read = readConfigObject(abs);
398
+ if (read.kind !== 'ok') {
399
+ const reason = read.kind === 'absent' ? 'file disappeared between resolution and read' : read.reason;
400
+ hops.push({ ...hop, origin: 'unresolved', reason });
401
+ continue;
402
+ }
403
+ hops.push(hop);
404
+ // An external hop's own directives are not followed. Its rules are
405
+ // already excluded from the digest, so walking deeper would only grow
406
+ // the report with paths the project does not own.
407
+ if (hop.origin === 'external') continue;
408
+ for (const specifier of directives(read.value)) {
409
+ const next = resolveSpecifier(repoRoot, path.dirname(abs), specifier, workspaces);
410
+ // A hop the specifier resolver could not place has no path to read,
411
+ // so it is RECORDED and not queued. Queueing it walked into
412
+ // `path.resolve(root, null)` and threw — which turned a partial
413
+ // digest, the whole point of this module, into a crash on exactly
414
+ // the input it exists to handle gracefully.
415
+ if (next.path === null) {
416
+ hops.push(next);
417
+ continue;
418
+ }
419
+ queue.push(next);
420
+ }
421
+ }
422
+
423
+ const unresolved = hops.filter((h) => h.origin === 'unresolved');
424
+ return {
425
+ hops,
426
+ complete: unresolved.length === 0,
427
+ digestible: hops.filter((h) => h.origin === 'project' || h.origin === 'workspace-package'),
428
+ externals: hops.filter((h) => h.origin === 'external'),
429
+ unresolved,
430
+ };
431
+ }
432
+
433
+ export interface NearestConfigResult {
434
+ /** The config that governs `editPath`, repository-relative. `null` = none. */
435
+ governing: string | null;
436
+ /** Every candidate found walking up, nearest first. The precedence order. */
437
+ candidates: string[];
438
+ /** Which rule decided: nearest-wins, root-only, or none-found. */
439
+ basis: 'nearest-wins' | 'root-only' | 'none-found';
440
+ }
441
+
442
+ /**
443
+ * Answer which config governs an edit, given the config filenames to look for.
444
+ *
445
+ * Precedence is **nearest-first**: the file in the edited path's own directory
446
+ * governs, then its parent, up to the repository root. This is not a preference
447
+ * — it is what the tools do. A per-package `tsconfig.json`, `.eslintrc`, `.env`
448
+ * or deployment manifest is the one its own package's build reads, and a root
449
+ * file it does not extend has no effect on it. Reading the root config for an
450
+ * edit inside a package that carries its own is a wrong answer, not a coarse one.
451
+ *
452
+ * `candidates` is the full walk rather than just the winner, because a reader
453
+ * needs to see that a root config was found and outranked before they trust the
454
+ * per-package answer.
455
+ */
456
+ export function nearestConfig(repoRoot: string, editPath: string, filenames: string[]): NearestConfigResult {
457
+ const candidates: string[] = [];
458
+ const startAbs = path.resolve(repoRoot, editPath);
459
+ let dir = isDir(startAbs) ? startAbs : path.dirname(startAbs);
460
+ const rootAbs = path.resolve(repoRoot);
461
+
462
+ for (;;) {
463
+ for (const name of filenames) {
464
+ const candidate = path.join(dir, name);
465
+ if (fs.existsSync(candidate) && !isDir(candidate)) candidates.push(path.relative(rootAbs, candidate));
466
+ }
467
+ if (dir === rootAbs) break;
468
+ const parent = path.dirname(dir);
469
+ if (parent === dir || !parent.startsWith(rootAbs)) break;
470
+ dir = parent;
471
+ }
472
+
473
+ if (candidates.length === 0) return { governing: null, candidates, basis: 'none-found' };
474
+ const governing = candidates[0] as string;
475
+ const basis = candidates.length === 1 && !governing.includes('/') ? 'root-only' : 'nearest-wins';
476
+ return { governing, candidates, basis };
477
+ }