@dommaker/harness 1.6.0 → 1.8.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 +52 -0
- package/bin/harness.js +17 -1
- package/dist/agents/index.d.ts +6 -2
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +6 -16
- package/dist/agents/index.js.map +1 -1
- package/dist/cli/commands/__tests__/gate-decision.d.ts +18 -0
- package/dist/cli/commands/__tests__/gate-decision.d.ts.map +1 -0
- package/dist/cli/commands/__tests__/gate-decision.js +26 -0
- package/dist/cli/commands/__tests__/gate-decision.js.map +1 -0
- package/dist/cli/commands/acceptance.d.ts.map +1 -1
- package/dist/cli/commands/acceptance.js +17 -28
- package/dist/cli/commands/acceptance.js.map +1 -1
- package/dist/cli/commands/check.d.ts +11 -3
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/check.js +26 -11
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/command.d.ts +0 -1
- package/dist/cli/commands/command.d.ts.map +1 -1
- package/dist/cli/commands/command.js +8 -6
- package/dist/cli/commands/command.js.map +1 -1
- package/dist/cli/commands/constraints-retire.d.ts.map +1 -1
- package/dist/cli/commands/constraints-retire.js +36 -57
- package/dist/cli/commands/constraints-retire.js.map +1 -1
- package/dist/cli/commands/contract.d.ts.map +1 -1
- package/dist/cli/commands/contract.js +36 -42
- package/dist/cli/commands/contract.js.map +1 -1
- package/dist/cli/commands/definitions.d.ts +2 -0
- package/dist/cli/commands/definitions.d.ts.map +1 -1
- package/dist/cli/commands/definitions.js +11 -6
- package/dist/cli/commands/definitions.js.map +1 -1
- package/dist/cli/commands/failure.d.ts.map +1 -1
- package/dist/cli/commands/failure.js +16 -2
- package/dist/cli/commands/failure.js.map +1 -1
- package/dist/cli/commands/init.d.ts +14 -8
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +172 -364
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/knowledge-view.d.ts +90 -0
- package/dist/cli/commands/knowledge-view.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-view.js +198 -0
- package/dist/cli/commands/knowledge-view.js.map +1 -0
- package/dist/cli/commands/knowledge.d.ts +137 -52
- package/dist/cli/commands/knowledge.d.ts.map +1 -1
- package/dist/cli/commands/knowledge.js +534 -400
- package/dist/cli/commands/knowledge.js.map +1 -1
- package/dist/cli/commands/passes-gate.d.ts +4 -1
- package/dist/cli/commands/passes-gate.d.ts.map +1 -1
- package/dist/cli/commands/passes-gate.js +11 -2
- package/dist/cli/commands/passes-gate.js.map +1 -1
- package/dist/cli/commands/performance.d.ts.map +1 -1
- package/dist/cli/commands/performance.js +19 -31
- package/dist/cli/commands/performance.js.map +1 -1
- package/dist/cli/commands/report.d.ts.map +1 -1
- package/dist/cli/commands/report.js +2 -1
- package/dist/cli/commands/report.js.map +1 -1
- package/dist/cli/commands/review.d.ts.map +1 -1
- package/dist/cli/commands/review.js +13 -25
- package/dist/cli/commands/review.js.map +1 -1
- package/dist/cli/commands/scaffold-templates.d.ts +73 -0
- package/dist/cli/commands/scaffold-templates.d.ts.map +1 -0
- package/dist/cli/commands/scaffold-templates.js +424 -0
- package/dist/cli/commands/scaffold-templates.js.map +1 -0
- package/dist/cli/commands/scaffold.d.ts +105 -0
- package/dist/cli/commands/scaffold.d.ts.map +1 -0
- package/dist/cli/commands/scaffold.js +263 -0
- package/dist/cli/commands/scaffold.js.map +1 -0
- package/dist/cli/commands/security.d.ts.map +1 -1
- package/dist/cli/commands/security.js +22 -24
- package/dist/cli/commands/security.js.map +1 -1
- package/dist/cli/commands/spec-baseline-check.d.ts +43 -0
- package/dist/cli/commands/spec-baseline-check.d.ts.map +1 -1
- package/dist/cli/commands/spec-baseline-check.js +109 -34
- package/dist/cli/commands/spec-baseline-check.js.map +1 -1
- package/dist/cli/commands/sync-docs/context-syncer.d.ts +21 -2
- package/dist/cli/commands/sync-docs/context-syncer.d.ts.map +1 -1
- package/dist/cli/commands/sync-docs/context-syncer.js +112 -28
- package/dist/cli/commands/sync-docs/context-syncer.js.map +1 -1
- package/dist/cli/commands/sync-docs/index.d.ts +1 -1
- package/dist/cli/commands/sync-docs/index.d.ts.map +1 -1
- package/dist/cli/commands/sync-docs/index.js +86 -27
- package/dist/cli/commands/sync-docs/index.js.map +1 -1
- package/dist/cli/commands/sync-docs/project-reader.d.ts +24 -1
- package/dist/cli/commands/sync-docs/project-reader.d.ts.map +1 -1
- package/dist/cli/commands/sync-docs/project-reader.js +33 -7
- package/dist/cli/commands/sync-docs/project-reader.js.map +1 -1
- package/dist/cli/commands/validate.d.ts +0 -16
- package/dist/cli/commands/validate.d.ts.map +1 -1
- package/dist/cli/commands/validate.js +2 -97
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/gate-command.d.ts +37 -0
- package/dist/cli/gate-command.d.ts.map +1 -0
- package/dist/cli/gate-command.js +64 -0
- package/dist/cli/gate-command.js.map +1 -0
- package/dist/completion-checkers/index.d.ts +1 -1
- package/dist/completion-checkers/index.d.ts.map +1 -1
- package/dist/completion-checkers/index.js +0 -15
- package/dist/completion-checkers/index.js.map +1 -1
- package/dist/context/knowledge-injector.d.ts +4 -2
- package/dist/context/knowledge-injector.d.ts.map +1 -1
- package/dist/context/knowledge-injector.js +13 -6
- package/dist/context/knowledge-injector.js.map +1 -1
- package/dist/core/constraints/agent-prompt-renderer.js +2 -2
- package/dist/core/constraints/agent-prompt-renderer.js.map +1 -1
- package/dist/core/constraints/capabilities-reconcile.d.ts +20 -0
- package/dist/core/constraints/capabilities-reconcile.d.ts.map +1 -1
- package/dist/core/constraints/capabilities-reconcile.js +26 -4
- package/dist/core/constraints/capabilities-reconcile.js.map +1 -1
- package/dist/core/constraints/check-cache.d.ts +1 -1
- package/dist/core/constraints/check-cache.js +1 -1
- package/dist/core/constraints/checker.d.ts +8 -3
- package/dist/core/constraints/checker.d.ts.map +1 -1
- package/dist/core/constraints/checker.js +30 -19
- package/dist/core/constraints/checker.js.map +1 -1
- package/dist/core/constraints/checkers/capability-sync.d.ts +3 -1
- package/dist/core/constraints/checkers/capability-sync.d.ts.map +1 -1
- package/dist/core/constraints/checkers/capability-sync.js +17 -24
- package/dist/core/constraints/checkers/capability-sync.js.map +1 -1
- package/dist/core/constraints/checkers/context-doc-sync.d.ts +1 -1
- package/dist/core/constraints/checkers/context-doc-sync.d.ts.map +1 -1
- package/dist/core/constraints/checkers/context-doc-sync.js +9 -6
- 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 +24 -30
- package/dist/core/constraints/checkers/docs-freshness.js.map +1 -1
- package/dist/core/constraints/checkers/governance-presence.d.ts.map +1 -1
- package/dist/core/constraints/checkers/governance-presence.js +10 -4
- package/dist/core/constraints/checkers/governance-presence.js.map +1 -1
- package/dist/core/constraints/checkers/types.d.ts +10 -6
- package/dist/core/constraints/checkers/types.d.ts.map +1 -1
- package/dist/core/constraints/checkers/types.js +7 -3
- package/dist/core/constraints/checkers/types.js.map +1 -1
- package/dist/core/constraints/context-builder.d.ts +11 -10
- package/dist/core/constraints/context-builder.d.ts.map +1 -1
- package/dist/core/constraints/context-builder.js +31 -27
- package/dist/core/constraints/context-builder.js.map +1 -1
- package/dist/core/constraints/context-reconcile.d.ts +75 -0
- package/dist/core/constraints/context-reconcile.d.ts.map +1 -0
- package/dist/core/constraints/context-reconcile.js +161 -0
- package/dist/core/constraints/context-reconcile.js.map +1 -0
- package/dist/core/constraints/doc-freshness/runner.d.ts +7 -0
- package/dist/core/constraints/doc-freshness/runner.d.ts.map +1 -1
- package/dist/core/constraints/doc-freshness/runner.js +8 -3
- package/dist/core/constraints/doc-freshness/runner.js.map +1 -1
- package/dist/core/constraints/git-evidence.js +1 -1
- package/dist/core/constraints/git-evidence.js.map +1 -1
- package/dist/core/constraints/injection-drift.d.ts +7 -2
- package/dist/core/constraints/injection-drift.d.ts.map +1 -1
- package/dist/core/constraints/injection-drift.js +13 -7
- package/dist/core/constraints/injection-drift.js.map +1 -1
- package/dist/core/constraints/run-env.d.ts +92 -0
- package/dist/core/constraints/run-env.d.ts.map +1 -0
- package/dist/core/constraints/run-env.js +175 -0
- package/dist/core/constraints/run-env.js.map +1 -0
- package/dist/core/constraints/triggers.d.ts +22 -0
- package/dist/core/constraints/triggers.d.ts.map +1 -0
- package/dist/core/constraints/triggers.js +31 -0
- package/dist/core/constraints/triggers.js.map +1 -0
- package/dist/core/effective-constraints.d.ts +13 -4
- package/dist/core/effective-constraints.d.ts.map +1 -1
- package/dist/core/effective-constraints.js +16 -6
- package/dist/core/effective-constraints.js.map +1 -1
- package/dist/core/effective-set.d.ts +8 -15
- package/dist/core/effective-set.d.ts.map +1 -1
- package/dist/core/effective-set.js +7 -12
- package/dist/core/effective-set.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/project-config-loader.d.ts +39 -17
- package/dist/core/project-config-loader.d.ts.map +1 -1
- package/dist/core/project-config-loader.js +51 -122
- package/dist/core/project-config-loader.js.map +1 -1
- package/dist/core/validators/check-handlers/http.d.ts +2 -2
- package/dist/core/validators/check-handlers/http.d.ts.map +1 -1
- package/dist/core/validators/check-handlers/http.js +12 -7
- package/dist/core/validators/check-handlers/http.js.map +1 -1
- package/dist/core/validators/index.d.ts +1 -1
- package/dist/core/validators/index.d.ts.map +1 -1
- package/dist/core/validators/passes-gate.d.ts.map +1 -1
- package/dist/core/validators/passes-gate.js +2 -2
- package/dist/core/validators/passes-gate.js.map +1 -1
- package/dist/failure/classifier.d.ts +1 -1
- package/dist/failure/classifier.d.ts.map +1 -1
- package/dist/failure/classifier.js +8 -8
- package/dist/failure/classifier.js.map +1 -1
- package/dist/failure/index.d.ts +2 -1
- package/dist/failure/index.d.ts.map +1 -1
- package/dist/failure/index.js +9 -17
- package/dist/failure/index.js.map +1 -1
- package/dist/failure/recorder.d.ts +1 -1
- package/dist/failure/recorder.d.ts.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 +3 -2
- package/dist/gates/checker-gate.js.map +1 -1
- package/dist/gates/command.d.ts +10 -4
- package/dist/gates/command.d.ts.map +1 -1
- package/dist/gates/command.js +36 -62
- package/dist/gates/command.js.map +1 -1
- package/dist/gates/contract.d.ts.map +1 -1
- package/dist/gates/contract.js +0 -4
- package/dist/gates/contract.js.map +1 -1
- package/dist/gates/definitions.d.ts +2 -1
- package/dist/gates/definitions.d.ts.map +1 -1
- package/dist/gates/definitions.js +6 -5
- package/dist/gates/definitions.js.map +1 -1
- package/dist/gates/index.d.ts +0 -4
- package/dist/gates/index.d.ts.map +1 -1
- package/dist/gates/index.js +1 -6
- package/dist/gates/index.js.map +1 -1
- package/dist/gates/performance.d.ts.map +1 -1
- package/dist/gates/performance.js +0 -4
- package/dist/gates/performance.js.map +1 -1
- package/dist/gates/runner.d.ts +1 -1
- package/dist/gates/runner.js +1 -1
- package/dist/gates/security.d.ts +1 -1
- package/dist/gates/security.d.ts.map +1 -1
- package/dist/gates/security.js +5 -6
- package/dist/gates/security.js.map +1 -1
- package/dist/gates/types.d.ts +14 -17
- package/dist/gates/types.d.ts.map +1 -1
- package/dist/gates/types.js.map +1 -1
- package/dist/hooks/bootstrap.d.ts +6 -4
- package/dist/hooks/bootstrap.d.ts.map +1 -1
- package/dist/hooks/bootstrap.js +25 -13
- package/dist/hooks/bootstrap.js.map +1 -1
- package/dist/hooks/config.d.ts +6 -2
- package/dist/hooks/config.d.ts.map +1 -1
- package/dist/hooks/config.js +5 -1
- package/dist/hooks/config.js.map +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +0 -15
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/pipeline.d.ts.map +1 -1
- package/dist/hooks/pipeline.js +2 -4
- package/dist/hooks/pipeline.js.map +1 -1
- package/dist/hooks/registry.d.ts +11 -8
- package/dist/hooks/registry.d.ts.map +1 -1
- package/dist/hooks/registry.js +22 -7
- package/dist/hooks/registry.js.map +1 -1
- package/dist/hooks/types.d.ts +23 -7
- package/dist/hooks/types.d.ts.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/dist/knowledge/audit-scoring.d.ts +87 -0
- package/dist/knowledge/audit-scoring.d.ts.map +1 -0
- package/dist/knowledge/audit-scoring.js +470 -0
- package/dist/knowledge/audit-scoring.js.map +1 -0
- package/dist/knowledge/audit.d.ts +11 -59
- package/dist/knowledge/audit.d.ts.map +1 -1
- package/dist/knowledge/audit.js +47 -522
- package/dist/knowledge/audit.js.map +1 -1
- package/dist/knowledge/import.d.ts.map +1 -1
- package/dist/knowledge/import.js +2 -0
- package/dist/knowledge/import.js.map +1 -1
- package/dist/knowledge/index-generator.d.ts.map +1 -1
- package/dist/knowledge/index-generator.js +4 -5
- package/dist/knowledge/index-generator.js.map +1 -1
- package/dist/knowledge/index.d.ts +3 -2
- package/dist/knowledge/index.d.ts.map +1 -1
- package/dist/knowledge/index.js +3 -16
- package/dist/knowledge/index.js.map +1 -1
- package/dist/knowledge/ingest.js +1 -1
- package/dist/knowledge/ingest.js.map +1 -1
- package/dist/knowledge/lifecycle.d.ts.map +1 -1
- package/dist/knowledge/lifecycle.js +4 -2
- package/dist/knowledge/lifecycle.js.map +1 -1
- package/dist/knowledge/migration.d.ts +3 -0
- package/dist/knowledge/migration.d.ts.map +1 -1
- package/dist/knowledge/migration.js +8 -2
- package/dist/knowledge/migration.js.map +1 -1
- package/dist/knowledge/query.d.ts +6 -0
- package/dist/knowledge/query.d.ts.map +1 -1
- package/dist/knowledge/query.js +8 -2
- package/dist/knowledge/query.js.map +1 -1
- package/dist/knowledge/reference-tracker.d.ts.map +1 -1
- package/dist/knowledge/reference-tracker.js +4 -6
- package/dist/knowledge/reference-tracker.js.map +1 -1
- package/dist/knowledge/store.d.ts +22 -16
- package/dist/knowledge/store.d.ts.map +1 -1
- package/dist/knowledge/store.js +53 -12
- package/dist/knowledge/store.js.map +1 -1
- package/dist/knowledge/tree-walker.d.ts +19 -0
- package/dist/knowledge/tree-walker.d.ts.map +1 -0
- package/dist/knowledge/tree-walker.js +30 -0
- package/dist/knowledge/tree-walker.js.map +1 -0
- package/dist/knowledge/types.d.ts +16 -0
- package/dist/knowledge/types.d.ts.map +1 -1
- package/dist/monitoring/traces.d.ts +5 -3
- package/dist/monitoring/traces.d.ts.map +1 -1
- package/dist/monitoring/traces.js +19 -5
- package/dist/monitoring/traces.js.map +1 -1
- package/dist/test-setup/jsonl-fake-fs.d.ts +30 -0
- package/dist/test-setup/jsonl-fake-fs.d.ts.map +1 -0
- package/dist/test-setup/jsonl-fake-fs.js +49 -0
- package/dist/test-setup/jsonl-fake-fs.js.map +1 -0
- package/dist/tools/index.d.ts +4 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +7 -15
- package/dist/tools/index.js.map +1 -1
- package/dist/types/checkpoint.d.ts +5 -0
- package/dist/types/checkpoint.d.ts.map +1 -1
- package/dist/types/passes-gate.d.ts +0 -13
- package/dist/types/passes-gate.d.ts.map +1 -1
- package/dist/types/project-config.d.ts +18 -0
- package/dist/types/project-config.d.ts.map +1 -1
- package/dist/types/trace.d.ts +13 -4
- package/dist/types/trace.d.ts.map +1 -1
- package/dist/types/trace.js +4 -3
- package/dist/types/trace.js.map +1 -1
- package/dist/utils/exec.d.ts +4 -27
- package/dist/utils/exec.d.ts.map +1 -1
- package/dist/utils/exec.js +4 -94
- package/dist/utils/exec.js.map +1 -1
- package/dist/utils/jsonl.d.ts +17 -7
- package/dist/utils/jsonl.d.ts.map +1 -1
- package/dist/utils/jsonl.js +144 -17
- package/dist/utils/jsonl.js.map +1 -1
- package/dist/utils/numeric-flag.d.ts +44 -0
- package/dist/utils/numeric-flag.d.ts.map +1 -0
- package/dist/utils/numeric-flag.js +62 -0
- package/dist/utils/numeric-flag.js.map +1 -0
- package/package.json +1 -1
- package/src/CONTEXT.md +5 -2
- package/src/__tests__/acceptance-gate.test.ts +7 -4
- package/src/__tests__/checker-extra.test.ts +3 -2
- package/src/__tests__/checker.test.ts +4 -3
- package/src/__tests__/checkpoint.test.ts +26 -9
- package/src/__tests__/context-files-resolution.test.ts +29 -15
- package/src/__tests__/contract-gate.test.ts +19 -40
- package/src/__tests__/error-classifier.test.ts +1 -1
- package/src/__tests__/exec.test.ts +45 -107
- package/src/__tests__/failure-recorder.test.ts +7 -5
- package/src/__tests__/hooks-pipeline.test.ts +34 -47
- package/src/__tests__/layering.test.ts +217 -25
- package/src/__tests__/passes-gate.test.ts +9 -4
- package/src/__tests__/performance-gate.test.ts +3 -15
- package/src/__tests__/project-config-loader-extra.test.ts +31 -57
- package/src/__tests__/project-config-loader.test.ts +6 -3
- package/src/__tests__/public-exports.test.ts +27 -6
- package/src/__tests__/public-type-surface.test.ts +360 -0
- package/src/__tests__/public-value-surface.test.ts +182 -0
- package/src/__tests__/review-gate.test.ts +4 -6
- package/src/__tests__/security-gate.test.ts +5 -20
- package/src/__tests__/skip-semantics.test.ts +5 -3
- package/src/__tests__/spec-validator.test.ts +3 -2
- package/src/__tests__/sub-barrels-explicit.test.ts +87 -0
- package/src/__tests__/test-fixture-hygiene.test.ts +53 -0
- package/src/__tests__/trace-analyzer-extra.test.ts +5 -3
- package/src/__tests__/trace-analyzer.test.ts +5 -3
- package/src/__tests__/trace-collector.test.ts +5 -3
- package/src/agents/index.ts +13 -2
- package/src/cli/__tests__/gate-command.test.ts +162 -0
- package/src/cli/commands/CONTEXT.md +29 -5
- package/src/cli/commands/__tests__/acceptance.test.ts +24 -25
- package/src/cli/commands/__tests__/bin-exit-mapping.test.ts +15 -0
- package/src/cli/commands/__tests__/check-drift.test.ts +42 -1
- package/src/cli/commands/__tests__/check-read-count.test.ts +167 -0
- package/src/cli/commands/__tests__/check-skip-output.test.ts +4 -1
- package/src/cli/commands/__tests__/check.test.ts +43 -36
- package/src/cli/commands/__tests__/command-gate-dead-options.test.ts +60 -0
- package/src/cli/commands/__tests__/command.test.ts +33 -17
- package/src/cli/commands/__tests__/constraints-retire.test.ts +52 -0
- package/src/cli/commands/__tests__/context-syncer.test.ts +141 -0
- package/src/cli/commands/__tests__/contract.test.ts +20 -20
- package/src/cli/commands/__tests__/failure.test.ts +5 -4
- package/src/cli/commands/__tests__/gate-decision.ts +30 -0
- package/src/cli/commands/__tests__/init-dead-options.test.ts +50 -0
- package/src/cli/commands/__tests__/init-governance-io.test.ts +139 -0
- package/src/cli/commands/__tests__/init-injection.test.ts +3 -3
- package/src/cli/commands/__tests__/init-ondisk.test.ts +867 -0
- package/src/cli/commands/__tests__/init.test.ts +82 -6
- package/src/cli/commands/__tests__/knowledge-audit-threshold.test.ts +146 -0
- package/src/cli/commands/__tests__/knowledge-flywheel-consistency.test.ts +1 -1
- package/src/cli/commands/__tests__/knowledge-tone-mapping.test.ts +244 -0
- package/src/cli/commands/__tests__/knowledge-view.test.ts +839 -0
- package/src/cli/commands/__tests__/knowledge.test.ts +33 -15
- package/src/cli/commands/__tests__/numeric-flag-assembly.test.ts +368 -0
- package/src/cli/commands/__tests__/passes-gate-dead-options.test.ts +89 -1
- package/src/cli/commands/__tests__/performance.test.ts +19 -21
- package/src/cli/commands/__tests__/posteval-plan.test.ts +5 -3
- package/src/cli/commands/__tests__/pre-push-hook.test.ts +181 -0
- package/src/cli/commands/__tests__/project-path-anchoring.test.ts +95 -2
- package/src/cli/commands/__tests__/project-path-convention.test.ts +103 -25
- package/src/cli/commands/__tests__/registry.test.ts +2 -0
- package/src/cli/commands/__tests__/report.test.ts +23 -1
- package/src/cli/commands/__tests__/review.test.ts +10 -17
- package/src/cli/commands/__tests__/scaffold.test.ts +505 -0
- package/src/cli/commands/__tests__/security-default-scan.test.ts +75 -0
- package/src/cli/commands/__tests__/security.test.ts +21 -24
- package/src/cli/commands/__tests__/spec-baseline-check.test.ts +3 -2
- package/src/cli/commands/__tests__/spec-baseline-index-cap.test.ts +131 -0
- package/src/cli/commands/__tests__/spec-baseline-read-count.test.ts +325 -0
- package/src/cli/commands/__tests__/sync-docs-agents.test.ts +19 -4
- package/src/cli/commands/__tests__/sync-docs-context-drift.test.ts +232 -0
- package/src/cli/commands/__tests__/sync-docs-module-order.test.ts +111 -0
- package/src/cli/commands/__tests__/sync-docs-read-count.test.ts +192 -0
- package/src/cli/commands/__tests__/sync-docs.test.ts +3 -2
- package/src/cli/commands/__tests__/validate.test.ts +1 -48
- package/src/cli/commands/acceptance.ts +24 -29
- package/src/cli/commands/check.ts +40 -17
- package/src/cli/commands/command.ts +9 -8
- package/src/cli/commands/constraints-retire.ts +57 -70
- package/src/cli/commands/contract.ts +44 -47
- package/src/cli/commands/definitions.ts +12 -6
- package/src/cli/commands/failure.ts +16 -3
- package/src/cli/commands/init.ts +242 -389
- package/src/cli/commands/knowledge-view.ts +224 -0
- package/src/cli/commands/knowledge.ts +643 -448
- package/src/cli/commands/passes-gate.ts +12 -3
- package/src/cli/commands/performance.ts +31 -38
- package/src/cli/commands/report.ts +3 -2
- package/src/cli/commands/review.ts +22 -28
- package/src/cli/commands/scaffold-templates.ts +406 -0
- package/src/cli/commands/scaffold.ts +302 -0
- package/src/cli/commands/security.ts +27 -23
- package/src/cli/commands/spec-baseline-check.ts +158 -33
- package/src/cli/commands/sync-docs/__tests__/context-export-surface.test.ts +102 -0
- package/src/cli/commands/sync-docs/__tests__/module-descriptions.test.ts +196 -0
- package/src/cli/commands/sync-docs/context-syncer.ts +137 -31
- package/src/cli/commands/sync-docs/index.ts +103 -28
- package/src/cli/commands/sync-docs/project-reader.ts +51 -7
- package/src/cli/commands/validate.ts +1 -104
- package/src/cli/gate-command.ts +87 -0
- package/src/completion-checkers/index.ts +10 -1
- package/src/context/CONTEXT.md +2 -1
- package/src/context/__tests__/knowledge-injector.test.ts +27 -0
- package/src/context/__tests__/session-manager.test.ts +19 -12
- package/src/context/knowledge-injector.ts +14 -7
- package/src/core/CONTEXT.md +10 -7
- package/src/core/__tests__/effective-set.test.ts +36 -60
- package/src/core/constraints/__tests__/context-reconcile.test.ts +246 -0
- package/src/core/constraints/__tests__/run-env.test.ts +377 -0
- package/src/core/constraints/__tests__/triggers.test.ts +70 -0
- package/src/core/constraints/agent-prompt-renderer.ts +1 -1
- package/src/core/constraints/capabilities-reconcile.ts +28 -4
- package/src/core/constraints/check-cache.ts +1 -1
- package/src/core/constraints/checker.ts +30 -14
- package/src/core/constraints/checkers/__tests__/context-doc-sync.test.ts +8 -3
- package/src/core/constraints/checkers/__tests__/governance-presence.test.ts +16 -7
- package/src/core/constraints/checkers/__tests__/no-hardcoded-credentials.test.ts +2 -1
- package/src/core/constraints/checkers/capability-sync.ts +27 -28
- package/src/core/constraints/checkers/context-doc-sync.ts +9 -7
- package/src/core/constraints/checkers/docs-freshness.ts +28 -33
- package/src/core/constraints/checkers/governance-presence.ts +10 -6
- package/src/core/constraints/checkers/types.ts +14 -8
- package/src/core/constraints/context-builder.ts +35 -26
- package/src/core/constraints/context-reconcile.ts +200 -0
- package/src/core/constraints/doc-freshness/__tests__/runner.test.ts +25 -0
- package/src/core/constraints/doc-freshness/runner.ts +18 -4
- package/src/core/constraints/git-evidence.ts +1 -1
- package/src/core/constraints/injection-drift.ts +19 -8
- package/src/core/constraints/run-env.ts +207 -0
- package/src/core/constraints/triggers.ts +33 -0
- package/src/core/effective-constraints.ts +17 -6
- package/src/core/effective-set.ts +8 -24
- package/src/core/index.ts +2 -1
- package/src/core/project-config-loader.ts +54 -102
- package/src/core/validators/__tests__/http-retry-sleep.test.ts +231 -0
- package/src/core/validators/check-handlers/http.ts +18 -7
- package/src/core/validators/index.ts +0 -1
- package/src/core/validators/passes-gate.ts +2 -3
- package/src/failure/CONTEXT.md +2 -1
- package/src/failure/classifier.ts +2 -2
- package/src/failure/index.ts +14 -2
- package/src/failure/recorder.ts +1 -1
- package/src/gates/CONTEXT.md +13 -7
- package/src/gates/__tests__/checker-gate.test.ts +1 -1
- package/src/gates/__tests__/command-single-predicate.test.ts +135 -0
- package/src/gates/__tests__/command.test.ts +8 -15
- package/src/gates/__tests__/contract.test.ts +5 -5
- package/src/gates/__tests__/gate-interface.test.ts +0 -17
- package/src/gates/__tests__/performance.test.ts +0 -13
- package/src/gates/__tests__/review.test.ts +0 -1
- package/src/gates/__tests__/runner.test.ts +1 -1
- package/src/gates/__tests__/security-default-scan.test.ts +97 -0
- package/src/gates/__tests__/security.test.ts +0 -13
- package/src/gates/checker-gate.ts +3 -2
- package/src/gates/command.ts +51 -74
- package/src/gates/contract.ts +0 -5
- package/src/gates/definitions.ts +6 -5
- package/src/gates/index.ts +0 -5
- package/src/gates/performance.ts +1 -6
- package/src/gates/runner.ts +1 -1
- package/src/gates/security.ts +9 -11
- package/src/gates/types.ts +20 -23
- package/src/hooks/CONTEXT.md +10 -9
- package/src/hooks/__tests__/bootstrap.test.ts +29 -6
- package/src/hooks/__tests__/pipeline.test.ts +28 -17
- package/src/hooks/__tests__/registry.test.ts +51 -3
- package/src/hooks/bootstrap.ts +35 -15
- package/src/hooks/config.ts +6 -2
- package/src/hooks/index.ts +10 -1
- package/src/hooks/pipeline.ts +4 -6
- package/src/hooks/registry.ts +31 -12
- package/src/hooks/types.ts +24 -7
- package/src/index.ts +1 -3
- package/src/knowledge/CONTEXT.md +14 -7
- package/src/knowledge/__tests__/audit-labels.test.ts +8 -5
- package/src/knowledge/__tests__/audit-scoring.test.ts +230 -0
- package/src/knowledge/__tests__/audit-write-count.test.ts +131 -0
- package/src/knowledge/__tests__/audit.test.ts +291 -208
- package/src/knowledge/__tests__/doctor.test.ts +3 -2
- package/src/knowledge/__tests__/ingest.test.ts +3 -2
- package/src/knowledge/__tests__/lifecycle.test.ts +57 -2
- package/src/knowledge/__tests__/migration.test.ts +35 -6
- package/src/knowledge/__tests__/query.test.ts +3 -2
- package/src/knowledge/__tests__/reference-tracker.test.ts +23 -2
- package/src/knowledge/__tests__/store.test.ts +149 -4
- package/src/knowledge/__tests__/tree-walker.test.ts +132 -0
- package/src/knowledge/audit-scoring.ts +589 -0
- package/src/knowledge/audit.ts +55 -599
- package/src/knowledge/import.ts +2 -0
- package/src/knowledge/index-generator.ts +4 -6
- package/src/knowledge/index.ts +27 -2
- package/src/knowledge/ingest.ts +1 -1
- package/src/knowledge/lifecycle.ts +5 -2
- package/src/knowledge/migration.ts +8 -2
- package/src/knowledge/query.ts +8 -1
- package/src/knowledge/reference-tracker.ts +5 -7
- package/src/knowledge/store.ts +75 -16
- package/src/knowledge/tree-walker.ts +29 -0
- package/src/knowledge/types.ts +19 -0
- package/src/monitoring/CONTEXT.md +5 -2
- package/src/monitoring/__tests__/context-tracker.test.ts +16 -8
- package/src/monitoring/__tests__/trace-file-anchoring.test.ts +80 -0
- package/src/monitoring/traces.ts +19 -5
- package/src/release/CONTEXT.md +1 -1
- package/src/release/__tests__/integrity.test.ts +21 -12
- package/src/test-setup/__tests__/jsonl-fake-fs.test.ts +98 -0
- package/src/test-setup/jsonl-fake-fs.ts +59 -0
- package/src/tools/index.ts +5 -1
- package/src/types/checkpoint.ts +6 -0
- package/src/types/passes-gate.ts +0 -17
- package/src/types/project-config.ts +21 -0
- package/src/types/trace.ts +14 -4
- package/src/utils/__tests__/file-walk.test.ts +3 -2
- package/src/utils/__tests__/jsonl-bounded-read.test.ts +106 -0
- package/src/utils/__tests__/jsonl-skip-disposition.test.ts +10 -6
- package/src/utils/__tests__/jsonl.test.ts +61 -14
- package/src/utils/__tests__/numeric-flag.test.ts +80 -0
- package/src/utils/__tests__/package-version.test.ts +2 -2
- package/src/utils/exec.ts +4 -64
- package/src/utils/jsonl.ts +159 -20
- package/src/utils/numeric-flag.ts +64 -0
- package/dist/failure/types.d.ts +0 -9
- package/dist/failure/types.d.ts.map +0 -1
- package/dist/failure/types.js +0 -25
- package/dist/failure/types.js.map +0 -1
- package/dist/gates/effective-gates.d.ts +0 -30
- package/dist/gates/effective-gates.d.ts.map +0 -1
- package/dist/gates/effective-gates.js +0 -81
- package/dist/gates/effective-gates.js.map +0 -1
- package/src/failure/types.ts +0 -9
- package/src/gates/__tests__/effective-gates.test.ts +0 -77
- package/src/gates/effective-gates.ts +0 -99
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { knowledgeAudit, knowledgeStats, knowledgeHealth, knowledgeSearch } from '../knowledge';
|
|
6
6
|
import { captureIO, type CapturingIO } from '../../command-contract';
|
|
7
|
+
import type { AuditReport } from '../../../knowledge/audit-scoring';
|
|
7
8
|
|
|
8
9
|
// Mock chalk
|
|
9
10
|
jest.mock('chalk', () => ({
|
|
@@ -13,6 +14,7 @@ jest.mock('chalk', () => ({
|
|
|
13
14
|
yellow: jest.fn((str: string) => str),
|
|
14
15
|
red: jest.fn((str: string) => str),
|
|
15
16
|
gray: jest.fn((str: string) => str),
|
|
17
|
+
cyan: jest.fn((str: string) => str),
|
|
16
18
|
}));
|
|
17
19
|
|
|
18
20
|
// Mock KnowledgeAudit
|
|
@@ -21,8 +23,6 @@ jest.mock('../../../knowledge/audit', () => ({
|
|
|
21
23
|
KnowledgeAudit: jest.fn().mockImplementation(() => ({
|
|
22
24
|
run: mockRun,
|
|
23
25
|
})),
|
|
24
|
-
// label 正本在 audit.ts 规则定义上,CLI 直接消费(#109)
|
|
25
|
-
AUDIT_RULE_LABELS: jest.requireActual('../../../knowledge/audit').AUDIT_RULE_LABELS,
|
|
26
26
|
}));
|
|
27
27
|
|
|
28
28
|
// Mock KnowledgeIndexGenerator (avoids real fs writes in CLI tests)
|
|
@@ -32,7 +32,11 @@ jest.mock('../../../knowledge/index-generator', () => ({
|
|
|
32
32
|
})),
|
|
33
33
|
}));
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
/**
|
|
36
|
+
* 审计报告的 mock 与真实类型同源(harness#133 验收 3):标注成 AuditReport 后,
|
|
37
|
+
* 7 个维度、14 条规则键由编译期穷尽性管住——缺键补偿(原先手写 6 键再 splice incremental)写不出来。
|
|
38
|
+
*/
|
|
39
|
+
const MOCK_REPORT: AuditReport = {
|
|
36
40
|
timestamp: '2026-06-02T00:00:00.000Z',
|
|
37
41
|
totalEntries: 100,
|
|
38
42
|
issues: [
|
|
@@ -49,14 +53,17 @@ const MOCK_REPORT = {
|
|
|
49
53
|
'frontmatter-missing': 0,
|
|
50
54
|
'test-data-pollution': 0,
|
|
51
55
|
'daily-audit-noise': 0,
|
|
56
|
+
'event-noise': 0,
|
|
52
57
|
'zero-content-proven': 0,
|
|
53
58
|
'short-content': 1,
|
|
54
59
|
'maturity-inflation': 0,
|
|
55
60
|
'title-duplicate': 0,
|
|
56
61
|
'source-refs-bloat': 0,
|
|
62
|
+
'fragment-cluster': 0,
|
|
57
63
|
'promotion-blocked': 0,
|
|
58
64
|
'orphan-draft': 0,
|
|
59
65
|
'stale-entry': 0,
|
|
66
|
+
'deprecated-domain': 0,
|
|
60
67
|
},
|
|
61
68
|
dimensions: {
|
|
62
69
|
structure: { score: 100, issues: 0, details: {} },
|
|
@@ -65,16 +72,20 @@ const MOCK_REPORT = {
|
|
|
65
72
|
maturity: { score: 100, issues: 0, details: {} },
|
|
66
73
|
freshness: { score: 100, issues: 0, details: {} },
|
|
67
74
|
flywheel: { score: 50, issues: 0, details: {} },
|
|
75
|
+
incremental: { score: 80, issues: 0, details: {} },
|
|
68
76
|
},
|
|
69
77
|
autoFixed: 0,
|
|
70
78
|
healthScore: { before: 95, after: 95 },
|
|
71
79
|
};
|
|
72
80
|
|
|
81
|
+
|
|
73
82
|
let io: CapturingIO;
|
|
74
83
|
beforeEach(() => {
|
|
75
84
|
io = captureIO();
|
|
76
85
|
});
|
|
77
86
|
|
|
87
|
+
// 解析函数本体自 #133 起住 knowledge-view.ts(resolveKnowledgeBaseDir),行为面不变:
|
|
88
|
+
// 这里经 knowledgeStats 观测 `-p` / KNOWLEDGE_BASE_DIR / 旧目录兜底三条路径的解析结果
|
|
78
89
|
describe('getKnowledgeDir', () => {
|
|
79
90
|
const fs = require('fs');
|
|
80
91
|
const os = require('os');
|
|
@@ -147,10 +158,22 @@ describe('getKnowledgeDir', () => {
|
|
|
147
158
|
});
|
|
148
159
|
|
|
149
160
|
describe('knowledgeAudit CLI', () => {
|
|
161
|
+
// 引擎改收 store(#134)后,视图层会真构造 FileKnowledgeStore(构造即 mkdir),
|
|
162
|
+
// 本 describe 判定的是接线,不落真目录:把 store 构造点换成替身
|
|
163
|
+
let storeCtorSpy: jest.SpyInstance;
|
|
150
164
|
|
|
151
165
|
beforeEach(() => {
|
|
152
166
|
jest.clearAllMocks();
|
|
153
167
|
mockRun.mockReturnValue(MOCK_REPORT);
|
|
168
|
+
storeCtorSpy = jest.spyOn(require('../../../knowledge/store'), 'FileKnowledgeStore').mockImplementation(() => ({
|
|
169
|
+
list: jest.fn().mockReturnValue([]),
|
|
170
|
+
get: jest.fn(),
|
|
171
|
+
getBaseDir: jest.fn().mockReturnValue('/tmp/knowledge'),
|
|
172
|
+
}));
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
afterEach(() => {
|
|
176
|
+
storeCtorSpy.mockRestore();
|
|
154
177
|
});
|
|
155
178
|
|
|
156
179
|
it('should output JSON when --json is set', async () => {
|
|
@@ -196,12 +219,12 @@ describe('knowledgeAudit CLI', () => {
|
|
|
196
219
|
expect(output).toContain('修复后: 95/100');
|
|
197
220
|
});
|
|
198
221
|
|
|
199
|
-
it('
|
|
222
|
+
it('引擎收 store:目录解析落 openKnowledgeStore,阈值走第二形参(#134)', async () => {
|
|
200
223
|
const { KnowledgeAudit } = require('../../../knowledge/audit');
|
|
201
|
-
await knowledgeAudit({ dir: '/custom/path' }, io);
|
|
202
|
-
expect(
|
|
203
|
-
|
|
204
|
-
})
|
|
224
|
+
await knowledgeAudit({ dir: '/custom/path', threshold: '30' }, io);
|
|
225
|
+
expect(storeCtorSpy).toHaveBeenCalledWith({ baseDir: '/custom/path' });
|
|
226
|
+
const store = storeCtorSpy.mock.results[0].value;
|
|
227
|
+
expect(KnowledgeAudit).toHaveBeenCalledWith(store, { shortContentThreshold: 30 });
|
|
205
228
|
});
|
|
206
229
|
|
|
207
230
|
it('规则 label 闭环:event-noise / deprecated-domain 显示中文 label,不回落英文键名(#109)', async () => {
|
|
@@ -223,13 +246,8 @@ describe('knowledgeAudit CLI', () => {
|
|
|
223
246
|
});
|
|
224
247
|
|
|
225
248
|
it('维度 label 闭环:incremental 维度显示中文 label,不回落英文键名(#109)', async () => {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
dimensions: {
|
|
229
|
-
...MOCK_REPORT.dimensions,
|
|
230
|
-
incremental: { score: 80, issues: 0, details: {} },
|
|
231
|
-
},
|
|
232
|
-
});
|
|
249
|
+
// mock 与 AuditReport 同源后不必再补 incremental 键(#133 验收 3)
|
|
250
|
+
mockRun.mockReturnValue(MOCK_REPORT);
|
|
233
251
|
await knowledgeAudit({}, io);
|
|
234
252
|
const output = io.outText();
|
|
235
253
|
expect(output).toContain('D7 增量存活');
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 数值旗帜装配口径推广测试(harness#154)
|
|
3
|
+
*
|
|
4
|
+
* #152 把判据落在 knowledge audit --threshold 一处,本票推广到其余数值旗帜:
|
|
5
|
+
* - 定义表装配(mapActionArgs,转不出来抛 NumericFlagError → bin 映射 usage-error):
|
|
6
|
+
* constraints report 三阈值、performance --coverage-threshold/--bundle-threshold、
|
|
7
|
+
* review --min-reviewers;
|
|
8
|
+
* - 命令模块装配(parseNumericFlag 判别 + 就地 logError + usage-error):
|
|
9
|
+
* knowledge search --limit、failure list --limit、passes-gate --coverage-threshold。
|
|
10
|
+
* 证三件事:脏输入 fail-loud(非零 + stderr 点名旗帜 + stdout 零字节 + 零副作用)、
|
|
11
|
+
* 合法路径逐字不变(未传 vs 显式缺省同果)、显式 '0' 不被当「未传」兜掉。
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import * as fs from 'fs';
|
|
15
|
+
import * as os from 'os';
|
|
16
|
+
import * as path from 'path';
|
|
17
|
+
import { spawnSync } from 'child_process';
|
|
18
|
+
|
|
19
|
+
// Mock chalk(断言看文本,不看 ANSI)
|
|
20
|
+
jest.mock('chalk', () => ({
|
|
21
|
+
blue: jest.fn((s: string) => s),
|
|
22
|
+
bold: jest.fn((s: string) => s),
|
|
23
|
+
green: jest.fn((s: string) => s),
|
|
24
|
+
yellow: jest.fn((s: string) => s),
|
|
25
|
+
red: jest.fn((s: string) => s),
|
|
26
|
+
gray: jest.fn((s: string) => s),
|
|
27
|
+
cyan: jest.fn((s: string) => s),
|
|
28
|
+
}));
|
|
29
|
+
|
|
30
|
+
import { captureIO, lastJsonOutput } from '../../command-contract';
|
|
31
|
+
import { COMMAND_DEFINITIONS } from '../definitions';
|
|
32
|
+
import { GATE_DEFINITIONS } from '../../../gates/definitions';
|
|
33
|
+
import { knowledgeSearchCommand } from '../knowledge';
|
|
34
|
+
import { failureList } from '../failure';
|
|
35
|
+
import { coverageCheck } from '../passes-gate';
|
|
36
|
+
import { FileKnowledgeStore } from '../../../knowledge/store';
|
|
37
|
+
import type { KnowledgeEntry } from '../../../knowledge/types';
|
|
38
|
+
import { FailureRecorder } from '../../../failure/recorder';
|
|
39
|
+
import { DEFAULT_FAILURE_LOG_FILE, ErrorType, FailureLevel } from '../../../types/failure';
|
|
40
|
+
import { NumericFlagError } from '../../../utils/numeric-flag';
|
|
41
|
+
|
|
42
|
+
const repoRoot = path.join(__dirname, '..', '..', '..', '..');
|
|
43
|
+
const distBin = path.join(repoRoot, 'bin', 'harness.js');
|
|
44
|
+
const hasDist = fs.existsSync(path.join(repoRoot, 'dist', 'cli', 'commands'));
|
|
45
|
+
|
|
46
|
+
function tmp(): string {
|
|
47
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), 'harness-k154-'));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ========================================
|
|
51
|
+
// 定义表装配点(mapActionArgs → requireNumericFlag)
|
|
52
|
+
// ========================================
|
|
53
|
+
|
|
54
|
+
const reportDef = COMMAND_DEFINITIONS.find(d => d.command === 'constraints')!
|
|
55
|
+
.children!.find(d => d.command === 'report')!;
|
|
56
|
+
const performanceCli = GATE_DEFINITIONS.find(g => g.id === 'performance')!.cli;
|
|
57
|
+
const reviewCli = GATE_DEFINITIONS.find(g => g.id === 'review')!.cli;
|
|
58
|
+
|
|
59
|
+
describe('constraints report 三阈值:装配点 fail-loud', () => {
|
|
60
|
+
const valid = { json: false, zeroInterceptMin: '50', noiseFailRate: '0.8', noiseMinTotal: '20' };
|
|
61
|
+
|
|
62
|
+
it('缺省字符串 → 数值(int/int/float 各归其形)', () => {
|
|
63
|
+
expect(reportDef.mapActionArgs!([], valid)).toEqual([{
|
|
64
|
+
projectPath: undefined,
|
|
65
|
+
export: undefined,
|
|
66
|
+
json: false,
|
|
67
|
+
zeroInterceptMin: 50,
|
|
68
|
+
noiseFailRate: 0.8,
|
|
69
|
+
noiseMinTotal: 20,
|
|
70
|
+
}]);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it.each([
|
|
74
|
+
['zeroInterceptMin', '--zero-intercept-min'],
|
|
75
|
+
['noiseFailRate', '--noise-fail-rate'],
|
|
76
|
+
['noiseMinTotal', '--noise-min-total'],
|
|
77
|
+
])('%s 脏值 → 抛 NumericFlagError 点名 %s(原先 NaN 静默减少候选、退出码 0)', (key, flag) => {
|
|
78
|
+
let caught: unknown;
|
|
79
|
+
try {
|
|
80
|
+
reportDef.mapActionArgs!([], { ...valid, [key]: 'abc' });
|
|
81
|
+
} catch (err) {
|
|
82
|
+
caught = err;
|
|
83
|
+
}
|
|
84
|
+
expect(caught).toBeInstanceOf(NumericFlagError);
|
|
85
|
+
expect((caught as Error).message).toContain(flag);
|
|
86
|
+
expect((caught as Error).message).toContain('"abc"');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('显式 "0" → 0(不被当未传兜掉)', () => {
|
|
90
|
+
const [args] = reportDef.mapActionArgs!([], { ...valid, zeroInterceptMin: '0' }) as [{ zeroInterceptMin: number }];
|
|
91
|
+
expect(args.zeroInterceptMin).toBe(0);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
describe('门禁 performance / review:装配点 fail-loud', () => {
|
|
96
|
+
it('performance 缺省字符串 → 数值;显式 "0" → 0', () => {
|
|
97
|
+
const [args] = performanceCli.mapActionArgs!([], {
|
|
98
|
+
coverage: true, coverageThreshold: '80', bundle: true, bundleThreshold: '500',
|
|
99
|
+
}) as [{ coverageThreshold: number; bundleThreshold: number }];
|
|
100
|
+
expect(args.coverageThreshold).toBe(80);
|
|
101
|
+
expect(args.bundleThreshold).toBe(500);
|
|
102
|
+
const [zeros] = performanceCli.mapActionArgs!([], {
|
|
103
|
+
coverage: true, coverageThreshold: '0', bundle: true, bundleThreshold: '0',
|
|
104
|
+
}) as [{ coverageThreshold: number; bundleThreshold: number }];
|
|
105
|
+
expect(zeros.coverageThreshold).toBe(0);
|
|
106
|
+
expect(zeros.bundleThreshold).toBe(0);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it.each([
|
|
110
|
+
['coverageThreshold', '--coverage-threshold'],
|
|
111
|
+
['bundleThreshold', '--bundle-threshold'],
|
|
112
|
+
])('performance %s 脏值 → 抛 NumericFlagError 点名 %s', (key, flag) => {
|
|
113
|
+
let caught: unknown;
|
|
114
|
+
try {
|
|
115
|
+
performanceCli.mapActionArgs!([], { coverageThreshold: '80', bundleThreshold: '500', [key]: 'abc' });
|
|
116
|
+
} catch (err) {
|
|
117
|
+
caught = err;
|
|
118
|
+
}
|
|
119
|
+
expect(caught).toBeInstanceOf(NumericFlagError);
|
|
120
|
+
expect((caught as Error).message).toContain(flag);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('review --min-reviewers:缺省 → 1,显式 "0" → 0,脏值抛错', () => {
|
|
124
|
+
const [args] = reviewCli.mapActionArgs!([], { minReviewers: '1' }) as [{ minReviewers: number }];
|
|
125
|
+
expect(args.minReviewers).toBe(1);
|
|
126
|
+
const [zero] = reviewCli.mapActionArgs!([], { minReviewers: '0' }) as [{ minReviewers: number }];
|
|
127
|
+
expect(zero.minReviewers).toBe(0);
|
|
128
|
+
expect(() => reviewCli.mapActionArgs!([], { minReviewers: 'abc' })).toThrow(NumericFlagError);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// ========================================
|
|
133
|
+
// 命令模块装配点(parseNumericFlag 判别 + 就地 usage-error)
|
|
134
|
+
// ========================================
|
|
135
|
+
|
|
136
|
+
const DAY = 24 * 60 * 60 * 1000;
|
|
137
|
+
function makeEntry(id: string, content: string): KnowledgeEntry {
|
|
138
|
+
return {
|
|
139
|
+
id,
|
|
140
|
+
type: 'guideline',
|
|
141
|
+
title: `探针 ${id}`,
|
|
142
|
+
content,
|
|
143
|
+
maturity: 'draft',
|
|
144
|
+
layer: 'project',
|
|
145
|
+
created: new Date(Date.now() - 3 * DAY).toISOString(),
|
|
146
|
+
lastReferenced: new Date(Date.now() - DAY).toISOString(),
|
|
147
|
+
contributors: [],
|
|
148
|
+
projects: [],
|
|
149
|
+
tags: [],
|
|
150
|
+
applicablePhases: [],
|
|
151
|
+
sourceReferences: [],
|
|
152
|
+
referencedBy: [],
|
|
153
|
+
executionResults: [],
|
|
154
|
+
consumptionMode: 'reference',
|
|
155
|
+
origin: 'agent',
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** 两条都含 probe 的条目,store 落在 projectPath 约定位置(openKnowledgeStore 同径) */
|
|
160
|
+
function seedKnowledge(projectPath: string): void {
|
|
161
|
+
const store = new FileKnowledgeStore({ baseDir: `${projectPath}/.harness/knowledge` });
|
|
162
|
+
store.save(makeEntry('P-1', 'probe alpha'));
|
|
163
|
+
store.save(makeEntry('P-2', 'probe beta'));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
describe('knowledge search --limit:命令入口 fail-loud', () => {
|
|
167
|
+
it('未传 vs 显式 "20" 逐字同果;"1" 真截断', async () => {
|
|
168
|
+
const projectPath = tmp();
|
|
169
|
+
seedKnowledge(projectPath);
|
|
170
|
+
const unset = captureIO();
|
|
171
|
+
const r1 = await knowledgeSearchCommand(['probe'], { projectPath, json: true }, unset);
|
|
172
|
+
expect(r1.kind).toBe('ok');
|
|
173
|
+
const explicit = captureIO();
|
|
174
|
+
const r2 = await knowledgeSearchCommand(['probe'], { projectPath, json: true, limit: '20' }, explicit);
|
|
175
|
+
expect(r2.kind).toBe('ok');
|
|
176
|
+
expect(explicit.outText()).toBe(unset.outText());
|
|
177
|
+
expect(lastJsonOutput<{ total: number }>(unset).total).toBe(2);
|
|
178
|
+
|
|
179
|
+
const one = captureIO();
|
|
180
|
+
await knowledgeSearchCommand(['probe'], { projectPath, json: true, limit: '1' }, one);
|
|
181
|
+
expect(lastJsonOutput<{ total: number }>(one).total).toBe(1);
|
|
182
|
+
fs.rmSync(projectPath, { recursive: true, force: true });
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('显式 "0" → 0 条(原先 0 || 20 静默落缺省)', async () => {
|
|
186
|
+
const projectPath = tmp();
|
|
187
|
+
seedKnowledge(projectPath);
|
|
188
|
+
const io = captureIO();
|
|
189
|
+
const r = await knowledgeSearchCommand(['probe'], { projectPath, json: true, limit: '0' }, io);
|
|
190
|
+
expect(r.kind).toBe('ok');
|
|
191
|
+
expect(lastJsonOutput<{ total: number }>(io).total).toBe(0);
|
|
192
|
+
fs.rmSync(projectPath, { recursive: true, force: true });
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it.each(['abc', '1e2', '0.7', '-5', '0x10'])(
|
|
196
|
+
'--limit %o → usage-error + stderr 点名,store 不构造、目录零新文件',
|
|
197
|
+
async (raw) => {
|
|
198
|
+
const projectPath = tmp();
|
|
199
|
+
const io = captureIO();
|
|
200
|
+
const r = await knowledgeSearchCommand(['probe'], { projectPath, json: true, limit: raw }, io);
|
|
201
|
+
expect(r.kind).toBe('usage-error');
|
|
202
|
+
expect(r).toEqual({ kind: 'usage-error', reason: expect.stringContaining('--limit') });
|
|
203
|
+
expect(io.outText()).toBe('');
|
|
204
|
+
expect(io.errText()).toContain('--limit');
|
|
205
|
+
expect(io.errText()).toContain(`"${raw}"`);
|
|
206
|
+
expect(fs.readdirSync(projectPath)).toEqual([]);
|
|
207
|
+
fs.rmSync(projectPath, { recursive: true, force: true });
|
|
208
|
+
},
|
|
209
|
+
);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
describe('failure list --limit:命令入口 fail-loud', () => {
|
|
213
|
+
async function seedFailures(projectPath: string, count: number): Promise<void> {
|
|
214
|
+
const recorder = new FailureRecorder({ logFile: path.join(projectPath, DEFAULT_FAILURE_LOG_FILE) });
|
|
215
|
+
for (let i = 0; i < count; i++) {
|
|
216
|
+
await recorder.record({
|
|
217
|
+
type: ErrorType.AGENT_ERROR,
|
|
218
|
+
level: FailureLevel.L2,
|
|
219
|
+
message: `探针失败 ${i}`,
|
|
220
|
+
timestamp: Date.now() + i,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
it('显式 "20" 截到 20 条;显式 "0" = 不截断(既有语义钉住,非兜回缺省)', async () => {
|
|
226
|
+
const projectPath = tmp();
|
|
227
|
+
await seedFailures(projectPath, 25);
|
|
228
|
+
const twenty = captureIO();
|
|
229
|
+
const r1 = await failureList({ projectPath, json: true, limit: '20' }, twenty);
|
|
230
|
+
expect(r1.kind).toBe('ok');
|
|
231
|
+
expect(lastJsonOutput<{ total: number }>(twenty).total).toBe(20);
|
|
232
|
+
|
|
233
|
+
const zero = captureIO();
|
|
234
|
+
const r2 = await failureList({ projectPath, json: true, limit: '0' }, zero);
|
|
235
|
+
expect(r2.kind).toBe('ok');
|
|
236
|
+
expect(lastJsonOutput<{ total: number }>(zero).total).toBe(25);
|
|
237
|
+
fs.rmSync(projectPath, { recursive: true, force: true });
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('程序内 number 入参形状不变(双形声明是对的)', async () => {
|
|
241
|
+
const projectPath = tmp();
|
|
242
|
+
await seedFailures(projectPath, 25);
|
|
243
|
+
const io = captureIO();
|
|
244
|
+
const r = await failureList({ projectPath, json: true, limit: 5 }, io);
|
|
245
|
+
expect(r.kind).toBe('ok');
|
|
246
|
+
expect(lastJsonOutput<{ total: number }>(io).total).toBe(5);
|
|
247
|
+
fs.rmSync(projectPath, { recursive: true, force: true });
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it('--limit abc → usage-error + stderr 点名,recorder 不构造、目录零新文件', async () => {
|
|
251
|
+
const projectPath = tmp();
|
|
252
|
+
const io = captureIO();
|
|
253
|
+
const r = await failureList({ projectPath, json: true, limit: 'abc' }, io);
|
|
254
|
+
expect(r).toEqual({ kind: 'usage-error', reason: expect.stringContaining('--limit') });
|
|
255
|
+
expect(io.outText()).toBe('');
|
|
256
|
+
expect(io.errText()).toContain('--limit');
|
|
257
|
+
expect(io.errText()).toContain('"abc"');
|
|
258
|
+
expect(fs.readdirSync(projectPath)).toEqual([]);
|
|
259
|
+
fs.rmSync(projectPath, { recursive: true, force: true });
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
describe('passes-gate --coverage-threshold:命令入口 fail-loud', () => {
|
|
264
|
+
it('脏值 → usage-error + stderr 点名,覆盖率检查不执行(原先打出自证异常的 "(x% < NaN%)")', async () => {
|
|
265
|
+
const projectPath = tmp();
|
|
266
|
+
const io = captureIO();
|
|
267
|
+
const r = await coverageCheck({ projectPath, coverageThreshold: 'abc' }, io);
|
|
268
|
+
expect(r).toEqual({ kind: 'usage-error', reason: expect.stringContaining('--coverage-threshold') });
|
|
269
|
+
expect(io.outText()).toBe('');
|
|
270
|
+
expect(io.errText()).toContain('--coverage-threshold');
|
|
271
|
+
expect(io.errText()).toContain('"abc"');
|
|
272
|
+
fs.rmSync(projectPath, { recursive: true, force: true });
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// ========================================
|
|
277
|
+
// 端到端:真实 spawn bin/harness.js(dist 存在时)
|
|
278
|
+
// ========================================
|
|
279
|
+
|
|
280
|
+
// 与 bin-exit-mapping.test.ts 同规:CI 上 dist 缺失显式失败而非静默 skip(harness#99)
|
|
281
|
+
if (!hasDist && process.env.CI) {
|
|
282
|
+
throw new Error('dist 未构建:数值旗帜端到端不得静默 skip —— CI 必须先 npm run build 再 npm test(harness#99)');
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const smoke = hasDist ? describe : describe.skip;
|
|
286
|
+
|
|
287
|
+
smoke('端到端:脏输入 → 非零退出 + stderr 点名 + stdout 零字节 + 零副作用落盘', () => {
|
|
288
|
+
const run = (argv: string[], cwd: string) => spawnSync(process.execPath, [distBin, ...argv], {
|
|
289
|
+
cwd,
|
|
290
|
+
encoding: 'utf-8',
|
|
291
|
+
timeout: 60000,
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
/** 四组静默降级站点(票面「确切缺口」1/2/3/4)+ performance --coverage-threshold */
|
|
295
|
+
it.each([
|
|
296
|
+
[['constraints', 'report', '--zero-intercept-min', 'abc'], '--zero-intercept-min'],
|
|
297
|
+
[['constraints', 'report', '--noise-fail-rate', 'abc'], '--noise-fail-rate'],
|
|
298
|
+
[['constraints', 'report', '--noise-min-total', 'abc'], '--noise-min-total'],
|
|
299
|
+
[['knowledge', 'search', 'probe', '--limit', 'abc'], '--limit'],
|
|
300
|
+
[['failure', 'list', '--limit', 'abc'], '--limit'],
|
|
301
|
+
[['performance', '--bundle', '--bundle-threshold', 'abc'], '--bundle-threshold'],
|
|
302
|
+
[['performance', '--coverage', '--coverage-threshold', 'abc'], '--coverage-threshold'],
|
|
303
|
+
])('%j → exit 1', (argv, flag) => {
|
|
304
|
+
const projectPath = tmp();
|
|
305
|
+
try {
|
|
306
|
+
const r = run([...argv, '-p', projectPath], projectPath);
|
|
307
|
+
expect(r.status).toBe(1);
|
|
308
|
+
expect(r.stderr).toContain(flag);
|
|
309
|
+
expect(r.stderr).toContain('"abc"');
|
|
310
|
+
expect(r.stdout).toBe('');
|
|
311
|
+
expect(fs.readdirSync(projectPath)).toEqual([]);
|
|
312
|
+
} finally {
|
|
313
|
+
fs.rmSync(projectPath, { recursive: true, force: true });
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it('review --min-reviewers abc → exit 1(fail-closed 面同样收敛为 fail-loud)', () => {
|
|
318
|
+
const projectPath = tmp();
|
|
319
|
+
try {
|
|
320
|
+
const r = run(['review', '--min-reviewers', 'abc', '-p', projectPath], projectPath);
|
|
321
|
+
expect(r.status).toBe(1);
|
|
322
|
+
expect(r.stderr).toContain('--min-reviewers');
|
|
323
|
+
expect(fs.readdirSync(projectPath)).toEqual([]);
|
|
324
|
+
} finally {
|
|
325
|
+
fs.rmSync(projectPath, { recursive: true, force: true });
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
it('passes-gate --coverage --coverage-threshold abc → exit 1(usage-error,先于覆盖率执行)', () => {
|
|
330
|
+
const projectPath = tmp();
|
|
331
|
+
try {
|
|
332
|
+
const r = run(['passes-gate', '--coverage', '--coverage-threshold', 'abc', '-p', projectPath], projectPath);
|
|
333
|
+
expect(r.status).toBe(1);
|
|
334
|
+
expect(r.stderr).toContain('--coverage-threshold');
|
|
335
|
+
expect(fs.readdirSync(projectPath)).toEqual([]);
|
|
336
|
+
} finally {
|
|
337
|
+
fs.rmSync(projectPath, { recursive: true, force: true });
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
it('合法路径逐字不变:未传 vs 显式缺省值,stdout 逐字相等', () => {
|
|
342
|
+
const pairs: string[][][] = [
|
|
343
|
+
[
|
|
344
|
+
['constraints', 'report'],
|
|
345
|
+
['constraints', 'report', '--zero-intercept-min', '50', '--noise-fail-rate', '0.8', '--noise-min-total', '20'],
|
|
346
|
+
],
|
|
347
|
+
[
|
|
348
|
+
['failure', 'list'],
|
|
349
|
+
['failure', 'list', '--limit', '20'],
|
|
350
|
+
],
|
|
351
|
+
[
|
|
352
|
+
['knowledge', 'search', 'probe'],
|
|
353
|
+
['knowledge', 'search', 'probe', '--limit', '20'],
|
|
354
|
+
],
|
|
355
|
+
];
|
|
356
|
+
for (const [unset, explicit] of pairs) {
|
|
357
|
+
const projectPath = tmp();
|
|
358
|
+
try {
|
|
359
|
+
const r1 = run([...unset, '-p', projectPath], projectPath);
|
|
360
|
+
const r2 = run([...explicit, '-p', projectPath], projectPath);
|
|
361
|
+
expect(r2.status).toBe(r1.status);
|
|
362
|
+
expect(r2.stdout).toBe(r1.stdout);
|
|
363
|
+
} finally {
|
|
364
|
+
fs.rmSync(projectPath, { recursive: true, force: true });
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
});
|
|
@@ -13,10 +13,53 @@
|
|
|
13
13
|
|
|
14
14
|
import * as fs from 'fs';
|
|
15
15
|
import * as path from 'path';
|
|
16
|
-
import { COMMAND_DEFINITIONS } from '../definitions';
|
|
16
|
+
import { COMMAND_DEFINITIONS, type CommandDefinition } from '../definitions';
|
|
17
|
+
import { GATE_DEFINITIONS } from '../../../gates/definitions';
|
|
17
18
|
import type { PassesGateConfig } from '../../../types/passes-gate';
|
|
18
19
|
import type { PassesGateOptions } from '../passes-gate';
|
|
19
20
|
|
|
21
|
+
/**
|
|
22
|
+
* 已删旗帜的精确令牌(二次复审 S2 收口)
|
|
23
|
+
*
|
|
24
|
+
* `--max-retries` 的旗帜名 + 它在 commander 里的选项键名(`optionRoutes.flag` 按键路由,
|
|
25
|
+
* 是同一个已删选项的第二个落点)。**只钉这两个令牌**,不钉「retry 这个词」。
|
|
26
|
+
*/
|
|
27
|
+
const DELETED_FLAG_TOKENS = ['--max-retries', 'maxRetries'];
|
|
28
|
+
|
|
29
|
+
interface FlagSite {
|
|
30
|
+
/** 命令位(含父命令前缀,如 'constraints report') */
|
|
31
|
+
slot: string;
|
|
32
|
+
/** 旗帜令牌('-t' / '--test-command')或选项路由键('list') */
|
|
33
|
+
token: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** 递归收集命令位上的旗帜令牌与选项路由键(走法同 registry.test.ts 的 collectRefs) */
|
|
37
|
+
function collectFlagSites(defs: CommandDefinition[], prefix = ''): FlagSite[] {
|
|
38
|
+
return defs.flatMap((def) => {
|
|
39
|
+
const slot = [prefix, def.command].filter(Boolean).join(' ');
|
|
40
|
+
const own: FlagSite[] = [
|
|
41
|
+
...def.options.flatMap((option) =>
|
|
42
|
+
option.flags
|
|
43
|
+
.split(/[\s,]+/)
|
|
44
|
+
.filter((token) => token.startsWith('-'))
|
|
45
|
+
.map((token) => ({ slot, token })),
|
|
46
|
+
),
|
|
47
|
+
...(def.optionRoutes || []).map((route) => ({ slot, token: route.flag })),
|
|
48
|
+
];
|
|
49
|
+
return [...own, ...collectFlagSites(def.children || [], slot)];
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function sitesHoldingDeletedFlag(sites: FlagSite[]): FlagSite[] {
|
|
54
|
+
return sites.filter((site) => DELETED_FLAG_TOKENS.includes(site.token));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** 全部命令位:通用命令表 + 门禁命令表(GATE_DEFINITIONS.cli 由 bin 同一引擎生成命令块) */
|
|
58
|
+
const ALL_CLI_SITES = [
|
|
59
|
+
...collectFlagSites(COMMAND_DEFINITIONS),
|
|
60
|
+
...collectFlagSites(GATE_DEFINITIONS.map((gate) => gate.cli)),
|
|
61
|
+
];
|
|
62
|
+
|
|
20
63
|
const passesGateCommand = COMMAND_DEFINITIONS.find(d => d.command === 'passes-gate');
|
|
21
64
|
const cliSource = fs.readFileSync(path.join(__dirname, '..', 'passes-gate.ts'), 'utf-8');
|
|
22
65
|
const validatorSource = fs.readFileSync(
|
|
@@ -39,10 +82,55 @@ describe('passes-gate 重试选项已删除(A1)', () => {
|
|
|
39
82
|
]);
|
|
40
83
|
});
|
|
41
84
|
|
|
85
|
+
it('采集面确实覆盖三类命令位(前提,防空扫致闸失效)', () => {
|
|
86
|
+
const rendered = ALL_CLI_SITES.map(s => `${s.slot} ${s.token}`);
|
|
87
|
+
expect(rendered).toContain('passes-gate --coverage-threshold'); // 通用表叶子命令的旗帜
|
|
88
|
+
expect(rendered).toContain('constraints report --json'); // children 递归(嵌套命令位)
|
|
89
|
+
expect(rendered).toContain('acceptance --task-id'); // 门禁表命令位(GATE_DEFINITIONS.cli)
|
|
90
|
+
expect(rendered).toContain('check list'); // 选项路由键(commander camelCase 键位)
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('已删的 --max-retries 不在任何命令位复活(逐命令逐选项精确冻结)', () => {
|
|
94
|
+
expect(sitesHoldingDeletedFlag(ALL_CLI_SITES)).toEqual([]);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 旧闸(A5 引入的全表禁词版)——原样保留,与上面的精确冻结并存。
|
|
99
|
+
* 它宽于「冻结已删选项」这一意图:将来任何命令新增合法的 retries 类选项都会被拦。
|
|
100
|
+
* 收窄(即删掉这条)是二次复审 S2 的应修项,但删除断言属 `no_test_simplification`
|
|
101
|
+
* 铁律拦截范围、而该闸无批准通道,故本轮只加不改,退役动作交人类裁决。
|
|
102
|
+
*/
|
|
42
103
|
it('命令定义表任意层级都不含 retry 旗帜(防换个命令位复活)', () => {
|
|
43
104
|
expect(JSON.stringify(COMMAND_DEFINITIONS)).not.toMatch(/retry/i);
|
|
44
105
|
});
|
|
45
106
|
|
|
107
|
+
/**
|
|
108
|
+
* 反向验闸(二次复审 S2):把已删旗帜分别挂到「另一条通用命令 / 门禁命令 / 选项路由键」
|
|
109
|
+
* 三处,断言扫描逐字报出——证明换掉的不是空洞,也证明覆盖面真的等于名义上的「任何命令位」。
|
|
110
|
+
* 将来若要在别的命令位做**有真实现**的重试,那是新设计:显式评审后把令牌从
|
|
111
|
+
* DELETED_FLAG_TOKENS 解除(同 ADR-0022 推翻 AC-007 的做法),不靠闸静默放行。
|
|
112
|
+
*/
|
|
113
|
+
it('闸非空洞:复活在别的命令位仍会红(通用命令 / 门禁命令 / 选项路由键)', () => {
|
|
114
|
+
const probe = { flags: '--max-retries <n>', description: '复活探针' };
|
|
115
|
+
const otherCommand = COMMAND_DEFINITIONS.find(d => d.command === 'check')!;
|
|
116
|
+
const gateSlot = GATE_DEFINITIONS.find(g => g.id === 'acceptance')!;
|
|
117
|
+
|
|
118
|
+
const resurrected = [
|
|
119
|
+
...collectFlagSites([{ ...otherCommand, options: [...otherCommand.options, probe] }]),
|
|
120
|
+
...collectFlagSites([{ ...gateSlot.cli, options: [...gateSlot.cli.options, probe] }]),
|
|
121
|
+
...collectFlagSites([{
|
|
122
|
+
...otherCommand,
|
|
123
|
+
optionRoutes: [...(otherCommand.optionRoutes || []), { ...otherCommand.optionRoutes![0], flag: 'maxRetries' }],
|
|
124
|
+
}]),
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
expect(sitesHoldingDeletedFlag(resurrected).map(s => `${s.slot} ${s.token}`)).toEqual([
|
|
128
|
+
'check --max-retries',
|
|
129
|
+
'acceptance --max-retries',
|
|
130
|
+
'check maxRetries',
|
|
131
|
+
]);
|
|
132
|
+
});
|
|
133
|
+
|
|
46
134
|
it('CLI 装配链与 validator 默认配置都不再写重试字段', () => {
|
|
47
135
|
expect(cliSource).not.toMatch(/maxRetries|retryDelay/);
|
|
48
136
|
expect(validatorSource).not.toMatch(/maxRetries|retryDelay/);
|