@event4u/agent-config 9.9.0 → 9.11.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 (479) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +212 -194
  3. package/README.md +13 -16
  4. package/agents/templates/.ai-council.yml.example +481 -0
  5. package/agents/templates/.ai-video.xml.example +247 -0
  6. package/dist/agent-src/commands/agent-status.md +12 -11
  7. package/dist/agent-src/commands/agents/user/accept.md +115 -30
  8. package/dist/agent-src/commands/agents/user/delete.md +147 -0
  9. package/dist/agent-src/commands/agents/user/review.md +65 -28
  10. package/dist/agent-src/commands/agents/user/show.md +82 -29
  11. package/dist/agent-src/commands/agents/user/update.md +2 -2
  12. package/dist/agent-src/commands/agents/user.md +16 -3
  13. package/dist/agent-src/commands/check-current-md.md +0 -10
  14. package/dist/agent-src/commands/condense.md +28 -97
  15. package/dist/agent-src/commands/cost/report.md +7 -0
  16. package/dist/agent-src/commands/fix/portability.md +0 -8
  17. package/dist/agent-src/commands/fix/refs.md +0 -8
  18. package/dist/agent-src/commands/humanize.md +2 -2
  19. package/dist/agent-src/commands/jira-ticket.md +1 -1
  20. package/dist/agent-src/commands/memory/load.md +11 -0
  21. package/dist/agent-src/commands/optimize/skills.md +1 -1
  22. package/dist/agent-src/commands/pr/create.md +4 -4
  23. package/dist/agent-src/commands/profile/show.md +3 -3
  24. package/dist/agent-src/commands/rule-compliance-audit.md +5 -4
  25. package/dist/agent-src/commands/security-audit-config.md +1 -1
  26. package/dist/agent-src/commands/sync/gitignore/fix.md +1 -1
  27. package/dist/agent-src/commands/tdd.md +21 -0
  28. package/dist/agent-src/commands/team/delegate.md +2 -2
  29. package/dist/agent-src/commands/team-knowledge/bootstrap.md +9 -8
  30. package/dist/agent-src/commands/team-knowledge/consolidate.md +8 -7
  31. package/dist/agent-src/commands/team.md +4 -1
  32. package/dist/agent-src/commands/upstream-contribute.md +0 -1
  33. package/dist/agent-src/contexts/authority/commit-mechanics.md +7 -0
  34. package/dist/agent-src/contexts/authority/destructive-mechanics.md +16 -0
  35. package/dist/agent-src/contexts/authority/scope-mechanics.md +61 -0
  36. package/dist/agent-src/contexts/communication/rules-auto/reply-close-mechanics.md +20 -18
  37. package/dist/agent-src/contexts/communication/rules-auto/skill-quality-mechanics.md +1 -1
  38. package/dist/agent-src/contexts/communication/rules-auto/slash-command-routing-policy-mechanics.md +1 -1
  39. package/dist/agent-src/contexts/communication/rules-auto/source-of-truth-mechanics.md +9 -10
  40. package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +1 -1
  41. package/dist/agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +11 -0
  42. package/dist/agent-src/contexts/contracts/artifact-engagement-flow.md +26 -15
  43. package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +3 -0
  44. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +67 -37
  45. package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +1 -1
  46. package/dist/agent-src/contexts/execution/autonomy-examples.md +1 -1
  47. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +7 -6
  48. package/dist/agent-src/contexts/execution/evidence-discipline.md +92 -77
  49. package/dist/agent-src/contexts/execution/orchestration-benchmark-gate.md +22 -21
  50. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +24 -0
  51. package/dist/agent-src/contexts/execution/project-intelligence.md +122 -103
  52. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +23 -21
  53. package/dist/agent-src/contexts/execution/subagent-response-contract.md +5 -5
  54. package/dist/agent-src/contexts/execution/subagent-routing.md +11 -0
  55. package/dist/agent-src/contexts/execution/subagent-spawn-contract.md +13 -13
  56. package/dist/agent-src/contexts/execution/subagent-steering.md +36 -34
  57. package/dist/agent-src/contexts/execution/toolchain-resolver.md +1 -1
  58. package/dist/agent-src/contexts/execution/user-memory-channels.md +189 -0
  59. package/dist/agent-src/contexts/execution/verification-mechanics.md +9 -0
  60. package/dist/agent-src/contexts/model-recommendations.md +3 -2
  61. package/dist/agent-src/contexts/subagent-configuration.md +3 -3
  62. package/dist/agent-src/ghostwriter/README.md +2 -2
  63. package/dist/agent-src/packs/README.md +1 -1
  64. package/dist/agent-src/personas/README.md +5 -5
  65. package/dist/agent-src/personas/_template-specialist/persona.md +3 -3
  66. package/dist/agent-src/personas/backend-architect.md +24 -23
  67. package/dist/agent-src/personas/eloquent-tamer.md +30 -30
  68. package/dist/agent-src/personas/frontend-engineer.md +30 -30
  69. package/dist/agent-src/personas/product-owner.md +41 -38
  70. package/dist/agent-src/personas/qa.md +13 -13
  71. package/dist/agent-src/personas/security-engineer.md +22 -22
  72. package/dist/agent-src/presets/README.md +3 -3
  73. package/dist/agent-src/profiles/README.md +3 -3
  74. package/dist/agent-src/rules/active-remediation.md +2 -2
  75. package/dist/agent-src/rules/artifact-engagement-recording.md +4 -4
  76. package/dist/agent-src/rules/ask-when-uncertain.md +0 -4
  77. package/dist/agent-src/rules/augment-edit-discipline.md +1 -1
  78. package/dist/agent-src/rules/broken-access-control.md +4 -4
  79. package/dist/agent-src/rules/code-comment-discipline.md +1 -1
  80. package/dist/agent-src/rules/code-provenance.md +2 -2
  81. package/dist/agent-src/rules/commit-policy.md +4 -9
  82. package/dist/agent-src/rules/communication-through-line.md +5 -5
  83. package/dist/agent-src/rules/decision-revisit-gate.md +1 -1
  84. package/dist/agent-src/rules/design-fidelity.md +1 -1
  85. package/dist/agent-src/rules/doc-screenshot-hygiene.md +1 -1
  86. package/dist/agent-src/rules/domain-adoption-policy.md +1 -1
  87. package/dist/agent-src/rules/domain-safety-pii.md +1 -1
  88. package/dist/agent-src/rules/external-code-graph-interop.md +1 -1
  89. package/dist/agent-src/rules/fast-path-marker-visibility.md +43 -7
  90. package/dist/agent-src/rules/finance-safety-floor.md +1 -1
  91. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +3 -3
  92. package/dist/agent-src/rules/history-discipline.md +1 -1
  93. package/dist/agent-src/rules/legal-safety-floor.md +1 -1
  94. package/dist/agent-src/rules/lethal-trifecta-guard.md +5 -5
  95. package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +10 -8
  96. package/dist/agent-src/rules/media-governance-routing.md +13 -13
  97. package/dist/agent-src/rules/media-sync-ground-truth.md +29 -11
  98. package/dist/agent-src/rules/no-cheap-questions.md +7 -7
  99. package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +29 -18
  100. package/dist/agent-src/rules/non-destructive-by-default.md +5 -23
  101. package/dist/agent-src/rules/onboarding-gate.md +14 -4
  102. package/dist/agent-src/rules/persona-governance.md +2 -2
  103. package/dist/agent-src/rules/prefer-enums-over-literals.md +9 -9
  104. package/dist/agent-src/rules/preservation-guard.md +10 -2
  105. package/dist/agent-src/rules/question-not-instruction.md +1 -1
  106. package/dist/agent-src/rules/roadmap-progress-sync.md +6 -6
  107. package/dist/agent-src/rules/rule-type-governance.md +1 -1
  108. package/dist/agent-src/rules/scale-discipline.md +1 -1
  109. package/dist/agent-src/rules/scope-control.md +1 -1
  110. package/dist/agent-src/rules/secret-vcs-guard.md +1 -1
  111. package/dist/agent-src/rules/security-sensitive-stop.md +17 -11
  112. package/dist/agent-src/rules/senior-engineering-discipline.md +17 -17
  113. package/dist/agent-src/rules/session-canary.md +1 -1
  114. package/dist/agent-src/rules/skill-quality.md +1 -1
  115. package/dist/agent-src/rules/source-confidentiality.md +21 -19
  116. package/dist/agent-src/rules/source-of-truth.md +6 -5
  117. package/dist/agent-src/rules/spreadsheet-source-quality.md +2 -2
  118. package/dist/agent-src/rules/strategy-safety-floor.md +1 -1
  119. package/dist/agent-src/rules/think-before-action.md +5 -5
  120. package/dist/agent-src/rules/token-budget-discipline.md +5 -3
  121. package/dist/agent-src/rules/token-efficiency.md +2 -2
  122. package/dist/agent-src/rules/untrusted-input-defense.md +4 -4
  123. package/dist/agent-src/rules/user-interaction.md +12 -0
  124. package/dist/agent-src/rules/verify-before-complete.md +4 -24
  125. package/dist/agent-src/skills/adversarial-review/SKILL.md +2 -2
  126. package/dist/agent-src/skills/agent-security-review/SKILL.md +52 -45
  127. package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +2 -2
  128. package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +20 -20
  129. package/dist/agent-src/skills/ai-council/SKILL.md +185 -128
  130. package/dist/agent-src/skills/analysis-skill-router/SKILL.md +3 -3
  131. package/dist/agent-src/skills/api-endpoint/SKILL.md +2 -2
  132. package/dist/agent-src/skills/artisan-commands/SKILL.md +2 -2
  133. package/dist/agent-src/skills/async-python-patterns/SKILL.md +8 -7
  134. package/dist/agent-src/skills/authz-review/SKILL.md +16 -15
  135. package/dist/agent-src/skills/aws-infrastructure/SKILL.md +5 -5
  136. package/dist/agent-src/skills/blade-ui/SKILL.md +1 -1
  137. package/dist/agent-src/skills/bug-analyzer/SKILL.md +30 -12
  138. package/dist/agent-src/skills/code-intelligence/SKILL.md +0 -1
  139. package/dist/agent-src/skills/code-intelligence/evals/triggers.json +52 -0
  140. package/dist/agent-src/skills/code-review/SKILL.md +6 -6
  141. package/dist/agent-src/skills/command-routing/SKILL.md +5 -4
  142. package/dist/agent-src/skills/composer-packages/SKILL.md +2 -2
  143. package/dist/agent-src/skills/condense-memory/SKILL.md +43 -41
  144. package/dist/agent-src/skills/context-document/SKILL.md +23 -21
  145. package/dist/agent-src/skills/copilot-config/SKILL.md +6 -1
  146. package/dist/agent-src/skills/decision-record/SKILL.md +20 -18
  147. package/dist/agent-src/skills/design-intelligence/SKILL.md +4 -4
  148. package/dist/agent-src/skills/design-review/SKILL.md +15 -14
  149. package/dist/agent-src/skills/design-system-capture/reference/design-system-json.md +28 -25
  150. package/dist/agent-src/skills/devcontainer/SKILL.md +2 -2
  151. package/dist/agent-src/skills/docker/SKILL.md +1 -1
  152. package/dist/agent-src/skills/docx-authoring/evals/triggers.json +52 -0
  153. package/dist/agent-src/skills/emit-tickets/SKILL.md +2 -2
  154. package/dist/agent-src/skills/error-handling-patterns/SKILL.md +1 -1
  155. package/dist/agent-src/skills/estimate-ticket/SKILL.md +2 -2
  156. package/dist/agent-src/skills/evaluate-llm-feature/SKILL.md +0 -1
  157. package/dist/agent-src/skills/evaluate-llm-feature/evals/triggers.json +52 -0
  158. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +21 -7
  159. package/dist/agent-src/skills/fe-design/SKILL.md +10 -0
  160. package/dist/agent-src/skills/feature-planning/SKILL.md +2 -2
  161. package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +3 -3
  162. package/dist/agent-src/skills/flux/SKILL.md +1 -1
  163. package/dist/agent-src/skills/frontend-render-security/SKILL.md +13 -13
  164. package/dist/agent-src/skills/git-workflow/SKILL.md +33 -33
  165. package/dist/agent-src/skills/grafana/SKILL.md +5 -0
  166. package/dist/agent-src/skills/humanizer/SKILL.md +83 -66
  167. package/dist/agent-src/skills/humanizer/data/patterns.md +14 -14
  168. package/dist/agent-src/skills/humanizer/references/anti-aiisms.md +4 -4
  169. package/dist/agent-src/skills/judge-artifact-completeness/SKILL.md +82 -37
  170. package/dist/agent-src/skills/judge-bug-hunter/SKILL.md +17 -5
  171. package/dist/agent-src/skills/judge-injection-defense/SKILL.md +63 -25
  172. package/dist/agent-src/skills/judge-security-auditor/SKILL.md +2 -0
  173. package/dist/agent-src/skills/judge-synthesis/SKILL.md +72 -28
  174. package/dist/agent-src/skills/laravel-horizon/SKILL.md +5 -0
  175. package/dist/agent-src/skills/laravel-mail/SKILL.md +5 -4
  176. package/dist/agent-src/skills/laravel-middleware/SKILL.md +5 -4
  177. package/dist/agent-src/skills/laravel-notifications/SKILL.md +10 -9
  178. package/dist/agent-src/skills/laravel-pennant/SKILL.md +1 -1
  179. package/dist/agent-src/skills/laravel-pulse/SKILL.md +9 -8
  180. package/dist/agent-src/skills/laravel-reverb/SKILL.md +6 -5
  181. package/dist/agent-src/skills/laravel-scheduling/SKILL.md +6 -1
  182. package/dist/agent-src/skills/laravel-validation/SKILL.md +12 -0
  183. package/dist/agent-src/skills/launch-readiness/SKILL.md +1 -1
  184. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +7 -7
  185. package/dist/agent-src/skills/learning-tutor/SKILL.md +44 -43
  186. package/dist/agent-src/skills/learning-tutor/evals/triggers.json +52 -0
  187. package/dist/agent-src/skills/license-compliance-audit/SKILL.md +7 -7
  188. package/dist/agent-src/skills/license-compliance-borrow-check/SKILL.md +3 -3
  189. package/dist/agent-src/skills/license-compliance-credits/SKILL.md +4 -4
  190. package/dist/agent-src/skills/llm-provider-knowledge/SKILL.md +0 -1
  191. package/dist/agent-src/skills/memory-consolidation/SKILL.md +69 -64
  192. package/dist/agent-src/skills/motion-choreographer/SKILL.md +6 -6
  193. package/dist/agent-src/skills/pdf-tools/evals/triggers.json +52 -0
  194. package/dist/agent-src/skills/performance-analysis/SKILL.md +7 -3
  195. package/dist/agent-src/skills/persona-improvement/SKILL.md +0 -2
  196. package/dist/agent-src/skills/persona-improvement/evals/triggers.json +52 -0
  197. package/dist/agent-src/skills/php-coder/SKILL.md +10 -0
  198. package/dist/agent-src/skills/prediction-pool-optimizer/SKILL.md +129 -120
  199. package/dist/agent-src/skills/prediction-pool-optimizer/reference/ev-fixtures.md +36 -35
  200. package/dist/agent-src/skills/prediction-pool-optimizer/reference/odds-and-bonus.md +45 -41
  201. package/dist/agent-src/skills/project-analysis-core/SKILL.md +4 -4
  202. package/dist/agent-src/skills/project-analysis-hypothesis-driven/SKILL.md +3 -3
  203. package/dist/agent-src/skills/project-analysis-react/SKILL.md +1 -1
  204. package/dist/agent-src/skills/project-analysis-symfony/SKILL.md +1 -1
  205. package/dist/agent-src/skills/project-analysis-zend-laminas/SKILL.md +2 -2
  206. package/dist/agent-src/skills/prompt-engineering-patterns/SKILL.md +1 -1
  207. package/dist/agent-src/skills/prompt-validator/SKILL.md +39 -39
  208. package/dist/agent-src/skills/quality-tools/SKILL.md +15 -15
  209. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +55 -19
  210. package/dist/agent-src/skills/react-shadcn-ui/reference/registry.md +29 -27
  211. package/dist/agent-src/skills/readme-writing-package/SKILL.md +2 -2
  212. package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +25 -25
  213. package/dist/agent-src/skills/recursive-verification/SKILL.md +6 -5
  214. package/dist/agent-src/skills/refine-prompt/SKILL.md +1 -1
  215. package/dist/agent-src/skills/refine-ticket/SKILL.md +20 -2
  216. package/dist/agent-src/skills/repomix-packer/SKILL.md +1 -1
  217. package/dist/agent-src/skills/requesting-code-review/SKILL.md +2 -2
  218. package/dist/agent-src/skills/roadmap-management/SKILL.md +80 -66
  219. package/dist/agent-src/skills/roadmap-writing/SKILL.md +84 -77
  220. package/dist/agent-src/skills/rule-refactor/SKILL.md +1 -1
  221. package/dist/agent-src/skills/screenshot-hygiene/evals/triggers.json +52 -0
  222. package/dist/agent-src/skills/security-audit/SKILL.md +26 -9
  223. package/dist/agent-src/skills/security-maturity-assessment/SKILL.md +38 -16
  224. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +14 -11
  225. package/dist/agent-src/skills/skill-writing/SKILL.md +9 -8
  226. package/dist/agent-src/skills/song-to-script/SKILL.md +93 -85
  227. package/dist/agent-src/skills/sql-writing/SKILL.md +2 -2
  228. package/dist/agent-src/skills/stakeholder-tradeoff/SKILL.md +4 -3
  229. package/dist/agent-src/skills/standards-from-config/SKILL.md +61 -43
  230. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +22 -8
  231. package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +28 -2
  232. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +13 -13
  233. package/dist/agent-src/skills/systematic-debugging/SKILL.md +22 -21
  234. package/dist/agent-src/skills/tailwind-engineer/SKILL.md +1 -1
  235. package/dist/agent-src/skills/technical-specification/SKILL.md +5 -0
  236. package/dist/agent-src/skills/terraform/SKILL.md +2 -2
  237. package/dist/agent-src/skills/terragrunt/SKILL.md +8 -8
  238. package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +1 -1
  239. package/dist/agent-src/skills/threat-modeling/SKILL.md +19 -13
  240. package/dist/agent-src/skills/universal-project-analysis/SKILL.md +1 -1
  241. package/dist/agent-src/skills/upstream-contribute/SKILL.md +0 -1
  242. package/dist/agent-src/skills/using-git-worktrees/SKILL.md +9 -9
  243. package/dist/agent-src/skills/validate-feature-fit/SKILL.md +3 -1
  244. package/dist/agent-src/skills/verify-completion-evidence/SKILL.md +4 -6
  245. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +67 -61
  246. package/dist/agent-src/skills/video-director/SKILL.md +7 -7
  247. package/dist/agent-src/skills/worktree-lifecycle/SKILL.md +3 -3
  248. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  249. package/dist/agent-src/templates/contexts/knowledge-pages.md +47 -45
  250. package/dist/agent-src/templates/contexts/lesson-card.md +2 -2
  251. package/dist/agent-src/templates/contexts/tenant-boundaries.md +2 -2
  252. package/dist/agent-src/templates/contexts.md +1 -1
  253. package/dist/agent-src/templates/features.md +1 -1
  254. package/dist/agent-src/templates/roadmaps.md +125 -116
  255. package/dist/agent-src/templates/rule.md +2 -1
  256. package/dist/agent-src/templates/scripts/pr_risk_review.ts +0 -0
  257. package/dist/agent-src/templates/scripts/telemetry/aggregator.ts +0 -0
  258. package/dist/agent-src/templates/scripts/tier_usage_report.ts +2 -2
  259. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +30 -30
  260. package/dist/agent-src/templates/scripts/work_engine/directives/ui/design.ts +88 -33
  261. package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +22 -2
  262. package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +21 -2
  263. package/dist/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +179 -0
  264. package/dist/agent-src/templates/scripts/work_engine/stack/detect.ts +155 -4
  265. package/dist/agent-src/templates/scripts/work_engine/state.ts +21 -4
  266. package/dist/agent-src/user-types/README.md +8 -8
  267. package/dist/agent-src/user-types/galabau-field-crew.md +34 -33
  268. package/dist/agent-src/user-types/metalworking-shop.md +35 -34
  269. package/dist/agent-src/user-types/truck-driver.md +22 -20
  270. package/dist/cli/initRouting.js +74 -11
  271. package/dist/cli/initRouting.js.map +1 -1
  272. package/dist/cli/main.js +14 -3
  273. package/dist/cli/main.js.map +1 -1
  274. package/dist/cli/python/workspace_roles.js +2 -2
  275. package/dist/cli/python/workspace_roles.js.map +1 -1
  276. package/dist/cli-delegate/chunk-4SV3XGFA.js +6910 -0
  277. package/dist/cli-delegate/chunk-736JCWLM.js +1104 -0
  278. package/dist/cli-delegate/chunk-7DSAMZFU.js +356 -0
  279. package/dist/cli-delegate/chunk-7HQ52DHU.js +74 -0
  280. package/dist/cli-delegate/chunk-BJGXZNPM.js +266 -0
  281. package/dist/cli-delegate/chunk-FTAISGDQ.js +117 -0
  282. package/dist/cli-delegate/chunk-GME3Q44L.js +82 -0
  283. package/dist/cli-delegate/chunk-GRRPEPRN.js +336 -0
  284. package/dist/cli-delegate/chunk-HJ6DAJHR.js +502 -0
  285. package/dist/cli-delegate/chunk-IR7P7JWA.js +872 -0
  286. package/dist/cli-delegate/chunk-J55WI3RR.js +47 -0
  287. package/dist/cli-delegate/chunk-MCJYCQPF.js +35 -0
  288. package/dist/cli-delegate/chunk-NDJLNC6Q.js +169 -0
  289. package/dist/cli-delegate/chunk-OMIVVCG2.js +26 -0
  290. package/dist/cli-delegate/chunk-OY53J6II.js +7336 -0
  291. package/dist/cli-delegate/chunk-RDGRHAAB.js +259 -0
  292. package/dist/cli-delegate/chunk-TFG57JJM.js +1969 -0
  293. package/dist/cli-delegate/chunk-XX6TOPD7.js +715 -0
  294. package/dist/cli-delegate/chunk-YMFO6FDN.js +10603 -0
  295. package/dist/cli-delegate/cmd_analyze_session.js +294 -0
  296. package/dist/cli-delegate/cmd_conformance.js +646 -0
  297. package/dist/cli-delegate/cmd_converge.js +326 -0
  298. package/dist/cli-delegate/cmd_doctor.js +144 -0
  299. package/dist/cli-delegate/cmd_explain.js +2508 -0
  300. package/dist/cli-delegate/cmd_export.js +296 -0
  301. package/dist/cli-delegate/cmd_fleet.js +332 -0
  302. package/dist/cli-delegate/cmd_memory_get.js +3878 -0
  303. package/dist/cli-delegate/cmd_migrate.js +11 -0
  304. package/dist/cli-delegate/cmd_preflight.js +270 -0
  305. package/dist/cli-delegate/cmd_prune.js +444 -0
  306. package/dist/cli-delegate/cmd_refresh.js +28 -0
  307. package/dist/cli-delegate/cmd_settings_check.js +574 -0
  308. package/dist/cli-delegate/cmd_settings_migrate.js +223 -0
  309. package/dist/cli-delegate/cmd_sync.js +264 -0
  310. package/dist/cli-delegate/cmd_uninstall.js +656 -0
  311. package/dist/cli-delegate/cmd_update.js +425 -0
  312. package/dist/cli-delegate/cmd_upgrade.js +444 -0
  313. package/dist/cli-delegate/cmd_validate.js +305 -0
  314. package/dist/cli-delegate/cmd_versions.js +370 -0
  315. package/dist/discovery/deprecation-report.md +1 -1
  316. package/dist/discovery/discovery-manifest.json +100 -67
  317. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  318. package/dist/discovery/discovery-manifest.summary.md +4 -4
  319. package/dist/discovery/orphan-report.md +1 -1
  320. package/dist/discovery/packs.json +16 -10
  321. package/dist/discovery/trust-report.md +2 -2
  322. package/dist/discovery/workspaces.json +7 -5
  323. package/dist/hooks/dispatch.js +186 -12
  324. package/dist/install/emit_host_rules_cli.js +2 -1
  325. package/dist/install/emit_host_rules_cli.js.map +1 -1
  326. package/dist/install/install.mjs +418 -378
  327. package/dist/install/rule_scope.js +5 -1
  328. package/dist/install/rule_scope.js.map +1 -1
  329. package/dist/install/toolDetection.js +40 -12
  330. package/dist/install/toolDetection.js.map +1 -1
  331. package/dist/install/wizard-plan.js +2 -2
  332. package/dist/install/wizard-plan.js.map +1 -1
  333. package/dist/mcp/registry-manifest.json +3 -3
  334. package/dist/mcp/server.json +2 -2
  335. package/dist/mcp/server.mjs +2194 -1003
  336. package/dist/router.json +1 -1
  337. package/dist/scripts/_lib/compile_time_toggles.js +48 -0
  338. package/dist/scripts/_lib/compile_time_toggles.js.map +1 -0
  339. package/dist/scripts/condense.js +234 -217
  340. package/dist/scripts/condense.js.map +1 -1
  341. package/dist/server/schemas/settings.js +4 -0
  342. package/dist/server/schemas/settings.js.map +1 -1
  343. package/dist/shared/userMd/utils.js +30 -0
  344. package/dist/shared/userMd/utils.js.map +1 -1
  345. package/dist/ui/assets/index-BpSQt5vm.js.map +1 -1
  346. package/docs/guidelines/agent-infra/api-cost-levers.md +56 -5
  347. package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +93 -33
  348. package/package.json +4 -2
  349. package/src/agent-src/templates/scripts/pr_risk_review.ts +0 -0
  350. package/src/agent-src/templates/scripts/telemetry/aggregator.ts +0 -0
  351. package/src/agent-src/templates/scripts/tier_usage_report.ts +2 -2
  352. package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +30 -30
  353. package/src/agent-src/templates/scripts/work_engine/directives/ui/design.ts +88 -33
  354. package/src/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +22 -2
  355. package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +21 -2
  356. package/src/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +179 -0
  357. package/src/agent-src/templates/scripts/work_engine/stack/detect.ts +155 -4
  358. package/src/agent-src/templates/scripts/work_engine/state.ts +21 -4
  359. package/src/config/agent-settings.template.yml +32 -2
  360. package/src/config/ci-local-parity.yml +142 -0
  361. package/src/config/discovery/packs.yml +7 -0
  362. package/src/config/evaluator-budgets.json +1 -1
  363. package/src/config/gate-coverage.yml +127 -0
  364. package/src/config/pack-size-budget.json +27 -0
  365. package/src/config/preamble-payload-budget.json +44 -0
  366. package/src/install/emit_host_rules_cli.ts +2 -1
  367. package/src/install/rule_scope.ts +5 -1
  368. package/src/install/toolDetection.ts +39 -8
  369. package/src/install/wizard-plan.ts +2 -2
  370. package/src/scripts/_cli/cmd_conformance.ts +2 -1
  371. package/src/scripts/_cli/cmd_converge.ts +2 -1
  372. package/src/scripts/_cli/cmd_doctor.ts +292 -15
  373. package/src/scripts/_cli/cmd_export.ts +2 -1
  374. package/src/scripts/_cli/cmd_fleet.ts +2 -1
  375. package/src/scripts/_cli/cmd_migrate.ts +2 -1
  376. package/src/scripts/_cli/cmd_preflight.ts +2 -1
  377. package/src/scripts/_cli/cmd_refresh.ts +2 -1
  378. package/src/scripts/_cli/cmd_update.ts +2 -1
  379. package/src/scripts/_cli/cmd_upgrade.ts +2 -1
  380. package/src/scripts/_cli/cmd_versions.ts +2 -1
  381. package/src/scripts/_cli/detection_report.ts +480 -0
  382. package/src/scripts/_dispatch.bash +52 -14
  383. package/src/scripts/_lib/agent_user_profile.ts +381 -0
  384. package/src/scripts/_lib/agents_overlay.ts +9 -0
  385. package/src/scripts/_lib/anchor_eval.ts +311 -0
  386. package/src/scripts/_lib/cc_transcript.ts +316 -0
  387. package/src/scripts/_lib/changelog_eras.ts +103 -9
  388. package/src/scripts/_lib/compile_time_toggles.ts +79 -0
  389. package/src/scripts/_lib/confusables.ts +101 -0
  390. package/src/scripts/_lib/duplicate_scope_census.ts +77 -0
  391. package/src/scripts/_lib/environment_detector.ts +441 -0
  392. package/src/scripts/_lib/managed_agents_folder.ts +181 -0
  393. package/src/scripts/_lib/package_root.ts +72 -0
  394. package/src/scripts/_lib/payload_hash_drift.ts +126 -0
  395. package/src/scripts/_lib/preservation_migration.ts +291 -0
  396. package/src/scripts/_lib/retrieval_sanitize.ts +166 -2
  397. package/src/scripts/_lib/scan_scope.ts +115 -0
  398. package/src/scripts/_lib/user_global_memory_audit.ts +187 -0
  399. package/src/scripts/_lib/user_global_observations.ts +830 -0
  400. package/src/scripts/_lib/user_global_revocations.ts +110 -0
  401. package/src/scripts/_lib/user_memory_gate_counters.ts +291 -0
  402. package/src/scripts/ai_council/blind_review.ts +0 -0
  403. package/src/scripts/ai_council/budget_guard.ts +90 -11
  404. package/src/scripts/ai_council/bundler.ts +2 -2
  405. package/src/scripts/ai_council/clients.ts +59 -3
  406. package/src/scripts/ai_council/config.ts +53 -7
  407. package/src/scripts/ai_council/modes.ts +68 -2
  408. package/src/scripts/ai_council/orchestrator.ts +54 -9
  409. package/src/scripts/ai_council/transport_resolver.ts +331 -0
  410. package/src/scripts/ai_team/team_dispatch.ts +17 -6
  411. package/src/scripts/anchor_eval_falsify.ts +198 -0
  412. package/src/scripts/anchor_scoring_run.ts +239 -0
  413. package/src/scripts/annotate_discovery.ts +1 -65
  414. package/src/scripts/bench_quality_run.ts +168 -4
  415. package/src/scripts/cache_realization_report.ts +782 -0
  416. package/src/scripts/check_artefact_count_messaging.ts +5 -1
  417. package/src/scripts/check_augment_description_cap.ts +15 -4
  418. package/src/scripts/check_bundle_path_leakage.ts +10 -4
  419. package/src/scripts/check_ci_local_parity.ts +317 -0
  420. package/src/scripts/check_condensation.ts +96 -191
  421. package/src/scripts/check_context_paths.ts +38 -9
  422. package/src/scripts/check_dependency_floors.ts +153 -0
  423. package/src/scripts/check_gate_coverage.ts +299 -0
  424. package/src/scripts/check_iron_law_prominence.ts +22 -1
  425. package/src/scripts/check_kernel_prefix_stability.ts +0 -0
  426. package/src/scripts/check_no_new_legacy_path.ts +16 -6
  427. package/src/scripts/check_no_roadmap_refs.ts +22 -9
  428. package/src/scripts/check_originality_freshness.ts +167 -0
  429. package/src/scripts/check_pack_size.ts +188 -0
  430. package/src/scripts/check_preamble_payload_budget.ts +130 -0
  431. package/src/scripts/check_proposal.ts +0 -0
  432. package/src/scripts/check_references.ts +0 -1
  433. package/src/scripts/check_safety_floor_untouched.ts +171 -24
  434. package/src/scripts/check_site_links.ts +62 -3
  435. package/src/scripts/ci_status.ts +0 -0
  436. package/src/scripts/cluster_near_miss_patterns.ts +0 -0
  437. package/src/scripts/code_graph/build.ts +0 -0
  438. package/src/scripts/command_suggester/types.ts +0 -0
  439. package/src/scripts/compile_router.ts +10 -14
  440. package/src/scripts/condense.sh +3 -4
  441. package/src/scripts/condense.ts +247 -228
  442. package/src/scripts/cost/track.mjs +168 -33
  443. package/src/scripts/cost_summary.ts +33 -1
  444. package/src/scripts/council_cli.ts +51 -5
  445. package/src/scripts/discovery_graph.ts +0 -0
  446. package/src/scripts/encoding_corpus.ts +500 -0
  447. package/src/scripts/encoding_corpus_report.ts +216 -0
  448. package/src/scripts/evaluator_umbrella.sh +34 -1
  449. package/src/scripts/generate_index.ts +19 -2
  450. package/src/scripts/install-hooks.sh +2 -2
  451. package/src/scripts/learning_sidecar.ts +0 -0
  452. package/src/scripts/lint_confusables.ts +10 -72
  453. package/src/scripts/lint_eval_fixture_citations.ts +113 -0
  454. package/src/scripts/lint_featured_skills.ts +0 -0
  455. package/src/scripts/lint_hidden_unicode.ts +208 -0
  456. package/src/scripts/lint_load_context.ts +17 -5
  457. package/src/scripts/lint_new_skill_gate.ts +9 -3
  458. package/src/scripts/lint_no_python_twin_rationale.ts +17 -2
  459. package/src/scripts/lint_originality.ts +1 -1
  460. package/src/scripts/lint_skill_originality.ts +1 -1
  461. package/src/scripts/lint_ticket_buildable.ts +1 -1
  462. package/src/scripts/lint_ui_stack_bundles.ts +170 -0
  463. package/src/scripts/mcp_server/tools.ts +4 -4
  464. package/src/scripts/measure_scope_dedup.ts +224 -0
  465. package/src/scripts/memory_lookup.ts +0 -0
  466. package/src/scripts/mine_session.ts +98 -0
  467. package/src/scripts/orchestration_payload_hash_drift.ts +145 -0
  468. package/src/scripts/preamble_byte_census.ts +574 -0
  469. package/src/scripts/probe_skill_registration.ts +2 -2
  470. package/src/scripts/redact_hook_capture.ts +13 -0
  471. package/src/scripts/release.ts +65 -10
  472. package/src/scripts/router_telemetry.ts +1 -1
  473. package/src/scripts/second_brain_retrieval.ts +14 -4
  474. package/src/scripts/skill_linter.ts +5 -0
  475. package/src/scripts/surface-tiers.yml +2 -0
  476. package/src/scripts/validate_pack_yaml.ts +0 -0
  477. package/src/server/schemas/settings.ts +8 -0
  478. package/src/shared/userMd/utils.ts +31 -0
  479. package/dist/agent-src/rules/telegraph-speak.md +0 -87
@@ -58,7 +58,11 @@ export const SURFACES: readonly string[] = [
58
58
  // watched this file. Added 2026-07-25 so a hand-typed count here fails CI.
59
59
  'docs/distribution/registries.md',
60
60
  'site/src/content/docs/index.mdx',
61
- 'site/src/content/docs/claims.md',
61
+ // NOT site/src/content/docs/claims.md — it is gitignored generated output
62
+ // (site/sync-docs.mjs copies docs/CLAIMS.md into it), and docs/CLAIMS.md is
63
+ // already checked above. Watching the copy added no coverage and turned a
64
+ // stale LOCAL artefact into a red gate, while CI passed because the file is
65
+ // absent there. A gate must judge repo content, not untracked local state.
62
66
  ];
63
67
 
64
68
  /** kind → canonical-count resolver. "governed rules" is the canonical total
@@ -6,10 +6,10 @@
6
6
  * Ported from the retired Python `src/scripts/check_augment_description_cap.py` (ADR-200,
7
7
  * Phase 4 / Wave 4c). The CLI contract is pinned — no flags, exit
8
8
  * codes (0 pass, 1 over-cap), stdout/stderr split, byte-identical finding
9
- * messages, same scan scope (`.agent-src.uncondensed/rules/*.md`) and file
9
+ * messages, same scan scope (`src/rules/*.md`) and file
10
10
  * ordering. Historical quirks are preserved deliberately — tests and downstream consumers pin the exact behaviour.
11
11
  *
12
- * For every `type: auto` rule under `.agent-src.uncondensed/rules/`,
12
+ * For every `type: auto` rule under `src/rules/`,
13
13
  * fail CI when the frontmatter `description:` exceeds DESC_CAP chars.
14
14
  *
15
15
  * Why: Augment injects each auto-rule's description into the
@@ -17,7 +17,7 @@
17
17
  * analysis showed this channel consuming 25 % of the workspace-guidelines
18
18
  * ceiling. Capping descriptions guards future drift.
19
19
  *
20
- * Source of truth: `.agent-src.uncondensed/rules/`. The condensed
20
+ * Source of truth: `src/rules/`. The condensed
21
21
  * projection is regenerated; the source dictates what ships.
22
22
  *
23
23
  * Exit codes: 0 = pass, 1 = at least one rule over cap.
@@ -31,7 +31,12 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
31
31
  // Mirrors the Python `Path(__file__).resolve().parent.parent.parent`.
32
32
  const _HERE = fileURLToPath(import.meta.url);
33
33
  const REPO_ROOT = path.resolve(path.dirname(_HERE), '..', '..');
34
- const RULES_DIR = path.join(REPO_ROOT, '.agent-src.uncondensed', 'rules');
34
+ // Retargeted 2026-07-29: pointed at the tree emptied by the ADR-051 flat-`src/`
35
+ // migration, so this gate printed "All 0 auto-rule descriptions ≤ 150 chars." and
36
+ // exited 0 while wired into CI — the count sat in its own output the whole time.
37
+ // Retargeting surfaced 16 real cap violations (98 auto-rules, max 189); all 16
38
+ // were shortened under an explicit operator review that kept every matching term.
39
+ const RULES_DIR = path.join(REPO_ROOT, 'src', 'rules');
35
40
  const DESC_CAP = 150;
36
41
 
37
42
  const _FM_LINE_RE = /^([A-Za-z_][A-Za-z0-9_-]*):\s*(.*)$/;
@@ -103,6 +108,12 @@ export function main(): number {
103
108
  }
104
109
  }
105
110
 
111
+ // Gate-coverage contract (src/config/gate-coverage.yml): emitted BEFORE the
112
+ // pass/fail branch. Coverage and verdict are different questions — a gate that
113
+ // found real violations still scanned its corpus, and reporting the count only
114
+ // on the success path would make it look 'silent' to check_gate_coverage.
115
+ process.stdout.write(`scanned: ${String(checked)}\n`);
116
+
106
117
  if (failures.length) {
107
118
  process.stderr.write(
108
119
  `❌ ${failures.length} auto-rule description(s) exceed ${DESC_CAP} chars:\n\n`,
@@ -62,10 +62,16 @@ const REPO = path.resolve(path.dirname(_HERE), '..', '..');
62
62
 
63
63
  // Tracked directories that may hold a build-generated bundle. Only
64
64
  // `dist/install/` is force-included in `.gitignore` today (`!/dist/install/`);
65
- // `dist/hooks/` and `dist/mcp/` are listed defensively in case a future
66
- // change tracks them too — `git ls-files` on an untracked directory returns
67
- // nothing, so listing an as-yet-untracked root here is always safe.
68
- const BUNDLE_ROOTS: readonly string[] = ['dist/install', 'dist/hooks', 'dist/mcp'];
65
+ // `dist/hooks/`, `dist/mcp/` and `dist/cli-delegate/` are listed defensively
66
+ // in case a future change tracks them too — `git ls-files` on an untracked
67
+ // directory returns nothing, so listing an as-yet-untracked root here is
68
+ // always safe.
69
+ const BUNDLE_ROOTS: readonly string[] = [
70
+ 'dist/install',
71
+ 'dist/hooks',
72
+ 'dist/mcp',
73
+ 'dist/cli-delegate',
74
+ ];
69
75
 
70
76
  interface LeakPattern {
71
77
  readonly name: string;
@@ -0,0 +1,317 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * CI ↔ local parity checker.
4
+ *
5
+ * A gate that exists on one side only drifts silently on the other, and both
6
+ * directions cost real defects (see `src/config/ci-local-parity.yml` for the
7
+ * measured cases). This checker DERIVES both sides rather than trusting a list:
8
+ *
9
+ * CI side every gate invocation in `.github/workflows/*.yml`
10
+ * local side the transitive closure of `task ci` / `task consistency` plus the
11
+ * pre-push hook, resolved through `Taskfile.yml` + `taskfiles/*.yml`
12
+ *
13
+ * Anything on one side and not the other must be declared in the manifest with a
14
+ * reason, or this fails. Drift stays allowed — but only on the record.
15
+ *
16
+ * Deriving beats listing because a hand-maintained list is exactly what goes stale:
17
+ * the first version of this analysis was done with a one-level grep and reported 71
18
+ * CI-only gates when the real number was 12. The closure is the whole point.
19
+ *
20
+ * Exit codes: 0 parity declared · 1 undeclared drift · 2 manifest/IO error.
21
+ *
22
+ * Usage:
23
+ * ./scripts-run src/scripts/check_ci_local_parity
24
+ * ./scripts-run src/scripts/check_ci_local_parity --format json
25
+ */
26
+
27
+ import * as fs from 'node:fs';
28
+ import * as path from 'node:path';
29
+ import { fileURLToPath, pathToFileURL } from 'node:url';
30
+
31
+ import { parse as parseYaml } from 'yaml';
32
+
33
+ const _FILE = fileURLToPath(import.meta.url);
34
+ export const REPO = path.resolve(path.dirname(_FILE), '..', '..');
35
+ const MANIFEST = path.join(REPO, 'src', 'config', 'ci-local-parity.yml');
36
+ const HOOK = path.join(REPO, 'src', 'scripts', 'install-hooks.sh');
37
+
38
+ /** Roots of the local closure. `ci` is the local mirror; the hook is what a push runs. */
39
+ const LOCAL_ROOTS = ['ci', 'consistency'] as const;
40
+
41
+ export interface Declared {
42
+ id: string;
43
+ class: string;
44
+ reason: string;
45
+ }
46
+
47
+ export interface Manifest {
48
+ pre_push_budget_seconds: number;
49
+ ci_only: Declared[];
50
+ local_only: Declared[];
51
+ }
52
+
53
+ export function load_manifest(file = MANIFEST): Manifest {
54
+ if (!fs.existsSync(file)) {
55
+ throw new Error(`manifest not found: ${path.relative(REPO, file)}`);
56
+ }
57
+ const doc = parseYaml(fs.readFileSync(file, 'utf-8')) as Record<string, unknown>;
58
+ const read = (key: string): Declared[] => {
59
+ const raw = doc[key];
60
+ if (raw === null || raw === undefined) return [];
61
+ if (!Array.isArray(raw)) throw new Error(`${key} must be a list`);
62
+ return raw.map((e, i) => {
63
+ const o = e as Record<string, unknown>;
64
+ const id = String(o['id'] ?? '');
65
+ if (id === '') throw new Error(`${key}[${String(i)}]: missing id`);
66
+ const reason = String(o['reason'] ?? '');
67
+ if (reason.trim() === '') {
68
+ // A declaration without a reason is the escape hatch that eats the
69
+ // gate: it looks reviewed and says nothing.
70
+ throw new Error(`${key} (${id}): reason must be non-empty`);
71
+ }
72
+ return { id, class: String(o['class'] ?? 'unclassified'), reason };
73
+ });
74
+ };
75
+ const budget = Number(doc['pre_push_budget_seconds']);
76
+ if (!Number.isFinite(budget) || budget <= 0) {
77
+ throw new Error('pre_push_budget_seconds must be a positive number');
78
+ }
79
+ return { pre_push_budget_seconds: budget, ci_only: read('ci_only'), local_only: read('local_only') };
80
+ }
81
+
82
+ /** Gate ids invoked anywhere in a blob of shell/YAML text. */
83
+ export function extract_gates(text: string): Set<string> {
84
+ const out = new Set<string>();
85
+ // ./scripts-run src/scripts/<name> | npx tsx src/scripts/<name>.ts | .sh
86
+ //
87
+ // The negative lookahead rejects a DIRECTORY segment: `src/scripts/_lib/x.ts`
88
+ // must not register `_lib` as a gate. Without it the first run reported 23
89
+ // CI-only gates, 10 of which were directory names (_cli, _lib, mcp_server, …) —
90
+ // a checker whose own extraction invents gates is worse than none, because every
91
+ // real finding then sits in a pile of noise. The backslash in the class is not
92
+ // decoration: the pre-push hook greps an escaped path (`pack_dependency_allowlist\.json`),
93
+ // and without it that JSON file registered as a local-only gate.
94
+ for (const m of text.matchAll(/src\/scripts\/([a-z0-9_]+)(?:\.(?:ts|sh))?(?![\w/.\\-])/g)) {
95
+ out.add(m[1] as string);
96
+ }
97
+ return out;
98
+ }
99
+
100
+ /** `task <name>` references in a blob of shell/YAML text. */
101
+ export function extract_tasks(text: string): Set<string> {
102
+ const out = new Set<string>();
103
+ for (const m of text.matchAll(/\btask\s+([a-z][a-z0-9:_-]*)/g)) {
104
+ out.add(m[1] as string);
105
+ }
106
+ return out;
107
+ }
108
+
109
+ interface TaskDef {
110
+ cmds: string[];
111
+ deps: string[];
112
+ }
113
+
114
+ /** Every task in Taskfile.yml + taskfiles/*.yml, flattened by name. */
115
+ export function load_tasks(repo = REPO): Map<string, TaskDef> {
116
+ const files = [path.join(repo, 'Taskfile.yml')];
117
+ const dir = path.join(repo, 'taskfiles');
118
+ if (fs.existsSync(dir)) {
119
+ for (const f of fs.readdirSync(dir).sort()) {
120
+ if (f.endsWith('.yml') || f.endsWith('.yaml')) files.push(path.join(dir, f));
121
+ }
122
+ }
123
+ const tasks = new Map<string, TaskDef>();
124
+ for (const file of files) {
125
+ if (!fs.existsSync(file)) continue;
126
+ let doc: Record<string, unknown>;
127
+ try {
128
+ doc = parseYaml(fs.readFileSync(file, 'utf-8')) as Record<string, unknown>;
129
+ } catch {
130
+ continue; // a malformed taskfile is another gate's verdict, not ours
131
+ }
132
+ const raw = doc['tasks'];
133
+ if (typeof raw !== 'object' || raw === null) continue;
134
+ for (const [name, body] of Object.entries(raw as Record<string, unknown>)) {
135
+ const def: TaskDef = { cmds: [], deps: [] };
136
+ const b = (typeof body === 'object' && body !== null ? body : {}) as Record<string, unknown>;
137
+ for (const key of ['cmd', 'cmds', 'deps']) {
138
+ const v = b[key];
139
+ if (typeof v === 'string') def.cmds.push(v);
140
+ else if (Array.isArray(v)) {
141
+ for (const item of v) {
142
+ if (typeof item === 'string') {
143
+ if (key === 'deps') def.deps.push(item);
144
+ else def.cmds.push(item);
145
+ } else if (typeof item === 'object' && item !== null) {
146
+ const o = item as Record<string, unknown>;
147
+ if (typeof o['task'] === 'string') def.deps.push(o['task']);
148
+ if (typeof o['cmd'] === 'string') def.cmds.push(o['cmd']);
149
+ if (typeof o['defer'] === 'object' && o['defer'] !== null) {
150
+ const d = o['defer'] as Record<string, unknown>;
151
+ if (typeof d['task'] === 'string') def.deps.push(d['task']);
152
+ }
153
+ }
154
+ }
155
+ }
156
+ }
157
+ // Later files win only if the name is new — mirrors `flatten: true`.
158
+ if (!tasks.has(name)) tasks.set(name, def);
159
+ }
160
+ }
161
+ return tasks;
162
+ }
163
+
164
+ /** Transitive closure of gate ids reachable from a set of task roots. */
165
+ export function local_closure(roots: readonly string[], tasks: Map<string, TaskDef>): Set<string> {
166
+ const gates = new Set<string>();
167
+ const seen = new Set<string>();
168
+ const queue = [...roots];
169
+ while (queue.length > 0) {
170
+ const name = queue.shift() as string;
171
+ if (seen.has(name)) continue;
172
+ seen.add(name);
173
+ const def = tasks.get(name);
174
+ if (def === undefined) continue;
175
+ for (const blob of [...def.cmds]) {
176
+ for (const g of extract_gates(blob)) gates.add(g);
177
+ for (const t of extract_tasks(blob)) queue.push(t);
178
+ }
179
+ for (const d of def.deps) queue.push(d);
180
+ }
181
+ return gates;
182
+ }
183
+
184
+ function _read_all(dir: string): string {
185
+ if (!fs.existsSync(dir)) return '';
186
+ return fs
187
+ .readdirSync(dir)
188
+ .filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'))
189
+ .sort()
190
+ .map((f) => fs.readFileSync(path.join(dir, f), 'utf-8'))
191
+ .join('\n');
192
+ }
193
+
194
+ export interface ParityReport {
195
+ ci_gates: string[];
196
+ local_gates: string[];
197
+ undeclared_ci_only: string[];
198
+ undeclared_local_only: string[];
199
+ stale_declarations: string[];
200
+ }
201
+
202
+ export function analyse(repo = REPO, manifest?: Manifest): ParityReport {
203
+ const mf = manifest ?? load_manifest();
204
+ const tasks = load_tasks(repo);
205
+
206
+ const ciText = _read_all(path.join(repo, '.github', 'workflows'));
207
+ const ciGates = new Set(extract_gates(ciText));
208
+ // A workflow may reach a gate through a task, so expand those too.
209
+ for (const t of extract_tasks(ciText)) {
210
+ for (const g of local_closure([t], tasks)) ciGates.add(g);
211
+ }
212
+
213
+ const localGates = local_closure(LOCAL_ROOTS, tasks);
214
+ if (fs.existsSync(HOOK)) {
215
+ const hook = fs.readFileSync(HOOK, 'utf-8');
216
+ for (const g of extract_gates(hook)) localGates.add(g);
217
+ for (const t of extract_tasks(hook)) {
218
+ for (const g of local_closure([t], tasks)) localGates.add(g);
219
+ }
220
+ }
221
+
222
+ const declaredCi = new Set(mf.ci_only.map((d) => d.id));
223
+ const declaredLocal = new Set(mf.local_only.map((d) => d.id));
224
+
225
+ const undeclared_ci_only = [...ciGates].filter((g) => !localGates.has(g) && !declaredCi.has(g)).sort();
226
+ const undeclared_local_only = [...localGates].filter((g) => !ciGates.has(g) && !declaredLocal.has(g)).sort();
227
+ // A declaration for a gate that is now on both sides is stale — it grants an
228
+ // exemption nothing needs, and the next reader trusts it.
229
+ const stale_declarations = [
230
+ ...[...declaredCi].filter((g) => localGates.has(g) && ciGates.has(g)),
231
+ ...[...declaredLocal].filter((g) => localGates.has(g) && ciGates.has(g)),
232
+ ].sort();
233
+
234
+ return {
235
+ ci_gates: [...ciGates].sort(),
236
+ local_gates: [...localGates].sort(),
237
+ undeclared_ci_only,
238
+ undeclared_local_only,
239
+ stale_declarations,
240
+ };
241
+ }
242
+
243
+ export function main(argv: readonly string[] = process.argv.slice(2)): number {
244
+ const wantJson = argv.includes('--format') && argv[argv.indexOf('--format') + 1] === 'json';
245
+ let mf: Manifest;
246
+ try {
247
+ mf = load_manifest();
248
+ } catch (e) {
249
+ process.stderr.write(`❌ ci-local-parity manifest: ${(e as Error).message}\n`);
250
+ return 2;
251
+ }
252
+ const r = analyse(REPO, mf);
253
+
254
+ if (wantJson) {
255
+ process.stdout.write(`${JSON.stringify({ generated_by: 'check_ci_local_parity', ...r }, null, 2)}\n`);
256
+ }
257
+
258
+ // Emitted on every path, including failure — a gate with findings must still
259
+ // report what it inspected.
260
+ process.stderr.write(`scanned: ${String(r.ci_gates.length + r.local_gates.length)}\n`);
261
+
262
+ let failed = false;
263
+ if (r.undeclared_ci_only.length > 0) {
264
+ failed = true;
265
+ process.stdout.write(
266
+ `❌ ${String(r.undeclared_ci_only.length)} gate(s) run in CI but are unreachable locally:\n`,
267
+ );
268
+ for (const g of r.undeclared_ci_only) process.stdout.write(` - ${g}\n`);
269
+ process.stdout.write(
270
+ "\n Either wire it into the `task ci` chain, or declare it under `ci_only:` in\n" +
271
+ ' src/config/ci-local-parity.yml with the reason it cannot run locally.\n' +
272
+ ' Undeclared, it means a contributor discovers this failure only after pushing.\n',
273
+ );
274
+ }
275
+ if (r.undeclared_local_only.length > 0) {
276
+ failed = true;
277
+ process.stdout.write(
278
+ `❌ ${String(r.undeclared_local_only.length)} gate(s) run locally but in no workflow:\n`,
279
+ );
280
+ for (const g of r.undeclared_local_only) process.stdout.write(` - ${g}\n`);
281
+ process.stdout.write(
282
+ '\n Prefer adding it to a workflow — this is the direction that let real defects\n' +
283
+ ' merge (16 stale index rows reached main behind a local-only check-index).\n' +
284
+ ' If remote enforcement is genuinely not wanted, declare it under `local_only:`.\n',
285
+ );
286
+ }
287
+ if (r.stale_declarations.length > 0) {
288
+ failed = true;
289
+ process.stdout.write(
290
+ `❌ ${String(r.stale_declarations.length)} stale declaration(s) — now on BOTH sides, so the exemption is dead:\n`,
291
+ );
292
+ for (const g of r.stale_declarations) process.stdout.write(` - ${g}\n`);
293
+ }
294
+
295
+ if (!failed) {
296
+ process.stdout.write(
297
+ `✅ CI ↔ local parity: ${String(r.ci_gates.length)} CI gate(s), ${String(r.local_gates.length)} local, ` +
298
+ `${String(mf.ci_only.length)} declared CI-only, ${String(mf.local_only.length)} declared local-only.\n`,
299
+ );
300
+ }
301
+ return failed ? 1 : 0;
302
+ }
303
+
304
+ function _isCliEntry(): boolean {
305
+ if (process.argv[1] === undefined) return false;
306
+ const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
307
+ if (import.meta.url === argvUrl) return true;
308
+ try {
309
+ return fs.realpathSync(fileURLToPath(import.meta.url)) === fs.realpathSync(path.resolve(process.argv[1]));
310
+ } catch {
311
+ return false;
312
+ }
313
+ }
314
+
315
+ if (_isCliEntry()) {
316
+ process.exit(main());
317
+ }