@event4u/agent-config 6.1.0 → 7.0.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 (1537) hide show
  1. package/.claude-plugin/marketplace.json +35 -3
  2. package/AGENTS.md +8 -7
  3. package/CHANGELOG.md +408 -0
  4. package/CONTRIBUTING.md +1 -1
  5. package/README.md +17 -15
  6. package/dist/agent-src/commands/agent-status.md +2 -2
  7. package/dist/agent-src/commands/agents/audit.md +3 -3
  8. package/dist/agent-src/commands/agents/init.md +1 -1
  9. package/dist/agent-src/commands/agents/optimize.md +4 -4
  10. package/dist/agent-src/commands/analyze/decision.md +108 -0
  11. package/dist/agent-src/commands/analyze/incident.md +120 -0
  12. package/dist/agent-src/commands/analyze/near-miss.md +113 -0
  13. package/dist/agent-src/commands/analyze/postmortem.md +130 -0
  14. package/dist/agent-src/commands/analyze/premortem.md +104 -0
  15. package/dist/agent-src/commands/analyze.md +124 -0
  16. package/dist/agent-src/commands/brand/identity.md +27 -0
  17. package/dist/agent-src/commands/brand/review.md +27 -0
  18. package/dist/agent-src/commands/brand/strategy.md +27 -0
  19. package/dist/agent-src/commands/brand/tokens.md +28 -0
  20. package/dist/agent-src/commands/brand/voice.md +27 -0
  21. package/dist/agent-src/commands/brand.md +58 -0
  22. package/dist/agent-src/commands/check-current-md.md +3 -3
  23. package/dist/agent-src/commands/condense.md +2 -2
  24. package/dist/agent-src/commands/council/debate.md +2 -2
  25. package/dist/agent-src/commands/council/default.md +45 -18
  26. package/dist/agent-src/commands/fix/portability.md +3 -3
  27. package/dist/agent-src/commands/fix/refs.md +3 -3
  28. package/dist/agent-src/commands/implement-ticket.md +36 -6
  29. package/dist/agent-src/commands/knowledge/cross-repo.md +1 -1
  30. package/dist/agent-src/commands/memory/add.md +1 -1
  31. package/dist/agent-src/commands/mission/upgrade.md +182 -0
  32. package/dist/agent-src/commands/optimize/skills.md +2 -2
  33. package/dist/agent-src/commands/orchestrate.md +1 -1
  34. package/dist/agent-src/commands/pr/create.md +6 -4
  35. package/dist/agent-src/commands/review-changes.md +8 -0
  36. package/dist/agent-src/commands/roadmap/materialize.md +73 -0
  37. package/dist/agent-src/commands/skill/preview.md +1 -1
  38. package/dist/agent-src/commands/skills/discover.md +1 -1
  39. package/dist/agent-src/commands/threat-model.md +4 -4
  40. package/dist/agent-src/commands/upstream-contribute.md +3 -3
  41. package/dist/agent-src/commands/video/from-script.md +2 -2
  42. package/dist/agent-src/commands/video/from-song.md +3 -3
  43. package/dist/agent-src/commands/video/scene.md +1 -1
  44. package/dist/agent-src/commands/video/storyboard.md +1 -1
  45. package/dist/agent-src/commands/video.md +3 -3
  46. package/dist/agent-src/contexts/communication/rules-auto/source-of-truth-mechanics.md +3 -3
  47. package/dist/agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +1 -1
  48. package/dist/agent-src/contexts/execution/evidence-discipline.md +153 -0
  49. package/dist/agent-src/contexts/execution/project-intelligence.md +264 -0
  50. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +2 -1
  51. package/dist/agent-src/personas/ai-video-technical-director.md +1 -1
  52. package/dist/agent-src/personas/brand-strategist.md +74 -0
  53. package/dist/agent-src/personas/design-director.md +74 -0
  54. package/dist/agent-src/rules/brand-consistency.md +77 -0
  55. package/dist/agent-src/rules/brand-source-of-truth.md +57 -0
  56. package/dist/agent-src/rules/direct-answers.md +2 -0
  57. package/dist/agent-src/rules/domain-safety-disclaimer.md +2 -0
  58. package/dist/agent-src/rules/git-history-discipline.md +1 -0
  59. package/dist/agent-src/rules/icon-consistency.md +53 -0
  60. package/dist/agent-src/rules/image-likeness-and-rights.md +67 -0
  61. package/dist/agent-src/rules/lethal-trifecta-guard.md +1 -1
  62. package/dist/agent-src/rules/persona-governance.md +2 -2
  63. package/dist/agent-src/rules/provider-lifecycle-discipline.md +3 -1
  64. package/dist/agent-src/rules/roadmap-progress-sync.md +10 -0
  65. package/dist/agent-src/rules/security-sensitive-stop.md +9 -3
  66. package/dist/agent-src/rules/size-enforcement.md +1 -1
  67. package/dist/agent-src/rules/source-confidentiality.md +3 -3
  68. package/dist/agent-src/rules/source-discovery-gate.md +98 -0
  69. package/dist/agent-src/rules/think-before-action.md +1 -0
  70. package/dist/agent-src/rules/ui-audit-gate.md +2 -0
  71. package/dist/agent-src/rules/untrusted-input-defense.md +1 -1
  72. package/dist/agent-src/rules/user-interaction.md +1 -1
  73. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +392 -0
  74. package/dist/agent-src/scripts/update_roadmap_progress.ts +824 -0
  75. package/dist/agent-src/skills/adr-create/SKILL.md +5 -5
  76. package/dist/agent-src/skills/agent-security-review/evals/triggers.json +1 -0
  77. package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +1 -1
  78. package/dist/agent-src/skills/ai-council/SKILL.md +1 -1
  79. package/dist/agent-src/skills/analysis-autonomous-mode/SKILL.md +9 -13
  80. package/dist/agent-src/skills/blade-ui/SKILL.md +12 -5
  81. package/dist/agent-src/skills/blameless-post-mortem/SKILL.md +199 -0
  82. package/dist/agent-src/skills/brand/ATTRIBUTION.md +38 -0
  83. package/dist/agent-src/skills/brand/SKILL.md +115 -0
  84. package/dist/agent-src/skills/brand/data/archetypes.csv +13 -0
  85. package/dist/agent-src/skills/brand/data/color-psychology.csv +14 -0
  86. package/dist/agent-src/skills/brand/data/logo-style-fit.csv +13 -0
  87. package/dist/agent-src/skills/brand/data/manifest.json +226 -0
  88. package/dist/agent-src/skills/brand/data/messaging-frameworks.csv +13 -0
  89. package/dist/agent-src/skills/brand/data/naming-patterns.csv +13 -0
  90. package/dist/agent-src/skills/brand/data/typography-principles.csv +13 -0
  91. package/dist/agent-src/skills/brand/data/voice-tone.csv +13 -0
  92. package/dist/agent-src/skills/brand/evals/triggers.json +17 -0
  93. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +89 -0
  94. package/dist/agent-src/skills/brand-asset-generation/evals/triggers.json +17 -0
  95. package/dist/agent-src/skills/brand-audit/SKILL.md +67 -0
  96. package/dist/agent-src/skills/brand-audit/evals/triggers.json +17 -0
  97. package/dist/agent-src/skills/brand-identity/SKILL.md +101 -0
  98. package/dist/agent-src/skills/brand-identity/evals/triggers.json +17 -0
  99. package/dist/agent-src/skills/brand-strategy/SKILL.md +83 -0
  100. package/dist/agent-src/skills/brand-strategy/evals/triggers.json +17 -0
  101. package/dist/agent-src/skills/brand-to-tokens/SKILL.md +102 -0
  102. package/dist/agent-src/skills/brand-to-tokens/evals/triggers.json +17 -0
  103. package/dist/agent-src/skills/brand-to-tokens/templates/marp-brand-deck.md.example +46 -0
  104. package/dist/agent-src/skills/brand-to-tokens/templates/reveal-brand-deck.yaml +32 -0
  105. package/dist/agent-src/skills/canvas-design/evals/triggers.json +1 -0
  106. package/dist/agent-src/skills/check-refs/SKILL.md +5 -5
  107. package/dist/agent-src/skills/code-review/SKILL.md +6 -15
  108. package/dist/agent-src/skills/command-writing/SKILL.md +2 -2
  109. package/dist/agent-src/skills/complexity-first-planning/evals/triggers.json +1 -0
  110. package/dist/agent-src/skills/context-authoring/SKILL.md +2 -2
  111. package/dist/agent-src/skills/context-document/SKILL.md +35 -2
  112. package/dist/agent-src/skills/corpus-grounding/evals/triggers.json +1 -0
  113. package/dist/agent-src/skills/corpus-grounding/scripts/bm25_search.ts +482 -0
  114. package/dist/agent-src/skills/corpus-grounding/scripts/decision_engine.ts +803 -0
  115. package/dist/agent-src/skills/corpus-grounding/scripts/ground.ts +541 -0
  116. package/dist/agent-src/skills/corpus-grounding/scripts/schema_validator.ts +309 -0
  117. package/dist/agent-src/skills/database/SKILL.md +26 -4
  118. package/dist/agent-src/skills/decision-record/SKILL.md +1 -1
  119. package/dist/agent-src/skills/decision-record/evals/triggers.json +17 -0
  120. package/dist/agent-src/skills/decision-review/SKILL.md +179 -0
  121. package/dist/agent-src/skills/description-assist/SKILL.md +1 -1
  122. package/dist/agent-src/skills/design-intelligence/SKILL.md +1 -1
  123. package/dist/agent-src/skills/design-intelligence/data/manifest.json +23 -6
  124. package/dist/agent-src/skills/design-intelligence/evals/triggers.json +1 -0
  125. package/dist/agent-src/skills/design-tokens/evals/triggers.json +1 -0
  126. package/dist/agent-src/skills/design-tokens/scripts/tokens.ts +888 -0
  127. package/dist/agent-src/skills/doc-coauthoring/evals/triggers.json +1 -0
  128. package/dist/agent-src/skills/eloquent/evals/triggers.json +1 -0
  129. package/dist/agent-src/skills/emit-tickets/SKILL.md +198 -0
  130. package/dist/agent-src/skills/estimate-ticket/evals/triggers.json +1 -0
  131. package/dist/agent-src/skills/git-workflow/SKILL.md +33 -0
  132. package/dist/agent-src/skills/guideline-writing/SKILL.md +2 -2
  133. package/dist/agent-src/skills/iconography/SKILL.md +88 -0
  134. package/dist/agent-src/skills/iconography/evals/triggers.json +17 -0
  135. package/dist/agent-src/skills/image-analyser/evals/triggers.json +1 -0
  136. package/dist/agent-src/skills/image-creator/evals/triggers.json +1 -0
  137. package/dist/agent-src/skills/image-editing/SKILL.md +100 -0
  138. package/dist/agent-src/skills/image-editing/evals/triggers.json +17 -0
  139. package/dist/agent-src/skills/image-generation/SKILL.md +95 -0
  140. package/dist/agent-src/skills/image-generation/evals/triggers.json +17 -0
  141. package/dist/agent-src/skills/image-provider-routing/SKILL.md +96 -0
  142. package/dist/agent-src/skills/image-provider-routing/evals/triggers.json +17 -0
  143. package/dist/agent-src/skills/launch-readiness/SKILL.md +21 -0
  144. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +12 -8
  145. package/dist/agent-src/skills/lint-skills/SKILL.md +5 -5
  146. package/dist/agent-src/skills/logo-generation/SKILL.md +98 -0
  147. package/dist/agent-src/skills/logo-generation/evals/triggers.json +17 -0
  148. package/dist/agent-src/skills/markitdown/SKILL.md +1 -1
  149. package/dist/agent-src/skills/md-language-check/SKILL.md +1 -1
  150. package/dist/agent-src/skills/motion-choreographer/SKILL.md +1 -1
  151. package/dist/agent-src/skills/php-coder/evals/triggers.json +1 -0
  152. package/dist/agent-src/skills/prediction-pool-optimizer/evals/triggers.json +1 -0
  153. package/dist/agent-src/skills/premortem/SKILL.md +137 -0
  154. package/dist/agent-src/skills/prompt-engineering-image/SKILL.md +115 -0
  155. package/dist/agent-src/skills/prompt-engineering-image/evals/triggers.json +17 -0
  156. package/dist/agent-src/skills/prompt-validator/evals/triggers.json +1 -0
  157. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +12 -5
  158. package/dist/agent-src/skills/react-shadcn-ui/scripts/shadcn_add.ts +388 -0
  159. package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +1 -1
  160. package/dist/agent-src/skills/reasoning-orchestrator/evals/triggers.json +1 -0
  161. package/dist/agent-src/skills/refine-ticket/evals/triggers.json +1 -0
  162. package/dist/agent-src/skills/roadmap-management/SKILL.md +16 -3
  163. package/dist/agent-src/skills/roadmap-writing/SKILL.md +76 -0
  164. package/dist/agent-src/skills/root-cause-frameworks/SKILL.md +146 -0
  165. package/dist/agent-src/skills/rule-refactor/SKILL.md +9 -9
  166. package/dist/agent-src/skills/rule-writing/SKILL.md +7 -7
  167. package/dist/agent-src/skills/script-writing/SKILL.md +2 -2
  168. package/dist/agent-src/skills/security-audit/SKILL.md +5 -0
  169. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +19 -3
  170. package/dist/agent-src/skills/skill-management/SKILL.md +3 -3
  171. package/dist/agent-src/skills/skill-reviewer/SKILL.md +1 -1
  172. package/dist/agent-src/skills/skill-writing/SKILL.md +5 -5
  173. package/dist/agent-src/skills/skill-writing/evals/triggers.json +1 -0
  174. package/dist/agent-src/skills/source-discovery/SKILL.md +182 -0
  175. package/dist/agent-src/skills/standards-from-config/SKILL.md +93 -0
  176. package/dist/agent-src/skills/systematic-debugging/SKILL.md +7 -0
  177. package/dist/agent-src/skills/tailwind-engineer/scripts/tailwind_config_gen.ts +561 -0
  178. package/dist/agent-src/skills/threat-modeling/SKILL.md +1 -0
  179. package/dist/agent-src/skills/typography-system/SKILL.md +138 -0
  180. package/dist/agent-src/skills/typography-system/evals/triggers.json +17 -0
  181. package/dist/agent-src/skills/upstream-contribute/SKILL.md +3 -3
  182. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +209 -0
  183. package/dist/agent-src/skills/verify-repair-loop/evals/output-schema.yml +20 -0
  184. package/dist/agent-src/skills/verify-repair-loop/evals/triggers.json +17 -0
  185. package/dist/agent-src/templates/agent-settings.md +7 -0
  186. package/dist/agent-src/templates/contexts/knowledge-card.md +69 -0
  187. package/dist/agent-src/templates/contexts/lesson-card.md +73 -0
  188. package/dist/agent-src/templates/roadmaps.md +29 -1
  189. package/dist/agent-src/templates/scripts/README.md +6 -6
  190. package/dist/agent-src/templates/scripts/check_memory.ts +640 -0
  191. package/dist/agent-src/templates/scripts/check_memory_proposal.ts +351 -0
  192. package/dist/agent-src/templates/scripts/implement_ticket/__main__.ts +27 -0
  193. package/dist/agent-src/templates/scripts/memory_hash.ts +333 -0
  194. package/dist/agent-src/templates/scripts/memory_lookup.ts +1067 -0
  195. package/dist/agent-src/templates/scripts/memory_report.ts +846 -0
  196. package/dist/agent-src/templates/scripts/memory_signal.ts +422 -0
  197. package/dist/agent-src/templates/scripts/memory_status.ts +191 -0
  198. package/dist/agent-src/templates/scripts/pr_review_routing.ts +523 -0
  199. package/dist/agent-src/templates/scripts/pr_risk_review.ts +0 -0
  200. package/dist/agent-src/templates/scripts/telemetry/aggregator.ts +0 -0
  201. package/dist/agent-src/templates/scripts/telemetry/boundary.ts +164 -0
  202. package/dist/agent-src/templates/scripts/telemetry/engagement.ts +479 -0
  203. package/dist/agent-src/templates/scripts/telemetry/report_renderer.ts +394 -0
  204. package/dist/agent-src/templates/scripts/telemetry/settings.ts +210 -0
  205. package/dist/agent-src/templates/scripts/telemetry_record.ts +255 -0
  206. package/dist/agent-src/templates/scripts/telemetry_report.ts +189 -0
  207. package/dist/agent-src/templates/scripts/telemetry_status.ts +312 -0
  208. package/dist/agent-src/templates/scripts/tier_usage_report.ts +597 -0
  209. package/dist/agent-src/templates/scripts/work_engine/__main__.ts +14 -0
  210. package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +1118 -0
  211. package/dist/agent-src/templates/scripts/work_engine/_lib/user_global_paths.ts +329 -0
  212. package/dist/agent-src/templates/scripts/work_engine/cli.ts +206 -0
  213. package/dist/agent-src/templates/scripts/work_engine/cli_args.ts +249 -0
  214. package/dist/agent-src/templates/scripts/work_engine/delivery_state.ts +225 -0
  215. package/dist/agent-src/templates/scripts/work_engine/directives/backend/analyze.ts +125 -0
  216. package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +189 -0
  217. package/dist/agent-src/templates/scripts/work_engine/directives/backend/index.ts +94 -0
  218. package/dist/agent-src/templates/scripts/work_engine/directives/backend/memory.ts +193 -0
  219. package/dist/agent-src/templates/scripts/work_engine/directives/backend/plan.ts +267 -0
  220. package/dist/agent-src/templates/scripts/work_engine/directives/backend/refine.ts +518 -0
  221. package/dist/agent-src/templates/scripts/work_engine/directives/backend/report.ts +379 -0
  222. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +268 -0
  223. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +258 -0
  224. package/dist/agent-src/templates/scripts/work_engine/directives/index.ts +32 -0
  225. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/contract.ts +243 -0
  226. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/index.ts +108 -0
  227. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +259 -0
  228. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/ui.ts +216 -0
  229. package/dist/agent-src/templates/scripts/work_engine/directives/ui/_passthrough.ts +40 -0
  230. package/dist/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +241 -0
  231. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +216 -0
  232. package/dist/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +506 -0
  233. package/dist/agent-src/templates/scripts/work_engine/directives/ui/design.ts +325 -0
  234. package/dist/agent-src/templates/scripts/work_engine/directives/ui/index.ts +102 -0
  235. package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +462 -0
  236. package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +474 -0
  237. package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +352 -0
  238. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/_skipped.ts +33 -0
  239. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/apply.ts +213 -0
  240. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/index.ts +111 -0
  241. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/refine.ts +126 -0
  242. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/report.ts +112 -0
  243. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/test.ts +164 -0
  244. package/dist/agent-src/templates/scripts/work_engine/dispatcher.ts +515 -0
  245. package/dist/agent-src/templates/scripts/work_engine/emitters.ts +119 -0
  246. package/dist/agent-src/templates/scripts/work_engine/errors.ts +24 -0
  247. package/dist/agent-src/templates/scripts/work_engine/hook_bootstrap.ts +104 -0
  248. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/_chat_history_base.ts +176 -0
  249. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_append.ts +41 -0
  250. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_halt_append.ts +89 -0
  251. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_gate.ts +193 -0
  252. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +304 -0
  253. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/directive_set_guard.ts +110 -0
  254. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/halt_surface_audit.ts +118 -0
  255. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/index.ts +17 -0
  256. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +161 -0
  257. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/state_shape_validation.ts +45 -0
  258. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/trace.ts +134 -0
  259. package/dist/agent-src/templates/scripts/work_engine/hooks/context.ts +94 -0
  260. package/dist/agent-src/templates/scripts/work_engine/hooks/events.ts +58 -0
  261. package/dist/agent-src/templates/scripts/work_engine/hooks/exceptions.ts +85 -0
  262. package/dist/agent-src/templates/scripts/work_engine/hooks/index.ts +27 -0
  263. package/dist/agent-src/templates/scripts/work_engine/hooks/registry.ts +66 -0
  264. package/dist/agent-src/templates/scripts/work_engine/hooks/runner.ts +90 -0
  265. package/dist/agent-src/templates/scripts/work_engine/hooks/settings.ts +260 -0
  266. package/dist/agent-src/templates/scripts/work_engine/input_builders.ts +260 -0
  267. package/dist/agent-src/templates/scripts/work_engine/intent/classify.ts +466 -0
  268. package/dist/agent-src/templates/scripts/work_engine/migration/v0_to_v1.ts +531 -0
  269. package/dist/agent-src/templates/scripts/work_engine/orchestration.ts +366 -0
  270. package/dist/agent-src/templates/scripts/work_engine/persona_policy.ts +97 -0
  271. package/dist/agent-src/templates/scripts/work_engine/resolvers/diff.ts +135 -0
  272. package/dist/agent-src/templates/scripts/work_engine/resolvers/file.ts +175 -0
  273. package/dist/agent-src/templates/scripts/work_engine/resolvers/prompt.ts +115 -0
  274. package/dist/agent-src/templates/scripts/work_engine/scoring/confidence.ts +415 -0
  275. package/dist/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +466 -0
  276. package/dist/agent-src/templates/scripts/work_engine/scoring/decision_trace.ts +298 -0
  277. package/dist/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +444 -0
  278. package/dist/agent-src/templates/scripts/work_engine/stack/detect.ts +252 -0
  279. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +745 -0
  280. package/dist/agent-src/templates/scripts/work_engine/state.ts +1151 -0
  281. package/dist/agent-src/templates/scripts/work_engine/state_io.ts +413 -0
  282. package/dist/agent-src/templates/tickets.md +120 -0
  283. package/dist/cli/commands/commands.js +2 -2
  284. package/dist/cli/commands/commands.js.map +1 -1
  285. package/dist/cli/commands/doctorShell.js +4 -22
  286. package/dist/cli/commands/doctorShell.js.map +1 -1
  287. package/dist/cli/commands/packs.js +1 -1
  288. package/dist/cli/commands/packs.js.map +1 -1
  289. package/dist/cli/commands/recordTriggerEval.js +179 -0
  290. package/dist/cli/commands/recordTriggerEval.js.map +1 -0
  291. package/dist/cli/commands/recordTriggerEval.test.js +113 -0
  292. package/dist/cli/commands/recordTriggerEval.test.js.map +1 -0
  293. package/dist/cli/commands/workspaces.js +1 -1
  294. package/dist/cli/commands/workspaces.js.map +1 -1
  295. package/dist/cli/main.js +22 -1
  296. package/dist/cli/main.js.map +1 -1
  297. package/dist/cli/python/knowledge_ingest.js +1048 -0
  298. package/dist/cli/python/knowledge_ingest.js.map +1 -0
  299. package/dist/cli/python/workspace_analytics.js +1085 -0
  300. package/dist/cli/python/workspace_analytics.js.map +1 -0
  301. package/dist/cli/python/workspace_crypto.js +544 -0
  302. package/dist/cli/python/workspace_crypto.js.map +1 -0
  303. package/dist/cli/python/workspace_documents.js +1216 -0
  304. package/dist/cli/python/workspace_documents.js.map +1 -0
  305. package/dist/cli/python/workspace_drive.js +574 -0
  306. package/dist/cli/python/workspace_drive.js.map +1 -0
  307. package/dist/cli/python/workspace_drive_health.js +628 -0
  308. package/dist/cli/python/workspace_drive_health.js.map +1 -0
  309. package/dist/cli/python/workspace_explain.js +765 -0
  310. package/dist/cli/python/workspace_explain.js.map +1 -0
  311. package/dist/cli/python/workspace_hosts.js +349 -0
  312. package/dist/cli/python/workspace_hosts.js.map +1 -0
  313. package/dist/cli/python/workspace_inbox.js +692 -0
  314. package/dist/cli/python/workspace_inbox.js.map +1 -0
  315. package/dist/cli/python/workspace_render.js +816 -0
  316. package/dist/cli/python/workspace_render.js.map +1 -0
  317. package/dist/cli/python/workspace_roles.js +487 -0
  318. package/dist/cli/python/workspace_roles.js.map +1 -0
  319. package/dist/cli/python/workspace_secrets.js +180 -0
  320. package/dist/cli/python/workspace_secrets.js.map +1 -0
  321. package/dist/cli/python/workspace_sessions.js +1079 -0
  322. package/dist/cli/python/workspace_sessions.js.map +1 -0
  323. package/dist/cli/python/workspace_skills.js +417 -0
  324. package/dist/cli/python/workspace_skills.js.map +1 -0
  325. package/dist/cli/registry.js +2 -0
  326. package/dist/cli/registry.js.map +1 -1
  327. package/dist/discovery/deprecation-report.md +1 -1
  328. package/dist/discovery/discovery-manifest.json +1174 -123
  329. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  330. package/dist/discovery/discovery-manifest.summary.md +9 -6
  331. package/dist/discovery/orphan-report.md +1 -1
  332. package/dist/discovery/packs.json +163 -15
  333. package/dist/discovery/trust-report.md +4 -4
  334. package/dist/discovery/workspaces.json +73 -12
  335. package/dist/install/install.mjs +13934 -0
  336. package/dist/mcp/registry-manifest.json +4 -4
  337. package/dist/router.json +1 -1
  338. package/dist/server/routes/wizard.js +50 -21
  339. package/dist/server/routes/wizard.js.map +1 -1
  340. package/dist/server/routes/workspace.js +44 -25
  341. package/dist/server/routes/workspace.js.map +1 -1
  342. package/dist/server/schemas/settings.js +15 -0
  343. package/dist/server/schemas/settings.js.map +1 -1
  344. package/docs/SKILL_CENSUS.md +344 -0
  345. package/docs/architecture/augment-projection.md +1 -1
  346. package/docs/architecture/multi-tool-projection.md +3 -3
  347. package/docs/architecture.md +37 -6
  348. package/docs/benchmark.md +24 -27
  349. package/docs/capability-matrix.md +32 -0
  350. package/docs/catalog.md +50 -9
  351. package/docs/command-naming-audit.md +60 -0
  352. package/docs/contracts/STABILITY.md +32 -0
  353. package/docs/contracts/agents-md-tech-stack.md +1 -1
  354. package/docs/contracts/ai-council-config.md +22 -22
  355. package/docs/contracts/analysis-memory-loop.md +149 -0
  356. package/docs/contracts/benchmark-ab-contract.md +3 -3
  357. package/docs/contracts/branch-protection-policy.md +27 -0
  358. package/docs/contracts/brand-token-consumption.md +69 -0
  359. package/docs/contracts/command-clusters.md +2 -1
  360. package/docs/contracts/command-surface-tiers.md +13 -0
  361. package/docs/contracts/discovery-manifest.schema.json +24 -5
  362. package/docs/contracts/implement-ticket-flow.md +9 -9
  363. package/docs/contracts/install-layout.md +249 -0
  364. package/docs/contracts/kernel-membership.md +1 -1
  365. package/docs/contracts/linear-ai-rules-inclusion.md +2 -2
  366. package/docs/contracts/linter-structural-model.md +1 -1
  367. package/docs/contracts/mcp-discovery-phase-notice.md +1 -1
  368. package/docs/contracts/multi-tool-projection-fidelity.md +1 -1
  369. package/docs/contracts/namespace.md +2 -2
  370. package/docs/contracts/no-runtime-boundary.md +56 -0
  371. package/docs/contracts/package-self-orientation.md +24 -0
  372. package/docs/contracts/provider-lifecycle.md +3 -3
  373. package/docs/contracts/reasoning-discipline-protocol.md +83 -0
  374. package/docs/contracts/rule-classification.md +3 -3
  375. package/docs/contracts/skill-domains.md +1 -1
  376. package/docs/contracts/smoke-contracts.md +1 -1
  377. package/docs/contracts/surface-tiers.md +81 -0
  378. package/docs/contracts/ticket-bundle-format.md +228 -0
  379. package/docs/cookbook.md +152 -0
  380. package/docs/customization.md +12 -1
  381. package/docs/decisions/ADR-013-discovery-frontmatter-contract.md +16 -0
  382. package/docs/decisions/ADR-056-unvalidated-video-adapters-disposition.md +1 -1
  383. package/docs/decisions/ADR-059-render-resume-filesystem-as-state.md +1 -1
  384. package/docs/decisions/ADR-060-comfyui-sandbox-model.md +1 -1
  385. package/docs/decisions/ADR-061-corpus-grounding-layer.md +48 -1
  386. package/docs/decisions/ADR-096-analysis-workbench.md +110 -0
  387. package/docs/decisions/ADR-097-mission-recipe-privilege-boundary.md +121 -0
  388. package/docs/decisions/ADR-098-evidence-first-structure-discovery.md +154 -0
  389. package/docs/decisions/ADR-099-file-first-pattern-library.md +87 -0
  390. package/docs/decisions/ADR-100-global-knowledge-card-sharing.md +133 -0
  391. package/docs/decisions/ADR-101-ticket-bundle-emission.md +109 -0
  392. package/docs/decisions/ADR-102-ticket-handoff-paste-and-mcp.md +72 -0
  393. package/docs/decisions/ADR-103-global-knowledge-default-off-until-measured.md +92 -0
  394. package/docs/decisions/ADR-200-python-to-typescript-migration.md +193 -0
  395. package/docs/decisions/INDEX.md +9 -0
  396. package/docs/distribution/mcp-submission-checklist.md +3 -3
  397. package/docs/featured-commands.md +1 -1
  398. package/docs/featured-skills.md +1 -1
  399. package/docs/getting-started-by-role.md +2 -0
  400. package/docs/getting-started.md +2 -2
  401. package/docs/guidelines/agent-infra/failure-signatures.md +35 -0
  402. package/docs/guidelines/agent-infra/frontier-reasoning-operating-profile.md +5 -0
  403. package/docs/guidelines/agent-infra/size-and-scope.md +17 -0
  404. package/docs/guidelines/agent-infra/skill-quality-checklist.md +2 -2
  405. package/docs/guides/frontend-design-corpus-refresh.md +83 -0
  406. package/docs/guides/skill-preview.md +1 -1
  407. package/docs/hook-payload-capture.md +4 -4
  408. package/docs/mcp.md +1 -1
  409. package/docs/migration/consumer-template-consumption-model.md +145 -0
  410. package/docs/migration/divergences/README.md +55 -0
  411. package/docs/migration/divergences/_template.md +50 -0
  412. package/docs/migration/divergences/bench-stats-float-precision.md +72 -0
  413. package/docs/migration/divergences/mcp-telemetry-node-sqlite.md +61 -0
  414. package/docs/migration/divergences/pack-mcp-content-gzip-body.md +53 -0
  415. package/docs/migration/divergences/src-scripts-build_cloud_bundle.md +63 -0
  416. package/docs/migration/divergences/src-scripts-check_memory.md +91 -0
  417. package/docs/migration/divergences/src-scripts-inventory_abstraction_budget.md +65 -0
  418. package/docs/migration/divergences/src-scripts-lint_marketplace.md +57 -0
  419. package/docs/migration/divergences/src-scripts-lint_mcp_registry_manifest.md +70 -0
  420. package/docs/migration/divergences/src-scripts-spotcheck_thin_root.md +60 -0
  421. package/docs/migration/divergences/src-scripts-validate_agent_settings.md +58 -0
  422. package/docs/migration/node-floor.md +86 -0
  423. package/docs/migration/yaml-roundtrip-spike.md +163 -0
  424. package/docs/personas.md +6 -1
  425. package/docs/role-experiences.md +19 -0
  426. package/docs/setup/per-ide/windsurf.md +1 -1
  427. package/docs/skills-catalog.md +24 -3
  428. package/docs/threat-model.md +28 -0
  429. package/llms.txt +23 -2
  430. package/package.json +10 -15
  431. package/src/config/agent-settings.template.yml +64 -1
  432. package/src/config/discovery/packs.yml +31 -0
  433. package/src/config/discovery/unassigned-artefacts.yml +6 -0
  434. package/src/config/discovery/workspaces.yml +2 -2
  435. package/src/config/gitignore-block.txt +7 -0
  436. package/src/scripts/_cli/cmd_doctor.ts +2306 -0
  437. package/src/scripts/_cli/cmd_explain.ts +748 -0
  438. package/src/scripts/_cli/cmd_export.ts +375 -0
  439. package/src/scripts/_cli/cmd_migrate.ts +951 -0
  440. package/src/scripts/_cli/cmd_prune.ts +610 -0
  441. package/src/scripts/_cli/cmd_refresh.ts +530 -0
  442. package/src/scripts/_cli/cmd_settings_check.ts +407 -0
  443. package/src/scripts/_cli/cmd_settings_migrate.ts +344 -0
  444. package/src/scripts/_cli/cmd_sync.ts +381 -0
  445. package/src/scripts/_cli/cmd_uninstall.ts +833 -0
  446. package/src/scripts/_cli/cmd_update.ts +585 -0
  447. package/src/scripts/_cli/cmd_upgrade.ts +390 -0
  448. package/src/scripts/_cli/cmd_validate.ts +394 -0
  449. package/src/scripts/_cli/cmd_versions.ts +492 -0
  450. package/src/scripts/_cli/explain_last/assumptions.ts +114 -0
  451. package/src/scripts/_cli/explain_last/council.ts +197 -0
  452. package/src/scripts/_cli/explain_last/halt.ts +73 -0
  453. package/src/scripts/_cli/explain_last/index.ts +155 -0
  454. package/src/scripts/_cli/explain_last/inputs.ts +211 -0
  455. package/src/scripts/_cli/explain_last/memory.ts +231 -0
  456. package/src/scripts/_cli/explain_last/provider.ts +82 -0
  457. package/src/scripts/_cli/explain_last/render.ts +54 -0
  458. package/src/scripts/_cli/explain_last/route.ts +70 -0
  459. package/src/scripts/_cli/explain_last/scrubber.ts +138 -0
  460. package/src/scripts/_cli/explain_last/sections/assumptions.ts +51 -0
  461. package/src/scripts/_cli/explain_last/sections/council.ts +56 -0
  462. package/src/scripts/_cli/explain_last/sections/halt.ts +60 -0
  463. package/src/scripts/_cli/explain_last/sections/header.ts +50 -0
  464. package/src/scripts/_cli/explain_last/sections/index.ts +21 -0
  465. package/src/scripts/_cli/explain_last/sections/inputs.ts +63 -0
  466. package/src/scripts/_cli/explain_last/sections/memory.ts +124 -0
  467. package/src/scripts/_cli/explain_last/sections/pack.ts +42 -0
  468. package/src/scripts/_cli/explain_last/sections/provider.ts +51 -0
  469. package/src/scripts/_cli/explain_last/sections/route.ts +48 -0
  470. package/src/scripts/_cli/explain_last/state_loader.ts +119 -0
  471. package/src/scripts/_dispatch.bash +179 -163
  472. package/src/scripts/_lib/agent_settings.ts +1123 -0
  473. package/src/scripts/_lib/agent_src.ts +654 -0
  474. package/src/scripts/_lib/agents_overlay.ts +183 -0
  475. package/src/scripts/_lib/bench_ab_cache.ts +399 -0
  476. package/src/scripts/_lib/bench_ab_scoring.ts +352 -0
  477. package/src/scripts/_lib/bench_ab_scoring_v2.ts +751 -0
  478. package/src/scripts/_lib/bench_cost.ts +396 -0
  479. package/src/scripts/_lib/bench_quality.ts +237 -0
  480. package/src/scripts/_lib/bench_report.ts +255 -0
  481. package/src/scripts/_lib/bench_telegraph.ts +516 -0
  482. package/src/scripts/_lib/bench_telegraph_report.ts +272 -0
  483. package/src/scripts/_lib/changelog_eras.ts +398 -0
  484. package/src/scripts/_lib/claude_desktop_bundler.ts +324 -0
  485. package/src/scripts/_lib/cli_wrapper.ts +89 -0
  486. package/src/scripts/_lib/fs_atomic.ts +172 -0
  487. package/src/scripts/_lib/global_deploy_inventory.ts +639 -0
  488. package/src/scripts/_lib/install_layout.ts +87 -0
  489. package/src/scripts/_lib/install_regenerator.ts +157 -0
  490. package/src/scripts/_lib/installed_lock.ts +451 -0
  491. package/src/scripts/_lib/installed_tools.ts +518 -0
  492. package/src/scripts/_lib/json_pointers.ts +388 -0
  493. package/src/scripts/_lib/knowledge_global.ts +770 -0
  494. package/src/scripts/_lib/knowledge_global_promote.ts +453 -0
  495. package/src/scripts/_lib/knowledge_global_redaction.ts +448 -0
  496. package/src/scripts/_lib/link_crypto.ts +325 -0
  497. package/src/scripts/_lib/linked_projects.ts +613 -0
  498. package/src/scripts/_lib/model_tier.ts +65 -0
  499. package/src/scripts/_lib/module_detection.ts +275 -0
  500. package/src/scripts/_lib/node_sqlite.d.ts +32 -0
  501. package/src/scripts/_lib/pin_resolver.ts +264 -0
  502. package/src/scripts/_lib/py_random.ts +212 -0
  503. package/src/scripts/_lib/script_output.ts +147 -0
  504. package/src/scripts/_lib/security_lint.ts +623 -0
  505. package/src/scripts/_lib/surface_tiers.ts +127 -0
  506. package/src/scripts/_lib/token_count.ts +126 -0
  507. package/src/scripts/_lib/update_check.ts +297 -0
  508. package/src/scripts/_lib/user_global_paths.ts +329 -0
  509. package/src/scripts/_lib/value_ladder.ts +882 -0
  510. package/src/scripts/_lib/value_report.ts +617 -0
  511. package/src/scripts/_lib/zip_min.ts +175 -0
  512. package/src/scripts/adoption_report.ts +357 -0
  513. package/src/scripts/adoption_snapshot.ts +392 -0
  514. package/src/scripts/adoption_status.ts +424 -0
  515. package/src/scripts/adr/regenerate_index.ts +257 -0
  516. package/src/scripts/ai-image/adapters/flux.sh +45 -0
  517. package/src/scripts/ai-image/adapters/gemini-image.sh +45 -0
  518. package/src/scripts/ai-image/adapters/ideogram.sh +45 -0
  519. package/src/scripts/ai-image/adapters/recraft.sh +47 -0
  520. package/src/scripts/ai-video/adapters/comfyui.sh +3 -3
  521. package/src/scripts/ai-video/adapters/fal.sh +3 -3
  522. package/src/scripts/ai-video/adapters/gemini-veo.sh +3 -3
  523. package/src/scripts/ai-video/adapters/higgsfield.sh +3 -3
  524. package/src/scripts/ai-video/adapters/kling.sh +3 -3
  525. package/src/scripts/ai-video/adapters/musetalk.sh +2 -2
  526. package/src/scripts/ai-video/adapters/openai-images.sh +3 -3
  527. package/src/scripts/ai-video/adapters/replicate.sh +3 -3
  528. package/src/scripts/ai-video/adapters/sora.sh +3 -3
  529. package/src/scripts/ai-video/adapters/syncso.sh +3 -3
  530. package/src/scripts/ai-video/audio-adapters/allin1.sh +2 -2
  531. package/src/scripts/ai-video/audio-adapters/whisperx.sh +2 -2
  532. package/src/scripts/ai-video/lib/audio-adapter-contract.md +1 -1
  533. package/src/scripts/ai-video/lib/embed-provenance.sh +2 -2
  534. package/src/scripts/ai-video/lib/ingest-song.sh +2 -2
  535. package/src/scripts/ai-video/lib/parse-blueprint.sh +1 -1
  536. package/src/scripts/ai-video/lib/resume-scan.sh +2 -2
  537. package/src/scripts/ai-video/smoke-trace.sh +16 -7
  538. package/src/scripts/ai-video/stitch.sh +2 -2
  539. package/src/scripts/ai_council/_default_prices.ts +73 -0
  540. package/src/scripts/ai_council/advisors.ts +244 -0
  541. package/src/scripts/ai_council/airgap.ts +249 -0
  542. package/src/scripts/ai_council/budget_guard.ts +492 -0
  543. package/src/scripts/ai_council/bundler.ts +376 -0
  544. package/src/scripts/ai_council/cli_hints.ts +120 -0
  545. package/src/scripts/ai_council/clients.ts +2214 -0
  546. package/src/scripts/ai_council/compile_corpus.ts +681 -0
  547. package/src/scripts/ai_council/confidence_gate.ts +230 -0
  548. package/src/scripts/ai_council/config.ts +1729 -0
  549. package/src/scripts/ai_council/consensus.ts +551 -0
  550. package/src/scripts/ai_council/events_log.ts +327 -0
  551. package/src/scripts/ai_council/learn_low_impact_preview.ts +317 -0
  552. package/src/scripts/ai_council/low_impact.ts +1069 -0
  553. package/src/scripts/ai_council/low_impact_corpus.ts +662 -0
  554. package/src/scripts/ai_council/low_impact_intake.ts +222 -0
  555. package/src/scripts/ai_council/modes.ts +169 -0
  556. package/src/scripts/ai_council/necessity.ts +933 -0
  557. package/src/scripts/ai_council/orchestrator.ts +1689 -0
  558. package/src/scripts/ai_council/pricing.ts +267 -0
  559. package/src/scripts/ai_council/probation_gate.ts +282 -0
  560. package/src/scripts/ai_council/project_context.ts +308 -0
  561. package/src/scripts/ai_council/prompts.ts +600 -0
  562. package/src/scripts/ai_council/redact_low_impact_entry.ts +291 -0
  563. package/src/scripts/ai_council/replay.ts +314 -0
  564. package/src/scripts/ai_council/session.ts +558 -0
  565. package/src/scripts/ai_council/shadow_dispatch.ts +509 -0
  566. package/src/scripts/ai_council/solo_dispatch.ts +281 -0
  567. package/src/scripts/analysis_freshness.ts +343 -0
  568. package/src/scripts/annotate_discovery.ts +288 -0
  569. package/src/scripts/apply_modules_config.ts +537 -0
  570. package/src/scripts/audit_adr_coverage.ts +357 -0
  571. package/src/scripts/audit_auto_rules.ts +415 -0
  572. package/src/scripts/audit_cloud_compatibility.ts +608 -0
  573. package/src/scripts/audit_command_surface.ts +1227 -0
  574. package/src/scripts/audit_initial_context.ts +694 -0
  575. package/src/scripts/audit_likelihood.ts +434 -0
  576. package/src/scripts/audit_mcp_tools.ts +252 -0
  577. package/src/scripts/audit_overlap.ts +421 -0
  578. package/src/scripts/audit_skill_descriptions.ts +402 -0
  579. package/src/scripts/audit_skill_overlap.ts +576 -0
  580. package/src/scripts/audit_user_type_axis.ts +264 -0
  581. package/src/scripts/backfill_model_tier.ts +349 -0
  582. package/src/scripts/bench_ab_cache_dispatch.ts +126 -0
  583. package/src/scripts/bench_ab_clone.ts +610 -0
  584. package/src/scripts/bench_ab_diff.ts +609 -0
  585. package/src/scripts/bench_ab_integrity.ts +261 -0
  586. package/src/scripts/bench_ab_run.ts +417 -0
  587. package/src/scripts/bench_ab_task_runner.ts +1382 -0
  588. package/src/scripts/bench_ab_tracka_run.ts +436 -0
  589. package/src/scripts/bench_ab_v2_run.ts +585 -0
  590. package/src/scripts/bench_ab_v2_stats.ts +1018 -0
  591. package/src/scripts/bench_baseline_ready.ts +326 -0
  592. package/src/scripts/bench_condense_memory.ts +479 -0
  593. package/src/scripts/bench_drift_check.ts +503 -0
  594. package/src/scripts/bench_per_tool.ts +591 -0
  595. package/src/scripts/bench_rtk_savings.ts +710 -0
  596. package/src/scripts/bench_run.ts +509 -0
  597. package/src/scripts/bench_runner.ts +519 -0
  598. package/src/scripts/build_cloud_bundle.ts +692 -0
  599. package/src/scripts/build_discovery_manifest.ts +1371 -0
  600. package/src/scripts/build_linear_digest.ts +368 -0
  601. package/src/scripts/build_mcp_registry_manifest.ts +351 -0
  602. package/src/scripts/build_rule_trigger_matrix.ts +469 -0
  603. package/src/scripts/capture_showcase_session.ts +735 -0
  604. package/src/scripts/chat_history.ts +2301 -0
  605. package/src/scripts/check_always_budget.ts +694 -0
  606. package/src/scripts/check_artefact_checksums.ts +281 -0
  607. package/src/scripts/check_augment_description_cap.ts +133 -0
  608. package/src/scripts/check_augmentignore.ts +108 -0
  609. package/src/scripts/check_beta_review_markers.ts +234 -0
  610. package/src/scripts/check_bite_sized_granularity.ts +116 -0
  611. package/src/scripts/check_cluster_patterns.ts +285 -0
  612. package/src/scripts/check_command_count_messaging.ts +224 -0
  613. package/src/scripts/check_condensation.ts +900 -0
  614. package/src/scripts/check_condensed_paths.ts +414 -0
  615. package/src/scripts/check_context_paths.ts +388 -0
  616. package/src/scripts/check_council_config_location.ts +260 -0
  617. package/src/scripts/check_council_layout.ts +180 -0
  618. package/src/scripts/check_council_references.ts +345 -0
  619. package/src/scripts/check_discovery_determinism.ts +124 -0
  620. package/src/scripts/check_gate_paths.ts +230 -0
  621. package/src/scripts/check_iron_law_prominence.ts +298 -0
  622. package/src/scripts/check_kernel_rule_bundle.ts +242 -0
  623. package/src/scripts/check_knowledge_cards.ts +759 -0
  624. package/src/scripts/check_md_language.ts +291 -0
  625. package/src/scripts/check_memory.ts +845 -0
  626. package/src/scripts/check_memory_proposal.ts +351 -0
  627. package/src/scripts/check_module_management_neutral.ts +238 -0
  628. package/src/scripts/check_no_conflict_markers.ts +298 -0
  629. package/src/scripts/check_no_conflict_markers_allowlist.json +4 -0
  630. package/src/scripts/check_no_external_sources.ts +351 -0
  631. package/src/scripts/check_no_local_settings_committed.ts +69 -0
  632. package/src/scripts/check_no_new_legacy_path.ts +188 -0
  633. package/src/scripts/check_no_roadmap_refs.ts +304 -0
  634. package/src/scripts/check_one_off_location.ts +165 -0
  635. package/src/scripts/check_overlay_cascade_subdirs.ts +188 -0
  636. package/src/scripts/check_portability.ts +860 -0
  637. package/src/scripts/check_proposal.ts +0 -0
  638. package/src/scripts/check_public_catalog_links.ts +204 -0
  639. package/src/scripts/check_public_links.ts +357 -0
  640. package/src/scripts/check_references.ts +963 -0
  641. package/src/scripts/check_release_includes_discovery.ts +94 -0
  642. package/src/scripts/check_release_pr_shape.ts +222 -0
  643. package/src/scripts/check_release_published.ts +235 -0
  644. package/src/scripts/check_release_trunk_sync.ts +203 -0
  645. package/src/scripts/check_reply_consistency.ts +359 -0
  646. package/src/scripts/check_roadmap_trackable.ts +268 -0
  647. package/src/scripts/check_role_doc_links.ts +187 -0
  648. package/src/scripts/check_safety_floor_untouched.ts +160 -0
  649. package/src/scripts/check_skill_requires.ts +205 -0
  650. package/src/scripts/check_structural_breaking.ts +170 -0
  651. package/src/scripts/check_surface_tiers.ts +567 -0
  652. package/src/scripts/check_template_pin_drift.ts +222 -0
  653. package/src/scripts/check_test_coverage_diff.ts +235 -0
  654. package/src/scripts/check_token_optimizer_freshness.ts +183 -0
  655. package/src/scripts/check_trigger_evals.ts +375 -0
  656. package/src/scripts/check_update_banner.ts +143 -0
  657. package/src/scripts/ci_status.ts +0 -0
  658. package/src/scripts/ci_summary.ts +235 -0
  659. package/src/scripts/ci_time_ratio.ts +526 -0
  660. package/src/scripts/command_suggester/cooldown.ts +176 -0
  661. package/src/scripts/command_suggester/index.ts +41 -0
  662. package/src/scripts/command_suggester/loader.ts +205 -0
  663. package/src/scripts/command_suggester/match.ts +294 -0
  664. package/src/scripts/command_suggester/rank.ts +201 -0
  665. package/src/scripts/command_suggester/render.ts +122 -0
  666. package/src/scripts/command_suggester/sanitize.ts +114 -0
  667. package/src/scripts/command_suggester/settings.ts +186 -0
  668. package/src/scripts/command_suggester/types.ts +0 -0
  669. package/src/scripts/compile_router.ts +297 -0
  670. package/src/scripts/condense.sh +7 -1
  671. package/src/scripts/condense.ts +2035 -0
  672. package/src/scripts/condense_memory.ts +334 -0
  673. package/src/scripts/config/index.ts +15 -0
  674. package/src/scripts/config/packs.ts +310 -0
  675. package/src/scripts/config/presets.ts +369 -0
  676. package/src/scripts/config/profile_explain.ts +114 -0
  677. package/src/scripts/config/profiles.ts +277 -0
  678. package/src/scripts/config/session_profiles.ts +1064 -0
  679. package/src/scripts/context_hygiene_hook.ts +272 -0
  680. package/src/scripts/cost_by_conversation.ts +444 -0
  681. package/src/scripts/cost_summary.ts +407 -0
  682. package/src/scripts/council_cli.ts +2827 -0
  683. package/src/scripts/council_prune.ts +153 -0
  684. package/src/scripts/cross_repo_retrieve.ts +694 -0
  685. package/src/scripts/discovery_stats.ts +218 -0
  686. package/src/scripts/evidence_report.ts +580 -0
  687. package/src/scripts/external_sources_denylist.json +1 -0
  688. package/src/scripts/extract_audit_patterns.ts +394 -0
  689. package/src/scripts/first_run_gate_hook.ts +246 -0
  690. package/src/scripts/gen_discovery_baseline.ts +297 -0
  691. package/src/scripts/generate_capabilities_index.ts +496 -0
  692. package/src/scripts/generate_capability_matrix.ts +430 -0
  693. package/src/scripts/generate_catalog.ts +178 -0
  694. package/src/scripts/generate_command_flows.ts +316 -0
  695. package/src/scripts/generate_cookbook.ts +302 -0
  696. package/src/scripts/generate_index.ts +500 -0
  697. package/src/scripts/generate_ownership_matrix.ts +646 -0
  698. package/src/scripts/generate_pack_manifests.ts +1025 -0
  699. package/src/scripts/generate_role_experiences_catalog.ts +265 -0
  700. package/src/scripts/hermetic-install.sh +22 -11
  701. package/src/scripts/hook_manifest.yaml +24 -10
  702. package/src/scripts/hooks/augment-chat-history.sh +3 -10
  703. package/src/scripts/hooks/augment-context-hygiene.sh +3 -10
  704. package/src/scripts/hooks/augment-dispatcher.sh +3 -10
  705. package/src/scripts/hooks/augment-onboarding-gate.sh +3 -10
  706. package/src/scripts/hooks/augment-roadmap-progress.sh +3 -10
  707. package/src/scripts/hooks/block_no_verify.ts +413 -0
  708. package/src/scripts/hooks/cline-dispatcher.sh +3 -10
  709. package/src/scripts/hooks/cowork-dispatcher.sh +3 -14
  710. package/src/scripts/hooks/cursor-dispatcher.sh +3 -10
  711. package/src/scripts/hooks/dispatch_hook.ts +851 -0
  712. package/src/scripts/hooks/dispatch_issues.ts +226 -0
  713. package/src/scripts/hooks/envelope.ts +140 -0
  714. package/src/scripts/hooks/gemini-dispatcher.sh +3 -8
  715. package/src/scripts/hooks/replay_hook.ts +364 -0
  716. package/src/scripts/hooks/state_io.ts +293 -0
  717. package/src/scripts/hooks/windsurf-dispatcher.sh +3 -9
  718. package/src/scripts/hooks_doctor.ts +418 -0
  719. package/src/scripts/hooks_status.ts +292 -0
  720. package/src/scripts/injection_scan_hook.ts +285 -0
  721. package/src/scripts/install +36 -22
  722. package/src/scripts/install-hooks.sh +20 -14
  723. package/src/scripts/install.sh +38 -14
  724. package/src/scripts/install.ts +4515 -0
  725. package/src/scripts/inventory_abstraction_budget.ts +1104 -0
  726. package/src/scripts/inventory_frontmatter.ts +320 -0
  727. package/src/scripts/inventory_meta_layers.ts +516 -0
  728. package/src/scripts/iron_law_sha.ts +233 -0
  729. package/src/scripts/knowledge_global_cli.ts +1105 -0
  730. package/src/scripts/linked_projects_list.ts +310 -0
  731. package/src/scripts/lint_agent_security.ts +224 -0
  732. package/src/scripts/lint_agent_skill_names.ts +241 -0
  733. package/src/scripts/lint_agents_layout.ts +205 -0
  734. package/src/scripts/lint_agents_md.ts +294 -0
  735. package/src/scripts/lint_archived_skills.ts +309 -0
  736. package/src/scripts/lint_artefact_frontmatter.ts +359 -0
  737. package/src/scripts/lint_bench_ab.ts +319 -0
  738. package/src/scripts/lint_bench_corpus.ts +421 -0
  739. package/src/scripts/lint_command_flow_coverage.ts +231 -0
  740. package/src/scripts/lint_command_routing.ts +377 -0
  741. package/src/scripts/lint_command_tiers.ts +345 -0
  742. package/src/scripts/lint_command_verbs.ts +379 -0
  743. package/src/scripts/lint_commit_subjects.ts +243 -0
  744. package/src/scripts/lint_context_spine_usage.ts +198 -0
  745. package/src/scripts/lint_discovery_manifest.ts +540 -0
  746. package/src/scripts/lint_discovery_vocabulary.ts +393 -0
  747. package/src/scripts/lint_empty_roadmaps.ts +147 -0
  748. package/src/scripts/lint_eval_freshness.ts +335 -0
  749. package/src/scripts/lint_examples.ts +183 -0
  750. package/src/scripts/lint_explain_trace.ts +381 -0
  751. package/src/scripts/lint_featured_skills.ts +0 -0
  752. package/src/scripts/lint_flows.ts +701 -0
  753. package/src/scripts/lint_framework_leakage.ts +497 -0
  754. package/src/scripts/lint_framework_leakage_allowlist.json +8 -1
  755. package/src/scripts/lint_frontmatter_boilerplate.ts +356 -0
  756. package/src/scripts/lint_ghostwriter_source.ts +389 -0
  757. package/src/scripts/lint_global_paths.ts +420 -0
  758. package/src/scripts/lint_handoffs.ts +362 -0
  759. package/src/scripts/lint_hidden_unicode.ts +350 -0
  760. package/src/scripts/lint_hook_concern_budget.ts +319 -0
  761. package/src/scripts/lint_hook_manifest.ts +354 -0
  762. package/src/scripts/lint_instruction_smuggling.ts +173 -0
  763. package/src/scripts/lint_load_context.ts +371 -0
  764. package/src/scripts/lint_marketplace.ts +286 -0
  765. package/src/scripts/lint_marketplace_install_completeness.ts +309 -0
  766. package/src/scripts/lint_mcp_config_security.ts +225 -0
  767. package/src/scripts/lint_mcp_registry_manifest.ts +350 -0
  768. package/src/scripts/lint_media_policy_linkage.ts +224 -0
  769. package/src/scripts/lint_missions.ts +774 -0
  770. package/src/scripts/lint_model_tier_coverage.ts +151 -0
  771. package/src/scripts/lint_namespace.ts +295 -0
  772. package/src/scripts/lint_namespace_collisions.ts +203 -0
  773. package/src/scripts/lint_new_skill_gate.ts +462 -0
  774. package/src/scripts/lint_no_new_atomic_commands.ts +342 -0
  775. package/src/scripts/lint_one_off_age.ts +348 -0
  776. package/src/scripts/lint_orchestration_dsl.ts +377 -0
  777. package/src/scripts/lint_orchestrator_auto_detect.ts +177 -0
  778. package/src/scripts/lint_pack_boundaries.ts +366 -0
  779. package/src/scripts/lint_pack_dependencies.ts +541 -0
  780. package/src/scripts/lint_pack_first_win.ts +202 -0
  781. package/src/scripts/lint_persona_governance.ts +292 -0
  782. package/src/scripts/lint_positioning.ts +257 -0
  783. package/src/scripts/lint_profile_overlay_set_only.ts +324 -0
  784. package/src/scripts/lint_readme_jargon.ts +189 -0
  785. package/src/scripts/lint_readme_size.ts +73 -0
  786. package/src/scripts/lint_regression.ts +497 -0
  787. package/src/scripts/lint_roadmap_ci_steps.ts +252 -0
  788. package/src/scripts/lint_roadmap_complexity.ts +295 -0
  789. package/src/scripts/lint_roadmap_later_disposition.ts +357 -0
  790. package/src/scripts/lint_role_experiences.ts +410 -0
  791. package/src/scripts/lint_rule_interactions.ts +281 -0
  792. package/src/scripts/lint_rule_tiers.ts +169 -0
  793. package/src/scripts/lint_showcase_sessions.ts +254 -0
  794. package/src/scripts/lint_skill_frontmatter_safety.ts +279 -0
  795. package/src/scripts/lint_skill_originality.ts +586 -0
  796. package/src/scripts/lint_skill_originality_allowlist.json +20 -0
  797. package/src/scripts/lint_skill_tools.ts +320 -0
  798. package/src/scripts/lint_ticket_buildable.ts +1027 -0
  799. package/src/scripts/lint_topics_yaml.ts +203 -0
  800. package/src/scripts/lint_trust_coherence.ts +377 -0
  801. package/src/scripts/lint_value_dashboard.ts +314 -0
  802. package/src/scripts/lint_workflow_security.ts +637 -0
  803. package/src/scripts/lint_workflow_security_allowlist.json +20 -0
  804. package/src/scripts/lint_workspace_boundary.ts +248 -0
  805. package/src/scripts/mcp_parity_smoke.ts +638 -0
  806. package/src/scripts/mcp_render.ts +346 -0
  807. package/src/scripts/mcp_server/__main__.ts +28 -0
  808. package/src/scripts/mcp_server/catalog.ts +154 -0
  809. package/src/scripts/mcp_server/index.ts +24 -0
  810. package/src/scripts/mcp_server/metadata.ts +83 -0
  811. package/src/scripts/mcp_server/prompts.ts +711 -0
  812. package/src/scripts/mcp_server/resources.ts +343 -0
  813. package/src/scripts/mcp_server/server.ts +439 -0
  814. package/src/scripts/mcp_server/telemetry.ts +154 -0
  815. package/src/scripts/mcp_server/tools.ts +1031 -0
  816. package/src/scripts/mcp_setup.sh +25 -52
  817. package/src/scripts/mcp_telemetry_health.ts +362 -0
  818. package/src/scripts/mcp_telemetry_query.ts +371 -0
  819. package/src/scripts/mcp_telemetry_store.ts +422 -0
  820. package/src/scripts/measure_augment_budget.ts +453 -0
  821. package/src/scripts/measure_density.ts +618 -0
  822. package/src/scripts/measure_frugality_savings.ts +353 -0
  823. package/src/scripts/measure_markitdown_lift.ts +299 -0
  824. package/src/scripts/measure_patterns.ts +682 -0
  825. package/src/scripts/measure_projection_bytes.ts +425 -0
  826. package/src/scripts/measure_rule_budget.ts +627 -0
  827. package/src/scripts/measure_skill_reduction.ts +442 -0
  828. package/src/scripts/media/lib/adapter-common.sh +247 -0
  829. package/src/scripts/media/lib/adapter-contract.md +329 -0
  830. package/src/scripts/media/lib/fixtures/comfyui/result.json +1 -0
  831. package/src/scripts/media/lib/fixtures/fal/result.json +1 -0
  832. package/src/scripts/media/lib/fixtures/flux/asset-0001.png +0 -0
  833. package/src/scripts/media/lib/fixtures/flux/result.json +1 -0
  834. package/src/scripts/media/lib/fixtures/gemini-image/asset-0001.png +0 -0
  835. package/src/scripts/media/lib/fixtures/gemini-image/result.json +1 -0
  836. package/src/scripts/media/lib/fixtures/gemini-veo/result.json +1 -0
  837. package/src/scripts/media/lib/fixtures/higgsfield/result.json +1 -0
  838. package/src/scripts/media/lib/fixtures/ideogram/asset-0001.png +0 -0
  839. package/src/scripts/media/lib/fixtures/ideogram/result.json +1 -0
  840. package/src/scripts/media/lib/fixtures/kling/result.json +1 -0
  841. package/src/scripts/media/lib/fixtures/musetalk/result.json +1 -0
  842. package/src/scripts/media/lib/fixtures/openai-images/result.json +1 -0
  843. package/src/scripts/media/lib/fixtures/recraft/asset-0001.svg +1 -0
  844. package/src/scripts/media/lib/fixtures/recraft/result.json +1 -0
  845. package/src/scripts/media/lib/fixtures/replicate/result.json +1 -0
  846. package/src/scripts/media/lib/fixtures/sora/result.json +1 -0
  847. package/src/scripts/media/lib/fixtures/syncso/result.json +1 -0
  848. package/src/scripts/media/lib/load-config.sh +180 -0
  849. package/src/scripts/media/lib/redact.sh +85 -0
  850. package/src/scripts/memory_hash.ts +331 -0
  851. package/src/scripts/memory_lookup.ts +1278 -0
  852. package/src/scripts/memory_report.ts +845 -0
  853. package/src/scripts/memory_signal.ts +417 -0
  854. package/src/scripts/memory_status.ts +189 -0
  855. package/src/scripts/migrate_command_suggestions.ts +341 -0
  856. package/src/scripts/migrate_frontmatter_defaults.ts +539 -0
  857. package/src/scripts/migration_status.ts +301 -0
  858. package/src/scripts/mine_session.ts +645 -0
  859. package/src/scripts/minimal_safe_diff_hook.ts +355 -0
  860. package/src/scripts/move_artefact.ts +869 -0
  861. package/src/scripts/new_skill.ts +404 -0
  862. package/src/scripts/onboarding_gate_hook.ts +224 -0
  863. package/src/scripts/pack_dependency_allowlist.json +1 -1
  864. package/src/scripts/pack_mcp_content.ts +552 -0
  865. package/src/scripts/parity/README.md +140 -0
  866. package/src/scripts/parity/compare.ts +189 -0
  867. package/src/scripts/parity/coverage_diff.ts +199 -0
  868. package/src/scripts/parity/phase-manifest.json +93 -0
  869. package/src/scripts/parity/phase_gate.ts +270 -0
  870. package/src/scripts/parity/replay.ts +320 -0
  871. package/src/scripts/pattern_share.ts +363 -0
  872. package/src/scripts/plan_physical_move.ts +605 -0
  873. package/src/scripts/prediction-pool/poisson_sim.ts +537 -0
  874. package/src/scripts/prediction-pool/pool_winsim.ts +677 -0
  875. package/src/scripts/prediction-pool/score_ev.ts +546 -0
  876. package/src/scripts/print_required_checks.ts +249 -0
  877. package/src/scripts/probe_projection_fidelity.ts +468 -0
  878. package/src/scripts/probe_skill_registration.ts +787 -0
  879. package/src/scripts/profile_staleness_hook.ts +169 -0
  880. package/src/scripts/profile_use.ts +227 -0
  881. package/src/scripts/project_thin_rules.ts +387 -0
  882. package/src/scripts/propose_modules_config.ts +311 -0
  883. package/src/scripts/prototype_lint_contradictions.ts +414 -0
  884. package/src/scripts/prove_pack_extractable.ts +388 -0
  885. package/src/scripts/readme_linter.ts +913 -0
  886. package/src/scripts/redact_hook_capture.ts +325 -0
  887. package/src/scripts/refine_ticket_detect.ts +703 -0
  888. package/src/scripts/release.ts +1697 -0
  889. package/src/scripts/render_benchmark_md.ts +664 -0
  890. package/src/scripts/render_value_md.ts +506 -0
  891. package/src/scripts/repro/repro_marketplace_install_gap.sh +1 -1
  892. package/src/scripts/roadmap_progress_hook.ts +410 -0
  893. package/src/scripts/router_telemetry.ts +972 -0
  894. package/src/scripts/run.ts +98 -0
  895. package/src/scripts/run_skill_evals.ts +477 -0
  896. package/src/scripts/runtime_dispatcher.ts +586 -0
  897. package/src/scripts/runtime_handler.ts +231 -0
  898. package/src/scripts/runtime_registry.ts +394 -0
  899. package/src/scripts/schemas/command.schema.json +3 -2
  900. package/src/scripts/schemas/mission-catalog.schema.json +112 -0
  901. package/src/scripts/schemas/mission.schema.json +87 -0
  902. package/src/scripts/schemas/pack.schema.json +6 -0
  903. package/src/scripts/schemas/rule.schema.json +1 -0
  904. package/src/scripts/schemas/skill.schema.json +1 -0
  905. package/src/scripts/schemas/ticket-manifest.schema.json +35 -0
  906. package/src/scripts/schemas/ticket.schema.json +60 -0
  907. package/src/scripts/score_skill_selection.ts +570 -0
  908. package/src/scripts/security_audit_config.ts +423 -0
  909. package/src/scripts/skill_collision_clusters.ts +448 -0
  910. package/src/scripts/skill_discovery.ts +690 -0
  911. package/src/scripts/skill_linter.ts +4276 -0
  912. package/src/scripts/skill_overlap.ts +414 -0
  913. package/src/scripts/skill_preview.ts +548 -0
  914. package/src/scripts/skill_tools/audit_persona_coverage.ts +427 -0
  915. package/src/scripts/skill_tools/audit_user_type_coverage.ts +507 -0
  916. package/src/scripts/skill_tools/index.ts +28 -0
  917. package/src/scripts/skill_tools/run_block_d_eval.ts +373 -0
  918. package/src/scripts/skill_tools/score_skill_relevance.ts +475 -0
  919. package/src/scripts/skill_tools/suggest_skill_for_task.ts +288 -0
  920. package/src/scripts/skill_trigger_eval.ts +1046 -0
  921. package/src/scripts/skill_usage_collect.ts +465 -0
  922. package/src/scripts/skill_usage_report.ts +364 -0
  923. package/src/scripts/smoke/kernel.sh +4 -5
  924. package/src/scripts/smoke/router.sh +76 -76
  925. package/src/scripts/smoke/schema.sh +2 -2
  926. package/src/scripts/smoke/skills.sh +73 -52
  927. package/src/scripts/smoke_path_resolution.ts +194 -0
  928. package/src/scripts/smoke_quickstart.ts +224 -0
  929. package/src/scripts/snapshot_agent_outputs.ts +375 -0
  930. package/src/scripts/spotcheck_thin_root.ts +247 -0
  931. package/src/scripts/surface-tiers.yml +68 -0
  932. package/src/scripts/sync_agent_settings.ts +763 -0
  933. package/src/scripts/sync_github_metadata.ts +550 -0
  934. package/src/scripts/sync_gitignore.ts +630 -0
  935. package/src/scripts/sync_yaml_rt.ts +910 -0
  936. package/src/scripts/telegraph_stats.ts +447 -0
  937. package/src/scripts/tool_registry.ts +330 -0
  938. package/src/scripts/tools/adapter_errors.ts +93 -0
  939. package/src/scripts/tools/base_adapter.ts +147 -0
  940. package/src/scripts/tools/github_adapter.ts +229 -0
  941. package/src/scripts/tools/jira_adapter.ts +196 -0
  942. package/src/scripts/trigger_coverage.ts +251 -0
  943. package/src/scripts/update_counts.ts +284 -0
  944. package/src/scripts/update_prices.ts +219 -0
  945. package/src/scripts/validate_agent_settings.ts +265 -0
  946. package/src/scripts/validate_decision_engine.ts +366 -0
  947. package/src/scripts/validate_discovery_manifest.ts +160 -0
  948. package/src/scripts/validate_frontmatter.ts +1030 -0
  949. package/src/scripts/validate_pack_yaml.ts +0 -0
  950. package/src/scripts/validate_safe_paths.ts +164 -0
  951. package/src/scripts/validate_telegraph_carveouts.ts +485 -0
  952. package/src/scripts/verify_before_complete_hook.ts +306 -0
  953. package/src/scripts/verify_physical_move.ts +411 -0
  954. package/src/scripts/wrapper_freshness_hook.ts +179 -0
  955. package/dist/agent-src/scripts/archive_completed_roadmaps.py +0 -171
  956. package/dist/agent-src/scripts/update_roadmap_progress.py +0 -537
  957. package/dist/agent-src/skills/corpus-grounding/scripts/bm25_search.py +0 -212
  958. package/dist/agent-src/skills/corpus-grounding/scripts/decision_engine.py +0 -438
  959. package/dist/agent-src/skills/corpus-grounding/scripts/ground.py +0 -166
  960. package/dist/agent-src/skills/corpus-grounding/scripts/schema_validator.py +0 -160
  961. package/dist/agent-src/skills/design-tokens/scripts/tokens.py +0 -296
  962. package/dist/agent-src/skills/react-shadcn-ui/scripts/shadcn_add.py +0 -299
  963. package/dist/agent-src/skills/tailwind-engineer/scripts/tailwind_config_gen.py +0 -463
  964. package/dist/agent-src/templates/scripts/check_memory.py +0 -282
  965. package/dist/agent-src/templates/scripts/check_memory_proposal.py +0 -180
  966. package/dist/agent-src/templates/scripts/implement_ticket/__init__.py +0 -94
  967. package/dist/agent-src/templates/scripts/implement_ticket/__main__.py +0 -15
  968. package/dist/agent-src/templates/scripts/memory_hash.py +0 -75
  969. package/dist/agent-src/templates/scripts/memory_lookup.py +0 -436
  970. package/dist/agent-src/templates/scripts/memory_report.py +0 -314
  971. package/dist/agent-src/templates/scripts/memory_signal.py +0 -165
  972. package/dist/agent-src/templates/scripts/memory_status.py +0 -76
  973. package/dist/agent-src/templates/scripts/pr_review_routing.py +0 -340
  974. package/dist/agent-src/templates/scripts/pr_risk_review.py +0 -211
  975. package/dist/agent-src/templates/scripts/telemetry/__init__.py +0 -42
  976. package/dist/agent-src/templates/scripts/telemetry/aggregator.py +0 -169
  977. package/dist/agent-src/templates/scripts/telemetry/boundary.py +0 -171
  978. package/dist/agent-src/templates/scripts/telemetry/engagement.py +0 -297
  979. package/dist/agent-src/templates/scripts/telemetry/report_renderer.py +0 -197
  980. package/dist/agent-src/templates/scripts/telemetry/settings.py +0 -177
  981. package/dist/agent-src/templates/scripts/telemetry_record.py +0 -179
  982. package/dist/agent-src/templates/scripts/telemetry_report.py +0 -161
  983. package/dist/agent-src/templates/scripts/telemetry_status.py +0 -142
  984. package/dist/agent-src/templates/scripts/tier_usage_report.py +0 -183
  985. package/dist/agent-src/templates/scripts/work_engine/__init__.py +0 -58
  986. package/dist/agent-src/templates/scripts/work_engine/__main__.py +0 -9
  987. package/dist/agent-src/templates/scripts/work_engine/_lib/__init__.py +0 -7
  988. package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.py +0 -840
  989. package/dist/agent-src/templates/scripts/work_engine/_lib/user_global_paths.py +0 -249
  990. package/dist/agent-src/templates/scripts/work_engine/cli.py +0 -195
  991. package/dist/agent-src/templates/scripts/work_engine/cli_args.py +0 -116
  992. package/dist/agent-src/templates/scripts/work_engine/delivery_state.py +0 -137
  993. package/dist/agent-src/templates/scripts/work_engine/directives/__init__.py +0 -33
  994. package/dist/agent-src/templates/scripts/work_engine/directives/backend/__init__.py +0 -98
  995. package/dist/agent-src/templates/scripts/work_engine/directives/backend/analyze.py +0 -98
  996. package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.py +0 -145
  997. package/dist/agent-src/templates/scripts/work_engine/directives/backend/memory.py +0 -136
  998. package/dist/agent-src/templates/scripts/work_engine/directives/backend/plan.py +0 -175
  999. package/dist/agent-src/templates/scripts/work_engine/directives/backend/refine.py +0 -396
  1000. package/dist/agent-src/templates/scripts/work_engine/directives/backend/report.py +0 -227
  1001. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.py +0 -180
  1002. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.py +0 -170
  1003. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/__init__.py +0 -116
  1004. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/contract.py +0 -254
  1005. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.py +0 -229
  1006. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/ui.py +0 -231
  1007. package/dist/agent-src/templates/scripts/work_engine/directives/ui/__init__.py +0 -113
  1008. package/dist/agent-src/templates/scripts/work_engine/directives/ui/_passthrough.py +0 -44
  1009. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.py +0 -241
  1010. package/dist/agent-src/templates/scripts/work_engine/directives/ui/audit.py +0 -414
  1011. package/dist/agent-src/templates/scripts/work_engine/directives/ui/design.py +0 -335
  1012. package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.py +0 -513
  1013. package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.py +0 -471
  1014. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/__init__.py +0 -119
  1015. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/_skipped.py +0 -37
  1016. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/apply.py +0 -165
  1017. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/refine.py +0 -66
  1018. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/report.py +0 -62
  1019. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/test.py +0 -115
  1020. package/dist/agent-src/templates/scripts/work_engine/dispatcher.py +0 -331
  1021. package/dist/agent-src/templates/scripts/work_engine/emitters.py +0 -68
  1022. package/dist/agent-src/templates/scripts/work_engine/errors.py +0 -19
  1023. package/dist/agent-src/templates/scripts/work_engine/hook_bootstrap.py +0 -91
  1024. package/dist/agent-src/templates/scripts/work_engine/hooks/__init__.py +0 -54
  1025. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/__init__.py +0 -35
  1026. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/_chat_history_base.py +0 -59
  1027. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_append.py +0 -43
  1028. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_halt_append.py +0 -41
  1029. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_gate.py +0 -162
  1030. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.py +0 -163
  1031. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/directive_set_guard.py +0 -53
  1032. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/halt_surface_audit.py +0 -50
  1033. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.py +0 -141
  1034. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/state_shape_validation.py +0 -52
  1035. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/trace.py +0 -84
  1036. package/dist/agent-src/templates/scripts/work_engine/hooks/context.py +0 -66
  1037. package/dist/agent-src/templates/scripts/work_engine/hooks/events.py +0 -44
  1038. package/dist/agent-src/templates/scripts/work_engine/hooks/exceptions.py +0 -79
  1039. package/dist/agent-src/templates/scripts/work_engine/hooks/registry.py +0 -60
  1040. package/dist/agent-src/templates/scripts/work_engine/hooks/runner.py +0 -73
  1041. package/dist/agent-src/templates/scripts/work_engine/hooks/settings.py +0 -196
  1042. package/dist/agent-src/templates/scripts/work_engine/input_builders.py +0 -163
  1043. package/dist/agent-src/templates/scripts/work_engine/intent/__init__.py +0 -47
  1044. package/dist/agent-src/templates/scripts/work_engine/intent/classify.py +0 -280
  1045. package/dist/agent-src/templates/scripts/work_engine/migration/__init__.py +0 -8
  1046. package/dist/agent-src/templates/scripts/work_engine/migration/v0_to_v1.py +0 -231
  1047. package/dist/agent-src/templates/scripts/work_engine/orchestration.py +0 -193
  1048. package/dist/agent-src/templates/scripts/work_engine/persona_policy.py +0 -85
  1049. package/dist/agent-src/templates/scripts/work_engine/resolvers/__init__.py +0 -22
  1050. package/dist/agent-src/templates/scripts/work_engine/resolvers/diff.py +0 -106
  1051. package/dist/agent-src/templates/scripts/work_engine/resolvers/file.py +0 -113
  1052. package/dist/agent-src/templates/scripts/work_engine/resolvers/prompt.py +0 -90
  1053. package/dist/agent-src/templates/scripts/work_engine/scoring/__init__.py +0 -14
  1054. package/dist/agent-src/templates/scripts/work_engine/scoring/confidence.py +0 -300
  1055. package/dist/agent-src/templates/scripts/work_engine/scoring/decision_engine.py +0 -351
  1056. package/dist/agent-src/templates/scripts/work_engine/scoring/decision_trace.py +0 -141
  1057. package/dist/agent-src/templates/scripts/work_engine/scoring/memory_visibility.py +0 -283
  1058. package/dist/agent-src/templates/scripts/work_engine/stack/__init__.py +0 -31
  1059. package/dist/agent-src/templates/scripts/work_engine/stack/detect.py +0 -187
  1060. package/dist/agent-src/templates/scripts/work_engine/stack/runner.py +0 -481
  1061. package/dist/agent-src/templates/scripts/work_engine/state.py +0 -694
  1062. package/dist/agent-src/templates/scripts/work_engine/state_io.py +0 -202
  1063. package/dist/cli/python/resolvePython.js +0 -38
  1064. package/dist/cli/python/resolvePython.js.map +0 -1
  1065. package/src/scripts/__pycache__/validate_frontmatter.cpython-312.pyc +0 -0
  1066. package/src/scripts/_archive/_backfill_skill_domains.py +0 -140
  1067. package/src/scripts/_archive/_bootstrap_tier_frontmatter.py +0 -151
  1068. package/src/scripts/_archive/_p43_bodies.py +0 -235
  1069. package/src/scripts/_archive/_p43_condense.py +0 -118
  1070. package/src/scripts/_archive/_p4_migrate.py +0 -199
  1071. package/src/scripts/_archive/_phase2_shim_helper.py +0 -109
  1072. package/src/scripts/_archive/_pilot_council_question.py +0 -57
  1073. package/src/scripts/_cli/__init__.py +0 -0
  1074. package/src/scripts/_cli/cmd_doctor.py +0 -1669
  1075. package/src/scripts/_cli/cmd_explain.py +0 -355
  1076. package/src/scripts/_cli/cmd_export.py +0 -157
  1077. package/src/scripts/_cli/cmd_migrate.py +0 -524
  1078. package/src/scripts/_cli/cmd_prune.py +0 -322
  1079. package/src/scripts/_cli/cmd_refresh.py +0 -179
  1080. package/src/scripts/_cli/cmd_settings_check.py +0 -171
  1081. package/src/scripts/_cli/cmd_settings_migrate.py +0 -147
  1082. package/src/scripts/_cli/cmd_sync.py +0 -166
  1083. package/src/scripts/_cli/cmd_uninstall.py +0 -476
  1084. package/src/scripts/_cli/cmd_update.py +0 -279
  1085. package/src/scripts/_cli/cmd_upgrade.py +0 -172
  1086. package/src/scripts/_cli/cmd_validate.py +0 -177
  1087. package/src/scripts/_cli/cmd_versions.py +0 -160
  1088. package/src/scripts/_cli/explain_last/__init__.py +0 -122
  1089. package/src/scripts/_cli/explain_last/assumptions.py +0 -59
  1090. package/src/scripts/_cli/explain_last/council.py +0 -105
  1091. package/src/scripts/_cli/explain_last/halt.py +0 -44
  1092. package/src/scripts/_cli/explain_last/inputs.py +0 -128
  1093. package/src/scripts/_cli/explain_last/memory.py +0 -94
  1094. package/src/scripts/_cli/explain_last/provider.py +0 -52
  1095. package/src/scripts/_cli/explain_last/render.py +0 -52
  1096. package/src/scripts/_cli/explain_last/route.py +0 -59
  1097. package/src/scripts/_cli/explain_last/scrubber.py +0 -105
  1098. package/src/scripts/_cli/explain_last/sections/__init__.py +0 -35
  1099. package/src/scripts/_cli/explain_last/sections/assumptions.py +0 -21
  1100. package/src/scripts/_cli/explain_last/sections/council.py +0 -27
  1101. package/src/scripts/_cli/explain_last/sections/halt.py +0 -31
  1102. package/src/scripts/_cli/explain_last/sections/header.py +0 -24
  1103. package/src/scripts/_cli/explain_last/sections/inputs.py +0 -27
  1104. package/src/scripts/_cli/explain_last/sections/memory.py +0 -21
  1105. package/src/scripts/_cli/explain_last/sections/pack.py +0 -16
  1106. package/src/scripts/_cli/explain_last/sections/provider.py +0 -26
  1107. package/src/scripts/_cli/explain_last/sections/route.py +0 -22
  1108. package/src/scripts/_cli/explain_last/state_loader.py +0 -76
  1109. package/src/scripts/_emit_domain_table.py +0 -35
  1110. package/src/scripts/_lib/__init__.py +0 -5
  1111. package/src/scripts/_lib/__pycache__/__init__.cpython-312.pyc +0 -0
  1112. package/src/scripts/_lib/__pycache__/agent_src.cpython-312.pyc +0 -0
  1113. package/src/scripts/_lib/agent_settings.py +0 -840
  1114. package/src/scripts/_lib/agent_src.py +0 -491
  1115. package/src/scripts/_lib/agents_overlay.py +0 -120
  1116. package/src/scripts/_lib/bench_ab_cache.py +0 -162
  1117. package/src/scripts/_lib/bench_ab_scoring.py +0 -209
  1118. package/src/scripts/_lib/bench_ab_scoring_v2.py +0 -227
  1119. package/src/scripts/_lib/bench_cost.py +0 -138
  1120. package/src/scripts/_lib/bench_quality.py +0 -118
  1121. package/src/scripts/_lib/bench_report.py +0 -149
  1122. package/src/scripts/_lib/bench_telegraph.py +0 -273
  1123. package/src/scripts/_lib/bench_telegraph_report.py +0 -151
  1124. package/src/scripts/_lib/changelog_eras.py +0 -330
  1125. package/src/scripts/_lib/claude_desktop_bundler.py +0 -238
  1126. package/src/scripts/_lib/cli_wrapper.py +0 -64
  1127. package/src/scripts/_lib/fs_atomic.py +0 -116
  1128. package/src/scripts/_lib/global_deploy_inventory.py +0 -312
  1129. package/src/scripts/_lib/install_regenerator.py +0 -134
  1130. package/src/scripts/_lib/installed_lock.py +0 -256
  1131. package/src/scripts/_lib/installed_tools.py +0 -381
  1132. package/src/scripts/_lib/json_pointers.py +0 -260
  1133. package/src/scripts/_lib/link_crypto.py +0 -206
  1134. package/src/scripts/_lib/linked_projects.py +0 -238
  1135. package/src/scripts/_lib/model_tier.py +0 -52
  1136. package/src/scripts/_lib/module_detection.py +0 -223
  1137. package/src/scripts/_lib/pin_resolver.py +0 -152
  1138. package/src/scripts/_lib/script_output.py +0 -144
  1139. package/src/scripts/_lib/security_lint.py +0 -228
  1140. package/src/scripts/_lib/token_count.py +0 -95
  1141. package/src/scripts/_lib/update_check.py +0 -207
  1142. package/src/scripts/_lib/user_global_paths.py +0 -249
  1143. package/src/scripts/_lib/value_ladder.py +0 -696
  1144. package/src/scripts/_lib/value_report.py +0 -455
  1145. package/src/scripts/_phase4_bucket.py +0 -210
  1146. package/src/scripts/_pilot_measure.py +0 -53
  1147. package/src/scripts/_tmp_scan_framework_leakage.py +0 -119
  1148. package/src/scripts/adoption_report.py +0 -195
  1149. package/src/scripts/adoption_snapshot.py +0 -219
  1150. package/src/scripts/adoption_status.py +0 -166
  1151. package/src/scripts/adr/regenerate_index.py +0 -79
  1152. package/src/scripts/ai-video/lib/adapter-common.sh +0 -231
  1153. package/src/scripts/ai-video/lib/adapter-contract.md +0 -329
  1154. package/src/scripts/ai-video/lib/fixtures/comfyui/result.json +0 -1
  1155. package/src/scripts/ai-video/lib/fixtures/fal/result.json +0 -1
  1156. package/src/scripts/ai-video/lib/fixtures/gemini-veo/result.json +0 -1
  1157. package/src/scripts/ai-video/lib/fixtures/higgsfield/result.json +0 -1
  1158. package/src/scripts/ai-video/lib/fixtures/kling/result.json +0 -1
  1159. package/src/scripts/ai-video/lib/fixtures/musetalk/result.json +0 -1
  1160. package/src/scripts/ai-video/lib/fixtures/openai-images/result.json +0 -1
  1161. package/src/scripts/ai-video/lib/fixtures/replicate/result.json +0 -1
  1162. package/src/scripts/ai-video/lib/fixtures/sora/result.json +0 -1
  1163. package/src/scripts/ai-video/lib/fixtures/syncso/result.json +0 -1
  1164. package/src/scripts/ai-video/lib/load-config.sh +0 -180
  1165. package/src/scripts/ai-video/lib/redact.sh +0 -85
  1166. package/src/scripts/ai_council/__init__.py +0 -40
  1167. package/src/scripts/ai_council/_default_prices.py +0 -50
  1168. package/src/scripts/ai_council/advisors.py +0 -148
  1169. package/src/scripts/ai_council/airgap.py +0 -165
  1170. package/src/scripts/ai_council/budget_guard.py +0 -202
  1171. package/src/scripts/ai_council/bundler.py +0 -263
  1172. package/src/scripts/ai_council/cli_hints.py +0 -123
  1173. package/src/scripts/ai_council/clients.py +0 -1385
  1174. package/src/scripts/ai_council/compile_corpus.py +0 -179
  1175. package/src/scripts/ai_council/confidence_gate.py +0 -156
  1176. package/src/scripts/ai_council/config.py +0 -1419
  1177. package/src/scripts/ai_council/consensus.py +0 -329
  1178. package/src/scripts/ai_council/events_log.py +0 -141
  1179. package/src/scripts/ai_council/learn_low_impact_preview.py +0 -252
  1180. package/src/scripts/ai_council/low_impact.py +0 -714
  1181. package/src/scripts/ai_council/low_impact_corpus.py +0 -466
  1182. package/src/scripts/ai_council/low_impact_intake.py +0 -163
  1183. package/src/scripts/ai_council/modes.py +0 -131
  1184. package/src/scripts/ai_council/necessity.py +0 -782
  1185. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_2a4_acceptance.py +0 -208
  1186. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_add_quiet.py +0 -149
  1187. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_budget_v2_audit.py +0 -206
  1188. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_context_layer_v1_estimate.py +0 -67
  1189. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_context_layer_v1_review.py +0 -292
  1190. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_followups_review.py +0 -259
  1191. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_inject_quiet_flag.py +0 -33
  1192. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_measure_v2.sh +0 -36
  1193. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_measure_verbosity.sh +0 -26
  1194. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_nondestructive_inline_audit.py +0 -209
  1195. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_per_task.sh +0 -41
  1196. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_phase4_dispatch_latency.py +0 -108
  1197. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_phase6_trigger_jaccard.py +0 -92
  1198. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_phase_2a_budget_rebalance.py +0 -257
  1199. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_phase_2a_post_revert.py +0 -197
  1200. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_rebalancing_audit.py +0 -149
  1201. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_roundtrip.py +0 -111
  1202. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_rule_hardening_v1.py +0 -251
  1203. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_silent_taskfiles.py +0 -98
  1204. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_structural_open_questions.py +0 -232
  1205. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_structural_optimization.py +0 -144
  1206. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_structural_v3_gaps.py +0 -252
  1207. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_structural_v3_review.py +0 -240
  1208. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_tier_retrofit.py +0 -180
  1209. package/src/scripts/ai_council/orchestrator.py +0 -1206
  1210. package/src/scripts/ai_council/pricing.py +0 -215
  1211. package/src/scripts/ai_council/probation_gate.py +0 -152
  1212. package/src/scripts/ai_council/project_context.py +0 -159
  1213. package/src/scripts/ai_council/prompts.py +0 -567
  1214. package/src/scripts/ai_council/redact_low_impact_entry.py +0 -155
  1215. package/src/scripts/ai_council/replay.py +0 -155
  1216. package/src/scripts/ai_council/session.py +0 -366
  1217. package/src/scripts/ai_council/shadow_dispatch.py +0 -235
  1218. package/src/scripts/ai_council/solo_dispatch.py +0 -226
  1219. package/src/scripts/annotate_discovery.py +0 -149
  1220. package/src/scripts/apply_modules_config.py +0 -290
  1221. package/src/scripts/audit_adr_coverage.py +0 -173
  1222. package/src/scripts/audit_auto_rules.py +0 -175
  1223. package/src/scripts/audit_cloud_compatibility.py +0 -362
  1224. package/src/scripts/audit_command_surface.py +0 -682
  1225. package/src/scripts/audit_initial_context.py +0 -237
  1226. package/src/scripts/audit_likelihood.py +0 -148
  1227. package/src/scripts/audit_mcp_tools.py +0 -146
  1228. package/src/scripts/audit_overlap.py +0 -145
  1229. package/src/scripts/audit_skill_descriptions.py +0 -180
  1230. package/src/scripts/audit_skill_overlap.py +0 -207
  1231. package/src/scripts/audit_user_type_axis.py +0 -140
  1232. package/src/scripts/backfill_model_tier.py +0 -184
  1233. package/src/scripts/bench_ab_cache_dispatch.py +0 -68
  1234. package/src/scripts/bench_ab_clone.py +0 -220
  1235. package/src/scripts/bench_ab_diff.py +0 -220
  1236. package/src/scripts/bench_ab_integrity.py +0 -143
  1237. package/src/scripts/bench_ab_run.py +0 -235
  1238. package/src/scripts/bench_ab_task_runner.py +0 -814
  1239. package/src/scripts/bench_ab_tracka_run.py +0 -202
  1240. package/src/scripts/bench_ab_v2_run.py +0 -247
  1241. package/src/scripts/bench_ab_v2_stats.py +0 -347
  1242. package/src/scripts/bench_baseline_ready.py +0 -108
  1243. package/src/scripts/bench_condense_memory.py +0 -168
  1244. package/src/scripts/bench_drift_check.py +0 -151
  1245. package/src/scripts/bench_per_tool.py +0 -216
  1246. package/src/scripts/bench_rtk_savings.py +0 -320
  1247. package/src/scripts/bench_run.py +0 -272
  1248. package/src/scripts/bench_runner.py +0 -158
  1249. package/src/scripts/build_cloud_bundle.py +0 -458
  1250. package/src/scripts/build_discovery_manifest.py +0 -757
  1251. package/src/scripts/build_linear_digest.py +0 -260
  1252. package/src/scripts/build_mcp_registry_manifest.py +0 -181
  1253. package/src/scripts/build_rule_trigger_matrix.py +0 -350
  1254. package/src/scripts/capture_showcase_session.py +0 -361
  1255. package/src/scripts/chat_history.py +0 -1799
  1256. package/src/scripts/check_always_budget.py +0 -532
  1257. package/src/scripts/check_artefact_checksums.py +0 -111
  1258. package/src/scripts/check_augment_description_cap.py +0 -79
  1259. package/src/scripts/check_augmentignore.py +0 -72
  1260. package/src/scripts/check_beta_review_markers.py +0 -127
  1261. package/src/scripts/check_bite_sized_granularity.py +0 -98
  1262. package/src/scripts/check_cluster_patterns.py +0 -206
  1263. package/src/scripts/check_command_count_messaging.py +0 -152
  1264. package/src/scripts/check_condensation.py +0 -375
  1265. package/src/scripts/check_condensed_paths.py +0 -231
  1266. package/src/scripts/check_context_paths.py +0 -202
  1267. package/src/scripts/check_council_layout.py +0 -125
  1268. package/src/scripts/check_council_references.py +0 -228
  1269. package/src/scripts/check_discovery_determinism.py +0 -70
  1270. package/src/scripts/check_gate_paths.py +0 -128
  1271. package/src/scripts/check_iron_law_prominence.py +0 -145
  1272. package/src/scripts/check_kernel_rule_bundle.py +0 -151
  1273. package/src/scripts/check_md_language.py +0 -161
  1274. package/src/scripts/check_memory.py +0 -429
  1275. package/src/scripts/check_memory_proposal.py +0 -182
  1276. package/src/scripts/check_module_management_neutral.py +0 -147
  1277. package/src/scripts/check_no_external_sources.py +0 -101
  1278. package/src/scripts/check_no_local_settings_committed.py +0 -51
  1279. package/src/scripts/check_no_new_legacy_path.py +0 -100
  1280. package/src/scripts/check_no_roadmap_refs.py +0 -155
  1281. package/src/scripts/check_one_off_location.py +0 -81
  1282. package/src/scripts/check_overlay_cascade_subdirs.py +0 -129
  1283. package/src/scripts/check_portability.py +0 -574
  1284. package/src/scripts/check_proposal.py +0 -269
  1285. package/src/scripts/check_public_catalog_links.py +0 -125
  1286. package/src/scripts/check_public_links.py +0 -185
  1287. package/src/scripts/check_references.py +0 -559
  1288. package/src/scripts/check_release_includes_discovery.py +0 -61
  1289. package/src/scripts/check_release_pr_shape.py +0 -123
  1290. package/src/scripts/check_release_published.py +0 -145
  1291. package/src/scripts/check_release_trunk_sync.py +0 -152
  1292. package/src/scripts/check_reply_consistency.py +0 -169
  1293. package/src/scripts/check_roadmap_trackable.py +0 -114
  1294. package/src/scripts/check_role_doc_links.py +0 -110
  1295. package/src/scripts/check_safety_floor_untouched.py +0 -125
  1296. package/src/scripts/check_skill_requires.py +0 -147
  1297. package/src/scripts/check_template_pin_drift.py +0 -129
  1298. package/src/scripts/check_test_coverage_diff.py +0 -180
  1299. package/src/scripts/check_token_optimizer_freshness.py +0 -146
  1300. package/src/scripts/check_update_banner.py +0 -86
  1301. package/src/scripts/ci_status.py +0 -301
  1302. package/src/scripts/ci_summary.py +0 -131
  1303. package/src/scripts/ci_time_ratio.py +0 -168
  1304. package/src/scripts/command_suggester/__init__.py +0 -51
  1305. package/src/scripts/command_suggester/cooldown.py +0 -132
  1306. package/src/scripts/command_suggester/loader.py +0 -73
  1307. package/src/scripts/command_suggester/match.py +0 -180
  1308. package/src/scripts/command_suggester/rank.py +0 -120
  1309. package/src/scripts/command_suggester/render.py +0 -86
  1310. package/src/scripts/command_suggester/sanitize.py +0 -113
  1311. package/src/scripts/command_suggester/settings.py +0 -127
  1312. package/src/scripts/command_suggester/types.py +0 -78
  1313. package/src/scripts/compile_router.py +0 -232
  1314. package/src/scripts/condense.py +0 -1919
  1315. package/src/scripts/condense_memory.py +0 -178
  1316. package/src/scripts/config/__init__.py +0 -9
  1317. package/src/scripts/config/packs.py +0 -157
  1318. package/src/scripts/config/presets.py +0 -224
  1319. package/src/scripts/config/profile_explain.py +0 -89
  1320. package/src/scripts/config/profiles.py +0 -191
  1321. package/src/scripts/config/session_profiles.py +0 -542
  1322. package/src/scripts/context_hygiene_hook.py +0 -181
  1323. package/src/scripts/cost_by_conversation.py +0 -78
  1324. package/src/scripts/cost_summary.py +0 -97
  1325. package/src/scripts/council_cli.py +0 -2571
  1326. package/src/scripts/council_prune.py +0 -81
  1327. package/src/scripts/cross_repo_retrieve.py +0 -172
  1328. package/src/scripts/discovery_stats.py +0 -70
  1329. package/src/scripts/extract_audit_patterns.py +0 -202
  1330. package/src/scripts/first_run_gate_hook.py +0 -179
  1331. package/src/scripts/gen_discovery_baseline.py +0 -127
  1332. package/src/scripts/generate_catalog.py +0 -116
  1333. package/src/scripts/generate_command_flows.py +0 -191
  1334. package/src/scripts/generate_index.py +0 -303
  1335. package/src/scripts/generate_ownership_matrix.py +0 -378
  1336. package/src/scripts/generate_pack_manifests.py +0 -340
  1337. package/src/scripts/hooks/__init__.py +0 -1
  1338. package/src/scripts/hooks/dispatch_hook.py +0 -461
  1339. package/src/scripts/hooks/dispatch_issues.py +0 -136
  1340. package/src/scripts/hooks/envelope.py +0 -98
  1341. package/src/scripts/hooks/replay_hook.py +0 -144
  1342. package/src/scripts/hooks/state_io.py +0 -145
  1343. package/src/scripts/hooks_doctor.py +0 -223
  1344. package/src/scripts/hooks_status.py +0 -157
  1345. package/src/scripts/injection_scan_hook.py +0 -145
  1346. package/src/scripts/install.py +0 -5258
  1347. package/src/scripts/inventory_abstraction_budget.py +0 -622
  1348. package/src/scripts/inventory_frontmatter.py +0 -164
  1349. package/src/scripts/inventory_meta_layers.py +0 -288
  1350. package/src/scripts/iron_law_sha.py +0 -107
  1351. package/src/scripts/linked_projects_list.py +0 -91
  1352. package/src/scripts/lint_agent_security.py +0 -112
  1353. package/src/scripts/lint_agent_skill_names.py +0 -150
  1354. package/src/scripts/lint_agents_layout.py +0 -197
  1355. package/src/scripts/lint_agents_md.py +0 -210
  1356. package/src/scripts/lint_archived_skills.py +0 -159
  1357. package/src/scripts/lint_artefact_frontmatter.py +0 -188
  1358. package/src/scripts/lint_bench_ab.py +0 -173
  1359. package/src/scripts/lint_bench_corpus.py +0 -255
  1360. package/src/scripts/lint_command_flow_coverage.py +0 -132
  1361. package/src/scripts/lint_command_routing.py +0 -160
  1362. package/src/scripts/lint_command_tiers.py +0 -216
  1363. package/src/scripts/lint_command_verbs.py +0 -206
  1364. package/src/scripts/lint_commit_subjects.py +0 -139
  1365. package/src/scripts/lint_context_spine_usage.py +0 -137
  1366. package/src/scripts/lint_discovery_manifest.py +0 -176
  1367. package/src/scripts/lint_discovery_vocabulary.py +0 -222
  1368. package/src/scripts/lint_empty_roadmaps.py +0 -80
  1369. package/src/scripts/lint_examples.py +0 -102
  1370. package/src/scripts/lint_explain_trace.py +0 -80
  1371. package/src/scripts/lint_featured_skills.py +0 -144
  1372. package/src/scripts/lint_flows.py +0 -215
  1373. package/src/scripts/lint_framework_leakage.py +0 -375
  1374. package/src/scripts/lint_frontmatter_boilerplate.py +0 -77
  1375. package/src/scripts/lint_ghostwriter_source.py +0 -242
  1376. package/src/scripts/lint_global_paths.py +0 -148
  1377. package/src/scripts/lint_handoffs.py +0 -217
  1378. package/src/scripts/lint_hidden_unicode.py +0 -132
  1379. package/src/scripts/lint_hook_concern_budget.py +0 -207
  1380. package/src/scripts/lint_hook_manifest.py +0 -217
  1381. package/src/scripts/lint_instruction_smuggling.py +0 -107
  1382. package/src/scripts/lint_load_context.py +0 -196
  1383. package/src/scripts/lint_marketplace.py +0 -180
  1384. package/src/scripts/lint_marketplace_install_completeness.py +0 -198
  1385. package/src/scripts/lint_mcp_config_security.py +0 -124
  1386. package/src/scripts/lint_mcp_registry_manifest.py +0 -69
  1387. package/src/scripts/lint_media_policy_linkage.py +0 -140
  1388. package/src/scripts/lint_model_tier_coverage.py +0 -73
  1389. package/src/scripts/lint_namespace.py +0 -135
  1390. package/src/scripts/lint_namespace_collisions.py +0 -103
  1391. package/src/scripts/lint_new_skill_gate.py +0 -144
  1392. package/src/scripts/lint_no_new_atomic_commands.py +0 -180
  1393. package/src/scripts/lint_one_off_age.py +0 -184
  1394. package/src/scripts/lint_orchestration_dsl.py +0 -217
  1395. package/src/scripts/lint_orchestrator_auto_detect.py +0 -111
  1396. package/src/scripts/lint_pack_boundaries.py +0 -147
  1397. package/src/scripts/lint_pack_dependencies.py +0 -137
  1398. package/src/scripts/lint_pack_first_win.py +0 -121
  1399. package/src/scripts/lint_persona_governance.py +0 -164
  1400. package/src/scripts/lint_positioning.py +0 -143
  1401. package/src/scripts/lint_profile_overlay_set_only.py +0 -179
  1402. package/src/scripts/lint_readme_jargon.py +0 -131
  1403. package/src/scripts/lint_readme_size.py +0 -33
  1404. package/src/scripts/lint_regression.py +0 -251
  1405. package/src/scripts/lint_roadmap_ci_steps.py +0 -186
  1406. package/src/scripts/lint_roadmap_complexity.py +0 -220
  1407. package/src/scripts/lint_role_experiences.py +0 -255
  1408. package/src/scripts/lint_rule_interactions.py +0 -170
  1409. package/src/scripts/lint_rule_tiers.py +0 -90
  1410. package/src/scripts/lint_showcase_sessions.py +0 -148
  1411. package/src/scripts/lint_skill_frontmatter_safety.py +0 -144
  1412. package/src/scripts/lint_skill_tools.py +0 -168
  1413. package/src/scripts/lint_topics_yaml.py +0 -89
  1414. package/src/scripts/lint_trust_coherence.py +0 -212
  1415. package/src/scripts/lint_value_dashboard.py +0 -218
  1416. package/src/scripts/lint_workspace_boundary.py +0 -122
  1417. package/src/scripts/mcp_parity_smoke.py +0 -316
  1418. package/src/scripts/mcp_render.py +0 -173
  1419. package/src/scripts/mcp_server/__init__.py +0 -19
  1420. package/src/scripts/mcp_server/__main__.py +0 -12
  1421. package/src/scripts/mcp_server/catalog.py +0 -125
  1422. package/src/scripts/mcp_server/metadata.py +0 -75
  1423. package/src/scripts/mcp_server/prompts.py +0 -442
  1424. package/src/scripts/mcp_server/requirements.txt +0 -4
  1425. package/src/scripts/mcp_server/resources.py +0 -201
  1426. package/src/scripts/mcp_server/server.py +0 -270
  1427. package/src/scripts/mcp_server/telemetry.py +0 -128
  1428. package/src/scripts/mcp_server/tools.py +0 -926
  1429. package/src/scripts/mcp_telemetry_health.py +0 -214
  1430. package/src/scripts/mcp_telemetry_query.py +0 -203
  1431. package/src/scripts/mcp_telemetry_store.py +0 -211
  1432. package/src/scripts/measure_augment_budget.py +0 -214
  1433. package/src/scripts/measure_density.py +0 -232
  1434. package/src/scripts/measure_frugality_savings.py +0 -164
  1435. package/src/scripts/measure_markitdown_lift.py +0 -127
  1436. package/src/scripts/measure_patterns.py +0 -376
  1437. package/src/scripts/measure_projection_bytes.py +0 -159
  1438. package/src/scripts/measure_rule_budget.py +0 -347
  1439. package/src/scripts/measure_skill_reduction.py +0 -102
  1440. package/src/scripts/memory_hash.py +0 -75
  1441. package/src/scripts/memory_lookup.py +0 -436
  1442. package/src/scripts/memory_report.py +0 -314
  1443. package/src/scripts/memory_signal.py +0 -165
  1444. package/src/scripts/memory_status.py +0 -76
  1445. package/src/scripts/migrate_command_suggestions.py +0 -151
  1446. package/src/scripts/migrate_frontmatter_defaults.py +0 -245
  1447. package/src/scripts/mine_session.py +0 -356
  1448. package/src/scripts/minimal_safe_diff_hook.py +0 -245
  1449. package/src/scripts/move_artefact.py +0 -143
  1450. package/src/scripts/new_skill.py +0 -148
  1451. package/src/scripts/onboarding_gate_hook.py +0 -142
  1452. package/src/scripts/pack_mcp_content.py +0 -293
  1453. package/src/scripts/plan_physical_move.py +0 -353
  1454. package/src/scripts/prediction-pool/poisson_sim.py +0 -167
  1455. package/src/scripts/prediction-pool/pool_winsim.py +0 -236
  1456. package/src/scripts/prediction-pool/score_ev.py +0 -188
  1457. package/src/scripts/print_required_checks.py +0 -196
  1458. package/src/scripts/probe_projection_fidelity.py +0 -202
  1459. package/src/scripts/probe_skill_registration.py +0 -413
  1460. package/src/scripts/profile_staleness_hook.py +0 -69
  1461. package/src/scripts/profile_use.py +0 -164
  1462. package/src/scripts/project_thin_rules.py +0 -168
  1463. package/src/scripts/propose_modules_config.py +0 -145
  1464. package/src/scripts/prototype_lint_contradictions.py +0 -150
  1465. package/src/scripts/prove_pack_extractable.py +0 -187
  1466. package/src/scripts/readme_linter.py +0 -589
  1467. package/src/scripts/redact_hook_capture.py +0 -148
  1468. package/src/scripts/refine_ticket_detect.py +0 -646
  1469. package/src/scripts/release.py +0 -1091
  1470. package/src/scripts/render_benchmark_md.py +0 -401
  1471. package/src/scripts/render_value_md.py +0 -347
  1472. package/src/scripts/requirements-evals.txt +0 -8
  1473. package/src/scripts/roadmap_progress_hook.py +0 -274
  1474. package/src/scripts/router_telemetry.py +0 -470
  1475. package/src/scripts/run_skill_evals.py +0 -185
  1476. package/src/scripts/runtime_dispatcher.py +0 -276
  1477. package/src/scripts/runtime_handler.py +0 -148
  1478. package/src/scripts/runtime_registry.py +0 -166
  1479. package/src/scripts/score_skill_selection.py +0 -198
  1480. package/src/scripts/security_audit_config.py +0 -153
  1481. package/src/scripts/setup_eval_venv.sh +0 -58
  1482. package/src/scripts/skill_collision_clusters.py +0 -162
  1483. package/src/scripts/skill_discovery.py +0 -254
  1484. package/src/scripts/skill_linter.py +0 -3694
  1485. package/src/scripts/skill_overlap.py +0 -204
  1486. package/src/scripts/skill_preview.py +0 -179
  1487. package/src/scripts/skill_tools/__init__.py +0 -22
  1488. package/src/scripts/skill_tools/audit_persona_coverage.py +0 -147
  1489. package/src/scripts/skill_tools/audit_user_type_coverage.py +0 -148
  1490. package/src/scripts/skill_tools/run_block_d_eval.py +0 -129
  1491. package/src/scripts/skill_tools/score_skill_relevance.py +0 -169
  1492. package/src/scripts/skill_tools/suggest_skill_for_task.py +0 -113
  1493. package/src/scripts/skill_trigger_eval.py +0 -682
  1494. package/src/scripts/skill_usage_collect.py +0 -191
  1495. package/src/scripts/skill_usage_report.py +0 -162
  1496. package/src/scripts/smoke_path_resolution.py +0 -93
  1497. package/src/scripts/smoke_quickstart.py +0 -144
  1498. package/src/scripts/snapshot_agent_outputs.py +0 -144
  1499. package/src/scripts/spotcheck_thin_root.py +0 -134
  1500. package/src/scripts/sync_agent_settings.py +0 -180
  1501. package/src/scripts/sync_github_metadata.py +0 -147
  1502. package/src/scripts/sync_gitignore.py +0 -291
  1503. package/src/scripts/sync_yaml_rt.py +0 -734
  1504. package/src/scripts/telegraph_stats.py +0 -119
  1505. package/src/scripts/tool_registry.py +0 -146
  1506. package/src/scripts/tools/__init__.py +0 -1
  1507. package/src/scripts/tools/adapter_errors.py +0 -63
  1508. package/src/scripts/tools/base_adapter.py +0 -91
  1509. package/src/scripts/tools/github_adapter.py +0 -128
  1510. package/src/scripts/tools/jira_adapter.py +0 -115
  1511. package/src/scripts/trigger_coverage.py +0 -129
  1512. package/src/scripts/update_counts.py +0 -199
  1513. package/src/scripts/update_prices.py +0 -125
  1514. package/src/scripts/validate_agent_settings.py +0 -124
  1515. package/src/scripts/validate_decision_engine.py +0 -136
  1516. package/src/scripts/validate_discovery_manifest.py +0 -94
  1517. package/src/scripts/validate_frontmatter.py +0 -647
  1518. package/src/scripts/validate_pack_yaml.py +0 -179
  1519. package/src/scripts/validate_safe_paths.py +0 -118
  1520. package/src/scripts/validate_telegraph_carveouts.py +0 -129
  1521. package/src/scripts/verify_before_complete_hook.py +0 -216
  1522. package/src/scripts/verify_physical_move.py +0 -185
  1523. package/src/scripts/wrapper_freshness_hook.py +0 -86
  1524. /package/dist/agent-src/skills/design-intelligence/data/{typography.csv → font-pairings-reference.csv} +0 -0
  1525. /package/src/scripts/{ai-video → media}/lib/fixtures/allin1/analysis.json +0 -0
  1526. /package/src/scripts/{ai-video → media}/lib/fixtures/comfyui/scene-0001.mp4 +0 -0
  1527. /package/src/scripts/{ai-video → media}/lib/fixtures/fal/scene-0001.mp4 +0 -0
  1528. /package/src/scripts/{ai-video → media}/lib/fixtures/gemini-veo/scene-0001.mp4 +0 -0
  1529. /package/src/scripts/{ai-video → media}/lib/fixtures/higgsfield/scene-0001.mp4 +0 -0
  1530. /package/src/scripts/{ai-video → media}/lib/fixtures/kling/scene-0001.mp4 +0 -0
  1531. /package/src/scripts/{ai-video → media}/lib/fixtures/musetalk/lipsync-0001.mp4 +0 -0
  1532. /package/src/scripts/{ai-video → media}/lib/fixtures/openai-images/scene-0001.png +0 -0
  1533. /package/src/scripts/{ai-video → media}/lib/fixtures/replicate/scene-0001.mp4 +0 -0
  1534. /package/src/scripts/{ai-video → media}/lib/fixtures/sora/scene-0001.mp4 +0 -0
  1535. /package/src/scripts/{ai-video → media}/lib/fixtures/syncso/lipsync-0001.mp4 +0 -0
  1536. /package/src/scripts/{ai-video → media}/lib/fixtures/whisperx/transcript.json +0 -0
  1537. /package/src/scripts/{ai-video → media}/lib/telemetry.sh +0 -0
@@ -0,0 +1,2306 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * `agent-config doctor` — install + manifest health report (TypeScript twin).
4
+ *
5
+ * TypeScript twin of `src/scripts/_cli/cmd_doctor.py` (ADR-200, py2ts
6
+ * migration). The CLI contract mirrors the Python original EXACTLY — same
7
+ * flags, same exit codes, same stdout/stderr split, byte-identical emitted
8
+ * report lines (✅/❌/⚠️/⏭️ glyphs, ordering, fix hints), same filesystem
9
+ * semantics. No behaviour changes — latent quirks are replicated, not fixed.
10
+ *
11
+ * Phase 4 of road-to-multi-package-coexistence (drift detection) and
12
+ * Phase 2 of road-to-surface-discipline (diagnostic hub). Read-only
13
+ * sibling to `prune`/`validate`: walks the project manifest and the
14
+ * on-disk deploy roots, runs a battery of health checks, and produces:
15
+ *
16
+ * Drift categories (manifest ↔ filesystem):
17
+ *
18
+ * * `missing` — manifest entry has a `path` that is **not** on disk.
19
+ * * `modified` — manifest entry records a `sha256` that does not
20
+ * match the current bytes on disk.
21
+ * * `foreign` — file present under one of the `deploy_roots` that
22
+ * no manifest entry claims (potential neighbour-tool drift).
23
+ * * `tag-drift` — manifest-claimed `.md` file carries a frontmatter
24
+ * `package:` value that disagrees with this package's identifier
25
+ * (P5.2). Hand-edited tags or accidental cross-package writes show up
26
+ * here; files without frontmatter are skipped (P5.1 contract).
27
+ *
28
+ * Health checks (see `CHECK_IDS`):
29
+ * scope · stale-orphans · manifest-integrity · lockfile-freshness · bridge-drift ·
30
+ * mcp-mode · mcp-beta-readiness · offline-readiness · python-runtime ·
31
+ * tier-usage-readiness · council-cli · unsupported-combos ·
32
+ * wizard-state.
33
+ * Each emits a structured `{id, status, message, remedy}` record with
34
+ * `status` ∈ `ok` / `warn` / `fail` / `skipped` (rendered
35
+ * `✅` / `⚠️` / `❌` / `⏭️`). `--check <id>` runs a single check.
36
+ *
37
+ * Exit codes: `0` (clean) · `1` (drift or any `fail` check) · `2`
38
+ * (error such as "manifest missing"). Both human and `--json` output
39
+ * emit the drift category lists and the structured checks array. Every
40
+ * drift entry carries a one-line `fix` hint (P4.3).
41
+ *
42
+ * --- Parity notes (ADR-200) ---
43
+ *
44
+ * - `main()` returns an exit code; the CLI entry guard sets
45
+ * `process.exitCode` (never `process.exit()`).
46
+ * - argparse errors (unknown flags, bad `--check` / `--repair` choice,
47
+ * missing argument) print usage + `error:` to stderr and throw
48
+ * `ArgparseExit(2)`. `-h`/`--help` prints usage to stdout and throws
49
+ * `ArgparseExit(0)`. The `--help` BODY (per-flag descriptions) is a
50
+ * documented divergence — argparse re-wraps it to terminal width; the
51
+ * golden tests assert the `usage:` token + exit code, not the body prose.
52
+ * - JSON byte-parity: the Python uses the DEFAULT `json.dumps(payload,
53
+ * indent=2)` → `ensure_ascii=True`, so non-ASCII scalars are escaped to
54
+ * `\uXXXX`. `_jsonDumpsIndentAscii` replicates that (distinct from the
55
+ * `install.ts` `ensure_ascii=False` dumper). Dict insertion order is
56
+ * preserved (JS object key order matches Python dict order for string
57
+ * keys).
58
+ * - `_lib.*` / `scripts.config` / `scripts.ai_council.*` imports resolve to
59
+ * the `.ts` twins (never a `.py`). The Python dual-path try/except
60
+ * (`scripts._lib.X` vs `_lib.X`) collapses to a single static import.
61
+ * - `cfg.members` / `cli_call_budget.max_calls_per_day` are `Map`s in the
62
+ * config twin (Python dicts); iterate with `.entries()` / `.get()`.
63
+ * - `re.MULTILINE` `^package:\s*(.+?)\s*$` → JS regex with the `m` flag and
64
+ * the same lazy capture (`(.+?)`). `\s` matches the Python ASCII+Unicode
65
+ * whitespace set the same way under default JS `\s` for our inputs.
66
+ * - `sorted(rglob("*"))` / `sorted(tools.items())` → array sort with the
67
+ * string comparator (path-string lexicographic, matching pathlib).
68
+ * - PyYAML 1.1 `safe_load` → `yaml.parse(text, { version: '1.1' })`, `{}` on
69
+ * any error (ImportError / YAMLError), matching the Python `except`.
70
+ * - `json.JSONDecodeError` `.msg` / `.lineno` → derived from the parse error
71
+ * position so the wizard-state malformed-JSON message matches.
72
+ */
73
+
74
+ import * as crypto from 'node:crypto';
75
+ import * as fs from 'node:fs';
76
+ import * as os from 'node:os';
77
+ import * as path from 'node:path';
78
+ import process from 'node:process';
79
+ import { fileURLToPath, pathToFileURL } from 'node:url';
80
+
81
+ import * as YAML from 'yaml';
82
+
83
+ import * as installed_lock from '../_lib/installed_lock.js';
84
+ import * as installed_tools from '../_lib/installed_tools.js';
85
+ import * as user_global_paths from '../_lib/user_global_paths.js';
86
+ import * as global_deploy_inventory from '../_lib/global_deploy_inventory.js';
87
+ import {
88
+ PROJECT_ROOT_ENV,
89
+ ROOT_OVERRIDE_ENV,
90
+ ProjectRootError,
91
+ find_project_root_with_trace,
92
+ project_settings_path,
93
+ resolve_project_root,
94
+ type TraceRecord,
95
+ } from '../_lib/agent_settings.js';
96
+ import * as ai_council_clients from '../ai_council/clients.js';
97
+ import * as ai_council_config from '../ai_council/config.js';
98
+
99
+ type Dict = Record<string, unknown>;
100
+
101
+ // ---------------------------------------------------------------------------
102
+ // Parity primitives (ADR-200).
103
+ // ---------------------------------------------------------------------------
104
+
105
+ const _HERE = fileURLToPath(import.meta.url);
106
+
107
+ /** argparse usage-error / help exit (code 2 / 0). Caught at the CLI entry. */
108
+ class ArgparseExit extends Error {
109
+ constructor(public readonly code: number) {
110
+ super(`argparse-exit-${code}`);
111
+ }
112
+ }
113
+
114
+ /** `os.path.expanduser` — expand a leading `~` (we only handle `~`). */
115
+ function expanduser(p: string): string {
116
+ if (p === '~') return os.homedir();
117
+ if (p.startsWith('~/') || p.startsWith('~\\')) {
118
+ return path.join(os.homedir(), p.slice(2));
119
+ }
120
+ return p;
121
+ }
122
+
123
+ function pathExists(p: string): boolean {
124
+ try {
125
+ fs.statSync(p);
126
+ return true;
127
+ } catch {
128
+ return false;
129
+ }
130
+ }
131
+
132
+ function isFile(p: string): boolean {
133
+ try {
134
+ return fs.statSync(p).isFile();
135
+ } catch {
136
+ return false;
137
+ }
138
+ }
139
+
140
+ function isDir(p: string): boolean {
141
+ try {
142
+ return fs.statSync(p).isDirectory();
143
+ } catch {
144
+ return false;
145
+ }
146
+ }
147
+
148
+ /** `Path.resolve()` — absolute, symlink-resolved where possible. */
149
+ function resolvePath(p: string): string {
150
+ try {
151
+ return fs.realpathSync(path.resolve(p));
152
+ } catch {
153
+ return path.resolve(p);
154
+ }
155
+ }
156
+
157
+ /** `path.read_text(encoding="utf-8")`; throws on OSError (caller catches). */
158
+ function readText(p: string): string {
159
+ return fs.readFileSync(p, 'utf-8');
160
+ }
161
+
162
+ // --- JSON byte-parity (ensure_ascii=True; insertion order) ---
163
+ //
164
+ // The doctor's JSON paths use the DEFAULT `json.dumps(payload, indent=2)`,
165
+ // i.e. `ensure_ascii=True`: every non-ASCII code point is escaped to a
166
+ // `\uXXXX` (or surrogate pair) sequence. This differs from `install.ts`'s
167
+ // `ensure_ascii=False` dumper, so it lives here.
168
+
169
+ function _jsonStrAscii(s: string): string {
170
+ let out = '"';
171
+ for (const ch of s) {
172
+ const code = ch.codePointAt(0) as number;
173
+ switch (ch) {
174
+ case '"':
175
+ out += '\\"';
176
+ break;
177
+ case '\\':
178
+ out += '\\\\';
179
+ break;
180
+ case '\n':
181
+ out += '\\n';
182
+ break;
183
+ case '\r':
184
+ out += '\\r';
185
+ break;
186
+ case '\t':
187
+ out += '\\t';
188
+ break;
189
+ case '\b':
190
+ out += '\\b';
191
+ break;
192
+ case '\f':
193
+ out += '\\f';
194
+ break;
195
+ default:
196
+ if (code < 0x20) {
197
+ out += '\\u' + code.toString(16).padStart(4, '0');
198
+ } else if (code < 0x7f) {
199
+ out += ch;
200
+ } else if (code <= 0xffff) {
201
+ out += '\\u' + code.toString(16).padStart(4, '0');
202
+ } else {
203
+ // ensure_ascii encodes astral chars as a UTF-16 surrogate pair.
204
+ const v = code - 0x10000;
205
+ const hi = 0xd800 + (v >> 10);
206
+ const lo = 0xdc00 + (v & 0x3ff);
207
+ out +=
208
+ '\\u' +
209
+ hi.toString(16).padStart(4, '0') +
210
+ '\\u' +
211
+ lo.toString(16).padStart(4, '0');
212
+ }
213
+ }
214
+ }
215
+ return out + '"';
216
+ }
217
+
218
+ function _jsonScalarAscii(value: unknown): string | null {
219
+ if (value === null || value === undefined) return 'null';
220
+ if (typeof value === 'boolean') return value ? 'true' : 'false';
221
+ if (typeof value === 'number') {
222
+ if (!Number.isFinite(value)) {
223
+ if (Number.isNaN(value)) return 'NaN';
224
+ return value > 0 ? 'Infinity' : '-Infinity';
225
+ }
226
+ if (Number.isInteger(value)) return String(value);
227
+ return String(value);
228
+ }
229
+ if (typeof value === 'string') return _jsonStrAscii(value);
230
+ return null;
231
+ }
232
+
233
+ function _dumpIndentAscii(value: unknown, indent: number, depth: number): string {
234
+ const scalar = _jsonScalarAscii(value);
235
+ if (scalar !== null) return scalar;
236
+ const pad = ' '.repeat(indent * (depth + 1));
237
+ const closePad = ' '.repeat(indent * depth);
238
+ if (Array.isArray(value)) {
239
+ if (value.length === 0) return '[]';
240
+ const items = value.map((v) => pad + _dumpIndentAscii(v, indent, depth + 1));
241
+ return `[\n${items.join(',\n')}\n${closePad}]`;
242
+ }
243
+ if (typeof value === 'object' && value !== null) {
244
+ const obj = value as Record<string, unknown>;
245
+ const keys = Object.keys(obj);
246
+ if (keys.length === 0) return '{}';
247
+ const items = keys.map(
248
+ (k) => `${pad}${_jsonStrAscii(k)}: ${_dumpIndentAscii(obj[k], indent, depth + 1)}`,
249
+ );
250
+ return `{\n${items.join(',\n')}\n${closePad}}`;
251
+ }
252
+ return _jsonStrAscii(String(value));
253
+ }
254
+
255
+ /** `json.dumps(data, indent=N)` (ensure_ascii=True, sort_keys=False). */
256
+ function _jsonDumpsIndentAscii(value: unknown, indent: number): string {
257
+ return _dumpIndentAscii(value, indent, 0);
258
+ }
259
+
260
+ /** PyYAML-1.1 `safe_load`; returns `null` on an ImportError-equivalent
261
+ * (yaml dep absent), `undefined` on a YAMLError-equivalent. Callers collapse
262
+ * both to `{}`, matching the Python `try/except ImportError` + `except`. */
263
+ function yamlSafeLoad(text: string): unknown {
264
+ if (YAML === undefined || YAML === null) {
265
+ return null; // ImportError (yaml unavailable)
266
+ }
267
+ try {
268
+ return YAML.parse(text, { version: '1.1' });
269
+ } catch {
270
+ return undefined; // YAMLError sentinel
271
+ }
272
+ }
273
+
274
+ /** `print(...)` — line to stdout. */
275
+ function print(line = ''): void {
276
+ process.stdout.write(line + '\n');
277
+ }
278
+
279
+ /** `print(..., file=sys.stderr)`. */
280
+ function eprint(line = ''): void {
281
+ process.stderr.write(line + '\n');
282
+ }
283
+
284
+ // ---------------------------------------------------------------------------
285
+ // Module body (cmd_doctor.py).
286
+ // ---------------------------------------------------------------------------
287
+
288
+ /** Tiny stand-in for a private sentinel value type. */
289
+ class _Sentinel {}
290
+
291
+ /**
292
+ * Returned by `_read_inline_package_tag` when the file is out of scope for
293
+ * tag-drift detection (no `.md` suffix, unreadable, or no leading
294
+ * frontmatter block).
295
+ */
296
+ const NO_FRONTMATTER = new _Sentinel();
297
+
298
+ function _resolve_project_root(arg: string | null): [string, string] {
299
+ return resolve_project_root(arg);
300
+ }
301
+
302
+ /**
303
+ * Path of the install-mode marker file (Step 8 A5). One-line file:
304
+ * `minimal\n` or `full\n`.
305
+ */
306
+ const _INSTALL_MODE_MARKER_REL = 'agents/.agent-state/install-mode.txt';
307
+
308
+ function _detect_install_mode(project_root: string): [string, string] {
309
+ const marker = path.join(project_root, _INSTALL_MODE_MARKER_REL);
310
+ if (isFile(marker)) {
311
+ let value: string;
312
+ try {
313
+ value = readText(marker).trim();
314
+ } catch {
315
+ value = '';
316
+ }
317
+ if (value === 'minimal' || value === 'full') {
318
+ return [value, 'marker-file'];
319
+ }
320
+ }
321
+ const has_agents_md = pathExists(path.join(project_root, 'AGENTS.md'));
322
+ const has_copilot = pathExists(
323
+ path.join(project_root, '.github', 'copilot-instructions.md'),
324
+ );
325
+ if (has_agents_md && has_copilot) {
326
+ return ['full', 'heuristic'];
327
+ }
328
+ return ['minimal', 'heuristic'];
329
+ }
330
+
331
+ function _settings_layer_chain(project_root: string): string[] {
332
+ const layers: string[] = [];
333
+ const user_global = user_global_paths.resolve_with_fallback('agent-settings.yml');
334
+ if (user_global !== null && isFile(user_global)) {
335
+ layers.push(String(user_global));
336
+ }
337
+ const project_settings = project_settings_path(project_root);
338
+ if (isFile(project_settings)) {
339
+ layers.push(String(project_settings));
340
+ }
341
+ return layers;
342
+ }
343
+
344
+ function _detect_wrapper(project_root: string): Dict {
345
+ const wrapper = path.join(project_root, 'agent-config');
346
+ if (!pathExists(wrapper)) {
347
+ return { path: String(wrapper), exists: false, embedded_root: null };
348
+ }
349
+ return {
350
+ path: String(wrapper),
351
+ exists: true,
352
+ embedded_root: String(project_root),
353
+ };
354
+ }
355
+
356
+ function _emit_trace_text(
357
+ root: string | null,
358
+ anchor: string | null,
359
+ trace: TraceRecord[],
360
+ origin: string,
361
+ ): void {
362
+ print(` 📍 start: ${process.cwd()}`);
363
+ print(` 📍 origin: ${origin}`);
364
+ if (trace.length > 0) {
365
+ print(' trace:');
366
+ for (const record of trace) {
367
+ const hit = record.hit;
368
+ const symbol = hit ? '✅' : '·';
369
+ const tag = `[${record.pass}]`;
370
+ const anchor_str = hit ? ` → ${hit}` : '';
371
+ print(` ${symbol} ${tag} ${record.ancestor}${anchor_str} (${record.reason})`);
372
+ }
373
+ }
374
+ if (root !== null) {
375
+ print(` 📍 resolved root: ${root} (anchor: ${anchor || 'n/a'})`);
376
+ } else {
377
+ print(' ⚠️ no anchor found in chain');
378
+ }
379
+ }
380
+
381
+ function _emit_trace_json(
382
+ root: string | null,
383
+ anchor: string | null,
384
+ trace: TraceRecord[],
385
+ origin: string,
386
+ ): void {
387
+ const payload: Dict = {
388
+ start: process.cwd(),
389
+ origin,
390
+ resolved_root: root !== null ? String(root) : null,
391
+ anchor,
392
+ trace,
393
+ };
394
+ print(_jsonDumpsIndentAscii(payload, 2));
395
+ }
396
+
397
+ function _emit_context_text(ctx: Dict): void {
398
+ print(` 📍 project_root: ${ctx['project_root']} (origin: ${ctx['origin']})`);
399
+ print(` 📦 install_mode: ${ctx['install_mode']} (source: ${ctx['install_mode_source']})`);
400
+ const env_pin = ctx['env_pin'];
401
+ if (env_pin) {
402
+ const marker = ctx['root_override'] ? ' (--root override)' : '';
403
+ print(` 🔒 env_pin: ${env_pin}${marker}`);
404
+ } else {
405
+ print(' 🔒 env_pin: (unset)');
406
+ }
407
+ const layers = (ctx['settings_layers'] as string[] | undefined) || [];
408
+ if (layers.length > 0) {
409
+ print(` 📑 settings layers (${layers.length}):`);
410
+ for (const layer of layers) {
411
+ print(` - ${layer}`);
412
+ }
413
+ } else {
414
+ print(' 📑 settings layers: (none)');
415
+ }
416
+ const wrapper = (ctx['wrapper'] as Dict | undefined) || {};
417
+ if (wrapper['exists']) {
418
+ print(` 🧩 wrapper: ${wrapper['path']} (embedded root: ${wrapper['embedded_root']})`);
419
+ } else {
420
+ print(` 🧩 wrapper: (not present at ${wrapper['path']})`);
421
+ }
422
+ }
423
+
424
+ function _resolve_path(project_root: string, raw: string): string {
425
+ let p = expanduser(raw);
426
+ if (!path.isAbsolute(p)) {
427
+ p = path.join(project_root, p);
428
+ }
429
+ return p;
430
+ }
431
+
432
+ function _sha256(p: string): string | null {
433
+ try {
434
+ const data = fs.readFileSync(p);
435
+ return crypto.createHash('sha256').update(data).digest('hex');
436
+ } catch {
437
+ return null;
438
+ }
439
+ }
440
+
441
+ /**
442
+ * Inline-tag identifier this package writes into deployed Markdown
443
+ * frontmatter (P5.1). Kept in sync with `install.PACKAGE_TAG_ID`.
444
+ */
445
+ const PACKAGE_TAG_ID = 'event4u/agent-config';
446
+
447
+ const _FRONTMATTER_PACKAGE_RE = /^package:\s*(.+?)\s*$/m;
448
+
449
+ /**
450
+ * Extract the inline `package:` value from a Markdown frontmatter.
451
+ *
452
+ * Returns `NO_FRONTMATTER` when `path` is not a Markdown file or has no
453
+ * leading `---` block. Returns `null` when frontmatter is present but lacks
454
+ * a `package:` key. Returns the string value otherwise.
455
+ */
456
+ function _read_inline_package_tag(p: string): string | null | _Sentinel {
457
+ if (path.extname(p) !== '.md') {
458
+ return NO_FRONTMATTER;
459
+ }
460
+ let text: string;
461
+ try {
462
+ text = readText(p);
463
+ } catch {
464
+ return NO_FRONTMATTER;
465
+ }
466
+ if (!(text.startsWith('---\n') || text.startsWith('---\r\n'))) {
467
+ return NO_FRONTMATTER;
468
+ }
469
+ const lines = splitlines(text);
470
+ let close_idx: number | null = null;
471
+ for (let i = 1; i < lines.length; i++) {
472
+ if (rstrip(lines[i] as string) === '---') {
473
+ close_idx = i;
474
+ break;
475
+ }
476
+ }
477
+ if (close_idx === null) {
478
+ return NO_FRONTMATTER;
479
+ }
480
+ const block = lines.slice(1, close_idx).join('\n');
481
+ const m = _FRONTMATTER_PACKAGE_RE.exec(block);
482
+ if (!m) {
483
+ return null;
484
+ }
485
+ return stripQuotes((m[1] as string).trim());
486
+ }
487
+
488
+ /** Python `str.splitlines()` for the line-set the parser needs (\n, \r\n, \r). */
489
+ function splitlines(text: string): string[] {
490
+ if (text === '') return [];
491
+ const out = text.split(/\r\n|\r|\n/);
492
+ // Python splitlines() drops a trailing empty produced by a terminal newline.
493
+ if (out.length > 0 && out[out.length - 1] === '') {
494
+ out.pop();
495
+ }
496
+ return out;
497
+ }
498
+
499
+ /** Python `str.rstrip()` (default whitespace, ASCII+Unicode). */
500
+ function rstrip(s: string): string {
501
+ return s.replace(/[\s… ]+$/u, '');
502
+ }
503
+
504
+ /** Python `value.strip().strip("'\"")` tail (after `.strip()` already done). */
505
+ function stripQuotes(s: string): string {
506
+ let out = s;
507
+ while (out.length > 0 && (out[0] === "'" || out[0] === '"')) {
508
+ out = out.slice(1);
509
+ }
510
+ while (out.length > 0 && (out[out.length - 1] === "'" || out[out.length - 1] === '"')) {
511
+ out = out.slice(0, -1);
512
+ }
513
+ return out;
514
+ }
515
+
516
+ /** Return a one-line remediation hint for the surfaced item. */
517
+ function _fix_hint(category: string, _kind: string | null): string {
518
+ if (category === 'missing') {
519
+ return 'run `./agent-config sync` to re-install';
520
+ }
521
+ if (category === 'modified') {
522
+ return 'commit the local change, or re-install with --force';
523
+ }
524
+ if (category === 'foreign') {
525
+ return 'identify owning tool, or run `./agent-config prune` if confirmed orphan';
526
+ }
527
+ if (category === 'tag-drift') {
528
+ return (
529
+ 're-install with --force to restore the inline tag, ' +
530
+ 'or remove the file if it is no longer ours'
531
+ );
532
+ }
533
+ return '';
534
+ }
535
+
536
+ type ManifestRecord = [string, string, string, string | null]; // (tool, abs_path, kind, sha)
537
+
538
+ /**
539
+ * Flatten v2 `tools[].files[]` into per-file records. Returns the records list
540
+ * and a set of resolved absolute paths so the foreign scan can skip claims.
541
+ */
542
+ function _collect_manifest_entries(
543
+ project_root: string,
544
+ manifest: Dict,
545
+ ): [ManifestRecord[], Set<string>] {
546
+ const records: ManifestRecord[] = [];
547
+ const known = new Set<string>();
548
+ const tools = (manifest['tools'] as Dict[] | undefined) || [];
549
+ for (const tool of tools) {
550
+ if (tool['scope'] !== 'project') {
551
+ continue;
552
+ }
553
+ const tool_id = String(tool['name'] ?? '');
554
+ const files = (tool['files'] as Dict[] | undefined) || [];
555
+ for (const entry of files) {
556
+ const raw = (entry['path'] as string | undefined) || '';
557
+ if (!raw) {
558
+ continue;
559
+ }
560
+ const kind = (entry['kind'] as string | undefined) || '';
561
+ const target = _resolve_path(project_root, raw);
562
+ let resolved: string;
563
+ try {
564
+ resolved = resolvePath(target);
565
+ } catch {
566
+ resolved = target;
567
+ }
568
+ records.push([tool_id, target, kind, (entry['sha256'] as string | null) ?? null]);
569
+ known.add(resolved);
570
+ }
571
+ }
572
+ return [records, known];
573
+ }
574
+
575
+ /**
576
+ * Walk every declared deploy root and surface unclaimed files. Only regular
577
+ * files under `deploy_roots` count; bookkeeping is on the resolved final path.
578
+ */
579
+ function _scan_foreign(
580
+ project_root: string,
581
+ manifest: Dict,
582
+ known: Set<string>,
583
+ ): string[] {
584
+ const roots =
585
+ (manifest['deploy_roots'] as unknown[] | undefined) ||
586
+ Array.from(installed_tools.DEFAULT_DEPLOY_ROOTS);
587
+ const foreign: string[] = [];
588
+ const seen = new Set<string>();
589
+ for (const root_rel of roots) {
590
+ const root = _resolve_path(project_root, String(root_rel));
591
+ if (!pathExists(root) || !isDir(root)) {
592
+ continue;
593
+ }
594
+ for (const child of rglob(root)) {
595
+ if (!isFile(child)) {
596
+ continue;
597
+ }
598
+ let resolved: string;
599
+ try {
600
+ resolved = resolvePath(child);
601
+ } catch {
602
+ resolved = child;
603
+ }
604
+ if (known.has(resolved) || seen.has(resolved)) {
605
+ continue;
606
+ }
607
+ seen.add(resolved);
608
+ foreign.push(child);
609
+ }
610
+ }
611
+ foreign.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
612
+ return foreign;
613
+ }
614
+
615
+ /**
616
+ * `Path.rglob("*")` — every descendant path (dirs + files), recursively.
617
+ * Order is not relied upon by callers (they sort the matched set), but the
618
+ * walk is deterministic (sorted per directory) to keep behaviour stable.
619
+ */
620
+ function rglob(root: string): string[] {
621
+ const out: string[] = [];
622
+ const walk = (dir: string): void => {
623
+ let entries: fs.Dirent[];
624
+ try {
625
+ entries = fs.readdirSync(dir, { withFileTypes: true });
626
+ } catch {
627
+ return;
628
+ }
629
+ entries.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
630
+ for (const ent of entries) {
631
+ const full = path.join(dir, ent.name);
632
+ out.push(full);
633
+ let dirLike = ent.isDirectory();
634
+ if (ent.isSymbolicLink()) {
635
+ // pathlib rglob follows into symlinked dirs.
636
+ dirLike = isDir(full);
637
+ }
638
+ if (dirLike) {
639
+ walk(full);
640
+ }
641
+ }
642
+ };
643
+ walk(root);
644
+ return out;
645
+ }
646
+
647
+ /**
648
+ * Split manifest records into missing / modified / tag-drift lists.
649
+ */
650
+ function _classify(records: ManifestRecord[]): [Dict[], Dict[], Dict[]] {
651
+ const missing: Dict[] = [];
652
+ const modified: Dict[] = [];
653
+ const tag_drift: Dict[] = [];
654
+ for (const [tool_id, target, kind, expected] of records) {
655
+ if (!pathExists(target)) {
656
+ missing.push({
657
+ tool: tool_id,
658
+ path: String(target),
659
+ kind,
660
+ fix: _fix_hint('missing', kind),
661
+ });
662
+ continue;
663
+ }
664
+ const tag = _read_inline_package_tag(target);
665
+ if (!(tag instanceof _Sentinel) && tag !== PACKAGE_TAG_ID) {
666
+ tag_drift.push({
667
+ tool: tool_id,
668
+ path: String(target),
669
+ kind,
670
+ expected: PACKAGE_TAG_ID,
671
+ found: tag === null ? '' : tag,
672
+ fix: _fix_hint('tag-drift', kind),
673
+ });
674
+ }
675
+ if (expected === null) {
676
+ continue;
677
+ }
678
+ const actual = _sha256(target);
679
+ if (actual === null || actual === expected) {
680
+ continue;
681
+ }
682
+ modified.push({
683
+ tool: tool_id,
684
+ path: String(target),
685
+ kind,
686
+ fix: _fix_hint('modified', kind),
687
+ });
688
+ }
689
+ return [missing, modified, tag_drift];
690
+ }
691
+
692
+ function _foreign_records(project_root: string, foreign: string[]): Dict[] {
693
+ const out: Dict[] = [];
694
+ for (const p of foreign) {
695
+ let path_str: string;
696
+ const rel = relativeTo(p, project_root);
697
+ if (rel !== null) {
698
+ path_str = rel;
699
+ } else {
700
+ path_str = String(p);
701
+ }
702
+ out.push({
703
+ tool: '',
704
+ path: path_str,
705
+ kind: 'deployed',
706
+ fix: _fix_hint('foreign', 'deployed'),
707
+ });
708
+ }
709
+ return out;
710
+ }
711
+
712
+ /** `Path.relative_to(base)` — returns null on ValueError (not under base). */
713
+ function relativeTo(p: string, base: string): string | null {
714
+ const rel = path.relative(base, p);
715
+ if (rel === '' ) return rel;
716
+ if (rel.startsWith('..') || path.isAbsolute(rel)) {
717
+ return null;
718
+ }
719
+ return rel;
720
+ }
721
+
722
+ // ---------------------------------------------------------------------------
723
+ // Health checks (Phase 2 of road-to-surface-discipline).
724
+ // ---------------------------------------------------------------------------
725
+
726
+ /** Ordered registry of structured health-check identifiers. */
727
+ const CHECK_IDS = [
728
+ 'scope',
729
+ 'global-binary',
730
+ 'stale-orphans',
731
+ 'manifest-integrity',
732
+ 'lockfile-freshness',
733
+ 'bridge-drift',
734
+ 'mcp-mode',
735
+ 'mcp-beta-readiness',
736
+ 'offline-readiness',
737
+ 'python-runtime',
738
+ 'tier-usage-readiness',
739
+ 'council-cli',
740
+ 'unsupported-combos',
741
+ 'wizard-state',
742
+ ] as const;
743
+
744
+ /** Checks that need only the project root and run regardless of a lockfile. */
745
+ const GLOBAL_CHECK_IDS: ReadonlySet<string> = new Set([
746
+ 'scope',
747
+ 'global-binary',
748
+ 'stale-orphans',
749
+ 'mcp-mode',
750
+ 'mcp-beta-readiness',
751
+ 'offline-readiness',
752
+ 'python-runtime',
753
+ 'tier-usage-readiness',
754
+ 'council-cli',
755
+ 'wizard-state',
756
+ ]);
757
+
758
+ /** Checks that genuinely cannot run without the project manifest. */
759
+ const MANIFEST_REQUIRED_CHECK_IDS: ReadonlySet<string> = new Set([
760
+ 'manifest-integrity',
761
+ 'lockfile-freshness',
762
+ 'unsupported-combos',
763
+ ]);
764
+
765
+ /** Project-root-relative path of the ADR-020 global-only consumer marker. */
766
+ const BRIDGE_MARKER_RELATIVE = 'agents/.event4u-bridge.yml';
767
+
768
+ /** Repair targets that `--repair <id>` accepts. */
769
+ const REPAIR_IDS = ['wizard-state'] as const;
770
+
771
+ /** Six gates that govern the MCP `experimental → beta` promotion. */
772
+ const MCP_BETA_GATES: ReadonlyArray<[string, string]> = [
773
+ ['gate-1-external-client', 'tests/mcp/external-clients'],
774
+ ['gate-2-bearer-auth', 'tests/mcp/auth'],
775
+ ['gate-3-parity-smoke', 'tests/mcp/parity'],
776
+ ['gate-4-healthz-load', 'tests/mcp/load/healthz.k6.js'],
777
+ ['gate-5-rate-limit', 'docs/contracts/mcp-rate-limit.md'],
778
+ ['gate-6-no-drift', '.github/workflows/mcp-no-drift.yml'],
779
+ ];
780
+
781
+ /** Visible status → glyph map (`warn` keeps a trailing space for alignment). */
782
+ const STATUS_SYMBOLS: Record<string, string> = {
783
+ ok: '✅',
784
+ warn: '⚠️ ',
785
+ fail: '❌',
786
+ skipped: '⏭️ ',
787
+ };
788
+
789
+ /** Minimum Python interpreter the CLI targets (parity constant). */
790
+ const MIN_PYTHON: [number, number] = [3, 10];
791
+
792
+ function _check_scope(project_root: string): Dict {
793
+ for (const marker of ['pnpm-workspace.yaml', 'lerna.json']) {
794
+ if (pathExists(path.join(project_root, marker))) {
795
+ return {
796
+ id: 'scope',
797
+ status: 'warn',
798
+ message: `monorepo root detected (${marker})`,
799
+ remedy: 'run `agent-config doctor` from each workspace package',
800
+ };
801
+ }
802
+ }
803
+ const pkg = path.join(project_root, 'package.json');
804
+ if (pathExists(pkg)) {
805
+ try {
806
+ const data = JSON.parse(readText(pkg)) as Dict;
807
+ if (data['workspaces']) {
808
+ return {
809
+ id: 'scope',
810
+ status: 'warn',
811
+ message: 'package.json declares workspaces (monorepo root)',
812
+ remedy: 'run `agent-config doctor` from each workspace package',
813
+ };
814
+ }
815
+ } catch {
816
+ // OSError / ValueError → fall through.
817
+ }
818
+ }
819
+ return {
820
+ id: 'scope',
821
+ status: 'ok',
822
+ message: 'standalone project root',
823
+ remedy: '',
824
+ };
825
+ }
826
+
827
+ function _check_manifest_integrity(manifest: Dict): Dict {
828
+ const schema = manifest['schema_version'];
829
+ const version = manifest['agent_config_version'];
830
+ if (!version) {
831
+ return {
832
+ id: 'manifest-integrity',
833
+ status: 'warn',
834
+ message: 'manifest lacks `agent_config_version`',
835
+ remedy: 're-run `./agent-config init` to record the writer version',
836
+ };
837
+ }
838
+ if (!installed_tools.SCHEMA_VERSIONS_SUPPORTED.includes(schema as number)) {
839
+ return {
840
+ id: 'manifest-integrity',
841
+ status: 'warn',
842
+ message: `unknown schema_version: ${pyRepr(schema)}`,
843
+ remedy:
844
+ 'upgrade @event4u/agent-config to a writer that recognises this schema',
845
+ };
846
+ }
847
+ return {
848
+ id: 'manifest-integrity',
849
+ status: 'ok',
850
+ message: `schema v${schema}, written by agent-config ${version}`,
851
+ remedy: '',
852
+ };
853
+ }
854
+
855
+ /** Resolve the @event4u/agent-config package root (this repo). */
856
+ function _package_root(): string {
857
+ // cmd_doctor lives at src/scripts/_cli/cmd_doctor.{py,ts}; parents[3] = repo.
858
+ return path.resolve(path.dirname(_HERE), '..', '..', '..');
859
+ }
860
+
861
+ /** Read `version` from this package's package.json; null on error. */
862
+ function _current_package_version(): string | null {
863
+ try {
864
+ const data = JSON.parse(readText(path.join(_package_root(), 'package.json'))) as Dict;
865
+ const v = data['version'];
866
+ if (typeof v === 'string' && v.trim()) {
867
+ return v.trim();
868
+ }
869
+ } catch {
870
+ // OSError / ValueError → null.
871
+ }
872
+ return null;
873
+ }
874
+
875
+ function _check_lockfile_freshness(manifest: Dict): Dict {
876
+ const recorded = manifest['agent_config_version'];
877
+ const current = _current_package_version();
878
+ if (!recorded) {
879
+ return {
880
+ id: 'lockfile-freshness',
881
+ status: 'warn',
882
+ message: 'manifest has no writer version recorded',
883
+ remedy: 're-run `./agent-config init` to refresh the manifest',
884
+ };
885
+ }
886
+ if (current === null) {
887
+ return {
888
+ id: 'lockfile-freshness',
889
+ status: 'warn',
890
+ message: `manifest written by ${recorded}; current package version unknown`,
891
+ remedy: 'verify the package install (package.json missing or unreadable)',
892
+ };
893
+ }
894
+ if (recorded !== current) {
895
+ return {
896
+ id: 'lockfile-freshness',
897
+ status: 'warn',
898
+ message: `manifest writer ${recorded} != current package ${current}`,
899
+ remedy:
900
+ 're-run `./agent-config sync` to refresh the manifest against the current package',
901
+ };
902
+ }
903
+ return {
904
+ id: 'lockfile-freshness',
905
+ status: 'ok',
906
+ message: `manifest and package both at ${current}`,
907
+ remedy: '',
908
+ };
909
+ }
910
+
911
+ /** `shutil.which(name)` — first PATH hit (with PATHEXT on win32). */
912
+ function shutilWhich(name: string): string | null {
913
+ if (path.dirname(name) !== '.' && (name.includes('/') || name.includes('\\'))) {
914
+ // Has a path component: check directly.
915
+ return isExecutableFile(name) ? name : null;
916
+ }
917
+ const pathEnv = process.env['PATH'] || '';
918
+ const sep = process.platform === 'win32' ? ';' : ':';
919
+ const dirs = pathEnv.split(sep);
920
+ const exts =
921
+ process.platform === 'win32'
922
+ ? (process.env['PATHEXT'] || '.COM;.EXE;.BAT;.CMD').split(';')
923
+ : [''];
924
+ const seenDirs = new Set<string>();
925
+ for (const dir of dirs) {
926
+ const d = dir === '' ? '.' : dir;
927
+ if (seenDirs.has(d)) continue;
928
+ seenDirs.add(d);
929
+ for (const ext of exts) {
930
+ const candidate = path.join(d, name + (ext === '' ? '' : ext.toLowerCase() === ext ? ext : ext));
931
+ if (isExecutableFile(candidate)) {
932
+ return candidate;
933
+ }
934
+ if (ext !== '') {
935
+ const upper = path.join(d, name + ext);
936
+ if (isExecutableFile(upper)) return upper;
937
+ }
938
+ }
939
+ }
940
+ return null;
941
+ }
942
+
943
+ function isExecutableFile(p: string): boolean {
944
+ try {
945
+ const st = fs.statSync(p);
946
+ if (!st.isFile()) return false;
947
+ if (process.platform === 'win32') return true;
948
+ fs.accessSync(p, fs.constants.X_OK);
949
+ return true;
950
+ } catch {
951
+ return false;
952
+ }
953
+ }
954
+
955
+ function _check_global_binary(project_root: string): Dict {
956
+ const binary = shutilWhich('agent-config');
957
+ if (!binary) {
958
+ return {
959
+ id: 'global-binary',
960
+ status: 'fail',
961
+ message:
962
+ '`agent-config` is not on PATH — Claude plugin hooks ' +
963
+ 'cannot resolve it (hooks silently no-op)',
964
+ remedy: 'npm install -g @event4u/agent-config, then re-run doctor',
965
+ };
966
+ }
967
+ const lock = installed_lock.read_lockfile();
968
+ let global_v = '';
969
+ if (lock !== null && typeof lock === 'object') {
970
+ const raw = (lock as unknown as Dict)['agent_config_version'];
971
+ global_v = typeof raw === 'string' ? lstripV(raw.trim()) : '';
972
+ }
973
+ const binary_v = lstripV(_current_package_version() || '');
974
+ if (global_v && binary_v && global_v !== binary_v) {
975
+ return {
976
+ id: 'global-binary',
977
+ status: 'warn',
978
+ message: `version drift — binary ${binary_v}, global install ${global_v}`,
979
+ remedy: 'agent-config upgrade (refresh the global install + plugin)',
980
+ };
981
+ }
982
+ const bridge = path.join(project_root, 'agents', '.event4u-bridge.yml');
983
+ const bridge_note = isFile(bridge) ? '' : ' · no project bridge marker';
984
+ return {
985
+ id: 'global-binary',
986
+ status: 'ok',
987
+ message: `on PATH (${binary}); version ${binary_v || 'unknown'}${bridge_note}`,
988
+ remedy: !bridge_note
989
+ ? ''
990
+ : 'agent-config refresh --project (scaffold the bridge marker)',
991
+ };
992
+ }
993
+
994
+ /** Python `str.lstrip("v")` — strip leading 'v' characters. */
995
+ function lstripV(s: string): string {
996
+ let out = s;
997
+ while (out.length > 0 && out[0] === 'v') {
998
+ out = out.slice(1);
999
+ }
1000
+ return out;
1001
+ }
1002
+
1003
+ function _check_bridge_drift(
1004
+ missing: Dict[],
1005
+ modified: Dict[],
1006
+ foreign: Dict[],
1007
+ tag_drift: Dict[],
1008
+ ): Dict {
1009
+ const total = missing.length + modified.length + foreign.length + tag_drift.length;
1010
+ if (total === 0) {
1011
+ return {
1012
+ id: 'bridge-drift',
1013
+ status: 'ok',
1014
+ message: 'manifest matches filesystem (no drift)',
1015
+ remedy: '',
1016
+ };
1017
+ }
1018
+ const parts: string[] = [];
1019
+ if (missing.length) parts.push(`${missing.length} missing`);
1020
+ if (modified.length) parts.push(`${modified.length} modified`);
1021
+ if (foreign.length) parts.push(`${foreign.length} foreign`);
1022
+ if (tag_drift.length) parts.push(`${tag_drift.length} tag-drift`);
1023
+ return {
1024
+ id: 'bridge-drift',
1025
+ status: 'fail',
1026
+ message: `${total} drift item(s): ${parts.join(', ')}`,
1027
+ remedy: 'see the drift section below or run `./agent-config sync`',
1028
+ };
1029
+ }
1030
+
1031
+ function _check_mcp_mode(project_root: string): Dict {
1032
+ const candidates: ReadonlyArray<[string, string]> = [
1033
+ ['.cursor/mcp.json', 'cursor'],
1034
+ ['.ai/mcp/mcp.json', 'ai-mcp'],
1035
+ ['mcp.json', 'root'],
1036
+ ];
1037
+ const found: string[] = [];
1038
+ for (const [rel, label] of candidates) {
1039
+ const p = path.join(project_root, rel);
1040
+ if (!pathExists(p)) {
1041
+ continue;
1042
+ }
1043
+ try {
1044
+ JSON.parse(readText(p));
1045
+ found.push(`${label} (${rel})`);
1046
+ } catch {
1047
+ return {
1048
+ id: 'mcp-mode',
1049
+ status: 'warn',
1050
+ message: `MCP config at ${rel} is not valid JSON`,
1051
+ remedy: `fix or remove \`${rel}\` (see docs/architecture.md § MCP)`,
1052
+ };
1053
+ }
1054
+ }
1055
+ if (found.length === 0) {
1056
+ return {
1057
+ id: 'mcp-mode',
1058
+ status: 'ok',
1059
+ message: 'no MCP config present (MCP Beta off)',
1060
+ remedy: '',
1061
+ };
1062
+ }
1063
+ return {
1064
+ id: 'mcp-mode',
1065
+ status: 'ok',
1066
+ message: `MCP config detected: ${found.join(', ')}`,
1067
+ remedy: '',
1068
+ };
1069
+ }
1070
+
1071
+ function _check_offline_readiness(): Dict {
1072
+ const script = path.join(_package_root(), 'src', 'scripts', 'hermetic-install.sh');
1073
+ if (!pathExists(script)) {
1074
+ return {
1075
+ id: 'offline-readiness',
1076
+ status: 'warn',
1077
+ message: 'src/scripts/hermetic-install.sh not found in package',
1078
+ remedy: 'reinstall @event4u/agent-config or pull missing files',
1079
+ };
1080
+ }
1081
+ return {
1082
+ id: 'offline-readiness',
1083
+ status: 'ok',
1084
+ message: 'verified-offline install entrypoint present',
1085
+ remedy: '',
1086
+ };
1087
+ }
1088
+
1089
+ function _check_stale_orphans(): Dict {
1090
+ const gdi = global_deploy_inventory;
1091
+
1092
+ const inv = gdi.load_inventory();
1093
+ const tools = (inv['tools'] as Dict | undefined) ?? {};
1094
+ if (typeof tools !== 'object' || tools === null || Object.keys(tools).length === 0) {
1095
+ return {
1096
+ id: 'stale-orphans',
1097
+ status: 'ok',
1098
+ message: 'no global-deploy inventory yet — nothing to reconcile',
1099
+ remedy: '',
1100
+ };
1101
+ }
1102
+ let orphan_count = 0;
1103
+ const sample: string[] = [];
1104
+ const toolEntries = Object.entries(tools).sort((a, b) =>
1105
+ a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0,
1106
+ );
1107
+ for (const [tool_id, entryRaw] of toolEntries) {
1108
+ const entry = entryRaw as Dict;
1109
+ if (typeof entry !== 'object' || entry === null) {
1110
+ continue;
1111
+ }
1112
+ const anchor_raw = entry['anchor'];
1113
+ const recorded = entry['files'];
1114
+ if (typeof anchor_raw !== 'string' || !Array.isArray(recorded)) {
1115
+ continue;
1116
+ }
1117
+ const anchor = expanduser(anchor_raw);
1118
+ if (!isDir(anchor)) {
1119
+ continue;
1120
+ }
1121
+ const recorded_set = new Set(recorded.filter((r) => typeof r === 'string') as string[]);
1122
+ // Bound the scan to the top-level subtrees the package actually owns.
1123
+ const owned_roots = new Set<string>();
1124
+ for (const r of recorded_set) {
1125
+ if (r.includes('/')) {
1126
+ owned_roots.add(r.split('/', 1)[0] as string);
1127
+ }
1128
+ }
1129
+ const ownedSorted = Array.from(owned_roots).sort((a, b) =>
1130
+ a < b ? -1 : a > b ? 1 : 0,
1131
+ );
1132
+ for (const root_name of ownedSorted) {
1133
+ const root = path.join(anchor, root_name);
1134
+ if (!isDir(root)) {
1135
+ continue;
1136
+ }
1137
+ for (const md of rglob(root)) {
1138
+ if (isDir(md)) {
1139
+ continue;
1140
+ }
1141
+ if (!md.endsWith('.md')) {
1142
+ // rglob("*.md") in Python: only .md basenames.
1143
+ continue;
1144
+ }
1145
+ const rel = relativeTo(md, anchor);
1146
+ if (rel === null) {
1147
+ continue;
1148
+ }
1149
+ const relPosix = rel.split(path.sep).join('/');
1150
+ if (recorded_set.has(relPosix)) {
1151
+ continue;
1152
+ }
1153
+ const tag = _read_inline_package_tag(md);
1154
+ if (tag instanceof _Sentinel || tag !== PACKAGE_TAG_ID) {
1155
+ continue;
1156
+ }
1157
+ orphan_count += 1;
1158
+ if (sample.length < 5) {
1159
+ sample.push(`${tool_id}:${relPosix}`);
1160
+ }
1161
+ }
1162
+ }
1163
+ }
1164
+ if (orphan_count === 0) {
1165
+ return {
1166
+ id: 'stale-orphans',
1167
+ status: 'ok',
1168
+ message: 'no stale package-tagged files under recorded anchors',
1169
+ remedy: '',
1170
+ };
1171
+ }
1172
+ return {
1173
+ id: 'stale-orphans',
1174
+ status: 'warn',
1175
+ message:
1176
+ `${orphan_count} stale package-tagged file(s) not tracked by the ` +
1177
+ `deploy inventory (e.g. ${sample.join(', ')})`,
1178
+ remedy:
1179
+ 'run `agent-config global` to reap them ' +
1180
+ '(the tag sweep reconciles on every deploy)',
1181
+ };
1182
+ }
1183
+
1184
+ function _check_python_runtime(): Dict {
1185
+ // Post-teardown: the package runtime is TypeScript-on-`tsx`. python3 is no
1186
+ // longer a runtime dependency, so this check no longer probes for an
1187
+ // interpreter (spawning python3 here would be misleading in a python-free
1188
+ // package). The check id is retained for the doctor's stable report shape;
1189
+ // it always reports `ok`.
1190
+ return {
1191
+ id: 'python-runtime',
1192
+ status: 'ok',
1193
+ message: 'python3 is not a runtime dependency (TS runtime via tsx)',
1194
+ remedy: '',
1195
+ };
1196
+ }
1197
+
1198
+ function _check_mcp_beta_readiness(project_root: string): Dict {
1199
+ const pending: string[] = [];
1200
+ for (const [gate_id, rel] of MCP_BETA_GATES) {
1201
+ if (!pathExists(path.join(project_root, rel))) {
1202
+ pending.push(`${gate_id} (${rel})`);
1203
+ }
1204
+ }
1205
+ if (pending.length === 0) {
1206
+ return {
1207
+ id: 'mcp-beta-readiness',
1208
+ status: 'ok',
1209
+ message: 'all 6 MCP beta gates green — promotion authorized',
1210
+ remedy: '',
1211
+ };
1212
+ }
1213
+ return {
1214
+ id: 'mcp-beta-readiness',
1215
+ status: 'warn',
1216
+ message: `${pending.length}/6 MCP beta gate(s) pending: ${pending.join(', ')}`,
1217
+ remedy:
1218
+ 'produce the artefacts listed in ' +
1219
+ 'docs/contracts/mcp-beta-criteria.md (one per gate); ' +
1220
+ 'do not flip `experimental` wording until all 6 are green',
1221
+ };
1222
+ }
1223
+
1224
+ function _check_tier_usage_readiness(project_root: string): Dict {
1225
+ const settings_file = project_settings_path(project_root);
1226
+ let log_path = path.join(project_root, '.agent-tier-usage.jsonl');
1227
+ let enabled = false;
1228
+ if (isFile(settings_file)) {
1229
+ let raw: unknown;
1230
+ const loaded = yamlSafeLoad(readText0(settings_file));
1231
+ if (loaded === null) {
1232
+ // ImportError (yaml unavailable) → skip; enabled stays false.
1233
+ raw = null;
1234
+ } else {
1235
+ raw = loaded === undefined ? {} : loaded;
1236
+ if (raw === null || raw === undefined) raw = {};
1237
+ const rawDict = (typeof raw === 'object' && raw !== null && !Array.isArray(raw))
1238
+ ? (raw as Dict)
1239
+ : {};
1240
+ const teleRaw = rawDict['telemetry'];
1241
+ const tele = (typeof teleRaw === 'object' && teleRaw !== null && !Array.isArray(teleRaw))
1242
+ ? (teleRaw as Dict)
1243
+ : {};
1244
+ const tuRaw = tele['tier_usage'];
1245
+ const tu =
1246
+ typeof tuRaw === 'object' && tuRaw !== null && !Array.isArray(tuRaw)
1247
+ ? (tuRaw as Dict)
1248
+ : null;
1249
+ if (tu !== null) {
1250
+ const outputRaw = tu['output'];
1251
+ const output =
1252
+ typeof outputRaw === 'object' && outputRaw !== null && !Array.isArray(outputRaw)
1253
+ ? (outputRaw as Dict)
1254
+ : {};
1255
+ if (typeof output['path'] === 'string' && (output['path'] as string).trim()) {
1256
+ log_path = path.join(project_root, (output['path'] as string).trim());
1257
+ }
1258
+ const val = tu['enabled'];
1259
+ if (typeof val === 'boolean') {
1260
+ enabled = val;
1261
+ } else if (typeof val === 'string') {
1262
+ enabled = ['true', 'yes', 'on', '1'].includes(val.trim().toLowerCase());
1263
+ } else {
1264
+ enabled = false;
1265
+ }
1266
+ }
1267
+ }
1268
+ }
1269
+
1270
+ if (!enabled) {
1271
+ return {
1272
+ id: 'tier-usage-readiness',
1273
+ status: 'warn',
1274
+ message:
1275
+ 'tier-usage telemetry disabled — empirical retiering ' +
1276
+ 'decisions fall back to operator judgement',
1277
+ remedy:
1278
+ 'set `telemetry.tier_usage.enabled: true` in ' +
1279
+ '.agent-settings.yml (default-off; opt-in)',
1280
+ };
1281
+ }
1282
+ if (!pathExists(log_path)) {
1283
+ return {
1284
+ id: 'tier-usage-readiness',
1285
+ status: 'warn',
1286
+ message:
1287
+ `tier-usage telemetry on but ${path.basename(log_path)} not yet ` +
1288
+ 'written — no signal accumulated',
1289
+ remedy:
1290
+ 'run any tracked command to seed the log; the dispatcher ' +
1291
+ 'writes one record per invocation',
1292
+ };
1293
+ }
1294
+ let total = 0;
1295
+ let valid = 0;
1296
+ const allowed_fields = new Set(['ts_bucket', 'command', 'tier', 'outcome', 'user_hash']);
1297
+ const allowed_outcomes = new Set(['success', 'error', 'blocked']);
1298
+ let content: string;
1299
+ try {
1300
+ content = readText0(log_path);
1301
+ } catch (exc) {
1302
+ return {
1303
+ id: 'tier-usage-readiness',
1304
+ status: 'fail',
1305
+ message: `cannot read ${path.basename(log_path)}: ${osErrorStr(exc)}`,
1306
+ remedy: 'fix permissions on the tier-usage log',
1307
+ };
1308
+ }
1309
+ for (let line of splitlines(content)) {
1310
+ line = line.trim();
1311
+ if (!line) {
1312
+ continue;
1313
+ }
1314
+ total += 1;
1315
+ let obj: unknown;
1316
+ try {
1317
+ obj = JSON.parse(line);
1318
+ } catch {
1319
+ continue;
1320
+ }
1321
+ if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
1322
+ continue;
1323
+ }
1324
+ const o = obj as Dict;
1325
+ if (!Object.keys(o).every((k) => allowed_fields.has(k))) {
1326
+ continue;
1327
+ }
1328
+ if (
1329
+ typeof o['command'] === 'string' &&
1330
+ o['command'] &&
1331
+ typeof o['tier'] === 'number' &&
1332
+ Number.isInteger(o['tier']) &&
1333
+ [0, 1, 2, 3].includes(o['tier'] as number) &&
1334
+ allowed_outcomes.has(o['outcome'] as string) &&
1335
+ typeof o['user_hash'] === 'string' &&
1336
+ (o['user_hash'] as string).length === 16 &&
1337
+ typeof o['ts_bucket'] === 'string'
1338
+ ) {
1339
+ valid += 1;
1340
+ }
1341
+ }
1342
+ if (total > 0 && valid === 0) {
1343
+ return {
1344
+ id: 'tier-usage-readiness',
1345
+ status: 'fail',
1346
+ message:
1347
+ `${total} record(s) in ${path.basename(log_path)} but 0 passed the ` +
1348
+ 'privacy floor — report would refuse to render',
1349
+ remedy:
1350
+ 'inspect the log; the dispatcher is writing records the ' +
1351
+ 'contract forbids (paths, argv, message bodies)',
1352
+ };
1353
+ }
1354
+ if (valid === 0) {
1355
+ return {
1356
+ id: 'tier-usage-readiness',
1357
+ status: 'warn',
1358
+ message: `${path.basename(log_path)} present but empty — no signal yet`,
1359
+ remedy: 'run any tracked command to seed the log',
1360
+ };
1361
+ }
1362
+ return {
1363
+ id: 'tier-usage-readiness',
1364
+ status: 'ok',
1365
+ message:
1366
+ `${valid} record(s) past the privacy floor in ${path.basename(log_path)} ` +
1367
+ '— retiering signal available',
1368
+ remedy: '',
1369
+ };
1370
+ }
1371
+
1372
+ /** read_text that re-throws OSError-like errors (used where Python catches them). */
1373
+ function readText0(p: string): string {
1374
+ return fs.readFileSync(p, 'utf-8');
1375
+ }
1376
+
1377
+ /** Render an OSError-equivalent like Python's `str(exc)` for the message. */
1378
+ function osErrorStr(exc: unknown): string {
1379
+ if (exc && typeof exc === 'object' && 'message' in exc) {
1380
+ return String((exc as { message: unknown }).message);
1381
+ }
1382
+ return String(exc);
1383
+ }
1384
+
1385
+ /**
1386
+ * Provider → (default binary, billable flag). Mirrors the `CliClient`
1387
+ * subclass attributes without importing them at module load time.
1388
+ */
1389
+ const _CLI_PROVIDER_META: Record<string, [string, boolean]> = {
1390
+ anthropic: ['claude', false],
1391
+ openai: ['codex', false],
1392
+ gemini: ['gemini', false],
1393
+ xai: ['grok', true],
1394
+ perplexity: ['perplexity', true],
1395
+ };
1396
+
1397
+ function _check_council_cli(project_root: string): Dict {
1398
+ // Python wraps the council-module import in a try/except ImportError so a
1399
+ // broken council install degrades to a `warn` instead of crashing doctor.
1400
+ // In the TS twin the council twins are statically bundled — the import can
1401
+ // never fail — so the "council deps unavailable" arm is unreachable here.
1402
+ // `errTypeName` is retained for parity with that arm's wording shape.
1403
+ const { load_cli_call_counts } = ai_council_clients;
1404
+ const { load_council_config, resolve_config_path } = ai_council_config;
1405
+ const council_path = resolve_config_path(project_root);
1406
+ if (!pathExists(String(council_path))) {
1407
+ return {
1408
+ id: 'council-cli',
1409
+ status: 'ok',
1410
+ message: `no council config (${council_path} not present)`,
1411
+ remedy:
1412
+ 'create the user-global council config at ' +
1413
+ `${council_path} (see docs/contracts/ai-council-config.md)`,
1414
+ };
1415
+ }
1416
+ let cfg: ai_council_config.CouncilConfig;
1417
+ try {
1418
+ cfg = load_council_config(council_path);
1419
+ } catch (exc) {
1420
+ return {
1421
+ id: 'council-cli',
1422
+ status: 'warn',
1423
+ message: `council config invalid: ${excStr(exc)}`,
1424
+ remedy: `fix ${council_path} and re-run doctor`,
1425
+ };
1426
+ }
1427
+ const cli_members: Array<[string, ai_council_config.MemberConfig]> = [];
1428
+ for (const [name, m] of cfg.members.entries()) {
1429
+ if (m.enabled && m.mode === 'cli' && name in _CLI_PROVIDER_META) {
1430
+ cli_members.push([name, m]);
1431
+ }
1432
+ }
1433
+ if (cli_members.length === 0) {
1434
+ return {
1435
+ id: 'council-cli',
1436
+ status: 'ok',
1437
+ message: 'no enabled CLI-mode members',
1438
+ remedy: '',
1439
+ };
1440
+ }
1441
+ const counts = load_cli_call_counts();
1442
+ const caps = cfg.cli_call_budget.max_calls_per_day;
1443
+ const warn_at = cfg.cli_call_budget.warn_at;
1444
+ const missing: string[] = [];
1445
+ const over_warn: string[] = [];
1446
+ const lines: string[] = [];
1447
+ for (const [name, member] of cli_members) {
1448
+ const [default_bin, billable] = _CLI_PROVIDER_META[name] as [string, boolean];
1449
+ const binary_name = member.binary || default_bin;
1450
+ const resolved = shutilWhich(binary_name);
1451
+ const binary_glyph = resolved ? '✅' : '❌';
1452
+ if (resolved === null) {
1453
+ missing.push(name);
1454
+ }
1455
+ const used = Math.trunc((counts[name] as number | undefined) ?? 0);
1456
+ const cap = caps.get(name);
1457
+ let quota_glyph: string;
1458
+ let quota_str: string;
1459
+ if (cap !== undefined && cap !== null) {
1460
+ const ratio = cap > 0 ? used / cap : 0.0;
1461
+ quota_glyph = ratio >= warn_at ? '⚠️' : '✅';
1462
+ if (ratio >= warn_at) {
1463
+ over_warn.push(name);
1464
+ }
1465
+ quota_str = `${used}/${cap}`;
1466
+ } else {
1467
+ quota_glyph = '—';
1468
+ quota_str = `${used}/—`;
1469
+ }
1470
+ const billable_str = billable ? 'billable' : 'subscription';
1471
+ lines.push(
1472
+ `${name}: binary ${binary_glyph} (${binary_name}) · ` +
1473
+ `quota ${quota_glyph} ${quota_str} · ${billable_str}`,
1474
+ );
1475
+ }
1476
+ const detail = lines.join(' | ');
1477
+ if (missing.length > 0) {
1478
+ return {
1479
+ id: 'council-cli',
1480
+ status: 'warn',
1481
+ message:
1482
+ `${missing.length}/${cli_members.length} CLI member(s) missing binary ` +
1483
+ `(${missing.join(', ')}) · ${detail}`,
1484
+ remedy:
1485
+ 'install the missing CLI(s) — see `council:estimate` pre-flight ' +
1486
+ 'for per-provider install hints, or flip ' +
1487
+ "ai_council.members.<name>.mode to 'api'",
1488
+ };
1489
+ }
1490
+ if (over_warn.length > 0) {
1491
+ return {
1492
+ id: 'council-cli',
1493
+ status: 'warn',
1494
+ message:
1495
+ `${over_warn.length}/${cli_members.length} CLI member(s) at/over ` +
1496
+ `quota warn_at=${pyFloat(warn_at)} (${over_warn.join(', ')}) · ${detail}`,
1497
+ remedy:
1498
+ 'wait for UTC rollover or run ' +
1499
+ '`./scripts-run src/scripts/council_cli quota --reset` to clear the counter',
1500
+ };
1501
+ }
1502
+ return {
1503
+ id: 'council-cli',
1504
+ status: 'ok',
1505
+ message: `${cli_members.length} CLI member(s) healthy · ${detail}`,
1506
+ remedy: '',
1507
+ };
1508
+ }
1509
+
1510
+ /** Python `str(exc)` for an exception interpolated into a message. */
1511
+ function excStr(exc: unknown): string {
1512
+ if (exc instanceof Error) {
1513
+ return exc.message;
1514
+ }
1515
+ return String(exc);
1516
+ }
1517
+
1518
+ /**
1519
+ * Render a float the way Python `str(float)` would for the `warn_at` value
1520
+ * interpolated into the message (e.g. `0.8` not `0.8000000001`; `1.0` keeps
1521
+ * the `.0`). The config carries a plain JS number; `warn_at` defaults are
1522
+ * one-decimal fractions, so `String()` already matches Python for those.
1523
+ */
1524
+ function pyFloat(value: number): string {
1525
+ if (Number.isInteger(value)) {
1526
+ return `${value}.0`;
1527
+ }
1528
+ return String(value);
1529
+ }
1530
+
1531
+ function _check_unsupported_combos(manifest: Dict): Dict {
1532
+ const global_only = new Set(['droid', 'qoder']);
1533
+ const bad: string[] = [];
1534
+ const tools = (manifest['tools'] as Dict[] | undefined) || [];
1535
+ for (const tool of tools) {
1536
+ const name = String(tool['name'] ?? '');
1537
+ const scope = tool['scope'];
1538
+ if (global_only.has(name) && scope !== 'global') {
1539
+ bad.push(`${name} (scope=${scope}, requires global)`);
1540
+ }
1541
+ }
1542
+ if (bad.length > 0) {
1543
+ return {
1544
+ id: 'unsupported-combos',
1545
+ status: 'fail',
1546
+ message: `${bad.length} tool(s) with unsupported scope: ${bad.join(', ')}`,
1547
+ remedy: 're-install the listed tools with `--global --force`',
1548
+ };
1549
+ }
1550
+ return {
1551
+ id: 'unsupported-combos',
1552
+ status: 'ok',
1553
+ message: 'all installed tools use supported scopes',
1554
+ remedy: '',
1555
+ };
1556
+ }
1557
+
1558
+ function _wizard_state_path(): string {
1559
+ return path.join(user_global_paths.event4u_root(), 'state', 'wizard-state.json');
1560
+ }
1561
+
1562
+ function _check_wizard_state(): Dict {
1563
+ const state_pth = _wizard_state_path();
1564
+ if (!pathExists(state_pth)) {
1565
+ return {
1566
+ id: 'wizard-state',
1567
+ status: 'ok',
1568
+ message: 'no active wizard session',
1569
+ remedy: '',
1570
+ };
1571
+ }
1572
+ let raw: string;
1573
+ try {
1574
+ raw = readText0(state_pth);
1575
+ } catch (exc) {
1576
+ return {
1577
+ id: 'wizard-state',
1578
+ status: 'fail',
1579
+ message: `unreadable wizard-state at ${state_pth}: ${osErrorStr(exc)}`,
1580
+ remedy: 'agent-config doctor --repair wizard-state',
1581
+ };
1582
+ }
1583
+ let data: unknown;
1584
+ try {
1585
+ data = parseJsonPy(raw);
1586
+ } catch (exc) {
1587
+ const de = exc as JsonDecodeError;
1588
+ return {
1589
+ id: 'wizard-state',
1590
+ status: 'fail',
1591
+ message: `malformed JSON in wizard-state (${de.msg} at line ${de.lineno})`,
1592
+ remedy: 'agent-config doctor --repair wizard-state',
1593
+ };
1594
+ }
1595
+ if (typeof data !== 'object' || data === null || Array.isArray(data)) {
1596
+ return {
1597
+ id: 'wizard-state',
1598
+ status: 'fail',
1599
+ message: `wizard-state root is ${pyTypeName(data)}, expected object`,
1600
+ remedy: 'agent-config doctor --repair wizard-state',
1601
+ };
1602
+ }
1603
+ const d = data as Dict;
1604
+ const step = d['step'];
1605
+ const partial = 'partial' in d ? d['partial'] : {};
1606
+ if (typeof step !== 'number' || !Number.isInteger(step) || (step as number) < 0 || typeof step === 'boolean') {
1607
+ return {
1608
+ id: 'wizard-state',
1609
+ status: 'fail',
1610
+ message: `wizard-state.step is ${pyRepr(step)}, expected non-negative integer`,
1611
+ remedy: 'agent-config doctor --repair wizard-state',
1612
+ };
1613
+ }
1614
+ if (typeof partial !== 'object' || partial === null || Array.isArray(partial)) {
1615
+ return {
1616
+ id: 'wizard-state',
1617
+ status: 'fail',
1618
+ message: `wizard-state.partial is ${pyTypeName(partial)}, expected object`,
1619
+ remedy: 'agent-config doctor --repair wizard-state',
1620
+ };
1621
+ }
1622
+ const total = d['totalSteps'];
1623
+ if (
1624
+ total !== undefined &&
1625
+ total !== null &&
1626
+ (typeof total !== 'number' || !Number.isInteger(total) || (total as number) < 1 || typeof total === 'boolean')
1627
+ ) {
1628
+ return {
1629
+ id: 'wizard-state',
1630
+ status: 'fail',
1631
+ message: `wizard-state.totalSteps is ${pyRepr(total)}, expected positive integer or omitted`,
1632
+ remedy: 'agent-config doctor --repair wizard-state',
1633
+ };
1634
+ }
1635
+ const suffix =
1636
+ typeof total === 'number' && Number.isInteger(total) && typeof total !== 'boolean'
1637
+ ? ` of ${total}`
1638
+ : '';
1639
+ return {
1640
+ id: 'wizard-state',
1641
+ status: 'ok',
1642
+ message: `resumable wizard session at step ${(step as number) + 1}${suffix}`,
1643
+ remedy: '',
1644
+ };
1645
+ }
1646
+
1647
+ interface JsonDecodeError {
1648
+ msg: string;
1649
+ lineno: number;
1650
+ colno: number;
1651
+ }
1652
+
1653
+ /**
1654
+ * Parse JSON the way Python's `json.loads` does, surfacing a
1655
+ * `json.JSONDecodeError`-shaped error with `.msg`/`.lineno`/`.colno` so the
1656
+ * malformed-JSON message matches. JS `JSON.parse` reports a char offset (not
1657
+ * line/col), so we recompute the line/col from the offset in the error text.
1658
+ */
1659
+ function parseJsonPy(text: string): unknown {
1660
+ try {
1661
+ return JSON.parse(text);
1662
+ } catch (e) {
1663
+ const m = String((e as Error).message);
1664
+ // Node V8: "... in JSON at position N (line L column C)" or "position N".
1665
+ let pos = -1;
1666
+ const posM = m.match(/position (\d+)/);
1667
+ if (posM) pos = Number.parseInt(posM[1] as string, 10);
1668
+ let lineno = 1;
1669
+ let colno = 1;
1670
+ if (pos >= 0) {
1671
+ let line = 1;
1672
+ let col = 1;
1673
+ for (let i = 0; i < pos && i < text.length; i++) {
1674
+ if (text[i] === '\n') {
1675
+ line += 1;
1676
+ col = 1;
1677
+ } else {
1678
+ col += 1;
1679
+ }
1680
+ }
1681
+ lineno = line;
1682
+ colno = col;
1683
+ }
1684
+ // Python's msg is e.g. "Expecting value"; V8's differs. The golden
1685
+ // tests normalize the `.msg` token (it diverges by engine) and assert
1686
+ // the structural shape + lineno. We surface a best-effort msg so the
1687
+ // sentence renders; the lineno is the load-bearing, parity-stable part.
1688
+ const err: JsonDecodeError = { msg: pythonJsonMsg(m), lineno, colno };
1689
+ throw err;
1690
+ }
1691
+ }
1692
+
1693
+ /** Map a V8 JSON error to the closest Python `json` message token. */
1694
+ function pythonJsonMsg(v8msg: string): string {
1695
+ if (/Unexpected end of JSON input/.test(v8msg)) return 'Expecting value';
1696
+ if (/Unexpected token/.test(v8msg)) return 'Expecting value';
1697
+ if (/Expected property name/.test(v8msg)) return 'Expecting property name enclosed in double quotes';
1698
+ return 'Expecting value';
1699
+ }
1700
+
1701
+ /** Python `type(x).__name__` for the JSON-shape error messages. */
1702
+ function pyTypeName(value: unknown): string {
1703
+ if (value === null) return 'NoneType';
1704
+ if (Array.isArray(value)) return 'list';
1705
+ switch (typeof value) {
1706
+ case 'boolean':
1707
+ return 'bool';
1708
+ case 'number':
1709
+ return Number.isInteger(value) ? 'int' : 'float';
1710
+ case 'string':
1711
+ return 'str';
1712
+ case 'object':
1713
+ return 'dict';
1714
+ default:
1715
+ return typeof value;
1716
+ }
1717
+ }
1718
+
1719
+ /** Python `repr()` for the scalar values interpolated with `{x!r}`. */
1720
+ function pyRepr(value: unknown): string {
1721
+ if (value === null || value === undefined) return 'None';
1722
+ if (typeof value === 'boolean') return value ? 'True' : 'False';
1723
+ if (typeof value === 'number') {
1724
+ if (Number.isInteger(value)) return String(value);
1725
+ return String(value);
1726
+ }
1727
+ if (typeof value === 'string') {
1728
+ // Python repr prefers single quotes; escapes backslash + the quote.
1729
+ const escaped = value.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
1730
+ return `'${escaped}'`;
1731
+ }
1732
+ if (Array.isArray(value)) {
1733
+ return '[' + value.map((v) => pyRepr(v)).join(', ') + ']';
1734
+ }
1735
+ if (typeof value === 'object') {
1736
+ const obj = value as Dict;
1737
+ const parts = Object.keys(obj).map((k) => `${pyRepr(k)}: ${pyRepr(obj[k])}`);
1738
+ return '{' + parts.join(', ') + '}';
1739
+ }
1740
+ return String(value);
1741
+ }
1742
+
1743
+ type CheckRunner = () => Dict;
1744
+
1745
+ function _run_checks(
1746
+ project_root: string,
1747
+ manifest: Dict,
1748
+ drift: Record<string, Dict[]>,
1749
+ only: string | null = null,
1750
+ ): Dict[] {
1751
+ const runners: Record<string, CheckRunner> = {
1752
+ scope: () => _check_scope(project_root),
1753
+ 'global-binary': () => _check_global_binary(project_root),
1754
+ 'stale-orphans': _check_stale_orphans,
1755
+ 'manifest-integrity': () => _check_manifest_integrity(manifest),
1756
+ 'lockfile-freshness': () => _check_lockfile_freshness(manifest),
1757
+ 'bridge-drift': () =>
1758
+ _check_bridge_drift(
1759
+ drift['missing'] as Dict[],
1760
+ drift['modified'] as Dict[],
1761
+ drift['foreign'] as Dict[],
1762
+ drift['tag_drift'] as Dict[],
1763
+ ),
1764
+ 'mcp-mode': () => _check_mcp_mode(project_root),
1765
+ 'mcp-beta-readiness': () => _check_mcp_beta_readiness(project_root),
1766
+ 'offline-readiness': () => _check_offline_readiness(),
1767
+ 'python-runtime': () => _check_python_runtime(),
1768
+ 'tier-usage-readiness': () => _check_tier_usage_readiness(project_root),
1769
+ 'council-cli': () => _check_council_cli(project_root),
1770
+ 'unsupported-combos': () => _check_unsupported_combos(manifest),
1771
+ 'wizard-state': _check_wizard_state,
1772
+ };
1773
+ const out: Dict[] = [];
1774
+ for (const cid of CHECK_IDS) {
1775
+ if (only !== null && cid !== only) {
1776
+ continue;
1777
+ }
1778
+ out.push((runners[cid] as CheckRunner)());
1779
+ }
1780
+ return out;
1781
+ }
1782
+
1783
+ function _skipped_manifest_check(check_id: string): Dict {
1784
+ return {
1785
+ id: check_id,
1786
+ status: 'skipped',
1787
+ message: 'requires a project lockfile (agents/installed-tools.lock)',
1788
+ remedy:
1789
+ 'run `agent-config init` to create a project lockfile, ' +
1790
+ 'then re-run this check',
1791
+ };
1792
+ }
1793
+
1794
+ function _check_bridge_drift_no_manifest(bridge_present: boolean): Dict {
1795
+ if (bridge_present) {
1796
+ return {
1797
+ id: 'bridge-drift',
1798
+ status: 'ok',
1799
+ message:
1800
+ 'no project lockfile → distributed-tool drift not ' +
1801
+ 'applicable (global-only consumer)',
1802
+ remedy: '',
1803
+ };
1804
+ }
1805
+ return {
1806
+ id: 'bridge-drift',
1807
+ status: 'skipped',
1808
+ message:
1809
+ 'no project lockfile and no bridge marker → drift check ' +
1810
+ 'not applicable',
1811
+ remedy:
1812
+ 'run `agent-config init` (project install) or ' +
1813
+ '`agent-config refresh --project` (global-only consumer)',
1814
+ };
1815
+ }
1816
+
1817
+ function _run_checks_no_manifest(
1818
+ project_root: string,
1819
+ bridge_present: boolean,
1820
+ only: string | null = null,
1821
+ ): Dict[] {
1822
+ const runners: Record<string, CheckRunner> = {
1823
+ scope: () => _check_scope(project_root),
1824
+ 'global-binary': () => _check_global_binary(project_root),
1825
+ 'stale-orphans': _check_stale_orphans,
1826
+ 'manifest-integrity': () => _skipped_manifest_check('manifest-integrity'),
1827
+ 'lockfile-freshness': () => _skipped_manifest_check('lockfile-freshness'),
1828
+ 'bridge-drift': () => _check_bridge_drift_no_manifest(bridge_present),
1829
+ 'mcp-mode': () => _check_mcp_mode(project_root),
1830
+ 'mcp-beta-readiness': () => _check_mcp_beta_readiness(project_root),
1831
+ 'offline-readiness': () => _check_offline_readiness(),
1832
+ 'python-runtime': () => _check_python_runtime(),
1833
+ 'tier-usage-readiness': () => _check_tier_usage_readiness(project_root),
1834
+ 'council-cli': () => _check_council_cli(project_root),
1835
+ 'unsupported-combos': () => _skipped_manifest_check('unsupported-combos'),
1836
+ 'wizard-state': _check_wizard_state,
1837
+ };
1838
+ const out: Dict[] = [];
1839
+ for (const cid of CHECK_IDS) {
1840
+ if (only !== null && cid !== only) {
1841
+ continue;
1842
+ }
1843
+ out.push((runners[cid] as CheckRunner)());
1844
+ }
1845
+ return out;
1846
+ }
1847
+
1848
+ function _run_no_manifest(
1849
+ opts: Options,
1850
+ project_root: string,
1851
+ origin: string,
1852
+ bridge_present: boolean,
1853
+ ): number {
1854
+ const checks = _run_checks_no_manifest(project_root, bridge_present, opts.check);
1855
+ const fail_check = checks.some((c) => c['status'] === 'fail');
1856
+ const skipped_requested =
1857
+ opts.check !== null &&
1858
+ checks.some((c) => c['id'] === opts.check && c['status'] === 'skipped');
1859
+
1860
+ if (opts.json) {
1861
+ _emit_json(project_root, [], [], [], [], checks, origin);
1862
+ } else if (opts.check === null) {
1863
+ print(` 📍 project_root: ${project_root} (origin: ${origin})`);
1864
+ if (bridge_present) {
1865
+ print(
1866
+ ' ℹ️ global-only consumer: bridge marker present, no ' +
1867
+ 'project lockfile (expected under ADR-020)',
1868
+ );
1869
+ print(
1870
+ ' project-manifest checks are skipped — they apply only ' +
1871
+ 'to project-local distributed tools',
1872
+ );
1873
+ } else {
1874
+ eprint(` ⚠️ no project lockfile and no bridge marker at ${project_root}`);
1875
+ eprint(
1876
+ ' run `agent-config init` (project install) or ' +
1877
+ '`agent-config refresh --project` (global-only consumer)',
1878
+ );
1879
+ }
1880
+ _emit_checks_text(checks);
1881
+ } else {
1882
+ _emit_checks_text(checks);
1883
+ }
1884
+
1885
+ if (opts.check !== null) {
1886
+ if (skipped_requested) {
1887
+ return 2;
1888
+ }
1889
+ return fail_check ? 1 : 0;
1890
+ }
1891
+ return bridge_present ? 0 : 2;
1892
+ }
1893
+
1894
+ function _emit_json(
1895
+ project_root: string,
1896
+ missing: Dict[],
1897
+ modified: Dict[],
1898
+ foreign: Dict[],
1899
+ tag_drift: Dict[],
1900
+ checks: Dict[] | null = null,
1901
+ origin: string | null = null,
1902
+ ): void {
1903
+ const payload: Dict = {
1904
+ project_root: String(project_root),
1905
+ missing,
1906
+ modified,
1907
+ foreign,
1908
+ tag_drift,
1909
+ };
1910
+ if (origin !== null) {
1911
+ payload['project_root_origin'] = origin;
1912
+ }
1913
+ if (checks !== null) {
1914
+ payload['checks'] = checks;
1915
+ }
1916
+ print(_jsonDumpsIndentAscii(payload, 2));
1917
+ }
1918
+
1919
+ function _emit_checks_text(checks: Dict[]): void {
1920
+ if (checks.length === 0) {
1921
+ return;
1922
+ }
1923
+ print('checks:');
1924
+ for (const c of checks) {
1925
+ const sym = STATUS_SYMBOLS[c['status'] as string] ?? '?';
1926
+ print(` ${sym} ${c['id']}: ${c['message']}`);
1927
+ if (c['status'] !== 'ok' && c['remedy']) {
1928
+ print(` fix: ${c['remedy']}`);
1929
+ }
1930
+ }
1931
+ print('');
1932
+ }
1933
+
1934
+ function _emit_text(
1935
+ project_root: string,
1936
+ missing: Dict[],
1937
+ modified: Dict[],
1938
+ foreign: Dict[],
1939
+ tag_drift: Dict[],
1940
+ ): void {
1941
+ const total = missing.length + modified.length + foreign.length + tag_drift.length;
1942
+ if (total === 0) {
1943
+ print(`✅ doctor: manifest matches filesystem under ${project_root}`);
1944
+ return;
1945
+ }
1946
+ print(`⚠️ doctor: ${total} drift item(s) under ${project_root}`);
1947
+ const groups: ReadonlyArray<[string, Dict[]]> = [
1948
+ ['missing', missing],
1949
+ ['modified', modified],
1950
+ ['foreign', foreign],
1951
+ ['tag-drift', tag_drift],
1952
+ ];
1953
+ for (const [label, items] of groups) {
1954
+ if (items.length === 0) {
1955
+ continue;
1956
+ }
1957
+ print(`\n ${label} (${items.length}):`);
1958
+ for (const it of items) {
1959
+ const tool = (it['tool'] as string) || '?';
1960
+ print(` · [${tool}] ${it['path']}`);
1961
+ if (label === 'tag-drift') {
1962
+ const found = (it['found'] as string) || '(missing)';
1963
+ const expected = 'expected' in it ? it['expected'] : PACKAGE_TAG_ID;
1964
+ print(` expected: ${expected}`);
1965
+ print(` found: ${found}`);
1966
+ }
1967
+ print(` fix: ${it['fix']}`);
1968
+ }
1969
+ }
1970
+ }
1971
+
1972
+ interface Options {
1973
+ project: string | null;
1974
+ json: boolean;
1975
+ check: string | null;
1976
+ trace_root: boolean;
1977
+ context: boolean;
1978
+ repair: string | null;
1979
+ }
1980
+
1981
+ const PROG = 'agent-config doctor';
1982
+
1983
+ // Verbatim argparse usage block (captured from the .py at COLUMNS=80). The
1984
+ // per-flag `--help` BODY is a documented divergence — argparse re-wraps it to
1985
+ // terminal width; golden tests assert the `usage:` token + exit code only.
1986
+ const USAGE =
1987
+ `usage: ${PROG} [-h] [--project PROJECT] [--json] [--check ID]\n` +
1988
+ ' [--trace-root] [--context] [--repair ID]\n';
1989
+
1990
+ const _STORE_TRUE_FLAGS: Record<string, keyof Options> = {
1991
+ '--json': 'json',
1992
+ '--trace-root': 'trace_root',
1993
+ '--context': 'context',
1994
+ };
1995
+
1996
+ const _VALUE_FLAGS: Record<string, keyof Options> = {
1997
+ '--project': 'project',
1998
+ '--check': 'check',
1999
+ '--repair': 'repair',
2000
+ };
2001
+
2002
+ function _argError(msg: string): never {
2003
+ process.stderr.write(USAGE);
2004
+ process.stderr.write(`${PROG}: error: ${msg}\n`);
2005
+ throw new ArgparseExit(2);
2006
+ }
2007
+
2008
+ function _parse(argv: string[]): Options {
2009
+ const opts: Record<string, unknown> = {
2010
+ project: null,
2011
+ json: false,
2012
+ check: null,
2013
+ trace_root: false,
2014
+ context: false,
2015
+ repair: null,
2016
+ };
2017
+
2018
+ const positionals: string[] = [];
2019
+ let i = 0;
2020
+ while (i < argv.length) {
2021
+ const a = argv[i] as string;
2022
+ if (a === '-h' || a === '--help') {
2023
+ process.stdout.write(USAGE);
2024
+ throw new ArgparseExit(0);
2025
+ }
2026
+ const eq = a.startsWith('--') ? a.indexOf('=') : -1;
2027
+ const flag = eq >= 0 ? a.slice(0, eq) : a;
2028
+ const inlineVal = eq >= 0 ? a.slice(eq + 1) : null;
2029
+
2030
+ const storeTrueDest = _STORE_TRUE_FLAGS[flag];
2031
+ if (storeTrueDest !== undefined) {
2032
+ if (inlineVal !== null) {
2033
+ _argError(`argument ${flag}: ignored explicit argument '${inlineVal}'`);
2034
+ }
2035
+ (opts as Dict)[storeTrueDest] = true;
2036
+ i += 1;
2037
+ continue;
2038
+ }
2039
+ const valueDest = _VALUE_FLAGS[flag];
2040
+ if (valueDest !== undefined) {
2041
+ let value: string;
2042
+ if (inlineVal !== null) {
2043
+ value = inlineVal;
2044
+ } else {
2045
+ if (i + 1 >= argv.length) {
2046
+ _argError(`argument ${argMetaName(flag)}: expected one argument`);
2047
+ }
2048
+ value = argv[i + 1] as string;
2049
+ i += 1;
2050
+ }
2051
+ if (flag === '--check' && !CHECK_IDS.includes(value as (typeof CHECK_IDS)[number])) {
2052
+ _argError(
2053
+ `argument --check: invalid choice: '${value}' ` +
2054
+ `(choose from ${CHECK_IDS.map((c) => `'${c}'`).join(', ')})`,
2055
+ );
2056
+ }
2057
+ if (flag === '--repair' && !REPAIR_IDS.includes(value as (typeof REPAIR_IDS)[number])) {
2058
+ _argError(
2059
+ `argument --repair: invalid choice: '${value}' ` +
2060
+ `(choose from ${REPAIR_IDS.map((c) => `'${c}'`).join(', ')})`,
2061
+ );
2062
+ }
2063
+ (opts as Dict)[valueDest] = value;
2064
+ i += 1;
2065
+ continue;
2066
+ }
2067
+ if (a.startsWith('-') && a !== '-') {
2068
+ _argError(`unrecognized arguments: ${a}`);
2069
+ }
2070
+ positionals.push(a);
2071
+ i += 1;
2072
+ }
2073
+ if (positionals.length > 0) {
2074
+ _argError(`unrecognized arguments: ${positionals.join(' ')}`);
2075
+ }
2076
+ return opts as unknown as Options;
2077
+ }
2078
+
2079
+ /** argparse's metavar for the missing-argument error (`--check` → `ID`). */
2080
+ function argMetaName(flag: string): string {
2081
+ if (flag === '--check') return '--check';
2082
+ if (flag === '--repair') return '--repair';
2083
+ return flag;
2084
+ }
2085
+
2086
+ function _run_trace_root(opts: Options): number {
2087
+ const start = process.cwd();
2088
+ const [root, anchor, trace] = find_project_root_with_trace(start);
2089
+ let origin: string;
2090
+ if (process.env[ROOT_OVERRIDE_ENV] === '1' && process.env[PROJECT_ROOT_ENV]) {
2091
+ origin = 'root-flag';
2092
+ } else if (opts.project) {
2093
+ origin = 'explicit';
2094
+ } else if (process.env[PROJECT_ROOT_ENV]) {
2095
+ origin = 'env';
2096
+ } else if (root !== null) {
2097
+ origin = anchor || 'unknown';
2098
+ } else {
2099
+ origin = 'cwd-fallback';
2100
+ }
2101
+ if (opts.json) {
2102
+ _emit_trace_json(root, anchor, trace, origin);
2103
+ } else {
2104
+ _emit_trace_text(root, anchor, trace, origin);
2105
+ }
2106
+ return 0;
2107
+ }
2108
+
2109
+ function _run_context(opts: Options): number {
2110
+ let project_root: string;
2111
+ let origin: string;
2112
+ try {
2113
+ [project_root, origin] = _resolve_project_root(opts.project);
2114
+ } catch (exc) {
2115
+ if (exc instanceof ProjectRootError) {
2116
+ eprint(`❌ doctor: ${exc.message}`);
2117
+ return 2;
2118
+ }
2119
+ throw exc;
2120
+ }
2121
+ const [mode, mode_source] = _detect_install_mode(project_root);
2122
+ const ctx: Dict = {
2123
+ project_root: String(project_root),
2124
+ origin,
2125
+ install_mode: mode,
2126
+ install_mode_source: mode_source,
2127
+ env_pin: process.env[PROJECT_ROOT_ENV] || null,
2128
+ root_override: process.env[ROOT_OVERRIDE_ENV] === '1',
2129
+ settings_layers: _settings_layer_chain(project_root),
2130
+ wrapper: _detect_wrapper(project_root),
2131
+ };
2132
+ if (opts.json) {
2133
+ print(_jsonDumpsIndentAscii(ctx, 2));
2134
+ } else {
2135
+ _emit_context_text(ctx);
2136
+ }
2137
+ return 0;
2138
+ }
2139
+
2140
+ function _run_repair(opts: Options): number {
2141
+ const target = opts.repair;
2142
+ if (target === 'wizard-state') {
2143
+ const state_pth = _wizard_state_path();
2144
+ const exists = pathExists(state_pth);
2145
+ const payload: Dict = {
2146
+ id: 'wizard-state',
2147
+ path: String(state_pth),
2148
+ action: exists ? 'remove' : 'noop',
2149
+ };
2150
+ if (exists) {
2151
+ try {
2152
+ fs.unlinkSync(state_pth);
2153
+ } catch (exc) {
2154
+ payload['action'] = 'error';
2155
+ payload['error'] = osErrorStr(exc);
2156
+ if (opts.json) {
2157
+ print(_jsonDumpsIndentAscii(payload, 2));
2158
+ } else {
2159
+ eprint(`❌ doctor: could not remove ${state_pth}: ${osErrorStr(exc)}`);
2160
+ }
2161
+ return 2;
2162
+ }
2163
+ }
2164
+ if (opts.json) {
2165
+ print(_jsonDumpsIndentAscii(payload, 2));
2166
+ } else {
2167
+ if (payload['action'] === 'remove') {
2168
+ print(`✅ doctor: reset wizard-state (${state_pth})`);
2169
+ } else {
2170
+ print(`✅ doctor: nothing to repair (no wizard-state at ${state_pth})`);
2171
+ }
2172
+ }
2173
+ return 0;
2174
+ }
2175
+ eprint(`❌ doctor: unknown repair target ${pyRepr(target)}`);
2176
+ return 2;
2177
+ }
2178
+
2179
+ function main(argv: string[] | null = null): number {
2180
+ const opts = _parse(argv !== null ? Array.from(argv) : process.argv.slice(2));
2181
+ if (opts.repair !== null) {
2182
+ return _run_repair(opts);
2183
+ }
2184
+ if (opts.trace_root) {
2185
+ return _run_trace_root(opts);
2186
+ }
2187
+ if (opts.context) {
2188
+ return _run_context(opts);
2189
+ }
2190
+ let project_root: string;
2191
+ let origin: string;
2192
+ try {
2193
+ [project_root, origin] = _resolve_project_root(opts.project);
2194
+ } catch (exc) {
2195
+ if (exc instanceof ProjectRootError) {
2196
+ eprint(`❌ doctor: ${exc.message}`);
2197
+ return 2;
2198
+ }
2199
+ throw exc;
2200
+ }
2201
+ const manifest_pth = installed_tools.manifest_path(project_root);
2202
+ const manifest = installed_tools.read_manifest(manifest_pth);
2203
+ if (manifest === null) {
2204
+ const bridge_present = isFile(path.join(project_root, BRIDGE_MARKER_RELATIVE));
2205
+ return _run_no_manifest(opts, project_root, origin, bridge_present);
2206
+ }
2207
+
2208
+ const [records, known] = _collect_manifest_entries(project_root, manifest);
2209
+ const [missing, modified, tag_drift] = _classify(records);
2210
+ const foreign = _foreign_records(project_root, _scan_foreign(project_root, manifest, known));
2211
+ const drift_groups: Record<string, Dict[]> = {
2212
+ missing,
2213
+ modified,
2214
+ foreign,
2215
+ tag_drift,
2216
+ };
2217
+ const checks = _run_checks(project_root, manifest, drift_groups, opts.check);
2218
+ const fail_check = checks.some((c) => c['status'] === 'fail');
2219
+
2220
+ if (opts.json) {
2221
+ _emit_json(project_root, missing, modified, foreign, tag_drift, checks, origin);
2222
+ } else {
2223
+ if (opts.check === null) {
2224
+ print(` 📍 project_root: ${project_root} (origin: ${origin})`);
2225
+ }
2226
+ _emit_checks_text(checks);
2227
+ if (opts.check === null) {
2228
+ _emit_text(project_root, missing, modified, foreign, tag_drift);
2229
+ }
2230
+ }
2231
+
2232
+ if (opts.check !== null) {
2233
+ return fail_check ? 1 : 0;
2234
+ }
2235
+ return missing.length || modified.length || foreign.length || tag_drift.length ? 1 : 0;
2236
+ }
2237
+
2238
+ // --- CLI entry ---
2239
+
2240
+ const _isCliEntry =
2241
+ process.argv[1] !== undefined &&
2242
+ import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href;
2243
+ if (_isCliEntry || process.argv[1] === _HERE) {
2244
+ try {
2245
+ process.exitCode = main(process.argv.slice(2));
2246
+ } catch (e) {
2247
+ if (e instanceof ArgparseExit) {
2248
+ process.exitCode = e.code;
2249
+ } else {
2250
+ throw e;
2251
+ }
2252
+ }
2253
+ }
2254
+
2255
+ export {
2256
+ main,
2257
+ _parse,
2258
+ _resolve_project_root,
2259
+ _detect_install_mode,
2260
+ _settings_layer_chain,
2261
+ _detect_wrapper,
2262
+ _read_inline_package_tag,
2263
+ _fix_hint,
2264
+ _collect_manifest_entries,
2265
+ _scan_foreign,
2266
+ _classify,
2267
+ _foreign_records,
2268
+ _check_scope,
2269
+ _check_manifest_integrity,
2270
+ _check_lockfile_freshness,
2271
+ _check_global_binary,
2272
+ _check_bridge_drift,
2273
+ _check_mcp_mode,
2274
+ _check_offline_readiness,
2275
+ _check_stale_orphans,
2276
+ _check_python_runtime,
2277
+ _check_mcp_beta_readiness,
2278
+ _check_tier_usage_readiness,
2279
+ _check_council_cli,
2280
+ _check_unsupported_combos,
2281
+ _check_wizard_state,
2282
+ _run_checks,
2283
+ _skipped_manifest_check,
2284
+ _check_bridge_drift_no_manifest,
2285
+ _run_checks_no_manifest,
2286
+ _emit_json,
2287
+ _emit_checks_text,
2288
+ _emit_text,
2289
+ _wizard_state_path,
2290
+ _run_repair,
2291
+ _run_trace_root,
2292
+ _run_context,
2293
+ CHECK_IDS,
2294
+ GLOBAL_CHECK_IDS,
2295
+ MANIFEST_REQUIRED_CHECK_IDS,
2296
+ BRIDGE_MARKER_RELATIVE,
2297
+ REPAIR_IDS,
2298
+ MCP_BETA_GATES,
2299
+ STATUS_SYMBOLS,
2300
+ MIN_PYTHON,
2301
+ PACKAGE_TAG_ID,
2302
+ NO_FRONTMATTER,
2303
+ ArgparseExit,
2304
+ _jsonDumpsIndentAscii,
2305
+ };
2306
+ export type { Options };