@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 { review, reviewStatus } from '../review';
|
|
6
|
+
import { captureIO, type CapturingIO } from '../../command-contract';
|
|
6
7
|
import { execAsync } from '../../../utils/exec';
|
|
7
8
|
import { ReviewGate } from '../../../gates/review';
|
|
8
9
|
|
|
@@ -29,20 +30,12 @@ const mockExec = execAsync as jest.MockedFunction<typeof execAsync>;
|
|
|
29
30
|
const MockGate = ReviewGate as jest.MockedClass<typeof ReviewGate>;
|
|
30
31
|
|
|
31
32
|
describe('review command', () => {
|
|
32
|
-
let
|
|
33
|
-
let exitSpy: jest.SpyInstance;
|
|
33
|
+
let io: CapturingIO;
|
|
34
34
|
|
|
35
35
|
beforeEach(() => {
|
|
36
|
-
jest.clearAllMocks();
|
|
37
|
-
consoleSpy = jest.spyOn(console, 'log').mockImplementation();
|
|
38
|
-
exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => undefined as never);
|
|
39
|
-
process.exitCode = 0;
|
|
40
|
-
});
|
|
41
36
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
exitSpy.mockRestore();
|
|
45
|
-
process.exitCode = 0;
|
|
37
|
+
io = captureIO();
|
|
38
|
+
jest.clearAllMocks();
|
|
46
39
|
});
|
|
47
40
|
|
|
48
41
|
describe('review', () => {
|
|
@@ -55,10 +48,10 @@ describe('review command', () => {
|
|
|
55
48
|
});
|
|
56
49
|
MockGate.mockImplementation(() => ({ check: mockCheck }) as any);
|
|
57
50
|
|
|
58
|
-
await review({});
|
|
51
|
+
const result = await review({}, io);
|
|
59
52
|
|
|
60
|
-
expect(
|
|
61
|
-
expect(
|
|
53
|
+
expect(io.outText()).toContain('代码审查门控检查通过');
|
|
54
|
+
expect(result.kind).toBe('ok');
|
|
62
55
|
});
|
|
63
56
|
|
|
64
57
|
it('should print failure and exit 1 when check fails', async () => {
|
|
@@ -70,10 +63,13 @@ describe('review command', () => {
|
|
|
70
63
|
});
|
|
71
64
|
MockGate.mockImplementation(() => ({ check: mockCheck }) as any);
|
|
72
65
|
|
|
73
|
-
await review({});
|
|
66
|
+
const result = await review({}, io);
|
|
74
67
|
|
|
75
|
-
expect(
|
|
76
|
-
expect(
|
|
68
|
+
expect(io.outText()).toContain('代码审查门控检查失败');
|
|
69
|
+
expect(result).toEqual({
|
|
70
|
+
kind: 'fail',
|
|
71
|
+
reason: 'review gate denied: needs approval',
|
|
72
|
+
});
|
|
77
73
|
});
|
|
78
74
|
|
|
79
75
|
it('should handle errors and exit 1', async () => {
|
|
@@ -81,19 +77,25 @@ describe('review command', () => {
|
|
|
81
77
|
const mockCheck = jest.fn().mockRejectedValue(new Error('gate error'));
|
|
82
78
|
MockGate.mockImplementation(() => ({ check: mockCheck }) as any);
|
|
83
79
|
|
|
84
|
-
await review({});
|
|
80
|
+
const result = await review({}, io);
|
|
85
81
|
|
|
86
|
-
expect(
|
|
87
|
-
expect(
|
|
82
|
+
expect(io.outText()).toContain('代码审查门控检查出错');
|
|
83
|
+
expect(result).toEqual({
|
|
84
|
+
kind: 'fail',
|
|
85
|
+
reason: 'review gate error: gate error',
|
|
86
|
+
});
|
|
88
87
|
});
|
|
89
88
|
|
|
90
89
|
it('should show hint when not in a git repo', async () => {
|
|
91
90
|
mockExec.mockRejectedValue(new Error('not a git repository'));
|
|
92
91
|
|
|
93
|
-
await review({});
|
|
92
|
+
const result = await review({}, io);
|
|
94
93
|
|
|
95
|
-
expect(
|
|
96
|
-
expect(
|
|
94
|
+
expect(io.outText()).toContain('需要在 Git 仓库中运行');
|
|
95
|
+
expect(result).toEqual({
|
|
96
|
+
kind: 'fail',
|
|
97
|
+
reason: 'review gate error: not a git repository',
|
|
98
|
+
});
|
|
97
99
|
});
|
|
98
100
|
|
|
99
101
|
it('should parse allowedReviewers from comma-separated string', async () => {
|
|
@@ -101,7 +103,7 @@ describe('review command', () => {
|
|
|
101
103
|
const mockCheck = jest.fn().mockResolvedValue({ passed: true, message: 'ok' });
|
|
102
104
|
MockGate.mockImplementation(() => ({ check: mockCheck }) as any);
|
|
103
105
|
|
|
104
|
-
await review({ allowedReviewers: 'alice, bob, charlie' });
|
|
106
|
+
await review({ allowedReviewers: 'alice, bob, charlie' }, io);
|
|
105
107
|
|
|
106
108
|
expect(MockGate).toHaveBeenCalledWith(
|
|
107
109
|
expect.objectContaining({
|
|
@@ -126,10 +128,10 @@ describe('review command', () => {
|
|
|
126
128
|
stderr: '',
|
|
127
129
|
});
|
|
128
130
|
|
|
129
|
-
await reviewStatus({});
|
|
131
|
+
await reviewStatus({}, io);
|
|
130
132
|
|
|
131
|
-
expect(
|
|
132
|
-
expect(
|
|
133
|
+
expect(io.outText()).toContain('PR #42');
|
|
134
|
+
expect(io.outText()).toContain('APPROVED');
|
|
133
135
|
});
|
|
134
136
|
|
|
135
137
|
it('should handle no PR found', async () => {
|
|
@@ -137,17 +139,17 @@ describe('review command', () => {
|
|
|
137
139
|
.mockResolvedValueOnce({ stdout: 'feature-branch\n', stderr: '' })
|
|
138
140
|
.mockRejectedValueOnce(new Error('no PR'));
|
|
139
141
|
|
|
140
|
-
await reviewStatus({});
|
|
142
|
+
await reviewStatus({}, io);
|
|
141
143
|
|
|
142
|
-
expect(
|
|
144
|
+
expect(io.outText()).toContain('未找到关联的 PR');
|
|
143
145
|
});
|
|
144
146
|
|
|
145
147
|
it('should handle git errors', async () => {
|
|
146
148
|
mockExec.mockRejectedValue(new Error('not a git repository'));
|
|
147
149
|
|
|
148
|
-
await reviewStatus({});
|
|
150
|
+
await reviewStatus({}, io);
|
|
149
151
|
|
|
150
|
-
expect(
|
|
152
|
+
expect(io.outText()).toContain('获取审查状态失败');
|
|
151
153
|
});
|
|
152
154
|
});
|
|
153
155
|
});
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { security, auditDetails } from '../security';
|
|
6
|
+
import { captureIO, type CapturingIO } from '../../command-contract';
|
|
6
7
|
import { SecurityGate } from '../../../gates/security';
|
|
7
8
|
|
|
8
9
|
jest.mock('../../../gates/security', () => ({
|
|
@@ -22,20 +23,12 @@ jest.mock('chalk', () => ({
|
|
|
22
23
|
const MockGate = SecurityGate as jest.MockedClass<typeof SecurityGate>;
|
|
23
24
|
|
|
24
25
|
describe('security command', () => {
|
|
25
|
-
let
|
|
26
|
-
let exitSpy: jest.SpyInstance;
|
|
26
|
+
let io: CapturingIO;
|
|
27
27
|
|
|
28
28
|
beforeEach(() => {
|
|
29
|
-
jest.clearAllMocks();
|
|
30
|
-
consoleSpy = jest.spyOn(console, 'log').mockImplementation();
|
|
31
|
-
exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => undefined as never);
|
|
32
|
-
process.exitCode = 0;
|
|
33
|
-
});
|
|
34
29
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
exitSpy.mockRestore();
|
|
38
|
-
process.exitCode = 0;
|
|
30
|
+
io = captureIO();
|
|
31
|
+
jest.clearAllMocks();
|
|
39
32
|
});
|
|
40
33
|
|
|
41
34
|
describe('security', () => {
|
|
@@ -47,10 +40,10 @@ describe('security command', () => {
|
|
|
47
40
|
});
|
|
48
41
|
MockGate.mockImplementation(() => ({ scan: mockScan }) as any);
|
|
49
42
|
|
|
50
|
-
await security({});
|
|
43
|
+
const result = await security({}, io);
|
|
51
44
|
|
|
52
|
-
expect(
|
|
53
|
-
expect(
|
|
45
|
+
expect(io.outText()).toContain('安全门控检查通过');
|
|
46
|
+
expect(result.kind).toBe('ok');
|
|
54
47
|
});
|
|
55
48
|
|
|
56
49
|
it('should print failure and exit 1 when scan fails', async () => {
|
|
@@ -68,19 +61,22 @@ describe('security command', () => {
|
|
|
68
61
|
});
|
|
69
62
|
MockGate.mockImplementation(() => ({ scan: mockScan }) as any);
|
|
70
63
|
|
|
71
|
-
await security({});
|
|
64
|
+
const result = await security({}, io);
|
|
72
65
|
|
|
73
|
-
expect(
|
|
74
|
-
expect(
|
|
75
|
-
expect(
|
|
76
|
-
expect(
|
|
66
|
+
expect(io.outText()).toContain('安全门控检查失败');
|
|
67
|
+
expect(io.outText()).toContain('pkg-a');
|
|
68
|
+
expect(io.outText()).toContain('pkg-b');
|
|
69
|
+
expect(result).toEqual({
|
|
70
|
+
kind: 'fail',
|
|
71
|
+
reason: 'security gate denied (threshold high): vulnerabilities found',
|
|
72
|
+
});
|
|
77
73
|
});
|
|
78
74
|
|
|
79
75
|
it('should default severity to high', async () => {
|
|
80
76
|
const mockScan = jest.fn().mockResolvedValue({ passed: true, message: 'ok' });
|
|
81
77
|
MockGate.mockImplementation(() => ({ scan: mockScan }) as any);
|
|
82
78
|
|
|
83
|
-
await security({});
|
|
79
|
+
await security({}, io);
|
|
84
80
|
|
|
85
81
|
expect(MockGate).toHaveBeenCalledWith(
|
|
86
82
|
expect.objectContaining({ severityThreshold: 'high' }),
|
|
@@ -91,7 +87,7 @@ describe('security command', () => {
|
|
|
91
87
|
const mockScan = jest.fn().mockResolvedValue({ passed: true, message: 'ok' });
|
|
92
88
|
MockGate.mockImplementation(() => ({ scan: mockScan }) as any);
|
|
93
89
|
|
|
94
|
-
await security({ severity: 'critical' });
|
|
90
|
+
await security({ severity: 'critical' }, io);
|
|
95
91
|
|
|
96
92
|
expect(MockGate).toHaveBeenCalledWith(
|
|
97
93
|
expect.objectContaining({ severityThreshold: 'critical' }),
|
|
@@ -108,9 +104,9 @@ describe('security command', () => {
|
|
|
108
104
|
});
|
|
109
105
|
MockGate.mockImplementation(() => ({ scan: mockScan }) as any);
|
|
110
106
|
|
|
111
|
-
await auditDetails({});
|
|
107
|
+
await auditDetails({}, io);
|
|
112
108
|
|
|
113
|
-
expect(
|
|
109
|
+
expect(io.outText()).toContain('未发现安全漏洞');
|
|
114
110
|
});
|
|
115
111
|
|
|
116
112
|
it('should list vulnerabilities when present', async () => {
|
|
@@ -127,17 +123,17 @@ describe('security command', () => {
|
|
|
127
123
|
});
|
|
128
124
|
MockGate.mockImplementation(() => ({ scan: mockScan }) as any);
|
|
129
125
|
|
|
130
|
-
await auditDetails({});
|
|
126
|
+
await auditDetails({}, io);
|
|
131
127
|
|
|
132
|
-
expect(
|
|
133
|
-
expect(
|
|
128
|
+
expect(io.outText()).toContain('发现 2 个漏洞');
|
|
129
|
+
expect(io.outText()).toContain('pkg-a');
|
|
134
130
|
});
|
|
135
131
|
|
|
136
132
|
it('should default severity to low for audit', async () => {
|
|
137
133
|
const mockScan = jest.fn().mockResolvedValue({ passed: true, message: 'ok', details: {} });
|
|
138
134
|
MockGate.mockImplementation(() => ({ scan: mockScan }) as any);
|
|
139
135
|
|
|
140
|
-
await auditDetails({});
|
|
136
|
+
await auditDetails({}, io);
|
|
141
137
|
|
|
142
138
|
expect(MockGate).toHaveBeenCalledWith(
|
|
143
139
|
expect.objectContaining({ severityThreshold: 'low' }),
|
|
@@ -3,13 +3,17 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import * as fs from 'fs';
|
|
6
|
+
import { captureIO, type CapturingIO } from '../../command-contract';
|
|
6
7
|
import * as path from 'path';
|
|
7
8
|
import { extractBaselineSection, specBaselineCheck } from '../spec-baseline-check';
|
|
8
9
|
|
|
10
|
+
let io: CapturingIO;
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
io = captureIO();
|
|
13
|
+
});
|
|
14
|
+
|
|
9
15
|
describe('spec-baseline-check', () => {
|
|
10
16
|
const tempDir = path.join(process.cwd(), 'temp-test-spec-baseline');
|
|
11
|
-
let consoleSpy: jest.SpyInstance;
|
|
12
|
-
let errorSpy: jest.SpyInstance;
|
|
13
17
|
let originalExitCode: string | number | undefined;
|
|
14
18
|
|
|
15
19
|
beforeAll(() => {
|
|
@@ -26,15 +30,10 @@ describe('spec-baseline-check', () => {
|
|
|
26
30
|
|
|
27
31
|
beforeEach(() => {
|
|
28
32
|
jest.clearAllMocks();
|
|
29
|
-
consoleSpy = jest.spyOn(console, 'log').mockImplementation();
|
|
30
|
-
errorSpy = jest.spyOn(console, 'error').mockImplementation();
|
|
31
33
|
originalExitCode = process.exitCode;
|
|
32
|
-
process.exitCode = 0;
|
|
33
34
|
});
|
|
34
35
|
|
|
35
36
|
afterEach(() => {
|
|
36
|
-
consoleSpy.mockRestore();
|
|
37
|
-
errorSpy.mockRestore();
|
|
38
37
|
process.exitCode = originalExitCode;
|
|
39
38
|
});
|
|
40
39
|
|
|
@@ -153,19 +152,20 @@ describe('spec-baseline-check', () => {
|
|
|
153
152
|
|
|
154
153
|
describe('specBaselineCheck CLI', () => {
|
|
155
154
|
it('应该在文件不存在时报错', async () => {
|
|
156
|
-
await specBaselineCheck('/nonexistent/spec.md');
|
|
155
|
+
const result = await specBaselineCheck('/nonexistent/spec.md', {}, io);
|
|
157
156
|
|
|
158
|
-
expect(
|
|
159
|
-
expect(
|
|
157
|
+
expect(io.errText()).toContain('文件不存在');
|
|
158
|
+
expect(result).toEqual({ kind: 'usage-error', reason: expect.stringContaining('spec 文件不存在') });
|
|
160
159
|
});
|
|
161
160
|
|
|
162
161
|
it('没有 Baseline section 应该提示', async () => {
|
|
163
162
|
const specPath = path.join(tempDir, 'no-baseline.md');
|
|
164
163
|
fs.writeFileSync(specPath, '# Spec\n## Overview\nNo baseline here.');
|
|
165
164
|
|
|
166
|
-
await specBaselineCheck(specPath, { projectPath: tempDir });
|
|
165
|
+
const result = await specBaselineCheck(specPath, { projectPath: tempDir }, io);
|
|
167
166
|
|
|
168
|
-
expect(
|
|
167
|
+
expect(io.outText()).toContain('未找到');
|
|
168
|
+
expect(result).toEqual({ kind: 'skip', reason: expect.stringContaining('无可判定项') });
|
|
169
169
|
});
|
|
170
170
|
|
|
171
171
|
it('应该输出 table 格式结果', async () => {
|
|
@@ -182,9 +182,9 @@ describe('spec-baseline-check', () => {
|
|
|
182
182
|
'- 普通文本描述',
|
|
183
183
|
].join('\n'));
|
|
184
184
|
|
|
185
|
-
await specBaselineCheck(specPath, { projectPath: subDir });
|
|
185
|
+
await specBaselineCheck(specPath, { projectPath: subDir }, io);
|
|
186
186
|
|
|
187
|
-
const output =
|
|
187
|
+
const output = io.outText();
|
|
188
188
|
expect(output).toContain('前置条件检查');
|
|
189
189
|
});
|
|
190
190
|
|
|
@@ -196,9 +196,9 @@ describe('spec-baseline-check', () => {
|
|
|
196
196
|
'- `package.json` exists',
|
|
197
197
|
].join('\n'));
|
|
198
198
|
|
|
199
|
-
await specBaselineCheck(specPath, { json: true, projectPath: tempDir });
|
|
199
|
+
await specBaselineCheck(specPath, { json: true, projectPath: tempDir }, io);
|
|
200
200
|
|
|
201
|
-
const jsonCall =
|
|
201
|
+
const jsonCall = io.outRecords().map(chunk => [chunk] as string[]).find((c: any[]) => {
|
|
202
202
|
try {
|
|
203
203
|
const parsed = JSON.parse(c[0]);
|
|
204
204
|
return Array.isArray(parsed);
|
|
@@ -207,7 +207,7 @@ describe('spec-baseline-check', () => {
|
|
|
207
207
|
}
|
|
208
208
|
});
|
|
209
209
|
expect(jsonCall).toBeTruthy();
|
|
210
|
-
const parsed = JSON.parse(jsonCall[0]);
|
|
210
|
+
const parsed = JSON.parse(jsonCall![0]);
|
|
211
211
|
expect(parsed.length).toBe(1);
|
|
212
212
|
expect(parsed[0]).toHaveProperty('prerequisite');
|
|
213
213
|
expect(parsed[0]).toHaveProperty('satisfied');
|
|
@@ -218,9 +218,9 @@ describe('spec-baseline-check', () => {
|
|
|
218
218
|
const specPath = path.join(tempDir, 'empty-baseline.md');
|
|
219
219
|
fs.writeFileSync(specPath, '# Test\n## Baseline\n\n## Next');
|
|
220
220
|
|
|
221
|
-
await specBaselineCheck(specPath, { json: true, projectPath: tempDir });
|
|
221
|
+
await specBaselineCheck(specPath, { json: true, projectPath: tempDir }, io);
|
|
222
222
|
|
|
223
|
-
const jsonCall =
|
|
223
|
+
const jsonCall = io.outRecords().map(chunk => [chunk] as string[]).find((c: any[]) => {
|
|
224
224
|
try {
|
|
225
225
|
const parsed = JSON.parse(c[0]);
|
|
226
226
|
return parsed.prerequisites !== undefined;
|
|
@@ -229,7 +229,7 @@ describe('spec-baseline-check', () => {
|
|
|
229
229
|
}
|
|
230
230
|
});
|
|
231
231
|
expect(jsonCall).toBeTruthy();
|
|
232
|
-
expect(JSON.parse(jsonCall[0]).prerequisites).toHaveLength(0);
|
|
232
|
+
expect(JSON.parse(jsonCall![0]).prerequisites).toHaveLength(0);
|
|
233
233
|
});
|
|
234
234
|
});
|
|
235
235
|
});
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { specValidate, listSpecTypes } from '../spec';
|
|
6
|
+
import { captureIO, type CapturingIO } from '../../command-contract';
|
|
6
7
|
import { SpecValidator, validateAllSpecs } from '../../../core/spec/validator';
|
|
7
8
|
import type { BatchSpecValidationResult, SpecValidationResult } from '../../../types/spec';
|
|
8
9
|
|
|
@@ -27,8 +28,12 @@ jest.mock('chalk', () => ({
|
|
|
27
28
|
const MockSpecValidator = SpecValidator as jest.Mocked<typeof SpecValidator>;
|
|
28
29
|
const mockValidateAllSpecs = validateAllSpecs as jest.MockedFunction<typeof validateAllSpecs>;
|
|
29
30
|
|
|
31
|
+
let io: CapturingIO;
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
io = captureIO();
|
|
34
|
+
});
|
|
35
|
+
|
|
30
36
|
describe('spec command', () => {
|
|
31
|
-
let consoleSpy: jest.SpyInstance;
|
|
32
37
|
let mockValidator: {
|
|
33
38
|
setConfig: jest.Mock;
|
|
34
39
|
validateFile: jest.Mock;
|
|
@@ -36,8 +41,6 @@ describe('spec command', () => {
|
|
|
36
41
|
|
|
37
42
|
beforeEach(() => {
|
|
38
43
|
jest.clearAllMocks();
|
|
39
|
-
consoleSpy = jest.spyOn(console, 'log').mockImplementation();
|
|
40
|
-
process.exitCode = 0;
|
|
41
44
|
|
|
42
45
|
mockValidator = {
|
|
43
46
|
setConfig: jest.fn(),
|
|
@@ -46,11 +49,6 @@ describe('spec command', () => {
|
|
|
46
49
|
(MockSpecValidator.getInstance as jest.Mock).mockReturnValue(mockValidator);
|
|
47
50
|
});
|
|
48
51
|
|
|
49
|
-
afterEach(() => {
|
|
50
|
-
consoleSpy.mockRestore();
|
|
51
|
-
process.exitCode = 0;
|
|
52
|
-
});
|
|
53
|
-
|
|
54
52
|
describe('specValidate', () => {
|
|
55
53
|
describe('单文件验证', () => {
|
|
56
54
|
it('应该验证单个文件', async () => {
|
|
@@ -63,8 +61,8 @@ describe('spec command', () => {
|
|
|
63
61
|
};
|
|
64
62
|
mockValidator.validateFile.mockResolvedValue(mockResult);
|
|
65
63
|
|
|
66
|
-
await specValidate({ file: 'test.yml' });
|
|
67
|
-
expect(
|
|
64
|
+
await specValidate({ file: 'test.yml' }, io);
|
|
65
|
+
expect(io.outText()).toContain('验证通过');
|
|
68
66
|
});
|
|
69
67
|
|
|
70
68
|
it('应该显示验证错误', async () => {
|
|
@@ -77,9 +75,9 @@ describe('spec command', () => {
|
|
|
77
75
|
};
|
|
78
76
|
mockValidator.validateFile.mockResolvedValue(mockResult);
|
|
79
77
|
|
|
80
|
-
await specValidate({ file: 'test.yml' });
|
|
81
|
-
expect(
|
|
82
|
-
expect(
|
|
78
|
+
await specValidate({ file: 'test.yml' }, io);
|
|
79
|
+
expect(io.outText()).toContain('验证失败');
|
|
80
|
+
expect(io.outText()).toContain('错误');
|
|
83
81
|
});
|
|
84
82
|
|
|
85
83
|
it('应该显示警告', async () => {
|
|
@@ -92,8 +90,8 @@ describe('spec command', () => {
|
|
|
92
90
|
};
|
|
93
91
|
mockValidator.validateFile.mockResolvedValue(mockResult);
|
|
94
92
|
|
|
95
|
-
await specValidate({ file: 'test.yml' });
|
|
96
|
-
expect(
|
|
93
|
+
await specValidate({ file: 'test.yml' }, io);
|
|
94
|
+
expect(io.outText()).toContain('警告');
|
|
97
95
|
});
|
|
98
96
|
|
|
99
97
|
it('应该显示详细指标', async () => {
|
|
@@ -107,8 +105,8 @@ describe('spec command', () => {
|
|
|
107
105
|
};
|
|
108
106
|
mockValidator.validateFile.mockResolvedValue(mockResult);
|
|
109
107
|
|
|
110
|
-
await specValidate({ file: 'test.yml', verbose: true });
|
|
111
|
-
expect(
|
|
108
|
+
await specValidate({ file: 'test.yml', verbose: true }, io);
|
|
109
|
+
expect(io.outText()).toContain('指标');
|
|
112
110
|
});
|
|
113
111
|
});
|
|
114
112
|
|
|
@@ -123,8 +121,8 @@ describe('spec command', () => {
|
|
|
123
121
|
};
|
|
124
122
|
mockValidateAllSpecs.mockResolvedValue(mockResult);
|
|
125
123
|
|
|
126
|
-
await specValidate({});
|
|
127
|
-
expect(
|
|
124
|
+
await specValidate({}, io);
|
|
125
|
+
expect(io.outText()).toContain('所有 Spec 文件验证通过');
|
|
128
126
|
});
|
|
129
127
|
|
|
130
128
|
it('应该显示失败统计', async () => {
|
|
@@ -139,8 +137,8 @@ describe('spec command', () => {
|
|
|
139
137
|
};
|
|
140
138
|
mockValidateAllSpecs.mockResolvedValue(mockResult);
|
|
141
139
|
|
|
142
|
-
await specValidate({});
|
|
143
|
-
expect(
|
|
140
|
+
await specValidate({}, io);
|
|
141
|
+
expect(io.outText()).toContain('失败: 2');
|
|
144
142
|
});
|
|
145
143
|
|
|
146
144
|
it('应该处理无 Spec 文件情况', async () => {
|
|
@@ -153,11 +151,25 @@ describe('spec command', () => {
|
|
|
153
151
|
};
|
|
154
152
|
mockValidateAllSpecs.mockResolvedValue(mockResult);
|
|
155
153
|
|
|
156
|
-
await specValidate({});
|
|
157
|
-
expect(
|
|
154
|
+
await specValidate({}, io);
|
|
155
|
+
expect(io.outText()).toContain('没有找到 Spec 文件');
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('批量验证有失败:fail + 失败数原因', async () => {
|
|
159
|
+
const mockResult: BatchSpecValidationResult = {
|
|
160
|
+
total: 2,
|
|
161
|
+
passed: 1,
|
|
162
|
+
failed: 1,
|
|
163
|
+
warnings: 0,
|
|
164
|
+
results: [],
|
|
165
|
+
};
|
|
166
|
+
mockValidateAllSpecs.mockResolvedValue(mockResult);
|
|
167
|
+
|
|
168
|
+
const result = await specValidate({}, io);
|
|
169
|
+
expect(result).toEqual({ kind: 'fail', reason: '1 个 Spec 文件验证失败' });
|
|
158
170
|
});
|
|
159
171
|
|
|
160
|
-
it('
|
|
172
|
+
it('--staged 有失败:ok(历史退出码面 0,冻结不变)', async () => {
|
|
161
173
|
const mockResult: BatchSpecValidationResult = {
|
|
162
174
|
total: 2,
|
|
163
175
|
passed: 1,
|
|
@@ -167,8 +179,8 @@ describe('spec command', () => {
|
|
|
167
179
|
};
|
|
168
180
|
mockValidateAllSpecs.mockResolvedValue(mockResult);
|
|
169
181
|
|
|
170
|
-
await specValidate({});
|
|
171
|
-
expect(
|
|
182
|
+
const result = await specValidate({ staged: true }, io);
|
|
183
|
+
expect(result).toEqual({ kind: 'ok' });
|
|
172
184
|
});
|
|
173
185
|
});
|
|
174
186
|
|
|
@@ -178,7 +190,7 @@ describe('spec command', () => {
|
|
|
178
190
|
total: 0, passed: 0, failed: 0, warnings: 0, results: [],
|
|
179
191
|
});
|
|
180
192
|
|
|
181
|
-
await specValidate({ schema: 'custom-schema.ts' });
|
|
193
|
+
await specValidate({ schema: 'custom-schema.ts' }, io);
|
|
182
194
|
expect(mockValidator.setConfig).toHaveBeenCalled();
|
|
183
195
|
});
|
|
184
196
|
});
|
|
@@ -186,8 +198,8 @@ describe('spec command', () => {
|
|
|
186
198
|
|
|
187
199
|
describe('listSpecTypes', () => {
|
|
188
200
|
it('应该列出支持的 Spec 类型', () => {
|
|
189
|
-
listSpecTypes();
|
|
190
|
-
expect(
|
|
201
|
+
listSpecTypes({}, io);
|
|
202
|
+
expect(io.outText()).toContain('支持的 Spec 类型');
|
|
191
203
|
});
|
|
192
204
|
});
|
|
193
205
|
});
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { status } from '../status';
|
|
6
|
+
import { captureIO, type CapturingIO } from '../../command-contract';
|
|
6
7
|
import * as fs from 'fs';
|
|
7
8
|
import { TraceAnalyzer } from '../../../monitoring/trace-analyzer';
|
|
8
9
|
|
|
@@ -42,22 +43,21 @@ jest.mock('chalk', () => ({
|
|
|
42
43
|
const mockFs = fs as jest.Mocked<typeof fs>;
|
|
43
44
|
const MockTraceAnalyzer = TraceAnalyzer as jest.MockedClass<typeof TraceAnalyzer>;
|
|
44
45
|
|
|
46
|
+
let io: CapturingIO;
|
|
47
|
+
beforeEach(() => {
|
|
48
|
+
io = captureIO();
|
|
49
|
+
});
|
|
50
|
+
|
|
45
51
|
describe('status command - 补充覆盖', () => {
|
|
46
|
-
let consoleSpy: jest.SpyInstance;
|
|
47
52
|
|
|
48
53
|
beforeEach(() => {
|
|
49
54
|
jest.clearAllMocks();
|
|
50
|
-
consoleSpy = jest.spyOn(console, 'log').mockImplementation();
|
|
51
55
|
mockFs.existsSync.mockReturnValue(true);
|
|
52
56
|
mockFs.readFileSync.mockReturnValue('');
|
|
53
57
|
mockFs.writeFileSync.mockImplementation();
|
|
54
58
|
mockFs.mkdirSync.mockImplementation();
|
|
55
59
|
});
|
|
56
60
|
|
|
57
|
-
afterEach(() => {
|
|
58
|
-
consoleSpy.mockRestore();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
61
|
describe('异常检测完整流程', () => {
|
|
62
62
|
it('有异常时应该显示详细信息和下一步建议', async () => {
|
|
63
63
|
const mockTraces = [
|
|
@@ -87,9 +87,9 @@ describe('status command - 补充覆盖', () => {
|
|
|
87
87
|
};
|
|
88
88
|
(MockTraceAnalyzer as any).mockImplementation(() => mockAnalyze);
|
|
89
89
|
|
|
90
|
-
await status({ anomalies: true });
|
|
90
|
+
await status({ anomalies: true }, io);
|
|
91
91
|
|
|
92
|
-
const output =
|
|
92
|
+
const output = io.outText();
|
|
93
93
|
expect(output).toContain('异常');
|
|
94
94
|
expect(mockAnalyze.detectAnomalies).toHaveBeenCalled();
|
|
95
95
|
});
|
|
@@ -103,9 +103,9 @@ describe('status command - 补充覆盖', () => {
|
|
|
103
103
|
};
|
|
104
104
|
(MockTraceAnalyzer as any).mockImplementation(() => mockAnalyze);
|
|
105
105
|
|
|
106
|
-
await status({ anomalies: true });
|
|
106
|
+
await status({ anomalies: true }, io);
|
|
107
107
|
|
|
108
|
-
const output =
|
|
108
|
+
const output = io.outText();
|
|
109
109
|
expect(output).toContain('未发现异常');
|
|
110
110
|
});
|
|
111
111
|
});
|
|
@@ -128,9 +128,9 @@ describe('status command - 补充覆盖', () => {
|
|
|
128
128
|
};
|
|
129
129
|
(MockTraceAnalyzer as any).mockImplementation(() => mockAnalyze);
|
|
130
130
|
|
|
131
|
-
await status({});
|
|
131
|
+
await status({}, io);
|
|
132
132
|
|
|
133
|
-
const output =
|
|
133
|
+
const output = io.outText();
|
|
134
134
|
expect(output).toContain('约束统计');
|
|
135
135
|
});
|
|
136
136
|
|
|
@@ -149,9 +149,9 @@ describe('status command - 补充覆盖', () => {
|
|
|
149
149
|
};
|
|
150
150
|
(MockTraceAnalyzer as any).mockImplementation(() => mockAnalyze);
|
|
151
151
|
|
|
152
|
-
await status({});
|
|
152
|
+
await status({}, io);
|
|
153
153
|
|
|
154
|
-
expect(
|
|
154
|
+
expect(io.outText()).not.toBe('');
|
|
155
155
|
});
|
|
156
156
|
});
|
|
157
157
|
|
|
@@ -173,9 +173,9 @@ describe('status command - 补充覆盖', () => {
|
|
|
173
173
|
};
|
|
174
174
|
(MockTraceAnalyzer as any).mockImplementation(() => mockAnalyze);
|
|
175
175
|
|
|
176
|
-
await status({ detail: true });
|
|
176
|
+
await status({ detail: true }, io);
|
|
177
177
|
|
|
178
|
-
const output =
|
|
178
|
+
const output = io.outText();
|
|
179
179
|
expect(output).toContain('约束统计');
|
|
180
180
|
});
|
|
181
181
|
});
|
|
@@ -190,10 +190,10 @@ describe('status command - 补充覆盖', () => {
|
|
|
190
190
|
};
|
|
191
191
|
(MockTraceAnalyzer as any).mockImplementation(() => mockAnalyze);
|
|
192
192
|
|
|
193
|
-
await status({});
|
|
193
|
+
await status({}, io);
|
|
194
194
|
|
|
195
195
|
// 应该成功处理,不会抛出异常
|
|
196
|
-
expect(
|
|
196
|
+
expect(io.outText()).not.toBe('');
|
|
197
197
|
});
|
|
198
198
|
});
|
|
199
199
|
});
|