@dommaker/harness 1.7.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 +37 -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 +1 -0
- 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/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 +3 -3
- 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/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 +0 -1
- package/src/__tests__/public-type-surface.test.ts +5 -4
- 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__/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 -0
- 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/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 -2
- 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/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
|
@@ -9,6 +9,7 @@ import * as fs from 'fs/promises';
|
|
|
9
9
|
import * as path from 'path';
|
|
10
10
|
import { SpecAcceptanceGate } from '../../gates/acceptance';
|
|
11
11
|
import { log, processIO, type CommandIO, type CommandResult } from '../command-contract';
|
|
12
|
+
import { reportGateDecision, reportGateError } from '../gate-command';
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
export interface AcceptanceOptions {
|
|
@@ -43,38 +44,32 @@ export async function acceptance(
|
|
|
43
44
|
});
|
|
44
45
|
|
|
45
46
|
try {
|
|
46
|
-
|
|
47
|
-
const context = {
|
|
47
|
+
const decision = await gate.evaluate({
|
|
48
48
|
projectPath,
|
|
49
49
|
taskId: options.taskId,
|
|
50
|
-
};
|
|
50
|
+
});
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return
|
|
73
|
-
} catch (error: any) {
|
|
74
|
-
log(io);
|
|
75
|
-
log(io, chalk.red('❌ 验收标准检查出错'));
|
|
76
|
-
log(io, chalk.red(` ${error.message}`));
|
|
77
|
-
return { kind: 'fail', reason: `acceptance gate error: ${error.message}` };
|
|
52
|
+
return reportGateDecision(
|
|
53
|
+
io,
|
|
54
|
+
{
|
|
55
|
+
gateId: 'acceptance',
|
|
56
|
+
label: '验收标准',
|
|
57
|
+
onPass: (r) =>
|
|
58
|
+
r.details
|
|
59
|
+
? [
|
|
60
|
+
chalk.gray(` 通过项: ${r.details.checkedCriteria ?? 0}`),
|
|
61
|
+
chalk.gray(` 总项数: ${r.details.totalCriteria ?? 0}`),
|
|
62
|
+
]
|
|
63
|
+
: [],
|
|
64
|
+
onFail: (r) =>
|
|
65
|
+
r.details?.uncheckedCriteria
|
|
66
|
+
? (r.details.uncheckedCriteria as string[]).map((criteria: string) => chalk.red(` - ${criteria}`))
|
|
67
|
+
: [],
|
|
68
|
+
},
|
|
69
|
+
decision
|
|
70
|
+
);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
return reportGateError(io, 'acceptance', '验收标准', error);
|
|
78
73
|
}
|
|
79
74
|
}
|
|
80
75
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* 工单 23:触发条件与证据检测迁至 core/constraints/context-builder
|
|
6
6
|
* ADR-0001:约束集统一走 getMergedConstraintsConfig 生效集链路(preset/config 禁用/custom/scenes)
|
|
7
7
|
* harness#88:本命令是 trace 记录器的组合根——core 不上行依赖 monitoring,
|
|
8
|
-
*
|
|
8
|
+
* 真实收集器在此经构造参数接线;#139:收集器锚根构造,trace 落点跟 --project-path 走
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import chalk from 'chalk';
|
|
@@ -13,14 +13,15 @@ import * as fs from 'fs';
|
|
|
13
13
|
import * as path from 'path';
|
|
14
14
|
import { ConstraintChecker } from '../../core/constraints/checker';
|
|
15
15
|
import { IRON_LAWS, GUIDELINES, PROMPTS } from '../../core/constraints/definitions';
|
|
16
|
-
import { getMergedConstraintsConfig } from '../../core/effective-constraints';
|
|
16
|
+
import { getMergedConstraintsConfig, constraintsFromMerged } from '../../core/effective-constraints';
|
|
17
17
|
import { buildConstraintContext } from '../../core/constraints/context-builder';
|
|
18
18
|
import { createGitEvidence, type GitEvidence } from '../../core/constraints/git-evidence';
|
|
19
|
+
import { createRunEnv, type RunEnv } from '../../core/constraints/run-env';
|
|
19
20
|
import { detectInjectionDrift } from '../../core/constraints/injection-drift';
|
|
20
21
|
import { GOVERNANCE_HEADING } from '../../core/constraints/injection-writer';
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import { DEFAULT_TRACE_FILE } from '../../types/trace';
|
|
22
|
+
import { TraceCollector } from '../../monitoring/traces';
|
|
23
|
+
import { readJsonl } from '../../utils/jsonl';
|
|
24
|
+
import { DEFAULT_TRACE_FILE, type ExecutionTrace } from '../../types/trace';
|
|
24
25
|
import type { ConstraintResult, ConstraintTrigger } from '../../types/constraint';
|
|
25
26
|
import { log, processIO, type CommandIO, type CommandResult } from '../command-contract';
|
|
26
27
|
|
|
@@ -51,8 +52,8 @@ function logEvidence(
|
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
export interface CheckOptions {
|
|
54
|
-
/**
|
|
55
|
-
preset
|
|
55
|
+
/** 预设名称;**不传 = 按项目 `.harness/config.yml` 的 preset**(CLI 不给缺省值,见 commands/definitions.ts) */
|
|
56
|
+
preset?: string;
|
|
56
57
|
/** 是否只检查暂存文件 */
|
|
57
58
|
staged: boolean;
|
|
58
59
|
/** 触发条件 */
|
|
@@ -66,6 +67,13 @@ export interface CheckOptions {
|
|
|
66
67
|
* 测试据此断言"同一 run 内每条 git 命令至多执行一次"。
|
|
67
68
|
*/
|
|
68
69
|
evidence?: GitEvidence;
|
|
70
|
+
/**
|
|
71
|
+
* 运行级观察面(非 CLI flag;ADR-0023)
|
|
72
|
+
*
|
|
73
|
+
* 缺省 = 本 run 独占一份。注入则与调用方共用同一份上行数据读取,
|
|
74
|
+
* 测试据此断言「同一次运行内同一项目文件至多读一次」。
|
|
75
|
+
*/
|
|
76
|
+
runEnv?: RunEnv;
|
|
69
77
|
}
|
|
70
78
|
|
|
71
79
|
/**
|
|
@@ -76,15 +84,19 @@ export async function check(
|
|
|
76
84
|
io: CommandIO = processIO,
|
|
77
85
|
): Promise<CommandResult> {
|
|
78
86
|
log(io, chalk.blue('🔍 检查约束...'));
|
|
79
|
-
log(io, chalk.gray(`预设: ${options.preset}`));
|
|
87
|
+
log(io, chalk.gray(`预设: ${options.preset ?? '(按 config.yml,缺省 standard)'}`));
|
|
80
88
|
|
|
81
89
|
try {
|
|
82
90
|
const projectPath = options.projectPath || process.cwd();
|
|
91
|
+
// 一次 run 一份证据与观察面(#87 / ADR-0023):入口构造,沿生效集、context、checker 向下传
|
|
92
|
+
const evidence = options.evidence ?? createGitEvidence(projectPath);
|
|
93
|
+
const runEnv = options.runEnv ?? createRunEnv(projectPath);
|
|
83
94
|
|
|
84
95
|
// 生效约束集(ADR-0001):内置 → preset → config.yml 禁用 → custom 追加 → scenes 过滤。
|
|
85
96
|
// --preset 仅在没有项目自定义配置时覆盖 config.yml 的 preset(工单 23 语义:
|
|
86
97
|
// 项目自定义配置优先于 CLI 预设),优先级规则收在 getMergedConstraintsConfig 一处。
|
|
87
|
-
|
|
98
|
+
// CLI 不给 -p 缺省值:没传 = 尊重 config.yml(ADR-0023 步骤 4.5,缺省值曾让两者不可区分)
|
|
99
|
+
const merged = getMergedConstraintsConfig(runEnv, { preset: options.preset });
|
|
88
100
|
if (merged.custom.length > 0) {
|
|
89
101
|
log(io, chalk.gray(`自定义约束: ${merged.custom.length} 条`));
|
|
90
102
|
}
|
|
@@ -98,12 +110,13 @@ export async function check(
|
|
|
98
110
|
|
|
99
111
|
// 构建上下文(工单 23:触发条件与证据检测收敛至 core/constraints/context-builder)
|
|
100
112
|
// #87:一次 run 一份 git 证据——context-builder 与 checker 层共用同一实例
|
|
101
|
-
|
|
113
|
+
// ADR-0023:一次 run 一份运行级观察面——配置、源根探测、trace 证据探测全部共用同一份读取
|
|
102
114
|
const context = await buildConstraintContext({
|
|
103
115
|
projectPath: options.projectPath,
|
|
104
116
|
staged: options.staged,
|
|
105
117
|
trigger: options.trigger,
|
|
106
118
|
evidence,
|
|
119
|
+
runEnv,
|
|
107
120
|
});
|
|
108
121
|
const changedFiles = context.changedFiles ?? [];
|
|
109
122
|
if (changedFiles.length > 0) {
|
|
@@ -113,8 +126,9 @@ export async function check(
|
|
|
113
126
|
|
|
114
127
|
// 执行三层检查(per-request 传 customConfig,避免单例状态污染;证据同 run 同源)
|
|
115
128
|
// trace 记录器经构造参数接线(harness#88):一次命令一个 checker 实例
|
|
116
|
-
|
|
117
|
-
const
|
|
129
|
+
// #139:收集器锚根构造——不传 projectPath 时 trace 会落进调用方 cwd,B 侧读不到
|
|
130
|
+
const checker = new ConstraintChecker(new TraceCollector({ projectPath }));
|
|
131
|
+
const result = await checker.checkConstraints(context, merged, evidence, runEnv);
|
|
118
132
|
|
|
119
133
|
// 输出结果
|
|
120
134
|
log(io);
|
|
@@ -183,7 +197,8 @@ export async function check(
|
|
|
183
197
|
// 注入漂移校验(ADR-0001 决策 7):黄色警告块,不改 exit code、不影响门禁结果。
|
|
184
198
|
// 无漂移/未注入零输出;漂移检测自身异常静默吞掉,绝不影响 check。
|
|
185
199
|
try {
|
|
186
|
-
|
|
200
|
+
// 生效集直接用本 run 那一份:一遍算完,且比对对象就是本次实际执法的规则集(ADR-0023 步骤 4.5)
|
|
201
|
+
const drift = detectInjectionDrift(runEnv, undefined, constraintsFromMerged(merged));
|
|
187
202
|
if (drift.hasDrift) {
|
|
188
203
|
log(io);
|
|
189
204
|
log(io, chalk.yellow(`⚠️ 检测到 ${drift.injectionFile ?? '治理文档'} 约束注入漂移(仅警告,不阻断):`));
|
|
@@ -221,6 +236,9 @@ export async function check(
|
|
|
221
236
|
}
|
|
222
237
|
}
|
|
223
238
|
|
|
239
|
+
/** 智能提示阈值:trace 累计条数首次达到此数才提示跑 status(判定只要「够不够」,不要总数) */
|
|
240
|
+
const TRACE_HINT_THRESHOLD = 50;
|
|
241
|
+
|
|
224
242
|
/**
|
|
225
243
|
* 智能提示:检查是否需要提示用户下一步操作
|
|
226
244
|
*/
|
|
@@ -228,8 +246,13 @@ async function getSmartHint(projectPath: string): Promise<string | null> {
|
|
|
228
246
|
const tracesPath = path.join(projectPath, DEFAULT_TRACE_FILE);
|
|
229
247
|
const statePath = path.join(projectPath, '.harness', '.state.json');
|
|
230
248
|
|
|
231
|
-
//
|
|
232
|
-
|
|
249
|
+
// 只读够 TRACE_HINT_THRESHOLD 行即停(坏行照旧占位,条数口径与改前的纯计数逐字一致)——
|
|
250
|
+
// traces.log 是 append-only 无上限文件,为一个比较符整读不成立
|
|
251
|
+
// 计数去向:豁免(harness#100)——本消费面只输出「够不够」的提示行,没有可挂坏行计数的输出位
|
|
252
|
+
const { records, skippedLines } = readJsonl<ExecutionTrace>(tracesPath, 'skip', {
|
|
253
|
+
head: TRACE_HINT_THRESHOLD,
|
|
254
|
+
});
|
|
255
|
+
const traceCount = records.length + skippedLines;
|
|
233
256
|
if (traceCount === 0) {
|
|
234
257
|
return null;
|
|
235
258
|
}
|
|
@@ -246,8 +269,8 @@ async function getSmartHint(projectPath: string): Promise<string | null> {
|
|
|
246
269
|
|
|
247
270
|
const hints: string[] = [];
|
|
248
271
|
|
|
249
|
-
// 条件 1:
|
|
250
|
-
if (traceCount >=
|
|
272
|
+
// 条件 1: 记录数首次达到阈值
|
|
273
|
+
if (traceCount >= TRACE_HINT_THRESHOLD && !state.shownHints.includes('trace_50')) {
|
|
251
274
|
hints.push('📊 记录已足够,运行 harness status 查看统计');
|
|
252
275
|
state.shownHints.push('trace_50');
|
|
253
276
|
}
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
* 退出码映射收敛在 bin 一处。
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { createCommandGate,
|
|
13
|
+
import { createCommandGate, DEFAULT_COMMAND_BLACKLIST, type CommandBlacklistRule } from '../../gates';
|
|
14
14
|
import { log, logError, processIO, type CommandIO, type CommandResult } from '../command-contract';
|
|
15
|
+
import { gateCommandResult } from '../gate-command';
|
|
15
16
|
|
|
16
17
|
export interface CommandCheckOptions {
|
|
17
18
|
level?: boolean;
|
|
18
19
|
list?: boolean;
|
|
19
20
|
json?: boolean;
|
|
20
|
-
strict?: boolean;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -65,11 +65,14 @@ export async function executeCommand(
|
|
|
65
65
|
return { kind: 'usage-error', reason: '缺少要检查的命令参数' };
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
const gate = createCommandGate(
|
|
69
|
-
|
|
68
|
+
const gate = createCommandGate();
|
|
69
|
+
// 命令门禁只判命令串、不读项目根;GateContext 仍要求项目根——本命令无 -p 旗帜,取真实 cwd
|
|
70
|
+
const decision = await gate.evaluate({ projectPath: process.cwd(), command: cmd });
|
|
71
|
+
const result = decision.result;
|
|
70
72
|
|
|
71
73
|
if (options.level) {
|
|
72
|
-
|
|
74
|
+
// 等级取自本命令创建的这台实例:与默认分支同一来源,配置不再中途丢失(#135)
|
|
75
|
+
const level = gate.getRiskLevel(cmd);
|
|
73
76
|
if (options.json) {
|
|
74
77
|
log(io, JSON.stringify({ level, command: cmd }));
|
|
75
78
|
} else {
|
|
@@ -97,7 +100,5 @@ export async function executeCommand(
|
|
|
97
100
|
log(io, result.passed ? `\x1b[32m✓\x1b[0m ${result.message}` : `\x1b[31m✗\x1b[0m ${result.message}`);
|
|
98
101
|
}
|
|
99
102
|
|
|
100
|
-
return
|
|
101
|
-
? { kind: 'ok' }
|
|
102
|
-
: { kind: 'fail', reason: `command gate denied: ${result.message}` };
|
|
103
|
+
return gateCommandResult('command', decision);
|
|
103
104
|
}
|
|
@@ -40,7 +40,7 @@ import { getConstraint } from '../../core/constraints/definitions';
|
|
|
40
40
|
import { renderConstraintsSection, CONSTRAINTS_START_MARKER, CONSTRAINTS_END_MARKER } from '../../core/constraints/injection-renderer';
|
|
41
41
|
import { replaceStandaloneRange, resolveInjectionTarget } from '../../core/constraints/injection-writer';
|
|
42
42
|
import { getEffectiveConstraints } from '../../core/effective-constraints';
|
|
43
|
-
import {
|
|
43
|
+
import { isConstraintRetired, ProjectConfigLoader } from '../../core/project-config-loader';
|
|
44
44
|
import { getHarnessPackageVersion } from '../../utils/package-version';
|
|
45
45
|
import { FileKnowledgeStore } from '../../knowledge/store';
|
|
46
46
|
import type { KnowledgeEntry } from '../../knowledge/types';
|
|
@@ -97,8 +97,14 @@ interface RetireTargetInfo {
|
|
|
97
97
|
|
|
98
98
|
/**
|
|
99
99
|
* 查找约束定义(内置 definitions + 项目 custom-constraints)
|
|
100
|
+
*
|
|
101
|
+
* loader 由调用方给(一次退役一份观察面,见 retireConstraint):本函数只读它的装载结果,
|
|
102
|
+
* 不再自造 ProjectConfigLoader。
|
|
100
103
|
*/
|
|
101
|
-
function findRetireTarget(
|
|
104
|
+
function findRetireTarget(
|
|
105
|
+
loader: ProjectConfigLoader,
|
|
106
|
+
id: string
|
|
107
|
+
): RetireTargetInfo | undefined {
|
|
102
108
|
const builtIn = getConstraint(id);
|
|
103
109
|
if (builtIn) {
|
|
104
110
|
return {
|
|
@@ -112,8 +118,6 @@ function findRetireTarget(projectRoot: string, id: string): RetireTargetInfo | u
|
|
|
112
118
|
};
|
|
113
119
|
}
|
|
114
120
|
|
|
115
|
-
const loader = new ProjectConfigLoader(projectRoot);
|
|
116
|
-
loader.load();
|
|
117
121
|
const custom = loader.getCustomConstraints()[id];
|
|
118
122
|
if (custom) {
|
|
119
123
|
const level = custom.level || 'guideline';
|
|
@@ -132,52 +136,20 @@ function findRetireTarget(projectRoot: string, id: string): RetireTargetInfo | u
|
|
|
132
136
|
}
|
|
133
137
|
|
|
134
138
|
/**
|
|
135
|
-
*
|
|
139
|
+
* YAML 条目的读-改-写单点(harness#137)
|
|
136
140
|
*
|
|
137
|
-
*
|
|
141
|
+
* 内置与 custom 两处退役落点原本是两段同型的读-改-写,只差键路径与 patch 内容。
|
|
142
|
+
* js-yaml 不保留注释:原文件含注释行时重写会丢失,console 说明(`label` 是给用户看的
|
|
143
|
+
* 文件名,与合并前两处逐字一致)。落盘字节由 `__tests__/constraints-retire.test.ts`
|
|
144
|
+
* 的逐字节冻结用例钉住——合并属内部重构,对外产物不得漂移。
|
|
138
145
|
*/
|
|
139
|
-
function
|
|
140
|
-
|
|
146
|
+
function setYamlEntry(
|
|
147
|
+
filePath: string,
|
|
148
|
+
label: string,
|
|
149
|
+
section: string,
|
|
141
150
|
id: string,
|
|
142
|
-
|
|
151
|
+
patch: Record<string, unknown>
|
|
143
152
|
): void {
|
|
144
|
-
const configPath = path.join(projectRoot, '.harness', 'config.yml');
|
|
145
|
-
|
|
146
|
-
let raw: Record<string, unknown> = {};
|
|
147
|
-
let hadComments = false;
|
|
148
|
-
if (fs.existsSync(configPath)) {
|
|
149
|
-
const original = fs.readFileSync(configPath, 'utf-8');
|
|
150
|
-
hadComments = original.split('\n').some(l => l.trimStart().startsWith('#'));
|
|
151
|
-
raw = (yaml.load(original) as Record<string, unknown>) ?? {};
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const constraints = (raw.constraints ?? {}) as Record<string, unknown>;
|
|
155
|
-
const prev = (constraints[id] ?? {}) as Record<string, unknown>;
|
|
156
|
-
constraints[id] = { ...prev, enabled: false, retired: retiredMeta };
|
|
157
|
-
raw.constraints = constraints;
|
|
158
|
-
|
|
159
|
-
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
160
|
-
fs.writeFileSync(configPath, yaml.dump(raw, { lineWidth: 120 }), 'utf-8');
|
|
161
|
-
|
|
162
|
-
if (hadComments) {
|
|
163
|
-
console.log(chalk.yellow(' ⚠️ config.yml 已重写:js-yaml 不保留原文件注释'));
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* 写 custom-constraints.yml 退役段(studio#82 D6 统一落点)
|
|
169
|
-
*
|
|
170
|
-
* 在 custom_constraints.<id> 条目内追加 retired 元数据,保留规则原文。
|
|
171
|
-
* js-yaml 不保留注释:原文件含注释行时重写会丢失,console 说明。
|
|
172
|
-
*/
|
|
173
|
-
function writeCustomRetireYml(
|
|
174
|
-
projectRoot: string,
|
|
175
|
-
fileName: string,
|
|
176
|
-
id: string,
|
|
177
|
-
retiredMeta: { at: string; reason: string; stats: { total: number; fail: number; failRate: number } }
|
|
178
|
-
): void {
|
|
179
|
-
const filePath = path.join(projectRoot, '.harness', fileName);
|
|
180
|
-
|
|
181
153
|
let raw: Record<string, unknown> = {};
|
|
182
154
|
let hadComments = false;
|
|
183
155
|
if (fs.existsSync(filePath)) {
|
|
@@ -186,16 +158,16 @@ function writeCustomRetireYml(
|
|
|
186
158
|
raw = (yaml.load(original) as Record<string, unknown>) ?? {};
|
|
187
159
|
}
|
|
188
160
|
|
|
189
|
-
const
|
|
190
|
-
const prev =
|
|
191
|
-
|
|
192
|
-
raw
|
|
161
|
+
const entries = (raw[section] ?? {}) as Record<string, unknown>;
|
|
162
|
+
const prev = (entries[id] ?? {}) as Record<string, unknown>;
|
|
163
|
+
entries[id] = { ...prev, ...patch };
|
|
164
|
+
raw[section] = entries;
|
|
193
165
|
|
|
194
166
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
195
167
|
fs.writeFileSync(filePath, yaml.dump(raw, { lineWidth: 120 }), 'utf-8');
|
|
196
168
|
|
|
197
169
|
if (hadComments) {
|
|
198
|
-
console.log(chalk.yellow(
|
|
170
|
+
console.log(chalk.yellow(` ⚠️ ${label} 已重写:js-yaml 不保留原文件注释`));
|
|
199
171
|
}
|
|
200
172
|
}
|
|
201
173
|
|
|
@@ -293,7 +265,13 @@ export function retireConstraint(
|
|
|
293
265
|
const iso = now.toISOString();
|
|
294
266
|
const reason = options.reason ?? '';
|
|
295
267
|
|
|
296
|
-
|
|
268
|
+
// 一次退役一份观察面(ADR-0023 决策 2):定义查找、already_retired 判定与 custom 文件名
|
|
269
|
+
// 解析共用这一份装载结果。此前同一次调用 new 了 2–3 枚加载器、各带一次 load()(harness#137)。
|
|
270
|
+
// 只覆盖写盘**之前**的读取:写盘后 syncGovernanceInjection 必须读到新状态,另起观察面。
|
|
271
|
+
const loader = new ProjectConfigLoader(projectRoot);
|
|
272
|
+
loader.load();
|
|
273
|
+
|
|
274
|
+
const target = findRetireTarget(loader, id);
|
|
297
275
|
const emptyStats = { total: 0, fail: 0, failRate: 0 };
|
|
298
276
|
const landing: RetireResult['landing'] =
|
|
299
277
|
target?.source === 'custom' ? 'custom-constraints.yml' : 'config.yml';
|
|
@@ -301,17 +279,12 @@ export function retireConstraint(
|
|
|
301
279
|
return { id, status: 'unknown_id', isIronLaw: false, landing, stats: emptyStats, injectionSynced: false };
|
|
302
280
|
}
|
|
303
281
|
|
|
304
|
-
//
|
|
305
|
-
// custom 看 yml 条目 retired
|
|
306
|
-
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
loader.load();
|
|
311
|
-
if (loader.getCustomConstraints()[id]?.retired || existing?.enabled === false) {
|
|
312
|
-
return { id, status: 'already_retired', isIronLaw: target.isIronLaw, landing, stats: emptyStats, injectionSynced: false };
|
|
313
|
-
}
|
|
314
|
-
} else if (existing?.enabled === false) {
|
|
282
|
+
// 已退役保护:判定单点在 core/project-config-loader isConstraintRetired
|
|
283
|
+
// (内置看 config.yml enabled:false;custom 看 yml 条目 retired 元数据,
|
|
284
|
+
// 历史落点 config.yml enabled:false 同样保护)
|
|
285
|
+
const disabledInConfig = loader.getConfig().constraints?.[id]?.enabled === false;
|
|
286
|
+
const customDef = target.source === 'custom' ? loader.getCustomConstraints()[id] : undefined;
|
|
287
|
+
if (isConstraintRetired(customDef, disabledInConfig)) {
|
|
315
288
|
return { id, status: 'already_retired', isIronLaw: target.isIronLaw, landing, stats: emptyStats, injectionSynced: false };
|
|
316
289
|
}
|
|
317
290
|
|
|
@@ -327,14 +300,26 @@ export function retireConstraint(
|
|
|
327
300
|
failRate: evaluated > 0 ? (usage!.fail / evaluated) : 0,
|
|
328
301
|
};
|
|
329
302
|
|
|
330
|
-
// 1. 落盘退役(custom → yml 条目 retired 段;内置 → config.yml
|
|
303
|
+
// 1. 落盘退役(custom → yml 条目 retired 段;内置 → config.yml enabled:false + retired 段,
|
|
304
|
+
// 两处原文均保留)
|
|
305
|
+
const retiredMeta = { at: iso, reason, stats };
|
|
331
306
|
if (target.source === 'custom') {
|
|
332
|
-
const loader = new ProjectConfigLoader(projectRoot);
|
|
333
|
-
loader.load();
|
|
334
307
|
const customFile = loader.getConfig().custom_constraints_file ?? 'custom-constraints.yml';
|
|
335
|
-
|
|
308
|
+
setYamlEntry(
|
|
309
|
+
path.join(projectRoot, '.harness', customFile),
|
|
310
|
+
'custom-constraints.yml',
|
|
311
|
+
'custom_constraints',
|
|
312
|
+
id,
|
|
313
|
+
{ retired: retiredMeta }
|
|
314
|
+
);
|
|
336
315
|
} else {
|
|
337
|
-
|
|
316
|
+
setYamlEntry(
|
|
317
|
+
path.join(projectRoot, '.harness', 'config.yml'),
|
|
318
|
+
'config.yml',
|
|
319
|
+
'constraints',
|
|
320
|
+
id,
|
|
321
|
+
{ enabled: false, retired: retiredMeta }
|
|
322
|
+
);
|
|
338
323
|
}
|
|
339
324
|
|
|
340
325
|
// 2. KnowledgeStore
|
|
@@ -454,10 +439,12 @@ export async function runRetireInteractive(
|
|
|
454
439
|
selectedIds = [...new Set(selectedIds)];
|
|
455
440
|
}
|
|
456
441
|
|
|
457
|
-
// 逐条收集 reason + iron
|
|
442
|
+
// 逐条收集 reason + iron 二次确认(一次交互一份装载结果:候选到确认之间不写盘)
|
|
443
|
+
const planLoader = new ProjectConfigLoader(projectRoot);
|
|
444
|
+
planLoader.load();
|
|
458
445
|
const plan: { id: string; reason: string; source: RetireTargetInfo['source'] }[] = [];
|
|
459
446
|
for (const id of selectedIds) {
|
|
460
|
-
const target = findRetireTarget(
|
|
447
|
+
const target = findRetireTarget(planLoader, id);
|
|
461
448
|
if (!target) {
|
|
462
449
|
console.log(chalk.red(`❌ ${id}: 约束不存在,跳过`));
|
|
463
450
|
continue;
|
|
@@ -9,6 +9,7 @@ import * as fs from 'fs/promises';
|
|
|
9
9
|
import * as path from 'path';
|
|
10
10
|
import { ContractGate } from '../../gates/contract';
|
|
11
11
|
import { log, processIO, type CommandIO, type CommandResult } from '../command-contract';
|
|
12
|
+
import { reportGateDecision, reportGateError } from '../gate-command';
|
|
12
13
|
|
|
13
14
|
export interface ContractOptions {
|
|
14
15
|
/** 项目路径 */
|
|
@@ -52,55 +53,51 @@ export async function contract(
|
|
|
52
53
|
});
|
|
53
54
|
|
|
54
55
|
try {
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
log(io, chalk.red(` - ${error}`));
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
if (result.details?.breakingChanges) {
|
|
86
|
-
log(io);
|
|
87
|
-
log(io, chalk.red('破坏性变更:'));
|
|
88
|
-
(result.details.breakingChanges as any[]).forEach((change: any) => {
|
|
89
|
-
log(io, chalk.red(` - ${change.type}: ${change.path}`));
|
|
90
|
-
if (change.description) {
|
|
91
|
-
log(io, chalk.gray(` ${change.description}`));
|
|
56
|
+
const decision = await gate.evaluate({ projectPath });
|
|
57
|
+
|
|
58
|
+
return reportGateDecision(
|
|
59
|
+
io,
|
|
60
|
+
{
|
|
61
|
+
gateId: 'contract',
|
|
62
|
+
label: '契约门控',
|
|
63
|
+
onPass: (r) => {
|
|
64
|
+
if (!r.details) return [];
|
|
65
|
+
const lines = [chalk.gray(` Schema 有效: ✅`)];
|
|
66
|
+
if (r.details.endpoints) {
|
|
67
|
+
lines.push(chalk.gray(` 端点数: ${r.details.endpoints}`));
|
|
68
|
+
}
|
|
69
|
+
if (r.details.breakingChanges === false) {
|
|
70
|
+
lines.push(chalk.gray(` 破坏性变更: 无`));
|
|
71
|
+
}
|
|
72
|
+
return lines;
|
|
73
|
+
},
|
|
74
|
+
onFail: (r) => {
|
|
75
|
+
const lines: string[] = [];
|
|
76
|
+
|
|
77
|
+
if (r.details?.errors) {
|
|
78
|
+
lines.push('', chalk.red('验证错误:'));
|
|
79
|
+
(r.details.errors as string[]).forEach((issue: string) => {
|
|
80
|
+
lines.push(chalk.red(` - ${issue}`));
|
|
81
|
+
});
|
|
92
82
|
}
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
83
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
84
|
+
if (r.details?.breakingChanges) {
|
|
85
|
+
lines.push('', chalk.red('破坏性变更:'));
|
|
86
|
+
(r.details.breakingChanges as any[]).forEach((change: any) => {
|
|
87
|
+
lines.push(chalk.red(` - ${change.type}: ${change.path}`));
|
|
88
|
+
if (change.description) {
|
|
89
|
+
lines.push(chalk.gray(` ${change.description}`));
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return lines;
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
decision
|
|
98
|
+
);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
return reportGateError(io, 'contract', '契约门控', error);
|
|
104
101
|
}
|
|
105
102
|
}
|
|
106
103
|
|
|
@@ -11,8 +11,12 @@
|
|
|
11
11
|
* 子命令别名是数据(aliases),实参编组归各命令模块的具名导出
|
|
12
12
|
* (那才是它的 interface/测试面);保证 --help/--version 懒加载不被破坏;
|
|
13
13
|
* 注册表完整性断言(引用实现可解析)在 __tests__/registry.test.ts 构建/测试期校验。
|
|
14
|
+
* - 唯一例外 import:`utils/numeric-flag` 纯函数解析器(harness#154 口径条目指名的
|
|
15
|
+
* 数值旗帜唯一解析器)——非命令实现、零 IO,不破坏懒加载。
|
|
14
16
|
*/
|
|
15
17
|
|
|
18
|
+
import { requireNumericFlag } from '../../utils/numeric-flag';
|
|
19
|
+
|
|
16
20
|
/**
|
|
17
21
|
* 命令 CLI 选项元数据(直接映射 commander `.option()`)
|
|
18
22
|
*/
|
|
@@ -99,7 +103,9 @@ export const COMMAND_DEFINITIONS: CommandDefinition[] = [
|
|
|
99
103
|
command: 'check',
|
|
100
104
|
description: '检查铁律是否满足',
|
|
101
105
|
options: [
|
|
102
|
-
|
|
106
|
+
// 不给缺省值:「没传 -p」与「传了 standard」必须可区分,否则生效集侧的覆盖规则恒触发、
|
|
107
|
+
// config.yml 的 preset 静默失效(漂移检测侧按 config.yml 算,两边就会稳定对不上)
|
|
108
|
+
{ flags: '-p, --preset <preset>', description: '预设名称(缺省按项目 config.yml)' },
|
|
103
109
|
{ flags: '-s, --staged', description: '只检查暂存文件', defaultValue: false },
|
|
104
110
|
{ flags: '-t, --trigger <trigger>', description: '触发条件' },
|
|
105
111
|
{ flags: '--project-path <path>', description: '项目路径' },
|
|
@@ -143,10 +149,10 @@ export const COMMAND_DEFINITIONS: CommandDefinition[] = [
|
|
|
143
149
|
options: [
|
|
144
150
|
{ flags: '-p, --preset <preset>', description: '预设名称 (strict/standard/relaxed)', defaultValue: 'standard' },
|
|
145
151
|
{ flags: '-g, --governance <level>', description: '治理级别 (minimal/standard/strict)' },
|
|
146
|
-
{ flags: '-t, --type <type>', description: '项目类型 (node-api/nextjs-app/python-api/custom)' },
|
|
147
152
|
{ flags: '--project-path <path>', description: '项目路径' },
|
|
148
153
|
{ flags: '--no-git-hooks', description: '不创建 Git hooks' },
|
|
149
|
-
{ flags: '--
|
|
154
|
+
{ flags: '--ci <platform>', description: '服务端 CI 接线平台 (github/gitlab/none);none = 不创建任何 CI 文件(治理 CI 面亦不建),缺省按 .harness/config.yml 的 ci.platform' },
|
|
155
|
+
{ flags: '--no-github-actions', description: '不创建 GitHub Actions(已废弃:等价 --ci none)' },
|
|
150
156
|
{ flags: '--print-snippets', description: '只输出代码片段,不创建文件' },
|
|
151
157
|
],
|
|
152
158
|
action: { module: 'init', export: 'init' },
|
|
@@ -331,9 +337,9 @@ export const COMMAND_DEFINITIONS: CommandDefinition[] = [
|
|
|
331
337
|
projectPath: options.projectPath,
|
|
332
338
|
export: options.export,
|
|
333
339
|
json: options.json,
|
|
334
|
-
zeroInterceptMin:
|
|
335
|
-
noiseFailRate:
|
|
336
|
-
noiseMinTotal:
|
|
340
|
+
zeroInterceptMin: requireNumericFlag('--zero-intercept-min', options.zeroInterceptMin as string | undefined, 'int'),
|
|
341
|
+
noiseFailRate: requireNumericFlag('--noise-fail-rate', options.noiseFailRate as string | undefined, 'float'),
|
|
342
|
+
noiseMinTotal: requireNumericFlag('--noise-min-total', options.noiseMinTotal as string | undefined, 'int'),
|
|
337
343
|
}],
|
|
338
344
|
},
|
|
339
345
|
{
|