@dommaker/harness 1.2.3 → 1.4.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/CHANGELOG.md +15 -0
- package/README.md +0 -2
- package/bin/harness.js +86 -32
- package/dist/cli/command-contract.d.ts +83 -0
- package/dist/cli/command-contract.d.ts.map +1 -0
- package/dist/cli/command-contract.js +66 -0
- package/dist/cli/command-contract.js.map +1 -0
- package/dist/cli/commands/acceptance.d.ts +3 -2
- package/dist/cli/commands/acceptance.d.ts.map +1 -1
- package/dist/cli/commands/acceptance.js +28 -24
- package/dist/cli/commands/acceptance.js.map +1 -1
- package/dist/cli/commands/analyze-sessions.d.ts +2 -1
- package/dist/cli/commands/analyze-sessions.d.ts.map +1 -1
- package/dist/cli/commands/analyze-sessions.js +25 -24
- package/dist/cli/commands/analyze-sessions.js.map +1 -1
- package/dist/cli/commands/check.d.ts +14 -2
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/check.js +76 -61
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/command.d.ts +5 -1
- package/dist/cli/commands/command.d.ts.map +1 -1
- package/dist/cli/commands/command.js +26 -17
- package/dist/cli/commands/command.js.map +1 -1
- package/dist/cli/commands/constraints-report.d.ts +2 -1
- package/dist/cli/commands/constraints-report.d.ts.map +1 -1
- package/dist/cli/commands/constraints-report.js +37 -33
- package/dist/cli/commands/constraints-report.js.map +1 -1
- package/dist/cli/commands/constraints-retire.d.ts +6 -5
- package/dist/cli/commands/constraints-retire.d.ts.map +1 -1
- package/dist/cli/commands/constraints-retire.js +50 -52
- package/dist/cli/commands/constraints-retire.js.map +1 -1
- package/dist/cli/commands/constraints.d.ts +2 -1
- package/dist/cli/commands/constraints.d.ts.map +1 -1
- package/dist/cli/commands/constraints.js +10 -27
- package/dist/cli/commands/constraints.js.map +1 -1
- package/dist/cli/commands/contract.d.ts +3 -2
- package/dist/cli/commands/contract.d.ts.map +1 -1
- package/dist/cli/commands/contract.js +45 -42
- package/dist/cli/commands/contract.js.map +1 -1
- package/dist/cli/commands/definitions.d.ts +11 -11
- package/dist/cli/commands/definitions.d.ts.map +1 -1
- package/dist/cli/commands/definitions.js +30 -215
- package/dist/cli/commands/definitions.js.map +1 -1
- package/dist/cli/commands/failure.d.ts +5 -4
- package/dist/cli/commands/failure.d.ts.map +1 -1
- package/dist/cli/commands/failure.js +33 -26
- package/dist/cli/commands/failure.js.map +1 -1
- package/dist/cli/commands/init.d.ts +7 -5
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +147 -211
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/knowledge.d.ts +21 -15
- package/dist/cli/commands/knowledge.d.ts.map +1 -1
- package/dist/cli/commands/knowledge.js +237 -199
- package/dist/cli/commands/knowledge.js.map +1 -1
- package/dist/cli/commands/passes-gate.d.ts +8 -2
- package/dist/cli/commands/passes-gate.d.ts.map +1 -1
- package/dist/cli/commands/passes-gate.js +44 -66
- package/dist/cli/commands/passes-gate.js.map +1 -1
- package/dist/cli/commands/performance.d.ts +2 -1
- package/dist/cli/commands/performance.d.ts.map +1 -1
- package/dist/cli/commands/performance.js +20 -18
- package/dist/cli/commands/performance.js.map +1 -1
- package/dist/cli/commands/posteval-plan.d.ts +5 -1
- package/dist/cli/commands/posteval-plan.d.ts.map +1 -1
- package/dist/cli/commands/posteval-plan.js +26 -15
- package/dist/cli/commands/posteval-plan.js.map +1 -1
- package/dist/cli/commands/release.d.ts +6 -1
- package/dist/cli/commands/release.d.ts.map +1 -1
- package/dist/cli/commands/release.js +73 -77
- package/dist/cli/commands/release.js.map +1 -1
- package/dist/cli/commands/report.d.ts +2 -1
- package/dist/cli/commands/report.d.ts.map +1 -1
- package/dist/cli/commands/report.js +9 -5
- package/dist/cli/commands/report.js.map +1 -1
- package/dist/cli/commands/review.d.ts +3 -2
- package/dist/cli/commands/review.d.ts.map +1 -1
- package/dist/cli/commands/review.js +33 -29
- package/dist/cli/commands/review.js.map +1 -1
- package/dist/cli/commands/sdd.d.ts +2 -1
- package/dist/cli/commands/sdd.d.ts.map +1 -1
- package/dist/cli/commands/sdd.js +7 -5
- package/dist/cli/commands/sdd.js.map +1 -1
- package/dist/cli/commands/security.d.ts +3 -2
- package/dist/cli/commands/security.d.ts.map +1 -1
- package/dist/cli/commands/security.js +29 -26
- package/dist/cli/commands/security.js.map +1 -1
- package/dist/cli/commands/spec-baseline-check.d.ts +2 -1
- package/dist/cli/commands/spec-baseline-check.d.ts.map +1 -1
- package/dist/cli/commands/spec-baseline-check.js +15 -11
- package/dist/cli/commands/spec-baseline-check.js.map +1 -1
- package/dist/cli/commands/spec.d.ts +7 -2
- package/dist/cli/commands/spec.d.ts.map +1 -1
- package/dist/cli/commands/spec.js +61 -51
- package/dist/cli/commands/spec.js.map +1 -1
- package/dist/cli/commands/status.d.ts +2 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +57 -53
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/sync-docs/agents-syncer.d.ts.map +1 -1
- package/dist/cli/commands/sync-docs/agents-syncer.js +31 -16
- package/dist/cli/commands/sync-docs/agents-syncer.js.map +1 -1
- package/dist/cli/commands/sync-docs/context-syncer.d.ts.map +1 -1
- package/dist/cli/commands/sync-docs/context-syncer.js +3 -2
- package/dist/cli/commands/sync-docs/context-syncer.js.map +1 -1
- package/dist/cli/commands/sync-docs/index.d.ts +2 -1
- package/dist/cli/commands/sync-docs/index.d.ts.map +1 -1
- package/dist/cli/commands/sync-docs/index.js +68 -88
- package/dist/cli/commands/sync-docs/index.js.map +1 -1
- package/dist/cli/commands/sync-docs/project-reader.d.ts +6 -1
- package/dist/cli/commands/sync-docs/project-reader.d.ts.map +1 -1
- package/dist/cli/commands/sync-docs/project-reader.js +14 -16
- package/dist/cli/commands/sync-docs/project-reader.js.map +1 -1
- package/dist/cli/commands/update-user-model.d.ts +2 -1
- package/dist/cli/commands/update-user-model.d.ts.map +1 -1
- package/dist/cli/commands/update-user-model.js +31 -45
- package/dist/cli/commands/update-user-model.js.map +1 -1
- package/dist/cli/commands/validate.d.ts +4 -3
- package/dist/cli/commands/validate.d.ts.map +1 -1
- package/dist/cli/commands/validate.js +28 -26
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/session-mining/transcript.d.ts +7 -1
- package/dist/cli/session-mining/transcript.d.ts.map +1 -1
- package/dist/cli/session-mining/transcript.js +21 -14
- package/dist/cli/session-mining/transcript.js.map +1 -1
- package/dist/completion-checkers/index.d.ts +3 -3
- package/dist/completion-checkers/index.js +3 -3
- package/dist/completion-checkers/phase-format.d.ts +1 -1
- package/dist/completion-checkers/phase-format.js +2 -2
- package/dist/completion-checkers/phase-format.js.map +1 -1
- package/dist/completion-checkers/tdd-chain.d.ts +1 -1
- package/dist/completion-checkers/tdd-chain.js +2 -2
- package/dist/completion-checkers/tdd-chain.js.map +1 -1
- package/dist/completion-checkers/types.d.ts +5 -5
- package/dist/completion-checkers/types.d.ts.map +1 -1
- package/dist/completion-checkers/types.js +2 -2
- package/dist/context/session-manager.d.ts.map +1 -1
- package/dist/context/session-manager.js +19 -32
- package/dist/context/session-manager.js.map +1 -1
- package/dist/core/constraints/agent-prompt-renderer.d.ts.map +1 -1
- package/dist/core/constraints/agent-prompt-renderer.js +1 -4
- package/dist/core/constraints/agent-prompt-renderer.js.map +1 -1
- package/dist/core/constraints/capabilities-parser.d.ts +24 -7
- package/dist/core/constraints/capabilities-parser.d.ts.map +1 -1
- package/dist/core/constraints/capabilities-parser.js +32 -28
- package/dist/core/constraints/capabilities-parser.js.map +1 -1
- package/dist/core/constraints/capabilities-reconcile.d.ts +67 -0
- package/dist/core/constraints/capabilities-reconcile.d.ts.map +1 -0
- package/dist/core/constraints/capabilities-reconcile.js +105 -0
- package/dist/core/constraints/capabilities-reconcile.js.map +1 -0
- package/dist/core/constraints/checker.d.ts +21 -43
- package/dist/core/constraints/checker.d.ts.map +1 -1
- package/dist/core/constraints/checker.js +64 -115
- package/dist/core/constraints/checker.js.map +1 -1
- package/dist/core/constraints/checkers/capability-sync.d.ts +4 -3
- package/dist/core/constraints/checkers/capability-sync.d.ts.map +1 -1
- package/dist/core/constraints/checkers/capability-sync.js +29 -69
- package/dist/core/constraints/checkers/capability-sync.js.map +1 -1
- package/dist/core/constraints/checkers/context-doc-sync.d.ts +4 -2
- package/dist/core/constraints/checkers/context-doc-sync.d.ts.map +1 -1
- package/dist/core/constraints/checkers/context-doc-sync.js +13 -22
- package/dist/core/constraints/checkers/context-doc-sync.js.map +1 -1
- package/dist/core/constraints/checkers/docs-freshness.d.ts.map +1 -1
- package/dist/core/constraints/checkers/docs-freshness.js +37 -63
- package/dist/core/constraints/checkers/docs-freshness.js.map +1 -1
- package/dist/core/constraints/checkers/governance-presence.d.ts +2 -2
- package/dist/core/constraints/checkers/governance-presence.d.ts.map +1 -1
- package/dist/core/constraints/checkers/governance-presence.js +7 -28
- package/dist/core/constraints/checkers/governance-presence.js.map +1 -1
- package/dist/core/constraints/checkers/no-test-simplification.d.ts.map +1 -1
- package/dist/core/constraints/checkers/no-test-simplification.js +4 -3
- package/dist/core/constraints/checkers/no-test-simplification.js.map +1 -1
- package/dist/core/constraints/checkers/types.d.ts +2 -2
- package/dist/core/constraints/context-builder.d.ts +15 -14
- package/dist/core/constraints/context-builder.d.ts.map +1 -1
- package/dist/core/constraints/context-builder.js +32 -96
- package/dist/core/constraints/context-builder.js.map +1 -1
- package/dist/core/constraints/doc-freshness/runner.d.ts.map +1 -1
- package/dist/core/constraints/doc-freshness/runner.js +2 -1
- package/dist/core/constraints/doc-freshness/runner.js.map +1 -1
- package/dist/core/constraints/git-evidence.d.ts +60 -0
- package/dist/core/constraints/git-evidence.d.ts.map +1 -0
- package/dist/core/constraints/git-evidence.js +88 -0
- package/dist/core/constraints/git-evidence.js.map +1 -0
- package/dist/core/constraints/injection-drift.d.ts +3 -20
- package/dist/core/constraints/injection-drift.d.ts.map +1 -1
- package/dist/core/constraints/injection-drift.js +10 -57
- package/dist/core/constraints/injection-drift.js.map +1 -1
- package/dist/core/constraints/injection-writer.d.ts +113 -0
- package/dist/core/constraints/injection-writer.d.ts.map +1 -0
- package/dist/core/constraints/injection-writer.js +228 -0
- package/dist/core/constraints/injection-writer.js.map +1 -0
- package/dist/core/constraints/usage-report.d.ts +22 -1
- package/dist/core/constraints/usage-report.d.ts.map +1 -1
- package/dist/core/constraints/usage-report.js +27 -20
- package/dist/core/constraints/usage-report.js.map +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +4 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/project-config-loader.d.ts +32 -1
- package/dist/core/project-config-loader.d.ts.map +1 -1
- package/dist/core/project-config-loader.js +39 -9
- package/dist/core/project-config-loader.js.map +1 -1
- package/dist/core/validators/passes-gate.d.ts +15 -64
- package/dist/core/validators/passes-gate.d.ts.map +1 -1
- package/dist/core/validators/passes-gate.js +84 -222
- package/dist/core/validators/passes-gate.js.map +1 -1
- package/dist/core/validators/test-output.d.ts +58 -0
- package/dist/core/validators/test-output.d.ts.map +1 -0
- package/dist/core/validators/test-output.js +109 -0
- package/dist/core/validators/test-output.js.map +1 -0
- package/dist/failure/recorder.d.ts +7 -1
- package/dist/failure/recorder.d.ts.map +1 -1
- package/dist/failure/recorder.js +13 -9
- package/dist/failure/recorder.js.map +1 -1
- package/dist/gates/acceptance.d.ts +1 -48
- package/dist/gates/acceptance.d.ts.map +1 -1
- package/dist/gates/acceptance.js +6 -38
- package/dist/gates/acceptance.js.map +1 -1
- package/dist/gates/checker-gate.d.ts.map +1 -1
- package/dist/gates/checker-gate.js +6 -11
- package/dist/gates/checker-gate.js.map +1 -1
- package/dist/gates/command.d.ts.map +1 -1
- package/dist/gates/command.js +10 -22
- package/dist/gates/command.js.map +1 -1
- package/dist/gates/contract.d.ts.map +1 -1
- package/dist/gates/contract.js +22 -61
- package/dist/gates/contract.js.map +1 -1
- package/dist/gates/performance.d.ts.map +1 -1
- package/dist/gates/performance.js +13 -31
- package/dist/gates/performance.js.map +1 -1
- package/dist/gates/review.d.ts.map +1 -1
- package/dist/gates/review.js +21 -53
- package/dist/gates/review.js.map +1 -1
- package/dist/gates/security.d.ts.map +1 -1
- package/dist/gates/security.js +14 -32
- package/dist/gates/security.js.map +1 -1
- package/dist/gates/types.d.ts +28 -5
- package/dist/gates/types.d.ts.map +1 -1
- package/dist/gates/types.js +38 -1
- package/dist/gates/types.js.map +1 -1
- package/dist/hooks/bootstrap.d.ts +2 -0
- package/dist/hooks/bootstrap.d.ts.map +1 -1
- package/dist/hooks/bootstrap.js +5 -2
- package/dist/hooks/bootstrap.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -4
- package/dist/index.js.map +1 -1
- package/dist/knowledge/audit.d.ts +7 -2
- package/dist/knowledge/audit.d.ts.map +1 -1
- package/dist/knowledge/audit.js +59 -79
- package/dist/knowledge/audit.js.map +1 -1
- package/dist/knowledge/flywheel-metrics.d.ts +39 -0
- package/dist/knowledge/flywheel-metrics.d.ts.map +1 -0
- package/dist/knowledge/flywheel-metrics.js +47 -0
- package/dist/knowledge/flywheel-metrics.js.map +1 -0
- package/dist/knowledge/import.d.ts.map +1 -1
- package/dist/knowledge/import.js +4 -14
- package/dist/knowledge/import.js.map +1 -1
- package/dist/knowledge/index-generator.d.ts.map +1 -1
- package/dist/knowledge/index-generator.js +18 -15
- package/dist/knowledge/index-generator.js.map +1 -1
- package/dist/knowledge/ingest.d.ts.map +1 -1
- package/dist/knowledge/ingest.js +9 -4
- package/dist/knowledge/ingest.js.map +1 -1
- package/dist/knowledge/migration.d.ts.map +1 -1
- package/dist/knowledge/migration.js +11 -8
- package/dist/knowledge/migration.js.map +1 -1
- package/dist/knowledge/reference-tracker.d.ts.map +1 -1
- package/dist/knowledge/reference-tracker.js +12 -9
- package/dist/knowledge/reference-tracker.js.map +1 -1
- package/dist/knowledge/store.d.ts +15 -0
- package/dist/knowledge/store.d.ts.map +1 -1
- package/dist/knowledge/store.js +59 -10
- package/dist/knowledge/store.js.map +1 -1
- package/dist/monitoring/context-tracker.d.ts.map +1 -1
- package/dist/monitoring/context-tracker.js +11 -20
- package/dist/monitoring/context-tracker.js.map +1 -1
- package/dist/monitoring/index.d.ts +1 -1
- package/dist/monitoring/index.d.ts.map +1 -1
- package/dist/monitoring/index.js +1 -2
- package/dist/monitoring/index.js.map +1 -1
- package/dist/monitoring/trace-analyzer.d.ts +15 -0
- package/dist/monitoring/trace-analyzer.d.ts.map +1 -1
- package/dist/monitoring/trace-analyzer.js +19 -2
- package/dist/monitoring/trace-analyzer.js.map +1 -1
- package/dist/monitoring/traces.d.ts +21 -2
- package/dist/monitoring/traces.d.ts.map +1 -1
- package/dist/monitoring/traces.js +38 -29
- package/dist/monitoring/traces.js.map +1 -1
- package/dist/release/index.d.ts +3 -0
- package/dist/release/index.d.ts.map +1 -0
- package/dist/release/index.js +7 -0
- package/dist/release/index.js.map +1 -0
- package/dist/release/integrity.d.ts +65 -0
- package/dist/release/integrity.d.ts.map +1 -0
- package/dist/release/integrity.js +151 -0
- package/dist/release/integrity.js.map +1 -0
- package/dist/sdd/index-generator.js +10 -11
- package/dist/sdd/index-generator.js.map +1 -1
- package/dist/test-setup/project-fixture.d.ts +48 -0
- package/dist/test-setup/project-fixture.d.ts.map +1 -0
- package/dist/test-setup/project-fixture.js +106 -0
- package/dist/test-setup/project-fixture.js.map +1 -0
- package/dist/types/constraint.d.ts +0 -18
- package/dist/types/constraint.d.ts.map +1 -1
- package/dist/types/constraint.js.map +1 -1
- package/dist/types/failure.d.ts +7 -0
- package/dist/types/failure.d.ts.map +1 -1
- package/dist/types/failure.js +8 -1
- package/dist/types/failure.js.map +1 -1
- package/dist/types/passes-gate.d.ts +10 -25
- package/dist/types/passes-gate.d.ts.map +1 -1
- package/dist/types/project-config.d.ts +1 -1
- package/dist/types/session.d.ts +6 -5
- package/dist/types/session.d.ts.map +1 -1
- package/dist/utils/exec.d.ts +10 -0
- package/dist/utils/exec.d.ts.map +1 -1
- package/dist/utils/exec.js +12 -0
- package/dist/utils/exec.js.map +1 -1
- package/dist/utils/file-walk.d.ts +9 -1
- package/dist/utils/file-walk.d.ts.map +1 -1
- package/dist/utils/file-walk.js +10 -1
- package/dist/utils/file-walk.js.map +1 -1
- package/dist/utils/frontmatter.d.ts +73 -0
- package/dist/utils/frontmatter.d.ts.map +1 -0
- package/dist/utils/frontmatter.js +141 -0
- package/dist/utils/frontmatter.js.map +1 -0
- package/dist/utils/jsonl.d.ts +92 -0
- package/dist/utils/jsonl.d.ts.map +1 -0
- package/dist/utils/jsonl.js +166 -0
- package/dist/utils/jsonl.js.map +1 -0
- package/dist/utils/package-version.d.ts +16 -0
- package/dist/utils/package-version.d.ts.map +1 -0
- package/dist/utils/package-version.js +63 -0
- package/dist/utils/package-version.js.map +1 -0
- package/package.json +1 -1
- package/src/CONTEXT.md +7 -2
- package/src/__tests__/acceptance-gate.test.ts +3 -1
- package/src/__tests__/checker-extra.test.ts +7 -1218
- package/src/__tests__/context-files-resolution.test.ts +116 -0
- package/src/__tests__/effective-constraints.test.ts +10 -13
- package/src/__tests__/exec.test.ts +35 -1
- package/src/__tests__/failure-recorder.test.ts +9 -0
- package/src/__tests__/layering.test.ts +152 -0
- package/src/__tests__/passes-gate-extra.test.ts +0 -145
- package/src/__tests__/passes-gate.test.ts +142 -106
- package/src/__tests__/public-exports.test.ts +3 -0
- package/src/__tests__/skip-semantics.test.ts +5 -9
- package/src/cli/__tests__/command-contract.test.ts +170 -0
- package/src/cli/command-contract.ts +108 -0
- package/src/cli/commands/CONTEXT.md +22 -7
- package/src/cli/commands/__tests__/acceptance.test.ts +40 -33
- package/src/cli/commands/__tests__/analyze-sessions.test.ts +35 -29
- package/src/cli/commands/__tests__/bin-exit-mapping.test.ts +101 -0
- package/src/cli/commands/__tests__/check-drift.test.ts +27 -34
- package/src/cli/commands/__tests__/check-skip-output.test.ts +21 -24
- package/src/cli/commands/__tests__/check.test.ts +378 -382
- package/src/cli/commands/__tests__/command.test.ts +85 -70
- package/src/cli/commands/__tests__/constraints-report.test.ts +100 -71
- package/src/cli/commands/__tests__/constraints-retire.test.ts +152 -95
- package/src/cli/commands/__tests__/contract.test.ts +27 -34
- package/src/cli/commands/__tests__/failure.test.ts +31 -34
- package/src/cli/commands/__tests__/init-injection.test.ts +58 -28
- package/src/cli/commands/__tests__/init.test.ts +77 -48
- package/src/cli/commands/__tests__/knowledge-flywheel-consistency.test.ts +108 -0
- package/src/cli/commands/__tests__/knowledge.test.ts +96 -38
- package/src/cli/commands/__tests__/passes-gate.test.ts +43 -45
- package/src/cli/commands/__tests__/performance.test.ts +22 -23
- package/src/cli/commands/__tests__/posteval-plan.test.ts +39 -38
- package/src/cli/commands/__tests__/project-path-anchoring.test.ts +157 -0
- package/src/cli/commands/__tests__/project-path-convention.test.ts +169 -0
- package/src/cli/commands/__tests__/registry.test.ts +69 -35
- package/src/cli/commands/__tests__/release.test.ts +224 -74
- package/src/cli/commands/__tests__/report-extra.test.ts +16 -16
- package/src/cli/commands/__tests__/report.test.ts +25 -25
- package/src/cli/commands/__tests__/review.test.ts +33 -31
- package/src/cli/commands/__tests__/security.test.ts +23 -27
- package/src/cli/commands/__tests__/spec-baseline-check.test.ts +20 -20
- package/src/cli/commands/__tests__/spec.test.ts +41 -29
- package/src/cli/commands/__tests__/status-extra.test.ts +18 -18
- package/src/cli/commands/__tests__/status-skipped-lines.test.ts +72 -0
- package/src/cli/commands/__tests__/status.test.ts +34 -34
- package/src/cli/commands/__tests__/sync-docs-agents.test.ts +108 -86
- package/src/cli/commands/__tests__/sync-docs.test.ts +72 -74
- package/src/cli/commands/__tests__/update-user-model.test.ts +62 -33
- package/src/cli/commands/__tests__/validate.test.ts +27 -29
- package/src/cli/commands/acceptance.ts +35 -24
- package/src/cli/commands/analyze-sessions.ts +25 -24
- package/src/cli/commands/check.ts +88 -65
- package/src/cli/commands/command.ts +30 -17
- package/src/cli/commands/constraints-report.ts +37 -34
- package/src/cli/commands/constraints-retire.ts +58 -55
- package/src/cli/commands/constraints.ts +10 -27
- package/src/cli/commands/contract.ts +51 -42
- package/src/cli/commands/definitions.ts +37 -223
- package/src/cli/commands/failure.ts +35 -27
- package/src/cli/commands/init.ts +166 -220
- package/src/cli/commands/knowledge.ts +250 -203
- package/src/cli/commands/passes-gate.ts +58 -68
- package/src/cli/commands/performance.ts +23 -18
- package/src/cli/commands/posteval-plan.ts +29 -15
- package/src/cli/commands/release.ts +75 -78
- package/src/cli/commands/report.ts +9 -5
- package/src/cli/commands/review.ts +39 -29
- package/src/cli/commands/sdd.ts +7 -5
- package/src/cli/commands/security.ts +35 -26
- package/src/cli/commands/spec-baseline-check.ts +16 -11
- package/src/cli/commands/spec.ts +66 -53
- package/src/cli/commands/status.ts +59 -53
- package/src/cli/commands/sync-docs/agents-syncer.ts +31 -15
- package/src/cli/commands/sync-docs/context-syncer.ts +3 -2
- package/src/cli/commands/sync-docs/index.ts +73 -100
- package/src/cli/commands/sync-docs/project-reader.ts +17 -18
- package/src/cli/commands/update-user-model.ts +33 -45
- package/src/cli/commands/validate.ts +31 -25
- package/src/cli/session-mining/__tests__/transcript.test.ts +118 -0
- package/src/cli/session-mining/transcript.ts +26 -8
- package/src/completion-checkers/CONTEXT.md +1 -1
- package/src/completion-checkers/__tests__/contract-presence.test.ts +1 -1
- package/src/completion-checkers/__tests__/phase-format.test.ts +1 -1
- package/src/completion-checkers/__tests__/tdd-chain.test.ts +2 -2
- package/src/completion-checkers/index.ts +3 -3
- package/src/completion-checkers/phase-format.ts +2 -2
- package/src/completion-checkers/tdd-chain.ts +2 -2
- package/src/completion-checkers/types.ts +5 -5
- package/src/context/session-manager.ts +19 -33
- package/src/core/CONTEXT.md +9 -6
- package/src/core/constraints/__tests__/capabilities-reconcile.test.ts +200 -0
- package/src/core/constraints/__tests__/capability-counts.test.ts +94 -0
- package/src/core/constraints/__tests__/git-evidence.test.ts +208 -0
- package/src/core/constraints/__tests__/injection-drift.test.ts +3 -10
- package/src/core/constraints/__tests__/injection-writer.test.ts +231 -0
- package/src/core/constraints/__tests__/trace-injection.test.ts +71 -0
- package/src/core/constraints/__tests__/usage-report.test.ts +112 -0
- package/src/core/constraints/agent-prompt-renderer.ts +2 -6
- package/src/core/constraints/capabilities-parser.ts +53 -35
- package/src/core/constraints/capabilities-reconcile.ts +166 -0
- package/src/core/constraints/checker.ts +75 -130
- package/src/core/constraints/checkers/__tests__/capability-sync.test.ts +214 -0
- package/src/core/constraints/checkers/__tests__/context-doc-sync.test.ts +77 -0
- package/src/core/constraints/checkers/__tests__/docs-freshness.test.ts +117 -0
- package/src/{__tests__ → core/constraints/checkers/__tests__}/governance-presence.test.ts +83 -9
- package/src/core/constraints/checkers/__tests__/iron-flags.test.ts +50 -0
- package/src/core/constraints/checkers/__tests__/no-bypass-checkpoint.test.ts +76 -0
- package/src/{__tests__ → core/constraints/checkers/__tests__}/no-hardcoded-credentials.test.ts +4 -3
- package/src/core/constraints/checkers/__tests__/no-test-simplification.test.ts +58 -0
- package/src/core/constraints/checkers/__tests__/three-state-consistency.test.ts +145 -0
- package/src/core/constraints/checkers/capability-sync.ts +29 -88
- package/src/core/constraints/checkers/context-doc-sync.ts +15 -25
- package/src/core/constraints/checkers/docs-freshness.ts +40 -69
- package/src/core/constraints/checkers/governance-presence.ts +7 -25
- package/src/core/constraints/checkers/no-test-simplification.ts +4 -3
- package/src/core/constraints/checkers/types.ts +2 -2
- package/src/core/constraints/context-builder.ts +39 -91
- package/src/core/constraints/doc-freshness/runner.ts +2 -1
- package/src/core/constraints/git-evidence.ts +120 -0
- package/src/core/constraints/injection-drift.ts +13 -60
- package/src/core/constraints/injection-writer.ts +212 -0
- package/src/core/constraints/usage-report.ts +36 -17
- package/src/core/index.ts +4 -2
- package/src/core/project-config-loader.ts +49 -9
- package/src/core/validators/__tests__/passes-gate.test.ts +2 -56
- package/src/core/validators/__tests__/test-output.test.ts +372 -0
- package/src/core/validators/passes-gate.ts +86 -248
- package/src/core/validators/test-output.ts +128 -0
- package/src/failure/__tests__/recorder.test.ts +168 -0
- package/src/failure/recorder.ts +13 -11
- package/src/gates/CONTEXT.md +6 -3
- package/src/gates/__tests__/acceptance-types-single-source.test.ts +68 -0
- package/src/gates/__tests__/acceptance.test.ts +4 -86
- package/src/gates/__tests__/effective-gates.test.ts +3 -8
- package/src/gates/__tests__/test-verdict-consistency.test.ts +140 -0
- package/src/gates/acceptance.ts +19 -84
- package/src/gates/checker-gate.ts +8 -7
- package/src/gates/command.ts +10 -16
- package/src/gates/contract.ts +22 -61
- package/src/gates/performance.ts +10 -22
- package/src/gates/review.ts +21 -41
- package/src/gates/security.ts +10 -22
- package/src/gates/types.ts +70 -5
- package/src/hooks/CONTEXT.md +1 -1
- package/src/hooks/bootstrap.ts +5 -2
- package/src/index.ts +11 -6
- package/src/knowledge/CONTEXT.md +8 -3
- package/src/knowledge/__tests__/audit-labels.test.ts +44 -0
- package/src/knowledge/__tests__/flywheel-metrics.test.ts +135 -0
- package/src/knowledge/__tests__/import.test.ts +44 -0
- package/src/knowledge/__tests__/index-generator.test.ts +55 -2
- package/src/knowledge/__tests__/ingest.test.ts +85 -0
- package/src/knowledge/__tests__/migration.test.ts +47 -0
- package/src/knowledge/__tests__/reference-tracker.test.ts +16 -0
- package/src/knowledge/__tests__/store.test.ts +194 -0
- package/src/knowledge/audit.ts +67 -71
- package/src/knowledge/flywheel-metrics.ts +71 -0
- package/src/knowledge/import.ts +4 -18
- package/src/knowledge/index-generator.ts +20 -15
- package/src/knowledge/ingest.ts +9 -4
- package/src/knowledge/migration.ts +11 -8
- package/src/knowledge/reference-tracker.ts +12 -8
- package/src/knowledge/store.ts +64 -11
- package/src/monitoring/CONTEXT.md +8 -3
- package/src/monitoring/__tests__/skipped-lines-report.test.ts +178 -0
- package/src/monitoring/__tests__/traces.test.ts +57 -0
- package/src/monitoring/context-tracker.ts +11 -23
- package/src/monitoring/index.ts +1 -1
- package/src/monitoring/trace-analyzer.ts +21 -2
- package/src/monitoring/traces.ts +39 -36
- package/src/release/CONTEXT.md +24 -0
- package/src/release/__tests__/barrel.test.ts +60 -0
- package/src/release/__tests__/integrity.test.ts +157 -0
- package/src/release/index.ts +2 -0
- package/src/release/integrity.ts +141 -0
- package/src/sdd/__tests__/index-generator.test.ts +71 -0
- package/src/sdd/index-generator.ts +9 -9
- package/src/test-setup/__tests__/project-fixture.test.ts +178 -0
- package/src/test-setup/project-fixture.ts +87 -0
- package/src/tools/CONTEXT.md +6 -0
- package/src/tools/__tests__/registry.test.ts +221 -0
- package/src/types/__tests__/types.test.ts +4 -5
- package/src/types/constraint.ts +0 -25
- package/src/types/failure.ts +8 -0
- package/src/types/passes-gate.ts +10 -30
- package/src/types/project-config.ts +1 -1
- package/src/types/session.ts +5 -5
- package/src/utils/__tests__/frontmatter.test.ts +206 -0
- package/src/utils/__tests__/jsonl-skip-disposition.test.ts +175 -0
- package/src/utils/__tests__/jsonl.test.ts +187 -0
- package/src/utils/__tests__/package-version.test.ts +97 -0
- package/src/utils/exec.ts +15 -0
- package/src/utils/file-walk.ts +11 -2
- package/src/utils/frontmatter.ts +121 -0
- package/src/utils/jsonl.ts +167 -0
- package/src/utils/package-version.ts +27 -0
- package/dist/cli/commands/doc-freshness-check.d.ts +0 -53
- package/dist/cli/commands/doc-freshness-check.d.ts.map +0 -1
- package/dist/cli/commands/doc-freshness-check.js +0 -352
- package/dist/cli/commands/doc-freshness-check.js.map +0 -1
- package/dist/types/index.d.ts +0 -14
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -39
- package/dist/types/index.js.map +0 -1
- package/src/__tests__/long-running.test.ts +0 -17
- package/src/__tests__/passes-gate-extension.test.ts +0 -151
- package/src/cli/commands/__tests__/doc-freshness-check.test.ts +0 -168
- package/src/cli/commands/doc-freshness-check.ts +0 -386
- package/src/spec/CONTEXT.md +0 -11
- package/src/types/index.ts +0 -47
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { validate, createExampleCheckpoint, createExampleResolutions } from '../validate';
|
|
6
|
+
import { captureIO, type CapturingIO } from '../../command-contract';
|
|
6
7
|
import * as fs from 'fs/promises';
|
|
7
8
|
import { CheckpointValidator } from '../../../core/validators/checkpoint';
|
|
8
9
|
import * as yaml from 'js-yaml';
|
|
@@ -42,25 +43,22 @@ const MockCheckpointValidator = CheckpointValidator as jest.Mocked<typeof Checkp
|
|
|
42
43
|
const mockYaml = yaml as jest.Mocked<typeof yaml>;
|
|
43
44
|
|
|
44
45
|
describe('validate command', () => {
|
|
45
|
-
let
|
|
46
|
+
let io: CapturingIO;
|
|
46
47
|
|
|
47
48
|
beforeEach(() => {
|
|
48
|
-
jest.clearAllMocks();
|
|
49
|
-
consoleSpy = jest.spyOn(console, 'log').mockImplementation();
|
|
50
|
-
process.exitCode = 0;
|
|
51
|
-
});
|
|
52
49
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
process.exitCode = 0;
|
|
50
|
+
io = captureIO();
|
|
51
|
+
jest.clearAllMocks();
|
|
56
52
|
});
|
|
57
53
|
|
|
58
54
|
describe('validate', () => {
|
|
59
55
|
it('应该跳过无检查点的情况', async () => {
|
|
60
56
|
mockFs.readFile.mockRejectedValue(new Error('file not found'));
|
|
61
57
|
|
|
62
|
-
await validate({});
|
|
63
|
-
|
|
58
|
+
const result = await validate({}, io);
|
|
59
|
+
|
|
60
|
+
expect(io.outText()).toContain('没有定义检查点');
|
|
61
|
+
expect(result).toEqual({ kind: 'skip', reason: expect.stringContaining('没有定义检查点') });
|
|
64
62
|
});
|
|
65
63
|
|
|
66
64
|
it('应该通过所有检查点', async () => {
|
|
@@ -76,8 +74,10 @@ describe('validate command', () => {
|
|
|
76
74
|
};
|
|
77
75
|
(MockCheckpointValidator.getInstance as jest.Mock).mockReturnValue(mockValidator);
|
|
78
76
|
|
|
79
|
-
await validate({});
|
|
80
|
-
|
|
77
|
+
const result = await validate({}, io);
|
|
78
|
+
|
|
79
|
+
expect(io.outText()).toContain('所有检查点验证通过');
|
|
80
|
+
expect(result).toEqual({ kind: 'ok' });
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
it('应该显示失败的检查点', async () => {
|
|
@@ -97,12 +97,11 @@ describe('validate command', () => {
|
|
|
97
97
|
(MockCheckpointValidator.getInstance as jest.Mock).mockReturnValue(mockValidator);
|
|
98
98
|
|
|
99
99
|
// 工单 23:检查点失败一律 exit 1(门控语义)
|
|
100
|
-
const mockExit = jest.spyOn(process, 'exit').mockImplementation(() => undefined as never);
|
|
101
100
|
|
|
102
|
-
await validate({});
|
|
103
|
-
|
|
104
|
-
expect(
|
|
105
|
-
|
|
101
|
+
const result = await validate({}, io);
|
|
102
|
+
|
|
103
|
+
expect(io.outText()).toContain('失败');
|
|
104
|
+
expect(result).toEqual({ kind: 'fail', reason: '1 个检查点未通过: test-1' });
|
|
106
105
|
});
|
|
107
106
|
|
|
108
107
|
it('应该在严格模式下退出', async () => {
|
|
@@ -121,11 +120,10 @@ describe('validate command', () => {
|
|
|
121
120
|
};
|
|
122
121
|
(MockCheckpointValidator.getInstance as jest.Mock).mockReturnValue(mockValidator);
|
|
123
122
|
|
|
124
|
-
const
|
|
123
|
+
const result = await validate({ strict: true }, io);
|
|
125
124
|
|
|
126
|
-
|
|
127
|
-
expect(
|
|
128
|
-
mockExit.mockRestore();
|
|
125
|
+
// 工单 23 语义:--strict 与否都是 fail;退出码映射在 bin
|
|
126
|
+
expect(result).toEqual({ kind: 'fail', reason: '1 个检查点未通过: test-1' });
|
|
129
127
|
});
|
|
130
128
|
});
|
|
131
129
|
|
|
@@ -136,20 +134,20 @@ describe('validate command', () => {
|
|
|
136
134
|
mockFs.writeFile.mockResolvedValue(undefined);
|
|
137
135
|
mockYaml.dump.mockReturnValue('yaml content');
|
|
138
136
|
|
|
139
|
-
await createExampleCheckpoint('/project');
|
|
137
|
+
await createExampleCheckpoint('/project', io);
|
|
140
138
|
|
|
141
139
|
expect(mockFs.mkdir).toHaveBeenCalled();
|
|
142
140
|
expect(mockFs.writeFile).toHaveBeenCalled();
|
|
143
|
-
expect(
|
|
141
|
+
expect(io.outText()).toContain('已创建示例检查点');
|
|
144
142
|
});
|
|
145
143
|
|
|
146
144
|
it('已存在时不覆盖', async () => {
|
|
147
145
|
mockFs.access.mockResolvedValue(undefined);
|
|
148
146
|
|
|
149
|
-
await createExampleCheckpoint('/project');
|
|
147
|
+
await createExampleCheckpoint('/project', io);
|
|
150
148
|
|
|
151
149
|
expect(mockFs.writeFile).not.toHaveBeenCalled();
|
|
152
|
-
expect(
|
|
150
|
+
expect(io.outText()).toContain('checkpoints.yml 已存在,跳过');
|
|
153
151
|
});
|
|
154
152
|
});
|
|
155
153
|
|
|
@@ -159,20 +157,20 @@ describe('validate command', () => {
|
|
|
159
157
|
mockFs.mkdir.mockResolvedValue(undefined);
|
|
160
158
|
mockFs.writeFile.mockResolvedValue(undefined);
|
|
161
159
|
|
|
162
|
-
await createExampleResolutions('/project');
|
|
160
|
+
await createExampleResolutions('/project', io);
|
|
163
161
|
|
|
164
162
|
expect(mockFs.mkdir).toHaveBeenCalled();
|
|
165
163
|
expect(mockFs.writeFile).toHaveBeenCalled();
|
|
166
|
-
expect(
|
|
164
|
+
expect(io.outText()).toContain('已创建 Resolutions 文件');
|
|
167
165
|
});
|
|
168
166
|
|
|
169
167
|
it('已存在时不覆盖', async () => {
|
|
170
168
|
mockFs.access.mockResolvedValue(undefined);
|
|
171
169
|
|
|
172
|
-
await createExampleResolutions('/project');
|
|
170
|
+
await createExampleResolutions('/project', io);
|
|
173
171
|
|
|
174
172
|
expect(mockFs.writeFile).not.toHaveBeenCalled();
|
|
175
|
-
expect(
|
|
173
|
+
expect(io.outText()).toContain('resolutions.json 已存在,跳过');
|
|
176
174
|
});
|
|
177
175
|
});
|
|
178
176
|
});
|
|
@@ -8,6 +8,8 @@ import chalk from 'chalk';
|
|
|
8
8
|
import * as fs from 'fs/promises';
|
|
9
9
|
import * as path from 'path';
|
|
10
10
|
import { SpecAcceptanceGate } from '../../gates/acceptance';
|
|
11
|
+
import { log, processIO, type CommandIO, type CommandResult } from '../command-contract';
|
|
12
|
+
|
|
11
13
|
|
|
12
14
|
export interface AcceptanceOptions {
|
|
13
15
|
/** 任务 ID */
|
|
@@ -25,8 +27,11 @@ export interface AcceptanceOptions {
|
|
|
25
27
|
/**
|
|
26
28
|
* 执行验收门控
|
|
27
29
|
*/
|
|
28
|
-
export async function acceptance(
|
|
29
|
-
|
|
30
|
+
export async function acceptance(
|
|
31
|
+
options: AcceptanceOptions,
|
|
32
|
+
io: CommandIO = processIO,
|
|
33
|
+
): Promise<CommandResult> {
|
|
34
|
+
log(io, chalk.blue('📋 验收标准门控检查...'));
|
|
30
35
|
|
|
31
36
|
const projectPath = options.projectPath || process.cwd();
|
|
32
37
|
|
|
@@ -47,36 +52,40 @@ export async function acceptance(options: AcceptanceOptions): Promise<void> {
|
|
|
47
52
|
const result = await gate.check(context as any);
|
|
48
53
|
|
|
49
54
|
if (result.passed) {
|
|
50
|
-
|
|
51
|
-
|
|
55
|
+
log(io);
|
|
56
|
+
log(io, chalk.green('✅ 验收标准检查通过'));
|
|
52
57
|
if (result.details) {
|
|
53
|
-
|
|
54
|
-
|
|
58
|
+
log(io, chalk.gray(` 通过项: ${result.details.checkedCriteria ?? 0}`));
|
|
59
|
+
log(io, chalk.gray(` 总项数: ${result.details.totalCriteria ?? 0}`));
|
|
55
60
|
}
|
|
56
61
|
} else {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
log(io);
|
|
63
|
+
log(io, chalk.red('❌ 验收标准检查失败'));
|
|
64
|
+
log(io, chalk.red(` ${result.message}`));
|
|
60
65
|
if (result.details?.uncheckedCriteria) {
|
|
61
66
|
(result.details.uncheckedCriteria as string[]).forEach((criteria: string) => {
|
|
62
|
-
|
|
67
|
+
log(io, chalk.red(` - ${criteria}`));
|
|
63
68
|
});
|
|
64
69
|
}
|
|
65
|
-
|
|
70
|
+
return { kind: 'fail', reason: `acceptance gate denied: ${result.message}` };
|
|
66
71
|
}
|
|
72
|
+
return { kind: 'ok' };
|
|
67
73
|
} catch (error: any) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
74
|
+
log(io);
|
|
75
|
+
log(io, chalk.red('❌ 验收标准检查出错'));
|
|
76
|
+
log(io, chalk.red(` ${error.message}`));
|
|
77
|
+
return { kind: 'fail', reason: `acceptance gate error: ${error.message}` };
|
|
72
78
|
}
|
|
73
79
|
}
|
|
74
80
|
|
|
75
81
|
/**
|
|
76
82
|
* 列出所有任务及其验收标准
|
|
77
83
|
*/
|
|
78
|
-
export async function listAcceptanceCriteria(
|
|
79
|
-
|
|
84
|
+
export async function listAcceptanceCriteria(
|
|
85
|
+
options: AcceptanceOptions,
|
|
86
|
+
io: CommandIO = processIO,
|
|
87
|
+
): Promise<CommandResult> {
|
|
88
|
+
log(io, chalk.blue('📋 任务验收标准列表...\n'));
|
|
80
89
|
|
|
81
90
|
const projectPath = options.projectPath || process.cwd();
|
|
82
91
|
const tasksPath = options.tasksPath || path.join(projectPath, 'tasks.yml');
|
|
@@ -87,25 +96,27 @@ export async function listAcceptanceCriteria(options: AcceptanceOptions): Promis
|
|
|
87
96
|
const tasks = yaml.load(content) as any;
|
|
88
97
|
|
|
89
98
|
if (!tasks || typeof tasks !== 'object') {
|
|
90
|
-
|
|
91
|
-
return;
|
|
99
|
+
log(io, chalk.yellow('⚠️ 未找到任务定义'));
|
|
100
|
+
return { kind: 'skip', reason: `未找到任务定义: ${tasksPath}` };
|
|
92
101
|
}
|
|
93
102
|
|
|
94
103
|
for (const [taskId, task] of Object.entries(tasks)) {
|
|
95
104
|
if (typeof task === 'object' && task !== null) {
|
|
96
|
-
|
|
105
|
+
log(io, chalk.cyan(`${taskId}:`));
|
|
97
106
|
const taskObj = task as any;
|
|
98
107
|
if (taskObj.acceptanceCriteria) {
|
|
99
108
|
taskObj.acceptanceCriteria.forEach((criteria: string, i: number) => {
|
|
100
|
-
|
|
109
|
+
log(io, chalk.gray(` ${i + 1}. ${criteria}`));
|
|
101
110
|
});
|
|
102
111
|
} else {
|
|
103
|
-
|
|
112
|
+
log(io, chalk.gray(' (无验收标准)'));
|
|
104
113
|
}
|
|
105
|
-
|
|
114
|
+
log(io);
|
|
106
115
|
}
|
|
107
116
|
}
|
|
117
|
+
return { kind: 'ok' };
|
|
108
118
|
} catch (error: any) {
|
|
109
|
-
|
|
119
|
+
log(io, chalk.red(`❌ 读取 tasks.yml 失败: ${error.message}`));
|
|
120
|
+
return { kind: 'skip', reason: `读取 tasks.yml 失败: ${error.message}` };
|
|
110
121
|
}
|
|
111
122
|
}
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
hasSemanticContent,
|
|
29
29
|
STOP_WORDS,
|
|
30
30
|
} from '../session-mining';
|
|
31
|
+
import { log, processIO, type CommandIO, type CommandResult } from '../command-contract';
|
|
31
32
|
|
|
32
33
|
export interface AnalyzeSessionsOptions {
|
|
33
34
|
days?: number;
|
|
@@ -52,26 +53,25 @@ interface PatternCandidate {
|
|
|
52
53
|
|
|
53
54
|
// ── Main ──
|
|
54
55
|
|
|
55
|
-
export async function analyzeSessions(options: AnalyzeSessionsOptions): Promise<
|
|
56
|
+
export async function analyzeSessions(options: AnalyzeSessionsOptions, io: CommandIO = processIO): Promise<CommandResult> {
|
|
56
57
|
const transcriptDir = process.env.CLAUDE_TRANSCRIPTS_DIR
|
|
57
58
|
|| path.join(os.homedir(), '.claude', 'projects', '-root--claude');
|
|
58
59
|
const memoryDir = path.join(os.homedir(), '.claude', 'projects', '-root-projects', 'memory');
|
|
59
60
|
const days = options.days || 7;
|
|
60
61
|
|
|
61
62
|
if (!fs.existsSync(transcriptDir)) {
|
|
62
|
-
|
|
63
|
-
return;
|
|
63
|
+
log(io, chalk.yellow('No transcripts directory found'));
|
|
64
|
+
return { kind: 'skip', reason: `会话记录目录不存在: ${transcriptDir}` };
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
// 1. Scan transcripts
|
|
67
|
+
// 1. Scan transcripts(since 下推 seam(harness#112):stat 级过滤,窗口外不 parse;倒序)
|
|
67
68
|
const cutoff = Date.now() - days * 24 * 60 * 60 * 1000;
|
|
68
|
-
const sessions = readTranscriptSessions(transcriptDir)
|
|
69
|
-
.filter(s => s.mtimeMs >= cutoff)
|
|
69
|
+
const sessions = readTranscriptSessions(transcriptDir, { since: cutoff })
|
|
70
70
|
.sort((a, b) => b.date.localeCompare(a.date));
|
|
71
71
|
|
|
72
72
|
if (sessions.length === 0) {
|
|
73
|
-
|
|
74
|
-
return;
|
|
73
|
+
log(io, chalk.yellow(`No sessions found in the last ${days} days`));
|
|
74
|
+
return { kind: 'skip', reason: `最近 ${days} 天没有会话` };
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
// 2. Extract corrections + N-grams
|
|
@@ -86,14 +86,15 @@ export async function analyzeSessions(options: AnalyzeSessionsOptions): Promise<
|
|
|
86
86
|
|
|
87
87
|
// 5. Output
|
|
88
88
|
if (options.json) {
|
|
89
|
-
|
|
90
|
-
return;
|
|
89
|
+
log(io, JSON.stringify({ sessions: sessions.length, corrections: corrections.length, candidates }, null, 2));
|
|
90
|
+
return { kind: 'ok' };
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
log(io, chalk.blue(`🔍 Analyzing ${sessions.length} sessions (last ${days} days)...\n`));
|
|
94
94
|
|
|
95
|
-
printCorrectionSummary(corrections);
|
|
96
|
-
printCandidates(candidates);
|
|
95
|
+
printCorrectionSummary(corrections, io);
|
|
96
|
+
printCandidates(candidates, io);
|
|
97
|
+
return { kind: 'ok' };
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
// ── Correction Extraction ──
|
|
@@ -301,34 +302,34 @@ function extractConcept(sentences: string[]): string {
|
|
|
301
302
|
|
|
302
303
|
// ── Output ──
|
|
303
304
|
|
|
304
|
-
function printCorrectionSummary(corrections: Correction[]): void {
|
|
305
|
+
function printCorrectionSummary(corrections: Correction[], io: CommandIO): void {
|
|
305
306
|
if (corrections.length === 0) {
|
|
306
|
-
|
|
307
|
+
log(io, chalk.green('No correction patterns found'));
|
|
307
308
|
return;
|
|
308
309
|
}
|
|
309
310
|
|
|
310
|
-
|
|
311
|
+
log(io, chalk.yellow(`📢 ${corrections.length} correction signals detected\n`));
|
|
311
312
|
}
|
|
312
313
|
|
|
313
|
-
function printCandidates(candidates: PatternCandidate[]): void {
|
|
314
|
+
function printCandidates(candidates: PatternCandidate[], io: CommandIO): void {
|
|
314
315
|
if (candidates.length === 0) {
|
|
315
|
-
|
|
316
|
+
log(io, chalk.green('✅ No new pattern candidates — all recurring concepts already have rules\n'));
|
|
316
317
|
return;
|
|
317
318
|
}
|
|
318
319
|
|
|
319
|
-
|
|
320
|
+
log(io, chalk.bold('🔔 Pattern Candidates (suggested rules)\n'));
|
|
320
321
|
|
|
321
322
|
const topK = candidates.slice(0, 10);
|
|
322
323
|
for (const c of topK) {
|
|
323
324
|
const icon = c.source === 'correction' ? '🔴' : '🟡';
|
|
324
325
|
const confBar = '█'.repeat(Math.round(c.confidence * 10)) + '░'.repeat(10 - Math.round(c.confidence * 10));
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
326
|
+
log(io, chalk.bold(`${icon} ${c.pattern}`));
|
|
327
|
+
log(io, chalk.gray(` Source: ${c.source} | Freq: ${c.frequency} | Sessions: ${c.sessions.length} | Confidence: ${confBar}`));
|
|
328
|
+
log(io, chalk.cyan(` → Rule: ${c.suggestedRule}`));
|
|
329
|
+
log(io);
|
|
329
330
|
}
|
|
330
331
|
|
|
331
332
|
if (candidates.length > 10) {
|
|
332
|
-
|
|
333
|
+
log(io, chalk.gray(`... and ${candidates.length - 10} more candidates. Run with --json for full list.`));
|
|
333
334
|
}
|
|
334
335
|
}
|
|
@@ -4,18 +4,25 @@
|
|
|
4
4
|
* 检查约束是否满足(check 层:Iron Laws / Guidelines;prompt 层仅注入不检查)
|
|
5
5
|
* 工单 23:触发条件与证据检测迁至 core/constraints/context-builder
|
|
6
6
|
* ADR-0001:约束集统一走 getMergedConstraintsConfig 生效集链路(preset/config 禁用/custom/scenes)
|
|
7
|
+
* harness#88:本命令是 trace 记录器的组合根——core 不上行依赖 monitoring,
|
|
8
|
+
* 真实收集器在此经构造参数接线
|
|
7
9
|
*/
|
|
8
10
|
|
|
9
11
|
import chalk from 'chalk';
|
|
10
12
|
import * as fs from 'fs';
|
|
11
13
|
import * as path from 'path';
|
|
12
|
-
import {
|
|
14
|
+
import { ConstraintChecker } from '../../core/constraints/checker';
|
|
13
15
|
import { IRON_LAWS, GUIDELINES, PROMPTS } from '../../core/constraints/definitions';
|
|
14
16
|
import { getMergedConstraintsConfig } from '../../core/effective-constraints';
|
|
15
17
|
import { buildConstraintContext } from '../../core/constraints/context-builder';
|
|
18
|
+
import { createGitEvidence, type GitEvidence } from '../../core/constraints/git-evidence';
|
|
16
19
|
import { detectInjectionDrift } from '../../core/constraints/injection-drift';
|
|
20
|
+
import { GOVERNANCE_HEADING } from '../../core/constraints/injection-writer';
|
|
21
|
+
import { getTraceCollector } from '../../monitoring/traces';
|
|
22
|
+
import { countJsonlLines } from '../../utils/jsonl';
|
|
17
23
|
import { DEFAULT_TRACE_FILE } from '../../types/trace';
|
|
18
24
|
import type { ConstraintTrigger } from '../../types/constraint';
|
|
25
|
+
import { log, processIO, type CommandIO, type CommandResult } from '../command-contract';
|
|
19
26
|
|
|
20
27
|
export interface CheckOptions {
|
|
21
28
|
/** 预设名称 */
|
|
@@ -26,14 +33,24 @@ export interface CheckOptions {
|
|
|
26
33
|
trigger?: ConstraintTrigger;
|
|
27
34
|
/** 项目路径 */
|
|
28
35
|
projectPath?: string;
|
|
36
|
+
/**
|
|
37
|
+
* git 证据 adapter(非 CLI flag;#87)
|
|
38
|
+
*
|
|
39
|
+
* 缺省 = 本 run 独占一份真 git 证据。注入则与调用方共用同一证据快照,
|
|
40
|
+
* 测试据此断言"同一 run 内每条 git 命令至多执行一次"。
|
|
41
|
+
*/
|
|
42
|
+
evidence?: GitEvidence;
|
|
29
43
|
}
|
|
30
44
|
|
|
31
45
|
/**
|
|
32
46
|
* 执行约束检查
|
|
33
47
|
*/
|
|
34
|
-
export async function check(
|
|
35
|
-
|
|
36
|
-
|
|
48
|
+
export async function check(
|
|
49
|
+
options: CheckOptions,
|
|
50
|
+
io: CommandIO = processIO,
|
|
51
|
+
): Promise<CommandResult> {
|
|
52
|
+
log(io, chalk.blue('🔍 检查约束...'));
|
|
53
|
+
log(io, chalk.gray(`预设: ${options.preset}`));
|
|
37
54
|
|
|
38
55
|
try {
|
|
39
56
|
const projectPath = options.projectPath || process.cwd();
|
|
@@ -43,33 +60,38 @@ export async function check(options: CheckOptions): Promise<void> {
|
|
|
43
60
|
// 项目自定义配置优先于 CLI 预设),优先级规则收在 getMergedConstraintsConfig 一处。
|
|
44
61
|
const merged = getMergedConstraintsConfig(projectPath, { preset: options.preset });
|
|
45
62
|
if (merged.custom.length > 0) {
|
|
46
|
-
|
|
63
|
+
log(io, chalk.gray(`自定义约束: ${merged.custom.length} 条`));
|
|
47
64
|
}
|
|
48
65
|
if (merged.disabled.length > 0) {
|
|
49
|
-
|
|
66
|
+
log(io, chalk.gray(`已禁用约束: ${merged.disabled.join(', ')}`));
|
|
50
67
|
}
|
|
51
68
|
const unknownIds = merged.unknownIds ?? [];
|
|
52
69
|
if (unknownIds.length > 0) {
|
|
53
|
-
|
|
70
|
+
log(io, chalk.yellow(`⚠️ 配置中存在未知约束 id(已忽略,可清理): ${unknownIds.join(', ')}`));
|
|
54
71
|
}
|
|
55
72
|
|
|
56
73
|
// 构建上下文(工单 23:触发条件与证据检测收敛至 core/constraints/context-builder)
|
|
74
|
+
// #87:一次 run 一份 git 证据——context-builder 与 checker 层共用同一实例
|
|
75
|
+
const evidence = options.evidence ?? createGitEvidence(projectPath);
|
|
57
76
|
const context = await buildConstraintContext({
|
|
58
77
|
projectPath: options.projectPath,
|
|
59
78
|
staged: options.staged,
|
|
60
79
|
trigger: options.trigger,
|
|
80
|
+
evidence,
|
|
61
81
|
});
|
|
62
82
|
const changedFiles = context.changedFiles ?? [];
|
|
63
83
|
if (changedFiles.length > 0) {
|
|
64
|
-
|
|
84
|
+
log(io, chalk.gray(`变更文件: ${changedFiles.length} 个`));
|
|
65
85
|
}
|
|
66
|
-
|
|
86
|
+
log(io, chalk.gray(`触发条件: ${[context.operation, ...(context.extraTriggers ?? [])].join(', ')}`));
|
|
67
87
|
|
|
68
|
-
// 执行三层检查(per-request 传 customConfig
|
|
69
|
-
|
|
88
|
+
// 执行三层检查(per-request 传 customConfig,避免单例状态污染;证据同 run 同源)
|
|
89
|
+
// trace 记录器经构造参数接线(harness#88):一次命令一个 checker 实例
|
|
90
|
+
const checker = new ConstraintChecker(getTraceCollector());
|
|
91
|
+
const result = await checker.checkConstraints(context, merged, evidence);
|
|
70
92
|
|
|
71
93
|
// 输出结果
|
|
72
|
-
|
|
94
|
+
log(io);
|
|
73
95
|
|
|
74
96
|
// skipped(约定未采用/证据未接线)单独列示,不进 pass/fail 统计(ADR-0001)
|
|
75
97
|
const skippedResults = [
|
|
@@ -81,39 +103,42 @@ export async function check(options: CheckOptions): Promise<void> {
|
|
|
81
103
|
const evaluatedIronLaws = result.ironLaws.filter(r => !r.skipped);
|
|
82
104
|
const ironLawViolations = evaluatedIronLaws.filter(r => !r.satisfied);
|
|
83
105
|
if (ironLawViolations.length === 0 && evaluatedIronLaws.length > 0) {
|
|
84
|
-
|
|
106
|
+
log(io, chalk.green(`✅ 铁律: 全部通过 (${evaluatedIronLaws.length} 条)`));
|
|
85
107
|
} else if (ironLawViolations.length > 0) {
|
|
86
|
-
|
|
108
|
+
log(io, chalk.red(`❌ 铁律违规: ${ironLawViolations.length} 条`));
|
|
87
109
|
ironLawViolations.forEach(r => {
|
|
88
110
|
if (r.constraint) {
|
|
89
|
-
|
|
90
|
-
|
|
111
|
+
log(io, chalk.red(` - ${r.constraint.id}: ${r.constraint.message}`));
|
|
112
|
+
log(io, chalk.red(` ${r.constraint.rule}`));
|
|
91
113
|
}
|
|
92
114
|
});
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
115
|
+
log(io);
|
|
116
|
+
log(io, chalk.red('🛑 铁律检查失败,请修复后再提交'));
|
|
117
|
+
return {
|
|
118
|
+
kind: 'fail',
|
|
119
|
+
reason: `iron law violated: ${ironLawViolations.map(r => r.constraint?.id ?? 'unknown').join(', ')}`,
|
|
120
|
+
};
|
|
96
121
|
}
|
|
97
122
|
|
|
98
123
|
// Guidelines
|
|
99
124
|
if (result.warningCount > 0) {
|
|
100
|
-
|
|
125
|
+
log(io, chalk.yellow(`⚠️ 指导原则警告: ${result.warningCount} 条`));
|
|
101
126
|
result.guidelines.filter(r => !r.satisfied).forEach(r => {
|
|
102
127
|
if (r.constraint) {
|
|
103
|
-
|
|
128
|
+
log(io, chalk.yellow(` - ${r.constraint.id}: ${r.constraint.message}`));
|
|
104
129
|
}
|
|
105
130
|
});
|
|
106
131
|
} else if (result.guidelines.length > 0) {
|
|
107
132
|
const evaluatedGuidelines = result.guidelines.filter(r => !r.skipped);
|
|
108
133
|
const passedGuidelines = evaluatedGuidelines.filter(r => r.satisfied).length;
|
|
109
|
-
|
|
134
|
+
log(io, chalk.green(`✅ 指导原则: ${passedGuidelines}/${evaluatedGuidelines.length} 通过`));
|
|
110
135
|
}
|
|
111
136
|
|
|
112
137
|
// Skipped:约定未采用 / 证据未接线,未评估(不计通过/失败)
|
|
113
138
|
if (skippedResults.length > 0) {
|
|
114
|
-
|
|
139
|
+
log(io, chalk.gray(`⏭️ 跳过评估: ${skippedResults.length} 条(约定未采用或证据未接线,不计通过/失败)`));
|
|
115
140
|
skippedResults.forEach(r => {
|
|
116
|
-
|
|
141
|
+
log(io, chalk.gray(` - ${r.id}`));
|
|
117
142
|
});
|
|
118
143
|
}
|
|
119
144
|
|
|
@@ -122,38 +147,39 @@ export async function check(options: CheckOptions): Promise<void> {
|
|
|
122
147
|
try {
|
|
123
148
|
const drift = detectInjectionDrift(projectPath);
|
|
124
149
|
if (drift.hasDrift) {
|
|
125
|
-
|
|
126
|
-
|
|
150
|
+
log(io);
|
|
151
|
+
log(io, chalk.yellow(`⚠️ 检测到 ${drift.injectionFile ?? '治理文档'} 约束注入漂移(仅警告,不阻断):`));
|
|
127
152
|
if (drift.versionDrift) {
|
|
128
|
-
|
|
153
|
+
log(io, chalk.yellow(` ⚠️⚠️ 注入段版本 (${drift.versionDrift.actual}) ≠ 已安装 harness 版本 (${drift.versionDrift.expected}):agent 上下文中的规则与已安装 harness 版本不一致`));
|
|
129
154
|
}
|
|
130
155
|
if (drift.contentDrift) {
|
|
131
|
-
|
|
156
|
+
log(io, chalk.yellow(` 内容漂移: 缺失 ${drift.contentDrift.missing.length} 条 / 多余 ${drift.contentDrift.extra.length} 条(条目级差异见 harness constraints report)`));
|
|
132
157
|
}
|
|
133
158
|
if (drift.duplicateHeading) {
|
|
134
|
-
|
|
159
|
+
log(io, chalk.yellow(` 检测到重复的 "${GOVERNANCE_HEADING}" 章节`));
|
|
135
160
|
}
|
|
136
|
-
|
|
161
|
+
log(io, chalk.yellow(` 修复: ${drift.fixHint}`));
|
|
137
162
|
}
|
|
138
163
|
} catch {
|
|
139
164
|
// 漂移检测失败不影响 check 结果
|
|
140
165
|
}
|
|
141
166
|
|
|
142
|
-
|
|
143
|
-
|
|
167
|
+
log(io);
|
|
168
|
+
log(io, chalk.green('✅ 约束检查通过'));
|
|
144
169
|
|
|
145
170
|
// 智能提示
|
|
146
171
|
const hint = await getSmartHint(projectPath);
|
|
147
172
|
if (hint) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
173
|
+
log(io);
|
|
174
|
+
log(io, chalk.gray('────────────────────────────────────'));
|
|
175
|
+
log(io, hint);
|
|
176
|
+
log(io, chalk.gray('────────────────────────────────────'));
|
|
152
177
|
}
|
|
178
|
+
return { kind: 'ok' };
|
|
153
179
|
} catch (error) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
180
|
+
log(io);
|
|
181
|
+
log(io, chalk.red(`❌ 约束检查异常: ${error instanceof Error ? error.message : String(error)}`));
|
|
182
|
+
return { kind: 'fail', reason: `check error: ${error instanceof Error ? error.message : String(error)}` };
|
|
157
183
|
}
|
|
158
184
|
}
|
|
159
185
|
|
|
@@ -163,17 +189,12 @@ export async function check(options: CheckOptions): Promise<void> {
|
|
|
163
189
|
async function getSmartHint(projectPath: string): Promise<string | null> {
|
|
164
190
|
const tracesPath = path.join(projectPath, DEFAULT_TRACE_FILE);
|
|
165
191
|
const statePath = path.join(projectPath, '.harness', '.state.json');
|
|
166
|
-
|
|
167
|
-
//
|
|
168
|
-
|
|
192
|
+
|
|
193
|
+
// 只数非空行数(含坏行),零 parse——原语义不变,走 jsonl 正本(harness#82)
|
|
194
|
+
const traceCount = countJsonlLines(tracesPath);
|
|
195
|
+
if (traceCount === 0) {
|
|
169
196
|
return null;
|
|
170
197
|
}
|
|
171
|
-
|
|
172
|
-
// 读取 trace 记录数
|
|
173
|
-
const tracesContent = fs.readFileSync(tracesPath, 'utf-8');
|
|
174
|
-
const lines = tracesContent.trim().split('\n').filter(Boolean);
|
|
175
|
-
const traceCount = lines.length;
|
|
176
|
-
|
|
177
198
|
// 读取状态
|
|
178
199
|
let state: {
|
|
179
200
|
shownHints?: string[];
|
|
@@ -206,33 +227,35 @@ async function getSmartHint(projectPath: string): Promise<string | null> {
|
|
|
206
227
|
/**
|
|
207
228
|
* 列出所有约束
|
|
208
229
|
*/
|
|
209
|
-
|
|
210
|
-
|
|
230
|
+
/** optionRoutes 一律以 (options) 调用;--list 不消费检查选项,形参仅占位 */
|
|
231
|
+
export function listLaws(_options: Partial<CheckOptions> = {}, io: CommandIO = processIO): CommandResult {
|
|
232
|
+
log(io, chalk.blue('\n📜 所有约束:\n'));
|
|
211
233
|
|
|
212
234
|
// Iron Laws
|
|
213
|
-
|
|
235
|
+
log(io, chalk.red('🔴 铁律 (Iron Laws) - 绝对禁止,无例外:\n'));
|
|
214
236
|
Object.values(IRON_LAWS).forEach(constraint => {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
237
|
+
log(io, chalk.red(` ${constraint.id}`));
|
|
238
|
+
log(io, chalk.gray(` ${constraint.rule}`));
|
|
239
|
+
log(io, chalk.gray(` ${constraint.message}`));
|
|
240
|
+
log(io);
|
|
219
241
|
});
|
|
220
242
|
|
|
221
243
|
// Guidelines
|
|
222
|
-
|
|
244
|
+
log(io, chalk.yellow('🟡 指导原则 (Guidelines) - 优先建议,违背发警告但不阻止:\n'));
|
|
223
245
|
Object.values(GUIDELINES).forEach(constraint => {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
246
|
+
log(io, chalk.yellow(` ${constraint.id}`));
|
|
247
|
+
log(io, chalk.gray(` ${constraint.rule}`));
|
|
248
|
+
log(io, chalk.gray(` ${constraint.message}`));
|
|
249
|
+
log(io);
|
|
228
250
|
});
|
|
229
251
|
|
|
230
252
|
// Prompts(ADR-0001:纯注入层,不执行检查)
|
|
231
|
-
|
|
253
|
+
log(io, chalk.blue('🔵 提示 (Prompts) - 纯文本注入,不参与检查:\n'));
|
|
232
254
|
Object.values(PROMPTS).forEach(constraint => {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
255
|
+
log(io, chalk.blue(` ${constraint.id}`));
|
|
256
|
+
log(io, chalk.gray(` ${constraint.rule}`));
|
|
257
|
+
log(io, chalk.gray(` ${constraint.message}`));
|
|
258
|
+
log(io);
|
|
237
259
|
});
|
|
260
|
+
return { kind: 'ok' };
|
|
238
261
|
}
|