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,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The state machine behind the /dev-team usage overlay: which scope and view are shown and how the
|
|
3
|
+
* this-month load is going. Pure: `reduce` maps a state and an action (a key, or news from the load)
|
|
4
|
+
* to the next state plus the effects the view must carry out (start or cancel the load, close), so
|
|
5
|
+
* every rule is testable without pi or a terminal. Mapping raw terminal input to a UsageKey lives
|
|
6
|
+
* here too, as it is the machine's other input.
|
|
7
|
+
*/
|
|
8
|
+
import { Key, type KeyId, matchesKey } from "@earendil-works/pi-tui";
|
|
9
|
+
|
|
10
|
+
export type Scope = "session" | "month";
|
|
11
|
+
export type View = "model" | "provider" | "agent";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The this-month history load. It outlives the scope: "ready" is kept when the user goes back to this
|
|
15
|
+
* session, so pressing `s` again shows the loaded month at once. A cancelled or failed load is "idle"
|
|
16
|
+
* again, so `s` restarts it. In this-session scope the load is therefore only ever idle or ready.
|
|
17
|
+
*/
|
|
18
|
+
export type LoadState =
|
|
19
|
+
| { kind: "idle" }
|
|
20
|
+
| { kind: "loading"; progress?: { done: number; total: number } }
|
|
21
|
+
| { kind: "ready" }
|
|
22
|
+
| { kind: "error"; reason: string };
|
|
23
|
+
|
|
24
|
+
export interface UsageState {
|
|
25
|
+
scope: Scope;
|
|
26
|
+
view: View;
|
|
27
|
+
load: LoadState;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** What a key press means, independent of which key produced it. */
|
|
31
|
+
export type UsageKey = "next-view" | "previous-view" | "toggle-scope" | "close";
|
|
32
|
+
|
|
33
|
+
export type UsageAction =
|
|
34
|
+
| { type: "key"; key: UsageKey }
|
|
35
|
+
| { type: "progress"; done: number; total: number }
|
|
36
|
+
| { type: "loaded" }
|
|
37
|
+
| { type: "failed"; reason: string };
|
|
38
|
+
|
|
39
|
+
/** What the view must do besides re-render. */
|
|
40
|
+
export type UsageEffect = "start-load" | "cancel-load" | "close";
|
|
41
|
+
|
|
42
|
+
export interface Transition {
|
|
43
|
+
state: UsageState;
|
|
44
|
+
effects: UsageEffect[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Left to right as Tab walks them. */
|
|
48
|
+
const VIEWS: readonly View[] = ["model", "provider", "agent"];
|
|
49
|
+
|
|
50
|
+
const LOADING: LoadState = { kind: "loading" };
|
|
51
|
+
const IDLE: LoadState = { kind: "idle" };
|
|
52
|
+
|
|
53
|
+
/** The state a freshly opened overlay starts in: By model, with the month's load started when it opens on the month. */
|
|
54
|
+
export function openUsage(scope: Scope): Transition {
|
|
55
|
+
if (scope === "month") return { state: { scope, view: "model", load: LOADING }, effects: ["start-load"] };
|
|
56
|
+
return { state: { scope, view: "model", load: IDLE }, effects: [] };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function stepView(state: UsageState, step: number): Transition {
|
|
60
|
+
const next = VIEWS[(VIEWS.indexOf(state.view) + step + VIEWS.length) % VIEWS.length];
|
|
61
|
+
return { state: { ...state, view: next }, effects: [] };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** `s`: this session to this month (loading it unless already loaded), and back (cancelling a load still running). */
|
|
65
|
+
function toggleScope(state: UsageState): Transition {
|
|
66
|
+
if (state.scope === "session") {
|
|
67
|
+
if (state.load.kind === "ready") return { state: { ...state, scope: "month" }, effects: [] };
|
|
68
|
+
return { state: { ...state, scope: "month", load: LOADING }, effects: ["start-load"] };
|
|
69
|
+
}
|
|
70
|
+
const cancelling = state.load.kind === "loading";
|
|
71
|
+
const load = state.load.kind === "ready" ? state.load : IDLE;
|
|
72
|
+
return { state: { ...state, scope: "session", load }, effects: cancelling ? ["cancel-load"] : [] };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function pressKey(state: UsageState, key: UsageKey): Transition {
|
|
76
|
+
switch (key) {
|
|
77
|
+
case "next-view":
|
|
78
|
+
return stepView(state, 1);
|
|
79
|
+
case "previous-view":
|
|
80
|
+
return stepView(state, -1);
|
|
81
|
+
case "toggle-scope":
|
|
82
|
+
return toggleScope(state);
|
|
83
|
+
case "close":
|
|
84
|
+
return { state, effects: state.load.kind === "loading" ? ["cancel-load", "close"] : ["close"] };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** News about the load only counts while one is running: a late event from a cancelled load is dropped. */
|
|
89
|
+
function loadEvent(state: UsageState, action: Exclude<UsageAction, { type: "key" }>): Transition {
|
|
90
|
+
if (state.load.kind !== "loading") return { state, effects: [] };
|
|
91
|
+
switch (action.type) {
|
|
92
|
+
case "progress":
|
|
93
|
+
return { state: { ...state, load: { kind: "loading", progress: { done: action.done, total: action.total } } }, effects: [] };
|
|
94
|
+
case "loaded":
|
|
95
|
+
return { state: { ...state, load: { kind: "ready" } }, effects: [] };
|
|
96
|
+
case "failed":
|
|
97
|
+
return { state: { ...state, load: { kind: "error", reason: action.reason } }, effects: [] };
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function reduce(state: UsageState, action: UsageAction): Transition {
|
|
102
|
+
return action.type === "key" ? pressKey(state, action.key) : loadEvent(state, action);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Letters match in either case (`s` and `S`); Shift+Tab is its own key, so it steps back. */
|
|
106
|
+
const KEY_TABLE: readonly { key: UsageKey; ids: readonly KeyId[] }[] = [
|
|
107
|
+
{ key: "next-view", ids: [Key.tab] },
|
|
108
|
+
{ key: "previous-view", ids: [Key.shift("tab")] },
|
|
109
|
+
{ key: "toggle-scope", ids: ["s", Key.shift("s")] },
|
|
110
|
+
{ key: "close", ids: [Key.escape, "q", Key.shift("q"), Key.ctrl("c")] },
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
/** The action a chunk of terminal input stands for, or undefined for any other key. */
|
|
114
|
+
export function usageKeyFor(data: string): UsageKey | undefined {
|
|
115
|
+
return KEY_TABLE.find(({ ids }) => ids.some((id) => matchesKey(data, id)))?.key;
|
|
116
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The plain-text usage summary for /dev-team usage when no overlay can be shown (print mode, RPC),
|
|
3
|
+
* and the wording both it and the overlay (usage-render.ts) use: scope names, view titles, header
|
|
4
|
+
* pieces, empty-state, failure and footnote sentences. Keeping the sentences here is what keeps the
|
|
5
|
+
* two presentations saying the same thing.
|
|
6
|
+
*/
|
|
7
|
+
import { formatAiCredits, formatCredits, hasVisibleCredits, usageMonthStart } from "./ai-credits.ts";
|
|
8
|
+
import {
|
|
9
|
+
formatShare,
|
|
10
|
+
formatTokens,
|
|
11
|
+
formatUsd,
|
|
12
|
+
hasUsage,
|
|
13
|
+
type MonthSnapshot,
|
|
14
|
+
type SpendAmounts,
|
|
15
|
+
THREAD_ORDER,
|
|
16
|
+
type UsageBreakdown,
|
|
17
|
+
type UsageRow,
|
|
18
|
+
} from "./usage-breakdown.ts";
|
|
19
|
+
import type { BarChartOptions, ChartFormat } from "./usage-chart.ts";
|
|
20
|
+
import { toSpacedSingleLine, toSingleLine } from "./terminal-text.ts";
|
|
21
|
+
import type { Scope, View } from "./usage-state.ts";
|
|
22
|
+
|
|
23
|
+
export const SEPARATOR = " · ";
|
|
24
|
+
export const SCOPE_TITLE: Record<Scope, string> = { session: "This session", month: "This month" };
|
|
25
|
+
export const SCOPE_NOUN: Record<Scope, string> = { session: "this session", month: "this month" };
|
|
26
|
+
export const VIEW_TITLE: Record<View, string> = { model: "By model", provider: "By provider", agent: "By agent" };
|
|
27
|
+
/** Joins an agent and its provider in an agent row's label. */
|
|
28
|
+
export const AGENT_PROVIDER_SEPARATOR = " · ";
|
|
29
|
+
/** The chart area's text while this month's files are read; the overlay appends the progress. */
|
|
30
|
+
export const READING_SESSIONS = "Reading sessions…";
|
|
31
|
+
|
|
32
|
+
/** "in this session", "this month": how a sentence refers to the scope. */
|
|
33
|
+
export const scopePhrase = (scope: Scope) => (scope === "session" ? "in this session" : "this month");
|
|
34
|
+
|
|
35
|
+
const monthDay = (date: Date) => date.toLocaleDateString("en-US", { month: "short", day: "numeric", timeZone: "UTC" });
|
|
36
|
+
|
|
37
|
+
/** "This session", or "This month (Oct 1 – Oct 4)": the month's UTC dates, 1st to `now`. */
|
|
38
|
+
export function scopeHeading(scope: Scope, now: Date): string {
|
|
39
|
+
if (scope === "session") return SCOPE_TITLE.session;
|
|
40
|
+
return `${SCOPE_TITLE.month} (${monthDay(usageMonthStart(now))} – ${monthDay(now)})`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** "as of 14:05": local time, so it reads against the user's own clock. */
|
|
44
|
+
export const asOfLabel = (date: Date) => `as of ${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
|
|
45
|
+
|
|
46
|
+
/** A row's AI credits in a column: "210 cr", or "" when Copilot served none of it. */
|
|
47
|
+
export const formatCreditsCell = (credits: number) => (hasVisibleCredits(credits) ? `${formatCredits(credits)} cr` : "");
|
|
48
|
+
|
|
49
|
+
/** How the chart and the summary write each amount. */
|
|
50
|
+
export const CHART_FORMAT: ChartFormat = { usd: formatUsd, credits: formatCreditsCell, tokens: formatTokens, share: formatShare };
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The optional columns a view's rows want, for the overlay's chart and the text summary alike: AI
|
|
54
|
+
* credits when any row has some, tokens when any row cost nothing (so a free model still says what it
|
|
55
|
+
* used). Judged over every row, before the chart folds any into "other".
|
|
56
|
+
*/
|
|
57
|
+
export function wantedColumns(rows: readonly UsageRow[]): BarChartOptions["wantedColumns"] {
|
|
58
|
+
return { credits: rows.some((r) => hasVisibleCredits(r.credits)), tokens: rows.some((r) => !(r.usd > 0)) };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** The total as header parts: "$4.20", then "312 AI credits" when Copilot served any of it. USD is always first. */
|
|
62
|
+
export function totalHeaderParts(total: SpendAmounts): string[] {
|
|
63
|
+
return [formatUsd(total.usd), ...(hasVisibleCredits(total.credits) ? [formatAiCredits(total.credits)] : [])];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** The ranked rows of a view; an agent row is labelled "agent · provider". */
|
|
67
|
+
export function viewRows(view: View, breakdown: UsageBreakdown): UsageRow[] {
|
|
68
|
+
if (view === "model") return breakdown.byModel;
|
|
69
|
+
if (view === "provider") return breakdown.byProvider;
|
|
70
|
+
return breakdown.byAgent.map((row) => ({ ...row, label: `${row.label}${AGENT_PROVIDER_SEPARATOR}${row.provider}` }));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** One split of the total: its parts in drawing order, each with its USD and share of the total. */
|
|
74
|
+
export interface SplitSection {
|
|
75
|
+
title: "Providers" | "Threads";
|
|
76
|
+
/** How the overlay's legend names a part's amount. */
|
|
77
|
+
legend: "share" | "usd";
|
|
78
|
+
parts: { label: string; usd: number; share: number }[];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The splits both presentations show. Providers: only when two or more have a cost, the paid ones in
|
|
83
|
+
* rank order. Threads: always main, subagents, overhead, in that order; a thread that spent nothing
|
|
84
|
+
* stays with 0 so it keeps its place and its glyph. None when nothing cost anything.
|
|
85
|
+
*/
|
|
86
|
+
export function splitSections(breakdown: UsageBreakdown): SplitSection[] {
|
|
87
|
+
const total = breakdown.total.usd;
|
|
88
|
+
if (!(total > 0)) return [];
|
|
89
|
+
const part = (label: string, usd: number) => ({ label, usd, share: usd / total });
|
|
90
|
+
const paidProviders = breakdown.byProvider.filter((r) => r.usd > 0);
|
|
91
|
+
const providers: SplitSection[] = paidProviders.length > 1 ? [{ title: "Providers", legend: "share", parts: paidProviders.map((r) => part(r.label, r.usd)) }] : [];
|
|
92
|
+
const threadUsd = new Map(breakdown.byThread.map((r) => [r.label, r.usd]));
|
|
93
|
+
return [...providers, { title: "Threads", legend: "usd", parts: THREAD_ORDER.map((label) => part(label, threadUsd.get(label) ?? 0)) }];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export const emptyUsageMessage = (scope: Scope) => `No usage ${scopePhrase(scope)}`;
|
|
97
|
+
export const noSubagentUsageMessage = (scope: Scope) => `No subagent usage ${scopePhrase(scope)}`;
|
|
98
|
+
|
|
99
|
+
/** Appended to the empty session message: this month may have spend even when this session has none. */
|
|
100
|
+
export const pressSHint = (scope: Scope) => (scope === "session" ? " — press s for this month" : "");
|
|
101
|
+
|
|
102
|
+
/** The reason is an error's message and may carry escape sequences, control characters or newlines: sequences go, each run of controls becomes one space. */
|
|
103
|
+
export const loadFailedMessage = (reason: string) => `Could not load history: ${toSpacedSingleLine(reason)}`;
|
|
104
|
+
|
|
105
|
+
/** The text of whatever a load rejected with. */
|
|
106
|
+
export const errorReason = (err: unknown): string => (err instanceof Error ? err.message : String(err));
|
|
107
|
+
|
|
108
|
+
/** The footnote for session files that could not be read, or undefined when every file was. */
|
|
109
|
+
export function unreadableFilesNote(unreadable: number): string | undefined {
|
|
110
|
+
return unreadable > 0 ? `${unreadable} session ${unreadable === 1 ? "file" : "files"} could not be read` : undefined;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface UsageSummaryInput {
|
|
114
|
+
scope: Scope;
|
|
115
|
+
breakdown: UsageBreakdown;
|
|
116
|
+
now: Date;
|
|
117
|
+
/** Present for this month: how the load went. */
|
|
118
|
+
month?: Omit<MonthSnapshot, "breakdown">;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Rows as aligned " label usd credits tokens share" lines, with the columns wantedColumns() asks for. */
|
|
122
|
+
function rankedLines(rows: readonly UsageRow[]): string[] {
|
|
123
|
+
const columns = wantedColumns(rows);
|
|
124
|
+
const cells = rows.map((r) => [
|
|
125
|
+
toSingleLine(r.label),
|
|
126
|
+
CHART_FORMAT.usd(r.usd),
|
|
127
|
+
...(columns.credits ? [CHART_FORMAT.credits(r.credits)] : []),
|
|
128
|
+
...(columns.tokens ? [CHART_FORMAT.tokens(r.tokens)] : []),
|
|
129
|
+
CHART_FORMAT.share(r.share),
|
|
130
|
+
]);
|
|
131
|
+
const widths = cells[0].map((_, column) => Math.max(...cells.map((row) => row[column].length)));
|
|
132
|
+
return cells.map((row) => ` ${row.map((cell, column) => (column === 0 ? cell.padEnd(widths[column]) : cell.padStart(widths[column]))).join(" ")}`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** "Providers github-copilot $3.12 74.3% · openai $1.08 25.7%": the parts that spent something. */
|
|
136
|
+
function splitLine({ title, parts }: SplitSection): string {
|
|
137
|
+
const spent = parts.filter((p) => p.usd > 0);
|
|
138
|
+
return `${title} ${spent.map((p) => `${toSingleLine(p.label)} ${formatUsd(p.usd)} ${formatShare(p.share)}`).join(SEPARATOR)}`;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Header, the provider and thread splits, then models, providers and agents ranked; or the empty-state sentence. Either way the unreadable-files note ends it, as in the overlay. */
|
|
142
|
+
export function usageSummary({ scope, breakdown, now, month }: UsageSummaryInput): string {
|
|
143
|
+
const note = unreadableFilesNote(month?.unreadable ?? 0);
|
|
144
|
+
const noteLines = note ? ["", note] : [];
|
|
145
|
+
if (!hasUsage(breakdown.total)) return [emptyUsageMessage(scope), ...noteLines].join("\n");
|
|
146
|
+
const header = [scopeHeading(scope, now), ...totalHeaderParts(breakdown.total), ...(month ? [asOfLabel(month.loadedAt)] : [])].join(SEPARATOR);
|
|
147
|
+
const section = (view: View) => {
|
|
148
|
+
const rows = viewRows(view, breakdown);
|
|
149
|
+
return ["", VIEW_TITLE[view], ...(rows.length ? rankedLines(rows) : [` ${noSubagentUsageMessage(scope)}`])];
|
|
150
|
+
};
|
|
151
|
+
return [
|
|
152
|
+
header,
|
|
153
|
+
...splitSections(breakdown).map(splitLine),
|
|
154
|
+
...section("model"),
|
|
155
|
+
...section("provider"),
|
|
156
|
+
...section("agent"),
|
|
157
|
+
...noteLines,
|
|
158
|
+
].join("\n");
|
|
159
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The /dev-team usage overlay component. It holds the state machine's state (usage-state.ts), turns
|
|
3
|
+
* keys into transitions, runs this month's load and hands the model to renderUsage (usage-render.ts).
|
|
4
|
+
*/
|
|
5
|
+
import type { Component } from "@earendil-works/pi-tui";
|
|
6
|
+
import type { SpendRun } from "./session-spend.ts";
|
|
7
|
+
import { type MonthSnapshot, monthSnapshot, type UsageBreakdown, usageBreakdown } from "./usage-breakdown.ts";
|
|
8
|
+
import type { LoadOptions, SpendHistory } from "./usage-history.ts";
|
|
9
|
+
import { usageMonthStart } from "./ai-credits.ts";
|
|
10
|
+
import { renderUsage, type UsageStyle } from "./usage-render.ts";
|
|
11
|
+
import { reduce, type Transition, type UsageAction, type UsageEffect, type UsageState, usageKeyFor } from "./usage-state.ts";
|
|
12
|
+
import { errorReason } from "./usage-text.ts";
|
|
13
|
+
|
|
14
|
+
/** The overlay may take this share of the terminal's height; the command passes the same to pi as `maxHeight`. */
|
|
15
|
+
export const OVERLAY_HEIGHT_PERCENT = 90;
|
|
16
|
+
|
|
17
|
+
export interface UsageViewDeps {
|
|
18
|
+
/** This session's runs; read again after `invalidate()`. */
|
|
19
|
+
sessionRuns(): readonly SpendRun[];
|
|
20
|
+
now(): Date;
|
|
21
|
+
/** The terminal's height in rows. */
|
|
22
|
+
terminalRows(): number;
|
|
23
|
+
style: UsageStyle;
|
|
24
|
+
requestRender(): void;
|
|
25
|
+
/** Closes the overlay. */
|
|
26
|
+
close(): void;
|
|
27
|
+
/** Reads this month's spend from the saved sessions; the view cancels it through `signal`. */
|
|
28
|
+
loadHistory(options: Required<Omit<LoadOptions, "root">>): Promise<SpendHistory>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** The overlay component: owns the state, turns keys into transitions, runs the month's load and renders the model. */
|
|
32
|
+
export class UsageView implements Component {
|
|
33
|
+
private readonly deps: UsageViewDeps;
|
|
34
|
+
private state: UsageState;
|
|
35
|
+
private session: UsageBreakdown | undefined;
|
|
36
|
+
private month: MonthSnapshot | undefined;
|
|
37
|
+
/** The load in flight. Whatever else holds a different controller (or none) is a stale load whose news is dropped. */
|
|
38
|
+
private activeLoad: AbortController | undefined;
|
|
39
|
+
|
|
40
|
+
constructor(deps: UsageViewDeps, initial: Transition) {
|
|
41
|
+
this.deps = deps;
|
|
42
|
+
this.state = initial.state;
|
|
43
|
+
this.runEffects(initial.effects);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
render(width: number): string[] {
|
|
47
|
+
this.session ??= usageBreakdown(this.deps.sessionRuns());
|
|
48
|
+
const height = Math.max(1, Math.floor((this.deps.terminalRows() * OVERLAY_HEIGHT_PERCENT) / 100));
|
|
49
|
+
return renderUsage({ state: this.state, session: this.session, month: this.month, now: this.deps.now() }, { width, height, style: this.deps.style });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
handleInput(data: string): void {
|
|
53
|
+
const key = usageKeyFor(data);
|
|
54
|
+
if (key) this.dispatch({ type: "key", key });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
invalidate(): void {
|
|
58
|
+
this.session = undefined;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Called by pi when the overlay goes away; a load still running is of no use any more. */
|
|
62
|
+
dispose(): void {
|
|
63
|
+
this.cancelLoad();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private dispatch(action: UsageAction): void {
|
|
67
|
+
const { state, effects } = reduce(this.state, action);
|
|
68
|
+
this.state = state;
|
|
69
|
+
this.runEffects(effects);
|
|
70
|
+
this.deps.requestRender();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private runEffects(effects: readonly UsageEffect[]): void {
|
|
74
|
+
for (const effect of effects) {
|
|
75
|
+
if (effect === "start-load") this.startLoad();
|
|
76
|
+
else if (effect === "cancel-load") this.cancelLoad();
|
|
77
|
+
else this.deps.close();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private startLoad(): void {
|
|
82
|
+
const controller = new AbortController();
|
|
83
|
+
this.activeLoad = controller;
|
|
84
|
+
const isCurrentLoad = () => this.activeLoad === controller;
|
|
85
|
+
const since = usageMonthStart(this.deps.now());
|
|
86
|
+
const onProgress = (done: number, total: number) => {
|
|
87
|
+
if (isCurrentLoad()) this.dispatch({ type: "progress", done, total });
|
|
88
|
+
};
|
|
89
|
+
// The snapshot is built inside the async function, so anything it throws is a failed load too.
|
|
90
|
+
(async () => monthSnapshot(await this.deps.loadHistory({ since, signal: controller.signal, onProgress }), this.deps.now()))().then(
|
|
91
|
+
(snapshot) => {
|
|
92
|
+
if (!isCurrentLoad()) return;
|
|
93
|
+
this.activeLoad = undefined;
|
|
94
|
+
this.month = snapshot;
|
|
95
|
+
this.dispatch({ type: "loaded" });
|
|
96
|
+
},
|
|
97
|
+
(err: unknown) => {
|
|
98
|
+
if (!isCurrentLoad()) return;
|
|
99
|
+
this.activeLoad = undefined;
|
|
100
|
+
this.dispatch({ type: "failed", reason: errorReason(err) });
|
|
101
|
+
},
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private cancelLoad(): void {
|
|
106
|
+
this.activeLoad?.abort();
|
|
107
|
+
this.activeLoad = undefined;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""agent_dispatch_ledger.py — PreToolUse dispatch-ledger hook (#1461).
|
|
3
|
+
|
|
4
|
+
Registered in `settings.json`'s existing `PreToolUse` `"Agent|Task"` matcher
|
|
5
|
+
(alongside `subagent_skill_context.py`). Records a `boundary-events.jsonl`
|
|
6
|
+
`"record"` event whenever a genuine review-agent dispatch fires, so
|
|
7
|
+
`hooks/pre_commit_review.py`'s `.review-passed` gate can later corroborate
|
|
8
|
+
that a hash-matching write was backed by real, independent Agent-tool
|
|
9
|
+
dispatches — not just a self-computed hash (issue #1461's residual gap; see
|
|
10
|
+
`hooks/lib/review_gate_hash.py`'s own docstring for the full account).
|
|
11
|
+
|
|
12
|
+
On each Agent/Task dispatch, reads `tool_input.subagent_type`. If and only if
|
|
13
|
+
it is present in `hooks/lib/review_agent_registry`'s closed set of registered
|
|
14
|
+
`agents/*-review.md` stems, records one `"record"` boundary event carrying
|
|
15
|
+
that agent name as `matched_rule`, stamped with a `subject_hash` binding this
|
|
16
|
+
dispatch to whatever content is under review right now, so a review of one
|
|
17
|
+
changeset can't later corroborate an unrelated one (#1461 security review).
|
|
18
|
+
Anything not in the closed set — a typo, a non-review team agent, or a
|
|
19
|
+
fabricated name — is silently NOT recorded, never written as free text:
|
|
20
|
+
matching `boundary_events.py`'s own no-free-text constraint (rule IDs /
|
|
21
|
+
closed-vocabulary values only, never arbitrary strings). `"record"` is a new,
|
|
22
|
+
fifth-plus decision value: an observation, not a block/warn/bypass/
|
|
23
|
+
intervention/revert policy verdict — see `knowledge/telemetry-schema.md` for
|
|
24
|
+
its full documentation.
|
|
25
|
+
|
|
26
|
+
**`subject_hash` selection (#1904 Bug 2b, revised from the original
|
|
27
|
+
staged-diff-only stamp):** the staged patch (`review_gate_hash()`) is empty
|
|
28
|
+
by definition during a `--since <base>`-scoped `/code-review` run
|
|
29
|
+
(`skills/pr/SKILL.md`'s only path to `gh pr create` — its step 1 requires a
|
|
30
|
+
CLEAN working tree before that review runs, so nothing is ever staged during
|
|
31
|
+
it). Stamping the constant `EMPTY_DIGEST` in that case would be exactly the
|
|
32
|
+
Bug 1 hazard `review_gate_hash.py`'s own docstring warns against, AND it
|
|
33
|
+
would leave this hook's evidence unable to corroborate
|
|
34
|
+
`hooks/pre_pr_review.py`'s gate at all for that mode (that gate always
|
|
35
|
+
compares against `branch_diff_gate_hash()`, never the staged-diff hash).
|
|
36
|
+
So: when the staged diff is empty, fall back to
|
|
37
|
+
`branch_diff_gate_hash(default_base_ref(cwd), cwd)` — the SAME content
|
|
38
|
+
domain `hooks/pre_pr_review.py` checks and `skills/code-review/SKILL.md`
|
|
39
|
+
step 9 now writes for a `--since <base>`-scoped review — and refuse to stamp
|
|
40
|
+
(`None`) rather than fall back to the empty digest a second time. The
|
|
41
|
+
ordinary auto-scope path (something IS staged) is unchanged: it still stamps
|
|
42
|
+
`review_gate_hash()`, matching step 9's own disclosed "identical only in the
|
|
43
|
+
common single-commit-then-PR shape" limitation for that mode.
|
|
44
|
+
|
|
45
|
+
Fail-open, matching this codebase's own hook convention (and
|
|
46
|
+
`emit_boundary_event`'s own fail-open write side): any error here — a
|
|
47
|
+
missing/unreadable `agents/` directory, a malformed payload, an exception
|
|
48
|
+
from the shared helper — must never block a real Agent dispatch. This hook
|
|
49
|
+
always exits 0.
|
|
50
|
+
|
|
51
|
+
KNOWN RESIDUAL GAP (#1461 security re-review): this module is itself a
|
|
52
|
+
directly executable script that reads an attacker-/self-controlled stdin
|
|
53
|
+
payload. Anyone with Bash access to this repo can run
|
|
54
|
+
`echo '{"tool_name":"Task","tool_input":{"subagent_type":"security-review"},
|
|
55
|
+
"cwd":"."}' | python3 hooks/agent_dispatch_ledger.py` (repeated with a second
|
|
56
|
+
registered agent stem) and produce two byte-genuine "record" rows, correctly
|
|
57
|
+
subject-hash-bound, with NO actual Agent/Task dispatch ever occurring. Locking
|
|
58
|
+
down `boundary_events.py`'s CLI (this module's sibling forgery vector) does
|
|
59
|
+
not close this one — the forge just moves one file over. Registered agent
|
|
60
|
+
names are public filenames, so the registry re-validation in
|
|
61
|
+
`review_gate_corroboration.py` does not help either. This is not fixable at
|
|
62
|
+
this module's level: it requires the harness itself to supply something a
|
|
63
|
+
hand-run process cannot fabricate (a signed dispatch receipt, or a
|
|
64
|
+
session/turn-identity check against a live stream the harness — not this
|
|
65
|
+
script — controls). Until that exists, this control raises the bar against
|
|
66
|
+
an agent that takes an *accidental* self-certification shortcut under
|
|
67
|
+
ambiguity (this issue's original, observed failure mode); it is not effective
|
|
68
|
+
against a deliberate, adversarial bypass. See
|
|
69
|
+
`hooks/pre_commit_review.py`'s module docstring for the matching disclosure
|
|
70
|
+
on the read side.
|
|
71
|
+
|
|
72
|
+
Contract (docs/python-hook-contract.md):
|
|
73
|
+
Input : PreToolUse JSON on stdin (Agent/Task matcher)
|
|
74
|
+
Output: always exit 0 — fail-open, this hook never blocks a dispatch.
|
|
75
|
+
|
|
76
|
+
Stdlib only. See ADR 0014 / ADR 0015.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
from __future__ import annotations
|
|
80
|
+
|
|
81
|
+
import sys
|
|
82
|
+
from pathlib import Path
|
|
83
|
+
|
|
84
|
+
_HOOK_DIR = Path(__file__).resolve().parent
|
|
85
|
+
_LIB_DIR = _HOOK_DIR / "lib"
|
|
86
|
+
if str(_LIB_DIR) not in sys.path:
|
|
87
|
+
sys.path.insert(0, str(_LIB_DIR))
|
|
88
|
+
|
|
89
|
+
from boundary_events import emit_boundary_event as _emit_boundary_event
|
|
90
|
+
from review_agent_registry import is_registered_review_lens, strip_plugin_prefix
|
|
91
|
+
from review_gate_hash import (
|
|
92
|
+
EMPTY_DIGEST,
|
|
93
|
+
branch_diff_gate_hash,
|
|
94
|
+
default_base_ref,
|
|
95
|
+
review_gate_hash,
|
|
96
|
+
)
|
|
97
|
+
from stdin_json import read_stdin_json
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def emit_boundary_event(*args, **kwargs) -> None:
|
|
101
|
+
"""Local safety net (#859): even a misbehaving helper must never affect
|
|
102
|
+
this hook's exit code, stdout, or stderr."""
|
|
103
|
+
try:
|
|
104
|
+
_emit_boundary_event(*args, **kwargs)
|
|
105
|
+
except Exception: # noqa: BLE001, S110 - fail-open by design
|
|
106
|
+
pass
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def main() -> int:
|
|
110
|
+
payload = read_stdin_json()
|
|
111
|
+
if payload is None:
|
|
112
|
+
# Empty or malformed stdin -> silent-pass.
|
|
113
|
+
return 0
|
|
114
|
+
|
|
115
|
+
tool_input = payload.get("tool_input")
|
|
116
|
+
if not isinstance(tool_input, dict):
|
|
117
|
+
return 0
|
|
118
|
+
|
|
119
|
+
subagent_type = tool_input.get("subagent_type")
|
|
120
|
+
if not isinstance(subagent_type, str) or not subagent_type:
|
|
121
|
+
return 0
|
|
122
|
+
|
|
123
|
+
# `is_registered_review_lens()` (review_agent_registry.py) owns the
|
|
124
|
+
# strip-prefix + registry-read + membership check, including the
|
|
125
|
+
# "unreadable registry collapses to skip" posture — this is the
|
|
126
|
+
# WRITE/POSITIVE-evidence side (recording that a dispatch happened),
|
|
127
|
+
# where collapsing an unreadable registry to "don't record" is the safe
|
|
128
|
+
# direction: narrowing corroboration can only narrow, never widen, what
|
|
129
|
+
# counts as a passing gate later.
|
|
130
|
+
if not is_registered_review_lens(subagent_type):
|
|
131
|
+
# Not a real, registered review agent, or the registry could not be
|
|
132
|
+
# read at all — never recorded, not even as a rejected/flagged entry
|
|
133
|
+
# (module docstring).
|
|
134
|
+
return 0
|
|
135
|
+
|
|
136
|
+
# Normalize the plugin-qualified dispatch form ("dev-team:doc-review") to
|
|
137
|
+
# the bare name the registry's closed set uses, so the plugin's normal,
|
|
138
|
+
# installed invocation form is recognized identically to a bare-named one.
|
|
139
|
+
subagent_type = strip_plugin_prefix(subagent_type)
|
|
140
|
+
|
|
141
|
+
cwd = payload.get("cwd") or "."
|
|
142
|
+
session_id = payload.get("session_id")
|
|
143
|
+
tool_name = payload.get("tool_name") or "Agent"
|
|
144
|
+
|
|
145
|
+
# Stamp the CURRENT content hash (#1461 security review, revised #1904
|
|
146
|
+
# Bug 2b) — binds this dispatch to whatever is under review right now,
|
|
147
|
+
# so the corroboration reader can require dispatch evidence for the SAME
|
|
148
|
+
# content as the eventual `.pr-review-passed` write, not merely "some
|
|
149
|
+
# review happened recently" against unrelated content. A hash-
|
|
150
|
+
# computation failure (e.g. no git repo) fails open per this hook's own
|
|
151
|
+
# convention: still record the dispatch, just without a subject_hash —
|
|
152
|
+
# such an event can never satisfy a gate check, which requires an exact
|
|
153
|
+
# hash match, so this can only ever under-record, never forge evidence.
|
|
154
|
+
try:
|
|
155
|
+
subject_hash = review_gate_hash(cwd)
|
|
156
|
+
if subject_hash == EMPTY_DIGEST:
|
|
157
|
+
# Nothing staged — the routine state during a `--since <base>`-
|
|
158
|
+
# scoped review (skills/pr/SKILL.md requires a clean working
|
|
159
|
+
# tree before that review runs). Stamping EMPTY_DIGEST here
|
|
160
|
+
# would be the exact Bug 1 hazard (a constant shared by every
|
|
161
|
+
# such dispatch, regardless of real content) AND would leave
|
|
162
|
+
# this evidence unable to corroborate `hooks/pre_pr_review.py`'s
|
|
163
|
+
# gate, which always compares against `branch_diff_gate_hash()`.
|
|
164
|
+
# Fall back to that same content domain; refuse to stamp (None)
|
|
165
|
+
# rather than fall back to the empty digest a second time.
|
|
166
|
+
base_ref = default_base_ref(cwd)
|
|
167
|
+
branch_hash = branch_diff_gate_hash(base_ref, cwd) if base_ref is not None else None
|
|
168
|
+
subject_hash = (
|
|
169
|
+
branch_hash if branch_hash and branch_hash != EMPTY_DIGEST else None
|
|
170
|
+
)
|
|
171
|
+
except Exception: # noqa: BLE001 - fail-open: a hash failure never blocks a dispatch
|
|
172
|
+
subject_hash = None
|
|
173
|
+
|
|
174
|
+
emit_boundary_event(
|
|
175
|
+
cwd,
|
|
176
|
+
"agent_dispatch_ledger",
|
|
177
|
+
tool_name,
|
|
178
|
+
"record",
|
|
179
|
+
subagent_type,
|
|
180
|
+
session_id,
|
|
181
|
+
subject_hash=subject_hash,
|
|
182
|
+
)
|
|
183
|
+
return 0
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
if __name__ == "__main__":
|
|
187
|
+
try:
|
|
188
|
+
sys.exit(main())
|
|
189
|
+
except Exception: # noqa: BLE001 - fail-open: a hook bug must never block a dispatch
|
|
190
|
+
sys.exit(0)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""autocompact_setup_nudge — Claude Code SessionStart hook (#2177, slice 3).
|
|
3
|
+
|
|
4
|
+
The plugin no longer forces a handoff at a context ceiling; instead
|
|
5
|
+
`/dev-team:setup` sets the harness's own `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE`.
|
|
6
|
+
That makes `/setup` load-bearing, so this hook advises running it when a repo
|
|
7
|
+
shows no sign it has been.
|
|
8
|
+
|
|
9
|
+
Channel: plain stdout (`sys.stdout.write`), matching the other nudge hooks
|
|
10
|
+
(`repo_review_nudge.py`, `mcp_json_repowise_nudge.py`). Like them it is
|
|
11
|
+
self-silencing from state — once the key is configured it never prints — and
|
|
12
|
+
has no once-per-session marker.
|
|
13
|
+
|
|
14
|
+
- Key absent (process env, settings.local.json, settings.json, user settings):
|
|
15
|
+
one advisory line.
|
|
16
|
+
- Key present but invalid (not an integer 1-100): one corrective line.
|
|
17
|
+
- Key valid, opted out, or SessionStart source is "compact": silent.
|
|
18
|
+
|
|
19
|
+
Opt-out: `DEV_TEAM_AUTOCOMPACT_NUDGE=0` or the marker file
|
|
20
|
+
`.claude/memory/autocompact-nudge-off` (written by `/setup --no-autocompact`).
|
|
21
|
+
|
|
22
|
+
Project dir: `$CLAUDE_PROJECT_DIR`, else the payload `cwd`, else the process
|
|
23
|
+
cwd. Advisory only: fail-open, always exits 0, never blocks session start.
|
|
24
|
+
Stdlib only.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from __future__ import annotations
|
|
28
|
+
|
|
29
|
+
import os
|
|
30
|
+
import sys
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
|
|
33
|
+
_LIB = Path(__file__).resolve().parent / "lib"
|
|
34
|
+
if str(_LIB) not in sys.path:
|
|
35
|
+
sys.path.insert(0, str(_LIB))
|
|
36
|
+
|
|
37
|
+
from autocompact_config import KEY, Status, detect # type: ignore[import-not-found]
|
|
38
|
+
from stdin_json import read_stdin_json, resolve_cwd # type: ignore[import-not-found]
|
|
39
|
+
|
|
40
|
+
OPT_OUT_ENV = "DEV_TEAM_AUTOCOMPACT_NUDGE"
|
|
41
|
+
OPT_OUT_MARKER = Path(".claude") / "memory" / "autocompact-nudge-off"
|
|
42
|
+
|
|
43
|
+
ABSENT_MESSAGE = (
|
|
44
|
+
"dev-team: context autocompact is not configured for this repo; "
|
|
45
|
+
"run /dev-team:setup to set it (default 40%). "
|
|
46
|
+
f"Silence: {OPT_OUT_ENV}=0 or create {OPT_OUT_MARKER.as_posix()}\n"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
_MAX_SHOWN = 40
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def invalid_message(raw: object, source: str | None) -> str:
|
|
54
|
+
shown = repr(raw)
|
|
55
|
+
if len(shown) > _MAX_SHOWN:
|
|
56
|
+
shown = shown[: _MAX_SHOWN - 3] + "..."
|
|
57
|
+
where = f" in {source}" if source else ""
|
|
58
|
+
return (
|
|
59
|
+
f"dev-team: {KEY}={shown}{where} is invalid (need integer 1-100); "
|
|
60
|
+
"re-run /dev-team:setup\n"
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _project_dir(payload: dict) -> Path:
|
|
65
|
+
override = os.environ.get("CLAUDE_PROJECT_DIR")
|
|
66
|
+
if override and Path(override).is_dir():
|
|
67
|
+
return Path(override)
|
|
68
|
+
return Path(resolve_cwd(payload))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def message_for(payload: dict) -> str:
|
|
72
|
+
"""The text to print, or '' when the hook should stay silent."""
|
|
73
|
+
if payload.get("source") == "compact":
|
|
74
|
+
return ""
|
|
75
|
+
if os.environ.get(OPT_OUT_ENV) == "0":
|
|
76
|
+
return ""
|
|
77
|
+
project = _project_dir(payload)
|
|
78
|
+
if (project / OPT_OUT_MARKER).exists():
|
|
79
|
+
return ""
|
|
80
|
+
detection = detect(project, os.environ)
|
|
81
|
+
if detection.status is Status.ABSENT:
|
|
82
|
+
return ABSENT_MESSAGE
|
|
83
|
+
if detection.status is Status.INVALID:
|
|
84
|
+
return invalid_message(detection.raw, detection.source)
|
|
85
|
+
return ""
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def main() -> int:
|
|
89
|
+
try:
|
|
90
|
+
text = message_for(read_stdin_json() or {})
|
|
91
|
+
if text:
|
|
92
|
+
sys.stdout.write(text)
|
|
93
|
+
except Exception: # noqa: BLE001 - advisory hook: never block session start
|
|
94
|
+
return 0
|
|
95
|
+
return 0
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
if __name__ == "__main__":
|
|
99
|
+
sys.exit(main())
|