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.
- package/LICENSE +21 -0
- package/PORTING.md +134 -0
- package/README.md +207 -0
- package/UPSTREAM.json +64 -0
- package/agents/Explore.md +15 -0
- package/agents/a11y-review.md +118 -0
- package/agents/adr-author.md +70 -0
- package/agents/ai-provenance-review.md +120 -0
- package/agents/angular-reactivity-review.md +95 -0
- package/agents/arch-review.md +135 -0
- package/agents/architect.md +78 -0
- package/agents/autoship-batch-proposer.md +69 -0
- package/agents/claude-setup-review.md +136 -0
- package/agents/codebase-recon.md +184 -0
- package/agents/component-architecture-review.md +119 -0
- package/agents/concurrency-review.md +109 -0
- package/agents/correctness-review.md +290 -0
- package/agents/data-flow-tracer.md +120 -0
- package/agents/doc-review.md +165 -0
- package/agents/domain-review.md +136 -0
- package/agents/general-purpose.md +10 -0
- package/agents/gherkin-quality-critic.md +113 -0
- package/agents/js-fp-review.md +114 -0
- package/agents/mutation-kill.md +684 -0
- package/agents/naming-review.md +142 -0
- package/agents/orchestrator.md +339 -0
- package/agents/performance-review.md +105 -0
- package/agents/plan-review-acceptance.md +115 -0
- package/agents/plan-review-design.md +90 -0
- package/agents/plan-review-parallelization.md +84 -0
- package/agents/plan-review-strategic.md +96 -0
- package/agents/plan-review-ux.md +110 -0
- package/agents/platform-engineer.md +64 -0
- package/agents/product-manager.md +68 -0
- package/agents/progress-guardian.md +79 -0
- package/agents/qa-engineer.md +289 -0
- package/agents/quality-reviewer.md +132 -0
- package/agents/react-reactivity-review.md +102 -0
- package/agents/refactor-opportunity-review.md +128 -0
- package/agents/security-engineer.md +60 -0
- package/agents/security-review.md +218 -0
- package/agents/session-analysis.md +95 -0
- package/agents/software-engineer.md +105 -0
- package/agents/spec-compliance-review.md +100 -0
- package/agents/spec-reviewer.md +114 -0
- package/agents/structure-review.md +146 -0
- package/agents/tech-writer.md +84 -0
- package/agents/test-review.md +246 -0
- package/agents/test-smell-review.md +188 -0
- package/agents/token-efficiency-review.md +139 -0
- package/agents/ui-ux-designer.md +54 -0
- package/agents/vue-reactivity-review.md +95 -0
- package/bin/__pycache__/claudecpython-314.pyc +0 -0
- package/bin/claude +258 -0
- package/docs/upstream/.pages +1 -0
- package/docs/upstream/CHANGELOG.md +2586 -0
- package/docs/upstream/README.md +155 -0
- package/docs/upstream/agent-architecture.md +214 -0
- package/docs/upstream/agent_info.md +187 -0
- package/docs/upstream/artifact-migration.md +124 -0
- package/docs/upstream/code-intelligence-nudge.md +149 -0
- package/docs/upstream/code-review-process.md +294 -0
- package/docs/upstream/concurrent-use.md +73 -0
- package/docs/upstream/context-management.md +111 -0
- package/docs/upstream/developer-notes.md +280 -0
- package/docs/upstream/diagrams/architecture-overview.svg +101 -0
- package/docs/upstream/diagrams/review-dispatch.svg +139 -0
- package/docs/upstream/diagrams/team-agents.svg +128 -0
- package/docs/upstream/diagrams/test-improve-flow.svg +166 -0
- package/docs/upstream/diagrams/workflow-linear.svg +66 -0
- package/docs/upstream/diagrams/workflow-three-phase.svg +200 -0
- package/docs/upstream/eval-maintenance.md +95 -0
- package/docs/upstream/eval-running-guide.md +147 -0
- package/docs/upstream/eval-system.md +291 -0
- package/docs/upstream/session-review-oss-complements.md +75 -0
- package/docs/upstream/session-review.md +212 -0
- package/docs/upstream/skills.md +188 -0
- package/docs/upstream/team-structure.md +21 -0
- package/docs/upstream/telemetry-ci-access.md +129 -0
- package/docs/upstream/telemetry-repo-security.md +120 -0
- package/docs/upstream/test-evaluation.md +277 -0
- package/docs/upstream/test-improve.md +154 -0
- package/docs/upstream/triage-workflow.md +282 -0
- package/docs/upstream/workflows.md +289 -0
- package/extensions/dev-team/index.ts +539 -0
- package/extensions/dev-team/lib/agents.ts +272 -0
- package/extensions/dev-team/lib/ai-credits.ts +92 -0
- package/extensions/dev-team/lib/autocompact.ts +81 -0
- package/extensions/dev-team/lib/child-run.ts +102 -0
- package/extensions/dev-team/lib/config.ts +236 -0
- package/extensions/dev-team/lib/gh-command.ts +103 -0
- package/extensions/dev-team/lib/github-style.ts +307 -0
- package/extensions/dev-team/lib/hooks.ts +350 -0
- package/extensions/dev-team/lib/metrics.ts +115 -0
- package/extensions/dev-team/lib/safe-read.ts +49 -0
- package/extensions/dev-team/lib/session-files.ts +57 -0
- package/extensions/dev-team/lib/session-spend.ts +123 -0
- package/extensions/dev-team/lib/shell-scan.ts +205 -0
- package/extensions/dev-team/lib/skills.ts +213 -0
- package/extensions/dev-team/lib/subagent-render.ts +245 -0
- package/extensions/dev-team/lib/subagent-types.ts +164 -0
- package/extensions/dev-team/lib/subagent.ts +596 -0
- package/extensions/dev-team/lib/terminal-text.ts +54 -0
- package/extensions/dev-team/lib/tools-misc.ts +152 -0
- package/extensions/dev-team/lib/transcript.ts +110 -0
- package/extensions/dev-team/lib/trust.ts +52 -0
- package/extensions/dev-team/lib/usage-breakdown.ts +176 -0
- package/extensions/dev-team/lib/usage-chart.ts +153 -0
- package/extensions/dev-team/lib/usage-command.ts +107 -0
- package/extensions/dev-team/lib/usage-history.ts +203 -0
- package/extensions/dev-team/lib/usage-render.ts +225 -0
- package/extensions/dev-team/lib/usage-split-bar.ts +127 -0
- package/extensions/dev-team/lib/usage-state.ts +116 -0
- package/extensions/dev-team/lib/usage-text.ts +159 -0
- package/extensions/dev-team/lib/usage-view.ts +109 -0
- package/hooks/__pycache__/refactor_test_freeze_guard.cpython-314.pyc +0 -0
- package/hooks/agent_dispatch_ledger.py +190 -0
- package/hooks/autocompact_setup_nudge.py +99 -0
- package/hooks/bash_retry_guard.py +228 -0
- package/hooks/boundary_events_write_guard.py +352 -0
- package/hooks/code_intelligence_nudge.py +293 -0
- package/hooks/code_intelligence_turn_mark.py +317 -0
- package/hooks/codegraph_bootstrap.py +139 -0
- package/hooks/contract_version_guard.py +362 -0
- package/hooks/cost_meter.py +106 -0
- package/hooks/destructive-commands.json +62 -0
- package/hooks/destructive_guard.py +477 -0
- package/hooks/eval_compliance_check.py +440 -0
- package/hooks/guards.json +17 -0
- package/hooks/hooks.json +323 -0
- package/hooks/internal_double_gate.py +296 -0
- package/hooks/js_fp_review.py +212 -0
- package/hooks/knowledge_index.py +119 -0
- package/hooks/lib/__pycache__/artifact_paths.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/atomic_state.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/autocompact_config.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/boundary_events.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/doc_classification.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/gh_pr_create_detect.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/git_safe_diff.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/instrument_log.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/metrics_query.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/plugin_version.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/pre_commit_doc_classifier.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/review_agent_registry.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/review_gate_corroboration.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/review_gate_hash.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/review_verdicts.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/stdin_json.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/stryker_invocation.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/telemetry_consent.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/test_file_classify.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/token_efficiency_limits.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/verify_guard_state.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/xunit_v3_operator_gate.cpython-314.pyc +0 -0
- package/hooks/lib/agent_skill_hints.py +74 -0
- package/hooks/lib/artifact_paths.py +263 -0
- package/hooks/lib/atomic_state.py +557 -0
- package/hooks/lib/autocompact_config.py +103 -0
- package/hooks/lib/autoship_log.py +106 -0
- package/hooks/lib/banned_scripts_policy.py +51 -0
- package/hooks/lib/boundary_events.py +436 -0
- package/hooks/lib/build_knowledge_index.py +504 -0
- package/hooks/lib/build_skills_index.py +361 -0
- package/hooks/lib/build_state.py +116 -0
- package/hooks/lib/classify_ship_outcome.py +126 -0
- package/hooks/lib/config_changelog_schema.py +115 -0
- package/hooks/lib/cost_meter.py +955 -0
- package/hooks/lib/doc_classification.py +116 -0
- package/hooks/lib/gh_pr_create_detect.py +136 -0
- package/hooks/lib/git_safe_diff.py +123 -0
- package/hooks/lib/instrument_log.py +66 -0
- package/hooks/lib/iteration_journal_gate.py +197 -0
- package/hooks/lib/knowledge_index_paths.py +88 -0
- package/hooks/lib/mcp_json_repowise.py +177 -0
- package/hooks/lib/metrics_query.py +202 -0
- package/hooks/lib/minimal_yaml.py +434 -0
- package/hooks/lib/plugin_version.py +142 -0
- package/hooks/lib/pre_commit_detect.py +537 -0
- package/hooks/lib/pre_commit_doc_classifier.py +126 -0
- package/hooks/lib/pricing.py +118 -0
- package/hooks/lib/report_pdf.py +371 -0
- package/hooks/lib/review_agent_registry.py +142 -0
- package/hooks/lib/review_dispatch_ledger.py +101 -0
- package/hooks/lib/review_gate_corroboration.py +521 -0
- package/hooks/lib/review_gate_hash.py +252 -0
- package/hooks/lib/review_gate_normalized_hash.py +1115 -0
- package/hooks/lib/review_verdicts.py +301 -0
- package/hooks/lib/run_report.py +160 -0
- package/hooks/lib/skill_categories.yaml +125 -0
- package/hooks/lib/stdin_json.py +57 -0
- package/hooks/lib/stryker_invocation.py +102 -0
- package/hooks/lib/telemetry_consent.py +41 -0
- package/hooks/lib/telemetry_report.py +108 -0
- package/hooks/lib/test_file_classify.py +160 -0
- package/hooks/lib/token_efficiency_limits.py +51 -0
- package/hooks/lib/turn_identity.py +77 -0
- package/hooks/lib/verify_guard_state.py +110 -0
- package/hooks/lib/workflow_state.py +206 -0
- package/hooks/lib/xunit_v3_operator_gate.py +596 -0
- package/hooks/mcp_json_repowise_nudge.py +74 -0
- package/hooks/mutation_adapters/__init__.py +7 -0
- package/hooks/mutation_adapters/__pycache__/__init__.cpython-314.pyc +0 -0
- package/hooks/mutation_adapters/__pycache__/lib.cpython-314.pyc +0 -0
- package/hooks/mutation_adapters/__pycache__/mutmut.cpython-314.pyc +0 -0
- package/hooks/mutation_adapters/__pycache__/pitest.cpython-314.pyc +0 -0
- package/hooks/mutation_adapters/__pycache__/stryker.cpython-314.pyc +0 -0
- package/hooks/mutation_adapters/__pycache__/stryker_net.cpython-314.pyc +0 -0
- package/hooks/mutation_adapters/lib.py +478 -0
- package/hooks/mutation_adapters/mutmut.py +188 -0
- package/hooks/mutation_adapters/pitest.py +266 -0
- package/hooks/mutation_adapters/stryker.py +157 -0
- package/hooks/mutation_adapters/stryker_net.py +264 -0
- package/hooks/mutation_gate.py +193 -0
- package/hooks/mutation_testing_smoke_gate.py +371 -0
- package/hooks/pending_review_notify.py +121 -0
- package/hooks/phase_marker.py +138 -0
- package/hooks/post_compact_state_reinject.py +180 -0
- package/hooks/post_format.py +115 -0
- package/hooks/pre_commit_knowledge_index.py +128 -0
- package/hooks/pre_commit_review.py +66 -0
- package/hooks/pre_pr_review.py +694 -0
- package/hooks/pre_tool_guard.py +405 -0
- package/hooks/py.sh +73 -0
- package/hooks/refactor-bash-write-patterns.json +29 -0
- package/hooks/refactor_test_bash_guard.py +253 -0
- package/hooks/refactor_test_freeze_guard.py +139 -0
- package/hooks/refactor_test_revert_guard.py +186 -0
- package/hooks/repo_review_nudge.py +287 -0
- package/hooks/review_verdict_recorder.py +464 -0
- package/hooks/scan_bash_command_for_banned_scripts.py +428 -0
- package/hooks/scan_worktree_for_banned_scripts.py +238 -0
- package/hooks/session_learning_trigger.py +248 -0
- package/hooks/skills_index.py +126 -0
- package/hooks/stryker_xunit_shim_guard.py +571 -0
- package/hooks/subagent_completion_guard.py +309 -0
- package/hooks/subagent_skill_context.py +139 -0
- package/hooks/task_completion_metrics.py +216 -0
- package/hooks/tdd_guard.py +229 -0
- package/hooks/telemetry.py +341 -0
- package/hooks/token_efficiency_review.py +194 -0
- package/hooks/verify_guard.py +183 -0
- package/hooks/verify_guard_edit_marker.py +73 -0
- package/hooks/version_check.py +173 -0
- package/knowledge/accepted-risks-schema.md +98 -0
- package/knowledge/adr-decision-criteria.md +64 -0
- package/knowledge/adversarial-review-protocol.md +139 -0
- package/knowledge/agent-registry.md +228 -0
- package/knowledge/agent-review-methodology.md +80 -0
- package/knowledge/ai-friendly-repo-guidelines.md +67 -0
- package/knowledge/architecture-assessment.md +96 -0
- package/knowledge/artifact-lifecycle.md +57 -0
- package/knowledge/cd-maturity-model.md +82 -0
- package/knowledge/cd-test-architecture.md +190 -0
- package/knowledge/ci-cd-file-scope.md +24 -0
- package/knowledge/codegraph-vs-graphify.md +192 -0
- package/knowledge/component-test-patterns.md +139 -0
- package/knowledge/database-change-management.md +80 -0
- package/knowledge/database-test-patterns.md +79 -0
- package/knowledge/decision-defaults.md +88 -0
- package/knowledge/dependency-breaking-techniques.md +116 -0
- package/knowledge/deployment-pipeline.md +86 -0
- package/knowledge/design-smells.md +122 -0
- package/knowledge/directory-enumeration.md +38 -0
- package/knowledge/domain-modeling.md +123 -0
- package/knowledge/evidence-bundle.md +90 -0
- package/knowledge/exploratory-testing-field-guide.md +122 -0
- package/knowledge/failure-routing.md +28 -0
- package/knowledge/fixture-construction.md +56 -0
- package/knowledge/frontend-component-architecture.md +139 -0
- package/knowledge/gherkin-quality-review-dispatch.md +135 -0
- package/knowledge/index.json +6766 -0
- package/knowledge/internal-collaborator-doubling.md +101 -0
- package/knowledge/legacy-test-strategy.md +71 -0
- package/knowledge/long-run-waiting.md +66 -0
- package/knowledge/microservice-testing.md +71 -0
- package/knowledge/model-pricing.json +23 -0
- package/knowledge/mutation-score-formulas.md +60 -0
- package/knowledge/object-calisthenics.md +147 -0
- package/knowledge/oracle-provenance.md +94 -0
- package/knowledge/orchestrator-script-implementation.md +185 -0
- package/knowledge/owasp-detection.md +148 -0
- package/knowledge/plan-review-rubric.md +56 -0
- package/knowledge/proxy-connectivity.md +62 -0
- package/knowledge/reactive-effect-patterns.md +73 -0
- package/knowledge/recon-inventory-excludes.txt +32 -0
- package/knowledge/references/bdd-value-guide.md +61 -0
- package/knowledge/references/csharp-http-client-testing.md +264 -0
- package/knowledge/release-strategies.md +74 -0
- package/knowledge/report-output-location.md +117 -0
- package/knowledge/report-pdf-integration.md +63 -0
- package/knowledge/report-print.css +129 -0
- package/knowledge/report-template.md +114 -0
- package/knowledge/report-to-pdf.md +69 -0
- package/knowledge/request-processing-flow.md +63 -0
- package/knowledge/result-verification.md +52 -0
- package/knowledge/review-agent-output-contract.md +121 -0
- package/knowledge/review-lens-classification.md +113 -0
- package/knowledge/review-rubric.md +62 -0
- package/knowledge/review-template.md +104 -0
- package/knowledge/rule-fixtures/A02.insecure-random-js/negative.js +1 -0
- package/knowledge/rule-fixtures/A02.insecure-random-js/positive.js +1 -0
- package/knowledge/rule-fixtures/A02.weak-hashing-md5/negative.py +1 -0
- package/knowledge/rule-fixtures/A02.weak-hashing-md5/positive.py +1 -0
- package/knowledge/rule-fixtures/A03.command-injection/negative.js +1 -0
- package/knowledge/rule-fixtures/A03.command-injection/positive.js +1 -0
- package/knowledge/rule-fixtures/A03.sql-injection/negative.js +1 -0
- package/knowledge/rule-fixtures/A03.sql-injection/positive.js +1 -0
- package/knowledge/rule-fixtures/A03.xss-innerhtml/negative.js +1 -0
- package/knowledge/rule-fixtures/A03.xss-innerhtml/positive.js +1 -0
- package/knowledge/rule-fixtures/A05.cors-wildcard/negative.js +1 -0
- package/knowledge/rule-fixtures/A05.cors-wildcard/positive.js +1 -0
- package/knowledge/rule-fixtures/A05.default-credentials/negative.js +1 -0
- package/knowledge/rule-fixtures/A05.default-credentials/positive.js +1 -0
- package/knowledge/rule-fixtures/A07.jwt-alg-none/negative.js +1 -0
- package/knowledge/rule-fixtures/A07.jwt-alg-none/positive.js +1 -0
- package/knowledge/rule-fixtures/A08.binary-formatter/negative.cs +1 -0
- package/knowledge/rule-fixtures/A08.binary-formatter/positive.cs +1 -0
- package/knowledge/rule-fixtures/A08.js-eval/negative.js +1 -0
- package/knowledge/rule-fixtures/A08.js-eval/positive.js +1 -0
- package/knowledge/rule-fixtures/A08.object-input-stream/negative.java +1 -0
- package/knowledge/rule-fixtures/A08.object-input-stream/positive.java +1 -0
- package/knowledge/schemas/disposition-register-v1.json +65 -0
- package/knowledge/schemas/recon-envelope-v1.json +198 -0
- package/knowledge/schemas/unified-finding-v1.json +72 -0
- package/knowledge/security-primitives-contract.md +301 -0
- package/knowledge/security-review-rule-map.yaml +107 -0
- package/knowledge/skills-registry.md +72 -0
- package/knowledge/task-size-classifier.md +103 -0
- package/knowledge/telemetry-schema.md +881 -0
- package/knowledge/test-automation-maturity.md +56 -0
- package/knowledge/test-automation-principles.md +71 -0
- package/knowledge/test-cadence-tradeoffs.md +68 -0
- package/knowledge/test-doubles.md +105 -0
- package/knowledge/test-file-indicators.md +22 -0
- package/knowledge/test-layer-gates.md +35 -0
- package/knowledge/test-matrix-examples/django-batch.md +24 -0
- package/knowledge/test-matrix-examples/dotnet-grpc-fronting-api.md +90 -0
- package/knowledge/test-matrix-examples/dotnet-http-consumer.md +131 -0
- package/knowledge/test-matrix-examples/react-node-spa.md +24 -0
- package/knowledge/test-matrix-examples/spring-boot-service.md +25 -0
- package/knowledge/test-matrix-examples/ssr-htmx.md +24 -0
- package/knowledge/test-organization.md +70 -0
- package/knowledge/test-pyramid.md +84 -0
- package/knowledge/test-refactoring.md +67 -0
- package/knowledge/test-review-division-of-labor.md +85 -0
- package/knowledge/test-smells.md +80 -0
- package/knowledge/test-stack-profiles/bdd-frameworks.md +235 -0
- package/knowledge/test-stack-profiles/django.md +13 -0
- package/knowledge/test-stack-profiles/dotnet.md +18 -0
- package/knowledge/test-stack-profiles/go.md +16 -0
- package/knowledge/test-stack-profiles/node.md +16 -0
- package/knowledge/test-stack-profiles/react.md +12 -0
- package/knowledge/test-stack-profiles/spring-boot.md +16 -0
- package/knowledge/test-stack-profiles/ssr-htmx.md +14 -0
- package/knowledge/test-stack-profiles/vue.md +12 -0
- package/knowledge/test-strategy.md +70 -0
- package/knowledge/testability-patterns.md +240 -0
- package/knowledge/testing-quadrants.md +44 -0
- package/knowledge/testing-techniques/approval.md +15 -0
- package/knowledge/testing-techniques/chaos.md +17 -0
- package/knowledge/testing-techniques/fuzz.md +15 -0
- package/knowledge/testing-techniques/property-based.md +15 -0
- package/knowledge/testing-techniques/schema-validation.md +15 -0
- package/knowledge/testing-techniques/screenshot.md +15 -0
- package/knowledge/three-phase-workflow.md +198 -0
- package/knowledge/value-patterns.md +55 -0
- package/knowledge/verification-mode.md +116 -0
- package/knowledge/virtual-service-libraries.md +75 -0
- package/knowledge/wave-consolidation-guidance.md +21 -0
- package/overrides/agents/Explore.md +15 -0
- package/overrides/agents/general-purpose.md +10 -0
- package/overrides/notes/autoship.md +6 -0
- package/overrides/notes/issues-from-assessment.md +3 -0
- package/overrides/notes/issues-from-plan.md +3 -0
- package/overrides/notes/mutation-night-watch.md +3 -0
- package/overrides/notes/mutation-testing.md +3 -0
- package/overrides/notes/pr.md +7 -0
- package/overrides/notes/project-init.md +6 -0
- package/overrides/notes/setup.md +13 -0
- package/overrides/notes/specs.md +3 -0
- package/overrides/skills/headless-run/SKILL.md +45 -0
- package/overrides/skills/upgrade/SKILL.md +30 -0
- package/overrides/skills/version/SKILL.md +25 -0
- package/package.json +36 -0
- package/scripts/authoring_digest.py +93 -0
- package/scripts/autoship_discover.py +121 -0
- package/scripts/autoship_group.py +409 -0
- package/scripts/autoship_proposals.py +494 -0
- package/scripts/autoship_queue.py +291 -0
- package/scripts/autoship_reclaim.py +495 -0
- package/scripts/build_jobs.py +108 -0
- package/scripts/build_rollback_point.py +240 -0
- package/scripts/build_slice_scope.py +157 -0
- package/scripts/build_wave.py +109 -0
- package/scripts/build_wave_reconcile.py +252 -0
- package/scripts/build_worktree_baseref.py +113 -0
- package/scripts/check_agent_scope.py +117 -0
- package/scripts/check_agent_tool_mapping.py +213 -0
- package/scripts/check_review_agent_mcp_tools.py +317 -0
- package/scripts/check_security_assessment_mcp_tools.py +165 -0
- package/scripts/checkpoint_abort.py +502 -0
- package/scripts/claude_setup_review.py +438 -0
- package/scripts/codebase_recon.py +556 -0
- package/scripts/coverage_config.py +623 -0
- package/scripts/coverage_delta_steering.py +330 -0
- package/scripts/coverage_discovery_dotnet.py +315 -0
- package/scripts/coverage_discovery_java.py +742 -0
- package/scripts/coverage_discovery_js.py +546 -0
- package/scripts/coverage_gap_ranking.py +556 -0
- package/scripts/coverage_readiness.py +455 -0
- package/scripts/coverage_report_parse.py +521 -0
- package/scripts/detect_bdd_convention.py +252 -0
- package/scripts/eval_ablation.py +376 -0
- package/scripts/gherkin_analysis_coverage_gate.py +306 -0
- package/scripts/gherkin_cross_feature_duplicate_titles_gate.py +173 -0
- package/scripts/gherkin_effectiveness_rollup.py +238 -0
- package/scripts/gherkin_failure_path_gate.py +206 -0
- package/scripts/gherkin_feature_merge.py +720 -0
- package/scripts/gherkin_stub_gate.py +163 -0
- package/scripts/gherkin_stub_merge.py +479 -0
- package/scripts/git_origin_host.py +88 -0
- package/scripts/install-java-static-analysis.py +110 -0
- package/scripts/issue_deps.py +74 -0
- package/scripts/lib/_bdd_markers.py +28 -0
- package/scripts/lib/_gherkin_text.py +93 -0
- package/scripts/lib/_vendored_tree.py +70 -0
- package/scripts/lib/autoship_state.py +397 -0
- package/scripts/lib/claude_md_guard.py +226 -0
- package/scripts/lib/deterministic_recon.py +446 -0
- package/scripts/lib/mcp_tool_grants.py +211 -0
- package/scripts/lib/plan_parse.py +386 -0
- package/scripts/lib/review_result.py +84 -0
- package/scripts/lib/review_roster.py +86 -0
- package/scripts/lib/session_log/__init__.py +34 -0
- package/scripts/lib/session_log/__pycache__/__init__.cpython-314.pyc +0 -0
- package/scripts/lib/session_log/__pycache__/records.cpython-314.pyc +0 -0
- package/scripts/lib/session_log/classify.py +231 -0
- package/scripts/lib/session_log/corrections.py +194 -0
- package/scripts/lib/session_log/discovery.py +108 -0
- package/scripts/lib/session_log/records.py +218 -0
- package/scripts/lib/session_log/redact.py +76 -0
- package/scripts/lib/session_log/signals.py +373 -0
- package/scripts/lib/session_report_downstream.py +614 -0
- package/scripts/lib/session_report_maintainer.py +1273 -0
- package/scripts/lib/session_report_shared.py +262 -0
- package/scripts/lib/settings_hook_guard.py +157 -0
- package/scripts/lib/slug.py +33 -0
- package/scripts/lib/stub_extractors/__init__.py +82 -0
- package/scripts/lib/stub_extractors/_common.py +328 -0
- package/scripts/lib/stub_extractors/csharp.py +19 -0
- package/scripts/lib/stub_extractors/go.py +173 -0
- package/scripts/lib/stub_extractors/java.py +18 -0
- package/scripts/lib/stub_extractors/jsts.py +126 -0
- package/scripts/mutation_stack_sections.py +149 -0
- package/scripts/mutation_yield_steering.py +345 -0
- package/scripts/orchestrator.py +895 -0
- package/scripts/plan_gherkin_export.py +227 -0
- package/scripts/plan_waves.py +208 -0
- package/scripts/pr_close_keyword_lint.py +108 -0
- package/scripts/progress_guardian.py +888 -0
- package/scripts/recon_inventory.py +273 -0
- package/scripts/review_findings_log.py +93 -0
- package/scripts/run_invariants.py +124 -0
- package/scripts/select_lenses.py +640 -0
- package/scripts/session_report.py +486 -0
- package/scripts/set_autocompact_env.py +221 -0
- package/scripts/ship_resume_guard.py +135 -0
- package/scripts/ship_review_gate.py +63 -0
- package/scripts/specs_convention_marker.py +103 -0
- package/scripts/test_improve_resume.py +277 -0
- package/scripts/test_review_mechanics.py +958 -0
- package/scripts/token_efficiency_review.py +322 -0
- package/scripts/verdict_scope.py +285 -0
- package/scripts/verify_gherkin_quality_critic_isolation.py +296 -0
- package/scripts/verify_tier.py +157 -0
- package/skills/adr-tools/SKILL.md +118 -0
- package/skills/agent-readiness/SKILL.md +105 -0
- package/skills/agent-readiness/ai_friendly_analyzers.py +326 -0
- package/skills/agent-readiness/scanner.py +441 -0
- package/skills/agent-readiness/scorecard.yaml +88 -0
- package/skills/api-design/SKILL.md +115 -0
- package/skills/apply-fixes/SKILL.md +171 -0
- package/skills/apply-test-doubles/SKILL.md +321 -0
- package/skills/artifact-lifecycle/SKILL.md +127 -0
- package/skills/autoship/SKILL.md +1124 -0
- package/skills/benchmark/SKILL.md +105 -0
- package/skills/branch-workflow/SKILL.md +89 -0
- package/skills/browse/SKILL.md +184 -0
- package/skills/browser-testing/SKILL.md +62 -0
- package/skills/browser-testing/references/playwright-patterns.md +216 -0
- package/skills/build/SKILL.md +422 -0
- package/skills/build/references/static-self-heal.md +245 -0
- package/skills/careful/SKILL.md +72 -0
- package/skills/cd-test-architecture/SKILL.md +371 -0
- package/skills/ci-debugging/SKILL.md +105 -0
- package/skills/co-evolution-audit/SKILL.md +269 -0
- package/skills/code-review/SKILL.md +1015 -0
- package/skills/code-review/examples/aggregated-sample.json +56 -0
- package/skills/code-review/examples/sample-report.md +41 -0
- package/skills/code-review/output-format.md +478 -0
- package/skills/code-review/scripts/activation.py +86 -0
- package/skills/code-review/scripts/change_impact.py +357 -0
- package/skills/code-review/scripts/change_shape.py +372 -0
- package/skills/code-review/scripts/change_size.py +212 -0
- package/skills/code-review/scripts/changed_file_list.py +141 -0
- package/skills/code-review/scripts/closing_pass.py +187 -0
- package/skills/code-review/scripts/consolidate.py +277 -0
- package/skills/code-review/scripts/contract_failure_report.py +185 -0
- package/skills/code-review/scripts/dispatch_reconcile.py +66 -0
- package/skills/code-review/scripts/dispatch_waves.py +164 -0
- package/skills/code-review/scripts/finding_signature.py +446 -0
- package/skills/code-review/scripts/ledger.py +283 -0
- package/skills/code-review/scripts/partition.py +169 -0
- package/skills/code-review/scripts/render_tiered_findings.py +274 -0
- package/skills/code-review/scripts/repo_invariants.py +1066 -0
- package/skills/code-review/scripts/review_context_pack.py +306 -0
- package/skills/code-review/scripts/review_round_log.py +345 -0
- package/skills/code-review/scripts/review_value_coverage.py +297 -0
- package/skills/code-review/scripts/validate_review_output.py +467 -0
- package/skills/code-review/sliced-mode.md +205 -0
- package/skills/competitive-analysis/SKILL.md +191 -0
- package/skills/context-loading-protocol/SKILL.md +157 -0
- package/skills/continue/SKILL.md +90 -0
- package/skills/cost-report/SKILL.md +178 -0
- package/skills/coverage-baseline/SKILL.md +335 -0
- package/skills/coverage-baseline/references/multi-project-discovery.md +202 -0
- package/skills/coverage-delta/SKILL.md +181 -0
- package/skills/coverage-delta/references/mutation-gate.md +70 -0
- package/skills/design-doc/SKILL.md +95 -0
- package/skills/design-interrogation/SKILL.md +89 -0
- package/skills/design-it-twice/SKILL.md +91 -0
- package/skills/docker-image-audit/SKILL.md +108 -0
- package/skills/docker-image-audit/references/install-guide.md +64 -0
- package/skills/docker-image-audit/references/report-template.md +73 -0
- package/skills/docker-image-create/SKILL.md +185 -0
- package/skills/domain-analysis/SKILL.md +183 -0
- package/skills/domain-driven-design/SKILL.md +194 -0
- package/skills/exploratory-testing/SKILL.md +108 -0
- package/skills/explore/SKILL.md +51 -0
- package/skills/farley-score/SKILL.md +165 -0
- package/skills/feature-file-validation/SKILL.md +78 -0
- package/skills/feature-file-validation/references/validation-rules.md +115 -0
- package/skills/feedback-learning/SKILL.md +414 -0
- package/skills/fix/SKILL.md +450 -0
- package/skills/freeze/SKILL.md +68 -0
- package/skills/frontend-architecture/SKILL.md +113 -0
- package/skills/gherkin-derive/SKILL.md +630 -0
- package/skills/gherkin-public/SKILL.md +266 -0
- package/skills/governance-compliance/SKILL.md +150 -0
- package/skills/guard/SKILL.md +75 -0
- package/skills/handoff/SKILL.md +139 -0
- package/skills/handoff/references/summary-templates.md +242 -0
- package/skills/harness-audit/SKILL.md +751 -0
- package/skills/harness-audit/scripts/lesson_validate.py +386 -0
- package/skills/harness-audit/scripts/redundancy_criterion.py +188 -0
- package/skills/headless-run/SKILL.md +45 -0
- package/skills/headless-run/scripts/isolated_dispatch.py +381 -0
- package/skills/help/SKILL.md +72 -0
- package/skills/hexagonal-architecture/SKILL.md +85 -0
- package/skills/human-oversight-protocol/SKILL.md +224 -0
- package/skills/issues-from-assessment/SKILL.md +223 -0
- package/skills/issues-from-plan/SKILL.md +133 -0
- package/skills/legacy-code/SKILL.md +132 -0
- package/skills/mermaid-diagramming/SKILL.md +120 -0
- package/skills/mutation-night-watch/SKILL.md +154 -0
- package/skills/mutation-night-watch/references/scheduling.md +135 -0
- package/skills/mutation-testing/SKILL.md +396 -0
- package/skills/mutation-testing/references/languages/csharp-stryker-net.md +676 -0
- package/skills/mutation-testing/references/languages/go-go-mutesting.md +95 -0
- package/skills/mutation-testing/references/languages/java-pitest.md +77 -0
- package/skills/mutation-testing/references/languages/javascript-stryker.md +188 -0
- package/skills/mutation-testing/references/languages/python-mutmut.md +97 -0
- package/skills/mutation-testing/references/time-estimation.md +34 -0
- package/skills/mutation-testing/references/tool-detection.md +15 -0
- package/skills/mutation-testing/references/workflow-callers.md +23 -0
- package/skills/mutation-testing/scripts/__pycache__/xunit_v3_feature_detector.cpython-314.pyc +0 -0
- package/skills/mutation-testing/scripts/csharp_stryker_net_slice_runner.py +635 -0
- package/skills/mutation-testing/scripts/csharp_stryker_net_status_loop.py +525 -0
- package/skills/mutation-testing/scripts/csharp_stryker_net_wrapper.py +681 -0
- package/skills/mutation-testing/scripts/mutation_baseline_reuse.py +292 -0
- package/skills/mutation-testing/scripts/mutation_exclude_policy.py +268 -0
- package/skills/mutation-testing/scripts/mutation_feasibility_gate.py +463 -0
- package/skills/mutation-testing/scripts/mutation_kill_headless.py +331 -0
- package/skills/mutation-testing/scripts/mutation_kill_insert.py +199 -0
- package/skills/mutation-testing/scripts/mutation_kill_insert_python.py +150 -0
- package/skills/mutation-testing/scripts/mutation_kill_loop.py +869 -0
- package/skills/mutation-testing/scripts/mutation_kill_loop_python.py +949 -0
- package/skills/mutation-testing/scripts/mutation_kill_retry.py +592 -0
- package/skills/mutation-testing/scripts/mutation_kill_shared.py +620 -0
- package/skills/mutation-testing/scripts/mutation_nightwatch.py +462 -0
- package/skills/mutation-testing/scripts/mutation_nightwatch_stacks.py +425 -0
- package/skills/mutation-testing/scripts/mutation_report.py +743 -0
- package/skills/mutation-testing/scripts/mutation_report_cli.py +175 -0
- package/skills/mutation-testing/scripts/mutation_safety_gate.py +69 -0
- package/skills/mutation-testing/scripts/stryker_shard_pipeline.py +847 -0
- package/skills/mutation-testing/scripts/stryker_shard_setup.py +440 -0
- package/skills/mutation-testing/scripts/stryker_timeout_retry.py +142 -0
- package/skills/mutation-testing/scripts/xunit_v3_feature_detector.py +341 -0
- package/skills/performance-benchmark/SKILL.md +174 -0
- package/skills/performance-benchmark/examples/report-format.md +43 -0
- package/skills/performance-benchmark/references/benchmark-script.md +169 -0
- package/skills/performance-metrics/SKILL.md +265 -0
- package/skills/plan/SKILL.md +199 -0
- package/skills/plan/references/gherkin-persistence.md +43 -0
- package/skills/plan/references/plan-template.md +182 -0
- package/skills/pr/SKILL.md +289 -0
- package/skills/pr/scripts/gate_retry_state.py +368 -0
- package/skills/project-init/README.md +141 -0
- package/skills/project-init/SKILL.md +1197 -0
- package/skills/project-init/evals/evals.json +200 -0
- package/skills/project-init/references/capability-tools.md +55 -0
- package/skills/project-init/references/configs.md +221 -0
- package/skills/property-based-testing/SKILL.md +121 -0
- package/skills/property-based-testing/fixtures/invariant_fixture.py +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/README.md +42 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/LICENSE +21 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/README.md +263 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/cjs/fast-check.d.ts +5165 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/cjs/fast-check.js +12147 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/cjs/package.json +3 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/cjs/types57/fast-check.d.ts +5165 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/fast-check.d.ts +5165 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/fast-check.js +12011 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/rolldown-runtime-D7D4PA-g.js +13 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/types57/fast-check.d.ts +5165 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/package.json +94 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/LICENSE +21 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/README.md +168 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/RandomGenerator-DcXj09Ch.d.ts +14 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformBigInt.d.ts +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformBigInt.js +38 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformFloat32.d.ts +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformFloat32.js +18 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformFloat64.d.ts +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformFloat64.js +22 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformInt.d.ts +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformInt.js +134 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/RandomGenerator-DcXj09Ch.d.ts +14 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformBigInt.d.ts +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformBigInt.js +37 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformFloat32.d.ts +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformFloat32.js +17 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformFloat64.d.ts +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformFloat64.js +21 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformInt.d.ts +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformInt.js +133 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/congruential32.d.ts +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/congruential32.js +44 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/mersenne.d.ts +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/mersenne.js +90 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/xoroshiro128plus.d.ts +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/xoroshiro128plus.js +80 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/xorshift128plus.d.ts +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/xorshift128plus.js +78 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/package.json +3 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/types/JumpableRandomGenerator.d.ts +16 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/types/JumpableRandomGenerator.js +0 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/types/RandomGenerator.d.ts +2 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/types/RandomGenerator.js +0 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/generateN.d.ts +6 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/generateN.js +8 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/purify.d.ts +12 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/purify.js +9 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/skipN.d.ts +6 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/skipN.js +6 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/congruential32.d.ts +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/congruential32.js +46 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/mersenne.d.ts +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/mersenne.js +92 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/xoroshiro128plus.d.ts +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/xoroshiro128plus.js +82 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/xorshift128plus.d.ts +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/xorshift128plus.js +80 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/types/JumpableRandomGenerator.d.ts +16 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/types/JumpableRandomGenerator.js +0 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/types/RandomGenerator.d.ts +2 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/types/RandomGenerator.js +0 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/generateN.d.ts +6 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/generateN.js +9 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/purify.d.ts +12 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/purify.js +10 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/skipN.d.ts +6 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/skipN.js +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/package.json +133 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/package-lock.json +1179 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/package.json +14 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/roundtrip.js +29 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/roundtrip.properties.test.js +16 -0
- package/skills/property-based-testing/fixtures/no_property_fixture.py +10 -0
- package/skills/property-based-testing/fixtures/roundtrip_fixture.py +16 -0
- package/skills/property-based-testing/references/languages/javascript.md +54 -0
- package/skills/property-based-testing/scripts/detect_and_dispatch.py +80 -0
- package/skills/property-based-testing/scripts/hypothesis_scaffold.py +276 -0
- package/skills/proxy-resilience/SKILL.md +84 -0
- package/skills/quality-gate-pipeline/SKILL.md +184 -0
- package/skills/quality-targets-converge/SKILL.md +254 -0
- package/skills/repo-review/SKILL.md +159 -0
- package/skills/report-pdf/SKILL.md +66 -0
- package/skills/review/SKILL.md +47 -0
- package/skills/review-agent/SKILL.md +152 -0
- package/skills/review-summary/SKILL.md +73 -0
- package/skills/run-report/SKILL.md +70 -0
- package/skills/semantic-duplication-scan/SKILL.md +337 -0
- package/skills/semantic-scan/SKILL.md +53 -0
- package/skills/semgrep-analyze/SKILL.md +139 -0
- package/skills/setup/SKILL.md +1122 -0
- package/skills/ship/SKILL.md +240 -0
- package/skills/source-verification/SKILL.md +210 -0
- package/skills/source-verification/scripts/claim_extractor.py +155 -0
- package/skills/specs/.size-baseline.json +4 -0
- package/skills/specs/SKILL.md +243 -0
- package/skills/specs/references/completeness-checklist.md +83 -0
- package/skills/specs/references/extraction.md +58 -0
- package/skills/specs/references/glossary.md +59 -0
- package/skills/specs/references/persistence.md +115 -0
- package/skills/specs/references/predictability-check.md +77 -0
- package/skills/static-analysis-integration/SKILL.md +235 -0
- package/skills/static-analysis-integration/adapters/_envelope.py +26 -0
- package/skills/static-analysis-integration/adapters/jscpd-adapter.py +66 -0
- package/skills/static-analysis-integration/adapters/lizard-adapter.py +81 -0
- package/skills/static-analysis-integration/adapters/mypy-adapter.py +50 -0
- package/skills/static-analysis-integration/adapters/mypy-src-layout.py +93 -0
- package/skills/static-analysis-integration/adapters/security-review-adapter.py +212 -0
- package/skills/static-analysis-integration/maintenance.md +23 -0
- package/skills/static-analysis-integration/references/language-setup.md +228 -0
- package/skills/static-analysis-integration/references/sarif-parser.md +124 -0
- package/skills/static-analysis-integration/references/security-review-adapter.md +118 -0
- package/skills/static-analysis-integration/references/tool-configs.md +617 -0
- package/skills/static-analysis-integration/rulesets/pmd-quickstart.xml +24 -0
- package/skills/stryker-xunit-v2-shim/SKILL.md +274 -0
- package/skills/stryker-xunit-v2-shim/references/shim-howto.md +256 -0
- package/skills/stryker-xunit-v2-shim/scripts/generate_shim.py +143 -0
- package/skills/systematic-debugging/SKILL.md +130 -0
- package/skills/telemetry/SKILL.md +75 -0
- package/skills/test-audit-disable/SKILL.md +129 -0
- package/skills/test-design/SKILL.md +177 -0
- package/skills/test-design/scripts/__pycache__/internal_double_detector.cpython-314.pyc +0 -0
- package/skills/test-design/scripts/internal_double_detector.py +631 -0
- package/skills/test-design-advisor/SKILL.md +166 -0
- package/skills/test-driven-development/SKILL.md +169 -0
- package/skills/test-health/SKILL.md +262 -0
- package/skills/test-improve/SKILL.md +239 -0
- package/skills/test-improve/references/phase-0-approach-contract.md +228 -0
- package/skills/test-improve/references/phase-1-analyze.md +131 -0
- package/skills/test-improve/references/phase-2-baseline.md +121 -0
- package/skills/test-improve/references/phase-3-derive-gherkin.md +53 -0
- package/skills/test-improve/references/phase-4-plan-fixes.md +34 -0
- package/skills/test-improve/references/phase-5-improve.md +215 -0
- package/skills/test-improve/references/phase-6-refactor-decision.md +45 -0
- package/skills/test-improve/references/phase-7-refactor.md +44 -0
- package/skills/test-improve/references/phase-8-validate.md +66 -0
- package/skills/test-improve/references/phase-9-close-out-prompt.md +11 -0
- package/skills/test-improve/references/phase-9-report.md +62 -0
- package/skills/test-improve/references/review-loop.md +92 -0
- package/skills/test-improve/templates/executive-summary.md +123 -0
- package/skills/threat-modeling/SKILL.md +108 -0
- package/skills/triage/SKILL.md +211 -0
- package/skills/ubiquitous-language/SKILL.md +192 -0
- package/skills/ubiquitous-language/scripts/collect_domain_signals.py +300 -0
- package/skills/unfreeze/SKILL.md +37 -0
- package/skills/upgrade/SKILL.md +31 -0
- package/skills/upgrade/scripts/check_version_drift.py +113 -0
- package/skills/upgrade/scripts/enable_autoupdate.py +149 -0
- package/skills/version/SKILL.md +25 -0
- package/sync/__pycache__/sync_upstream.cpython-314.pyc +0 -0
- package/sync/sync_upstream.py +293 -0
- package/templates/ACCEPTED-RISKS.md.tmpl +46 -0
- package/templates/agents/agent-template.md +151 -0
- package/templates/agents/angular-testing.md +66 -0
- package/templates/agents/csharp-quality.md +63 -0
- package/templates/agents/esm-enforcer.md +52 -0
- package/templates/agents/front-end-testing.md +65 -0
- package/templates/agents/go-quality.md +65 -0
- package/templates/agents/python-quality.md +62 -0
- package/templates/agents/react-testing.md +61 -0
- package/templates/agents/ts-enforcer.md +60 -0
- package/templates/agents/twelve-factor-audit.md +49 -0
- package/tools/entropy-check.py +250 -0
- package/tools/model-hash-verify.py +213 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""build_skills_index.py — generate docs/skills.md from the skills' frontmatter.
|
|
3
|
+
|
|
4
|
+
docs/skills.md is the human-readable skills catalog. It used to be hand-edited,
|
|
5
|
+
which drifted: skills were added on disk with no catalog row (14 missing at the
|
|
6
|
+
time this generator was introduced). This builder makes the catalog a derived
|
|
7
|
+
artifact — one row per skills/<name>/SKILL.md (and commands/<name>.md when the
|
|
8
|
+
directory exists), sourced from that file's `name` and `description` frontmatter,
|
|
9
|
+
split into the three sub-types the frontmatter already encodes:
|
|
10
|
+
- user-invocable with argument-hint → slash command, hint in Options column
|
|
11
|
+
- user-invocable without argument-hint → slash command, "no flags — run directly"
|
|
12
|
+
- agent-loaded (user-invocable absent or false) → "agent-loaded — not directly invocable"
|
|
13
|
+
No hand-curation survives in the output, so it can never silently drift.
|
|
14
|
+
|
|
15
|
+
Modes (argv[1]):
|
|
16
|
+
(none) / write rebuild docs/skills.md in place (atomic write)
|
|
17
|
+
--check diff a fresh build against the on-disk file; exit non-zero
|
|
18
|
+
with a unified diff on stderr if they differ. Writes nothing.
|
|
19
|
+
|
|
20
|
+
Flags:
|
|
21
|
+
--plugin-dir <path> Root directory of a plugin (default: two levels above this
|
|
22
|
+
file, i.e. the dev-team plugin). Overrides the default
|
|
23
|
+
SKILLS_DIR, OUTPUT, and CATEGORIES_FILE paths.
|
|
24
|
+
|
|
25
|
+
Env (TEST-ONLY injection seams — lower-level overrides, below --plugin-dir;
|
|
26
|
+
production callers must NOT set these):
|
|
27
|
+
SKILLS_INDEX_SKILLS_DIR override the skills/ corpus root
|
|
28
|
+
SKILLS_INDEX_OUTPUT override the output path
|
|
29
|
+
SKILLS_INDEX_CATEGORIES override the skill_categories.yaml path
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
from __future__ import annotations
|
|
33
|
+
|
|
34
|
+
import argparse
|
|
35
|
+
import difflib
|
|
36
|
+
import os
|
|
37
|
+
import sys
|
|
38
|
+
from pathlib import Path
|
|
39
|
+
|
|
40
|
+
from minimal_yaml import FrontmatterError as _NoMarkersError
|
|
41
|
+
from minimal_yaml import YamlError, extract_frontmatter_block, parse_yaml
|
|
42
|
+
|
|
43
|
+
_SCRIPT_DIR = Path(__file__).resolve().parent
|
|
44
|
+
_DEFAULT_PLUGIN_DIR = _SCRIPT_DIR.parents[1] # lib -> hooks -> dev-team
|
|
45
|
+
_REPO_ROOT = _DEFAULT_PLUGIN_DIR.parents[1] # dev-team -> plugins -> repo root
|
|
46
|
+
_BLOB_BASE = "https://github.com/bdfinst/agentic-dev-team/blob/main"
|
|
47
|
+
|
|
48
|
+
# Options-column sentinel values
|
|
49
|
+
_OPT_NO_FLAGS = "no flags — run directly"
|
|
50
|
+
_OPT_AGENT_LOADED = "agent-loaded — not directly invocable"
|
|
51
|
+
_OPT_UNGROUPED_SECTION = "Ungrouped"
|
|
52
|
+
_OPT_OTHER = "Other"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _resolve_paths(plugin_dir: Path) -> tuple[Path, Path, Path]:
|
|
56
|
+
"""Return (skills_dir, output, categories_file) for a plugin directory.
|
|
57
|
+
|
|
58
|
+
Env vars are lower-level overrides, applied after --plugin-dir so the
|
|
59
|
+
SKILLS_INDEX_* test seam keeps working without modification.
|
|
60
|
+
"""
|
|
61
|
+
skills_dir = Path(
|
|
62
|
+
os.environ.get(
|
|
63
|
+
"SKILLS_INDEX_SKILLS_DIR", plugin_dir / "skills"
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
output = Path(
|
|
67
|
+
os.environ.get(
|
|
68
|
+
"SKILLS_INDEX_OUTPUT", plugin_dir / "docs" / "skills.md"
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
# For categories: env var wins, else <plugin>/hooks/lib/skill_categories.yaml,
|
|
72
|
+
# falling back to the dev-team one when the plugin has none (only when the
|
|
73
|
+
# env var is absent and the plugin-specific file does not exist the caller
|
|
74
|
+
# should let it be missing — _load_categories handles that gracefully).
|
|
75
|
+
cats_default = plugin_dir / "hooks" / "lib" / "skill_categories.yaml"
|
|
76
|
+
categories_file = Path(
|
|
77
|
+
os.environ.get("SKILLS_INDEX_CATEGORIES", cats_default)
|
|
78
|
+
)
|
|
79
|
+
return skills_dir, output, categories_file
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _make_header(plugin_dir: Path) -> str:
|
|
83
|
+
"""Return a header block appropriate for `plugin_dir`.
|
|
84
|
+
|
|
85
|
+
When targeting the default dev-team plugin the header uses the short form
|
|
86
|
+
without --plugin-dir. For any other plugin the header includes the
|
|
87
|
+
relative plugin path so readers know how to regenerate the file.
|
|
88
|
+
"""
|
|
89
|
+
rel = str(plugin_dir.relative_to(Path.cwd())) if plugin_dir != _DEFAULT_PLUGIN_DIR else None
|
|
90
|
+
if rel:
|
|
91
|
+
return (
|
|
92
|
+
"# Skills\n\n"
|
|
93
|
+
"<!-- GENERATED FILE — do not edit by hand.\n"
|
|
94
|
+
f" Rows: each {rel}/skills/<name>/SKILL.md (and {rel}/commands/<name>.md if present).\n"
|
|
95
|
+
f" Grouping: {rel}/skill_categories.yaml (by capability).\n"
|
|
96
|
+
f" Regenerate: python3 plugins/dev-team/hooks/lib/build_skills_index.py --plugin-dir {rel}\n"
|
|
97
|
+
" A CI freshness gate (--check) fails if this file drifts from the skills on disk. -->\n\n"
|
|
98
|
+
"Skills are the unified reusable capability layer in this plugin. "
|
|
99
|
+
"Skills live in `skills/<name>/SKILL.md`; user-invocable commands live "
|
|
100
|
+
"in `commands/<name>.md`. This catalog groups them **by capability** (the "
|
|
101
|
+
"sections below); each row's description is the file's own frontmatter "
|
|
102
|
+
"`description`, verbatim.\n\n"
|
|
103
|
+
"Most skills are **user-invocable** as slash commands — shown as `/name`; run them "
|
|
104
|
+
"directly or let the Orchestrator dispatch them. The rest are **agent-loaded** "
|
|
105
|
+
"knowledge modules — shown as a plain `name` — that agents read for domain expertise.\n"
|
|
106
|
+
)
|
|
107
|
+
return (
|
|
108
|
+
"# Skills\n\n"
|
|
109
|
+
"<!-- GENERATED FILE — do not edit by hand.\n"
|
|
110
|
+
" Rows: each plugins/dev-team/skills/<name>/SKILL.md frontmatter (name, description).\n"
|
|
111
|
+
" Grouping: plugins/dev-team/hooks/lib/skill_categories.yaml (by capability).\n"
|
|
112
|
+
" Regenerate: python3 plugins/dev-team/hooks/lib/build_skills_index.py\n"
|
|
113
|
+
" A CI freshness gate (--check) fails if this file drifts from the skills on disk. -->\n\n"
|
|
114
|
+
"Skills are the unified reusable capability layer in this system. Every skill lives "
|
|
115
|
+
"in `skills/<name>/SKILL.md`. This catalog groups them **by capability** (the "
|
|
116
|
+
"sections below); each row's description is the skill's own frontmatter "
|
|
117
|
+
"`description`, verbatim.\n\n"
|
|
118
|
+
"Most skills are **user-invocable** as slash commands — shown as `/name`; run them "
|
|
119
|
+
"directly or let the Orchestrator dispatch them. The rest are **agent-loaded** "
|
|
120
|
+
"knowledge modules — shown as a plain `name` — that agents read for domain expertise.\n"
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# Keep a module-level constant for the dev-team default (used by tests that
|
|
125
|
+
# import HEADER directly).
|
|
126
|
+
HEADER = _make_header(_DEFAULT_PLUGIN_DIR)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class FrontmatterError(ValueError):
|
|
130
|
+
"""A SKILL.md whose frontmatter can't be parsed — fail loudly, never emit a
|
|
131
|
+
silent empty/miscategorized catalog row."""
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _frontmatter(path: Path) -> dict:
|
|
135
|
+
"""Parse the YAML frontmatter block of a SKILL.md (between the first `---`s)."""
|
|
136
|
+
text = path.read_text(encoding="utf-8")
|
|
137
|
+
try:
|
|
138
|
+
block = extract_frontmatter_block(text)
|
|
139
|
+
except _NoMarkersError as e:
|
|
140
|
+
raise FrontmatterError(f"{path}: {e}") from e
|
|
141
|
+
try:
|
|
142
|
+
data = parse_yaml(block)
|
|
143
|
+
except YamlError as e:
|
|
144
|
+
# Almost always an unquoted scalar with a bare `: ` (e.g. a description
|
|
145
|
+
# like "...agent: this skill..."). Use a `>-` block scalar to fix it.
|
|
146
|
+
raise FrontmatterError(f"{path}: invalid frontmatter YAML: {e}") from e
|
|
147
|
+
if not isinstance(data, dict):
|
|
148
|
+
raise FrontmatterError(f"{path}: frontmatter is not a mapping")
|
|
149
|
+
return data
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _cell(text: str) -> str:
|
|
153
|
+
"""Collapse a description to one table-safe line."""
|
|
154
|
+
return " ".join(str(text).split()).replace("|", "\\|")
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _source_link(label: str, target: Path, fallback_rel: str) -> str:
|
|
158
|
+
"""Link `label` to `target`'s source.
|
|
159
|
+
|
|
160
|
+
The rendered catalog (docs/skills.md) is published on the MkDocs site,
|
|
161
|
+
whose assembled tree (scripts/assemble-docs.sh) copies only each plugin's
|
|
162
|
+
docs/ directory — not skills/ or commands/. A relative `../skills/...`
|
|
163
|
+
link resolves in a repo checkout but 404s on the deployed page (#2103),
|
|
164
|
+
so link to the file's permanent GitHub source instead. `target` outside
|
|
165
|
+
the repo tree (synthetic paths used by tests) keeps the old repo-relative
|
|
166
|
+
form, which is never published.
|
|
167
|
+
"""
|
|
168
|
+
try:
|
|
169
|
+
rel = target.resolve().relative_to(_REPO_ROOT)
|
|
170
|
+
except ValueError:
|
|
171
|
+
return f"[`{label}`]({fallback_rel})"
|
|
172
|
+
return f"[`{label}`]({_BLOB_BASE}/{rel.as_posix()})"
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def _options_value(fm: dict) -> str:
|
|
176
|
+
"""Return the Options column value for a skill/command's frontmatter."""
|
|
177
|
+
if fm.get("user-invocable") is True:
|
|
178
|
+
hint = fm.get("argument-hint")
|
|
179
|
+
if hint:
|
|
180
|
+
return _cell(str(hint))
|
|
181
|
+
return _OPT_NO_FLAGS
|
|
182
|
+
return _OPT_AGENT_LOADED
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def _load_categories(categories_file: Path) -> list[tuple[str, list[str]]]:
|
|
186
|
+
"""Ordered [(category_name, [skill, ...]), ...] from skill_categories.yaml.
|
|
187
|
+
|
|
188
|
+
Returns an empty list when the file does not exist, which causes all entries
|
|
189
|
+
to land in a trailing Ungrouped section (see _collect).
|
|
190
|
+
"""
|
|
191
|
+
if not categories_file.exists():
|
|
192
|
+
return []
|
|
193
|
+
data = parse_yaml(categories_file.read_text(encoding="utf-8")) or {}
|
|
194
|
+
return [
|
|
195
|
+
(c["name"], list(c.get("skills") or [])) for c in (data.get("categories") or [])
|
|
196
|
+
]
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def _collect(
|
|
200
|
+
skills_dir: Path,
|
|
201
|
+
categories_file: Path,
|
|
202
|
+
) -> list[tuple[str, list]]:
|
|
203
|
+
"""Group skills and commands by capability.
|
|
204
|
+
|
|
205
|
+
Returns ordered [(category, rows), ...] where each row is
|
|
206
|
+
(name, key, link, desc, slash, options).
|
|
207
|
+
A skill/command whose key isn't in the taxonomy lands in a trailing section
|
|
208
|
+
so it stays visible in the diff:
|
|
209
|
+
- "Other" when a categories file exists (taxonomy gap)
|
|
210
|
+
- "Ungrouped" when no categories file exists at all
|
|
211
|
+
"""
|
|
212
|
+
cats = _load_categories(categories_file)
|
|
213
|
+
has_categories = bool(cats)
|
|
214
|
+
order = [name for name, _ in cats]
|
|
215
|
+
lookup = {skill: name for name, skills in cats for skill in skills}
|
|
216
|
+
buckets: dict[str, list] = {name: [] for name in order}
|
|
217
|
+
|
|
218
|
+
def _add_entry(key: str, fm: dict, link: str) -> None:
|
|
219
|
+
if not fm.get("description"):
|
|
220
|
+
raise FrontmatterError(f"{link}: frontmatter has no `description`")
|
|
221
|
+
name = str(fm.get("name") or key)
|
|
222
|
+
desc = _cell(fm["description"])
|
|
223
|
+
slash = fm.get("user-invocable") is True
|
|
224
|
+
opts = _options_value(fm)
|
|
225
|
+
fallback = _OPT_OTHER if has_categories else _OPT_UNGROUPED_SECTION
|
|
226
|
+
buckets.setdefault(lookup.get(key, fallback), []).append(
|
|
227
|
+
(name, key, link, desc, slash, opts)
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
# skills/<name>/SKILL.md — keyed by folder name
|
|
231
|
+
for skill_md in sorted(skills_dir.glob("*/SKILL.md")):
|
|
232
|
+
folder = skill_md.parent.name
|
|
233
|
+
fm = _frontmatter(skill_md)
|
|
234
|
+
link = _source_link(
|
|
235
|
+
f"{folder}/SKILL.md", skill_md, f"../skills/{folder}/SKILL.md"
|
|
236
|
+
)
|
|
237
|
+
_add_entry(folder, fm, link)
|
|
238
|
+
|
|
239
|
+
# commands/<name>.md — keyed by frontmatter `name`
|
|
240
|
+
commands_dir = skills_dir.parent / "commands"
|
|
241
|
+
if commands_dir.is_dir():
|
|
242
|
+
for cmd_md in sorted(commands_dir.glob("*.md")):
|
|
243
|
+
fm = _frontmatter(cmd_md)
|
|
244
|
+
key = str(fm.get("name") or cmd_md.stem)
|
|
245
|
+
link = _source_link(
|
|
246
|
+
f"commands/{cmd_md.name}", cmd_md, f"../commands/{cmd_md.name}"
|
|
247
|
+
)
|
|
248
|
+
_add_entry(key, fm, link)
|
|
249
|
+
|
|
250
|
+
display = [(name, buckets[name]) for name in order if buckets.get(name)]
|
|
251
|
+
# Trailing ungrouped/other bucket
|
|
252
|
+
fallback_key = _OPT_OTHER if has_categories else _OPT_UNGROUPED_SECTION
|
|
253
|
+
if buckets.get(fallback_key):
|
|
254
|
+
display.append((fallback_key, buckets[fallback_key]))
|
|
255
|
+
for _name, rows in display:
|
|
256
|
+
rows.sort(key=lambda r: r[1])
|
|
257
|
+
return display
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def _table(rows: list) -> str:
|
|
261
|
+
head = "| Skill | Options | File | Description |\n| --- | --- | --- | --- |\n"
|
|
262
|
+
body = []
|
|
263
|
+
for name, _key, link, desc, slash, opts in rows:
|
|
264
|
+
label = f"`/{name}`" if slash else name
|
|
265
|
+
body.append(f"| {label} | {opts} | {link} | {desc} |")
|
|
266
|
+
return head + "\n".join(body) + "\n"
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def build(plugin_dir: Path) -> str:
|
|
270
|
+
skills_dir, _output, categories_file = _resolve_paths(plugin_dir)
|
|
271
|
+
parts = [_make_header(plugin_dir)]
|
|
272
|
+
for cat_name, rows in _collect(skills_dir, categories_file):
|
|
273
|
+
parts += ["", f"## {cat_name}", "", _table(rows)]
|
|
274
|
+
return "\n".join(parts).rstrip("\n") + "\n"
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def _atomic_write(output: Path, text: str) -> None:
|
|
278
|
+
tmp = output.with_suffix(output.suffix + ".tmp")
|
|
279
|
+
try:
|
|
280
|
+
tmp.write_text(text, encoding="utf-8")
|
|
281
|
+
os.replace(tmp, output)
|
|
282
|
+
finally:
|
|
283
|
+
if tmp.exists():
|
|
284
|
+
tmp.unlink()
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def _parse_args(argv: list[str]) -> tuple[str, Path]:
|
|
288
|
+
"""Return (mode, plugin_dir)."""
|
|
289
|
+
parser = argparse.ArgumentParser(
|
|
290
|
+
prog="build_skills_index.py",
|
|
291
|
+
description="Generate docs/skills.md from plugin skill/command frontmatter.",
|
|
292
|
+
add_help=True,
|
|
293
|
+
)
|
|
294
|
+
parser.add_argument(
|
|
295
|
+
"mode",
|
|
296
|
+
nargs="?",
|
|
297
|
+
default="write",
|
|
298
|
+
choices=["write", "--check"],
|
|
299
|
+
help="write (default) or --check",
|
|
300
|
+
)
|
|
301
|
+
parser.add_argument(
|
|
302
|
+
"--plugin-dir",
|
|
303
|
+
type=Path,
|
|
304
|
+
default=None,
|
|
305
|
+
help="Root directory of the plugin (default: dev-team plugin).",
|
|
306
|
+
)
|
|
307
|
+
# argparse doesn't handle '--check' as a positional value gracefully when
|
|
308
|
+
# it looks like a flag. Accept it via a dedicated flag too.
|
|
309
|
+
parser.add_argument(
|
|
310
|
+
"--check",
|
|
311
|
+
action="store_true",
|
|
312
|
+
default=False,
|
|
313
|
+
help="Alias for mode=--check.",
|
|
314
|
+
)
|
|
315
|
+
ns = parser.parse_args(argv[1:])
|
|
316
|
+
mode = "--check" if (ns.mode == "--check" or ns.check) else "write"
|
|
317
|
+
plugin_dir = ns.plugin_dir.resolve() if ns.plugin_dir else _DEFAULT_PLUGIN_DIR
|
|
318
|
+
return mode, plugin_dir
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def main(argv: list) -> int:
|
|
322
|
+
try:
|
|
323
|
+
mode, plugin_dir = _parse_args(argv)
|
|
324
|
+
except SystemExit as e:
|
|
325
|
+
return int(e.code) if e.code is not None else 2
|
|
326
|
+
|
|
327
|
+
_skills_dir, output, _cats = _resolve_paths(plugin_dir)
|
|
328
|
+
|
|
329
|
+
try:
|
|
330
|
+
actual = build(plugin_dir)
|
|
331
|
+
except FrontmatterError as e:
|
|
332
|
+
sys.stderr.write(f"[skills-index] {e}\n")
|
|
333
|
+
return 1
|
|
334
|
+
|
|
335
|
+
if mode == "--check":
|
|
336
|
+
if not output.exists():
|
|
337
|
+
sys.stderr.write(f"[skills-index] index file missing: {output}\n")
|
|
338
|
+
return 1
|
|
339
|
+
current = output.read_text(encoding="utf-8")
|
|
340
|
+
if current == actual:
|
|
341
|
+
return 0
|
|
342
|
+
diff = difflib.unified_diff(
|
|
343
|
+
current.splitlines(keepends=True),
|
|
344
|
+
actual.splitlines(keepends=True),
|
|
345
|
+
fromfile=str(output),
|
|
346
|
+
tofile="<fresh build>",
|
|
347
|
+
)
|
|
348
|
+
sys.stderr.writelines(diff)
|
|
349
|
+
sys.stderr.write(
|
|
350
|
+
"\n[skills-index] docs/skills.md is stale. Regenerate: "
|
|
351
|
+
"python3 plugins/dev-team/hooks/lib/build_skills_index.py\n"
|
|
352
|
+
)
|
|
353
|
+
return 1
|
|
354
|
+
|
|
355
|
+
# write mode
|
|
356
|
+
_atomic_write(output, actual)
|
|
357
|
+
return 0
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
if __name__ == "__main__":
|
|
361
|
+
sys.exit(main(sys.argv))
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Shared reader for `/build`'s active-state record (#2177, slice 1).
|
|
2
|
+
|
|
3
|
+
`/build` owns `.claude/memory/build-phase.json` (see `skills/build/SKILL.md`):
|
|
4
|
+
{"phase": "<implement|test|refactor|between-steps>", "step": "<N.M>", "written_at": "<ISO8601>",
|
|
5
|
+
"test_files_staged": [], "plan_path": "<repo-relative plan file>"}
|
|
6
|
+
|
|
7
|
+
This module is the single reader of that record, so the post-compaction
|
|
8
|
+
re-injection hook and `/build` agree on one contract (pinned by
|
|
9
|
+
`tests/hooks/test_build_state_contract.py`).
|
|
10
|
+
|
|
11
|
+
"Cleared" means: the file is absent, empty, `{}`, unreadable, malformed, or
|
|
12
|
+
lacks a string `phase` AND a string `step`. `/build` clears the record only when
|
|
13
|
+
the plan completes. At each step completion it rewrites it as a `between-steps`
|
|
14
|
+
record (`phase == BETWEEN_STEPS`, `step` = the next step, same `plan_path`), so a
|
|
15
|
+
compaction between steps still restores the plan and next step. Only the
|
|
16
|
+
`refactor` phase is enforced by the guards, so the retained record is inert to
|
|
17
|
+
them, and an old one is ignored by the same staleness rule below.
|
|
18
|
+
|
|
19
|
+
A record whose `written_at` is missing/unparseable, or older than
|
|
20
|
+
`STALE_AFTER_SECONDS` or more than `FUTURE_SKEW_SECONDS` in the future (shared with `test_file_classify.py`: a crashed `/build`
|
|
21
|
+
must not haunt later sessions), is also treated as cleared.
|
|
22
|
+
|
|
23
|
+
`plan_path` is taken verbatim from the record — never globbed or searched —
|
|
24
|
+
and is kept only when it resolves to an existing regular file inside the
|
|
25
|
+
project directory; otherwise it is None (phase/step are still returned).
|
|
26
|
+
|
|
27
|
+
Stdlib only; never raises (fail-open for hook callers).
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
from __future__ import annotations
|
|
31
|
+
|
|
32
|
+
import json
|
|
33
|
+
import time
|
|
34
|
+
from dataclasses import dataclass
|
|
35
|
+
from datetime import datetime, timezone
|
|
36
|
+
from pathlib import Path
|
|
37
|
+
|
|
38
|
+
from test_file_classify import STALE_AFTER_SECONDS # same staleness rule as the guards
|
|
39
|
+
|
|
40
|
+
#: Keys `/build` documents for the record; the contract test compares this to SKILL.md.
|
|
41
|
+
RECORD_KEYS = ("phase", "step", "written_at", "test_files_staged", "plan_path")
|
|
42
|
+
|
|
43
|
+
#: `phase` value `/build` writes at step completion in place of deleting the file.
|
|
44
|
+
BETWEEN_STEPS = "between-steps"
|
|
45
|
+
|
|
46
|
+
#: A `written_at` further ahead than this is clock skew or forgery, never "fresh".
|
|
47
|
+
FUTURE_SKEW_SECONDS = 300
|
|
48
|
+
|
|
49
|
+
STATE_RELPATH = Path(".claude") / "memory" / "build-phase.json"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass(frozen=True)
|
|
53
|
+
class BuildState:
|
|
54
|
+
phase: str
|
|
55
|
+
step: str
|
|
56
|
+
plan_path: str | None
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _contained_plan_path(project_dir: Path, raw: object) -> str | None:
|
|
60
|
+
"""Return `raw` when it names a regular file inside `project_dir`."""
|
|
61
|
+
if not isinstance(raw, str) or not raw.strip() or "\x00" in raw:
|
|
62
|
+
return None
|
|
63
|
+
try:
|
|
64
|
+
root = project_dir.resolve()
|
|
65
|
+
candidate = (root / raw).resolve()
|
|
66
|
+
candidate.relative_to(root)
|
|
67
|
+
if not candidate.is_file():
|
|
68
|
+
return None
|
|
69
|
+
except (OSError, ValueError, RuntimeError):
|
|
70
|
+
return None
|
|
71
|
+
return raw
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _parse_written_at(value: object) -> float | None:
|
|
75
|
+
if not isinstance(value, str) or not value.strip():
|
|
76
|
+
return None
|
|
77
|
+
candidate = value.strip()
|
|
78
|
+
if candidate.endswith("Z"):
|
|
79
|
+
candidate = candidate[:-1] + "+00:00"
|
|
80
|
+
try:
|
|
81
|
+
parsed = datetime.fromisoformat(candidate)
|
|
82
|
+
except ValueError:
|
|
83
|
+
return None
|
|
84
|
+
if parsed.tzinfo is None:
|
|
85
|
+
parsed = parsed.replace(tzinfo=timezone.utc)
|
|
86
|
+
return parsed.timestamp()
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def read_active_build_state(
|
|
90
|
+
project_dir: str | Path, now: float | None = None
|
|
91
|
+
) -> BuildState | None:
|
|
92
|
+
"""Read the active build state for `project_dir`, or None when cleared/stale.
|
|
93
|
+
|
|
94
|
+
`now` is the injectable clock (epoch seconds) for staleness tests.
|
|
95
|
+
"""
|
|
96
|
+
try:
|
|
97
|
+
root = Path(project_dir)
|
|
98
|
+
data = json.loads((root / STATE_RELPATH).read_text(encoding="utf-8"))
|
|
99
|
+
except (OSError, ValueError, UnicodeDecodeError, RecursionError, RuntimeError):
|
|
100
|
+
return None
|
|
101
|
+
if not isinstance(data, dict):
|
|
102
|
+
return None
|
|
103
|
+
phase, step = data.get("phase"), data.get("step")
|
|
104
|
+
if not (isinstance(phase, str) and phase and isinstance(step, str) and step):
|
|
105
|
+
return None
|
|
106
|
+
written_at = _parse_written_at(data.get("written_at"))
|
|
107
|
+
if written_at is None:
|
|
108
|
+
return None
|
|
109
|
+
age = (time.time() if now is None else now) - written_at
|
|
110
|
+
if age > STALE_AFTER_SECONDS or age < -FUTURE_SKEW_SECONDS:
|
|
111
|
+
return None
|
|
112
|
+
return BuildState(
|
|
113
|
+
phase=phase,
|
|
114
|
+
step=step,
|
|
115
|
+
plan_path=_contained_plan_path(root, data.get("plan_path")),
|
|
116
|
+
)
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""
|
|
2
|
+
classify_ship_outcome.py — deterministic /ship outcome classifier.
|
|
3
|
+
|
|
4
|
+
Reads metrics/review-value.jsonl and metrics/verify-log.jsonl since a
|
|
5
|
+
start timestamp and returns one of three outcome strings:
|
|
6
|
+
|
|
7
|
+
"convergence_failure" — any review-value entry since `since_iso` has
|
|
8
|
+
outcome == "escalated"
|
|
9
|
+
"success" — at least one verify-log entry since `since_iso`
|
|
10
|
+
has outcome in {"ran", "failed-then-fixed"}
|
|
11
|
+
"unrecognized" — neither condition met (or no matching entries)
|
|
12
|
+
|
|
13
|
+
Files that do not exist are treated as empty (no lines).
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import argparse
|
|
19
|
+
import json
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
|
|
22
|
+
_VERIFY_SUCCESS_OUTCOMES = {"ran", "failed-then-fixed"}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _timestamp_field(record: dict) -> str | None:
|
|
26
|
+
"""Return the timestamp string from a JSONL record, trying common field names."""
|
|
27
|
+
for key in ("timestamp", "logged_at", "ts"):
|
|
28
|
+
if key in record:
|
|
29
|
+
return str(record[key])
|
|
30
|
+
return None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _read_since(path: Path, since_iso: str) -> list[dict]:
|
|
34
|
+
"""
|
|
35
|
+
Return all JSON records from *path* whose timestamp >= since_iso.
|
|
36
|
+
|
|
37
|
+
Lines that are not valid JSON, or that have no recognisable timestamp
|
|
38
|
+
field, are skipped silently.
|
|
39
|
+
"""
|
|
40
|
+
if not path.exists():
|
|
41
|
+
return []
|
|
42
|
+
|
|
43
|
+
results: list[dict] = []
|
|
44
|
+
with path.open(encoding="utf-8") as fh:
|
|
45
|
+
for raw in fh:
|
|
46
|
+
raw = raw.strip()
|
|
47
|
+
if not raw:
|
|
48
|
+
continue
|
|
49
|
+
try:
|
|
50
|
+
record = json.loads(raw)
|
|
51
|
+
except json.JSONDecodeError:
|
|
52
|
+
continue
|
|
53
|
+
ts = _timestamp_field(record)
|
|
54
|
+
if ts is not None and ts < since_iso:
|
|
55
|
+
continue
|
|
56
|
+
results.append(record)
|
|
57
|
+
return results
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def classify(
|
|
61
|
+
review_value_path: Path,
|
|
62
|
+
verify_log_path: Path,
|
|
63
|
+
since_iso: str,
|
|
64
|
+
) -> str:
|
|
65
|
+
"""
|
|
66
|
+
Classify the /ship outcome from two JSONL metric files.
|
|
67
|
+
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
review_value_path:
|
|
71
|
+
Path to metrics/review-value.jsonl (may not exist).
|
|
72
|
+
verify_log_path:
|
|
73
|
+
Path to metrics/verify-log.jsonl (may not exist).
|
|
74
|
+
since_iso:
|
|
75
|
+
ISO-8601 timestamp string. Only records at or after this time
|
|
76
|
+
are considered.
|
|
77
|
+
|
|
78
|
+
Returns
|
|
79
|
+
-------
|
|
80
|
+
One of "convergence_failure", "success", or "unrecognized".
|
|
81
|
+
"""
|
|
82
|
+
review_records = _read_since(Path(review_value_path), since_iso)
|
|
83
|
+
if any(r.get("outcome") == "escalated" for r in review_records):
|
|
84
|
+
return "convergence_failure"
|
|
85
|
+
|
|
86
|
+
verify_records = _read_since(Path(verify_log_path), since_iso)
|
|
87
|
+
if any(r.get("outcome") in _VERIFY_SUCCESS_OUTCOMES for r in verify_records):
|
|
88
|
+
return "success"
|
|
89
|
+
|
|
90
|
+
return "unrecognized"
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _main() -> None:
|
|
94
|
+
parser = argparse.ArgumentParser(
|
|
95
|
+
description="Classify /ship outcome from JSONL metric files."
|
|
96
|
+
)
|
|
97
|
+
parser.add_argument(
|
|
98
|
+
"--review-value",
|
|
99
|
+
required=True,
|
|
100
|
+
metavar="PATH",
|
|
101
|
+
help="Path to metrics/review-value.jsonl",
|
|
102
|
+
)
|
|
103
|
+
parser.add_argument(
|
|
104
|
+
"--verify-log",
|
|
105
|
+
required=True,
|
|
106
|
+
metavar="PATH",
|
|
107
|
+
help="Path to metrics/verify-log.jsonl",
|
|
108
|
+
)
|
|
109
|
+
parser.add_argument(
|
|
110
|
+
"--since",
|
|
111
|
+
required=True,
|
|
112
|
+
metavar="ISO_TIMESTAMP",
|
|
113
|
+
help="Consider only records at or after this ISO-8601 timestamp",
|
|
114
|
+
)
|
|
115
|
+
args = parser.parse_args()
|
|
116
|
+
|
|
117
|
+
result = classify(
|
|
118
|
+
review_value_path=Path(args.review_value),
|
|
119
|
+
verify_log_path=Path(args.verify_log),
|
|
120
|
+
since_iso=args.since,
|
|
121
|
+
)
|
|
122
|
+
print(result)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
if __name__ == "__main__":
|
|
126
|
+
_main()
|