@dommaker/harness 1.3.0 → 1.5.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 +20 -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 +104 -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 +27 -219
- 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 +31 -25
- 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 +17 -30
- package/dist/cli/commands/knowledge.d.ts.map +1 -1
- package/dist/cli/commands/knowledge.js +183 -273
- 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 +69 -59
- 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 +5 -2
- 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 +9 -3
- package/dist/cli/commands/update-user-model.d.ts.map +1 -1
- package/dist/cli/commands/update-user-model.js +56 -61
- 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/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 +68 -117
- package/dist/core/constraints/checker.js.map +1 -1
- package/dist/core/constraints/checkers/capability-sync.d.ts +20 -8
- package/dist/core/constraints/checkers/capability-sync.d.ts.map +1 -1
- package/dist/core/constraints/checkers/capability-sync.js +66 -77
- 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 +49 -66
- 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/index.d.ts +2 -2
- package/dist/core/constraints/checkers/index.d.ts.map +1 -1
- package/dist/core/constraints/checkers/index.js +2 -1
- package/dist/core/constraints/checkers/index.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 +43 -4
- package/dist/core/constraints/checkers/types.d.ts.map +1 -1
- package/dist/core/constraints/checkers/types.js +33 -0
- package/dist/core/constraints/checkers/types.js.map +1 -1
- 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 +6 -0
- package/dist/failure/recorder.d.ts.map +1 -1
- package/dist/failure/recorder.js +12 -8
- 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 +2 -1
- package/dist/gates/checker-gate.d.ts.map +1 -1
- package/dist/gates/checker-gate.js +11 -13
- 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 +1 -2
- package/dist/index.d.ts.map +1 -1
- 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 +17 -14
- 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 +2 -2
- package/dist/release/index.d.ts.map +1 -1
- package/dist/release/index.js +1 -5
- package/dist/release/index.js.map +1 -1
- 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 +8 -18
- package/dist/types/constraint.d.ts.map +1 -1
- package/dist/types/constraint.js +6 -1
- package/dist/types/constraint.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/types/trace.d.ts +9 -0
- package/dist/types/trace.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 +8 -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__/layering.test.ts +152 -0
- package/src/__tests__/passes-gate-extra.test.ts +0 -145
- package/src/__tests__/passes-gate.test.ts +130 -101
- 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 +23 -8
- 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 +107 -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 +448 -378
- 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 +69 -43
- 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 +231 -0
- package/src/cli/commands/__tests__/registry.test.ts +75 -35
- package/src/cli/commands/__tests__/release.test.ts +209 -80
- 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 +77 -78
- package/src/cli/commands/__tests__/sync-docs.test.ts +72 -74
- package/src/cli/commands/__tests__/update-user-model.test.ts +97 -34
- 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 +127 -66
- 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 +34 -227
- package/src/cli/commands/failure.ts +33 -26
- package/src/cli/commands/init.ts +166 -220
- package/src/cli/commands/knowledge.ts +192 -289
- 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 +70 -59
- 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 +5 -2
- 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 +64 -61
- 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/context/session-manager.ts +19 -33
- package/src/core/CONTEXT.md +10 -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 +82 -133
- package/src/core/constraints/checkers/__tests__/capability-sync.test.ts +273 -0
- package/src/core/constraints/checkers/__tests__/check-outcome.test.ts +176 -0
- package/src/core/constraints/checkers/__tests__/context-doc-sync.test.ts +77 -0
- package/src/core/constraints/checkers/__tests__/docs-freshness.test.ts +126 -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 +153 -0
- package/src/core/constraints/checkers/capability-sync.ts +75 -96
- package/src/core/constraints/checkers/context-doc-sync.ts +15 -25
- package/src/core/constraints/checkers/docs-freshness.ts +54 -70
- package/src/core/constraints/checkers/governance-presence.ts +7 -25
- package/src/core/constraints/checkers/index.ts +9 -2
- package/src/core/constraints/checkers/no-test-simplification.ts +4 -3
- package/src/core/constraints/checkers/types.ts +60 -4
- 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 +12 -10
- package/src/gates/CONTEXT.md +7 -4
- 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__/checker-gate.test.ts +24 -0
- 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 +12 -15
- 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 +0 -4
- 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 +53 -0
- 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 +19 -14
- 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 +1 -0
- package/src/release/__tests__/barrel.test.ts +60 -0
- package/src/release/index.ts +2 -13
- 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 +16 -27
- 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/types/trace.ts +10 -0
- 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
|
@@ -13,6 +13,7 @@ import * as path from 'path';
|
|
|
13
13
|
import type { Constraint } from '../../types/constraint';
|
|
14
14
|
import type { ExecutionTrace } from '../../types/trace';
|
|
15
15
|
import { DEFAULT_TRACE_FILE } from '../../types/trace';
|
|
16
|
+
import { readJsonl } from '../../utils/jsonl';
|
|
16
17
|
import { getEffectiveConstraints, lintEffectiveConfig } from '../effective-constraints';
|
|
17
18
|
import type { EffectiveConfigLint } from '../effective-constraints';
|
|
18
19
|
|
|
@@ -67,6 +68,14 @@ export interface RetireCandidate {
|
|
|
67
68
|
reason: string;
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
/** 候选种类的呈现名(constraints report / retire 共用) */
|
|
72
|
+
export const CANDIDATE_KIND_LABEL: Record<RetireCandidateKind, string> = {
|
|
73
|
+
zero_trigger: '零触发',
|
|
74
|
+
unevaluable: '不可评估',
|
|
75
|
+
high_noise: '高噪',
|
|
76
|
+
zero_intercept: '零拦截',
|
|
77
|
+
};
|
|
78
|
+
|
|
70
79
|
/**
|
|
71
80
|
* 候选诊断阈值(CLI 可覆盖)
|
|
72
81
|
*/
|
|
@@ -99,27 +108,36 @@ export interface ConstraintsUsageReport {
|
|
|
99
108
|
lint: EffectiveConfigLint;
|
|
100
109
|
/** trace 文件是否存在 */
|
|
101
110
|
traceFileExists: boolean;
|
|
111
|
+
/**
|
|
112
|
+
* trace 文件被跳过的坏行数(harness#100,与 `traceFileExists` 同一降级维度)
|
|
113
|
+
*
|
|
114
|
+
* 恒有值,0 = 无损坏。文件级口径:坏行没有 timestamp,归不进任何统计窗口。
|
|
115
|
+
*/
|
|
116
|
+
skippedLines: number;
|
|
102
117
|
}
|
|
103
118
|
|
|
104
119
|
/**
|
|
105
|
-
* 读取项目 traces.log
|
|
120
|
+
* 读取项目 traces.log 并带出坏行计数(只读,harness#100 报告入口)
|
|
121
|
+
*
|
|
122
|
+
* 坏行策略:skip(原语义不变——report 只读,不因单行损坏失败);
|
|
123
|
+
* 计数去向:透传——`skippedLines` 随本方法返回,进 `ConstraintsUsageReport.skippedLines`,
|
|
124
|
+
* 消费面为 `constraints report` 的文本行 / `--json` 字段 / `--export` 摘要。
|
|
125
|
+
*/
|
|
126
|
+
export function readProjectTracesReport(projectRoot: string): { traces: ExecutionTrace[]; skippedLines: number } {
|
|
127
|
+
const { records, skippedLines } = readJsonl<ExecutionTrace>(
|
|
128
|
+
path.join(projectRoot, DEFAULT_TRACE_FILE),
|
|
129
|
+
'skip'
|
|
130
|
+
);
|
|
131
|
+
return { traces: records, skippedLines };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 读取项目 traces.log(只读)
|
|
136
|
+
*
|
|
137
|
+
* 兼容签名:只返回记录数组、丢坏行计数,需要计数的消费方走 `readProjectTracesReport()`。
|
|
106
138
|
*/
|
|
107
139
|
export function readProjectTraces(projectRoot: string): ExecutionTrace[] {
|
|
108
|
-
|
|
109
|
-
if (!fs.existsSync(tracePath)) return [];
|
|
110
|
-
|
|
111
|
-
const content = fs.readFileSync(tracePath, 'utf-8');
|
|
112
|
-
const traces: ExecutionTrace[] = [];
|
|
113
|
-
for (const line of content.split('\n')) {
|
|
114
|
-
const trimmed = line.trim();
|
|
115
|
-
if (!trimmed) continue;
|
|
116
|
-
try {
|
|
117
|
-
traces.push(JSON.parse(trimmed) as ExecutionTrace);
|
|
118
|
-
} catch {
|
|
119
|
-
// 坏行跳过(report 只读,不因单行损坏失败)
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return traces;
|
|
140
|
+
return readProjectTracesReport(projectRoot).traces;
|
|
123
141
|
}
|
|
124
142
|
|
|
125
143
|
/**
|
|
@@ -234,7 +252,7 @@ export function buildConstraintsUsageReport(
|
|
|
234
252
|
const activePromptIds = effective.filter(c => c.kind === 'prompt').map(c => c.id);
|
|
235
253
|
|
|
236
254
|
const tracePath = path.join(projectRoot, DEFAULT_TRACE_FILE);
|
|
237
|
-
const traces =
|
|
255
|
+
const { traces, skippedLines } = readProjectTracesReport(projectRoot);
|
|
238
256
|
const usage = collectUsageByConstraint(traces);
|
|
239
257
|
|
|
240
258
|
const stats = checkConstraints.map(c => toStats(c.id, c.level, usage.get(c.id)));
|
|
@@ -247,5 +265,6 @@ export function buildConstraintsUsageReport(
|
|
|
247
265
|
activePromptIds,
|
|
248
266
|
lint,
|
|
249
267
|
traceFileExists: fs.existsSync(tracePath),
|
|
268
|
+
skippedLines,
|
|
250
269
|
};
|
|
251
270
|
}
|
package/src/core/index.ts
CHANGED
|
@@ -84,13 +84,15 @@ export type {
|
|
|
84
84
|
SpecType,
|
|
85
85
|
} from '../types/spec';
|
|
86
86
|
|
|
87
|
-
//
|
|
87
|
+
// 项目配置加载器(governance 段读取一律经访问器,禁止消费方手写钻取)
|
|
88
88
|
export {
|
|
89
89
|
ProjectConfigLoader,
|
|
90
90
|
loadRawProjectConfig,
|
|
91
|
+
getGovernanceConfig,
|
|
92
|
+
resolveContextFiles,
|
|
91
93
|
getCapabilitiesMode,
|
|
92
94
|
} from './project-config-loader';
|
|
93
|
-
export type { CapabilitiesMode } from './project-config-loader';
|
|
95
|
+
export type { CapabilitiesMode, ContextFilesResolution } from './project-config-loader';
|
|
94
96
|
|
|
95
97
|
// 生效约束集(ADR-0001:唯一生效集来源)
|
|
96
98
|
export {
|
|
@@ -14,6 +14,7 @@ import type {
|
|
|
14
14
|
CustomConstraintDefinition,
|
|
15
15
|
MergedConstraintsConfig,
|
|
16
16
|
CapabilitiesConfig,
|
|
17
|
+
GovernanceConfig,
|
|
17
18
|
} from '../types/project-config';
|
|
18
19
|
import { IRON_LAWS, GUIDELINES, PROMPTS } from './constraints/definitions';
|
|
19
20
|
import { PRESETS_BY_NAME, STANDARD_PRESET } from '../presets';
|
|
@@ -78,20 +79,59 @@ export function loadRawProjectConfig(projectPath: string): Record<string, unknow
|
|
|
78
79
|
export type CapabilitiesMode = NonNullable<CapabilitiesConfig['mode']>;
|
|
79
80
|
|
|
80
81
|
/**
|
|
81
|
-
* 读取 governance
|
|
82
|
+
* 读取 governance 段(全仓唯一手写钻取点,工单 84)
|
|
82
83
|
*
|
|
83
|
-
*
|
|
84
|
+
* 基于 loadRawProjectConfig 的进程级 memoize,不引入第二次 yaml 解析。
|
|
85
|
+
* 配置缺失 / 解析失败 / 形状不符时返回 undefined,由调用方按未配置处理。
|
|
84
86
|
*/
|
|
85
|
-
export function
|
|
87
|
+
export function getGovernanceConfig(projectPath: string): GovernanceConfig | undefined {
|
|
86
88
|
try {
|
|
87
89
|
const raw = loadRawProjectConfig(projectPath);
|
|
88
|
-
const governance = raw?.governance
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (mode === 'file' || mode === 'module' || mode === 'listing') return mode;
|
|
90
|
+
const governance = raw?.governance;
|
|
91
|
+
if (governance === null || typeof governance !== 'object') return undefined;
|
|
92
|
+
return governance as GovernanceConfig;
|
|
92
93
|
} catch {
|
|
93
|
-
|
|
94
|
+
return undefined;
|
|
94
95
|
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* governance.context_files 三态分辨率(工单 84 triage 裁决口径)
|
|
100
|
+
*
|
|
101
|
+
* - unconfigured:段缺失 / enabled 为假 / 解析失败——约定未采用
|
|
102
|
+
* - enabled-empty:enabled 但 required_dirs 缺失、非数组、含非字符串项或空——
|
|
103
|
+
* 约定已立但无可用目标
|
|
104
|
+
* - enabled:enabled 且 required_dirs 为非空字符串数组——约定有效
|
|
105
|
+
*/
|
|
106
|
+
export type ContextFilesResolution =
|
|
107
|
+
| { state: 'unconfigured' }
|
|
108
|
+
| { state: 'enabled-empty' }
|
|
109
|
+
| { state: 'enabled'; dirs: string[] };
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* 分辨 governance.context_files 三态(语义见 ContextFilesResolution)
|
|
113
|
+
*
|
|
114
|
+
* 消费方约定:约束 checker 对前两态一律 skip(与 ADR-0001 存在性探测同构);
|
|
115
|
+
* init / 扫描类工具流的自动探测回落保留在调用方,不进本访问器。
|
|
116
|
+
* 元素类型在此收口:脏配置(如 required_dirs: [1])不得流入调用方 path.join。
|
|
117
|
+
*/
|
|
118
|
+
export function resolveContextFiles(projectPath: string): ContextFilesResolution {
|
|
119
|
+
const contextFiles = getGovernanceConfig(projectPath)?.context_files;
|
|
120
|
+
if (!contextFiles?.enabled) return { state: 'unconfigured' };
|
|
121
|
+
const dirs = contextFiles.required_dirs;
|
|
122
|
+
if (!Array.isArray(dirs) || dirs.length === 0) return { state: 'enabled-empty' };
|
|
123
|
+
if (!dirs.every(dir => typeof dir === 'string')) return { state: 'enabled-empty' };
|
|
124
|
+
return { state: 'enabled', dirs };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* 读取 governance.capabilities.mode(缺省 'file',向后兼容)
|
|
129
|
+
*
|
|
130
|
+
* 配置缺失/解析失败/取值非法时一律回落 'file'。
|
|
131
|
+
*/
|
|
132
|
+
export function getCapabilitiesMode(projectPath: string): CapabilitiesMode {
|
|
133
|
+
const mode = getGovernanceConfig(projectPath)?.capabilities?.mode;
|
|
134
|
+
if (mode === 'file' || mode === 'module' || mode === 'listing') return mode;
|
|
95
135
|
return 'file';
|
|
96
136
|
}
|
|
97
137
|
|
|
@@ -228,7 +268,7 @@ export class ProjectConfigLoader {
|
|
|
228
268
|
|
|
229
269
|
// 2. 添加自定义约束(config.yml 禁用的 id 不追加:step 1 已将其
|
|
230
270
|
// 收集进 disabled,custom 在 step 1 时尚未入桶,须在此兜底跳过;
|
|
231
|
-
// 条目带 retired
|
|
271
|
+
// 条目带 retired 元数据的同样不追加——studio#82 D6 退役落点在条目自身)
|
|
232
272
|
for (const [id, customDef] of Object.entries(this.customConstraints)) {
|
|
233
273
|
if (result.disabled.includes(id) || customDef.retired) {
|
|
234
274
|
continue;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tests for passes-gate.ts
|
|
3
3
|
*
|
|
4
|
-
* Priority: test pure logic methods (check
|
|
4
|
+
* Priority: test pure logic methods (check)
|
|
5
5
|
* Skip methods that do real file I/O / exec (setPasses, runTests, runTest, detectTestCommand, etc.)
|
|
6
|
+
* 测试产物解析判定不在此面:见 test-output.test.ts(ADR-0012)
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
import { PassesGate, createPassesGate } from '../passes-gate';
|
|
@@ -67,65 +68,10 @@ describe('PassesGate', () => {
|
|
|
67
68
|
});
|
|
68
69
|
});
|
|
69
70
|
|
|
70
|
-
describe('extension management', () => {
|
|
71
|
-
it('registerExtension adds an extension', () => {
|
|
72
|
-
const gate = createPassesGate();
|
|
73
|
-
const ext = { name: 'e2e', run: async () => ({ passed: true, command: 'e2e' }) };
|
|
74
|
-
gate.registerExtension('e2e', ext);
|
|
75
|
-
expect(gate.getExtensionNames()).toContain('e2e');
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('unregisterExtension removes an extension', () => {
|
|
79
|
-
const gate = createPassesGate();
|
|
80
|
-
const ext = { name: 'e2e', run: async () => ({ passed: true, command: 'e2e' }) };
|
|
81
|
-
gate.registerExtension('e2e', ext);
|
|
82
|
-
const removed = gate.unregisterExtension('e2e');
|
|
83
|
-
expect(removed).toBe(true);
|
|
84
|
-
expect(gate.getExtensionNames()).not.toContain('e2e');
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('unregisterExtension returns false for non-existent extension', () => {
|
|
88
|
-
const gate = createPassesGate();
|
|
89
|
-
const removed = gate.unregisterExtension('nonexistent');
|
|
90
|
-
expect(removed).toBe(false);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it('getExtensionNames returns empty array when no extensions', () => {
|
|
94
|
-
const gate = createPassesGate();
|
|
95
|
-
expect(gate.getExtensionNames()).toEqual([]);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it('getExtensionNames returns multiple extension names', () => {
|
|
99
|
-
const gate = createPassesGate();
|
|
100
|
-
gate.registerExtension('a', { name: 'a', run: async () => ({ passed: true, command: 'a' }) });
|
|
101
|
-
gate.registerExtension('b', { name: 'b', run: async () => ({ passed: true, command: 'b' }) });
|
|
102
|
-
const names = gate.getExtensionNames();
|
|
103
|
-
expect(names).toContain('a');
|
|
104
|
-
expect(names).toContain('b');
|
|
105
|
-
expect(names).toHaveLength(2);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
|
|
109
71
|
describe('getTestResult', () => {
|
|
110
72
|
it('returns undefined for unknown task', () => {
|
|
111
73
|
const gate = createPassesGate();
|
|
112
74
|
expect(gate.getTestResult('unknown')).toBeUndefined();
|
|
113
75
|
});
|
|
114
76
|
});
|
|
115
|
-
|
|
116
|
-
describe('extractCoverage (via extractCoverage private method behavior check)', () => {
|
|
117
|
-
// extractCoverage is private but we can infer behavior through public API
|
|
118
|
-
// runTest uses it internally — but that method is not easily testable without mocking exec
|
|
119
|
-
it('PassesGate instance is properly constructed', () => {
|
|
120
|
-
const gate = createPassesGate({ testCommand: 'npm test' });
|
|
121
|
-
expect(gate).toBeInstanceOf(PassesGate);
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
describe('extractFailures (via extractFailures private method behavior check)', () => {
|
|
126
|
-
it('PassesGate handles config properly', () => {
|
|
127
|
-
const gate = createPassesGate({ allowPartialPass: true, maxRetries: 0, retryDelay: 0 });
|
|
128
|
-
expect(gate).toBeInstanceOf(PassesGate);
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
77
|
});
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* test-output 表驱动旁测(架构评审候选1 / #80 → ADR-0012;判定口径 #93 → ADR-0014;
|
|
3
|
+
* 覆盖率取数路删除 #94)
|
|
4
|
+
*
|
|
5
|
+
* runner 输出解读口的唯一测试面:真实 stdout 样本进、判定值出。
|
|
6
|
+
* 迁移前 extractCoverage / extractFailures / parseTestOutput 是 PassesGate 与
|
|
7
|
+
* SpecAcceptanceGate 的 private 方法,分支覆盖率 0%——passes-gate.test.ts 里只剩
|
|
8
|
+
* toBeInstanceOf 占位断言,acceptance.test.ts 要写 6 份近重复 exec mock 才碰得到分支。
|
|
9
|
+
*
|
|
10
|
+
* extractFailures 的期望值钉的是**迁移前的既有行为**(ADR-0012 硬门槛:行为零变更),
|
|
11
|
+
* 标 ⚠ 的行是已知的粗糙解析,原样钉住不代表认可。
|
|
12
|
+
*
|
|
13
|
+
* judgeTestRun 是 #93 裁决后的**判定唯一入口**(退出码为主 + 文本交叉否决),取代
|
|
14
|
+
* 原 parseTestOutput(纯文本判定,可被测试名里的 FAIL 反转);两门禁消费同一函数的
|
|
15
|
+
* 一致性用例在 gates/__tests__/test-verdict-consistency.test.ts。
|
|
16
|
+
*
|
|
17
|
+
* extractCoverage 曾在此有 8 条表驱动用例,#94 裁决 B(harness 核心判定不管覆盖率)
|
|
18
|
+
* 连同函数一起删除,只剩下面那条导出面守卫钉住「不再导出」。
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { describe, it, expect } from '@jest/globals';
|
|
22
|
+
import { extractFailures, judgeTestRun } from '../test-output';
|
|
23
|
+
|
|
24
|
+
// ========================================
|
|
25
|
+
// 真实输出样本(各 runner 家族的原始 stdout)
|
|
26
|
+
// ========================================
|
|
27
|
+
|
|
28
|
+
/** jest --coverage:文本表 + 汇总行 */
|
|
29
|
+
const JEST_COV = `PASS src/app.test.ts
|
|
30
|
+
----------------|---------|----------|---------|---------|-------------------
|
|
31
|
+
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
|
|
32
|
+
----------------|---------|----------|---------|---------|-------------------
|
|
33
|
+
All files | 80.50 | 70.21 | 83.33 | 79.59 |
|
|
34
|
+
app.ts | 80.50 | 70.21 | 83.33 | 79.59 | 12-13
|
|
35
|
+
----------------|---------|----------|---------|---------|-------------------
|
|
36
|
+
Test Suites: 1 passed, 1 total
|
|
37
|
+
Tests: 5 passed, 5 total
|
|
38
|
+
`;
|
|
39
|
+
|
|
40
|
+
const MOCHA_PLAIN = ` 2 passing (11ms)
|
|
41
|
+
1 failing
|
|
42
|
+
`;
|
|
43
|
+
|
|
44
|
+
/** jest verbose 失败清单 */
|
|
45
|
+
const JEST_FAILURES = `FAIL src/app.test.ts
|
|
46
|
+
App
|
|
47
|
+
✕ renders title (23 ms)
|
|
48
|
+
✓ renders subtitle (5 ms)
|
|
49
|
+
✕ handles click (12 ms)
|
|
50
|
+
|
|
51
|
+
Test Suites: 1 failed, 1 total
|
|
52
|
+
Tests: 2 failed, 1 passed, 3 total
|
|
53
|
+
`;
|
|
54
|
+
|
|
55
|
+
/** jest 失败详情带堆栈行 */
|
|
56
|
+
const JEST_FAILURES_WITH_STACK = `FAIL src/app.test.ts
|
|
57
|
+
App
|
|
58
|
+
✕ renders title (23 ms)
|
|
59
|
+
|
|
60
|
+
● App › renders title
|
|
61
|
+
|
|
62
|
+
expect(received).toBe(expected)
|
|
63
|
+
|
|
64
|
+
at Object.<anonymous> (src/app.test.ts:12:15)
|
|
65
|
+
|
|
66
|
+
Test Suites: 1 failed, 1 total
|
|
67
|
+
`;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* PR #117 实发样本(2026-09-08):全绿 jest 输出混 console 噪音——init/sync-docs 测试
|
|
71
|
+
* 直接打印的 ✅ 日志行(行尾 (v1.0.0))与失败路径测试的 stack trace(行尾 :213:23))。
|
|
72
|
+
* 行尾「数字+)」+ 下一行含 ":" 是旧 mocha 正则(\s+ 跨行)的诱饵:它在同形状的真实输出
|
|
73
|
+
* 上捕出 24 条假失败,governance 门禁因此对 exit 0 的绿色 npm test 误判失败。
|
|
74
|
+
*/
|
|
75
|
+
const JEST_GREEN_WITH_CONSOLE_NOISE = `PASS src/cli/commands/__tests__/init-injection.test.ts
|
|
76
|
+
✅ 已创建 AGENTS.md 并写入治理契约 PRESERVE:governance 段 (v1.0.0)
|
|
77
|
+
✅ 已创建 AGENTS.md 并写入治理契约 PRESERVE:governance 段 (v1.0.0)
|
|
78
|
+
✅ 已更新 CLAUDE.md 治理约束 (v1.0.0)
|
|
79
|
+
PASS src/__tests__/skip-semantics.test.ts
|
|
80
|
+
at Object.evaluate (src/core/constraints/checkers/docs-freshness.ts:100:15)
|
|
81
|
+
at ConstraintChecker.checkPrecondition (src/core/constraints/checker.ts:213:23)
|
|
82
|
+
at Object.<anonymous> (src/__tests__/skip-semantics.test.ts:152:36)
|
|
83
|
+
PASS src/failure/__tests__/recorder.test.ts
|
|
84
|
+
|
|
85
|
+
Test Suites: 156 passed, 156 total
|
|
86
|
+
Tests: 7 skipped, 2182 passed, 2189 total
|
|
87
|
+
`;
|
|
88
|
+
|
|
89
|
+
/** mocha 单行形状:编号 + 套件 + 标题同行,末尾带冒号(正则认的形状) */
|
|
90
|
+
const MOCHA_ONE_LINE = ` 1) Account "should open":
|
|
91
|
+
AssertionError: expected false to be true
|
|
92
|
+
|
|
93
|
+
2) Account "should close":
|
|
94
|
+
Error: timeout of 2000ms exceeded
|
|
95
|
+
`;
|
|
96
|
+
|
|
97
|
+
/** mocha 10 spec reporter 实际形状:编号行与标题行分两行 */
|
|
98
|
+
const MOCHA_TWO_LINE = ` 1) Account
|
|
99
|
+
should open:
|
|
100
|
+
AssertionError: expected false to be true
|
|
101
|
+
|
|
102
|
+
2) Account
|
|
103
|
+
should close:
|
|
104
|
+
Error: timeout of 2000ms exceeded
|
|
105
|
+
`;
|
|
106
|
+
|
|
107
|
+
const MOCHA_TWO_LINE_WITH_STACK = ` 1) Account
|
|
108
|
+
should open:
|
|
109
|
+
AssertionError: expected false to be true
|
|
110
|
+
at Context.<anonymous> (test/account.test.js:14:16)
|
|
111
|
+
at processImmediate (node:internal/timers:476:21)
|
|
112
|
+
|
|
113
|
+
2) Account
|
|
114
|
+
should close:
|
|
115
|
+
Error: timeout of 2000ms exceeded
|
|
116
|
+
`;
|
|
117
|
+
|
|
118
|
+
const PYTEST_FAILURES = `FAILED tests/test_app.py::TestLogin::test_empty_password - AssertionError: 400 != 200
|
|
119
|
+
FAILED tests/test_app.py::test_logout - assert False
|
|
120
|
+
2 failed, 5 passed in 0.88s
|
|
121
|
+
`;
|
|
122
|
+
|
|
123
|
+
const GO_FAILURES = `=== RUN TestLogin
|
|
124
|
+
--- FAIL: TestLogin (0.00s)
|
|
125
|
+
app_test.go:24: expected 200, got 401
|
|
126
|
+
=== RUN TestLogout
|
|
127
|
+
--- FAIL: TestLogout (0.01s)
|
|
128
|
+
FAIL
|
|
129
|
+
exit status 1
|
|
130
|
+
FAIL example.com/app 0.014s
|
|
131
|
+
`;
|
|
132
|
+
|
|
133
|
+
const PW_PASS = `Running 3 tests using 1 worker
|
|
134
|
+
|
|
135
|
+
✓ 1 example.spec.ts:5:5 › should have title (1.2s)
|
|
136
|
+
✓ 2 example.spec.ts:8:5 › should navigate (0.6s)
|
|
137
|
+
✓ 3 example.spec.ts:12:5 › should submit (0.3s)
|
|
138
|
+
|
|
139
|
+
3 passed (2.1s)
|
|
140
|
+
`;
|
|
141
|
+
|
|
142
|
+
const PW_FAIL = `Running 3 tests using 1 worker
|
|
143
|
+
|
|
144
|
+
✓ 1 example.spec.ts:5:5 › should have title (1.2s)
|
|
145
|
+
✘ 2 example.spec.ts:10:5 › should fail (0.9s)
|
|
146
|
+
✓ 3 example.spec.ts:12:5 › should submit (0.3s)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
1) example.spec.ts:10:5 › should fail ─────────────────────────────
|
|
150
|
+
|
|
151
|
+
Error: expect(received).toBe(expected)
|
|
152
|
+
|
|
153
|
+
1 failed
|
|
154
|
+
example.spec.ts:10:5 › should fail
|
|
155
|
+
2 passed (3.1s)
|
|
156
|
+
`;
|
|
157
|
+
|
|
158
|
+
const JEST_SUITES_PASS = `Test Suites: 5 passed, 5 total
|
|
159
|
+
Tests: 42 passed, 42 total
|
|
160
|
+
`;
|
|
161
|
+
|
|
162
|
+
const JEST_SUITES_FAIL = `Test Suites: 2 failed, 3 passed, 5 total
|
|
163
|
+
`;
|
|
164
|
+
|
|
165
|
+
/** 零套件通过时 jest 的汇总形状(只有 failed/total,无 "passed" 字样 → 走 Jest 分支) */
|
|
166
|
+
const JEST_ALL_FAILED = `Test Suites: 2 failed, 2 total
|
|
167
|
+
Tests: 3 failed, 3 total
|
|
168
|
+
`;
|
|
169
|
+
|
|
170
|
+
/** jest 汇总行零失败,但输出里没有 "passed" 字样(截断/过滤后的形状) */
|
|
171
|
+
const JEST_SUITES_NO_PASSED_WORD = `Test Suites: 0 failed, 2 total
|
|
172
|
+
`;
|
|
173
|
+
|
|
174
|
+
const GENERIC_PASS = `PASS src/a.test.js
|
|
175
|
+
PASS src/b.test.js
|
|
176
|
+
`;
|
|
177
|
+
|
|
178
|
+
const GENERIC_MIXED = `PASS src/a.test.js
|
|
179
|
+
FAIL src/b.test.js
|
|
180
|
+
`;
|
|
181
|
+
|
|
182
|
+
/** 全绿输出,但通过的测试标题里带大写 FAIL 字样 */
|
|
183
|
+
const GENERIC_FAIL_IN_TEST_NAME = `PASS src/a.test.js
|
|
184
|
+
✓ does not FAIL here (3 ms)
|
|
185
|
+
`;
|
|
186
|
+
|
|
187
|
+
// ========================================
|
|
188
|
+
// 模块导出面(harness#94 裁决 B:extractCoverage 已删除)
|
|
189
|
+
// ========================================
|
|
190
|
+
|
|
191
|
+
describe('test-output 导出面', () => {
|
|
192
|
+
it('运行时只有 extractFailures 与 judgeTestRun,不含 extractCoverage', async () => {
|
|
193
|
+
const mod = await import('../test-output');
|
|
194
|
+
expect(Object.keys(mod).sort()).toEqual(['extractFailures', 'judgeTestRun']);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// ========================================
|
|
199
|
+
// extractFailures
|
|
200
|
+
// ========================================
|
|
201
|
+
|
|
202
|
+
type FailuresCase = { name: string; output: string; expected: string[] };
|
|
203
|
+
|
|
204
|
+
const FAILURES_CASES: FailuresCase[] = [
|
|
205
|
+
{ name: 'jest ✕ 行 → 两个用例名', output: JEST_FAILURES, expected: ['renders title', 'handles click'] },
|
|
206
|
+
{
|
|
207
|
+
name: 'jest 带堆栈行 → 只有 ✕ 用例名(旧跨行 mocha 误捕 "Test Suites",PR #117 已修)',
|
|
208
|
+
output: JEST_FAILURES_WITH_STACK,
|
|
209
|
+
expected: ['renders title'],
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
name: 'mocha 单行形状 → 套件 + 标题',
|
|
213
|
+
output: MOCHA_ONE_LINE,
|
|
214
|
+
expected: ['Account "should open"', 'Account "should close"'],
|
|
215
|
+
},
|
|
216
|
+
{ name: '⚠ mocha 10 两行形状 → 识别不到任何失败', output: MOCHA_TWO_LINE, expected: [] },
|
|
217
|
+
{
|
|
218
|
+
name: 'mocha 两行 + 堆栈 → [](旧跨行误捕堆栈帧 "at processImmediate (node",PR #117 已修)',
|
|
219
|
+
output: MOCHA_TWO_LINE_WITH_STACK,
|
|
220
|
+
expected: [],
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: '全绿 jest 输出混 console 噪音(行尾数字+")" 跨行诱饵)→ [](PR #117 实发误否决)',
|
|
224
|
+
output: JEST_GREEN_WITH_CONSOLE_NOISE,
|
|
225
|
+
expected: [],
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: '⚠ pytest 节点 id 在首个 :: 前截断 → 同文件多条失败重复且丢测试名',
|
|
229
|
+
output: PYTEST_FAILURES,
|
|
230
|
+
expected: ['tests/test_app.py', 'tests/test_app.py'],
|
|
231
|
+
},
|
|
232
|
+
{ name: 'go test --- FAIL: → 函数名', output: GO_FAILURES, expected: ['TestLogin', 'TestLogout'] },
|
|
233
|
+
{ name: '无匹配:全绿 jest 输出 → []', output: JEST_COV, expected: [] },
|
|
234
|
+
{ name: '无匹配:空字符串 → []', output: '', expected: [] },
|
|
235
|
+
];
|
|
236
|
+
|
|
237
|
+
describe('extractFailures', () => {
|
|
238
|
+
for (const c of FAILURES_CASES) {
|
|
239
|
+
it(c.name, () => {
|
|
240
|
+
expect(extractFailures(c.output)).toEqual(c.expected);
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// ========================================
|
|
246
|
+
// judgeTestRun — 判定唯一入口(ADR-0014 / #93)
|
|
247
|
+
// ========================================
|
|
248
|
+
|
|
249
|
+
type JudgeCase = {
|
|
250
|
+
name: string;
|
|
251
|
+
exitCode: number;
|
|
252
|
+
output: string;
|
|
253
|
+
allowPartialPass?: boolean;
|
|
254
|
+
expected: boolean;
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const JUDGE_CASES: JudgeCase[] = [
|
|
258
|
+
// ── 退出码为主:文本不能把非零退出救成 pass ──
|
|
259
|
+
{ name: 'exit 1 + 全绿 jest 输出 → false(文本不赦免非零退出)', exitCode: 1, output: JEST_COV, expected: false },
|
|
260
|
+
{ name: 'exit 1 + 空输出 → false', exitCode: 1, output: '', expected: false },
|
|
261
|
+
{
|
|
262
|
+
name: 'exit 2 + allowPartialPass → false(部分通过不碰退出码这一维)',
|
|
263
|
+
exitCode: 2,
|
|
264
|
+
output: JEST_COV,
|
|
265
|
+
allowPartialPass: true,
|
|
266
|
+
expected: false,
|
|
267
|
+
},
|
|
268
|
+
// ── 后果1:exit 0 但输出印着失败 → 文本交叉否决 ──
|
|
269
|
+
{ name: 'exit 0 + jest ✕ 用例清单 → false', exitCode: 0, output: JEST_FAILURES, expected: false },
|
|
270
|
+
{ name: 'exit 0 + jest 带堆栈失败清单 → false', exitCode: 0, output: JEST_FAILURES_WITH_STACK, expected: false },
|
|
271
|
+
{
|
|
272
|
+
name: 'exit 0 + 只有 jest 汇总行(无 ✕ 行,非 verbose)→ false(统一用结构化汇总行)',
|
|
273
|
+
exitCode: 0,
|
|
274
|
+
output: JEST_ALL_FAILED,
|
|
275
|
+
expected: false,
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
name: 'exit 0 + jest 汇总行有 failed 也有 passed → false',
|
|
279
|
+
exitCode: 0,
|
|
280
|
+
output: JEST_SUITES_FAIL,
|
|
281
|
+
expected: false,
|
|
282
|
+
},
|
|
283
|
+
{ name: 'exit 0 + 套件级 FAIL 行 → false', exitCode: 0, output: GENERIC_MIXED, expected: false },
|
|
284
|
+
{ name: 'exit 0 + mocha 汇总行 1 failing → false', exitCode: 0, output: MOCHA_PLAIN, expected: false },
|
|
285
|
+
{ name: 'exit 0 + pytest FAILED 行 → false', exitCode: 0, output: PYTEST_FAILURES, expected: false },
|
|
286
|
+
{ name: 'exit 0 + go --- FAIL: 行 → false', exitCode: 0, output: GO_FAILURES, expected: false },
|
|
287
|
+
{ name: 'exit 0 + playwright 失败汇总 → false', exitCode: 0, output: PW_FAIL, expected: false },
|
|
288
|
+
// ── 后果2:裸 includes(FAIL) 兜底弃用后不再误伤 ──
|
|
289
|
+
{
|
|
290
|
+
name: 'exit 0 + 全绿但通过的用例名里带大写 FAIL → true(旧兜底子串反转已修)',
|
|
291
|
+
exitCode: 0,
|
|
292
|
+
output: GENERIC_FAIL_IN_TEST_NAME,
|
|
293
|
+
expected: true,
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
name: 'exit 0 + 路径含大写 FAIL 目录名 → true(子串兜底已弃用)',
|
|
297
|
+
exitCode: 0,
|
|
298
|
+
output: 'PASS src/fixtures/FAIL/app.test.js\nTests: 3 passed, 3 total\n',
|
|
299
|
+
expected: true,
|
|
300
|
+
},
|
|
301
|
+
// ── 全绿样本 ──
|
|
302
|
+
{ name: 'exit 0 + jest 全绿带覆盖率表 → true', exitCode: 0, output: JEST_COV, expected: true },
|
|
303
|
+
{ name: 'exit 0 + jest 全绿汇总行 → true', exitCode: 0, output: JEST_SUITES_PASS, expected: true },
|
|
304
|
+
{
|
|
305
|
+
name: 'exit 0 + jest 零失败但无 "passed" 字样 → true(旧判定要求该字样,误伤)',
|
|
306
|
+
exitCode: 0,
|
|
307
|
+
output: JEST_SUITES_NO_PASSED_WORD,
|
|
308
|
+
expected: true,
|
|
309
|
+
},
|
|
310
|
+
{ name: 'exit 0 + playwright 全过 → true', exitCode: 0, output: PW_PASS, expected: true },
|
|
311
|
+
{ name: 'exit 0 + 通用 PASS 行 → true', exitCode: 0, output: GENERIC_PASS, expected: true },
|
|
312
|
+
{
|
|
313
|
+
name: 'exit 0 + 全绿输出混 console 噪音 → true(PR #117 实发:extractFailures 跨行误捕曾否决绿色输出)',
|
|
314
|
+
exitCode: 0,
|
|
315
|
+
output: JEST_GREEN_WITH_CONSOLE_NOISE,
|
|
316
|
+
expected: true,
|
|
317
|
+
},
|
|
318
|
+
// ── allowPartialPass 的新位置:只作用于文本否决这一维 ──
|
|
319
|
+
{
|
|
320
|
+
name: 'exit 0 + jest ✕ 清单 + allowPartialPass → true(部分通过 = 放弃文本否决)',
|
|
321
|
+
exitCode: 0,
|
|
322
|
+
output: JEST_FAILURES,
|
|
323
|
+
allowPartialPass: true,
|
|
324
|
+
expected: true,
|
|
325
|
+
},
|
|
326
|
+
// ── 退出码权威的边界:文本否决只管「看出失败」,不管「没跑出测试」 ──
|
|
327
|
+
{
|
|
328
|
+
name: '⚠ exit 0 + 空输出 → true(零测试识别不属本判定,另票)',
|
|
329
|
+
exitCode: 0,
|
|
330
|
+
output: '',
|
|
331
|
+
expected: true,
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
name: '⚠ exit 0 + 零测试汇总 "0 passed" → true(同上)',
|
|
335
|
+
exitCode: 0,
|
|
336
|
+
output: ' 0 passed (1.0s)\n',
|
|
337
|
+
expected: true,
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
name: '⚠ exit 0 + 畸形 "X passed X failed"(计数位非数字)→ true(同上:无结构化失败信号)',
|
|
341
|
+
exitCode: 0,
|
|
342
|
+
output: ' X passed X failed\n',
|
|
343
|
+
expected: true,
|
|
344
|
+
},
|
|
345
|
+
{ name: 'exit 0 + 仅覆盖率表格分隔线 → true(无失败信号)', exitCode: 0, output: '----------|---------|\n', expected: true },
|
|
346
|
+
];
|
|
347
|
+
|
|
348
|
+
describe('judgeTestRun', () => {
|
|
349
|
+
for (const c of JUDGE_CASES) {
|
|
350
|
+
it(c.name, () => {
|
|
351
|
+
expect(judgeTestRun({ exitCode: c.exitCode, output: c.output, allowPartialPass: c.allowPartialPass })).toEqual(
|
|
352
|
+
expect.objectContaining({ passed: c.expected }),
|
|
353
|
+
);
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
it('allowPartialPass 缺省 = false(否决默认生效)', () => {
|
|
358
|
+
expect(judgeTestRun({ exitCode: 0, output: JEST_FAILURES }).passed).toBe(false);
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
it('否决时 failures 带出用例名(判负有据)', () => {
|
|
362
|
+
expect(judgeTestRun({ exitCode: 0, output: JEST_FAILURES }).failures).toEqual(['renders title', 'handles click']);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('全绿时 failures 为空数组', () => {
|
|
366
|
+
expect(judgeTestRun({ exitCode: 0, output: GENERIC_FAIL_IN_TEST_NAME }).failures).toEqual([]);
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it('非零退出时仍带出文本里的失败名(供上层拼错误信息)', () => {
|
|
370
|
+
expect(judgeTestRun({ exitCode: 1, output: GO_FAILURES }).failures).toEqual(['TestLogin', 'TestLogout']);
|
|
371
|
+
});
|
|
372
|
+
});
|