pi-dev-team 0.2.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 (780) hide show
  1. package/LICENSE +21 -0
  2. package/PORTING.md +134 -0
  3. package/README.md +207 -0
  4. package/UPSTREAM.json +64 -0
  5. package/agents/Explore.md +15 -0
  6. package/agents/a11y-review.md +118 -0
  7. package/agents/adr-author.md +70 -0
  8. package/agents/ai-provenance-review.md +120 -0
  9. package/agents/angular-reactivity-review.md +95 -0
  10. package/agents/arch-review.md +135 -0
  11. package/agents/architect.md +78 -0
  12. package/agents/autoship-batch-proposer.md +69 -0
  13. package/agents/claude-setup-review.md +136 -0
  14. package/agents/codebase-recon.md +184 -0
  15. package/agents/component-architecture-review.md +119 -0
  16. package/agents/concurrency-review.md +109 -0
  17. package/agents/correctness-review.md +290 -0
  18. package/agents/data-flow-tracer.md +120 -0
  19. package/agents/doc-review.md +165 -0
  20. package/agents/domain-review.md +136 -0
  21. package/agents/general-purpose.md +10 -0
  22. package/agents/gherkin-quality-critic.md +113 -0
  23. package/agents/js-fp-review.md +114 -0
  24. package/agents/mutation-kill.md +684 -0
  25. package/agents/naming-review.md +142 -0
  26. package/agents/orchestrator.md +339 -0
  27. package/agents/performance-review.md +105 -0
  28. package/agents/plan-review-acceptance.md +115 -0
  29. package/agents/plan-review-design.md +90 -0
  30. package/agents/plan-review-parallelization.md +84 -0
  31. package/agents/plan-review-strategic.md +96 -0
  32. package/agents/plan-review-ux.md +110 -0
  33. package/agents/platform-engineer.md +64 -0
  34. package/agents/product-manager.md +68 -0
  35. package/agents/progress-guardian.md +79 -0
  36. package/agents/qa-engineer.md +289 -0
  37. package/agents/quality-reviewer.md +132 -0
  38. package/agents/react-reactivity-review.md +102 -0
  39. package/agents/refactor-opportunity-review.md +128 -0
  40. package/agents/security-engineer.md +60 -0
  41. package/agents/security-review.md +218 -0
  42. package/agents/session-analysis.md +95 -0
  43. package/agents/software-engineer.md +105 -0
  44. package/agents/spec-compliance-review.md +100 -0
  45. package/agents/spec-reviewer.md +114 -0
  46. package/agents/structure-review.md +146 -0
  47. package/agents/tech-writer.md +84 -0
  48. package/agents/test-review.md +246 -0
  49. package/agents/test-smell-review.md +188 -0
  50. package/agents/token-efficiency-review.md +139 -0
  51. package/agents/ui-ux-designer.md +54 -0
  52. package/agents/vue-reactivity-review.md +95 -0
  53. package/bin/__pycache__/claudecpython-314.pyc +0 -0
  54. package/bin/claude +258 -0
  55. package/docs/upstream/.pages +1 -0
  56. package/docs/upstream/CHANGELOG.md +2586 -0
  57. package/docs/upstream/README.md +155 -0
  58. package/docs/upstream/agent-architecture.md +214 -0
  59. package/docs/upstream/agent_info.md +187 -0
  60. package/docs/upstream/artifact-migration.md +124 -0
  61. package/docs/upstream/code-intelligence-nudge.md +149 -0
  62. package/docs/upstream/code-review-process.md +294 -0
  63. package/docs/upstream/concurrent-use.md +73 -0
  64. package/docs/upstream/context-management.md +111 -0
  65. package/docs/upstream/developer-notes.md +280 -0
  66. package/docs/upstream/diagrams/architecture-overview.svg +101 -0
  67. package/docs/upstream/diagrams/review-dispatch.svg +139 -0
  68. package/docs/upstream/diagrams/team-agents.svg +128 -0
  69. package/docs/upstream/diagrams/test-improve-flow.svg +166 -0
  70. package/docs/upstream/diagrams/workflow-linear.svg +66 -0
  71. package/docs/upstream/diagrams/workflow-three-phase.svg +200 -0
  72. package/docs/upstream/eval-maintenance.md +95 -0
  73. package/docs/upstream/eval-running-guide.md +147 -0
  74. package/docs/upstream/eval-system.md +291 -0
  75. package/docs/upstream/session-review-oss-complements.md +75 -0
  76. package/docs/upstream/session-review.md +212 -0
  77. package/docs/upstream/skills.md +188 -0
  78. package/docs/upstream/team-structure.md +21 -0
  79. package/docs/upstream/telemetry-ci-access.md +129 -0
  80. package/docs/upstream/telemetry-repo-security.md +120 -0
  81. package/docs/upstream/test-evaluation.md +277 -0
  82. package/docs/upstream/test-improve.md +154 -0
  83. package/docs/upstream/triage-workflow.md +282 -0
  84. package/docs/upstream/workflows.md +289 -0
  85. package/extensions/dev-team/index.ts +539 -0
  86. package/extensions/dev-team/lib/agents.ts +272 -0
  87. package/extensions/dev-team/lib/ai-credits.ts +92 -0
  88. package/extensions/dev-team/lib/autocompact.ts +81 -0
  89. package/extensions/dev-team/lib/child-run.ts +102 -0
  90. package/extensions/dev-team/lib/config.ts +236 -0
  91. package/extensions/dev-team/lib/gh-command.ts +103 -0
  92. package/extensions/dev-team/lib/github-style.ts +307 -0
  93. package/extensions/dev-team/lib/hooks.ts +350 -0
  94. package/extensions/dev-team/lib/metrics.ts +115 -0
  95. package/extensions/dev-team/lib/safe-read.ts +49 -0
  96. package/extensions/dev-team/lib/session-files.ts +57 -0
  97. package/extensions/dev-team/lib/session-spend.ts +123 -0
  98. package/extensions/dev-team/lib/shell-scan.ts +205 -0
  99. package/extensions/dev-team/lib/skills.ts +213 -0
  100. package/extensions/dev-team/lib/subagent-render.ts +245 -0
  101. package/extensions/dev-team/lib/subagent-types.ts +164 -0
  102. package/extensions/dev-team/lib/subagent.ts +596 -0
  103. package/extensions/dev-team/lib/terminal-text.ts +54 -0
  104. package/extensions/dev-team/lib/tools-misc.ts +152 -0
  105. package/extensions/dev-team/lib/transcript.ts +110 -0
  106. package/extensions/dev-team/lib/trust.ts +52 -0
  107. package/extensions/dev-team/lib/usage-breakdown.ts +176 -0
  108. package/extensions/dev-team/lib/usage-chart.ts +153 -0
  109. package/extensions/dev-team/lib/usage-command.ts +107 -0
  110. package/extensions/dev-team/lib/usage-history.ts +203 -0
  111. package/extensions/dev-team/lib/usage-render.ts +225 -0
  112. package/extensions/dev-team/lib/usage-split-bar.ts +127 -0
  113. package/extensions/dev-team/lib/usage-state.ts +116 -0
  114. package/extensions/dev-team/lib/usage-text.ts +159 -0
  115. package/extensions/dev-team/lib/usage-view.ts +109 -0
  116. package/hooks/__pycache__/refactor_test_freeze_guard.cpython-314.pyc +0 -0
  117. package/hooks/agent_dispatch_ledger.py +190 -0
  118. package/hooks/autocompact_setup_nudge.py +99 -0
  119. package/hooks/bash_retry_guard.py +228 -0
  120. package/hooks/boundary_events_write_guard.py +352 -0
  121. package/hooks/code_intelligence_nudge.py +293 -0
  122. package/hooks/code_intelligence_turn_mark.py +317 -0
  123. package/hooks/codegraph_bootstrap.py +139 -0
  124. package/hooks/contract_version_guard.py +362 -0
  125. package/hooks/cost_meter.py +106 -0
  126. package/hooks/destructive-commands.json +62 -0
  127. package/hooks/destructive_guard.py +477 -0
  128. package/hooks/eval_compliance_check.py +440 -0
  129. package/hooks/guards.json +17 -0
  130. package/hooks/hooks.json +323 -0
  131. package/hooks/internal_double_gate.py +296 -0
  132. package/hooks/js_fp_review.py +212 -0
  133. package/hooks/knowledge_index.py +119 -0
  134. package/hooks/lib/__pycache__/artifact_paths.cpython-314.pyc +0 -0
  135. package/hooks/lib/__pycache__/atomic_state.cpython-314.pyc +0 -0
  136. package/hooks/lib/__pycache__/autocompact_config.cpython-314.pyc +0 -0
  137. package/hooks/lib/__pycache__/boundary_events.cpython-314.pyc +0 -0
  138. package/hooks/lib/__pycache__/doc_classification.cpython-314.pyc +0 -0
  139. package/hooks/lib/__pycache__/gh_pr_create_detect.cpython-314.pyc +0 -0
  140. package/hooks/lib/__pycache__/git_safe_diff.cpython-314.pyc +0 -0
  141. package/hooks/lib/__pycache__/instrument_log.cpython-314.pyc +0 -0
  142. package/hooks/lib/__pycache__/metrics_query.cpython-314.pyc +0 -0
  143. package/hooks/lib/__pycache__/plugin_version.cpython-314.pyc +0 -0
  144. package/hooks/lib/__pycache__/pre_commit_doc_classifier.cpython-314.pyc +0 -0
  145. package/hooks/lib/__pycache__/review_agent_registry.cpython-314.pyc +0 -0
  146. package/hooks/lib/__pycache__/review_gate_corroboration.cpython-314.pyc +0 -0
  147. package/hooks/lib/__pycache__/review_gate_hash.cpython-314.pyc +0 -0
  148. package/hooks/lib/__pycache__/review_verdicts.cpython-314.pyc +0 -0
  149. package/hooks/lib/__pycache__/stdin_json.cpython-314.pyc +0 -0
  150. package/hooks/lib/__pycache__/stryker_invocation.cpython-314.pyc +0 -0
  151. package/hooks/lib/__pycache__/telemetry_consent.cpython-314.pyc +0 -0
  152. package/hooks/lib/__pycache__/test_file_classify.cpython-314.pyc +0 -0
  153. package/hooks/lib/__pycache__/token_efficiency_limits.cpython-314.pyc +0 -0
  154. package/hooks/lib/__pycache__/verify_guard_state.cpython-314.pyc +0 -0
  155. package/hooks/lib/__pycache__/xunit_v3_operator_gate.cpython-314.pyc +0 -0
  156. package/hooks/lib/agent_skill_hints.py +74 -0
  157. package/hooks/lib/artifact_paths.py +263 -0
  158. package/hooks/lib/atomic_state.py +557 -0
  159. package/hooks/lib/autocompact_config.py +103 -0
  160. package/hooks/lib/autoship_log.py +106 -0
  161. package/hooks/lib/banned_scripts_policy.py +51 -0
  162. package/hooks/lib/boundary_events.py +436 -0
  163. package/hooks/lib/build_knowledge_index.py +504 -0
  164. package/hooks/lib/build_skills_index.py +361 -0
  165. package/hooks/lib/build_state.py +116 -0
  166. package/hooks/lib/classify_ship_outcome.py +126 -0
  167. package/hooks/lib/config_changelog_schema.py +115 -0
  168. package/hooks/lib/cost_meter.py +955 -0
  169. package/hooks/lib/doc_classification.py +116 -0
  170. package/hooks/lib/gh_pr_create_detect.py +136 -0
  171. package/hooks/lib/git_safe_diff.py +123 -0
  172. package/hooks/lib/instrument_log.py +66 -0
  173. package/hooks/lib/iteration_journal_gate.py +197 -0
  174. package/hooks/lib/knowledge_index_paths.py +88 -0
  175. package/hooks/lib/mcp_json_repowise.py +177 -0
  176. package/hooks/lib/metrics_query.py +202 -0
  177. package/hooks/lib/minimal_yaml.py +434 -0
  178. package/hooks/lib/plugin_version.py +142 -0
  179. package/hooks/lib/pre_commit_detect.py +537 -0
  180. package/hooks/lib/pre_commit_doc_classifier.py +126 -0
  181. package/hooks/lib/pricing.py +118 -0
  182. package/hooks/lib/report_pdf.py +371 -0
  183. package/hooks/lib/review_agent_registry.py +142 -0
  184. package/hooks/lib/review_dispatch_ledger.py +101 -0
  185. package/hooks/lib/review_gate_corroboration.py +521 -0
  186. package/hooks/lib/review_gate_hash.py +252 -0
  187. package/hooks/lib/review_gate_normalized_hash.py +1115 -0
  188. package/hooks/lib/review_verdicts.py +301 -0
  189. package/hooks/lib/run_report.py +160 -0
  190. package/hooks/lib/skill_categories.yaml +125 -0
  191. package/hooks/lib/stdin_json.py +57 -0
  192. package/hooks/lib/stryker_invocation.py +102 -0
  193. package/hooks/lib/telemetry_consent.py +41 -0
  194. package/hooks/lib/telemetry_report.py +108 -0
  195. package/hooks/lib/test_file_classify.py +160 -0
  196. package/hooks/lib/token_efficiency_limits.py +51 -0
  197. package/hooks/lib/turn_identity.py +77 -0
  198. package/hooks/lib/verify_guard_state.py +110 -0
  199. package/hooks/lib/workflow_state.py +206 -0
  200. package/hooks/lib/xunit_v3_operator_gate.py +596 -0
  201. package/hooks/mcp_json_repowise_nudge.py +74 -0
  202. package/hooks/mutation_adapters/__init__.py +7 -0
  203. package/hooks/mutation_adapters/__pycache__/__init__.cpython-314.pyc +0 -0
  204. package/hooks/mutation_adapters/__pycache__/lib.cpython-314.pyc +0 -0
  205. package/hooks/mutation_adapters/__pycache__/mutmut.cpython-314.pyc +0 -0
  206. package/hooks/mutation_adapters/__pycache__/pitest.cpython-314.pyc +0 -0
  207. package/hooks/mutation_adapters/__pycache__/stryker.cpython-314.pyc +0 -0
  208. package/hooks/mutation_adapters/__pycache__/stryker_net.cpython-314.pyc +0 -0
  209. package/hooks/mutation_adapters/lib.py +478 -0
  210. package/hooks/mutation_adapters/mutmut.py +188 -0
  211. package/hooks/mutation_adapters/pitest.py +266 -0
  212. package/hooks/mutation_adapters/stryker.py +157 -0
  213. package/hooks/mutation_adapters/stryker_net.py +264 -0
  214. package/hooks/mutation_gate.py +193 -0
  215. package/hooks/mutation_testing_smoke_gate.py +371 -0
  216. package/hooks/pending_review_notify.py +121 -0
  217. package/hooks/phase_marker.py +138 -0
  218. package/hooks/post_compact_state_reinject.py +180 -0
  219. package/hooks/post_format.py +115 -0
  220. package/hooks/pre_commit_knowledge_index.py +128 -0
  221. package/hooks/pre_commit_review.py +66 -0
  222. package/hooks/pre_pr_review.py +694 -0
  223. package/hooks/pre_tool_guard.py +405 -0
  224. package/hooks/py.sh +73 -0
  225. package/hooks/refactor-bash-write-patterns.json +29 -0
  226. package/hooks/refactor_test_bash_guard.py +253 -0
  227. package/hooks/refactor_test_freeze_guard.py +139 -0
  228. package/hooks/refactor_test_revert_guard.py +186 -0
  229. package/hooks/repo_review_nudge.py +287 -0
  230. package/hooks/review_verdict_recorder.py +464 -0
  231. package/hooks/scan_bash_command_for_banned_scripts.py +428 -0
  232. package/hooks/scan_worktree_for_banned_scripts.py +238 -0
  233. package/hooks/session_learning_trigger.py +248 -0
  234. package/hooks/skills_index.py +126 -0
  235. package/hooks/stryker_xunit_shim_guard.py +571 -0
  236. package/hooks/subagent_completion_guard.py +309 -0
  237. package/hooks/subagent_skill_context.py +139 -0
  238. package/hooks/task_completion_metrics.py +216 -0
  239. package/hooks/tdd_guard.py +229 -0
  240. package/hooks/telemetry.py +341 -0
  241. package/hooks/token_efficiency_review.py +194 -0
  242. package/hooks/verify_guard.py +183 -0
  243. package/hooks/verify_guard_edit_marker.py +73 -0
  244. package/hooks/version_check.py +173 -0
  245. package/knowledge/accepted-risks-schema.md +98 -0
  246. package/knowledge/adr-decision-criteria.md +64 -0
  247. package/knowledge/adversarial-review-protocol.md +139 -0
  248. package/knowledge/agent-registry.md +228 -0
  249. package/knowledge/agent-review-methodology.md +80 -0
  250. package/knowledge/ai-friendly-repo-guidelines.md +67 -0
  251. package/knowledge/architecture-assessment.md +96 -0
  252. package/knowledge/artifact-lifecycle.md +57 -0
  253. package/knowledge/cd-maturity-model.md +82 -0
  254. package/knowledge/cd-test-architecture.md +190 -0
  255. package/knowledge/ci-cd-file-scope.md +24 -0
  256. package/knowledge/codegraph-vs-graphify.md +192 -0
  257. package/knowledge/component-test-patterns.md +139 -0
  258. package/knowledge/database-change-management.md +80 -0
  259. package/knowledge/database-test-patterns.md +79 -0
  260. package/knowledge/decision-defaults.md +88 -0
  261. package/knowledge/dependency-breaking-techniques.md +116 -0
  262. package/knowledge/deployment-pipeline.md +86 -0
  263. package/knowledge/design-smells.md +122 -0
  264. package/knowledge/directory-enumeration.md +38 -0
  265. package/knowledge/domain-modeling.md +123 -0
  266. package/knowledge/evidence-bundle.md +90 -0
  267. package/knowledge/exploratory-testing-field-guide.md +122 -0
  268. package/knowledge/failure-routing.md +28 -0
  269. package/knowledge/fixture-construction.md +56 -0
  270. package/knowledge/frontend-component-architecture.md +139 -0
  271. package/knowledge/gherkin-quality-review-dispatch.md +135 -0
  272. package/knowledge/index.json +6766 -0
  273. package/knowledge/internal-collaborator-doubling.md +101 -0
  274. package/knowledge/legacy-test-strategy.md +71 -0
  275. package/knowledge/long-run-waiting.md +66 -0
  276. package/knowledge/microservice-testing.md +71 -0
  277. package/knowledge/model-pricing.json +23 -0
  278. package/knowledge/mutation-score-formulas.md +60 -0
  279. package/knowledge/object-calisthenics.md +147 -0
  280. package/knowledge/oracle-provenance.md +94 -0
  281. package/knowledge/orchestrator-script-implementation.md +185 -0
  282. package/knowledge/owasp-detection.md +148 -0
  283. package/knowledge/plan-review-rubric.md +56 -0
  284. package/knowledge/proxy-connectivity.md +62 -0
  285. package/knowledge/reactive-effect-patterns.md +73 -0
  286. package/knowledge/recon-inventory-excludes.txt +32 -0
  287. package/knowledge/references/bdd-value-guide.md +61 -0
  288. package/knowledge/references/csharp-http-client-testing.md +264 -0
  289. package/knowledge/release-strategies.md +74 -0
  290. package/knowledge/report-output-location.md +117 -0
  291. package/knowledge/report-pdf-integration.md +63 -0
  292. package/knowledge/report-print.css +129 -0
  293. package/knowledge/report-template.md +114 -0
  294. package/knowledge/report-to-pdf.md +69 -0
  295. package/knowledge/request-processing-flow.md +63 -0
  296. package/knowledge/result-verification.md +52 -0
  297. package/knowledge/review-agent-output-contract.md +121 -0
  298. package/knowledge/review-lens-classification.md +113 -0
  299. package/knowledge/review-rubric.md +62 -0
  300. package/knowledge/review-template.md +104 -0
  301. package/knowledge/rule-fixtures/A02.insecure-random-js/negative.js +1 -0
  302. package/knowledge/rule-fixtures/A02.insecure-random-js/positive.js +1 -0
  303. package/knowledge/rule-fixtures/A02.weak-hashing-md5/negative.py +1 -0
  304. package/knowledge/rule-fixtures/A02.weak-hashing-md5/positive.py +1 -0
  305. package/knowledge/rule-fixtures/A03.command-injection/negative.js +1 -0
  306. package/knowledge/rule-fixtures/A03.command-injection/positive.js +1 -0
  307. package/knowledge/rule-fixtures/A03.sql-injection/negative.js +1 -0
  308. package/knowledge/rule-fixtures/A03.sql-injection/positive.js +1 -0
  309. package/knowledge/rule-fixtures/A03.xss-innerhtml/negative.js +1 -0
  310. package/knowledge/rule-fixtures/A03.xss-innerhtml/positive.js +1 -0
  311. package/knowledge/rule-fixtures/A05.cors-wildcard/negative.js +1 -0
  312. package/knowledge/rule-fixtures/A05.cors-wildcard/positive.js +1 -0
  313. package/knowledge/rule-fixtures/A05.default-credentials/negative.js +1 -0
  314. package/knowledge/rule-fixtures/A05.default-credentials/positive.js +1 -0
  315. package/knowledge/rule-fixtures/A07.jwt-alg-none/negative.js +1 -0
  316. package/knowledge/rule-fixtures/A07.jwt-alg-none/positive.js +1 -0
  317. package/knowledge/rule-fixtures/A08.binary-formatter/negative.cs +1 -0
  318. package/knowledge/rule-fixtures/A08.binary-formatter/positive.cs +1 -0
  319. package/knowledge/rule-fixtures/A08.js-eval/negative.js +1 -0
  320. package/knowledge/rule-fixtures/A08.js-eval/positive.js +1 -0
  321. package/knowledge/rule-fixtures/A08.object-input-stream/negative.java +1 -0
  322. package/knowledge/rule-fixtures/A08.object-input-stream/positive.java +1 -0
  323. package/knowledge/schemas/disposition-register-v1.json +65 -0
  324. package/knowledge/schemas/recon-envelope-v1.json +198 -0
  325. package/knowledge/schemas/unified-finding-v1.json +72 -0
  326. package/knowledge/security-primitives-contract.md +301 -0
  327. package/knowledge/security-review-rule-map.yaml +107 -0
  328. package/knowledge/skills-registry.md +72 -0
  329. package/knowledge/task-size-classifier.md +103 -0
  330. package/knowledge/telemetry-schema.md +881 -0
  331. package/knowledge/test-automation-maturity.md +56 -0
  332. package/knowledge/test-automation-principles.md +71 -0
  333. package/knowledge/test-cadence-tradeoffs.md +68 -0
  334. package/knowledge/test-doubles.md +105 -0
  335. package/knowledge/test-file-indicators.md +22 -0
  336. package/knowledge/test-layer-gates.md +35 -0
  337. package/knowledge/test-matrix-examples/django-batch.md +24 -0
  338. package/knowledge/test-matrix-examples/dotnet-grpc-fronting-api.md +90 -0
  339. package/knowledge/test-matrix-examples/dotnet-http-consumer.md +131 -0
  340. package/knowledge/test-matrix-examples/react-node-spa.md +24 -0
  341. package/knowledge/test-matrix-examples/spring-boot-service.md +25 -0
  342. package/knowledge/test-matrix-examples/ssr-htmx.md +24 -0
  343. package/knowledge/test-organization.md +70 -0
  344. package/knowledge/test-pyramid.md +84 -0
  345. package/knowledge/test-refactoring.md +67 -0
  346. package/knowledge/test-review-division-of-labor.md +85 -0
  347. package/knowledge/test-smells.md +80 -0
  348. package/knowledge/test-stack-profiles/bdd-frameworks.md +235 -0
  349. package/knowledge/test-stack-profiles/django.md +13 -0
  350. package/knowledge/test-stack-profiles/dotnet.md +18 -0
  351. package/knowledge/test-stack-profiles/go.md +16 -0
  352. package/knowledge/test-stack-profiles/node.md +16 -0
  353. package/knowledge/test-stack-profiles/react.md +12 -0
  354. package/knowledge/test-stack-profiles/spring-boot.md +16 -0
  355. package/knowledge/test-stack-profiles/ssr-htmx.md +14 -0
  356. package/knowledge/test-stack-profiles/vue.md +12 -0
  357. package/knowledge/test-strategy.md +70 -0
  358. package/knowledge/testability-patterns.md +240 -0
  359. package/knowledge/testing-quadrants.md +44 -0
  360. package/knowledge/testing-techniques/approval.md +15 -0
  361. package/knowledge/testing-techniques/chaos.md +17 -0
  362. package/knowledge/testing-techniques/fuzz.md +15 -0
  363. package/knowledge/testing-techniques/property-based.md +15 -0
  364. package/knowledge/testing-techniques/schema-validation.md +15 -0
  365. package/knowledge/testing-techniques/screenshot.md +15 -0
  366. package/knowledge/three-phase-workflow.md +198 -0
  367. package/knowledge/value-patterns.md +55 -0
  368. package/knowledge/verification-mode.md +116 -0
  369. package/knowledge/virtual-service-libraries.md +75 -0
  370. package/knowledge/wave-consolidation-guidance.md +21 -0
  371. package/overrides/agents/Explore.md +15 -0
  372. package/overrides/agents/general-purpose.md +10 -0
  373. package/overrides/notes/autoship.md +6 -0
  374. package/overrides/notes/issues-from-assessment.md +3 -0
  375. package/overrides/notes/issues-from-plan.md +3 -0
  376. package/overrides/notes/mutation-night-watch.md +3 -0
  377. package/overrides/notes/mutation-testing.md +3 -0
  378. package/overrides/notes/pr.md +7 -0
  379. package/overrides/notes/project-init.md +6 -0
  380. package/overrides/notes/setup.md +13 -0
  381. package/overrides/notes/specs.md +3 -0
  382. package/overrides/skills/headless-run/SKILL.md +45 -0
  383. package/overrides/skills/upgrade/SKILL.md +30 -0
  384. package/overrides/skills/version/SKILL.md +25 -0
  385. package/package.json +36 -0
  386. package/scripts/authoring_digest.py +93 -0
  387. package/scripts/autoship_discover.py +121 -0
  388. package/scripts/autoship_group.py +409 -0
  389. package/scripts/autoship_proposals.py +494 -0
  390. package/scripts/autoship_queue.py +291 -0
  391. package/scripts/autoship_reclaim.py +495 -0
  392. package/scripts/build_jobs.py +108 -0
  393. package/scripts/build_rollback_point.py +240 -0
  394. package/scripts/build_slice_scope.py +157 -0
  395. package/scripts/build_wave.py +109 -0
  396. package/scripts/build_wave_reconcile.py +252 -0
  397. package/scripts/build_worktree_baseref.py +113 -0
  398. package/scripts/check_agent_scope.py +117 -0
  399. package/scripts/check_agent_tool_mapping.py +213 -0
  400. package/scripts/check_review_agent_mcp_tools.py +317 -0
  401. package/scripts/check_security_assessment_mcp_tools.py +165 -0
  402. package/scripts/checkpoint_abort.py +502 -0
  403. package/scripts/claude_setup_review.py +438 -0
  404. package/scripts/codebase_recon.py +556 -0
  405. package/scripts/coverage_config.py +623 -0
  406. package/scripts/coverage_delta_steering.py +330 -0
  407. package/scripts/coverage_discovery_dotnet.py +315 -0
  408. package/scripts/coverage_discovery_java.py +742 -0
  409. package/scripts/coverage_discovery_js.py +546 -0
  410. package/scripts/coverage_gap_ranking.py +556 -0
  411. package/scripts/coverage_readiness.py +455 -0
  412. package/scripts/coverage_report_parse.py +521 -0
  413. package/scripts/detect_bdd_convention.py +252 -0
  414. package/scripts/eval_ablation.py +376 -0
  415. package/scripts/gherkin_analysis_coverage_gate.py +306 -0
  416. package/scripts/gherkin_cross_feature_duplicate_titles_gate.py +173 -0
  417. package/scripts/gherkin_effectiveness_rollup.py +238 -0
  418. package/scripts/gherkin_failure_path_gate.py +206 -0
  419. package/scripts/gherkin_feature_merge.py +720 -0
  420. package/scripts/gherkin_stub_gate.py +163 -0
  421. package/scripts/gherkin_stub_merge.py +479 -0
  422. package/scripts/git_origin_host.py +88 -0
  423. package/scripts/install-java-static-analysis.py +110 -0
  424. package/scripts/issue_deps.py +74 -0
  425. package/scripts/lib/_bdd_markers.py +28 -0
  426. package/scripts/lib/_gherkin_text.py +93 -0
  427. package/scripts/lib/_vendored_tree.py +70 -0
  428. package/scripts/lib/autoship_state.py +397 -0
  429. package/scripts/lib/claude_md_guard.py +226 -0
  430. package/scripts/lib/deterministic_recon.py +446 -0
  431. package/scripts/lib/mcp_tool_grants.py +211 -0
  432. package/scripts/lib/plan_parse.py +386 -0
  433. package/scripts/lib/review_result.py +84 -0
  434. package/scripts/lib/review_roster.py +86 -0
  435. package/scripts/lib/session_log/__init__.py +34 -0
  436. package/scripts/lib/session_log/__pycache__/__init__.cpython-314.pyc +0 -0
  437. package/scripts/lib/session_log/__pycache__/records.cpython-314.pyc +0 -0
  438. package/scripts/lib/session_log/classify.py +231 -0
  439. package/scripts/lib/session_log/corrections.py +194 -0
  440. package/scripts/lib/session_log/discovery.py +108 -0
  441. package/scripts/lib/session_log/records.py +218 -0
  442. package/scripts/lib/session_log/redact.py +76 -0
  443. package/scripts/lib/session_log/signals.py +373 -0
  444. package/scripts/lib/session_report_downstream.py +614 -0
  445. package/scripts/lib/session_report_maintainer.py +1273 -0
  446. package/scripts/lib/session_report_shared.py +262 -0
  447. package/scripts/lib/settings_hook_guard.py +157 -0
  448. package/scripts/lib/slug.py +33 -0
  449. package/scripts/lib/stub_extractors/__init__.py +82 -0
  450. package/scripts/lib/stub_extractors/_common.py +328 -0
  451. package/scripts/lib/stub_extractors/csharp.py +19 -0
  452. package/scripts/lib/stub_extractors/go.py +173 -0
  453. package/scripts/lib/stub_extractors/java.py +18 -0
  454. package/scripts/lib/stub_extractors/jsts.py +126 -0
  455. package/scripts/mutation_stack_sections.py +149 -0
  456. package/scripts/mutation_yield_steering.py +345 -0
  457. package/scripts/orchestrator.py +895 -0
  458. package/scripts/plan_gherkin_export.py +227 -0
  459. package/scripts/plan_waves.py +208 -0
  460. package/scripts/pr_close_keyword_lint.py +108 -0
  461. package/scripts/progress_guardian.py +888 -0
  462. package/scripts/recon_inventory.py +273 -0
  463. package/scripts/review_findings_log.py +93 -0
  464. package/scripts/run_invariants.py +124 -0
  465. package/scripts/select_lenses.py +640 -0
  466. package/scripts/session_report.py +486 -0
  467. package/scripts/set_autocompact_env.py +221 -0
  468. package/scripts/ship_resume_guard.py +135 -0
  469. package/scripts/ship_review_gate.py +63 -0
  470. package/scripts/specs_convention_marker.py +103 -0
  471. package/scripts/test_improve_resume.py +277 -0
  472. package/scripts/test_review_mechanics.py +958 -0
  473. package/scripts/token_efficiency_review.py +322 -0
  474. package/scripts/verdict_scope.py +285 -0
  475. package/scripts/verify_gherkin_quality_critic_isolation.py +296 -0
  476. package/scripts/verify_tier.py +157 -0
  477. package/skills/adr-tools/SKILL.md +118 -0
  478. package/skills/agent-readiness/SKILL.md +105 -0
  479. package/skills/agent-readiness/ai_friendly_analyzers.py +326 -0
  480. package/skills/agent-readiness/scanner.py +441 -0
  481. package/skills/agent-readiness/scorecard.yaml +88 -0
  482. package/skills/api-design/SKILL.md +115 -0
  483. package/skills/apply-fixes/SKILL.md +171 -0
  484. package/skills/apply-test-doubles/SKILL.md +321 -0
  485. package/skills/artifact-lifecycle/SKILL.md +127 -0
  486. package/skills/autoship/SKILL.md +1124 -0
  487. package/skills/benchmark/SKILL.md +105 -0
  488. package/skills/branch-workflow/SKILL.md +89 -0
  489. package/skills/browse/SKILL.md +184 -0
  490. package/skills/browser-testing/SKILL.md +62 -0
  491. package/skills/browser-testing/references/playwright-patterns.md +216 -0
  492. package/skills/build/SKILL.md +422 -0
  493. package/skills/build/references/static-self-heal.md +245 -0
  494. package/skills/careful/SKILL.md +72 -0
  495. package/skills/cd-test-architecture/SKILL.md +371 -0
  496. package/skills/ci-debugging/SKILL.md +105 -0
  497. package/skills/co-evolution-audit/SKILL.md +269 -0
  498. package/skills/code-review/SKILL.md +1015 -0
  499. package/skills/code-review/examples/aggregated-sample.json +56 -0
  500. package/skills/code-review/examples/sample-report.md +41 -0
  501. package/skills/code-review/output-format.md +478 -0
  502. package/skills/code-review/scripts/activation.py +86 -0
  503. package/skills/code-review/scripts/change_impact.py +357 -0
  504. package/skills/code-review/scripts/change_shape.py +372 -0
  505. package/skills/code-review/scripts/change_size.py +212 -0
  506. package/skills/code-review/scripts/changed_file_list.py +141 -0
  507. package/skills/code-review/scripts/closing_pass.py +187 -0
  508. package/skills/code-review/scripts/consolidate.py +277 -0
  509. package/skills/code-review/scripts/contract_failure_report.py +185 -0
  510. package/skills/code-review/scripts/dispatch_reconcile.py +66 -0
  511. package/skills/code-review/scripts/dispatch_waves.py +164 -0
  512. package/skills/code-review/scripts/finding_signature.py +446 -0
  513. package/skills/code-review/scripts/ledger.py +283 -0
  514. package/skills/code-review/scripts/partition.py +169 -0
  515. package/skills/code-review/scripts/render_tiered_findings.py +274 -0
  516. package/skills/code-review/scripts/repo_invariants.py +1066 -0
  517. package/skills/code-review/scripts/review_context_pack.py +306 -0
  518. package/skills/code-review/scripts/review_round_log.py +345 -0
  519. package/skills/code-review/scripts/review_value_coverage.py +297 -0
  520. package/skills/code-review/scripts/validate_review_output.py +467 -0
  521. package/skills/code-review/sliced-mode.md +205 -0
  522. package/skills/competitive-analysis/SKILL.md +191 -0
  523. package/skills/context-loading-protocol/SKILL.md +157 -0
  524. package/skills/continue/SKILL.md +90 -0
  525. package/skills/cost-report/SKILL.md +178 -0
  526. package/skills/coverage-baseline/SKILL.md +335 -0
  527. package/skills/coverage-baseline/references/multi-project-discovery.md +202 -0
  528. package/skills/coverage-delta/SKILL.md +181 -0
  529. package/skills/coverage-delta/references/mutation-gate.md +70 -0
  530. package/skills/design-doc/SKILL.md +95 -0
  531. package/skills/design-interrogation/SKILL.md +89 -0
  532. package/skills/design-it-twice/SKILL.md +91 -0
  533. package/skills/docker-image-audit/SKILL.md +108 -0
  534. package/skills/docker-image-audit/references/install-guide.md +64 -0
  535. package/skills/docker-image-audit/references/report-template.md +73 -0
  536. package/skills/docker-image-create/SKILL.md +185 -0
  537. package/skills/domain-analysis/SKILL.md +183 -0
  538. package/skills/domain-driven-design/SKILL.md +194 -0
  539. package/skills/exploratory-testing/SKILL.md +108 -0
  540. package/skills/explore/SKILL.md +51 -0
  541. package/skills/farley-score/SKILL.md +165 -0
  542. package/skills/feature-file-validation/SKILL.md +78 -0
  543. package/skills/feature-file-validation/references/validation-rules.md +115 -0
  544. package/skills/feedback-learning/SKILL.md +414 -0
  545. package/skills/fix/SKILL.md +450 -0
  546. package/skills/freeze/SKILL.md +68 -0
  547. package/skills/frontend-architecture/SKILL.md +113 -0
  548. package/skills/gherkin-derive/SKILL.md +630 -0
  549. package/skills/gherkin-public/SKILL.md +266 -0
  550. package/skills/governance-compliance/SKILL.md +150 -0
  551. package/skills/guard/SKILL.md +75 -0
  552. package/skills/handoff/SKILL.md +139 -0
  553. package/skills/handoff/references/summary-templates.md +242 -0
  554. package/skills/harness-audit/SKILL.md +751 -0
  555. package/skills/harness-audit/scripts/lesson_validate.py +386 -0
  556. package/skills/harness-audit/scripts/redundancy_criterion.py +188 -0
  557. package/skills/headless-run/SKILL.md +45 -0
  558. package/skills/headless-run/scripts/isolated_dispatch.py +381 -0
  559. package/skills/help/SKILL.md +72 -0
  560. package/skills/hexagonal-architecture/SKILL.md +85 -0
  561. package/skills/human-oversight-protocol/SKILL.md +224 -0
  562. package/skills/issues-from-assessment/SKILL.md +223 -0
  563. package/skills/issues-from-plan/SKILL.md +133 -0
  564. package/skills/legacy-code/SKILL.md +132 -0
  565. package/skills/mermaid-diagramming/SKILL.md +120 -0
  566. package/skills/mutation-night-watch/SKILL.md +154 -0
  567. package/skills/mutation-night-watch/references/scheduling.md +135 -0
  568. package/skills/mutation-testing/SKILL.md +396 -0
  569. package/skills/mutation-testing/references/languages/csharp-stryker-net.md +676 -0
  570. package/skills/mutation-testing/references/languages/go-go-mutesting.md +95 -0
  571. package/skills/mutation-testing/references/languages/java-pitest.md +77 -0
  572. package/skills/mutation-testing/references/languages/javascript-stryker.md +188 -0
  573. package/skills/mutation-testing/references/languages/python-mutmut.md +97 -0
  574. package/skills/mutation-testing/references/time-estimation.md +34 -0
  575. package/skills/mutation-testing/references/tool-detection.md +15 -0
  576. package/skills/mutation-testing/references/workflow-callers.md +23 -0
  577. package/skills/mutation-testing/scripts/__pycache__/xunit_v3_feature_detector.cpython-314.pyc +0 -0
  578. package/skills/mutation-testing/scripts/csharp_stryker_net_slice_runner.py +635 -0
  579. package/skills/mutation-testing/scripts/csharp_stryker_net_status_loop.py +525 -0
  580. package/skills/mutation-testing/scripts/csharp_stryker_net_wrapper.py +681 -0
  581. package/skills/mutation-testing/scripts/mutation_baseline_reuse.py +292 -0
  582. package/skills/mutation-testing/scripts/mutation_exclude_policy.py +268 -0
  583. package/skills/mutation-testing/scripts/mutation_feasibility_gate.py +463 -0
  584. package/skills/mutation-testing/scripts/mutation_kill_headless.py +331 -0
  585. package/skills/mutation-testing/scripts/mutation_kill_insert.py +199 -0
  586. package/skills/mutation-testing/scripts/mutation_kill_insert_python.py +150 -0
  587. package/skills/mutation-testing/scripts/mutation_kill_loop.py +869 -0
  588. package/skills/mutation-testing/scripts/mutation_kill_loop_python.py +949 -0
  589. package/skills/mutation-testing/scripts/mutation_kill_retry.py +592 -0
  590. package/skills/mutation-testing/scripts/mutation_kill_shared.py +620 -0
  591. package/skills/mutation-testing/scripts/mutation_nightwatch.py +462 -0
  592. package/skills/mutation-testing/scripts/mutation_nightwatch_stacks.py +425 -0
  593. package/skills/mutation-testing/scripts/mutation_report.py +743 -0
  594. package/skills/mutation-testing/scripts/mutation_report_cli.py +175 -0
  595. package/skills/mutation-testing/scripts/mutation_safety_gate.py +69 -0
  596. package/skills/mutation-testing/scripts/stryker_shard_pipeline.py +847 -0
  597. package/skills/mutation-testing/scripts/stryker_shard_setup.py +440 -0
  598. package/skills/mutation-testing/scripts/stryker_timeout_retry.py +142 -0
  599. package/skills/mutation-testing/scripts/xunit_v3_feature_detector.py +341 -0
  600. package/skills/performance-benchmark/SKILL.md +174 -0
  601. package/skills/performance-benchmark/examples/report-format.md +43 -0
  602. package/skills/performance-benchmark/references/benchmark-script.md +169 -0
  603. package/skills/performance-metrics/SKILL.md +265 -0
  604. package/skills/plan/SKILL.md +199 -0
  605. package/skills/plan/references/gherkin-persistence.md +43 -0
  606. package/skills/plan/references/plan-template.md +182 -0
  607. package/skills/pr/SKILL.md +289 -0
  608. package/skills/pr/scripts/gate_retry_state.py +368 -0
  609. package/skills/project-init/README.md +141 -0
  610. package/skills/project-init/SKILL.md +1197 -0
  611. package/skills/project-init/evals/evals.json +200 -0
  612. package/skills/project-init/references/capability-tools.md +55 -0
  613. package/skills/project-init/references/configs.md +221 -0
  614. package/skills/property-based-testing/SKILL.md +121 -0
  615. package/skills/property-based-testing/fixtures/invariant_fixture.py +15 -0
  616. package/skills/property-based-testing/fixtures/js-roundtrip/README.md +42 -0
  617. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/LICENSE +21 -0
  618. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/README.md +263 -0
  619. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/cjs/fast-check.d.ts +5165 -0
  620. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/cjs/fast-check.js +12147 -0
  621. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/cjs/package.json +3 -0
  622. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/cjs/types57/fast-check.d.ts +5165 -0
  623. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/fast-check.d.ts +5165 -0
  624. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/fast-check.js +12011 -0
  625. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/rolldown-runtime-D7D4PA-g.js +13 -0
  626. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/types57/fast-check.d.ts +5165 -0
  627. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/package.json +94 -0
  628. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/LICENSE +21 -0
  629. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/README.md +168 -0
  630. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/RandomGenerator-DcXj09Ch.d.ts +14 -0
  631. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformBigInt.d.ts +15 -0
  632. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformBigInt.js +38 -0
  633. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformFloat32.d.ts +15 -0
  634. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformFloat32.js +18 -0
  635. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformFloat64.d.ts +15 -0
  636. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformFloat64.js +22 -0
  637. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformInt.d.ts +15 -0
  638. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformInt.js +134 -0
  639. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/RandomGenerator-DcXj09Ch.d.ts +14 -0
  640. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformBigInt.d.ts +15 -0
  641. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformBigInt.js +37 -0
  642. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformFloat32.d.ts +15 -0
  643. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformFloat32.js +17 -0
  644. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformFloat64.d.ts +15 -0
  645. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformFloat64.js +21 -0
  646. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformInt.d.ts +15 -0
  647. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformInt.js +133 -0
  648. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/congruential32.d.ts +7 -0
  649. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/congruential32.js +44 -0
  650. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/mersenne.d.ts +7 -0
  651. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/mersenne.js +90 -0
  652. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/xoroshiro128plus.d.ts +7 -0
  653. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/xoroshiro128plus.js +80 -0
  654. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/xorshift128plus.d.ts +7 -0
  655. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/xorshift128plus.js +78 -0
  656. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/package.json +3 -0
  657. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/types/JumpableRandomGenerator.d.ts +16 -0
  658. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/types/JumpableRandomGenerator.js +0 -0
  659. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/types/RandomGenerator.d.ts +2 -0
  660. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/types/RandomGenerator.js +0 -0
  661. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/generateN.d.ts +6 -0
  662. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/generateN.js +8 -0
  663. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/purify.d.ts +12 -0
  664. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/purify.js +9 -0
  665. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/skipN.d.ts +6 -0
  666. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/skipN.js +6 -0
  667. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/congruential32.d.ts +7 -0
  668. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/congruential32.js +46 -0
  669. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/mersenne.d.ts +7 -0
  670. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/mersenne.js +92 -0
  671. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/xoroshiro128plus.d.ts +7 -0
  672. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/xoroshiro128plus.js +82 -0
  673. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/xorshift128plus.d.ts +7 -0
  674. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/xorshift128plus.js +80 -0
  675. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/types/JumpableRandomGenerator.d.ts +16 -0
  676. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/types/JumpableRandomGenerator.js +0 -0
  677. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/types/RandomGenerator.d.ts +2 -0
  678. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/types/RandomGenerator.js +0 -0
  679. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/generateN.d.ts +6 -0
  680. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/generateN.js +9 -0
  681. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/purify.d.ts +12 -0
  682. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/purify.js +10 -0
  683. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/skipN.d.ts +6 -0
  684. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/skipN.js +7 -0
  685. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/package.json +133 -0
  686. package/skills/property-based-testing/fixtures/js-roundtrip/package-lock.json +1179 -0
  687. package/skills/property-based-testing/fixtures/js-roundtrip/package.json +14 -0
  688. package/skills/property-based-testing/fixtures/js-roundtrip/roundtrip.js +29 -0
  689. package/skills/property-based-testing/fixtures/js-roundtrip/roundtrip.properties.test.js +16 -0
  690. package/skills/property-based-testing/fixtures/no_property_fixture.py +10 -0
  691. package/skills/property-based-testing/fixtures/roundtrip_fixture.py +16 -0
  692. package/skills/property-based-testing/references/languages/javascript.md +54 -0
  693. package/skills/property-based-testing/scripts/detect_and_dispatch.py +80 -0
  694. package/skills/property-based-testing/scripts/hypothesis_scaffold.py +276 -0
  695. package/skills/proxy-resilience/SKILL.md +84 -0
  696. package/skills/quality-gate-pipeline/SKILL.md +184 -0
  697. package/skills/quality-targets-converge/SKILL.md +254 -0
  698. package/skills/repo-review/SKILL.md +159 -0
  699. package/skills/report-pdf/SKILL.md +66 -0
  700. package/skills/review/SKILL.md +47 -0
  701. package/skills/review-agent/SKILL.md +152 -0
  702. package/skills/review-summary/SKILL.md +73 -0
  703. package/skills/run-report/SKILL.md +70 -0
  704. package/skills/semantic-duplication-scan/SKILL.md +337 -0
  705. package/skills/semantic-scan/SKILL.md +53 -0
  706. package/skills/semgrep-analyze/SKILL.md +139 -0
  707. package/skills/setup/SKILL.md +1122 -0
  708. package/skills/ship/SKILL.md +240 -0
  709. package/skills/source-verification/SKILL.md +210 -0
  710. package/skills/source-verification/scripts/claim_extractor.py +155 -0
  711. package/skills/specs/.size-baseline.json +4 -0
  712. package/skills/specs/SKILL.md +243 -0
  713. package/skills/specs/references/completeness-checklist.md +83 -0
  714. package/skills/specs/references/extraction.md +58 -0
  715. package/skills/specs/references/glossary.md +59 -0
  716. package/skills/specs/references/persistence.md +115 -0
  717. package/skills/specs/references/predictability-check.md +77 -0
  718. package/skills/static-analysis-integration/SKILL.md +235 -0
  719. package/skills/static-analysis-integration/adapters/_envelope.py +26 -0
  720. package/skills/static-analysis-integration/adapters/jscpd-adapter.py +66 -0
  721. package/skills/static-analysis-integration/adapters/lizard-adapter.py +81 -0
  722. package/skills/static-analysis-integration/adapters/mypy-adapter.py +50 -0
  723. package/skills/static-analysis-integration/adapters/mypy-src-layout.py +93 -0
  724. package/skills/static-analysis-integration/adapters/security-review-adapter.py +212 -0
  725. package/skills/static-analysis-integration/maintenance.md +23 -0
  726. package/skills/static-analysis-integration/references/language-setup.md +228 -0
  727. package/skills/static-analysis-integration/references/sarif-parser.md +124 -0
  728. package/skills/static-analysis-integration/references/security-review-adapter.md +118 -0
  729. package/skills/static-analysis-integration/references/tool-configs.md +617 -0
  730. package/skills/static-analysis-integration/rulesets/pmd-quickstart.xml +24 -0
  731. package/skills/stryker-xunit-v2-shim/SKILL.md +274 -0
  732. package/skills/stryker-xunit-v2-shim/references/shim-howto.md +256 -0
  733. package/skills/stryker-xunit-v2-shim/scripts/generate_shim.py +143 -0
  734. package/skills/systematic-debugging/SKILL.md +130 -0
  735. package/skills/telemetry/SKILL.md +75 -0
  736. package/skills/test-audit-disable/SKILL.md +129 -0
  737. package/skills/test-design/SKILL.md +177 -0
  738. package/skills/test-design/scripts/__pycache__/internal_double_detector.cpython-314.pyc +0 -0
  739. package/skills/test-design/scripts/internal_double_detector.py +631 -0
  740. package/skills/test-design-advisor/SKILL.md +166 -0
  741. package/skills/test-driven-development/SKILL.md +169 -0
  742. package/skills/test-health/SKILL.md +262 -0
  743. package/skills/test-improve/SKILL.md +239 -0
  744. package/skills/test-improve/references/phase-0-approach-contract.md +228 -0
  745. package/skills/test-improve/references/phase-1-analyze.md +131 -0
  746. package/skills/test-improve/references/phase-2-baseline.md +121 -0
  747. package/skills/test-improve/references/phase-3-derive-gherkin.md +53 -0
  748. package/skills/test-improve/references/phase-4-plan-fixes.md +34 -0
  749. package/skills/test-improve/references/phase-5-improve.md +215 -0
  750. package/skills/test-improve/references/phase-6-refactor-decision.md +45 -0
  751. package/skills/test-improve/references/phase-7-refactor.md +44 -0
  752. package/skills/test-improve/references/phase-8-validate.md +66 -0
  753. package/skills/test-improve/references/phase-9-close-out-prompt.md +11 -0
  754. package/skills/test-improve/references/phase-9-report.md +62 -0
  755. package/skills/test-improve/references/review-loop.md +92 -0
  756. package/skills/test-improve/templates/executive-summary.md +123 -0
  757. package/skills/threat-modeling/SKILL.md +108 -0
  758. package/skills/triage/SKILL.md +211 -0
  759. package/skills/ubiquitous-language/SKILL.md +192 -0
  760. package/skills/ubiquitous-language/scripts/collect_domain_signals.py +300 -0
  761. package/skills/unfreeze/SKILL.md +37 -0
  762. package/skills/upgrade/SKILL.md +31 -0
  763. package/skills/upgrade/scripts/check_version_drift.py +113 -0
  764. package/skills/upgrade/scripts/enable_autoupdate.py +149 -0
  765. package/skills/version/SKILL.md +25 -0
  766. package/sync/__pycache__/sync_upstream.cpython-314.pyc +0 -0
  767. package/sync/sync_upstream.py +293 -0
  768. package/templates/ACCEPTED-RISKS.md.tmpl +46 -0
  769. package/templates/agents/agent-template.md +151 -0
  770. package/templates/agents/angular-testing.md +66 -0
  771. package/templates/agents/csharp-quality.md +63 -0
  772. package/templates/agents/esm-enforcer.md +52 -0
  773. package/templates/agents/front-end-testing.md +65 -0
  774. package/templates/agents/go-quality.md +65 -0
  775. package/templates/agents/python-quality.md +62 -0
  776. package/templates/agents/react-testing.md +61 -0
  777. package/templates/agents/ts-enforcer.md +60 -0
  778. package/templates/agents/twelve-factor-audit.md +49 -0
  779. package/tools/entropy-check.py +250 -0
  780. package/tools/model-hash-verify.py +213 -0
@@ -0,0 +1,309 @@
1
+ #!/usr/bin/env python3
2
+ """subagent_completion_guard.py — SubagentStop transcript-tail classifier (#2188).
3
+
4
+ Step 2.1a's research findings (below, preserved verbatim as the source citation
5
+ for the classifier Step 2.1b implements after them) confirmed the real
6
+ transcript-level shape of a subagent's completion against 70 real subagent
7
+ transcripts from this session. Step 2.1b (this implementation) turns those
8
+ findings into `classify_stop()`.
9
+
10
+ ## Contract (docs/python-hook-contract.md)
11
+
12
+ Input : SubagentStop JSON on stdin (`transcript_path`, `session_id`, `cwd`)
13
+ Output: one `boundary-events.jsonl` `"record"`-decision row (#1461's
14
+ non-verdict, observational sense -- this hook never blocks, warns,
15
+ bypasses, intervenes, or reverts anything; see
16
+ `knowledge/telemetry-schema.md`) via
17
+ `hooks/lib/boundary_events.emit_boundary_event` for the two
18
+ non-clean, explainable classifications (`empty-final-turn`,
19
+ `truncated-final-turn`); nothing emitted for `clean` or
20
+ `unreadable` (Step 2.2, see `_EMIT_CLASSIFICATIONS`).
21
+ Posture: record-only and fail-open. Any error -> exit 0 silently.
22
+
23
+ Stdlib-only (json/pathlib/sys). See ADR 0014, ADR 0015.
24
+
25
+ ## What was confirmed, and how
26
+
27
+ Primary source: this session's own subagent dispatch transcripts on disk at
28
+ ~/.claude/projects/<project-slug>/<session-id>/subagents/agent-<hash>.jsonl
29
+ (+ a sibling agent-<hash>.meta.json per dispatch). 70 completed subagent transcripts were
30
+ inspected directly (not recalled/guessed) — this is real, live harness output from
31
+ Claude Code 2.1.278, not documentation. No web-doc citation was needed or used since a
32
+ real transcript was reachable, per this step's own instructions.
33
+
34
+ Compared against `hooks/cost_meter.py` (reads `transcript_path` from the hook payload,
35
+ checks `.is_file()`, does not itself parse rows — delegates to
36
+ `hooks/lib/cost_meter.py record`) and `hooks/task_completion_metrics.py` (reads
37
+ `payload.get("stop_reason")` — informational only, never branches on it) for how
38
+ existing SubagentStop hooks already touch this payload, and against
39
+ the former context ceiling guard's `_tail_lines`/`_is_sidechain`/`_measure_occupancy`
40
+ (its former lines 270-424) for the tail-reading and sidechain-row pattern.
41
+
42
+ ## Finding 1 — where a subagent's own transcript lives, and what "sidechain" means here
43
+
44
+ A subagent's transcript is a SEPARATE file from the orchestrator/main-thread session
45
+ file, not inlined into it: `<session>.jsonl` (main thread) has a sibling
46
+ `<session>/subagents/agent-<hash>.jsonl` per dispatched subagent (confirmed: the main
47
+ thread's own `<session>.jsonl` had zero `"isSidechain":true` rows across 7798 lines,
48
+ while every row inside a per-agent `subagents/agent-*.jsonl` file is
49
+ `"isSidechain":true`). This matches Step 2.1b's own plan text precisely: for a
50
+ SubagentStop payload, the "sidechain" rows the former context ceiling guard excluded when
51
+ scanning the MAIN thread are exactly the subagent's own transcript rows when read from
52
+ its own file — nothing needs excluding when reading a subagent's transcript directly.
53
+
54
+ ## Finding 2 — message.stop_reason IS present, but is null far more often than not
55
+
56
+ `message.stop_reason` uses the same field name and the same Anthropic Messages API
57
+ values (`end_turn` | `max_tokens` | `stop_sequence` | `tool_use`) as main-thread rows —
58
+ confirmed directly (e.g. a mid-turn row with `stop_reason:"tool_use"` on a finalized
59
+ tool_use block). However, across the true LAST row of 70 completed subagent transcripts:
60
+
61
+ stop_reason == null -> 61/70 (87%)
62
+ stop_reason == "end_turn" -> 8/70 (11%)
63
+ stop_reason == "tool_use" -> 1/70 (this session's own still-in-progress transcript
64
+ at the time of sampling, not a stopped turn)
65
+ stop_reason == "max_tokens" or "stop_sequence" -> 0/70 (no real example seen either
66
+ way; both remain unverified against a real
67
+ transcript — Anthropic's documented contract is
68
+ the only source for those two values)
69
+
70
+ All 61 `null` cases were genuinely clean, complete hand-backs (e.g. "Report delivered.",
71
+ "Report delivered to caller.", "Handed back: skip — no `.feature` files..."), not
72
+ truncated or errored ones — content was well-formed, non-empty text every time. A
73
+ classifier that treats "clean" as `stop_reason in ("end_turn", "tool_use")` on the final
74
+ row alone will misclassify the large majority of real clean completions. Step 2.1b's
75
+ classifier needs "non-empty content AND stop_reason != 'max_tokens'" as the clean
76
+ signal, not a stop_reason allow-list — `null` must be treated as equivalent to clean,
77
+ not as an unhandled case. (This finding was outside Step 2.1a's edit mandate, which was
78
+ scoped to the malformed-hand-back scenario only, so the plan's Gherkin "Clean
79
+ completion" `Given` clause text was left unedited — flagged here and in the plan's
80
+ Risks & Open Questions section for Step 2.1b to account for.)
81
+
82
+ ## Finding 3 — SubagentHandback is a real, distinguishable tool_use block
83
+
84
+ `SubagentHandback` (the tool a dispatched subagent calls to report back to its caller,
85
+ per this session's own system-prompt tool description) shows up as a genuine
86
+ `{"type":"tool_use","name":"SubagentHandback","input":{"message": "..."}}` block — 69
87
+ real occurrences found across the 70 transcripts. It is a real, greppable signal beyond
88
+ bare stop_reason+content.
89
+
90
+ It is essentially NEVER the transcript's true final row, though: every real example
91
+ followed the same shape — `tool_use` (SubagentHandback, stop_reason "tool_use") ->
92
+ `tool_result` (ack) -> one more short assistant text turn (stop_reason usually null, see
93
+ Finding 2) such as "Report delivered." That final wrap-up turn, not the SubagentHandback
94
+ call itself, is the transcript's real last row on a clean path.
95
+
96
+ ## Finding 4 — "malformed hand-back" has no reliable, unique transcript-level signal
97
+
98
+ Zero of the 69 real `SubagentHandback` calls were malformed (none missing/empty the
99
+ required `message` field), and zero `tool_result` rows tied to a `SubagentHandback`
100
+ `tool_use_id` were flagged `is_error`. Structurally: the tool schema requires `message`
101
+ as a string parameter, so a call missing it would almost certainly be rejected at the
102
+ tool-call-validation layer before ever being persisted as a "call with a missing
103
+ field" — producing a generic `is_error` tool_result indistinguishable in shape from any
104
+ other tool's error (a bad `Read` path, a failed `Bash` command, etc.), not a
105
+ hand-back-specific signature. Combined with Finding 3 (the call is essentially never the
106
+ final row anyway, so "final turn contains a hand-back-shaped call" doesn't match the
107
+ real shape), there is no way to build the plan's original "Malformed hand-back" scenario
108
+ against real evidence rather than a guess.
109
+
110
+ **Decision (per this step's own instruction): the "Malformed hand-back" Gherkin
111
+ scenario and its corresponding Acceptance Criteria bullet are DROPPED, not rescoped.**
112
+ Recorded against issue #2188 (epic #2172) — its Gherkin block, Acceptance Criteria
113
+ bullet, and Risks & Open Questions entry were revised to match, in the same commit-set
114
+ as this file's header.
115
+
116
+ ## Classification precedence (#2188 Step 2.1b — stated explicitly here so two
117
+ ## implementers can't disagree)
118
+
119
+ 1. Unreadable/missing transcript, or a readable transcript whose last row is
120
+ missing an expected `message`/`content` field entirely (structurally
121
+ malformed, not just "empty") -> fail-open, `"unreadable"`, no event.
122
+ 2. `message.stop_reason == "max_tokens"` -> `"truncated-final-turn"`. Checked
123
+ BEFORE the empty-content check: a token-limit cutoff can itself produce
124
+ empty/near-empty content (Finding 2 notes no real `max_tokens` example was
125
+ seen, but the Messages API contract still governs it), and `stop_reason` is
126
+ the more specific, intentional signal, so it wins the overlap case.
127
+ 3. Empty/whitespace-only final assistant content, with `stop_reason` anything
128
+ other than `"max_tokens"` (including the common `null` case, per Finding 2)
129
+ -> `"empty-final-turn"`.
130
+ 4. Otherwise (including `stop_reason: null` with non-empty content, and
131
+ `stop_reason: "end_turn"`/`"tool_use"` with non-empty content) -> `"clean"`.
132
+
133
+ No "malformed hand-back" branch: Finding 4 above found no reliable,
134
+ uniquely-identifying transcript-level signal for it, and the plan's Gherkin
135
+ scenario for it was dropped rather than built against a guess.
136
+ """
137
+
138
+ from __future__ import annotations
139
+
140
+ import json
141
+ import sys
142
+ from pathlib import Path
143
+ from typing import Literal
144
+
145
+ _HOOK_DIR = Path(__file__).resolve().parent
146
+ _LIB_DIR = _HOOK_DIR / "lib"
147
+ if str(_LIB_DIR) not in sys.path:
148
+ sys.path.insert(0, str(_LIB_DIR))
149
+
150
+ from boundary_events import emit_boundary_event # type: ignore[import-not-found]
151
+ from instrument_log import append_row # type: ignore[import-not-found]
152
+ from stdin_json import read_stdin_json # type: ignore[import-not-found]
153
+
154
+ StopClassification = Literal[
155
+ "clean", "empty-final-turn", "truncated-final-turn", "unreadable"
156
+ ]
157
+
158
+ # Classifications that warrant a boundary event (#2188 Step 2.2). "clean" and
159
+ # "unreadable" are both no-ops: "clean" is the expected happy path (nothing to
160
+ # record), and "unreadable" has no reliable transcript-level signal to name a
161
+ # rule for (see Finding 4 above) -- emitting a matched_rule for a case this
162
+ # hook itself can't explain would be a fabricated-confidence event, so it
163
+ # stays silent like every other fail-open path in this hook.
164
+ _EMIT_CLASSIFICATIONS: frozenset[StopClassification] = frozenset(
165
+ {"empty-final-turn", "truncated-final-turn"}
166
+ )
167
+
168
+
169
+ def _tail_lines(path: Path, n: int = 50) -> list[str]:
170
+ """Read the last `n` lines of `path`. Fail-safe: [] on any IO error.
171
+
172
+ Deliberately a small, private, inline reader for this hook rather than
173
+ `scripts/lib/session_log/records.py`'s `iter_file_records` (the
174
+ sanctioned shared transcript-row reader that `review_verdict_recorder.py`
175
+ and `hooks/lib/cost_meter.py` already use over the documented
176
+ hooks/ -> scripts/lib/session_log/ edge — see the import note in
177
+ `hooks/lib/cost_meter.py`). Not reused here because the semantics genuinely differ: `iter_file_records` streams
178
+ forward and silently skips an undecodable line, continuing to the next
179
+ one, while this hook needs "the transcript's true LAST line is malformed
180
+ JSON" to classify as its own distinct outcome (`"unreadable"`, see
181
+ `_last_row` below) rather than silently falling back to an earlier valid
182
+ row. A skip-and-continue streaming reader cannot express that
183
+ distinction, so this hook keeps its own minimal last-row reader (#2188
184
+ Step 2.1b).
185
+ """
186
+ try:
187
+ with path.open("r", encoding="utf-8", errors="replace") as fh:
188
+ lines = fh.readlines()
189
+ except OSError:
190
+ return []
191
+ return lines[-n:] if len(lines) > n else lines
192
+
193
+
194
+ def _last_row(transcript_path: str) -> dict | None:
195
+ """Return the transcript's true last JSON row as a dict, or None.
196
+
197
+ None covers every fail-open case this hook treats identically: a missing
198
+ file, an unreadable file, an empty file, or a last non-blank line that
199
+ isn't valid JSON / isn't a JSON object. Per Finding 1, a subagent's own
200
+ transcript file needs no sidechain filtering — every row in it already
201
+ belongs to this subagent.
202
+ """
203
+ lines = _tail_lines(Path(transcript_path))
204
+ for raw in reversed(lines):
205
+ raw = raw.strip()
206
+ if not raw:
207
+ continue
208
+ try:
209
+ row = json.loads(raw)
210
+ except (json.JSONDecodeError, ValueError):
211
+ return None
212
+ return row if isinstance(row, dict) else None
213
+ return None
214
+
215
+
216
+ def _is_empty_content(content: object) -> bool:
217
+ """True when an assistant message's `content` carries no real text.
218
+
219
+ A plain string is checked directly. A content-block list (the normal
220
+ Messages API shape) is empty when every block is a `text` block and their
221
+ concatenated text is blank; a list containing any non-text block (e.g. a
222
+ `tool_use` block) is never considered empty here.
223
+ """
224
+ if content is None:
225
+ return True
226
+ if isinstance(content, str):
227
+ return not content.strip()
228
+ if isinstance(content, list):
229
+ if not content:
230
+ return True
231
+ text_parts: list[str] = []
232
+ for block in content:
233
+ if isinstance(block, dict) and block.get("type") == "text":
234
+ text_parts.append(block.get("text") or "")
235
+ else:
236
+ return False
237
+ return not "".join(text_parts).strip()
238
+ return True
239
+
240
+
241
+ def classify_stop(transcript_path: str) -> StopClassification:
242
+ """Classify a subagent's SubagentStop transcript tail.
243
+
244
+ See the module-level "Classification precedence" section above for the
245
+ full rule order and citations. Pure function: no I/O beyond reading
246
+ `transcript_path`, no side effects — `main()` wires the result to
247
+ `hooks/lib/boundary_events.emit_boundary_event` (Step 2.2).
248
+ """
249
+ row = _last_row(transcript_path)
250
+ if row is None:
251
+ return "unreadable"
252
+
253
+ message = row.get("message")
254
+ if not isinstance(message, dict) or "content" not in message:
255
+ return "unreadable"
256
+
257
+ if message.get("stop_reason") == "max_tokens":
258
+ return "truncated-final-turn"
259
+
260
+ if _is_empty_content(message.get("content")):
261
+ return "empty-final-turn"
262
+
263
+ return "clean"
264
+
265
+
266
+ def main() -> int:
267
+ """Fail-open SubagentStop entry point.
268
+
269
+ Reads the hook payload, classifies the transcript tail, and emits a
270
+ `boundary-events.jsonl` `"record"`-decision row for the two non-clean,
271
+ explainable outcomes (`empty-final-turn`, `truncated-final-turn`) via
272
+ `hooks/lib/boundary_events.emit_boundary_event` — see
273
+ `_EMIT_CLASSIFICATIONS` above for why `clean`/`unreadable` stay silent.
274
+ `emit_boundary_event` is already fail-open internally (module docstring,
275
+ `boundary_events.py`); this function's own try/except is the same
276
+ outer safety net every other hook in this plugin wraps its entire
277
+ `main()` in (e.g. `destructive_guard.py`), so a failure anywhere in
278
+ this hook — payload parsing, classification, or emission — degrades to a
279
+ silent no-op, never a crash or a non-zero exit.
280
+ """
281
+ try:
282
+ payload = read_stdin_json() or {}
283
+ transcript_path = payload.get("transcript_path")
284
+ if isinstance(transcript_path, str) and transcript_path:
285
+ classification = classify_stop(transcript_path)
286
+ # Every classification, incl. clean/unreadable: the denominator
287
+ # the divergence rate needs (#2201). Observational only.
288
+ append_row(
289
+ "subagent-stops",
290
+ {"classification": classification},
291
+ cwd=payload.get("cwd"),
292
+ session_id=payload.get("session_id"),
293
+ )
294
+ if classification in _EMIT_CLASSIFICATIONS:
295
+ emit_boundary_event(
296
+ payload.get("cwd"),
297
+ "subagent_completion_guard",
298
+ "SubagentStop",
299
+ "record",
300
+ classification,
301
+ payload.get("session_id"),
302
+ )
303
+ except Exception: # noqa: BLE001, S110 — fail-open by design, see module docstring
304
+ pass
305
+ return 0
306
+
307
+
308
+ if __name__ == "__main__":
309
+ sys.exit(main())
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env python3
2
+ """subagent_skill_context.py — PreToolUse hook injecting skill-loading
3
+ context into an Agent/Task dispatch (#2187, Slice 1 Step 1.2).
4
+
5
+ Registered in the existing `PreToolUse` `"Agent|Task"` matcher (alongside
6
+ `agent_dispatch_ledger.py`). Reads
7
+ `tool_input.subagent_type`, resolves its declared skills via
8
+ `hooks/lib/agent_skill_hints.py::skills_for_agent_type` (frontmatter
9
+ `skills:` is the single source of truth — ADR 0028), and when that list is
10
+ non-empty, emits `hookSpecificOutput.updatedInput` naming those skills as an
11
+ `additionalContext` note appended to the dispatch's `tool_input` — the
12
+ original `tool_input` keys are preserved unchanged, never replaced.
13
+
14
+ No collision with the other hooks on this matcher: none emits
15
+ `hookSpecificOutput`/`updatedInput` today, so this hook is the sole supplier of `updatedInput`
16
+ for `Agent|Task` PreToolUse.
17
+
18
+ Fail-open throughout, matching every other hook in this plugin:
19
+ - `tool_name` not in {"Agent", "Task"} -> exit 0, no stdout.
20
+ - `tool_input.subagent_type` missing or not a non-empty string -> exit 0,
21
+ no stdout, no `updatedInput`.
22
+ - unrecognized agent type / no declared skills -> exit 0, no stdout.
23
+ - malformed/missing stdin -> exit 0 (mirrors `read_stdin_json`'s own
24
+ fail-open contract exactly).
25
+
26
+ Contract (docs/python-hook-contract.md):
27
+ Input : PreToolUse JSON on stdin
28
+ Output: JSON on stdout carrying `hookSpecificOutput.updatedInput` when a
29
+ skill hint applies; otherwise no stdout. Always exits 0.
30
+
31
+ Stdlib only. See ADR 0014 / ADR 0015.
32
+ """
33
+
34
+ from __future__ import annotations
35
+
36
+ import json
37
+ import sys
38
+ from pathlib import Path
39
+
40
+ _HOOKS_DIR = Path(__file__).resolve().parent
41
+ _LIB_DIR = _HOOKS_DIR / "lib"
42
+ if str(_LIB_DIR) not in sys.path:
43
+ sys.path.insert(0, str(_LIB_DIR))
44
+
45
+ from agent_skill_hints import skills_for_agent_type # type: ignore[import-not-found]
46
+ from instrument_log import append_row # type: ignore[import-not-found]
47
+ from review_agent_registry import strip_plugin_prefix # type: ignore[import-not-found]
48
+ from stdin_json import read_stdin_json # type: ignore[import-not-found]
49
+
50
+ # hooks/subagent_skill_context.py -> hooks -> plugin root -> agents
51
+ _DEFAULT_AGENTS_DIR = _HOOKS_DIR.parent / "agents"
52
+
53
+ _DISPATCH_TOOLS = frozenset({"Agent", "Task"})
54
+
55
+
56
+ def _build_note(skills: list[str]) -> str:
57
+ return (
58
+ "Relevant skills for this dispatch (per the agent's own frontmatter "
59
+ f"`skills:` list): {', '.join(skills)}."
60
+ )
61
+
62
+
63
+ def resolve_updated_input(
64
+ payload: dict, agents_dir: Path | None = None
65
+ ) -> dict | None:
66
+ """Compute the `updatedInput` dict for a PreToolUse payload, or `None`
67
+ when no hint applies. Split from `main()` for testability.
68
+
69
+ `agents_dir` defaults to the module-level `_DEFAULT_AGENTS_DIR`, read at
70
+ call time (not bound as a mutable default) so tests can
71
+ `monkeypatch.setattr(hook, "_DEFAULT_AGENTS_DIR", tmp_path)` and have it
72
+ take effect.
73
+ """
74
+ if agents_dir is None:
75
+ agents_dir = _DEFAULT_AGENTS_DIR
76
+
77
+ tool_name = payload.get("tool_name")
78
+ if tool_name not in _DISPATCH_TOOLS:
79
+ return None
80
+
81
+ tool_input = payload.get("tool_input")
82
+ if not isinstance(tool_input, dict):
83
+ return None
84
+
85
+ subagent_type = tool_input.get("subagent_type")
86
+ if not isinstance(subagent_type, str) or not subagent_type:
87
+ return None
88
+ subagent_type = strip_plugin_prefix(subagent_type)
89
+
90
+ skills = skills_for_agent_type(subagent_type, agents_dir)
91
+ if not skills:
92
+ return None
93
+
94
+ return {**tool_input, "additionalContext": _build_note(skills)}
95
+
96
+
97
+ def main() -> int:
98
+ try:
99
+ payload = read_stdin_json()
100
+ if payload is None:
101
+ # Empty or malformed stdin -> silent pass, same as every other hook.
102
+ return 0
103
+
104
+ updated_input = resolve_updated_input(payload)
105
+ if updated_input is None:
106
+ return 0
107
+
108
+ # Observational only (#2201): lets uptake be computed against the
109
+ # subagent transcripts' Skill tool calls.
110
+ append_row(
111
+ "skill-injection",
112
+ {
113
+ "agent_type": payload["tool_input"]["subagent_type"],
114
+ "skills": skills_for_agent_type(
115
+ strip_plugin_prefix(payload["tool_input"]["subagent_type"]),
116
+ _DEFAULT_AGENTS_DIR,
117
+ ),
118
+ "added_chars": len(updated_input["additionalContext"]),
119
+ },
120
+ cwd=payload.get("cwd"),
121
+ session_id=payload.get("session_id"),
122
+ )
123
+ print(
124
+ json.dumps(
125
+ {
126
+ "hookSpecificOutput": {
127
+ "hookEventName": "PreToolUse",
128
+ "updatedInput": updated_input,
129
+ }
130
+ }
131
+ )
132
+ )
133
+ except Exception: # noqa: BLE001, S110 — fail-open by design, see module docstring
134
+ pass
135
+ return 0
136
+
137
+
138
+ if __name__ == "__main__": # pragma: no cover
139
+ sys.exit(main())
@@ -0,0 +1,216 @@
1
+ #!/usr/bin/env python3
2
+ """task_completion_metrics.py — Stop/SubagentStop hook for JSONL audit logging.
3
+
4
+ Fires on task/session completion signals (Stop + SubagentStop) and writes
5
+ standard metrics fields to their respective JSONL files, mechanically,
6
+ regardless of which skill or agent was active.
7
+
8
+ Skills no longer need "remember to log X" prose in their Output sections.
9
+ They only need to have populated the shared scratch file
10
+ `.claude/session-metrics.json` with any task-local values they want recorded.
11
+ The hook consumes that file and clears it after writing.
12
+
13
+ ## Scratch file format (.claude/session-metrics.json)
14
+
15
+ ```json
16
+ {
17
+ "task_id": "optional-human-slug",
18
+ "task_type": "implementation",
19
+ "task_description": "Short description of the task",
20
+ "agents_used": ["software-engineer"],
21
+ "skills_used": ["quality-gate-pipeline"],
22
+ "hallucination_detected": false,
23
+ "rework_cycles": 0,
24
+ "defects_found": 0,
25
+ "config_change": {
26
+ "parameter": "CLAUDE_AUTOCOMPACT_PCT_OVERRIDE",
27
+ "old_value": "40",
28
+ "new_value": "50",
29
+ "reason": "Increased for larger context models"
30
+ }
31
+ }
32
+ ```
33
+
34
+ All fields are optional. If the scratch file is absent or empty, the hook
35
+ writes **nothing** and exits — a Stop/SubagentStop with no task-local payload
36
+ carries no signal worth recording, and a bare heartbeat only produces
37
+ `task_type:"unknown"` noise that dilutes `/harness-audit` Step 3 (see #1258;
38
+ a single 2026-07-20 audit run emitted 172 empty heartbeats vs 10 real rows).
39
+
40
+ ## Output files
41
+
42
+ - `.claude/metrics/{date}-task-log.jsonl` — task completion entry
43
+ - `.claude/metrics/config-changelog.jsonl` — config change entry (if `config_change` present)
44
+
45
+ ## Contract (docs/python-hook-contract.md)
46
+
47
+ Input : Stop / SubagentStop JSON on stdin
48
+ Output: appends to metrics JSONL files; no stdout. Exit 0.
49
+ Posture: record-only and fail-open. Any error -> exit 0 silently.
50
+ Opt-out: DEV_TEAM_TASK_METRICS=off disables entirely.
51
+
52
+ Stdlib-only (datetime/json/os/pathlib/sys/uuid).
53
+ See ADR 0014, ADR 0015.
54
+
55
+ Refs: #1044 (this hook), #1042 (parent epic).
56
+ """
57
+
58
+ from __future__ import annotations
59
+
60
+ import datetime
61
+ import json
62
+ import os
63
+ import sys
64
+ import uuid
65
+ from pathlib import Path
66
+
67
+ _HOOK_DIR = Path(__file__).resolve().parent
68
+ _PLUGIN_DIR = _HOOK_DIR.parent
69
+ _LIB_DIR = _HOOK_DIR / "lib"
70
+ if str(_LIB_DIR) not in sys.path:
71
+ sys.path.insert(0, str(_LIB_DIR))
72
+
73
+ import artifact_paths
74
+ import telemetry_consent
75
+ from atomic_state import append_line_locked
76
+ from stdin_json import read_stdin_json # type: ignore[import-not-found]
77
+
78
+ # Scratch file location: resolved relative to the project root (cwd when hook
79
+ # fires) so it is session-local, not baked into the plugin install tree.
80
+ _SCRATCH_RELATIVE = Path(".claude") / "session-metrics.json"
81
+
82
+
83
+ def _env_off(var: str) -> bool:
84
+ return os.environ.get(var, "").strip().lower() == "off"
85
+
86
+
87
+ def _load_scratch(cwd: Path) -> dict:
88
+ scratch = cwd / _SCRATCH_RELATIVE
89
+ try:
90
+ if not scratch.exists():
91
+ return {}
92
+ text = scratch.read_text(encoding="utf-8").strip()
93
+ if not text:
94
+ return {}
95
+ parsed = json.loads(text)
96
+ return parsed if isinstance(parsed, dict) else {}
97
+ except (json.JSONDecodeError, UnicodeDecodeError, OSError):
98
+ return {}
99
+
100
+
101
+ def _clear_scratch(cwd: Path) -> None:
102
+ scratch = cwd / _SCRATCH_RELATIVE
103
+ try:
104
+ if scratch.exists():
105
+ scratch.unlink()
106
+ except OSError: # best-effort cleanup; a stale scratch file is harmless
107
+ pass
108
+
109
+
110
+ def _ensure_metrics_dir(cwd: Path) -> Path:
111
+ metrics = artifact_paths.metrics_dir(cwd)
112
+ metrics.mkdir(parents=True, exist_ok=True)
113
+ return metrics
114
+
115
+
116
+ def _now_iso() -> str:
117
+ return datetime.datetime.now(tz=datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
118
+
119
+
120
+ def _today() -> str:
121
+ return datetime.datetime.now(tz=datetime.timezone.utc).strftime("%Y-%m-%d")
122
+
123
+
124
+ def _append_jsonl(path: Path, entry: dict) -> None:
125
+ """Append one JSON line to a JSONL file, creating it if needed.
126
+
127
+ Serialized against concurrent writers via `atomic_state.append_line_locked`
128
+ (#1896) — fail-open, matching this hook's outer `main()` try/except.
129
+ """
130
+ line = json.dumps(entry, separators=(",", ":"), sort_keys=False)
131
+ append_line_locked(path, line + "\n")
132
+
133
+
134
+ def _write_task_completion(cwd: Path, scratch: dict, payload: dict) -> None:
135
+ """Write a task completion entry to .claude/metrics/{date}-task-log.jsonl."""
136
+ ts = _now_iso()
137
+ entry: dict = {
138
+ "timestamp": ts,
139
+ "task_id": scratch.get("task_id") or str(uuid.uuid4()),
140
+ "task_type": scratch.get("task_type", "unknown"),
141
+ "task_description": scratch.get("task_description", ""),
142
+ "agents_used": scratch.get("agents_used") or [],
143
+ "skills_used": scratch.get("skills_used") or [],
144
+ "hallucination_detected": bool(scratch.get("hallucination_detected", False)),
145
+ "rework_cycles": int(scratch.get("rework_cycles", 0)),
146
+ "defects_found": int(scratch.get("defects_found", 0)),
147
+ }
148
+
149
+ # Include stop-reason from harness if available (informational).
150
+ stop_reason = payload.get("stop_reason") or payload.get("stopReason")
151
+ if stop_reason:
152
+ entry["stop_reason"] = stop_reason
153
+
154
+ log_path = artifact_paths.resolve_file(
155
+ "metrics", f"{_today()}-task-log.jsonl", cwd
156
+ )
157
+ log_path.parent.mkdir(parents=True, exist_ok=True)
158
+ _append_jsonl(log_path, entry)
159
+
160
+
161
+ def _write_config_changelog(cwd: Path, scratch: dict) -> None:
162
+ """Write a config-changelog entry if scratch contains config_change."""
163
+ change = scratch.get("config_change")
164
+ if not change or not isinstance(change, dict):
165
+ return
166
+
167
+ ts = _now_iso()
168
+ entry: dict = {
169
+ "timestamp": ts,
170
+ "parameter": change.get("parameter", ""),
171
+ "old_value": change.get("old_value", ""),
172
+ "new_value": change.get("new_value", ""),
173
+ "reason": change.get("reason", ""),
174
+ }
175
+ log_path = artifact_paths.resolve_file("metrics", "config-changelog.jsonl", cwd)
176
+ log_path.parent.mkdir(parents=True, exist_ok=True)
177
+ _append_jsonl(log_path, entry)
178
+
179
+
180
+ def main() -> int:
181
+ if _env_off("DEV_TEAM_TASK_METRICS"):
182
+ return 0
183
+ if not telemetry_consent.is_enabled():
184
+ return 0
185
+
186
+ payload = read_stdin_json() or {}
187
+
188
+ # Resolve project root from the hook payload's cwd, falling back to
189
+ # process cwd (which the harness sets to the project root).
190
+ raw_cwd = payload.get("cwd") or os.environ.get("CLAUDE_PROJECT_DIR") or ""
191
+ cwd = Path(raw_cwd).resolve() if raw_cwd else Path.cwd()
192
+
193
+ scratch = _load_scratch(cwd)
194
+
195
+ # Suppress empty heartbeats (#1258). A Stop/SubagentStop with no scratch
196
+ # payload has nothing task-local to record — writing an entry would only
197
+ # emit a hollow task_type:"unknown" row that dilutes downstream analysis
198
+ # (harness-audit Step 3). The stop payload alone (stop_reason, cost) is not
199
+ # enough to justify a row; a skill that wants a row populates the scratch.
200
+ if not scratch:
201
+ return 0
202
+
203
+ try:
204
+ _ensure_metrics_dir(cwd)
205
+ _write_task_completion(cwd, scratch, payload)
206
+ _write_config_changelog(cwd, scratch)
207
+ _clear_scratch(cwd)
208
+ except Exception: # noqa: BLE001, S110
209
+ # Fail-open: never block the session on a metrics write failure.
210
+ pass
211
+
212
+ return 0
213
+
214
+
215
+ if __name__ == "__main__":
216
+ sys.exit(main())