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,397 @@
1
+ """autoship_state — shared round-state helpers for /dev-team:autoship (#989).
2
+
3
+ Shared by `autoship_discover.py`, `autoship_group.py`, and
4
+ `autoship_reclaim.py` so none has to inspect another's code to reuse common
5
+ logic: the `autoship:*` label constants scripts filter on, the
6
+ `--input-file`/`--now-override` CLI seam, the positive-value CLI validators,
7
+ and (as of the Slice 1 grouping work) the shared `gh issue list` fetch +
8
+ eligibility-filter pipeline (`fetch_eligible_issues`) that both
9
+ `autoship_discover.py` and `autoship_group.py` build on.
10
+ `is_stale`/`format_round_timestamp` are consumed only by
11
+ `autoship_reclaim.py`'s staleness check — discovery/grouping have no
12
+ staleness concept of their own.
13
+
14
+ Stdlib-only. See docs/python-hook-contract.md.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import argparse
20
+ import json
21
+ import subprocess
22
+ from datetime import datetime
23
+ from typing import Any
24
+
25
+ READY_LABEL = "autoship:ready"
26
+ IN_PROGRESS_LABEL = "autoship:in-progress"
27
+ BLOCKED_LABEL = "autoship:blocked"
28
+
29
+ # The label a human confirmation applies to an agent-proposed batch (Step 2c,
30
+ # `skills/autoship/SKILL.md`) — recognized by `autoship_group.py`'s
31
+ # `has_batch_confirmed_override` signal function, and stripped by
32
+ # `autoship_reclaim.py`'s reclaim relabel. Lives here, alongside the other
33
+ # three `autoship:*` label constants, so both scripts import one definition
34
+ # instead of each redefining it independently.
35
+ BATCH_CONFIRMED_LABEL = "autoship:batch-confirmed"
36
+
37
+ # `gh issue list` applies a default result cap (typically 30) — every caller
38
+ # that needs the FULL matching pool (discovery/grouping's eligible pool,
39
+ # reclaim's in-progress pool) passes this explicit override instead of each
40
+ # hardcoding its own "500" literal.
41
+ GH_LIST_LIMIT = "500"
42
+
43
+ # Same fields `gh issue list --json` returns for these names — no schema
44
+ # invention. `title` is required because `autoship_discover.py`'s stdout
45
+ # contract emits it; `state` is required because `is_eligible` checks it
46
+ # directly. Callers needing richer data (e.g. `autoship_group.py`'s
47
+ # dependency/parent signals) pass their own, larger `required_fields` tuple
48
+ # to `fetch_eligible_issues`/`validate_issues`/`load_issues_from_file`.
49
+ BASE_REQUIRED_FIELDS = (
50
+ "number",
51
+ "title",
52
+ "state",
53
+ "createdAt",
54
+ "labels",
55
+ "closedByPullRequestsReferences",
56
+ "subIssuesSummary",
57
+ )
58
+
59
+ # gh subprocess calls get a hard timeout so a hung/stalled network call never
60
+ # blocks a caller script indefinitely.
61
+ _GH_TIMEOUT_SECONDS = 30
62
+
63
+
64
+ class FetchError(Exception):
65
+ """A discovery/grouping-input or `gh` fetch problem that must surface as
66
+ a clear CLI error message, not an uncaught exception/traceback."""
67
+
68
+
69
+ def format_round_timestamp(dt: datetime) -> str:
70
+ """Format `dt` as an ISO-8601 UTC string ending in "Z".
71
+
72
+ Matches the timestamp shape already used in `metrics/config-changelog.jsonl`.
73
+ """
74
+ return dt.strftime("%Y-%m-%dT%H:%M:%SZ")
75
+
76
+
77
+ def is_stale(labeled_at: datetime, stale_after_hours: float, now: datetime) -> bool:
78
+ """True when `labeled_at` is at or beyond `stale_after_hours` before `now`.
79
+
80
+ Inclusive at the boundary: exactly `stale_after_hours` counts as stale —
81
+ "past" in the issue's own language means "at or beyond".
82
+ """
83
+ elapsed_hours = (now - labeled_at).total_seconds() / 3600
84
+ return elapsed_hours >= stale_after_hours
85
+
86
+
87
+ def _iso8601(raw: str) -> datetime:
88
+ """`argparse` `type=` validator for an ISO-8601 timestamp string."""
89
+ # Deliberately naive: `is_stale`'s `now` (autoship_reclaim.py) strips
90
+ # tzinfo from its UTC clock read to match this, so both sides of the
91
+ # subtraction stay naive-UTC. Making this tz-aware would break that pairing.
92
+ return datetime.strptime(raw, "%Y-%m-%dT%H:%M:%SZ") # noqa: DTZ007
93
+
94
+
95
+ def positive_float_validator(flag_name: str):
96
+ """Return an `argparse` `type=` validator that rejects `<= 0` for `flag_name`.
97
+
98
+ Shared by `autoship_discover.py`'s `--max-cost-usd` and
99
+ `autoship_reclaim.py`'s `--stale-after-hours` so both fail loud at the
100
+ CLI boundary the same way, per `evals/code-review-benchmark/cli.py`'s
101
+ `_positive_float` precedent — one implementation instead of two
102
+ independently-copied ones.
103
+ """
104
+
105
+ def _validator(raw: str) -> float:
106
+ value = float(raw)
107
+ if value <= 0:
108
+ raise argparse.ArgumentTypeError(
109
+ f"{flag_name} must be a positive number, got {raw!r}"
110
+ )
111
+ return value
112
+
113
+ return _validator
114
+
115
+
116
+ def positive_int_validator(flag_name: str):
117
+ """Return an `argparse` `type=` validator that rejects `<= 0` for `flag_name`.
118
+
119
+ Same shape as `positive_float_validator`, for integer-valued flags —
120
+ shared by `autoship_discover.py`'s `--max-issues` so the CLI boundary
121
+ fails loud the same way `--max-cost-usd` does.
122
+ """
123
+
124
+ def _validator(raw: str) -> int:
125
+ value = int(raw)
126
+ if value <= 0:
127
+ raise argparse.ArgumentTypeError(
128
+ f"{flag_name} must be a positive integer, got {raw!r}"
129
+ )
130
+ return value
131
+
132
+ return _validator
133
+
134
+
135
+ def _label_names(issue: dict[str, Any]) -> list[str]:
136
+ return [label["name"] for label in issue["labels"]]
137
+
138
+
139
+ def _is_epic(issue: dict[str, Any]) -> bool:
140
+ return issue["subIssuesSummary"].get("total", 0) > 0
141
+
142
+
143
+ def _has_open_linked_pr(issue: dict[str, Any]) -> bool:
144
+ """True when any entry in `closedByPullRequestsReferences` is itself
145
+ still open — a single open PR anywhere in the list excludes the issue,
146
+ even when other entries in the same list are closed/merged."""
147
+ return any(
148
+ pr.get("state") == "OPEN" for pr in issue["closedByPullRequestsReferences"]
149
+ )
150
+
151
+
152
+ def is_eligible(issue: dict[str, Any], label: str) -> bool:
153
+ """True when `issue` qualifies for autoship dispatch: open, carries
154
+ `label`, is not in-progress/blocked, is not an epic, and has no open
155
+ linked pull request."""
156
+ if issue["state"] != "OPEN":
157
+ return False
158
+ labels = _label_names(issue)
159
+ if label not in labels:
160
+ return False
161
+ if IN_PROGRESS_LABEL in labels or BLOCKED_LABEL in labels:
162
+ return False
163
+ if _is_epic(issue):
164
+ return False
165
+ return not _has_open_linked_pr(issue)
166
+
167
+
168
+ def _validate_shape(issue: dict[str, Any], identifier: str) -> None:
169
+ """Validate the structural shape of `labels`, `subIssuesSummary`, and
170
+ `closedByPullRequestsReferences` when present on `issue`.
171
+
172
+ `is_eligible` reads these three fields structurally, not just by key
173
+ presence: `_label_names` indexes every `labels` entry with `label["name"]`,
174
+ `_is_epic` calls `.get("total", 0)` on `subIssuesSummary`, and
175
+ `_has_open_linked_pr` calls `.get("state")` on every
176
+ `closedByPullRequestsReferences` entry. A malformed `--input-file` (e.g.
177
+ `labels` as bare strings instead of `{"name": ...}` objects) reached an
178
+ uncaught `TypeError`/`AttributeError` deep inside `is_eligible` instead of
179
+ a clean `FetchError` here.
180
+
181
+ Raises `FetchError` naming `identifier` and the offending field.
182
+ """
183
+ if "labels" in issue:
184
+ labels = issue["labels"]
185
+ if not isinstance(labels, list):
186
+ raise FetchError(
187
+ f"malformed --input-file entry ({identifier}): field "
188
+ f'"labels" must be a JSON array, got {type(labels).__name__}'
189
+ )
190
+ for label_idx, label in enumerate(labels):
191
+ if not isinstance(label, dict) or not isinstance(label.get("name"), str):
192
+ raise FetchError(
193
+ f"malformed --input-file entry ({identifier}): "
194
+ f'"labels[{label_idx}]" must be a JSON object with a '
195
+ 'string "name" field'
196
+ )
197
+
198
+ if "subIssuesSummary" in issue:
199
+ summary = issue["subIssuesSummary"]
200
+ if not isinstance(summary, dict):
201
+ raise FetchError(
202
+ f"malformed --input-file entry ({identifier}): field "
203
+ f'"subIssuesSummary" must be a JSON object, got '
204
+ f"{type(summary).__name__}"
205
+ )
206
+ if "total" in summary and not isinstance(summary["total"], int):
207
+ raise FetchError(
208
+ f"malformed --input-file entry ({identifier}): field "
209
+ f'"subIssuesSummary.total" must be a number, got '
210
+ f"{type(summary['total']).__name__}"
211
+ )
212
+
213
+ if "closedByPullRequestsReferences" in issue:
214
+ refs = issue["closedByPullRequestsReferences"]
215
+ if not isinstance(refs, list):
216
+ raise FetchError(
217
+ f"malformed --input-file entry ({identifier}): field "
218
+ '"closedByPullRequestsReferences" must be a JSON array, got '
219
+ f"{type(refs).__name__}"
220
+ )
221
+ for ref_idx, ref in enumerate(refs):
222
+ if not isinstance(ref, dict):
223
+ raise FetchError(
224
+ f"malformed --input-file entry ({identifier}): "
225
+ f'"closedByPullRequestsReferences[{ref_idx}]" must be a '
226
+ "JSON object"
227
+ )
228
+
229
+
230
+ def validate_issues(
231
+ issues: Any, required_fields: tuple[str, ...] = BASE_REQUIRED_FIELDS
232
+ ) -> None:
233
+ """Validate `issues` is a JSON array of objects each carrying every
234
+ `required_fields` entry, and that `labels`/`subIssuesSummary`/
235
+ `closedByPullRequestsReferences` (when present) have the structural shape
236
+ `is_eligible` expects (see `_validate_shape`).
237
+
238
+ Raises `FetchError` naming the malformed entry (by issue number if
239
+ present, by index otherwise) rather than letting a `KeyError`/`TypeError`/
240
+ `AttributeError` propagate uncaught.
241
+ """
242
+ if not isinstance(issues, list):
243
+ raise FetchError(
244
+ "--input-file must contain a JSON array of issue objects, got "
245
+ f"{type(issues).__name__}"
246
+ )
247
+ for idx, issue in enumerate(issues):
248
+ if not isinstance(issue, dict):
249
+ raise FetchError(
250
+ f"malformed --input-file entry at index {idx}: not a JSON object"
251
+ )
252
+ identifier = f"#{issue['number']}" if "number" in issue else f"index {idx}"
253
+ missing = [field for field in required_fields if field not in issue]
254
+ if missing:
255
+ raise FetchError(
256
+ f"malformed --input-file entry ({identifier}): missing required "
257
+ f"field(s) {', '.join(missing)}"
258
+ )
259
+ _validate_shape(issue, identifier)
260
+
261
+
262
+ def load_issues_from_file(
263
+ path: str, required_fields: tuple[str, ...] = BASE_REQUIRED_FIELDS
264
+ ) -> list[dict[str, Any]]:
265
+ """Read and validate an `--input-file` JSON array of issue objects.
266
+
267
+ Raises `FetchError` on unreadable/malformed JSON or a schema violation —
268
+ never an uncaught exception.
269
+ """
270
+ try:
271
+ with open(path, encoding="utf-8") as fh:
272
+ issues = json.load(fh)
273
+ except json.JSONDecodeError as exc:
274
+ raise FetchError(f"--input-file {path!r} is not valid JSON: {exc}") from exc
275
+ except OSError as exc:
276
+ raise FetchError(f"--input-file {path!r} could not be read: {exc}") from exc
277
+ validate_issues(issues, required_fields)
278
+ return issues
279
+
280
+
281
+ def fetch_issues_from_gh(
282
+ label: str,
283
+ required_fields: tuple[str, ...] = BASE_REQUIRED_FIELDS,
284
+ extra_fields: tuple[str, ...] = (),
285
+ ) -> list[dict[str, Any]]:
286
+ """Fetch open issues labeled `label` via a live `gh issue list` call,
287
+ using `gh`'s cwd-based repo auto-detection (no `--repo` flag).
288
+
289
+ `--json` requests `required_fields` plus any `extra_fields` a caller
290
+ needs on top of that base set (e.g. `autoship_group.py`'s dependency/
291
+ parent fields), deduplicated while preserving order.
292
+
293
+ The `--state open` server-side filter and the requested `state` field
294
+ are intentionally redundant with `is_eligible`'s own `state == "OPEN"`
295
+ check — this is what makes the `--input-file` and live paths behave
296
+ identically.
297
+
298
+ `--limit 500` is required here: `gh issue list` applies a default
299
+ result cap (typically 30), and this function is documented (see
300
+ `fetch_eligible_issues`) as returning the FULL eligible pool — without
301
+ an explicit override that claim is false on any repo with more than a
302
+ page of matching issues.
303
+
304
+ Raises `FetchError` on a non-zero `gh` exit, a timeout, or malformed
305
+ JSON output — never an uncaught
306
+ `CalledProcessError`/`TimeoutExpired`/`JSONDecodeError`/traceback.
307
+ """
308
+ fields = list(required_fields)
309
+ for field in extra_fields:
310
+ if field not in fields:
311
+ fields.append(field)
312
+ gh_json_fields = ",".join(fields)
313
+
314
+ try:
315
+ result = subprocess.run(
316
+ [
317
+ "gh",
318
+ "issue",
319
+ "list",
320
+ "--state",
321
+ "open",
322
+ "--label",
323
+ label,
324
+ "--limit",
325
+ GH_LIST_LIMIT,
326
+ "--json",
327
+ gh_json_fields,
328
+ ],
329
+ capture_output=True,
330
+ text=True,
331
+ check=True,
332
+ timeout=_GH_TIMEOUT_SECONDS,
333
+ )
334
+ except FileNotFoundError as exc:
335
+ raise FetchError(f"gh CLI not found: {exc}") from exc
336
+ except subprocess.TimeoutExpired as exc:
337
+ raise FetchError(
338
+ f"gh issue list timed out after {_GH_TIMEOUT_SECONDS}s: {exc}"
339
+ ) from exc
340
+ except subprocess.CalledProcessError as exc:
341
+ stderr = (exc.stderr or "").strip()
342
+ raise FetchError(
343
+ f"gh issue list failed (exit {exc.returncode}): {stderr}"
344
+ ) from exc
345
+
346
+ try:
347
+ issues = json.loads(result.stdout)
348
+ except json.JSONDecodeError as exc:
349
+ raise FetchError(f"gh issue list returned malformed JSON: {exc}") from exc
350
+
351
+ validate_issues(issues, required_fields)
352
+ return issues
353
+
354
+
355
+ def fetch_eligible_issues(
356
+ label: str,
357
+ extra_fields: tuple[str, ...] = (),
358
+ input_file: str | None = None,
359
+ required_fields: tuple[str, ...] = BASE_REQUIRED_FIELDS,
360
+ ) -> list[dict[str, Any]]:
361
+ """Return the FULL eligible pool for `label`, oldest-first by
362
+ `createdAt` — no `--max-issues`-style truncation (that stays each
363
+ caller's own concern, applied after this returns).
364
+
365
+ Sources issues from `input_file` when given (bypassing the live `gh`
366
+ call, the shared `--input-file` test seam), otherwise from a live
367
+ `gh issue list` call requesting `required_fields` plus `extra_fields`.
368
+ Raises `FetchError` on any fetch/validation problem (never an uncaught
369
+ exception).
370
+ """
371
+ if input_file:
372
+ issues = load_issues_from_file(input_file, required_fields)
373
+ else:
374
+ issues = fetch_issues_from_gh(label, required_fields, extra_fields)
375
+
376
+ eligible = [issue for issue in issues if is_eligible(issue, label)]
377
+ eligible.sort(key=lambda issue: issue["createdAt"])
378
+ return eligible
379
+
380
+
381
+ def add_input_seam_args(parser: argparse.ArgumentParser) -> None:
382
+ """Add the shared `--input-file`/`--now-override` test seam to `parser`.
383
+
384
+ Both flags are optional at this shared level; each caller decides its
385
+ own default file-source behavior. `--input-file` lets a caller skip its
386
+ live `gh` fetch entirely (JSON array of issue objects); `--now-override`
387
+ feeds `is_stale` an explicit "now" instead of the real clock.
388
+ """
389
+ parser.add_argument(
390
+ "--input-file",
391
+ help="Path to a JSON array of issue objects, bypassing the live gh fetch.",
392
+ )
393
+ parser.add_argument(
394
+ "--now-override",
395
+ type=_iso8601,
396
+ help="ISO-8601 UTC timestamp (e.g. 2026-07-08T12:00:00Z) to use as 'now'.",
397
+ )
@@ -0,0 +1,226 @@
1
+ """Snapshot/diff/restore guards for tools that touch a project's `CLAUDE.md`.
2
+
3
+ Two distinct guards live here, for two distinct contracts:
4
+
5
+ **`run_install_with_guard`** — for `graphify install --project` (#846), which
6
+ rewrites the target repo's `CLAUDE.md` to add a `## graphify` section. Its
7
+ updater matches the literal `## graphify` header text and replaces everything
8
+ between it and the next `##` heading — a known bug can over-delete, removing
9
+ pre-existing unrelated content along with the stale graphify section.
10
+
11
+ 1. Snapshot `CLAUDE.md` before running the installer.
12
+ 2. Diff the snapshot against the post-install file.
13
+ 3. If any pre-existing line was lost, restore the snapshot and append the
14
+ canonical `## graphify` section text at EOF instead of trusting the
15
+ installer's in-place edit.
16
+ 4. If nothing was lost, leave the installer's output as-is.
17
+
18
+ **`run_install_reverting_unexpected_writes`** — general-purpose guard for an
19
+ installer that is expected to leave `CLAUDE.md` **completely untouched**: ANY
20
+ diff — added or removed lines, even a write followed by the installer itself
21
+ raising — is reverted in full. The reverted-or-not outcome and any added
22
+ lines are returned separately, so a deletion-only write is never mistaken for
23
+ a no-op. Originally written for `repowise init` (#1670 item 3), whose
24
+ `## Codebase Intelligence for <project> (Repowise)` write into
25
+ `.claude/CLAUDE.md` turned out to be intended, expected behavior, not a bug —
26
+ so `project-init/SKILL.md` does not call this function today. Kept as
27
+ reviewed, tested infra for a future installer that genuinely needs a
28
+ zero-tolerance guard (unlike `run_install_with_guard`'s scoped-section
29
+ tolerance above), rather than deleted, since the two guards' contracts are
30
+ otherwise easy to conflate and re-deriving this one from scratch later would
31
+ repeat work already done once.
32
+
33
+ Stdlib-only, per ADR 0014/0015 (Python for cross-OS scripts).
34
+ """
35
+
36
+ from __future__ import annotations
37
+
38
+ import traceback
39
+ from collections import Counter
40
+ from collections.abc import Callable
41
+ from pathlib import Path
42
+
43
+ _GRAPHIFY_HEADER = "## graphify"
44
+
45
+
46
+ def _protected_lines(text: str) -> list[str]:
47
+ """All lines of `text` except the existing `## graphify` section's body.
48
+
49
+ The graphify section is expected to change on every install (that's the
50
+ point of re-running the installer) so it is excluded from the
51
+ corruption check — only lines *outside* that section must survive.
52
+ """
53
+ lines = text.splitlines()
54
+ start = next(
55
+ (i for i, line in enumerate(lines) if line.strip() == _GRAPHIFY_HEADER),
56
+ None,
57
+ )
58
+ if start is None:
59
+ return lines
60
+
61
+ end = len(lines)
62
+ for i in range(start + 1, len(lines)):
63
+ if lines[i].startswith("## "):
64
+ end = i
65
+ break
66
+
67
+ return lines[:start] + lines[end:]
68
+
69
+
70
+ def _lines_only_in(candidate_lines: list[str], baseline_counts: Counter) -> list[str]:
71
+ """Multiset-diff kernel shared by `find_missing_lines`/`find_added_lines`:
72
+ lines in `candidate_lines` that occur more often there than in
73
+ `baseline_counts`. Order-preserving relative to `candidate_lines`. A line
74
+ appearing twice in the candidate but only once in the baseline is
75
+ reported once.
76
+ """
77
+ diff: list[str] = []
78
+ seen = Counter()
79
+ for line in candidate_lines:
80
+ seen[line] += 1
81
+ if seen[line] > baseline_counts[line]:
82
+ diff.append(line)
83
+ return diff
84
+
85
+
86
+ def find_missing_lines(old_text: str, new_text: str) -> list[str]:
87
+ """Return lines present in `old_text` (outside its `## graphify` section)
88
+ but missing (by multiset) from `new_text`.
89
+
90
+ Order-preserving relative to `old_text`. A line that appears twice in
91
+ `old_text` but only once in `new_text` is reported as missing once.
92
+ """
93
+ return _lines_only_in(_protected_lines(old_text), Counter(new_text.splitlines()))
94
+
95
+
96
+ def run_install_with_guard(
97
+ claude_md_path: Path,
98
+ installer: Callable[[], None],
99
+ canonical_section: str,
100
+ ) -> bool:
101
+ """Run `installer()` against `claude_md_path` under the corruption guard.
102
+
103
+ Returns True if corruption was detected and repaired (snapshot restored
104
+ + canonical section appended), False if the installer's output was left
105
+ as-is because nothing pre-existing was lost.
106
+
107
+ The compare-and-repair check runs even if `installer()` itself raises
108
+ partway through a write (a build error after the `CLAUDE.md` edit already
109
+ landed, for instance) — it happens in a `finally` block, and the original
110
+ exception still propagates once the repair completes. Reads go through
111
+ `_read_or_none` rather than assuming `claude_md_path` exists, since an
112
+ installer can fail before ever creating the file.
113
+ """
114
+ snapshot = _read_or_none(claude_md_path)
115
+ was_repaired = False
116
+ installer_raised = False
117
+
118
+ try:
119
+ installer()
120
+ except BaseException:
121
+ # Bound to THIS call, not read from ambient `sys.exc_info()` inside
122
+ # `finally` below — the ambient form would report whatever exception
123
+ # is being handled if this function is ever called from inside an
124
+ # active `except:` block elsewhere, which is not necessarily
125
+ # installer()'s own.
126
+ installer_raised = True
127
+ raise
128
+ finally:
129
+ try:
130
+ post_install = _read_or_none(claude_md_path)
131
+ missing = find_missing_lines(snapshot or "", post_install or "")
132
+
133
+ if missing:
134
+ was_repaired = True
135
+ repaired = snapshot or ""
136
+ if not repaired.endswith("\n"):
137
+ repaired += "\n"
138
+ if not canonical_section.startswith("\n"):
139
+ repaired += "\n"
140
+ repaired += canonical_section
141
+ claude_md_path.write_text(repaired, encoding="utf-8")
142
+ except Exception:
143
+ # A secondary failure while repairing must never displace
144
+ # installer()'s own in-flight exception — that would mask the
145
+ # real failure with an unrelated one from the repair path itself
146
+ # (e.g. a permission error writing the repair back). If
147
+ # installer() did NOT raise, this secondary failure is the only
148
+ # one there is, so it must propagate normally.
149
+ if installer_raised:
150
+ traceback.print_exc()
151
+ else:
152
+ raise
153
+
154
+ return was_repaired
155
+
156
+
157
+ def find_added_lines(old_text: str, new_text: str) -> list[str]:
158
+ """Return lines present in `new_text` but missing (by multiset) from
159
+ `old_text`. Order-preserving relative to `new_text`.
160
+
161
+ Unlike `find_missing_lines`, this does NOT exclude any section — the
162
+ zero-tolerance contract this serves (see `run_install_reverting_unexpected_writes`
163
+ and the module docstring) tolerates no section at all, so excluding a
164
+ `## graphify` body here would under-report a genuine addition landing
165
+ inside one. Not a strict mirror of `find_missing_lines` for that reason;
166
+ both share their multiset-diff logic via `_lines_only_in`.
167
+ """
168
+ return _lines_only_in(new_text.splitlines(), Counter(old_text.splitlines()))
169
+
170
+
171
+ def _read_or_none(path: Path) -> str | None:
172
+ """Read `path`'s text, or `None` if it does not exist.
173
+
174
+ A single call rather than a separate `exists()` + `read_text()` pair, so
175
+ there is no window between the two where the file could be removed out
176
+ from under this guard.
177
+ """
178
+ try:
179
+ return path.read_text(encoding="utf-8")
180
+ except FileNotFoundError:
181
+ return None
182
+
183
+
184
+ def run_install_reverting_unexpected_writes(
185
+ claude_md_path: Path,
186
+ installer: Callable[[], None],
187
+ ) -> tuple[bool, list[str]]:
188
+ """Run `installer()` against `claude_md_path`, reverting ANY write it made.
189
+
190
+ No shipped caller today — kept deliberately, see module docstring
191
+ (#1670 item 3).
192
+
193
+ Unlike `run_install_with_guard`, which expects and tolerates changes
194
+ scoped to one known section, this treats `claude_md_path` as a file the
195
+ installer must leave completely untouched. If `installer()` changed it at
196
+ all (added or removed lines, or created/deleted the file), the pre-run
197
+ state is restored — the file is rewritten to its snapshot, or deleted if
198
+ it did not exist beforehand.
199
+
200
+ Returns `(reverted, added)`: `reverted` is True iff anything changed and
201
+ was undone. `added` lists any lines the installer had added — it is empty
202
+ both when nothing changed AND when the installer only removed lines, so
203
+ callers MUST branch on `reverted`, never on `bool(added)`, to decide
204
+ whether anything happened (a deletion-only write still needs reporting).
205
+
206
+ The revert runs even if `installer()` itself raises partway through a
207
+ write — the compare-and-restore happens in a `finally` block, and the
208
+ original exception still propagates once it completes.
209
+ """
210
+ snapshot = _read_or_none(claude_md_path)
211
+ reverted = False
212
+ added: list[str] = []
213
+
214
+ try:
215
+ installer()
216
+ finally:
217
+ post_install = _read_or_none(claude_md_path)
218
+ if post_install != snapshot:
219
+ reverted = True
220
+ added = find_added_lines(snapshot or "", post_install or "")
221
+ if snapshot is not None:
222
+ claude_md_path.write_text(snapshot, encoding="utf-8")
223
+ elif post_install is not None:
224
+ claude_md_path.unlink()
225
+
226
+ return reverted, added