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,504 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# build_knowledge_index.py — single-process knowledge index builder.
|
|
3
|
+
#
|
|
4
|
+
# Replaces the shell+jq+awk+python-per-section pipeline. Forks once
|
|
5
|
+
# instead of ~300 times per build. Output is byte-identical to what
|
|
6
|
+
# the previous `jq -s 'add'` pipeline produced, so the freshness gate
|
|
7
|
+
# does not trip across the rewrite.
|
|
8
|
+
#
|
|
9
|
+
# Modes:
|
|
10
|
+
# default rebuild the index file in place
|
|
11
|
+
# --check diff a fresh build against the on-disk index; exit non-
|
|
12
|
+
# zero with a unified diff on stderr if they differ
|
|
13
|
+
#
|
|
14
|
+
# Env vars (TEST-ONLY injection seams — do not document as user-facing):
|
|
15
|
+
# KNOWLEDGE_INDEX_CORPUS_ROOTS override the corpus root
|
|
16
|
+
# KNOWLEDGE_INDEX_OUTPUT override the output path
|
|
17
|
+
|
|
18
|
+
import difflib
|
|
19
|
+
import json
|
|
20
|
+
import os
|
|
21
|
+
import re
|
|
22
|
+
import sys
|
|
23
|
+
import tempfile
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
|
|
26
|
+
# ---------------------------------------------------------------------------
|
|
27
|
+
# Config — path resolution mirrors the shell wrapper's defaults.
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
ABBREVS = {
|
|
31
|
+
"e.g",
|
|
32
|
+
"i.e",
|
|
33
|
+
"etc",
|
|
34
|
+
"vs",
|
|
35
|
+
"Mr",
|
|
36
|
+
"Mrs",
|
|
37
|
+
"Ms",
|
|
38
|
+
"Dr",
|
|
39
|
+
"Jr",
|
|
40
|
+
"Sr",
|
|
41
|
+
"St",
|
|
42
|
+
"No",
|
|
43
|
+
"cf",
|
|
44
|
+
}
|
|
45
|
+
MAX_SUMMARY_LEN = 240
|
|
46
|
+
ELLIPSIS = "…"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _resolve_paths():
|
|
50
|
+
script_dir = Path(__file__).resolve().parent
|
|
51
|
+
plugin_dir = script_dir.parent.parent
|
|
52
|
+
roots = os.environ.get("KNOWLEDGE_INDEX_CORPUS_ROOTS", str(plugin_dir))
|
|
53
|
+
output = os.environ.get(
|
|
54
|
+
"KNOWLEDGE_INDEX_OUTPUT", str(plugin_dir / "knowledge" / "index.json")
|
|
55
|
+
)
|
|
56
|
+
return Path(roots), Path(output)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# ---------------------------------------------------------------------------
|
|
60
|
+
# Slugify — matches the shell `_slugify` exactly:
|
|
61
|
+
# lowercase | strip non [a-z0-9 -] | spaces→hyphens | collapse hyphens | trim
|
|
62
|
+
# ---------------------------------------------------------------------------
|
|
63
|
+
|
|
64
|
+
_SLUG_DROP_RE = re.compile(r"[^a-z0-9 \-]+")
|
|
65
|
+
_SLUG_SPACE_RE = re.compile(r" +")
|
|
66
|
+
_SLUG_DASH_RE = re.compile(r"-+")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def slugify(text: str) -> str:
|
|
70
|
+
s = text.lower()
|
|
71
|
+
s = _SLUG_DROP_RE.sub("", s)
|
|
72
|
+
s = _SLUG_SPACE_RE.sub("-", s)
|
|
73
|
+
s = _SLUG_DASH_RE.sub("-", s)
|
|
74
|
+
return s.strip("-")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# ---------------------------------------------------------------------------
|
|
78
|
+
# First-sentence extraction — operational boundary rule from the spec.
|
|
79
|
+
# Logic mirrors the previous heredoc Python exactly so the sentence-boundary rule stays green.
|
|
80
|
+
# ---------------------------------------------------------------------------
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def first_sentence(text: str) -> str:
|
|
84
|
+
text = text.lstrip()
|
|
85
|
+
i = 0
|
|
86
|
+
end = None
|
|
87
|
+
while i < len(text):
|
|
88
|
+
ch = text[i]
|
|
89
|
+
if ch in ".!?":
|
|
90
|
+
after = text[i + 1] if i + 1 < len(text) else ""
|
|
91
|
+
if not (after == "" or after.isspace()):
|
|
92
|
+
i += 1
|
|
93
|
+
continue
|
|
94
|
+
if i >= 1 and text[i - 1].isupper():
|
|
95
|
+
prev2 = text[i - 2] if i - 2 >= 0 else ""
|
|
96
|
+
if prev2 == "" or prev2.isspace() or prev2 == ".":
|
|
97
|
+
i += 1
|
|
98
|
+
continue
|
|
99
|
+
j = i - 1
|
|
100
|
+
while j >= 0 and not text[j].isspace():
|
|
101
|
+
j -= 1
|
|
102
|
+
token = text[j + 1 : i]
|
|
103
|
+
if token in ABBREVS:
|
|
104
|
+
i += 1
|
|
105
|
+
continue
|
|
106
|
+
end = i + 1
|
|
107
|
+
break
|
|
108
|
+
i += 1
|
|
109
|
+
|
|
110
|
+
if end is not None:
|
|
111
|
+
return text[:end]
|
|
112
|
+
if len(text) <= MAX_SUMMARY_LEN:
|
|
113
|
+
return text
|
|
114
|
+
cut = text[:MAX_SUMMARY_LEN].rstrip()
|
|
115
|
+
last_ws = cut.rfind(" ")
|
|
116
|
+
if last_ws > 0:
|
|
117
|
+
cut = cut[:last_ws]
|
|
118
|
+
return cut + ELLIPSIS
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# ---------------------------------------------------------------------------
|
|
122
|
+
# Section extraction — replicates the awk first pass + the backfill pass.
|
|
123
|
+
#
|
|
124
|
+
# Rules (must match shell):
|
|
125
|
+
# - Code fences (```...```) are skipped wholesale; only prose outside
|
|
126
|
+
# fenced blocks is considered.
|
|
127
|
+
# - `## ` is an H2; `### ` is an H3; both are indexed.
|
|
128
|
+
# - `# ` (H1) resets collection; `#### ` (H4+) closes the enclosing body
|
|
129
|
+
# but emits nothing for the H4.
|
|
130
|
+
# - Body is the first non-blank line under the header. A leading bullet
|
|
131
|
+
# marker (`- `, `* `, `+ `) is stripped.
|
|
132
|
+
# - Empty bodies are backfilled from the next non-empty body in source
|
|
133
|
+
# order (cascades through child sections).
|
|
134
|
+
# ---------------------------------------------------------------------------
|
|
135
|
+
|
|
136
|
+
_FENCE_RE = re.compile(r"^```")
|
|
137
|
+
_H4_PLUS_RE = re.compile(r"^#{4,} ")
|
|
138
|
+
_H3_RE = re.compile(r"^### (.+)$")
|
|
139
|
+
_H2_RE = re.compile(r"^## (.+)$")
|
|
140
|
+
_H1_RE = re.compile(r"^# ")
|
|
141
|
+
_BULLET_RE = re.compile(r"^[ \t]*[-*+][ \t]+")
|
|
142
|
+
|
|
143
|
+
# ---------------------------------------------------------------------------
|
|
144
|
+
# Include-marker resolution — `<!-- include: <path> -->` splices another
|
|
145
|
+
# file's content in place of the marker line (introduced by /test-improve's
|
|
146
|
+
# SKILL.md split, plans/test-improve-context-loading-strategy.md Step 1.1).
|
|
147
|
+
# A section body that is only the marker line has no real content of its
|
|
148
|
+
# own — resolve it to the first prose line of the referenced file so the
|
|
149
|
+
# summary is a real sentence, not the literal marker text. General-purpose:
|
|
150
|
+
# any file under the corpus may use this convention, not just test-improve.
|
|
151
|
+
#
|
|
152
|
+
# INCLUDE_MARKER_RE/MAX_INCLUDE_DEPTH are public: tests/skills/
|
|
153
|
+
# skill_include_resolver.py (which cannot be imported *from* here, since
|
|
154
|
+
# that module lives under tests/) imports them from here rather than
|
|
155
|
+
# re-declaring its own copies, so the grammar and recursion budget have one
|
|
156
|
+
# owner instead of two hand-kept-equal ones. Every marker — at any recursion
|
|
157
|
+
# depth — must carry a single-path-segment `references/<name>.md` path (no
|
|
158
|
+
# `/` inside `<name>`, matching knowledge_index_paths.CORPUS_REGEX's own
|
|
159
|
+
# shape and closing off `../` traversal at the regex level), and every path
|
|
160
|
+
# resolves against the ORIGINAL including file's own directory (`root`),
|
|
161
|
+
# pinned for every recursive call. A marker inside an already-spliced-in
|
|
162
|
+
# reference file is still relative to the top-level file's directory, never
|
|
163
|
+
# rebased to the nested target's own directory.
|
|
164
|
+
# ---------------------------------------------------------------------------
|
|
165
|
+
|
|
166
|
+
# Excludes both `/` and `\` from the captured segment — not just `/` — so
|
|
167
|
+
# the traversal closure holds on Windows too, where `\` is also a path
|
|
168
|
+
# separator (a POSIX-only `[^/\s]+` would let `references/..\..\outside.md`
|
|
169
|
+
# through the regex and rely on the resolve()/containment check below as
|
|
170
|
+
# the only backstop there instead of a second, independent layer).
|
|
171
|
+
INCLUDE_MARKER_RE = re.compile(r"^<!-- include: (references/[^/\\\s]+\.md) -->$")
|
|
172
|
+
MAX_INCLUDE_DEPTH = 5
|
|
173
|
+
|
|
174
|
+
# Deliberately unbounded (`#+`, not `#{1,6}`) to match _H4_PLUS_RE's own
|
|
175
|
+
# unbounded run — a `####### ` (7+ `#`s) line is a heading to
|
|
176
|
+
# extract_sections and must be one here too, or a body line that IS a
|
|
177
|
+
# heading there would be returned verbatim as a section summary here.
|
|
178
|
+
# One known, accepted residual divergence from extract_sections()'s
|
|
179
|
+
# _H2_RE/_H3_RE (which require content after the `#`s via `(.+)`): a bare
|
|
180
|
+
# `##`/`###` with nothing following is body text to extract_sections but a
|
|
181
|
+
# heading here. Needs degenerate markdown ("## " on a line by itself) that
|
|
182
|
+
# doesn't exist in this corpus today; this pattern's own contract is
|
|
183
|
+
# stated on its own terms — skip an ATX heading (1+ `#`s, space or
|
|
184
|
+
# end-of-line) — never assumed to be full parity with extract_sections's
|
|
185
|
+
# regexes.
|
|
186
|
+
_HEADING_LINE_RE = re.compile(r"^#+( |$)")
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def resolve_contained_target(target: Path, root: Path) -> Path | None:
|
|
190
|
+
"""Resolve `target` and verify it is a symlink-free descendant of
|
|
191
|
+
`root`. Returns the resolved `Path` on success, `None` if `target` is a
|
|
192
|
+
symlink, its resolution escapes `root`, or resolution itself fails (a
|
|
193
|
+
NUL byte or other unencodable component raises `ValueError`, not
|
|
194
|
+
`OSError`, from `Path.resolve()` — both are caught here so a malformed
|
|
195
|
+
marker degrades to the caller's own not-found handling instead of
|
|
196
|
+
crashing it).
|
|
197
|
+
|
|
198
|
+
Existence is deliberately NOT checked here: "target doesn't exist" and
|
|
199
|
+
"target fails containment" are different event classes, and callers
|
|
200
|
+
that want to tell them apart check `.is_file()` on the returned path
|
|
201
|
+
themselves. Shared by `_resolve_include_marker` below and
|
|
202
|
+
`tests/skills/skill_include_resolver.py`'s `_splice` (imported from
|
|
203
|
+
here rather than re-implemented) — the two differ only in what they do
|
|
204
|
+
with a `None` result (fail open to literal text vs. raise), not in the
|
|
205
|
+
containment logic itself.
|
|
206
|
+
|
|
207
|
+
`is_symlink()` is inside the same try as `resolve()`, not before it:
|
|
208
|
+
this repo's own convention is not to rely on an unverified claim about a
|
|
209
|
+
library's internal error-swallowing behavior as a safety guarantee (see
|
|
210
|
+
root CLAUDE.md's "validate the property explicitly in your own code
|
|
211
|
+
instead") — the explicit `except (OSError, ValueError)` below is what
|
|
212
|
+
actually closes the must-never-crash gap, not an assumption that
|
|
213
|
+
`is_symlink()` never raises."""
|
|
214
|
+
try:
|
|
215
|
+
if target.is_symlink():
|
|
216
|
+
return None
|
|
217
|
+
resolved_root = root.resolve()
|
|
218
|
+
resolved_target = target.resolve()
|
|
219
|
+
except (OSError, ValueError):
|
|
220
|
+
return None
|
|
221
|
+
if not resolved_target.is_relative_to(resolved_root):
|
|
222
|
+
return None
|
|
223
|
+
return resolved_target
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def _skip_fenced_lines(lines):
|
|
227
|
+
"""Yields only lines outside fenced (```) code blocks — the fence
|
|
228
|
+
markers themselves and everything between a matched pair are dropped.
|
|
229
|
+
Shared by extract_sections() and _first_prose_line() so the fence-toggle
|
|
230
|
+
idiom has one implementation instead of two independently maintained
|
|
231
|
+
copies."""
|
|
232
|
+
in_code = False
|
|
233
|
+
for raw_line in lines:
|
|
234
|
+
line = raw_line.rstrip("\n")
|
|
235
|
+
if _FENCE_RE.match(line):
|
|
236
|
+
in_code = not in_code
|
|
237
|
+
continue
|
|
238
|
+
if in_code:
|
|
239
|
+
continue
|
|
240
|
+
yield line
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def _first_prose_line(path: Path) -> str:
|
|
244
|
+
"""First non-blank, non-heading line outside fenced code blocks,
|
|
245
|
+
bullet-stripped. Heading detection uses `_HEADING_LINE_RE` (an ATX
|
|
246
|
+
heading: 1 or more `#`s followed by a space or end-of-line) — a
|
|
247
|
+
narrower, own-terms rule than a bare `line.startswith(\"#\")`, so a body
|
|
248
|
+
line like `#1787 tracks this` is correctly treated as prose, not a
|
|
249
|
+
heading."""
|
|
250
|
+
try:
|
|
251
|
+
with path.open("r", encoding="utf-8", errors="replace") as fh:
|
|
252
|
+
for line in _skip_fenced_lines(fh):
|
|
253
|
+
if not line.strip():
|
|
254
|
+
continue
|
|
255
|
+
if _HEADING_LINE_RE.match(line):
|
|
256
|
+
continue
|
|
257
|
+
return _BULLET_RE.sub("", line, count=1)
|
|
258
|
+
except OSError:
|
|
259
|
+
return ""
|
|
260
|
+
return ""
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def _resolve_include_marker(body: str, root: Path, depth: int = 0) -> str:
|
|
264
|
+
"""If `body` is exactly an `<!-- include: references/<path>.md -->`
|
|
265
|
+
marker line, resolve it to the first prose line of the referenced file
|
|
266
|
+
(resolved against `root` — the ORIGINAL including file's own directory,
|
|
267
|
+
pinned for every recursive call and never rebased to a nested target's
|
|
268
|
+
own directory), recursing through nested markers up to
|
|
269
|
+
`MAX_INCLUDE_DEPTH`. Returns `body` unchanged when it is not a marker,
|
|
270
|
+
the target fails `resolve_contained_target`'s containment check (a
|
|
271
|
+
symlink, an escape from `root`, or a resolution failure such as a NUL
|
|
272
|
+
byte — logged to stderr, since any of these is a different event class
|
|
273
|
+
from an ordinary authoring mistake), the target file doesn't exist, the
|
|
274
|
+
target has no prose line, or the recursion budget is exhausted.
|
|
275
|
+
|
|
276
|
+
Design choice, deliberate and different from the mirror: the mirror
|
|
277
|
+
(tests/skills/skill_include_resolver.py) raises RecursionError on a
|
|
278
|
+
cycle/over-depth include, which is fine for a test assertion to be
|
|
279
|
+
strict about. This is a build tool over a whole corpus that must never
|
|
280
|
+
crash on a cycle — it falls back to the literal unresolved marker text
|
|
281
|
+
instead, same as the missing-file and no-prose-line fallbacks above.
|
|
282
|
+
"""
|
|
283
|
+
m = INCLUDE_MARKER_RE.match(body.strip())
|
|
284
|
+
if not m or depth > MAX_INCLUDE_DEPTH:
|
|
285
|
+
return body
|
|
286
|
+
target = root / m.group(1)
|
|
287
|
+
resolved_target = resolve_contained_target(target, root)
|
|
288
|
+
if resolved_target is None:
|
|
289
|
+
print(
|
|
290
|
+
f"warning: refusing include target {target} — symlink, "
|
|
291
|
+
f"escapes {root}, or could not be resolved",
|
|
292
|
+
file=sys.stderr,
|
|
293
|
+
)
|
|
294
|
+
return body
|
|
295
|
+
if not resolved_target.is_file():
|
|
296
|
+
return body
|
|
297
|
+
line = _first_prose_line(resolved_target)
|
|
298
|
+
if not line:
|
|
299
|
+
return body
|
|
300
|
+
return _resolve_include_marker(line, root, depth + 1)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def extract_sections(path: Path) -> list:
|
|
304
|
+
"""Returns [(header, body), ...] in source order, with backfill applied."""
|
|
305
|
+
rows = [] # each (header, body) — body may start empty
|
|
306
|
+
header = None
|
|
307
|
+
body = ""
|
|
308
|
+
collecting = False
|
|
309
|
+
|
|
310
|
+
def flush():
|
|
311
|
+
nonlocal header, body
|
|
312
|
+
if header is not None:
|
|
313
|
+
rows.append((header, body))
|
|
314
|
+
header = None
|
|
315
|
+
body = ""
|
|
316
|
+
|
|
317
|
+
with path.open("r", encoding="utf-8", errors="replace") as fh:
|
|
318
|
+
for line in _skip_fenced_lines(fh):
|
|
319
|
+
if _H4_PLUS_RE.match(line):
|
|
320
|
+
flush()
|
|
321
|
+
collecting = False
|
|
322
|
+
continue
|
|
323
|
+
m3 = _H3_RE.match(line)
|
|
324
|
+
if m3:
|
|
325
|
+
flush()
|
|
326
|
+
header = m3.group(1)
|
|
327
|
+
collecting = True
|
|
328
|
+
body = ""
|
|
329
|
+
continue
|
|
330
|
+
m2 = _H2_RE.match(line)
|
|
331
|
+
if m2:
|
|
332
|
+
flush()
|
|
333
|
+
header = m2.group(1)
|
|
334
|
+
collecting = True
|
|
335
|
+
body = ""
|
|
336
|
+
continue
|
|
337
|
+
if _H1_RE.match(line):
|
|
338
|
+
flush()
|
|
339
|
+
collecting = False
|
|
340
|
+
continue
|
|
341
|
+
if collecting and not body and line.strip():
|
|
342
|
+
stripped = _BULLET_RE.sub("", line, count=1)
|
|
343
|
+
body = stripped
|
|
344
|
+
flush()
|
|
345
|
+
|
|
346
|
+
rows = [
|
|
347
|
+
(header, _resolve_include_marker(body, path.parent)) for header, body in rows
|
|
348
|
+
]
|
|
349
|
+
|
|
350
|
+
# Backfill empty bodies from the next non-empty body in source order.
|
|
351
|
+
for i in range(len(rows)):
|
|
352
|
+
if not rows[i][1].strip():
|
|
353
|
+
for j in range(i + 1, len(rows)):
|
|
354
|
+
if rows[j][1].strip():
|
|
355
|
+
rows[i] = (rows[i][0], rows[j][1])
|
|
356
|
+
break
|
|
357
|
+
|
|
358
|
+
return rows
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
# ---------------------------------------------------------------------------
|
|
362
|
+
# Per-file section objects with slug + header disambiguation.
|
|
363
|
+
# ---------------------------------------------------------------------------
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
def file_entry(rows: list) -> "dict":
|
|
367
|
+
"""Build the {header: {summary, anchor}} mapping for one file.
|
|
368
|
+
|
|
369
|
+
Preserves source order, applies GitHub-style slug disambiguation
|
|
370
|
+
(`overview` / `overview-1` / `overview-2`) and parallel header-key
|
|
371
|
+
disambiguation (`Overview (2)`, `Overview (3)`) so JSON keys remain
|
|
372
|
+
unique even when the source has duplicate H2/H3 headers.
|
|
373
|
+
"""
|
|
374
|
+
out = {}
|
|
375
|
+
slug_seen = {} # base_slug → count seen so far
|
|
376
|
+
header_seen = {} # raw header → count seen so far
|
|
377
|
+
for header, body in rows:
|
|
378
|
+
if not header:
|
|
379
|
+
continue
|
|
380
|
+
base = slugify(header)
|
|
381
|
+
n = slug_seen.get(base, 0)
|
|
382
|
+
anchor = base if n == 0 else f"{base}-{n}"
|
|
383
|
+
slug_seen[base] = n + 1
|
|
384
|
+
|
|
385
|
+
hc = header_seen.get(header, 0)
|
|
386
|
+
key = header if hc == 0 else f"{header} ({hc + 1})"
|
|
387
|
+
header_seen[header] = hc + 1
|
|
388
|
+
|
|
389
|
+
out[key] = {"summary": first_sentence(body), "anchor": anchor}
|
|
390
|
+
return out
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
# ---------------------------------------------------------------------------
|
|
394
|
+
# Corpus discovery — must match the shell's LC_ALL=C sorted order.
|
|
395
|
+
# ---------------------------------------------------------------------------
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def discover_files(roots: Path) -> list:
|
|
399
|
+
paths = []
|
|
400
|
+
knowledge = roots / "knowledge"
|
|
401
|
+
if knowledge.is_dir():
|
|
402
|
+
paths.extend(
|
|
403
|
+
p for p in knowledge.iterdir() if p.is_file() and p.suffix == ".md"
|
|
404
|
+
)
|
|
405
|
+
skills = roots / "skills"
|
|
406
|
+
if skills.is_dir():
|
|
407
|
+
for child in skills.iterdir():
|
|
408
|
+
if not child.is_dir():
|
|
409
|
+
continue
|
|
410
|
+
skill = child / "SKILL.md"
|
|
411
|
+
if skill.is_file():
|
|
412
|
+
paths.append(skill)
|
|
413
|
+
# Sort with C locale semantics: codepoint order on absolute path.
|
|
414
|
+
paths.sort(key=lambda p: str(p))
|
|
415
|
+
return paths
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
# ---------------------------------------------------------------------------
|
|
419
|
+
# Output — byte-identical to `jq -s 'add'` of per-file objects:
|
|
420
|
+
# 2-space indent, ": " separator, no trailing newline.
|
|
421
|
+
# ---------------------------------------------------------------------------
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def build_index_text(roots: Path) -> str:
|
|
425
|
+
index = {}
|
|
426
|
+
for path in discover_files(roots):
|
|
427
|
+
rel = path.relative_to(roots)
|
|
428
|
+
# The roots env var may point at the plugin dir; reattach the
|
|
429
|
+
# plugin prefix so keys are repo-relative.
|
|
430
|
+
rel_key = f"plugins/dev-team/{rel.as_posix()}"
|
|
431
|
+
rows = extract_sections(path)
|
|
432
|
+
if not rows:
|
|
433
|
+
continue
|
|
434
|
+
index[rel_key] = file_entry(rows)
|
|
435
|
+
# jq's `add` output ends with a trailing newline; preserve that so
|
|
436
|
+
# the freshness gate stays byte-identical across the rewrite.
|
|
437
|
+
return json.dumps(index, indent=2, ensure_ascii=False) + "\n"
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
# ---------------------------------------------------------------------------
|
|
441
|
+
# Atomic publish — never truncate the live index in place.
|
|
442
|
+
#
|
|
443
|
+
# The index is read by other tooling (and, under parallel test runs, by
|
|
444
|
+
# concurrent readers). A plain truncate-then-stream write exposes a window in
|
|
445
|
+
# which a reader observes an empty or partial file. Writing to a sibling temp
|
|
446
|
+
# file in the same directory and renaming it over the destination makes the
|
|
447
|
+
# publish atomic: every reader sees either the whole old file or the whole new
|
|
448
|
+
# file, never a half-written one. os.replace is an atomic rename on POSIX.
|
|
449
|
+
# ---------------------------------------------------------------------------
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
def _atomic_write(output: Path, text: str) -> None:
|
|
453
|
+
fd, tmp_name = tempfile.mkstemp(
|
|
454
|
+
dir=str(output.parent), prefix=f".{output.name}.", suffix=".tmp"
|
|
455
|
+
)
|
|
456
|
+
tmp = Path(tmp_name)
|
|
457
|
+
try:
|
|
458
|
+
with os.fdopen(fd, "w", encoding="utf-8") as fh:
|
|
459
|
+
fh.write(text)
|
|
460
|
+
os.replace(tmp, output)
|
|
461
|
+
except BaseException:
|
|
462
|
+
# Don't leave a partial temp file behind if the write/rename failed.
|
|
463
|
+
tmp.unlink(missing_ok=True)
|
|
464
|
+
raise
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
# ---------------------------------------------------------------------------
|
|
468
|
+
# Entry points — write mode and --check.
|
|
469
|
+
# ---------------------------------------------------------------------------
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
def main(argv: list) -> int:
|
|
473
|
+
roots, output = _resolve_paths()
|
|
474
|
+
mode = argv[1] if len(argv) > 1 else "write"
|
|
475
|
+
|
|
476
|
+
actual = build_index_text(roots)
|
|
477
|
+
|
|
478
|
+
if mode == "--check":
|
|
479
|
+
if not output.exists():
|
|
480
|
+
sys.stderr.write(f"[knowledge-index] index file missing: {output}\n")
|
|
481
|
+
return 1
|
|
482
|
+
expected = output.read_text(encoding="utf-8")
|
|
483
|
+
if actual == expected:
|
|
484
|
+
return 0
|
|
485
|
+
diff = difflib.unified_diff(
|
|
486
|
+
expected.splitlines(keepends=True),
|
|
487
|
+
actual.splitlines(keepends=True),
|
|
488
|
+
fromfile=str(output),
|
|
489
|
+
tofile="<fresh build>",
|
|
490
|
+
)
|
|
491
|
+
sys.stderr.writelines(diff)
|
|
492
|
+
return 1
|
|
493
|
+
|
|
494
|
+
if mode in ("write", ""):
|
|
495
|
+
output.parent.mkdir(parents=True, exist_ok=True)
|
|
496
|
+
_atomic_write(output, actual)
|
|
497
|
+
return 0
|
|
498
|
+
|
|
499
|
+
sys.stderr.write(f"Unknown mode: {mode}\n")
|
|
500
|
+
return 2
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
if __name__ == "__main__":
|
|
504
|
+
sys.exit(main(sys.argv))
|