@event4u/agent-config 7.5.0 → 8.1.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 (429) hide show
  1. package/.claude-plugin/marketplace.json +8 -1
  2. package/AGENTS.md +9 -9
  3. package/CHANGELOG.md +317 -260
  4. package/README.md +35 -5
  5. package/dist/agent-src/commands/analytics/prune.md +1 -1
  6. package/dist/agent-src/commands/analytics/show.md +1 -1
  7. package/dist/agent-src/commands/analyze/decision.md +2 -2
  8. package/dist/agent-src/commands/analyze/incident.md +2 -2
  9. package/dist/agent-src/commands/analyze/near-miss.md +2 -2
  10. package/dist/agent-src/commands/analyze/postmortem.md +2 -2
  11. package/dist/agent-src/commands/analyze/premortem.md +2 -2
  12. package/dist/agent-src/commands/cost-report.md +25 -0
  13. package/dist/agent-src/commands/evals/analyze.json +30 -0
  14. package/dist/agent-src/commands/evals/mission-upgrade.json +30 -0
  15. package/dist/agent-src/commands/implement-ticket.md +1 -1
  16. package/dist/agent-src/commands/knowledge/forget.md +1 -1
  17. package/dist/agent-src/commands/knowledge/ingest.md +1 -1
  18. package/dist/agent-src/commands/knowledge/list.md +1 -1
  19. package/dist/agent-src/commands/memory/load.md +12 -11
  20. package/dist/agent-src/commands/memory/promote.md +30 -0
  21. package/dist/agent-src/commands/memory/propose.md +16 -2
  22. package/dist/agent-src/commands/mission/upgrade.md +1 -1
  23. package/dist/agent-src/commands/module/explore.md +11 -7
  24. package/dist/agent-src/commands/optimize-project.md +243 -0
  25. package/dist/agent-src/commands/optimize.md +5 -0
  26. package/dist/agent-src/commands/pr/create.md +37 -8
  27. package/dist/agent-src/commands/prediction-pool.md +2 -2
  28. package/dist/agent-src/commands/profile/activate.md +3 -3
  29. package/dist/agent-src/commands/profile/deactivate.md +2 -2
  30. package/dist/agent-src/commands/profile/show.md +3 -3
  31. package/dist/agent-src/commands/research/deep.md +5 -0
  32. package/dist/agent-src/commands/research/report.md +2 -1
  33. package/dist/agent-src/commands/roadmap/create.md +88 -10
  34. package/dist/agent-src/commands/roadmap/materialize.md +1 -1
  35. package/dist/agent-src/commands/roadmap/process-full.md +15 -2
  36. package/dist/agent-src/commands/roadmap/process-phase.md +18 -6
  37. package/dist/agent-src/commands/roadmap/process-step.md +4 -0
  38. package/dist/agent-src/commands/roadmap.md +1 -1
  39. package/dist/agent-src/commands/security-audit-config.md +1 -1
  40. package/dist/agent-src/commands/sync-agent-settings.md +1 -1
  41. package/dist/agent-src/commands/sync-gitignore/fix.md +42 -6
  42. package/dist/agent-src/commands/team-knowledge/bootstrap.md +106 -0
  43. package/dist/agent-src/commands/team-knowledge/consolidate.md +105 -0
  44. package/dist/agent-src/commands/team-knowledge.md +64 -0
  45. package/dist/agent-src/contexts/authority/commit-mechanics.md +8 -0
  46. package/dist/agent-src/contexts/authority/destructive-mechanics.md +11 -0
  47. package/dist/agent-src/contexts/authority/scope-mechanics.md +25 -0
  48. package/dist/agent-src/contexts/communication/rules-auto/reply-close-mechanics.md +43 -0
  49. package/dist/agent-src/contexts/contracts/agents-md-anatomy.md +1 -1
  50. package/dist/agent-src/contexts/contracts/artifact-engagement-flow.md +2 -2
  51. package/dist/agent-src/contexts/contracts/frugality-charter.md +1 -0
  52. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +14 -4
  53. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +11 -0
  54. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +32 -8
  55. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +107 -0
  56. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +71 -15
  57. package/dist/agent-src/contexts/execution/subagent-steering.md +41 -1
  58. package/dist/agent-src/contexts/override-system.md +1 -1
  59. package/dist/agent-src/personas/brand-strategist.md +0 -1
  60. package/dist/agent-src/personas/data-integrity.md +66 -0
  61. package/dist/agent-src/personas/design-director.md +0 -1
  62. package/dist/agent-src/personas/performance-engineer.md +66 -0
  63. package/dist/agent-src/personas/production-validator.md +73 -0
  64. package/dist/agent-src/rules/agent-authority.md +3 -4
  65. package/dist/agent-src/rules/analysis-skill-routing.md +3 -5
  66. package/dist/agent-src/rules/architecture.md +2 -4
  67. package/dist/agent-src/rules/artifact-drafting-protocol.md +35 -6
  68. package/dist/agent-src/rules/artifact-engagement-recording.md +2 -4
  69. package/dist/agent-src/rules/ask-when-uncertain.md +10 -14
  70. package/dist/agent-src/rules/augment-edit-discipline.md +3 -5
  71. package/dist/agent-src/rules/autonomous-execution.md +3 -5
  72. package/dist/agent-src/rules/brand-consistency.md +3 -5
  73. package/dist/agent-src/rules/brand-source-of-truth.md +3 -5
  74. package/dist/agent-src/rules/cli-output-handling.md +4 -6
  75. package/dist/agent-src/rules/command-suggestion-policy.md +3 -5
  76. package/dist/agent-src/rules/commit-conventions.md +3 -5
  77. package/dist/agent-src/rules/commit-policy.md +18 -10
  78. package/dist/agent-src/rules/content-quoting-floor.md +88 -0
  79. package/dist/agent-src/rules/context-hygiene.md +3 -5
  80. package/dist/agent-src/rules/copilot-routing.md +4 -6
  81. package/dist/agent-src/rules/decision-revisit-gate.md +120 -0
  82. package/dist/agent-src/rules/delegation-policy.md +10 -6
  83. package/dist/agent-src/rules/design-fidelity.md +3 -5
  84. package/dist/agent-src/rules/devcontainer-routing.md +4 -6
  85. package/dist/agent-src/rules/direct-answers.md +13 -17
  86. package/dist/agent-src/rules/docker-commands.md +3 -5
  87. package/dist/agent-src/rules/domain-adoption-policy.md +3 -5
  88. package/dist/agent-src/rules/domain-safety-disclaimer.md +3 -5
  89. package/dist/agent-src/rules/domain-safety-pii.md +3 -5
  90. package/dist/agent-src/rules/domain-safety-retention.md +3 -5
  91. package/dist/agent-src/rules/downstream-changes.md +3 -4
  92. package/dist/agent-src/rules/engineering-safety-floor.md +3 -5
  93. package/dist/agent-src/rules/external-reference-deep-dive.md +3 -5
  94. package/dist/agent-src/rules/fast-path-marker-visibility.md +3 -5
  95. package/dist/agent-src/rules/finance-safety-floor.md +3 -6
  96. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +3 -5
  97. package/dist/agent-src/rules/git-history-discipline.md +3 -5
  98. package/dist/agent-src/rules/guidelines.md +2 -4
  99. package/dist/agent-src/rules/icon-consistency.md +3 -5
  100. package/dist/agent-src/rules/image-likeness-and-rights.md +3 -5
  101. package/dist/agent-src/rules/improve-before-implement.md +5 -5
  102. package/dist/agent-src/rules/invite-challenge.md +3 -5
  103. package/dist/agent-src/rules/language-and-tone.md +13 -15
  104. package/dist/agent-src/rules/laravel-routing.md +3 -5
  105. package/dist/agent-src/rules/laravel-translations.md +3 -5
  106. package/dist/agent-src/rules/legal-safety-floor.md +3 -5
  107. package/dist/agent-src/rules/lethal-trifecta-guard.md +3 -5
  108. package/dist/agent-src/rules/linked-projects-onboarding-gate.md +4 -7
  109. package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +3 -5
  110. package/dist/agent-src/rules/markdown-safe-codeblocks.md +2 -4
  111. package/dist/agent-src/rules/media-governance-routing.md +3 -5
  112. package/dist/agent-src/rules/media-sync-ground-truth.md +3 -5
  113. package/dist/agent-src/rules/minimal-safe-diff.md +5 -5
  114. package/dist/agent-src/rules/missing-tool-handling.md +3 -5
  115. package/dist/agent-src/rules/model-recommendation.md +4 -6
  116. package/dist/agent-src/rules/no-attribution-footers.md +3 -5
  117. package/dist/agent-src/rules/no-cheap-questions.md +5 -8
  118. package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +3 -6
  119. package/dist/agent-src/rules/no-pr-progress-comments.md +3 -6
  120. package/dist/agent-src/rules/no-roadmap-references.md +3 -5
  121. package/dist/agent-src/rules/non-destructive-by-default.md +11 -13
  122. package/dist/agent-src/rules/notes-first-reasoning.md +3 -5
  123. package/dist/agent-src/rules/onboarding-gate.md +4 -6
  124. package/dist/agent-src/rules/output-discipline.md +3 -5
  125. package/dist/agent-src/rules/package-ci-checks.md +3 -5
  126. package/dist/agent-src/rules/persona-governance.md +2 -4
  127. package/dist/agent-src/rules/php-coding.md +3 -5
  128. package/dist/agent-src/rules/preservation-guard.md +2 -4
  129. package/dist/agent-src/rules/provider-lifecycle-discipline.md +3 -5
  130. package/dist/agent-src/rules/reviewer-awareness.md +5 -6
  131. package/dist/agent-src/rules/roadmap-ci-steps-policy.md +3 -5
  132. package/dist/agent-src/rules/roadmap-progress-sync.md +5 -5
  133. package/dist/agent-src/rules/role-mode-adherence.md +2 -4
  134. package/dist/agent-src/rules/rule-type-governance.md +3 -5
  135. package/dist/agent-src/rules/runtime-safety.md +2 -4
  136. package/dist/agent-src/rules/scope-control.md +10 -11
  137. package/dist/agent-src/rules/security-sensitive-stop.md +4 -5
  138. package/dist/agent-src/rules/size-enforcement.md +2 -4
  139. package/dist/agent-src/rules/skill-improvement-trigger.md +3 -5
  140. package/dist/agent-src/rules/skill-quality.md +3 -5
  141. package/dist/agent-src/rules/slash-command-routing-policy.md +3 -5
  142. package/dist/agent-src/rules/source-confidentiality.md +3 -5
  143. package/dist/agent-src/rules/source-discovery-gate.md +3 -5
  144. package/dist/agent-src/rules/source-of-truth.md +3 -5
  145. package/dist/agent-src/rules/strategy-safety-floor.md +3 -5
  146. package/dist/agent-src/rules/symfony-routing.md +4 -6
  147. package/dist/agent-src/rules/telegraph-speak.md +4 -5
  148. package/dist/agent-src/rules/think-before-action.md +7 -4
  149. package/dist/agent-src/rules/token-budget-discipline.md +29 -5
  150. package/dist/agent-src/rules/token-efficiency.md +3 -5
  151. package/dist/agent-src/rules/token-optimizer-maintenance.md +3 -5
  152. package/dist/agent-src/rules/tool-safety.md +2 -4
  153. package/dist/agent-src/rules/ui-audit-gate.md +3 -6
  154. package/dist/agent-src/rules/untrusted-input-defense.md +3 -5
  155. package/dist/agent-src/rules/upstream-proposal.md +4 -6
  156. package/dist/agent-src/rules/user-interaction.md +7 -5
  157. package/dist/agent-src/rules/user-interrupt-priority.md +17 -8
  158. package/dist/agent-src/rules/verify-before-complete.md +12 -22
  159. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +3 -3
  160. package/dist/agent-src/scripts/update_roadmap_progress.ts +197 -7
  161. package/dist/agent-src/skills/adr-create/SKILL.md +48 -42
  162. package/dist/agent-src/skills/agent-docs-writing/SKILL.md +18 -0
  163. package/dist/agent-src/skills/agent-security-review/SKILL.md +1 -1
  164. package/dist/agent-src/skills/ai-council/SKILL.md +14 -1
  165. package/dist/agent-src/skills/blameless-post-mortem/SKILL.md +0 -3
  166. package/dist/agent-src/skills/brand/SKILL.md +1 -1
  167. package/dist/agent-src/skills/brand-identity/SKILL.md +3 -3
  168. package/dist/agent-src/skills/brand-strategy/SKILL.md +1 -1
  169. package/dist/agent-src/skills/brand-to-tokens/SKILL.md +3 -3
  170. package/dist/agent-src/skills/canvas-design/SKILL.md +6 -0
  171. package/dist/agent-src/skills/check-refs/SKILL.md +7 -4
  172. package/dist/agent-src/skills/code-review/SKILL.md +1 -0
  173. package/dist/agent-src/skills/complexity-first-planning/SKILL.md +6 -5
  174. package/dist/agent-src/skills/condense-memory/SKILL.md +11 -11
  175. package/dist/agent-src/skills/context-document/SKILL.md +17 -0
  176. package/dist/agent-src/skills/corpus-grounding/SKILL.md +3 -3
  177. package/dist/agent-src/skills/decision-record/SKILL.md +6 -0
  178. package/dist/agent-src/skills/decision-review/SKILL.md +5 -3
  179. package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +6 -1
  180. package/dist/agent-src/skills/design-intelligence/SKILL.md +5 -2
  181. package/dist/agent-src/skills/design-intelligence/references/design-languages.md +1 -1
  182. package/dist/agent-src/skills/design-tokens/SKILL.md +10 -4
  183. package/dist/agent-src/skills/design-variations/SKILL.md +127 -0
  184. package/dist/agent-src/skills/design-variations/evals/triggers.json +17 -0
  185. package/dist/agent-src/skills/emit-tickets/SKILL.md +4 -4
  186. package/dist/agent-src/skills/fe-design/SKILL.md +20 -0
  187. package/dist/agent-src/skills/html-deck/SKILL.md +123 -0
  188. package/dist/agent-src/skills/html-deck/evals/triggers.json +17 -0
  189. package/dist/agent-src/skills/html-deck/templates/deck-shell.html +77 -0
  190. package/dist/agent-src/skills/judge-code-quality/SKILL.md +1 -0
  191. package/dist/agent-src/skills/laravel/SKILL.md +0 -1
  192. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +46 -0
  193. package/dist/agent-src/skills/lint-skills/SKILL.md +6 -6
  194. package/dist/agent-src/skills/md-language-check/SKILL.md +3 -3
  195. package/dist/agent-src/skills/memory-consolidation/SKILL.md +66 -1
  196. package/dist/agent-src/skills/migration-architect/SKILL.md +1 -0
  197. package/dist/agent-src/skills/module-detect-on-the-fly/SKILL.md +2 -2
  198. package/dist/agent-src/skills/performance-analysis/SKILL.md +2 -0
  199. package/dist/agent-src/skills/prediction-pool-optimizer/SKILL.md +4 -4
  200. package/dist/agent-src/skills/premortem/SKILL.md +0 -3
  201. package/dist/agent-src/skills/project-analysis-core/SKILL.md +16 -0
  202. package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +3 -1
  203. package/dist/agent-src/skills/release-comms/SKILL.md +46 -45
  204. package/dist/agent-src/skills/roadmap-management/SKILL.md +21 -0
  205. package/dist/agent-src/skills/roadmap-writing/SKILL.md +32 -2
  206. package/dist/agent-src/skills/root-cause-frameworks/SKILL.md +0 -3
  207. package/dist/agent-src/skills/security-audit/SKILL.md +1 -0
  208. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +4 -0
  209. package/dist/agent-src/skills/source-discovery/SKILL.md +22 -3
  210. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +33 -14
  211. package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +11 -0
  212. package/dist/agent-src/skills/subagent-orchestration/prompts/do-in-steps.md +8 -0
  213. package/dist/agent-src/skills/systematic-debugging/SKILL.md +29 -0
  214. package/dist/agent-src/skills/threat-modeling/SKILL.md +2 -2
  215. package/dist/agent-src/skills/typography-system/SKILL.md +2 -2
  216. package/dist/agent-src/skills/verify-completion-evidence/SKILL.md +2 -0
  217. package/dist/agent-src/skills/wireframe/SKILL.md +118 -0
  218. package/dist/agent-src/skills/wireframe/evals/triggers.json +17 -0
  219. package/dist/agent-src/templates/agent-settings.md +22 -1
  220. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  221. package/dist/agent-src/templates/command.md +2 -2
  222. package/dist/agent-src/templates/contexts/knowledge-pages.md +116 -0
  223. package/dist/agent-src/templates/hooks/pre-commit-frontmatter +1 -1
  224. package/dist/agent-src/templates/roadmaps.md +70 -2
  225. package/dist/agent-src/templates/rule.md +1 -1
  226. package/dist/agent-src/templates/scripts/README.md +3 -3
  227. package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +109 -0
  228. package/dist/agent-src/templates/tickets.md +8 -8
  229. package/dist/cli/commands/recordTriggerEval.test.js +1 -1
  230. package/dist/cli/commands/recordTriggerEval.test.js.map +1 -1
  231. package/dist/cli/initRouting.js +4 -2
  232. package/dist/cli/initRouting.js.map +1 -1
  233. package/dist/cli/registry.js +1 -0
  234. package/dist/cli/registry.js.map +1 -1
  235. package/dist/discovery/deprecation-report.md +1 -1
  236. package/dist/discovery/discovery-manifest.json +718 -240
  237. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  238. package/dist/discovery/discovery-manifest.summary.md +8 -8
  239. package/dist/discovery/orphan-report.md +1 -1
  240. package/dist/discovery/packs.json +43 -28
  241. package/dist/discovery/trust-report.md +12 -11
  242. package/dist/discovery/workspaces.json +29 -18
  243. package/dist/install/preflight.js +173 -0
  244. package/dist/install/preflight.js.map +1 -0
  245. package/dist/mcp/registry-manifest.json +4 -4
  246. package/dist/router.json +1 -1
  247. package/dist/server/routes/settings.js +4 -0
  248. package/dist/server/routes/settings.js.map +1 -1
  249. package/dist/server/schemas/settings.js +3 -1
  250. package/dist/server/schemas/settings.js.map +1 -1
  251. package/docs/CLAIMS.md +108 -0
  252. package/docs/MIGRATION.md +3 -3
  253. package/docs/architecture.md +5 -5
  254. package/docs/archive/CHANGELOG-pre-8.0.0.md +301 -0
  255. package/docs/benchmark.md +133 -2
  256. package/docs/benchmark.pinned.yml +31 -0
  257. package/docs/capability-matrix.md +1 -0
  258. package/docs/catalog.md +70 -60
  259. package/docs/command-flows.md +15 -3
  260. package/docs/comparison.yaml +35 -0
  261. package/docs/contracts/agents-layout.md +148 -0
  262. package/docs/contracts/brand-token-consumption.md +5 -0
  263. package/docs/contracts/capability-boundary.md +5 -0
  264. package/docs/contracts/command-category-governance.md +5 -0
  265. package/docs/contracts/command-clusters.md +1 -0
  266. package/docs/contracts/command-surface-tiers.md +1 -1
  267. package/docs/contracts/conformance.md +84 -0
  268. package/docs/contracts/creative-pack-boundary.md +5 -0
  269. package/docs/contracts/discovery-manifest.schema.json +5 -4
  270. package/docs/contracts/file-ownership-matrix.json +4605 -985
  271. package/docs/contracts/governance-enforcement-projection.md +5 -0
  272. package/docs/contracts/gui-wizard.md +1 -1
  273. package/docs/contracts/hook-architecture-v1.md +2 -2
  274. package/docs/contracts/implement-ticket-flow.md +1 -1
  275. package/docs/contracts/kernel-membership.md +13 -0
  276. package/docs/contracts/mcp-tool-inventory.md +23 -23
  277. package/docs/contracts/no-runtime-boundary.md +6 -1
  278. package/docs/contracts/review-lens-schema.md +5 -0
  279. package/docs/contracts/rule-router.md +102 -8
  280. package/docs/contracts/skill-bundled-assets.md +1 -1
  281. package/docs/contracts/skill-dry-run.md +1 -1
  282. package/docs/contracts/subagent-boundary.md +5 -0
  283. package/docs/contracts/ticket-bundle-format.md +9 -4
  284. package/docs/contracts/tier-3-contrib-plugin.md +2 -2
  285. package/docs/contracts/write-engine.md +3 -0
  286. package/docs/customization.md +87 -15
  287. package/docs/decisions/ADR-107-legal-domain-pack-adoption.md +1 -1
  288. package/docs/decisions/ADR-109-subagent-v1-contract.md +246 -0
  289. package/docs/decisions/ADR-110-discipline-profile-resolution-locus.md +105 -0
  290. package/docs/decisions/INDEX.md +2 -0
  291. package/docs/distribution/awesome-list-submission.md +46 -0
  292. package/docs/distribution/launch-story-draft.md +58 -0
  293. package/docs/end-to-end-walkthroughs.md +2 -2
  294. package/docs/getting-started.md +2 -2
  295. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +24 -0
  296. package/docs/guidelines/agent-infra/corpus-grounding-authoring.md +1 -1
  297. package/docs/guidelines/agent-infra/linked-projects-onboarding-gate.md +2 -2
  298. package/docs/guidelines/agent-infra/missing-tool-handling.md +3 -3
  299. package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
  300. package/docs/guidelines/augment-portability-patterns.md +1 -1
  301. package/docs/guidelines/code-clarity.md +19 -0
  302. package/docs/guidelines/design-antipatterns-triggers.json +2 -1
  303. package/docs/guidelines/design-antipatterns.md +10 -1
  304. package/docs/guidelines/design-modes.md +6 -0
  305. package/docs/guidelines/php/general.md +9 -1
  306. package/docs/guidelines/php/php-coding-patterns.md +7 -0
  307. package/docs/guides/cross-repo-retrieval.md +1 -1
  308. package/docs/guides/frontend-design-corpus-refresh.md +2 -2
  309. package/docs/guides/local-analytics.md +4 -4
  310. package/docs/guides/skill-discovery.md +1 -1
  311. package/docs/guides/skill-preview.md +1 -1
  312. package/docs/hook-payload-capture.md +6 -6
  313. package/docs/install-friction-report.md +66 -0
  314. package/docs/installation.md +1 -1
  315. package/docs/maintainers/optional-media-deps.md +50 -0
  316. package/docs/mcp-server.md +11 -12
  317. package/docs/media/proof-demo.cast +14 -0
  318. package/docs/media/proof-demo.gif +0 -0
  319. package/docs/migration/consumer-template-consumption-model.md +1 -1
  320. package/docs/migration/divergences/bench-stats-float-precision.md +1 -1
  321. package/docs/migration/node-floor.md +1 -1
  322. package/docs/migration/yaml-roundtrip-spike.md +1 -1
  323. package/docs/personas.md +16 -5
  324. package/docs/positioning-evidence.md +86 -0
  325. package/docs/proof.md +86 -0
  326. package/docs/skills-catalog.md +1 -1
  327. package/docs/troubleshooting.md +8 -8
  328. package/docs/wedge/production-validator/README.md +57 -0
  329. package/docs/wedge/production-validator/production-validator.md +56 -0
  330. package/docs/wizard.md +2 -2
  331. package/package.json +1 -1
  332. package/src/config/agent-settings.template.yml +59 -4
  333. package/src/config/agents-paths.yml +254 -0
  334. package/src/config/budgets.yml +16 -0
  335. package/src/config/discovery/packs.yml +1 -0
  336. package/src/config/discovery/unassigned-artefacts.yml +2 -0
  337. package/src/config/gitignore-block.txt +25 -0
  338. package/src/config/host-capabilities.yml +31 -0
  339. package/src/config/profiles/balanced.ini +4 -0
  340. package/src/config/profiles/full.ini +4 -0
  341. package/src/config/profiles/minimal.ini +4 -0
  342. package/src/scripts/_cli/cmd_conformance.ts +716 -0
  343. package/src/scripts/_cli/cmd_doctor.ts +23 -2
  344. package/src/scripts/_cli/cmd_fleet.ts +401 -0
  345. package/src/scripts/_cli/cmd_preflight.ts +159 -0
  346. package/src/scripts/_dispatch.bash +10 -0
  347. package/src/scripts/_lib/knowledge_events.ts +193 -0
  348. package/src/scripts/_lib/subagent_steering.ts +115 -3
  349. package/src/scripts/_lib/text_similarity.ts +75 -0
  350. package/src/scripts/ai-video/test-pipeline.sh +1 -1
  351. package/src/scripts/ai_council/clients.ts +19 -3
  352. package/src/scripts/append_contested.ts +112 -0
  353. package/src/scripts/audit_auto_rules.ts +11 -1
  354. package/src/scripts/audit_mcp_tools.ts +25 -11
  355. package/src/scripts/bench_ab_v2_run.ts +527 -40
  356. package/src/scripts/bench_ab_v2_stats.ts +6 -0
  357. package/src/scripts/bench_matrix.ts +266 -0
  358. package/src/scripts/bootstrap_knowledge.ts +267 -0
  359. package/src/scripts/build_discovery_manifest.ts +42 -2
  360. package/src/scripts/build_proof.ts +214 -0
  361. package/src/scripts/check_always_budget.ts +3 -0
  362. package/src/scripts/check_augment_description_cap.ts +2 -2
  363. package/src/scripts/check_claims.ts +270 -0
  364. package/src/scripts/check_comparison.ts +79 -0
  365. package/src/scripts/check_generated_artefact_headers.ts +109 -0
  366. package/src/scripts/check_generator_output_coverage.ts +142 -0
  367. package/src/scripts/check_gitignore_freshness.ts +127 -0
  368. package/src/scripts/check_knowledge_pages.ts +210 -0
  369. package/src/scripts/check_knowledge_sharing.ts +162 -0
  370. package/src/scripts/check_media_deps.ts +91 -0
  371. package/src/scripts/check_memory_contradiction.ts +280 -0
  372. package/src/scripts/check_memory_similarity.ts +134 -0
  373. package/src/scripts/check_quality_regression.ts +56 -10
  374. package/src/scripts/check_references.ts +3 -1
  375. package/src/scripts/check_release_pr_shape.ts +4 -0
  376. package/src/scripts/check_site_links.ts +135 -0
  377. package/src/scripts/check_skill_gaps.ts +99 -0
  378. package/src/scripts/check_token_quality_golden.ts +197 -11
  379. package/src/scripts/check_tracked_but_ignored.ts +67 -0
  380. package/src/scripts/cluster_near_miss_patterns.ts +0 -0
  381. package/src/scripts/compile_router.ts +30 -3
  382. package/src/scripts/condense.ts +350 -14
  383. package/src/scripts/consolidate_knowledge_events.ts +192 -0
  384. package/src/scripts/degrade_to_pointer.ts +136 -0
  385. package/src/scripts/design_slop_rules.test.ts +15 -0
  386. package/src/scripts/design_slop_rules.ts +28 -0
  387. package/src/scripts/emit_knowledge_event.ts +158 -0
  388. package/src/scripts/export_replay_corpus.ts +187 -0
  389. package/src/scripts/external_sources_denylist.json +7 -2
  390. package/src/scripts/fold_intake.ts +281 -0
  391. package/src/scripts/generate_capability_matrix.ts +9 -1
  392. package/src/scripts/generate_knowledge_index.ts +222 -0
  393. package/src/scripts/hook_manifest.yaml +26 -14
  394. package/src/scripts/hooks/dispatch_hook.ts +18 -0
  395. package/src/scripts/hot_context_hook.ts +372 -0
  396. package/src/scripts/install +47 -0
  397. package/src/scripts/install-hooks.sh +17 -0
  398. package/src/scripts/inventory_meta_layers.ts +11 -0
  399. package/src/scripts/janitor.ts +258 -0
  400. package/src/scripts/lint_agents_layout.ts +74 -15
  401. package/src/scripts/lint_bench_ab.ts +4 -1
  402. package/src/scripts/lint_featured_skills.ts +0 -0
  403. package/src/scripts/lint_framework_leakage_allowlist.json +26 -3
  404. package/src/scripts/lint_knowledge_scale.ts +250 -0
  405. package/src/scripts/lint_legal_pack.ts +67 -0
  406. package/src/scripts/lint_persona_governance.ts +8 -3
  407. package/src/scripts/lint_regression.ts +15 -0
  408. package/src/scripts/lint_roadmap_blockers.ts +202 -0
  409. package/src/scripts/lint_roadmap_complexity.ts +81 -2
  410. package/src/scripts/lint_subagent_determinism.ts +125 -0
  411. package/src/scripts/measure_augment_budget.ts +46 -6
  412. package/src/scripts/measure_patterns.ts +4 -3
  413. package/src/scripts/measure_skill_reduction.ts +6 -6
  414. package/src/scripts/migration_status.ts +6 -2
  415. package/src/scripts/mine_missing_guardrails.ts +189 -0
  416. package/src/scripts/parity/phase_gate.ts +1 -1
  417. package/src/scripts/parity/replay.ts +21 -0
  418. package/src/scripts/project_thin_rules.ts +120 -16
  419. package/src/scripts/release.ts +39 -1
  420. package/src/scripts/render_benchmark_composite.ts +378 -0
  421. package/src/scripts/roadmap_progress_hook.ts +101 -43
  422. package/src/scripts/schemas/skill.schema.json +27 -0
  423. package/src/scripts/schemas/subagent.schema.json +106 -0
  424. package/src/scripts/skill_linter.ts +1 -0
  425. package/src/scripts/smoke/kernel.sh +5 -4
  426. package/src/scripts/surface-tiers.yml +1 -0
  427. package/src/scripts/sync_gitignore.ts +4 -0
  428. package/src/scripts/update_skill_candidates.ts +172 -0
  429. package/src/scripts/validate_frontmatter.ts +1 -0
@@ -0,0 +1,716 @@
1
+ /**
2
+ * `agent-config conformance` — consumer conformance contract
3
+ * (road-to-flow-learnings Phase 0).
4
+ *
5
+ * Thin orchestrator over `cmd_doctor`'s exported check runner plus five
6
+ * consumer-facing checks that answer ONE question deterministically:
7
+ * "is agent-config installed AND firing in this repo?"
8
+ *
9
+ * (a) txlog-clean — install log tail carries no abandoned run
10
+ * (b) router-pointers — dist/router.json ids + routes_to resolve on disk
11
+ * (c) hook-dispatcher — dispatcher answers synthetic session_start/stop
12
+ * (d) lean-projection — lean_projection.mode matches projected artifacts
13
+ * (e) host-manifest — subagents.host_capabilities parses strictly
14
+ *
15
+ * All checks are deterministic — no LLM, no network. Exit contract:
16
+ * 0 = every check ok/skipped (warns allowed) and doctor --ci green
17
+ * 1 = at least one check failed (or doctor drift / doctor check fail)
18
+ * 2 = environment unresolvable (no project root, internal error)
19
+ *
20
+ * Every run appends ONE JSONL report line (txlog shape) to
21
+ * `~/.event4u/agent-config/conformance-log.jsonl` (override:
22
+ * `AGENT_CONFIG_CONFORMANCE_LOG`) so fleet runs can aggregate results.
23
+ *
24
+ * Contract page: docs/contracts/conformance.md
25
+ */
26
+
27
+ import * as fs from 'node:fs';
28
+ import * as os from 'node:os';
29
+ import * as path from 'node:path';
30
+ import process from 'node:process';
31
+ import { spawnSync } from 'node:child_process';
32
+ import { fileURLToPath, pathToFileURL } from 'node:url';
33
+
34
+ import * as YAML from 'yaml';
35
+
36
+ import * as installed_tools from '../_lib/installed_tools.js';
37
+ import { atomicAppendLine } from '../../install/atomic.js';
38
+ import { readRecentEntries } from '../../install/txlog.js';
39
+ import { detectToolPresence } from '../../install/detect.js';
40
+ import {
41
+ _classify,
42
+ _collect_manifest_entries,
43
+ _foreign_records,
44
+ _jsonDumpsIndentAscii,
45
+ _resolve_project_root,
46
+ _run_checks,
47
+ _run_checks_no_manifest,
48
+ _scan_foreign,
49
+ ArgparseExit,
50
+ BRIDGE_MARKER_RELATIVE,
51
+ STATUS_SYMBOLS,
52
+ } from './cmd_doctor.js';
53
+
54
+ type Dict = Record<string, unknown>;
55
+
56
+ const _HERE = fileURLToPath(import.meta.url);
57
+
58
+ /** Package root — two levels above `src/scripts/_cli/`. */
59
+ export const PACKAGE_ROOT = path.resolve(path.dirname(_HERE), '..', '..', '..');
60
+
61
+ /** Ordered registry of conformance check identifiers. */
62
+ export const CONFORMANCE_CHECK_IDS = [
63
+ 'txlog-clean',
64
+ 'router-pointers',
65
+ 'hook-dispatcher',
66
+ 'lean-projection',
67
+ 'host-manifest',
68
+ ] as const;
69
+
70
+ /** Marker emitted by `project_thin_rules.thin_entry()` — the thin-stub signature. */
71
+ export const THIN_STUB_MARKER = 'Routed rule — load the body on trigger-match';
72
+
73
+ function print(s = ''): void {
74
+ process.stdout.write(`${s}\n`);
75
+ }
76
+
77
+ function eprint(s = ''): void {
78
+ process.stderr.write(`${s}\n`);
79
+ }
80
+
81
+ /** Default JSONL report path (mirrors the install txlog directory). */
82
+ export function conformanceLogPath(): string {
83
+ const override = process.env['AGENT_CONFIG_CONFORMANCE_LOG'];
84
+ if (override && override.trim().length > 0) {
85
+ return override;
86
+ }
87
+ return path.join(os.homedir(), '.event4u', 'agent-config', 'conformance-log.jsonl');
88
+ }
89
+
90
+ /** Default install txlog path (kept in sync with `src/install/txlog.ts` docs). */
91
+ export function installLogPath(): string {
92
+ const override = process.env['AGENT_CONFIG_INSTALL_LOG'];
93
+ if (override && override.trim().length > 0) {
94
+ return override;
95
+ }
96
+ return path.join(os.homedir(), '.event4u', 'agent-config', 'install-log.jsonl');
97
+ }
98
+
99
+ // ---------------------------------------------------------------------------
100
+ // Check (a) — txlog tail clean.
101
+ // ---------------------------------------------------------------------------
102
+
103
+ export function _check_txlog_clean(logPath: string = installLogPath()): Dict {
104
+ if (!fs.existsSync(logPath)) {
105
+ return {
106
+ id: 'txlog-clean',
107
+ status: 'ok',
108
+ message: 'no install transaction log — nothing to recover',
109
+ remedy: '',
110
+ };
111
+ }
112
+ const entries = readRecentEntries(logPath);
113
+ if (entries.length === 0) {
114
+ return {
115
+ id: 'txlog-clean',
116
+ status: 'ok',
117
+ message: 'install transaction log is empty',
118
+ remedy: '',
119
+ };
120
+ }
121
+ const last = entries[entries.length - 1] as { kind: string; ts: string; note?: string };
122
+ if (last.kind === 'abort') {
123
+ return {
124
+ id: 'txlog-clean',
125
+ status: 'fail',
126
+ message:
127
+ `install log tail is an abandoned run (abort at ${last.ts}` +
128
+ `${last.note ? `: ${last.note}` : ''})`,
129
+ remedy: 're-run `agent-config init` (recovery reverse-applies the aborted tail)',
130
+ };
131
+ }
132
+ return {
133
+ id: 'txlog-clean',
134
+ status: 'ok',
135
+ message: `install log tail clean (${entries.length} recent entries, last: ${last.kind})`,
136
+ remedy: '',
137
+ };
138
+ }
139
+
140
+ // ---------------------------------------------------------------------------
141
+ // Check (b) — router pointers resolve against the installed package tree.
142
+ // ---------------------------------------------------------------------------
143
+
144
+ /**
145
+ * Map one `routes_to` target (`<kind>:<id>`) to its candidate
146
+ * package-relative paths. The FIRST existing candidate wins.
147
+ *
148
+ * `contract:` has two legitimate homes in the shipped tree: the public
149
+ * contract pages under `docs/contracts/` (per the rule-router contract)
150
+ * and the agent-facing contract contexts under
151
+ * `dist/agent-src/contexts/contracts/` (e.g. artifact-engagement-flow).
152
+ */
153
+ export function routeTargetPaths(target: string): string[] {
154
+ const sep = target.indexOf(':');
155
+ if (sep <= 0) return [];
156
+ const kind = target.slice(0, sep);
157
+ const id = target.slice(sep + 1);
158
+ if (!id) return [];
159
+ switch (kind) {
160
+ case 'skill':
161
+ return [path.join('dist', 'agent-src', 'skills', id, 'SKILL.md')];
162
+ case 'command':
163
+ return [path.join('dist', 'agent-src', 'commands', `${id}.md`)];
164
+ case 'guideline':
165
+ return [path.join('docs', 'guidelines', `${id}.md`)];
166
+ case 'contract':
167
+ return [
168
+ path.join('docs', 'contracts', `${id}.md`),
169
+ path.join('dist', 'agent-src', 'contexts', 'contracts', `${id}.md`),
170
+ ];
171
+ default:
172
+ return [];
173
+ }
174
+ }
175
+
176
+ export function _check_router_pointers(packageRoot: string = PACKAGE_ROOT): Dict {
177
+ const routerPath = path.join(packageRoot, 'dist', 'router.json');
178
+ if (!fs.existsSync(routerPath)) {
179
+ return {
180
+ id: 'router-pointers',
181
+ status: 'fail',
182
+ message: `router index missing: ${routerPath}`,
183
+ remedy: 'reinstall the package (dist/router.json ships with every release)',
184
+ };
185
+ }
186
+ let router: Dict;
187
+ try {
188
+ router = JSON.parse(fs.readFileSync(routerPath, 'utf8')) as Dict;
189
+ } catch (exc) {
190
+ return {
191
+ id: 'router-pointers',
192
+ status: 'fail',
193
+ message: `router index does not parse: ${(exc as Error).message}`,
194
+ remedy: 'reinstall the package — dist/router.json is corrupt',
195
+ };
196
+ }
197
+ const rulesDir = path.join(packageRoot, 'dist', 'agent-src', 'rules');
198
+ const broken: string[] = [];
199
+ let ids = 0;
200
+ let targets = 0;
201
+
202
+ for (const kernelId of (router['kernel'] as string[] | undefined) ?? []) {
203
+ ids += 1;
204
+ if (!fs.existsSync(path.join(rulesDir, `${kernelId}.md`))) {
205
+ broken.push(`kernel:${kernelId} → rules/${kernelId}.md missing`);
206
+ }
207
+ }
208
+ for (const tier of ['tier_1', 'tier_2']) {
209
+ for (const entry of (router[tier] as Dict[] | undefined) ?? []) {
210
+ const ruleId = String(entry['id'] ?? '');
211
+ ids += 1;
212
+ if (!fs.existsSync(path.join(rulesDir, `${ruleId}.md`))) {
213
+ broken.push(`${tier}:${ruleId} → rules/${ruleId}.md missing`);
214
+ }
215
+ for (const target of (entry['routes_to'] as string[] | undefined) ?? []) {
216
+ targets += 1;
217
+ const candidates = routeTargetPaths(String(target));
218
+ if (candidates.length === 0) {
219
+ broken.push(`${ruleId} → unparseable routes_to ${JSON.stringify(target)}`);
220
+ continue;
221
+ }
222
+ if (!candidates.some((rel) => fs.existsSync(path.join(packageRoot, rel)))) {
223
+ broken.push(`${ruleId} → ${target} (${candidates[0]} missing)`);
224
+ }
225
+ }
226
+ }
227
+ }
228
+ if (broken.length > 0) {
229
+ const sample = broken.slice(0, 5).join('; ');
230
+ return {
231
+ id: 'router-pointers',
232
+ status: 'fail',
233
+ message: `${broken.length} unresolved router pointer(s): ${sample}`,
234
+ remedy: 'reinstall the package; if this is a dev tree, run the compile/condense pipeline',
235
+ };
236
+ }
237
+ return {
238
+ id: 'router-pointers',
239
+ status: 'ok',
240
+ message: `router index parses; ${ids} rule ids + ${targets} routes_to targets resolve`,
241
+ remedy: '',
242
+ };
243
+ }
244
+
245
+ // ---------------------------------------------------------------------------
246
+ // Check (c) — hook dispatcher answers synthetic session_start / stop.
247
+ // ---------------------------------------------------------------------------
248
+
249
+ /** Detected platform for the dispatcher smoke — first match wins. */
250
+ export function detectSmokePlatform(projectRoot: string): string {
251
+ const presence = detectToolPresence(projectRoot);
252
+ if (presence.claude) return 'claude';
253
+ if (presence.cursor) return 'cursor';
254
+ if (presence.augment) return 'augment';
255
+ if (presence.windsurf) return 'windsurf';
256
+ if (presence.cline) return 'cline';
257
+ return 'claude';
258
+ }
259
+
260
+ /** Resolve the dispatcher runner: local tsx binary, else `npx tsx`. */
261
+ function dispatcherRunner(packageRoot: string): string[] {
262
+ const localTsx = path.join(packageRoot, 'node_modules', '.bin', 'tsx');
263
+ const script = path.join(packageRoot, 'src', 'scripts', 'hooks', 'dispatch_hook.ts');
264
+ if (fs.existsSync(localTsx)) {
265
+ return [localTsx, script];
266
+ }
267
+ return ['npx', 'tsx', script];
268
+ }
269
+
270
+ export interface DispatcherSmokeOptions {
271
+ /** Full argv override (tests) — payload is still piped on stdin. */
272
+ readonly runner?: readonly string[];
273
+ readonly platform?: string;
274
+ readonly timeoutMs?: number;
275
+ }
276
+
277
+ export function _check_hook_dispatcher(
278
+ projectRoot: string,
279
+ packageRoot: string = PACKAGE_ROOT,
280
+ opts: DispatcherSmokeOptions = {},
281
+ ): Dict {
282
+ const platform = opts.platform ?? detectSmokePlatform(projectRoot);
283
+ const runner = opts.runner ?? dispatcherRunner(packageRoot);
284
+ const results: string[] = [];
285
+ for (const event of ['session_start', 'stop'] as const) {
286
+ const payload = JSON.stringify({
287
+ session_id: 'conformance-smoke',
288
+ cwd: projectRoot,
289
+ platform_hint: platform,
290
+ ...(event === 'stop' ? { stop_reason: 'conformance-smoke' } : { source: 'startup' }),
291
+ });
292
+ const argv = [...runner, '--platform', platform, '--event', event];
293
+ const proc = spawnSync(argv[0] as string, argv.slice(1), {
294
+ input: payload,
295
+ cwd: projectRoot,
296
+ encoding: 'utf8',
297
+ timeout: opts.timeoutMs ?? 30_000,
298
+ });
299
+ if (proc.error) {
300
+ return {
301
+ id: 'hook-dispatcher',
302
+ status: 'fail',
303
+ message: `dispatcher spawn failed for ${event}: ${proc.error.message}`,
304
+ remedy: 'verify the package install (node_modules present) and re-run',
305
+ };
306
+ }
307
+ // Dispatcher exit vocabulary: 0 allow · 1 block · 2 warn. A smoke
308
+ // envelope must never block; allow/warn both count as "firing".
309
+ if (proc.status !== 0 && proc.status !== 2) {
310
+ const tail = (proc.stderr ?? '').trim().split('\n').slice(-2).join(' | ');
311
+ return {
312
+ id: 'hook-dispatcher',
313
+ status: 'fail',
314
+ message: `dispatcher returned exit ${proc.status} for synthetic ${event} (${tail || 'no stderr'})`,
315
+ remedy: 'run `agent-config doctor --check offline-readiness` and check hook_manifest.yaml',
316
+ };
317
+ }
318
+ results.push(`${event}=${proc.status}`);
319
+ }
320
+ return {
321
+ id: 'hook-dispatcher',
322
+ status: 'ok',
323
+ message: `dispatcher (platform: ${platform}) answered ${results.join(', ')}`,
324
+ remedy: '',
325
+ };
326
+ }
327
+
328
+ // ---------------------------------------------------------------------------
329
+ // Check (d) — lean_projection.mode consistent with projected artifacts.
330
+ // ---------------------------------------------------------------------------
331
+
332
+ function readSettingsMode(projectRoot: string): string {
333
+ const settingsPath = path.join(projectRoot, '.agent-settings.yml');
334
+ if (!fs.existsSync(settingsPath)) {
335
+ return 'eager-all';
336
+ }
337
+ try {
338
+ const parsed = YAML.parse(fs.readFileSync(settingsPath, 'utf8')) as Dict | null;
339
+ const lean = (parsed?.['lean_projection'] ?? null) as Dict | null;
340
+ const mode = lean?.['mode'];
341
+ return typeof mode === 'string' && mode.length > 0 ? mode : 'eager-all';
342
+ } catch {
343
+ return 'eager-all';
344
+ }
345
+ }
346
+
347
+ function kernelIdsFromRouter(packageRoot: string): Set<string> {
348
+ try {
349
+ const router = JSON.parse(
350
+ fs.readFileSync(path.join(packageRoot, 'dist', 'router.json'), 'utf8'),
351
+ ) as Dict;
352
+ return new Set(((router['kernel'] as string[] | undefined) ?? []).map(String));
353
+ } catch {
354
+ return new Set();
355
+ }
356
+ }
357
+
358
+ export function _check_lean_projection(
359
+ projectRoot: string,
360
+ packageRoot: string = PACKAGE_ROOT,
361
+ projectedRulesDir?: string,
362
+ ): Dict {
363
+ const mode = readSettingsMode(projectRoot);
364
+ if (mode !== 'eager-all' && mode !== 'thin') {
365
+ return {
366
+ id: 'lean-projection',
367
+ status: 'fail',
368
+ message: `lean_projection.mode has unknown value ${JSON.stringify(mode)}`,
369
+ remedy: "set lean_projection.mode to 'eager-all' or 'thin' in .agent-settings.yml",
370
+ };
371
+ }
372
+ const rulesDir = projectedRulesDir ?? path.join(projectRoot, '.augment', 'rules');
373
+ if (!fs.existsSync(rulesDir)) {
374
+ return {
375
+ id: 'lean-projection',
376
+ status: 'skipped',
377
+ message: `no projected rules dir at ${rulesDir} — projection consistency not applicable`,
378
+ remedy: '',
379
+ };
380
+ }
381
+ const kernel = kernelIdsFromRouter(packageRoot);
382
+ const files = fs
383
+ .readdirSync(rulesDir)
384
+ .filter((f) => f.endsWith('.md') && f !== 'INDEX.md')
385
+ .sort();
386
+ const nonKernel = files.filter((f) => !kernel.has(f.replace(/\.md$/, '')));
387
+ if (nonKernel.length === 0) {
388
+ return {
389
+ id: 'lean-projection',
390
+ status: 'skipped',
391
+ message: 'no non-kernel projected rules found — nothing to compare',
392
+ remedy: '',
393
+ };
394
+ }
395
+ const inconsistent: string[] = [];
396
+ for (const f of nonKernel) {
397
+ let text = '';
398
+ try {
399
+ text = fs.readFileSync(path.join(rulesDir, f), 'utf8');
400
+ } catch {
401
+ continue; // dangling symlink etc. — not this check's concern
402
+ }
403
+ const isStub = text.includes(THIN_STUB_MARKER);
404
+ if (mode === 'thin' && !isStub) {
405
+ inconsistent.push(`${f} (full body under thin mode)`);
406
+ }
407
+ if (mode === 'eager-all' && isStub) {
408
+ inconsistent.push(`${f} (thin stub under eager-all mode)`);
409
+ }
410
+ }
411
+ if (inconsistent.length > 0) {
412
+ const sample = inconsistent.slice(0, 3).join('; ');
413
+ return {
414
+ id: 'lean-projection',
415
+ status: 'fail',
416
+ message:
417
+ `${inconsistent.length}/${nonKernel.length} projected rules contradict ` +
418
+ `lean_projection.mode=${mode}: ${sample}`,
419
+ remedy: 're-run the install/sync so the projection matches the configured mode',
420
+ };
421
+ }
422
+ return {
423
+ id: 'lean-projection',
424
+ status: 'ok',
425
+ message: `mode=${mode} consistent across ${nonKernel.length} non-kernel projected rules`,
426
+ remedy: '',
427
+ };
428
+ }
429
+
430
+ // ---------------------------------------------------------------------------
431
+ // Check (e) — host-capability manifest parses strictly + matches detection.
432
+ // ---------------------------------------------------------------------------
433
+
434
+ const HOST_MANIFEST_KEYS = new Set([
435
+ 'schema_version',
436
+ 'subagent_spawn',
437
+ 'parallel_spawn',
438
+ 'status_polling',
439
+ 'separate_quota_pool',
440
+ ]);
441
+
442
+ export function _check_host_manifest(projectRoot: string): Dict {
443
+ const detected = Object.entries(detectToolPresence(projectRoot))
444
+ .filter(([, v]) => v === true)
445
+ .map(([k]) => k);
446
+ const detectedNote =
447
+ detected.length > 0 ? `detected surfaces: ${detected.join(', ')}` : 'no surfaces detected';
448
+
449
+ const settingsPath = path.join(projectRoot, '.agent-settings.yml');
450
+ if (!fs.existsSync(settingsPath)) {
451
+ return {
452
+ id: 'host-manifest',
453
+ status: 'ok',
454
+ message: `no .agent-settings.yml — safe-default manifest applies (${detectedNote})`,
455
+ remedy: '',
456
+ };
457
+ }
458
+ let parsed: Dict | null = null;
459
+ try {
460
+ parsed = YAML.parse(fs.readFileSync(settingsPath, 'utf8')) as Dict | null;
461
+ } catch (exc) {
462
+ return {
463
+ id: 'host-manifest',
464
+ status: 'fail',
465
+ message: `.agent-settings.yml does not parse: ${(exc as Error).message}`,
466
+ remedy: 'fix the YAML syntax, or run `agent-config settings:check`',
467
+ };
468
+ }
469
+ const subagents = (parsed?.['subagents'] ?? null) as Dict | null;
470
+ const manifest = subagents?.['host_capabilities'];
471
+ if (manifest === undefined || manifest === null) {
472
+ return {
473
+ id: 'host-manifest',
474
+ status: 'ok',
475
+ message: `no host_capabilities override — safe-default manifest applies (${detectedNote})`,
476
+ remedy: '',
477
+ };
478
+ }
479
+ if (typeof manifest !== 'object' || Array.isArray(manifest)) {
480
+ return {
481
+ id: 'host-manifest',
482
+ status: 'fail',
483
+ message: 'subagents.host_capabilities is not a mapping',
484
+ remedy: 'use the four boolean fields from the host-capability manifest contract',
485
+ };
486
+ }
487
+ const problems: string[] = [];
488
+ for (const [key, value] of Object.entries(manifest as Dict)) {
489
+ if (!HOST_MANIFEST_KEYS.has(key)) {
490
+ problems.push(`unknown key '${key}'`);
491
+ continue;
492
+ }
493
+ if (key === 'schema_version') {
494
+ if (value !== 1) problems.push(`schema_version must be 1 (got ${JSON.stringify(value)})`);
495
+ continue;
496
+ }
497
+ if (typeof value !== 'boolean') {
498
+ problems.push(`'${key}' must be boolean (got ${JSON.stringify(value)})`);
499
+ }
500
+ }
501
+ if (problems.length > 0) {
502
+ return {
503
+ id: 'host-manifest',
504
+ status: 'fail',
505
+ message: `host_capabilities malformed: ${problems.slice(0, 4).join('; ')}`,
506
+ remedy: 'only schema_version:1 + four boolean capability fields are valid',
507
+ };
508
+ }
509
+ return {
510
+ id: 'host-manifest',
511
+ status: 'ok',
512
+ message: `host_capabilities override parses strictly (${detectedNote})`,
513
+ remedy: '',
514
+ };
515
+ }
516
+
517
+ // ---------------------------------------------------------------------------
518
+ // Orchestration.
519
+ // ---------------------------------------------------------------------------
520
+
521
+ export interface ConformanceRunOptions {
522
+ readonly projectRoot?: string;
523
+ readonly packageRoot?: string;
524
+ /** Skip the dispatcher spawn (unit tests / no-node sandboxes). */
525
+ readonly skipDispatcher?: boolean;
526
+ }
527
+
528
+ export function runConformanceChecks(opts: ConformanceRunOptions = {}): Dict[] {
529
+ const projectRoot = opts.projectRoot ?? process.cwd();
530
+ const packageRoot = opts.packageRoot ?? PACKAGE_ROOT;
531
+ const checks: Dict[] = [];
532
+ checks.push(_check_txlog_clean());
533
+ checks.push(_check_router_pointers(packageRoot));
534
+ if (opts.skipDispatcher === true) {
535
+ checks.push({
536
+ id: 'hook-dispatcher',
537
+ status: 'skipped',
538
+ message: 'dispatcher smoke skipped by flag',
539
+ remedy: '',
540
+ });
541
+ } else {
542
+ checks.push(_check_hook_dispatcher(projectRoot, packageRoot));
543
+ }
544
+ checks.push(_check_lean_projection(projectRoot, packageRoot));
545
+ checks.push(_check_host_manifest(projectRoot));
546
+ return checks;
547
+ }
548
+
549
+ /** One JSONL report line, mirroring the txlog entry shape. */
550
+ export function appendConformanceReport(
551
+ checks: readonly Dict[],
552
+ projectRoot: string,
553
+ logPath: string = conformanceLogPath(),
554
+ ): void {
555
+ const fails = checks.filter((c) => c['status'] === 'fail').map((c) => String(c['id']));
556
+ const ok = checks.filter((c) => c['status'] === 'ok').length;
557
+ const entry = {
558
+ ts: new Date().toISOString(),
559
+ kind: 'conformance',
560
+ path: projectRoot,
561
+ sha256: null,
562
+ note: `${ok}/${checks.length} ok; fails: ${fails.length > 0 ? fails.join(',') : 'none'}`,
563
+ };
564
+ try {
565
+ atomicAppendLine(logPath, JSON.stringify(entry));
566
+ } catch {
567
+ // Report emission must never break the exit contract.
568
+ }
569
+ }
570
+
571
+ const USAGE =
572
+ 'usage: agent-config conformance [-h] [--project PROJECT] [--json]\n' +
573
+ ' [--skip-dispatcher]\n';
574
+
575
+ interface Options {
576
+ project: string | null;
577
+ json: boolean;
578
+ skip_dispatcher: boolean;
579
+ }
580
+
581
+ function _parse(argv: string[]): Options {
582
+ const opts: Options = { project: null, json: false, skip_dispatcher: false };
583
+ let i = 0;
584
+ while (i < argv.length) {
585
+ const a = argv[i] as string;
586
+ if (a === '-h' || a === '--help') {
587
+ process.stdout.write(USAGE);
588
+ throw new ArgparseExit(0);
589
+ }
590
+ if (a === '--json') {
591
+ opts.json = true;
592
+ } else if (a === '--skip-dispatcher') {
593
+ opts.skip_dispatcher = true;
594
+ } else if (a === '--project' || a.startsWith('--project=')) {
595
+ if (a.includes('=')) {
596
+ opts.project = a.slice(a.indexOf('=') + 1);
597
+ } else {
598
+ if (i + 1 >= argv.length) {
599
+ process.stderr.write(USAGE);
600
+ process.stderr.write('agent-config conformance: error: --project expects a value\n');
601
+ throw new ArgparseExit(2);
602
+ }
603
+ opts.project = argv[i + 1] as string;
604
+ i += 1;
605
+ }
606
+ } else {
607
+ process.stderr.write(USAGE);
608
+ process.stderr.write(`agent-config conformance: error: unrecognized argument ${a}\n`);
609
+ throw new ArgparseExit(2);
610
+ }
611
+ i += 1;
612
+ }
613
+ return opts;
614
+ }
615
+
616
+ function main(argv: string[] | null = null): number {
617
+ const opts = _parse(argv !== null ? Array.from(argv) : process.argv.slice(2));
618
+
619
+ let project_root: string;
620
+ try {
621
+ [project_root] = _resolve_project_root(opts.project);
622
+ } catch (exc) {
623
+ eprint(`❌ conformance: ${(exc as Error).message}`);
624
+ return 2;
625
+ }
626
+
627
+ // Leg 1 — doctor's own drift + checks (the --ci contract, in-process).
628
+ const manifest_pth = installed_tools.manifest_path(project_root);
629
+ const manifest = installed_tools.read_manifest(manifest_pth);
630
+ let doctorChecks: Dict[];
631
+ let drift: Record<string, Dict[]> = { missing: [], modified: [], foreign: [], tag_drift: [] };
632
+ if (manifest === null) {
633
+ const bridge_present = fs.existsSync(path.join(project_root, BRIDGE_MARKER_RELATIVE));
634
+ doctorChecks = _run_checks_no_manifest(project_root, bridge_present, null);
635
+ } else {
636
+ const [records, known] = _collect_manifest_entries(project_root, manifest);
637
+ const [missing, modified, tag_drift] = _classify(records);
638
+ const foreign = _foreign_records(
639
+ project_root,
640
+ _scan_foreign(project_root, manifest, known),
641
+ );
642
+ drift = { missing, modified, foreign, tag_drift };
643
+ doctorChecks = _run_checks(project_root, manifest, drift, null);
644
+ }
645
+
646
+ // Leg 2 — the five conformance checks.
647
+ const conformanceChecks = runConformanceChecks({
648
+ projectRoot: project_root,
649
+ skipDispatcher: opts.skip_dispatcher,
650
+ });
651
+
652
+ const allChecks = [...doctorChecks, ...conformanceChecks];
653
+ const driftCount =
654
+ drift['missing']!.length +
655
+ drift['modified']!.length +
656
+ drift['foreign']!.length +
657
+ drift['tag_drift']!.length;
658
+ const failed = allChecks.some((c) => c['status'] === 'fail') || driftCount > 0;
659
+
660
+ appendConformanceReport(conformanceChecks, project_root);
661
+
662
+ if (opts.json) {
663
+ print(
664
+ _jsonDumpsIndentAscii(
665
+ {
666
+ project_root,
667
+ drift,
668
+ doctor_checks: doctorChecks,
669
+ conformance_checks: conformanceChecks,
670
+ status: failed ? 'fail' : 'ok',
671
+ },
672
+ 2,
673
+ ),
674
+ );
675
+ } else {
676
+ print(` 📍 project_root: ${project_root}`);
677
+ print('conformance:');
678
+ for (const c of allChecks) {
679
+ const sym = STATUS_SYMBOLS[c['status'] as string] ?? '?';
680
+ print(` ${sym} ${c['id']}: ${c['message']}`);
681
+ if (c['status'] !== 'ok' && c['remedy']) {
682
+ print(` fix: ${c['remedy']}`);
683
+ }
684
+ }
685
+ if (driftCount > 0) {
686
+ print(` ❌ drift: ${driftCount} drifted file(s) — run \`agent-config doctor\` for detail`);
687
+ }
688
+ print('');
689
+ print(
690
+ failed
691
+ ? '❌ conformance: red — the OS is not fully installed/firing here'
692
+ : '✅ conformance: green — installed and firing',
693
+ );
694
+ }
695
+ return failed ? 1 : 0;
696
+ }
697
+
698
+ // --- CLI entry ---
699
+
700
+ const _isCliEntry =
701
+ process.argv[1] !== undefined &&
702
+ import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href;
703
+ if (_isCliEntry || process.argv[1] === _HERE) {
704
+ try {
705
+ process.exitCode = main(process.argv.slice(2));
706
+ } catch (e) {
707
+ if (e instanceof ArgparseExit) {
708
+ process.exitCode = e.code;
709
+ } else {
710
+ throw e;
711
+ }
712
+ }
713
+ }
714
+
715
+ export { main, _parse };
716
+ export type { Options as ConformanceOptions };