@dommaker/harness 1.7.0 → 1.8.1
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 +44 -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 +19 -3
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/check.js +36 -22
- 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/status.d.ts +8 -0
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +5 -7
- package/dist/cli/commands/status.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/cli/state-io.d.ts +34 -0
- package/dist/cli/state-io.d.ts.map +1 -0
- package/dist/cli/state-io.js +71 -0
- package/dist/cli/state-io.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 +19 -1
- package/dist/hooks/pipeline.d.ts.map +1 -1
- package/dist/hooks/pipeline.js +42 -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 +25 -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/__tests__/state-io.test.ts +50 -0
- package/src/cli/commands/CONTEXT.md +30 -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 +170 -0
- package/src/cli/commands/__tests__/check-skip-output.test.ts +4 -1
- package/src/cli/commands/__tests__/check.test.ts +63 -44
- 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__/status-extra.test.ts +25 -8
- package/src/cli/commands/__tests__/status.test.ts +46 -18
- 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 +60 -35
- 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/status.ts +12 -7
- 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/cli/state-io.ts +53 -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 +133 -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 +51 -6
- package/src/hooks/registry.ts +31 -12
- package/src/hooks/types.ts +26 -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,8 +9,9 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { describe, it, expect } from '@jest/globals';
|
|
12
|
+
import { join } from 'path';
|
|
12
13
|
import { contextDocSync } from '../context-doc-sync';
|
|
13
|
-
import { buildCheckEnv } from '../types';
|
|
14
|
+
import { buildCheckEnv, normalizeCheckOutcome } from '../types';
|
|
14
15
|
import { createProjectFixture } from '../../../../test-setup/project-fixture';
|
|
15
16
|
import type { ConstraintContext } from '../../../../types/constraint';
|
|
16
17
|
|
|
@@ -65,9 +66,13 @@ describe('context_doc_sync — 判定', () => {
|
|
|
65
66
|
expect(await evaluate(dir)).toBe(true);
|
|
66
67
|
});
|
|
67
68
|
|
|
68
|
-
it('任一目录缺 CONTEXT.md → fail', async () => {
|
|
69
|
+
it('任一目录缺 CONTEXT.md → fail,证据点名缺的那一个(ADR-0016 补迁)', async () => {
|
|
69
70
|
const dir = setupDir('one-missing', CTX_FILES(true, ['src', 'bin']), ['src']);
|
|
70
|
-
|
|
71
|
+
const outcome = normalizeCheckOutcome(await evaluate(dir));
|
|
72
|
+
expect(outcome.satisfied).toBe(false);
|
|
73
|
+
expect(outcome.skipped).toBe(false);
|
|
74
|
+
expect(outcome.evidence.join('\n')).toContain(join('bin', 'CONTEXT.md'));
|
|
75
|
+
expect(outcome.evidence.join('\n')).not.toContain(join('src', 'CONTEXT.md'));
|
|
71
76
|
});
|
|
72
77
|
|
|
73
78
|
it('配置解析失败 → skip(不炸不报)', async () => {
|
|
@@ -18,12 +18,13 @@ import {
|
|
|
18
18
|
} from '../governance-presence';
|
|
19
19
|
import { detectInjectionDrift } from '../../injection-drift';
|
|
20
20
|
import { createProjectFixture, writeProjectConfig } from '../../../../test-setup/project-fixture';
|
|
21
|
-
import type
|
|
21
|
+
import { normalizeCheckOutcome, type CheckEnv } from '../types';
|
|
22
|
+
import { createRunEnv } from '../../run-env';
|
|
22
23
|
|
|
23
24
|
function makeEnv(projectPath: string): CheckEnv {
|
|
24
25
|
return {
|
|
26
|
+
...createRunEnv(projectPath),
|
|
25
27
|
context: { operation: 'commit', projectPath },
|
|
26
|
-
projectPath,
|
|
27
28
|
stagedDiff: async () => '',
|
|
28
29
|
stagedDiffNames: async () => '',
|
|
29
30
|
srcScan: () => [],
|
|
@@ -87,12 +88,20 @@ describe('governance_presence checker', () => {
|
|
|
87
88
|
expect(await governancePresence.evaluate(makeEnv(tempDir))).toBe(true);
|
|
88
89
|
});
|
|
89
90
|
|
|
90
|
-
|
|
91
|
+
/** 判定与证据的统一读法(harness#119/ADR-0016:布尔与 CheckDetail 两种形状同一断言) */
|
|
92
|
+
const outcomeOf = async (projectPath: string) =>
|
|
93
|
+
normalizeCheckOutcome(await governancePresence.evaluate(makeEnv(projectPath)));
|
|
94
|
+
|
|
95
|
+
it('两处都没有治理契约 → fail,证据点名两处落点与修复入口(不再走 stderr 侧信道)', async () => {
|
|
91
96
|
writeConfig();
|
|
92
97
|
fs.writeFileSync(path.join(tempDir, 'AGENTS.md'), '# AGENTS.md\n\n只有机器生成内容\n');
|
|
93
98
|
fs.writeFileSync(path.join(tempDir, 'CLAUDE.md'), '# CLAUDE.md\n\n@AGENTS.md\n');
|
|
94
|
-
|
|
95
|
-
expect(
|
|
99
|
+
const outcome = await outcomeOf(tempDir);
|
|
100
|
+
expect(outcome.satisfied).toBe(false);
|
|
101
|
+
expect(outcome.evidence.join('\n')).toContain('治理契约');
|
|
102
|
+
expect(outcome.evidence.join('\n')).toContain('harness init');
|
|
103
|
+
// ADR-0016:证据只有一个出口。侧信道留着会让 CLI 结构化输出与 trace 两头口径不一致
|
|
104
|
+
expect(errorSpy).not.toHaveBeenCalled();
|
|
96
105
|
});
|
|
97
106
|
|
|
98
107
|
it('PRESERVE:governance 段为空(被掏空)且 CLAUDE.md 无治理块 → fail', async () => {
|
|
@@ -101,7 +110,7 @@ describe('governance_presence checker', () => {
|
|
|
101
110
|
path.join(tempDir, 'AGENTS.md'),
|
|
102
111
|
'# AGENTS.md\n\n<!-- PRESERVE:governance -->\n\n<!-- /PRESERVE:governance -->\n'
|
|
103
112
|
);
|
|
104
|
-
expect(await
|
|
113
|
+
expect((await outcomeOf(tempDir)).satisfied).toBe(false);
|
|
105
114
|
});
|
|
106
115
|
|
|
107
116
|
it('PRESERVE:governance 标记未闭合视为不在场 → fail', async () => {
|
|
@@ -110,7 +119,7 @@ describe('governance_presence checker', () => {
|
|
|
110
119
|
path.join(tempDir, 'AGENTS.md'),
|
|
111
120
|
'# AGENTS.md\n\n<!-- PRESERVE:governance -->\n## Governance Rules\n内容\n'
|
|
112
121
|
);
|
|
113
|
-
expect(await
|
|
122
|
+
expect((await outcomeOf(tempDir)).satisfied).toBe(false);
|
|
114
123
|
});
|
|
115
124
|
});
|
|
116
125
|
|
|
@@ -12,11 +12,12 @@ import {
|
|
|
12
12
|
containsHardcodedCredential,
|
|
13
13
|
} from '../no-hardcoded-credentials';
|
|
14
14
|
import type { CheckEnv } from '../types';
|
|
15
|
+
import { createRunEnv } from '../../run-env';
|
|
15
16
|
|
|
16
17
|
function makeEnv(stagedDiff: string): CheckEnv {
|
|
17
18
|
return {
|
|
19
|
+
...createRunEnv('/nonexistent'),
|
|
18
20
|
context: { operation: 'commit', projectPath: '/nonexistent' },
|
|
19
|
-
projectPath: '/nonexistent',
|
|
20
21
|
stagedDiff: async () => stagedDiff,
|
|
21
22
|
stagedDiffNames: async () => '',
|
|
22
23
|
srcScan: () => [],
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
*
|
|
18
18
|
* 例外:「有表格但零条目」= 文档被清空,判违规(历史门,此前靠 Step 2 兜,现显式化)。
|
|
19
19
|
*
|
|
20
|
-
*
|
|
20
|
+
* 覆盖/漏登判定不在本文件实现:全量对照(解析文档 + 代码实况 + 覆盖/幽灵)由
|
|
21
|
+
* capabilities-reconcile 一次算好并与 docs_freshness 共用(ADR-0009 + ADR-0023 决策 4),
|
|
22
|
+
* 本文件只按导出的唯一覆盖规则 `isCoveredByEntries` 算「本次变更」那一维(增量清单属 git 证据)。
|
|
21
23
|
* 目录条目(以 / 结尾)前缀匹配,文件条目精确匹配或路径边界后缀匹配;
|
|
22
24
|
* module 模式下目录条目参与覆盖,未覆盖文件按源码根下第一级子目录聚合。
|
|
23
25
|
*
|
|
@@ -28,12 +30,15 @@
|
|
|
28
30
|
* 不计 pass/fail,避免在未采用约定的项目上全量误报。
|
|
29
31
|
*/
|
|
30
32
|
|
|
31
|
-
import { existsSync
|
|
33
|
+
import { existsSync } from 'fs';
|
|
32
34
|
import { join } from 'path';
|
|
33
|
-
import { isCapabilityListingFormat } from '../capabilities-parser';
|
|
34
35
|
import { getCapabilitiesMode } from '../../project-config-loader';
|
|
35
|
-
import {
|
|
36
|
-
|
|
36
|
+
import {
|
|
37
|
+
collectPopulationFiles,
|
|
38
|
+
isCoveredByEntries,
|
|
39
|
+
significantCodeChanges,
|
|
40
|
+
} from '../capabilities-reconcile';
|
|
41
|
+
import { CAPABILITIES_FILE_REL } from '../run-env';
|
|
37
42
|
import { formatEvidence, type ConstraintCheck } from './types';
|
|
38
43
|
|
|
39
44
|
export const capabilitySync: ConstraintCheck = {
|
|
@@ -41,41 +46,35 @@ export const capabilitySync: ConstraintCheck = {
|
|
|
41
46
|
async evaluate(env) {
|
|
42
47
|
const projectPath = env.projectPath;
|
|
43
48
|
// ADR-0001 存在性探测:项目未采用 CAPABILITIES.md 约定 → skip(不计 pass/fail)
|
|
44
|
-
if (!existsSync(join(projectPath,
|
|
49
|
+
if (!existsSync(join(projectPath, CAPABILITIES_FILE_REL))) {
|
|
45
50
|
return 'skip';
|
|
46
51
|
}
|
|
47
52
|
try {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
const
|
|
53
|
+
const capabilitiesMode = getCapabilitiesMode(env);
|
|
54
|
+
// 文档原文 + 源码根 + 代码实况 + 对照判定 = run 内一份,与 docs_freshness 共用(ADR-0023 决策 4)
|
|
55
|
+
const caps = env.capabilities(
|
|
56
|
+
collectPopulationFiles(projectPath, env.sourceRoots(), (root) => env.srcScan(root))
|
|
57
|
+
);
|
|
58
|
+
if (!caps) return 'skip'; // 探测与取数之间文档消失:与上方同一语义
|
|
59
|
+
const verdict = caps.verdict;
|
|
51
60
|
|
|
52
61
|
// 清单格式(计数行)没有文件表可核对,计数由 sync-docs 维护,直接放行
|
|
53
|
-
if (capabilitiesMode === 'listing' ||
|
|
62
|
+
if (capabilitiesMode === 'listing' || verdict.listingFormat) {
|
|
54
63
|
return true;
|
|
55
64
|
}
|
|
56
65
|
|
|
57
|
-
const sourceRoots = detectSourceRoots(projectPath);
|
|
58
|
-
const population: string[] = [];
|
|
59
|
-
for (const root of sourceRoots) {
|
|
60
|
-
if (existsSync(join(projectPath, root))) {
|
|
61
|
-
population.push(...env.srcScan(root));
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
66
|
const diffNames = (await env.stagedDiffNames()).split('\n').filter(Boolean);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
sourceRoots,
|
|
71
|
-
});
|
|
67
|
+
// 增量覆盖判定留在本文件:变更清单属 git 证据(#87),不在上行数据面
|
|
68
|
+
const uncoveredChanges = significantCodeChanges(diffNames).filter(
|
|
69
|
+
(f) => !isCoveredByEntries(verdict.coverageEntries, f)
|
|
70
|
+
);
|
|
72
71
|
|
|
73
72
|
// 无表格的散文文档:历史放行语义
|
|
74
73
|
if (!verdict.hasTable) return true;
|
|
75
74
|
|
|
76
75
|
// 文档退化门:有表格却什么都没登记(限定「源码根下确有文件」——空仓 + 空表没有可登记
|
|
77
76
|
// 对象,历史行为是放行,本票不顺手扩大 fail 面)
|
|
78
|
-
if (verdict.coverageEntries.length === 0 &&
|
|
77
|
+
if (verdict.coverageEntries.length === 0 && caps.populationFiles.length > 0) {
|
|
79
78
|
return {
|
|
80
79
|
pass: false,
|
|
81
80
|
evidence: ['CAPABILITIES.md 有表格但零条目登记,运行 harness sync-docs 或直接补登记'],
|
|
@@ -83,12 +82,12 @@ export const capabilitySync: ConstraintCheck = {
|
|
|
83
82
|
}
|
|
84
83
|
|
|
85
84
|
// ── Step 1: Git diff 增量检查(与本次变更有因果,每个变更文件都必须被覆盖)──
|
|
86
|
-
if (
|
|
85
|
+
if (uncoveredChanges.length > 0) {
|
|
87
86
|
return {
|
|
88
87
|
pass: false,
|
|
89
88
|
evidence: formatEvidence(
|
|
90
|
-
`本次变更有 ${
|
|
91
|
-
|
|
89
|
+
`本次变更有 ${uncoveredChanges.length} 个文件未登记进 CAPABILITIES.md`,
|
|
90
|
+
uncoveredChanges
|
|
92
91
|
),
|
|
93
92
|
};
|
|
94
93
|
}
|
|
@@ -10,22 +10,24 @@
|
|
|
10
10
|
import { existsSync } from 'fs';
|
|
11
11
|
import { join } from 'path';
|
|
12
12
|
import { resolveContextFiles } from '../../project-config-loader';
|
|
13
|
-
import type
|
|
13
|
+
import { formatEvidence, type ConstraintCheck } from './types';
|
|
14
14
|
|
|
15
15
|
export const contextDocSync: ConstraintCheck = {
|
|
16
16
|
id: 'context_doc_sync',
|
|
17
17
|
async evaluate(env) {
|
|
18
18
|
const projectPath = env.projectPath;
|
|
19
|
-
const resolution = resolveContextFiles(
|
|
19
|
+
const resolution = resolveContextFiles(env);
|
|
20
20
|
if (resolution.state !== 'enabled') {
|
|
21
21
|
return 'skip'; // 未配置或约定已立但无目标,跳过评估
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
// 证据随判定一并返回(ADR-0016 补迁):此前只回裸 false,
|
|
25
|
+
// 多个 required_dirs 里到底哪个没落 CONTEXT.md,CLI 与 trace 两头都看不出来
|
|
26
|
+
const missing = resolution.dirs
|
|
27
|
+
.map(dir => join(dir, 'CONTEXT.md'))
|
|
28
|
+
.filter(rel => !existsSync(join(projectPath, rel)));
|
|
29
|
+
if (missing.length > 0) {
|
|
30
|
+
return { pass: false, evidence: formatEvidence('关键目录缺 CONTEXT.md', missing) };
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
return true;
|
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
* 3. 无配置时注入内置默认配置(等价旧硬编码行为)
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { existsSync
|
|
10
|
+
import { existsSync } from 'fs';
|
|
11
11
|
import { join } from 'path';
|
|
12
12
|
import { getGovernanceConfig, resolveContextFiles } from '../../project-config-loader';
|
|
13
13
|
import { FreshnessRunner, type FreshnessCheckResult } from '../doc-freshness/runner';
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
14
|
+
import { collectPopulationFiles } from '../capabilities-reconcile';
|
|
15
|
+
import { CAPABILITIES_FILE_REL } from '../run-env';
|
|
16
16
|
import type { DocFreshnessCheck } from '../../../types/project-config';
|
|
17
17
|
import type { ConstraintCheck, CheckEnv } from './types';
|
|
18
18
|
import { formatEvidence } from './types';
|
|
@@ -33,28 +33,19 @@ function getBuiltInDocFreshnessConfig(): DocFreshnessCheck[] {
|
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* CAPABILITIES.md 文件表新鲜度:登记的条目(文件与目录)必须仍存在(ADR-0009 口径从严)。
|
|
36
|
-
*
|
|
37
|
-
*
|
|
36
|
+
* 判定逻辑与取数都在 run 级:文档原文、源码根、代码实况清单、对照判定一次算好,
|
|
37
|
+
* 与 capability_sync 共用同一份(ADR-0023 决策 4;此前两边各读一遍、各解析一遍)。
|
|
38
|
+
* 无表格(能力清单格式)时自然零幽灵。
|
|
38
39
|
*/
|
|
39
|
-
function findDeadCapabilityEntries(
|
|
40
|
+
function findDeadCapabilityEntries(env: CheckEnv): string[] {
|
|
40
41
|
try {
|
|
41
|
-
|
|
42
|
-
if (!existsSync(
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
if (existsSync(join(projectPath, root))) population.push(...env.srcScan(root));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const verdict = reconcileCapabilities({
|
|
52
|
-
content,
|
|
53
|
-
populationFiles: population,
|
|
54
|
-
sourceRoots,
|
|
55
|
-
fileExists: (rel) => existsSync(join(projectPath, rel)),
|
|
56
|
-
});
|
|
57
|
-
return verdict.deadEntries;
|
|
42
|
+
// 先探存在性再取数:只有 CHANGELOG 而无 CAPABILITIES.md 的项目不该为此扫一遍源码树
|
|
43
|
+
if (!existsSync(join(env.projectPath, CAPABILITIES_FILE_REL))) return [];
|
|
44
|
+
const population = collectPopulationFiles(env.projectPath, env.sourceRoots(), (root) =>
|
|
45
|
+
env.srcScan(root)
|
|
46
|
+
);
|
|
47
|
+
const caps = env.capabilities(population);
|
|
48
|
+
return caps ? caps.verdict.deadEntries : [];
|
|
58
49
|
} catch {
|
|
59
50
|
return [];
|
|
60
51
|
}
|
|
@@ -71,18 +62,19 @@ function findDeadCapabilityEntries(projectPath: string, env: CheckEnv): string[]
|
|
|
71
62
|
*
|
|
72
63
|
* 全部缺失 → 项目未采用该约定,调用方应 skip 而非评估内置默认配置。
|
|
73
64
|
*/
|
|
74
|
-
function hasFreshnessTargets(
|
|
75
|
-
|
|
65
|
+
function hasFreshnessTargets(env: CheckEnv): boolean {
|
|
66
|
+
const projectPath = env.projectPath;
|
|
67
|
+
if (existsSync(join(projectPath, CAPABILITIES_FILE_REL))) return true;
|
|
76
68
|
if (existsSync(join(projectPath, 'CHANGELOG.md')) || existsSync(join(projectPath, 'CHANGELOG'))) {
|
|
77
69
|
return true;
|
|
78
70
|
}
|
|
79
71
|
|
|
80
|
-
const governance = getGovernanceConfig(
|
|
72
|
+
const governance = getGovernanceConfig(env);
|
|
81
73
|
if (governance?.doc_freshness?.checks && governance.doc_freshness.checks.length > 0) {
|
|
82
74
|
return true;
|
|
83
75
|
}
|
|
84
76
|
|
|
85
|
-
return resolveContextFiles(
|
|
77
|
+
return resolveContextFiles(env).state === 'enabled';
|
|
86
78
|
}
|
|
87
79
|
|
|
88
80
|
export const docsFreshness: ConstraintCheck = {
|
|
@@ -91,10 +83,10 @@ export const docsFreshness: ConstraintCheck = {
|
|
|
91
83
|
const projectPath = env.projectPath;
|
|
92
84
|
|
|
93
85
|
// ADR-0001 存在性探测:项目无任何 freshness 配置/目标 → skip(不计 pass/fail)
|
|
94
|
-
if (!hasFreshnessTargets(
|
|
86
|
+
if (!hasFreshnessTargets(env)) return 'skip';
|
|
95
87
|
|
|
96
88
|
// Step 1: 文件表格式 — 登记的条目(文件+目录)是否仍存在(ADR-0009)
|
|
97
|
-
const deadEntries = findDeadCapabilityEntries(
|
|
89
|
+
const deadEntries = findDeadCapabilityEntries(env);
|
|
98
90
|
if (deadEntries.length > 0) {
|
|
99
91
|
// 证据通道点名条目(harness#119):此前是 console.error 侧信道(2026-08-08 studio
|
|
100
92
|
// CI 4 连红时的临时办法),CLI 结构化输出与 trace 两头都拿不到,
|
|
@@ -107,11 +99,11 @@ export const docsFreshness: ConstraintCheck = {
|
|
|
107
99
|
|
|
108
100
|
// Step 2: 能力清单格式 + CLAUDE.md + CHANGELOG — 通过 FreshnessRunner
|
|
109
101
|
try {
|
|
110
|
-
const freshnessConfig = getGovernanceConfig(
|
|
102
|
+
const freshnessConfig = getGovernanceConfig(env)?.doc_freshness;
|
|
111
103
|
|
|
112
104
|
// context_files 三态统一口径(工单 84):约定已立但无目标(enabled 但
|
|
113
105
|
// required_dirs 缺失/空)→ skip,与 context_doc_sync 同构;不再静默放行
|
|
114
|
-
const contextFiles = resolveContextFiles(
|
|
106
|
+
const contextFiles = resolveContextFiles(env);
|
|
115
107
|
if (contextFiles.state === 'enabled-empty') return 'skip';
|
|
116
108
|
const requiredDirs = contextFiles.state === 'enabled' ? contextFiles.dirs : undefined;
|
|
117
109
|
|
|
@@ -119,9 +111,12 @@ export const docsFreshness: ConstraintCheck = {
|
|
|
119
111
|
let results: FreshnessCheckResult[];
|
|
120
112
|
|
|
121
113
|
if (freshnessConfig?.checks && freshnessConfig.checks.length > 0) {
|
|
122
|
-
results = runner.runAll(freshnessConfig, projectPath, { requiredDirs });
|
|
114
|
+
results = runner.runAll(freshnessConfig, projectPath, { requiredDirs, sourceRoots: () => env.sourceRoots() });
|
|
123
115
|
} else {
|
|
124
|
-
results = runner.runAll({ checks: getBuiltInDocFreshnessConfig() }, projectPath, {
|
|
116
|
+
results = runner.runAll({ checks: getBuiltInDocFreshnessConfig() }, projectPath, {
|
|
117
|
+
requiredDirs,
|
|
118
|
+
sourceRoots: () => env.sourceRoots(),
|
|
119
|
+
});
|
|
125
120
|
}
|
|
126
121
|
|
|
127
122
|
const failed = results.filter(r => !r.pass);
|
|
@@ -38,7 +38,7 @@ export const governancePresence: ConstraintCheck = {
|
|
|
38
38
|
// 存在性探测:无 harness 配置 = 未采用治理约定 → skip(不计 pass/fail)
|
|
39
39
|
let adopted = false;
|
|
40
40
|
try {
|
|
41
|
-
adopted = loadRawProjectConfig(
|
|
41
|
+
adopted = loadRawProjectConfig(env) !== undefined;
|
|
42
42
|
} catch {
|
|
43
43
|
adopted = false;
|
|
44
44
|
}
|
|
@@ -47,10 +47,14 @@ export const governancePresence: ConstraintCheck = {
|
|
|
47
47
|
if (hasGovernancePreserveBlock(join(projectPath, 'AGENTS.md'))) return true;
|
|
48
48
|
if (hasClaudeGovernance(join(projectPath, 'CLAUDE.md'))) return true;
|
|
49
49
|
|
|
50
|
-
console.error
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
// 证据随判定一并返回(ADR-0016 补迁):此前这里是 console.error 侧信道——
|
|
51
|
+
// 只进本地 stderr,进不了 CLI 结论块与 trace,铁律拦截时用户看不到该恢复哪个正本
|
|
52
|
+
return {
|
|
53
|
+
pass: false,
|
|
54
|
+
evidence: [
|
|
55
|
+
'治理契约缺失:AGENTS.md 无非空 PRESERVE:governance 段,CLAUDE.md 也无 Governance Rules 块(正本静默丢失)',
|
|
56
|
+
'修复: 恢复其一(重跑 `harness init` 会同步注入段)',
|
|
57
|
+
],
|
|
58
|
+
};
|
|
55
59
|
},
|
|
56
60
|
};
|
|
@@ -6,18 +6,20 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { ConstraintContext } from '../../../types/constraint';
|
|
9
|
+
import { createRunEnv, type RunEnv } from '../run-env';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
|
-
*
|
|
12
|
+
* 检查环境:一次 run 内共享的观察面与证据提供者(ADR-0023 决策 1)
|
|
12
13
|
*
|
|
13
|
-
*
|
|
14
|
+
* = `RunEnv`(项目上行数据的读取:config.yml / trace 尾部 / 源根,run 内至多一次)
|
|
15
|
+
* + `context` + git/扫描证据。前者不含 context,故只能派生不能合并成一个对象。
|
|
16
|
+
*
|
|
17
|
+
* - stagedDiff/stagedDiffNames:run 内 git 命令至多一次(工单 18 / #87)
|
|
14
18
|
* - srcScan:run 内同根源码扫描至多一次(CheckCache)
|
|
15
19
|
*/
|
|
16
|
-
export interface CheckEnv {
|
|
20
|
+
export interface CheckEnv extends RunEnv {
|
|
17
21
|
/** 约束上下文(operation/changedFiles/各类证据标志) */
|
|
18
22
|
context: ConstraintContext;
|
|
19
|
-
/** 项目根路径(context.projectPath || process.cwd()) */
|
|
20
|
-
projectPath: string;
|
|
21
23
|
/** staged 全量 diff(run 内 memoized) */
|
|
22
24
|
stagedDiff(): Promise<string>;
|
|
23
25
|
/** staged 变更文件名列表(run 内 memoized) */
|
|
@@ -48,24 +50,28 @@ export interface EvidenceProviders {
|
|
|
48
50
|
* - 'none' = 显式不接证据:证据函数返回空;evidence flag 未接线的
|
|
49
51
|
* checker 按契约返回 'skip'(见 contextEvidenceFlag),直接读空
|
|
50
52
|
* 证据的 checker 在自然输入下判定
|
|
53
|
+
* - runEnv = 本 run 的运行级观察面(ADR-0023):传入即与 context-builder 及
|
|
54
|
+
* 其余 checker 共用同一份上行数据读取;不传则自造一枚,只服务本次调用
|
|
51
55
|
*
|
|
52
56
|
* studio 侧若需 git 证据(#129),传真实 providers 即可。
|
|
53
57
|
*/
|
|
54
58
|
export function buildCheckEnv(
|
|
55
59
|
context: ConstraintContext,
|
|
56
|
-
evidence: EvidenceProviders | 'none'
|
|
60
|
+
evidence: EvidenceProviders | 'none',
|
|
61
|
+
runEnv?: RunEnv
|
|
57
62
|
): CheckEnv {
|
|
58
63
|
const projectPath = context.projectPath || process.cwd();
|
|
64
|
+
const run = runEnv ?? createRunEnv(projectPath);
|
|
59
65
|
if (evidence === 'none') {
|
|
60
66
|
return {
|
|
67
|
+
...run,
|
|
61
68
|
context,
|
|
62
|
-
projectPath,
|
|
63
69
|
stagedDiff: async () => '',
|
|
64
70
|
stagedDiffNames: async () => '',
|
|
65
71
|
srcScan: () => [],
|
|
66
72
|
};
|
|
67
73
|
}
|
|
68
|
-
return {
|
|
74
|
+
return { ...run, context, ...evidence };
|
|
69
75
|
}
|
|
70
76
|
|
|
71
77
|
/**
|
|
@@ -8,14 +8,16 @@
|
|
|
8
8
|
* 架构评审 #87:本模块只做装配不做取证——git 证据一律经 git-evidence
|
|
9
9
|
* adapter 取(缺省真 git adapter,调用方可注入与 checker 层同源的那一份),
|
|
10
10
|
* 因此此处不再有 child_process / raw execSync。
|
|
11
|
+
*
|
|
12
|
+
* ADR-0023:同理,trace 记录与源码根探测改经运行级观察面 `RunEnv` 取——
|
|
13
|
+
* 此前本模块的两个证据探测各自整读一次 traces.log、detectTrigger 与 checker 层
|
|
14
|
+
* 各探一次源码根,同一次运行内重复读同一批文件。缺省自造一份 env,调用方(CLI check)
|
|
15
|
+
* 注入即全 run 共用。
|
|
11
16
|
*/
|
|
12
17
|
|
|
13
18
|
import * as fs from 'fs';
|
|
14
19
|
import * as path from 'path';
|
|
15
|
-
import {
|
|
16
|
-
import { readJsonl } from '../../utils/jsonl';
|
|
17
|
-
import { DEFAULT_TRACE_FILE } from '../../types/trace';
|
|
18
|
-
import type { ExecutionTrace } from '../../types/trace';
|
|
20
|
+
import { createRunEnv, TRACE_TAIL_WINDOW, type RunEnv } from './run-env';
|
|
19
21
|
import type { ConstraintContext, ConstraintTrigger } from '../../types/constraint';
|
|
20
22
|
import { createGitEvidence, splitFileNames, type GitEvidence } from './git-evidence';
|
|
21
23
|
|
|
@@ -51,6 +53,8 @@ export function detectTrigger(
|
|
|
51
53
|
trigger?: ConstraintTrigger;
|
|
52
54
|
projectPath?: string;
|
|
53
55
|
evidence?: GitEvidence;
|
|
56
|
+
/** 运行级观察面(ADR-0023):注入即与其余消费方共用同一份源根探测 */
|
|
57
|
+
runEnv?: RunEnv;
|
|
54
58
|
}
|
|
55
59
|
): ConstraintTrigger | ConstraintTrigger[] {
|
|
56
60
|
if (options.trigger) return options.trigger;
|
|
@@ -62,7 +66,7 @@ export function detectTrigger(
|
|
|
62
66
|
// pre-commit 场景下变更含代码文件 → 附加 code_implementation 推断
|
|
63
67
|
const hasCodeChange = changedFiles.some(f => CODE_FILE_REGEX.test(f));
|
|
64
68
|
const projectPath = options.projectPath || process.cwd();
|
|
65
|
-
const sourceRoots =
|
|
69
|
+
const sourceRoots = (options.runEnv ?? createRunEnv(projectPath)).sourceRoots();
|
|
66
70
|
const hasModuleChange = changedFiles.some(f =>
|
|
67
71
|
sourceRoots.some(root => f.startsWith(root + '/') || f.startsWith(root + '\\')) && !f.includes('__tests__')
|
|
68
72
|
);
|
|
@@ -85,17 +89,14 @@ export function detectTrigger(
|
|
|
85
89
|
}
|
|
86
90
|
|
|
87
91
|
/**
|
|
88
|
-
*
|
|
89
|
-
* 扫描 trace 文件(DEFAULT_TRACE_FILE)中最近的记录
|
|
92
|
+
* 检测是否有失败的测试记录(取运行级观察面的最近 20 条)
|
|
90
93
|
*/
|
|
91
|
-
|
|
94
|
+
async function detectFailingTest(env: RunEnv): Promise<boolean> {
|
|
92
95
|
try {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const { records } = readJsonl<ExecutionTrace>(traceFile, 'skip', { tail: 20 });
|
|
98
|
-
return records.some(trace => trace.result === 'fail');
|
|
96
|
+
// 坏行策略与计数去向见 run-env 的读点(ADR-0023 合并两处独立 tail 读为一份窗口)
|
|
97
|
+
return env
|
|
98
|
+
.traceTail(TRACE_TAIL_WINDOW)
|
|
99
|
+
.records.some(trace => trace.result === 'fail');
|
|
99
100
|
} catch {
|
|
100
101
|
return false;
|
|
101
102
|
}
|
|
@@ -123,19 +124,18 @@ export function detectRootCauseInvestigation(projectPath: string): boolean {
|
|
|
123
124
|
return false;
|
|
124
125
|
}
|
|
125
126
|
|
|
127
|
+
/** 验证证据的尾部窗口(工单 23 原口径:只看最近 10 条) */
|
|
128
|
+
const VERIFICATION_EVIDENCE_TAIL = 10;
|
|
129
|
+
|
|
126
130
|
/**
|
|
127
|
-
*
|
|
128
|
-
* 检查 trace 文件(DEFAULT_TRACE_FILE)中最近的成功验证记录
|
|
131
|
+
* 检测是否有验证证据(取运行级观察面的最近 10 条)
|
|
129
132
|
*/
|
|
130
|
-
|
|
133
|
+
async function detectVerificationEvidence(env: RunEnv): Promise<boolean> {
|
|
131
134
|
try {
|
|
132
|
-
const traceFile = path.join(projectPath, DEFAULT_TRACE_FILE);
|
|
133
|
-
// 坏行策略:skip(原逐行 catch→false 语义不变);只 parse 最近 10 行
|
|
134
135
|
// tail 在 parse 之前截断 → 坏行会占用尾部槽位(#82 裁决范围外的既有口径,本票不改)
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
return records.some(trace => trace.result === 'pass');
|
|
136
|
+
return env
|
|
137
|
+
.traceTail(VERIFICATION_EVIDENCE_TAIL)
|
|
138
|
+
.records.some(trace => trace.result === 'pass');
|
|
139
139
|
} catch {
|
|
140
140
|
return false;
|
|
141
141
|
}
|
|
@@ -191,17 +191,26 @@ export function detectReuseCheck(projectPath: string): boolean {
|
|
|
191
191
|
*
|
|
192
192
|
* options.evidence(#87):git 证据适配器。调用方(CLI check)注入同一实例给
|
|
193
193
|
* checkConstraints,即可让 context-builder 与 checker 层共用同一证据来源。
|
|
194
|
+
* options.runEnv(ADR-0023):运行级观察面。注入即本函数内的源根探测与两处 trace
|
|
195
|
+
* 证据探测与其余消费方共用同一份读取,缺省自造一份(只服务本次调用)。
|
|
194
196
|
*/
|
|
195
197
|
export async function buildConstraintContext(options: {
|
|
196
198
|
projectPath?: string;
|
|
197
199
|
staged: boolean;
|
|
198
200
|
trigger?: ConstraintTrigger;
|
|
199
201
|
evidence?: GitEvidence;
|
|
202
|
+
runEnv?: RunEnv;
|
|
200
203
|
}): Promise<ConstraintContext> {
|
|
201
204
|
const projectPath = options.projectPath || process.cwd();
|
|
205
|
+
const runEnv = options.runEnv ?? createRunEnv(projectPath);
|
|
202
206
|
const evidence = options.evidence ?? createGitEvidence(projectPath);
|
|
203
207
|
const changedFiles = splitFileNames(evidence.changedFileNames(options.staged));
|
|
204
|
-
const inferred = detectTrigger(changedFiles, {
|
|
208
|
+
const inferred = detectTrigger(changedFiles, {
|
|
209
|
+
trigger: options.trigger,
|
|
210
|
+
projectPath,
|
|
211
|
+
evidence,
|
|
212
|
+
runEnv,
|
|
213
|
+
});
|
|
205
214
|
const triggers = Array.isArray(inferred) ? inferred : [inferred];
|
|
206
215
|
|
|
207
216
|
return {
|
|
@@ -210,9 +219,9 @@ export async function buildConstraintContext(options: {
|
|
|
210
219
|
projectPath,
|
|
211
220
|
changedFiles,
|
|
212
221
|
hasTest: changedFiles.some(f => f.includes('.test.') || f.includes('.spec.')),
|
|
213
|
-
hasFailingTest: await detectFailingTest(
|
|
222
|
+
hasFailingTest: await detectFailingTest(runEnv),
|
|
214
223
|
hasRootCauseInvestigation: detectRootCauseInvestigation(projectPath),
|
|
215
|
-
hasVerificationEvidence: await detectVerificationEvidence(
|
|
224
|
+
hasVerificationEvidence: await detectVerificationEvidence(runEnv),
|
|
216
225
|
hasReuseCheck: detectReuseCheck(projectPath),
|
|
217
226
|
hasRequirement: detectRequirement(projectPath),
|
|
218
227
|
};
|