@dommaker/harness 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +0 -2
- package/bin/harness.js +86 -32
- package/dist/cli/command-contract.d.ts +83 -0
- package/dist/cli/command-contract.d.ts.map +1 -0
- package/dist/cli/command-contract.js +66 -0
- package/dist/cli/command-contract.js.map +1 -0
- package/dist/cli/commands/acceptance.d.ts +3 -2
- package/dist/cli/commands/acceptance.d.ts.map +1 -1
- package/dist/cli/commands/acceptance.js +28 -24
- package/dist/cli/commands/acceptance.js.map +1 -1
- package/dist/cli/commands/analyze-sessions.d.ts +2 -1
- package/dist/cli/commands/analyze-sessions.d.ts.map +1 -1
- package/dist/cli/commands/analyze-sessions.js +25 -24
- package/dist/cli/commands/analyze-sessions.js.map +1 -1
- package/dist/cli/commands/check.d.ts +14 -2
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/check.js +76 -61
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/command.d.ts +5 -1
- package/dist/cli/commands/command.d.ts.map +1 -1
- package/dist/cli/commands/command.js +26 -17
- package/dist/cli/commands/command.js.map +1 -1
- package/dist/cli/commands/constraints-report.d.ts +2 -1
- package/dist/cli/commands/constraints-report.d.ts.map +1 -1
- package/dist/cli/commands/constraints-report.js +37 -33
- package/dist/cli/commands/constraints-report.js.map +1 -1
- package/dist/cli/commands/constraints-retire.d.ts +6 -5
- package/dist/cli/commands/constraints-retire.d.ts.map +1 -1
- package/dist/cli/commands/constraints-retire.js +50 -52
- package/dist/cli/commands/constraints-retire.js.map +1 -1
- package/dist/cli/commands/constraints.d.ts +2 -1
- package/dist/cli/commands/constraints.d.ts.map +1 -1
- package/dist/cli/commands/constraints.js +10 -27
- package/dist/cli/commands/constraints.js.map +1 -1
- package/dist/cli/commands/contract.d.ts +3 -2
- package/dist/cli/commands/contract.d.ts.map +1 -1
- package/dist/cli/commands/contract.js +45 -42
- package/dist/cli/commands/contract.js.map +1 -1
- package/dist/cli/commands/definitions.d.ts +11 -11
- package/dist/cli/commands/definitions.d.ts.map +1 -1
- package/dist/cli/commands/definitions.js +29 -214
- package/dist/cli/commands/definitions.js.map +1 -1
- package/dist/cli/commands/failure.d.ts +5 -4
- package/dist/cli/commands/failure.d.ts.map +1 -1
- package/dist/cli/commands/failure.js +31 -25
- package/dist/cli/commands/failure.js.map +1 -1
- package/dist/cli/commands/init.d.ts +7 -5
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +147 -211
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/knowledge.d.ts +21 -15
- package/dist/cli/commands/knowledge.d.ts.map +1 -1
- package/dist/cli/commands/knowledge.js +214 -199
- package/dist/cli/commands/knowledge.js.map +1 -1
- package/dist/cli/commands/passes-gate.d.ts +8 -2
- package/dist/cli/commands/passes-gate.d.ts.map +1 -1
- package/dist/cli/commands/passes-gate.js +44 -66
- package/dist/cli/commands/passes-gate.js.map +1 -1
- package/dist/cli/commands/performance.d.ts +2 -1
- package/dist/cli/commands/performance.d.ts.map +1 -1
- package/dist/cli/commands/performance.js +20 -18
- package/dist/cli/commands/performance.js.map +1 -1
- package/dist/cli/commands/posteval-plan.d.ts +5 -1
- package/dist/cli/commands/posteval-plan.d.ts.map +1 -1
- package/dist/cli/commands/posteval-plan.js +26 -15
- package/dist/cli/commands/posteval-plan.js.map +1 -1
- package/dist/cli/commands/release.d.ts +6 -1
- package/dist/cli/commands/release.d.ts.map +1 -1
- package/dist/cli/commands/release.js +69 -59
- package/dist/cli/commands/release.js.map +1 -1
- package/dist/cli/commands/report.d.ts +2 -1
- package/dist/cli/commands/report.d.ts.map +1 -1
- package/dist/cli/commands/report.js +9 -5
- package/dist/cli/commands/report.js.map +1 -1
- package/dist/cli/commands/review.d.ts +3 -2
- package/dist/cli/commands/review.d.ts.map +1 -1
- package/dist/cli/commands/review.js +33 -29
- package/dist/cli/commands/review.js.map +1 -1
- package/dist/cli/commands/sdd.d.ts +2 -1
- package/dist/cli/commands/sdd.d.ts.map +1 -1
- package/dist/cli/commands/sdd.js +7 -5
- package/dist/cli/commands/sdd.js.map +1 -1
- package/dist/cli/commands/security.d.ts +3 -2
- package/dist/cli/commands/security.d.ts.map +1 -1
- package/dist/cli/commands/security.js +29 -26
- package/dist/cli/commands/security.js.map +1 -1
- package/dist/cli/commands/spec-baseline-check.d.ts +2 -1
- package/dist/cli/commands/spec-baseline-check.d.ts.map +1 -1
- package/dist/cli/commands/spec-baseline-check.js +15 -11
- package/dist/cli/commands/spec-baseline-check.js.map +1 -1
- package/dist/cli/commands/spec.d.ts +7 -2
- package/dist/cli/commands/spec.d.ts.map +1 -1
- package/dist/cli/commands/spec.js +61 -51
- package/dist/cli/commands/spec.js.map +1 -1
- package/dist/cli/commands/status.d.ts +2 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +57 -53
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/sync-docs/agents-syncer.d.ts.map +1 -1
- package/dist/cli/commands/sync-docs/agents-syncer.js +5 -2
- package/dist/cli/commands/sync-docs/agents-syncer.js.map +1 -1
- package/dist/cli/commands/sync-docs/context-syncer.d.ts.map +1 -1
- package/dist/cli/commands/sync-docs/context-syncer.js +3 -2
- package/dist/cli/commands/sync-docs/context-syncer.js.map +1 -1
- package/dist/cli/commands/sync-docs/index.d.ts +2 -1
- package/dist/cli/commands/sync-docs/index.d.ts.map +1 -1
- package/dist/cli/commands/sync-docs/index.js +68 -88
- package/dist/cli/commands/sync-docs/index.js.map +1 -1
- package/dist/cli/commands/sync-docs/project-reader.d.ts +6 -1
- package/dist/cli/commands/sync-docs/project-reader.d.ts.map +1 -1
- package/dist/cli/commands/sync-docs/project-reader.js +14 -16
- package/dist/cli/commands/sync-docs/project-reader.js.map +1 -1
- package/dist/cli/commands/update-user-model.d.ts +2 -1
- package/dist/cli/commands/update-user-model.d.ts.map +1 -1
- package/dist/cli/commands/update-user-model.js +31 -45
- package/dist/cli/commands/update-user-model.js.map +1 -1
- package/dist/cli/commands/validate.d.ts +4 -3
- package/dist/cli/commands/validate.d.ts.map +1 -1
- package/dist/cli/commands/validate.js +28 -26
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/session-mining/transcript.d.ts +7 -1
- package/dist/cli/session-mining/transcript.d.ts.map +1 -1
- package/dist/cli/session-mining/transcript.js +21 -14
- package/dist/cli/session-mining/transcript.js.map +1 -1
- package/dist/context/session-manager.d.ts.map +1 -1
- package/dist/context/session-manager.js +19 -32
- package/dist/context/session-manager.js.map +1 -1
- package/dist/core/constraints/agent-prompt-renderer.d.ts.map +1 -1
- package/dist/core/constraints/agent-prompt-renderer.js +1 -4
- package/dist/core/constraints/agent-prompt-renderer.js.map +1 -1
- package/dist/core/constraints/capabilities-parser.d.ts +24 -7
- package/dist/core/constraints/capabilities-parser.d.ts.map +1 -1
- package/dist/core/constraints/capabilities-parser.js +32 -28
- package/dist/core/constraints/capabilities-parser.js.map +1 -1
- package/dist/core/constraints/capabilities-reconcile.d.ts +67 -0
- package/dist/core/constraints/capabilities-reconcile.d.ts.map +1 -0
- package/dist/core/constraints/capabilities-reconcile.js +105 -0
- package/dist/core/constraints/capabilities-reconcile.js.map +1 -0
- package/dist/core/constraints/checker.d.ts +21 -43
- package/dist/core/constraints/checker.d.ts.map +1 -1
- package/dist/core/constraints/checker.js +64 -115
- package/dist/core/constraints/checker.js.map +1 -1
- package/dist/core/constraints/checkers/capability-sync.d.ts +4 -3
- package/dist/core/constraints/checkers/capability-sync.d.ts.map +1 -1
- package/dist/core/constraints/checkers/capability-sync.js +29 -69
- package/dist/core/constraints/checkers/capability-sync.js.map +1 -1
- package/dist/core/constraints/checkers/context-doc-sync.d.ts +4 -2
- package/dist/core/constraints/checkers/context-doc-sync.d.ts.map +1 -1
- package/dist/core/constraints/checkers/context-doc-sync.js +13 -22
- package/dist/core/constraints/checkers/context-doc-sync.js.map +1 -1
- package/dist/core/constraints/checkers/docs-freshness.d.ts.map +1 -1
- package/dist/core/constraints/checkers/docs-freshness.js +37 -63
- package/dist/core/constraints/checkers/docs-freshness.js.map +1 -1
- package/dist/core/constraints/checkers/governance-presence.d.ts +2 -2
- package/dist/core/constraints/checkers/governance-presence.d.ts.map +1 -1
- package/dist/core/constraints/checkers/governance-presence.js +7 -28
- package/dist/core/constraints/checkers/governance-presence.js.map +1 -1
- package/dist/core/constraints/checkers/no-test-simplification.d.ts.map +1 -1
- package/dist/core/constraints/checkers/no-test-simplification.js +4 -3
- package/dist/core/constraints/checkers/no-test-simplification.js.map +1 -1
- package/dist/core/constraints/checkers/types.d.ts +2 -2
- package/dist/core/constraints/context-builder.d.ts +15 -14
- package/dist/core/constraints/context-builder.d.ts.map +1 -1
- package/dist/core/constraints/context-builder.js +32 -96
- package/dist/core/constraints/context-builder.js.map +1 -1
- package/dist/core/constraints/doc-freshness/runner.d.ts.map +1 -1
- package/dist/core/constraints/doc-freshness/runner.js +2 -1
- package/dist/core/constraints/doc-freshness/runner.js.map +1 -1
- package/dist/core/constraints/git-evidence.d.ts +60 -0
- package/dist/core/constraints/git-evidence.d.ts.map +1 -0
- package/dist/core/constraints/git-evidence.js +88 -0
- package/dist/core/constraints/git-evidence.js.map +1 -0
- package/dist/core/constraints/injection-drift.d.ts +3 -20
- package/dist/core/constraints/injection-drift.d.ts.map +1 -1
- package/dist/core/constraints/injection-drift.js +10 -57
- package/dist/core/constraints/injection-drift.js.map +1 -1
- package/dist/core/constraints/injection-writer.d.ts +113 -0
- package/dist/core/constraints/injection-writer.d.ts.map +1 -0
- package/dist/core/constraints/injection-writer.js +228 -0
- package/dist/core/constraints/injection-writer.js.map +1 -0
- package/dist/core/constraints/usage-report.d.ts +22 -1
- package/dist/core/constraints/usage-report.d.ts.map +1 -1
- package/dist/core/constraints/usage-report.js +27 -20
- package/dist/core/constraints/usage-report.js.map +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +4 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/project-config-loader.d.ts +32 -1
- package/dist/core/project-config-loader.d.ts.map +1 -1
- package/dist/core/project-config-loader.js +39 -9
- package/dist/core/project-config-loader.js.map +1 -1
- package/dist/core/validators/passes-gate.d.ts +15 -64
- package/dist/core/validators/passes-gate.d.ts.map +1 -1
- package/dist/core/validators/passes-gate.js +84 -222
- package/dist/core/validators/passes-gate.js.map +1 -1
- package/dist/core/validators/test-output.d.ts +58 -0
- package/dist/core/validators/test-output.d.ts.map +1 -0
- package/dist/core/validators/test-output.js +109 -0
- package/dist/core/validators/test-output.js.map +1 -0
- package/dist/failure/recorder.d.ts +6 -0
- package/dist/failure/recorder.d.ts.map +1 -1
- package/dist/failure/recorder.js +12 -8
- package/dist/failure/recorder.js.map +1 -1
- package/dist/gates/acceptance.d.ts +1 -48
- package/dist/gates/acceptance.d.ts.map +1 -1
- package/dist/gates/acceptance.js +6 -38
- package/dist/gates/acceptance.js.map +1 -1
- package/dist/gates/checker-gate.d.ts.map +1 -1
- package/dist/gates/checker-gate.js +6 -11
- package/dist/gates/checker-gate.js.map +1 -1
- package/dist/gates/command.d.ts.map +1 -1
- package/dist/gates/command.js +10 -22
- package/dist/gates/command.js.map +1 -1
- package/dist/gates/contract.d.ts.map +1 -1
- package/dist/gates/contract.js +22 -61
- package/dist/gates/contract.js.map +1 -1
- package/dist/gates/performance.d.ts.map +1 -1
- package/dist/gates/performance.js +13 -31
- package/dist/gates/performance.js.map +1 -1
- package/dist/gates/review.d.ts.map +1 -1
- package/dist/gates/review.js +21 -53
- package/dist/gates/review.js.map +1 -1
- package/dist/gates/security.d.ts.map +1 -1
- package/dist/gates/security.js +14 -32
- package/dist/gates/security.js.map +1 -1
- package/dist/gates/types.d.ts +28 -5
- package/dist/gates/types.d.ts.map +1 -1
- package/dist/gates/types.js +38 -1
- package/dist/gates/types.js.map +1 -1
- package/dist/hooks/bootstrap.d.ts +2 -0
- package/dist/hooks/bootstrap.d.ts.map +1 -1
- package/dist/hooks/bootstrap.js +5 -2
- package/dist/hooks/bootstrap.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/knowledge/audit.d.ts +7 -2
- package/dist/knowledge/audit.d.ts.map +1 -1
- package/dist/knowledge/audit.js +59 -79
- package/dist/knowledge/audit.js.map +1 -1
- package/dist/knowledge/flywheel-metrics.d.ts +39 -0
- package/dist/knowledge/flywheel-metrics.d.ts.map +1 -0
- package/dist/knowledge/flywheel-metrics.js +47 -0
- package/dist/knowledge/flywheel-metrics.js.map +1 -0
- package/dist/knowledge/import.d.ts.map +1 -1
- package/dist/knowledge/import.js +4 -14
- package/dist/knowledge/import.js.map +1 -1
- package/dist/knowledge/index-generator.d.ts.map +1 -1
- package/dist/knowledge/index-generator.js +17 -14
- package/dist/knowledge/index-generator.js.map +1 -1
- package/dist/knowledge/ingest.d.ts.map +1 -1
- package/dist/knowledge/ingest.js +9 -4
- package/dist/knowledge/ingest.js.map +1 -1
- package/dist/knowledge/migration.d.ts.map +1 -1
- package/dist/knowledge/migration.js +11 -8
- package/dist/knowledge/migration.js.map +1 -1
- package/dist/knowledge/reference-tracker.d.ts.map +1 -1
- package/dist/knowledge/reference-tracker.js +12 -9
- package/dist/knowledge/reference-tracker.js.map +1 -1
- package/dist/knowledge/store.d.ts +15 -0
- package/dist/knowledge/store.d.ts.map +1 -1
- package/dist/knowledge/store.js +59 -10
- package/dist/knowledge/store.js.map +1 -1
- package/dist/monitoring/context-tracker.d.ts.map +1 -1
- package/dist/monitoring/context-tracker.js +11 -20
- package/dist/monitoring/context-tracker.js.map +1 -1
- package/dist/monitoring/index.d.ts +1 -1
- package/dist/monitoring/index.d.ts.map +1 -1
- package/dist/monitoring/index.js +1 -2
- package/dist/monitoring/index.js.map +1 -1
- package/dist/monitoring/trace-analyzer.d.ts +15 -0
- package/dist/monitoring/trace-analyzer.d.ts.map +1 -1
- package/dist/monitoring/trace-analyzer.js +19 -2
- package/dist/monitoring/trace-analyzer.js.map +1 -1
- package/dist/monitoring/traces.d.ts +21 -2
- package/dist/monitoring/traces.d.ts.map +1 -1
- package/dist/monitoring/traces.js +38 -29
- package/dist/monitoring/traces.js.map +1 -1
- package/dist/release/index.d.ts +2 -2
- package/dist/release/index.d.ts.map +1 -1
- package/dist/release/index.js +1 -5
- package/dist/release/index.js.map +1 -1
- package/dist/sdd/index-generator.js +10 -11
- package/dist/sdd/index-generator.js.map +1 -1
- package/dist/test-setup/project-fixture.d.ts +48 -0
- package/dist/test-setup/project-fixture.d.ts.map +1 -0
- package/dist/test-setup/project-fixture.js +106 -0
- package/dist/test-setup/project-fixture.js.map +1 -0
- package/dist/types/constraint.d.ts +0 -18
- package/dist/types/constraint.d.ts.map +1 -1
- package/dist/types/constraint.js.map +1 -1
- package/dist/types/passes-gate.d.ts +10 -25
- package/dist/types/passes-gate.d.ts.map +1 -1
- package/dist/types/project-config.d.ts +1 -1
- package/dist/types/session.d.ts +6 -5
- package/dist/types/session.d.ts.map +1 -1
- package/dist/utils/exec.d.ts +10 -0
- package/dist/utils/exec.d.ts.map +1 -1
- package/dist/utils/exec.js +12 -0
- package/dist/utils/exec.js.map +1 -1
- package/dist/utils/file-walk.d.ts +9 -1
- package/dist/utils/file-walk.d.ts.map +1 -1
- package/dist/utils/file-walk.js +10 -1
- package/dist/utils/file-walk.js.map +1 -1
- package/dist/utils/frontmatter.d.ts +73 -0
- package/dist/utils/frontmatter.d.ts.map +1 -0
- package/dist/utils/frontmatter.js +141 -0
- package/dist/utils/frontmatter.js.map +1 -0
- package/dist/utils/jsonl.d.ts +92 -0
- package/dist/utils/jsonl.d.ts.map +1 -0
- package/dist/utils/jsonl.js +166 -0
- package/dist/utils/jsonl.js.map +1 -0
- package/dist/utils/package-version.d.ts +16 -0
- package/dist/utils/package-version.d.ts.map +1 -0
- package/dist/utils/package-version.js +63 -0
- package/dist/utils/package-version.js.map +1 -0
- package/package.json +1 -1
- package/src/CONTEXT.md +7 -2
- package/src/__tests__/acceptance-gate.test.ts +3 -1
- package/src/__tests__/checker-extra.test.ts +7 -1218
- package/src/__tests__/context-files-resolution.test.ts +116 -0
- package/src/__tests__/effective-constraints.test.ts +10 -13
- package/src/__tests__/exec.test.ts +35 -1
- package/src/__tests__/layering.test.ts +152 -0
- package/src/__tests__/passes-gate-extra.test.ts +0 -145
- package/src/__tests__/passes-gate.test.ts +142 -106
- package/src/__tests__/skip-semantics.test.ts +5 -9
- package/src/cli/__tests__/command-contract.test.ts +170 -0
- package/src/cli/command-contract.ts +108 -0
- package/src/cli/commands/CONTEXT.md +22 -7
- package/src/cli/commands/__tests__/acceptance.test.ts +40 -33
- package/src/cli/commands/__tests__/analyze-sessions.test.ts +35 -29
- package/src/cli/commands/__tests__/bin-exit-mapping.test.ts +101 -0
- package/src/cli/commands/__tests__/check-drift.test.ts +27 -34
- package/src/cli/commands/__tests__/check-skip-output.test.ts +21 -24
- package/src/cli/commands/__tests__/check.test.ts +378 -382
- package/src/cli/commands/__tests__/command.test.ts +85 -70
- package/src/cli/commands/__tests__/constraints-report.test.ts +100 -71
- package/src/cli/commands/__tests__/constraints-retire.test.ts +152 -95
- package/src/cli/commands/__tests__/contract.test.ts +27 -34
- package/src/cli/commands/__tests__/failure.test.ts +31 -34
- package/src/cli/commands/__tests__/init-injection.test.ts +58 -28
- package/src/cli/commands/__tests__/init.test.ts +77 -48
- package/src/cli/commands/__tests__/knowledge-flywheel-consistency.test.ts +108 -0
- package/src/cli/commands/__tests__/knowledge.test.ts +69 -43
- package/src/cli/commands/__tests__/passes-gate.test.ts +43 -45
- package/src/cli/commands/__tests__/performance.test.ts +22 -23
- package/src/cli/commands/__tests__/posteval-plan.test.ts +39 -38
- package/src/cli/commands/__tests__/project-path-anchoring.test.ts +157 -0
- package/src/cli/commands/__tests__/project-path-convention.test.ts +169 -0
- package/src/cli/commands/__tests__/registry.test.ts +69 -35
- package/src/cli/commands/__tests__/release.test.ts +209 -80
- package/src/cli/commands/__tests__/report-extra.test.ts +16 -16
- package/src/cli/commands/__tests__/report.test.ts +25 -25
- package/src/cli/commands/__tests__/review.test.ts +33 -31
- package/src/cli/commands/__tests__/security.test.ts +23 -27
- package/src/cli/commands/__tests__/spec-baseline-check.test.ts +20 -20
- package/src/cli/commands/__tests__/spec.test.ts +41 -29
- package/src/cli/commands/__tests__/status-extra.test.ts +18 -18
- package/src/cli/commands/__tests__/status-skipped-lines.test.ts +72 -0
- package/src/cli/commands/__tests__/status.test.ts +34 -34
- package/src/cli/commands/__tests__/sync-docs-agents.test.ts +77 -78
- package/src/cli/commands/__tests__/sync-docs.test.ts +72 -74
- package/src/cli/commands/__tests__/update-user-model.test.ts +62 -33
- package/src/cli/commands/__tests__/validate.test.ts +27 -29
- package/src/cli/commands/acceptance.ts +35 -24
- package/src/cli/commands/analyze-sessions.ts +25 -24
- package/src/cli/commands/check.ts +88 -65
- package/src/cli/commands/command.ts +30 -17
- package/src/cli/commands/constraints-report.ts +37 -34
- package/src/cli/commands/constraints-retire.ts +58 -55
- package/src/cli/commands/constraints.ts +10 -27
- package/src/cli/commands/contract.ts +51 -42
- package/src/cli/commands/definitions.ts +36 -222
- package/src/cli/commands/failure.ts +33 -26
- package/src/cli/commands/init.ts +166 -220
- package/src/cli/commands/knowledge.ts +225 -203
- package/src/cli/commands/passes-gate.ts +58 -68
- package/src/cli/commands/performance.ts +23 -18
- package/src/cli/commands/posteval-plan.ts +29 -15
- package/src/cli/commands/release.ts +70 -59
- package/src/cli/commands/report.ts +9 -5
- package/src/cli/commands/review.ts +39 -29
- package/src/cli/commands/sdd.ts +7 -5
- package/src/cli/commands/security.ts +35 -26
- package/src/cli/commands/spec-baseline-check.ts +16 -11
- package/src/cli/commands/spec.ts +66 -53
- package/src/cli/commands/status.ts +59 -53
- package/src/cli/commands/sync-docs/agents-syncer.ts +5 -2
- package/src/cli/commands/sync-docs/context-syncer.ts +3 -2
- package/src/cli/commands/sync-docs/index.ts +73 -100
- package/src/cli/commands/sync-docs/project-reader.ts +17 -18
- package/src/cli/commands/update-user-model.ts +33 -45
- package/src/cli/commands/validate.ts +31 -25
- package/src/cli/session-mining/__tests__/transcript.test.ts +118 -0
- package/src/cli/session-mining/transcript.ts +26 -8
- package/src/context/session-manager.ts +19 -33
- package/src/core/CONTEXT.md +9 -6
- package/src/core/constraints/__tests__/capabilities-reconcile.test.ts +200 -0
- package/src/core/constraints/__tests__/capability-counts.test.ts +94 -0
- package/src/core/constraints/__tests__/git-evidence.test.ts +208 -0
- package/src/core/constraints/__tests__/injection-drift.test.ts +3 -10
- package/src/core/constraints/__tests__/injection-writer.test.ts +231 -0
- package/src/core/constraints/__tests__/trace-injection.test.ts +71 -0
- package/src/core/constraints/__tests__/usage-report.test.ts +112 -0
- package/src/core/constraints/agent-prompt-renderer.ts +2 -6
- package/src/core/constraints/capabilities-parser.ts +53 -35
- package/src/core/constraints/capabilities-reconcile.ts +166 -0
- package/src/core/constraints/checker.ts +75 -130
- package/src/core/constraints/checkers/__tests__/capability-sync.test.ts +214 -0
- package/src/core/constraints/checkers/__tests__/context-doc-sync.test.ts +77 -0
- package/src/core/constraints/checkers/__tests__/docs-freshness.test.ts +117 -0
- package/src/{__tests__ → core/constraints/checkers/__tests__}/governance-presence.test.ts +83 -9
- package/src/core/constraints/checkers/__tests__/iron-flags.test.ts +50 -0
- package/src/core/constraints/checkers/__tests__/no-bypass-checkpoint.test.ts +76 -0
- package/src/{__tests__ → core/constraints/checkers/__tests__}/no-hardcoded-credentials.test.ts +4 -3
- package/src/core/constraints/checkers/__tests__/no-test-simplification.test.ts +58 -0
- package/src/core/constraints/checkers/__tests__/three-state-consistency.test.ts +145 -0
- package/src/core/constraints/checkers/capability-sync.ts +29 -88
- package/src/core/constraints/checkers/context-doc-sync.ts +15 -25
- package/src/core/constraints/checkers/docs-freshness.ts +40 -69
- package/src/core/constraints/checkers/governance-presence.ts +7 -25
- package/src/core/constraints/checkers/no-test-simplification.ts +4 -3
- package/src/core/constraints/checkers/types.ts +2 -2
- package/src/core/constraints/context-builder.ts +39 -91
- package/src/core/constraints/doc-freshness/runner.ts +2 -1
- package/src/core/constraints/git-evidence.ts +120 -0
- package/src/core/constraints/injection-drift.ts +13 -60
- package/src/core/constraints/injection-writer.ts +212 -0
- package/src/core/constraints/usage-report.ts +36 -17
- package/src/core/index.ts +4 -2
- package/src/core/project-config-loader.ts +49 -9
- package/src/core/validators/__tests__/passes-gate.test.ts +2 -56
- package/src/core/validators/__tests__/test-output.test.ts +372 -0
- package/src/core/validators/passes-gate.ts +86 -248
- package/src/core/validators/test-output.ts +128 -0
- package/src/failure/__tests__/recorder.test.ts +168 -0
- package/src/failure/recorder.ts +12 -10
- package/src/gates/CONTEXT.md +6 -3
- package/src/gates/__tests__/acceptance-types-single-source.test.ts +68 -0
- package/src/gates/__tests__/acceptance.test.ts +4 -86
- package/src/gates/__tests__/effective-gates.test.ts +3 -8
- package/src/gates/__tests__/test-verdict-consistency.test.ts +140 -0
- package/src/gates/acceptance.ts +19 -84
- package/src/gates/checker-gate.ts +8 -7
- package/src/gates/command.ts +10 -16
- package/src/gates/contract.ts +22 -61
- package/src/gates/performance.ts +10 -22
- package/src/gates/review.ts +21 -41
- package/src/gates/security.ts +10 -22
- package/src/gates/types.ts +70 -5
- package/src/hooks/CONTEXT.md +1 -1
- package/src/hooks/bootstrap.ts +5 -2
- package/src/index.ts +0 -4
- package/src/knowledge/CONTEXT.md +8 -3
- package/src/knowledge/__tests__/audit-labels.test.ts +44 -0
- package/src/knowledge/__tests__/flywheel-metrics.test.ts +135 -0
- package/src/knowledge/__tests__/import.test.ts +44 -0
- package/src/knowledge/__tests__/index-generator.test.ts +53 -0
- package/src/knowledge/__tests__/ingest.test.ts +85 -0
- package/src/knowledge/__tests__/migration.test.ts +47 -0
- package/src/knowledge/__tests__/reference-tracker.test.ts +16 -0
- package/src/knowledge/__tests__/store.test.ts +194 -0
- package/src/knowledge/audit.ts +67 -71
- package/src/knowledge/flywheel-metrics.ts +71 -0
- package/src/knowledge/import.ts +4 -18
- package/src/knowledge/index-generator.ts +19 -14
- package/src/knowledge/ingest.ts +9 -4
- package/src/knowledge/migration.ts +11 -8
- package/src/knowledge/reference-tracker.ts +12 -8
- package/src/knowledge/store.ts +64 -11
- package/src/monitoring/CONTEXT.md +8 -3
- package/src/monitoring/__tests__/skipped-lines-report.test.ts +178 -0
- package/src/monitoring/__tests__/traces.test.ts +57 -0
- package/src/monitoring/context-tracker.ts +11 -23
- package/src/monitoring/index.ts +1 -1
- package/src/monitoring/trace-analyzer.ts +21 -2
- package/src/monitoring/traces.ts +39 -36
- package/src/release/CONTEXT.md +1 -0
- package/src/release/__tests__/barrel.test.ts +60 -0
- package/src/release/index.ts +2 -13
- package/src/sdd/__tests__/index-generator.test.ts +71 -0
- package/src/sdd/index-generator.ts +9 -9
- package/src/test-setup/__tests__/project-fixture.test.ts +178 -0
- package/src/test-setup/project-fixture.ts +87 -0
- package/src/tools/CONTEXT.md +6 -0
- package/src/tools/__tests__/registry.test.ts +221 -0
- package/src/types/__tests__/types.test.ts +4 -5
- package/src/types/constraint.ts +0 -25
- package/src/types/passes-gate.ts +10 -30
- package/src/types/project-config.ts +1 -1
- package/src/types/session.ts +5 -5
- package/src/utils/__tests__/frontmatter.test.ts +206 -0
- package/src/utils/__tests__/jsonl-skip-disposition.test.ts +175 -0
- package/src/utils/__tests__/jsonl.test.ts +187 -0
- package/src/utils/__tests__/package-version.test.ts +97 -0
- package/src/utils/exec.ts +15 -0
- package/src/utils/file-walk.ts +11 -2
- package/src/utils/frontmatter.ts +121 -0
- package/src/utils/jsonl.ts +167 -0
- package/src/utils/package-version.ts +27 -0
- package/dist/cli/commands/doc-freshness-check.d.ts +0 -53
- package/dist/cli/commands/doc-freshness-check.d.ts.map +0 -1
- package/dist/cli/commands/doc-freshness-check.js +0 -352
- package/dist/cli/commands/doc-freshness-check.js.map +0 -1
- package/dist/types/index.d.ts +0 -14
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -39
- package/dist/types/index.js.map +0 -1
- package/src/__tests__/long-running.test.ts +0 -17
- package/src/__tests__/passes-gate-extension.test.ts +0 -151
- package/src/cli/commands/__tests__/doc-freshness-check.test.ts +0 -168
- package/src/cli/commands/doc-freshness-check.ts +0 -386
- package/src/spec/CONTEXT.md +0 -11
- package/src/types/index.ts +0 -47
|
@@ -5,9 +5,13 @@
|
|
|
5
5
|
* harness command "rm -rf /"
|
|
6
6
|
* harness command --level "DROP TABLE users"
|
|
7
7
|
* harness command --list
|
|
8
|
+
*
|
|
9
|
+
* 判定经返回值外溢(架构评审候选7):风险等级/黑名单裁决译成 kind,
|
|
10
|
+
* 退出码映射收敛在 bin 一处。
|
|
8
11
|
*/
|
|
9
12
|
|
|
10
13
|
import { createCommandGate, getCommandRiskLevel, DEFAULT_COMMAND_BLACKLIST, type CommandBlacklistRule } from '../../gates';
|
|
14
|
+
import { log, logError, processIO, type CommandIO, type CommandResult } from '../command-contract';
|
|
11
15
|
|
|
12
16
|
export interface CommandCheckOptions {
|
|
13
17
|
level?: boolean;
|
|
@@ -19,17 +23,21 @@ export interface CommandCheckOptions {
|
|
|
19
23
|
/**
|
|
20
24
|
* 执行命令黑名单检查(供 bin/harness.js 调用)
|
|
21
25
|
*/
|
|
22
|
-
export async function executeCommand(
|
|
26
|
+
export async function executeCommand(
|
|
27
|
+
cmd: string | undefined,
|
|
28
|
+
options: CommandCheckOptions,
|
|
29
|
+
io: CommandIO = processIO,
|
|
30
|
+
): Promise<CommandResult> {
|
|
23
31
|
if (options.list) {
|
|
24
32
|
if (options.json) {
|
|
25
|
-
|
|
33
|
+
log(io, JSON.stringify(DEFAULT_COMMAND_BLACKLIST.map((r: CommandBlacklistRule) => ({
|
|
26
34
|
id: r.id,
|
|
27
35
|
level: r.level,
|
|
28
36
|
message: r.message,
|
|
29
37
|
category: r.category,
|
|
30
38
|
})), null, 2));
|
|
31
39
|
} else {
|
|
32
|
-
|
|
40
|
+
log(io, '\n命令黑名单规则:\n');
|
|
33
41
|
|
|
34
42
|
const byCategory = DEFAULT_COMMAND_BLACKLIST.reduce((acc: Record<string, CommandBlacklistRule[]>, rule: CommandBlacklistRule) => {
|
|
35
43
|
if (!acc[rule.category]) acc[rule.category] = [];
|
|
@@ -38,23 +46,23 @@ export async function executeCommand(cmd: string | undefined, options: CommandCh
|
|
|
38
46
|
}, {});
|
|
39
47
|
|
|
40
48
|
for (const [category, rules] of Object.entries(byCategory)) {
|
|
41
|
-
|
|
49
|
+
log(io, `[${category}]`);
|
|
42
50
|
for (const rule of rules as CommandBlacklistRule[]) {
|
|
43
51
|
const levelIcon = rule.level === 'block' ? '🚫' : rule.level === 'warn' ? '⚠️' : '📋';
|
|
44
|
-
|
|
52
|
+
log(io, ` ${levelIcon} ${rule.id}: ${rule.message} (${rule.level})`);
|
|
45
53
|
}
|
|
46
|
-
|
|
54
|
+
log(io);
|
|
47
55
|
}
|
|
48
56
|
|
|
49
|
-
|
|
57
|
+
log(io, `共 ${DEFAULT_COMMAND_BLACKLIST.length} 条规则`);
|
|
50
58
|
}
|
|
51
|
-
return;
|
|
59
|
+
return { kind: 'ok' };
|
|
52
60
|
}
|
|
53
61
|
|
|
54
62
|
if (!cmd) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
63
|
+
logError(io, '错误:请提供要检查的命令');
|
|
64
|
+
logError(io, '用法:harness command "your command"');
|
|
65
|
+
return { kind: 'usage-error', reason: '缺少要检查的命令参数' };
|
|
58
66
|
}
|
|
59
67
|
|
|
60
68
|
const gate = createCommandGate({ strict: options.strict });
|
|
@@ -63,28 +71,33 @@ export async function executeCommand(cmd: string | undefined, options: CommandCh
|
|
|
63
71
|
if (options.level) {
|
|
64
72
|
const level = getCommandRiskLevel(cmd);
|
|
65
73
|
if (options.json) {
|
|
66
|
-
|
|
74
|
+
log(io, JSON.stringify({ level, command: cmd }));
|
|
67
75
|
} else {
|
|
68
76
|
const levelColors: Record<string, string> = {
|
|
69
77
|
high: '\x1b[31m',
|
|
70
78
|
medium: '\x1b[33m',
|
|
71
79
|
low: '\x1b[32m',
|
|
72
80
|
};
|
|
73
|
-
|
|
81
|
+
log(io, `${levelColors[level]}${level}\x1b[0m ${cmd}`);
|
|
74
82
|
}
|
|
75
|
-
|
|
83
|
+
// 严重级闸门(历史条件式):high → 非零退出
|
|
84
|
+
return level === 'high'
|
|
85
|
+
? { kind: 'fail', reason: `command risk level is high: ${cmd}` }
|
|
86
|
+
: { kind: 'ok' };
|
|
76
87
|
}
|
|
77
88
|
|
|
78
89
|
if (options.json) {
|
|
79
|
-
|
|
90
|
+
log(io, JSON.stringify({
|
|
80
91
|
command: cmd,
|
|
81
92
|
passed: result.passed,
|
|
82
93
|
message: result.message,
|
|
83
94
|
details: result.details,
|
|
84
95
|
}, null, 2));
|
|
85
96
|
} else {
|
|
86
|
-
|
|
97
|
+
log(io, result.passed ? `\x1b[32m✓\x1b[0m ${result.message}` : `\x1b[31m✗\x1b[0m ${result.message}`);
|
|
87
98
|
}
|
|
88
99
|
|
|
89
|
-
|
|
100
|
+
return result.passed
|
|
101
|
+
? { kind: 'ok' }
|
|
102
|
+
: { kind: 'fail', reason: `command gate denied: ${result.message}` };
|
|
90
103
|
}
|
|
@@ -14,14 +14,16 @@ import * as path from 'path';
|
|
|
14
14
|
import chalk from 'chalk';
|
|
15
15
|
import {
|
|
16
16
|
buildConstraintsUsageReport,
|
|
17
|
+
CANDIDATE_KIND_LABEL,
|
|
17
18
|
DEFAULT_DIAGNOSE_THRESHOLDS,
|
|
18
19
|
type ConstraintsUsageReport,
|
|
19
20
|
type ConstraintUsageStats,
|
|
20
21
|
type DiagnoseThresholds,
|
|
21
|
-
type RetireCandidate,
|
|
22
22
|
} from '../../core/constraints/usage-report';
|
|
23
23
|
import { getConstraintsMeta } from './constraints';
|
|
24
24
|
import { detectInjectionDrift, type InjectionDrift } from '../../core/constraints/injection-drift';
|
|
25
|
+
import { GOVERNANCE_HEADING } from '../../core/constraints/injection-writer';
|
|
26
|
+
import { log, processIO, type CommandIO, type CommandResult } from '../command-contract';
|
|
25
27
|
|
|
26
28
|
export interface ConstraintsReportOptions {
|
|
27
29
|
projectPath?: string;
|
|
@@ -36,13 +38,6 @@ export interface ConstraintsReportOptions {
|
|
|
36
38
|
noiseMinTotal?: number;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
|
-
const CANDIDATE_KIND_LABEL: Record<RetireCandidate['kind'], string> = {
|
|
40
|
-
zero_trigger: '零触发',
|
|
41
|
-
unevaluable: '不可评估',
|
|
42
|
-
high_noise: '高噪',
|
|
43
|
-
zero_intercept: '零拦截',
|
|
44
|
-
};
|
|
45
|
-
|
|
46
41
|
function formatTime(ts: number | undefined): string {
|
|
47
42
|
return ts === undefined ? '-' : new Date(ts).toISOString().slice(0, 10);
|
|
48
43
|
}
|
|
@@ -74,6 +69,10 @@ export function renderExportMarkdown(
|
|
|
74
69
|
lines.push('');
|
|
75
70
|
lines.push(`- harness 版本: ${version}`);
|
|
76
71
|
lines.push(`- 日期: ${now.toISOString().slice(0, 10)}`);
|
|
72
|
+
if (report.skippedLines > 0) {
|
|
73
|
+
// 脱敏:只报条数,不报路径、不报坏行内容
|
|
74
|
+
lines.push(`- ⚠️ trace 文件有 ${report.skippedLines} 行损坏已跳过,下表统计只含其余合法记录`);
|
|
75
|
+
}
|
|
77
76
|
lines.push('');
|
|
78
77
|
|
|
79
78
|
lines.push('## 统计表(check 层)');
|
|
@@ -120,7 +119,7 @@ export function renderInjectionDriftLines(drift: InjectionDrift): string[] {
|
|
|
120
119
|
if (drift.notInjected) {
|
|
121
120
|
lines.push(' CLAUDE.md / AGENTS.md 均无约束注入标记段(未注入,不算漂移);可运行 npx @dommaker/harness init 注入');
|
|
122
121
|
if (drift.duplicateHeading) {
|
|
123
|
-
lines.push(
|
|
122
|
+
lines.push(` 另检测到多个 "${GOVERNANCE_HEADING}" 标题(历史遗留重复章节),建议手工清理后重跑 npx @dommaker/harness init`);
|
|
124
123
|
}
|
|
125
124
|
return lines;
|
|
126
125
|
}
|
|
@@ -141,7 +140,7 @@ export function renderInjectionDriftLines(drift: InjectionDrift): string[] {
|
|
|
141
140
|
}
|
|
142
141
|
}
|
|
143
142
|
if (drift.duplicateHeading) {
|
|
144
|
-
lines.push(
|
|
143
|
+
lines.push(` 重复章节: 标记段之外还存在另一个 "${GOVERNANCE_HEADING}" 标题`);
|
|
145
144
|
}
|
|
146
145
|
lines.push(` 修复: ${drift.fixHint}`);
|
|
147
146
|
return lines;
|
|
@@ -150,7 +149,7 @@ export function renderInjectionDriftLines(drift: InjectionDrift): string[] {
|
|
|
150
149
|
/**
|
|
151
150
|
* CLI handler: harness constraints report
|
|
152
151
|
*/
|
|
153
|
-
export async function constraintsReport(options: ConstraintsReportOptions = {}): Promise<
|
|
152
|
+
export async function constraintsReport(options: ConstraintsReportOptions = {}, io: CommandIO = processIO): Promise<CommandResult> {
|
|
154
153
|
const projectRoot = options.projectPath || process.cwd();
|
|
155
154
|
const thresholds: Partial<DiagnoseThresholds> = {};
|
|
156
155
|
if (options.zeroInterceptMin !== undefined) thresholds.zeroInterceptMinEvaluated = options.zeroInterceptMin;
|
|
@@ -160,58 +159,61 @@ export async function constraintsReport(options: ConstraintsReportOptions = {}):
|
|
|
160
159
|
const report = buildConstraintsUsageReport(projectRoot, thresholds);
|
|
161
160
|
|
|
162
161
|
if (options.json) {
|
|
163
|
-
|
|
164
|
-
return;
|
|
162
|
+
log(io, JSON.stringify(report, null, 2));
|
|
163
|
+
return { kind: 'ok' };
|
|
165
164
|
}
|
|
166
165
|
|
|
167
|
-
|
|
166
|
+
log(io, chalk.blue('📊 约束使用报告'));
|
|
168
167
|
if (!report.traceFileExists) {
|
|
169
|
-
|
|
168
|
+
log(io, chalk.gray(' (trace 文件不存在,全部按零触发统计)'));
|
|
169
|
+
}
|
|
170
|
+
if (report.skippedLines > 0) {
|
|
171
|
+
log(io, chalk.yellow(` ⚠️ trace 文件有 ${report.skippedLines} 行损坏已跳过,统计只含其余合法记录(数据不完整)`));
|
|
170
172
|
}
|
|
171
|
-
|
|
173
|
+
log(io);
|
|
172
174
|
|
|
173
175
|
// 统计表
|
|
174
|
-
|
|
176
|
+
log(io, chalk.bold('统计表(check 层):'));
|
|
175
177
|
for (const s of report.stats) {
|
|
176
|
-
|
|
178
|
+
log(io, ` ${renderStatsRow(s)}`);
|
|
177
179
|
}
|
|
178
|
-
|
|
180
|
+
log(io);
|
|
179
181
|
|
|
180
182
|
// 候选诊断
|
|
181
|
-
|
|
183
|
+
log(io, chalk.bold(`退役候选(${report.candidates.length} 条,阈值: 零拦截≥${thresholds.zeroInterceptMinEvaluated ?? DEFAULT_DIAGNOSE_THRESHOLDS.zeroInterceptMinEvaluated} 次评估, 高噪 fail率>${Math.round((thresholds.highNoiseFailRate ?? DEFAULT_DIAGNOSE_THRESHOLDS.highNoiseFailRate) * 100)}% 且 ≥${thresholds.highNoiseMinEvaluated ?? DEFAULT_DIAGNOSE_THRESHOLDS.highNoiseMinEvaluated} 次评估):`));
|
|
182
184
|
if (report.candidates.length === 0) {
|
|
183
|
-
|
|
185
|
+
log(io, chalk.green(' (无候选)'));
|
|
184
186
|
} else {
|
|
185
187
|
for (const c of report.candidates) {
|
|
186
|
-
|
|
188
|
+
log(io, ` [${CANDIDATE_KIND_LABEL[c.kind]}] ${c.id} — ${c.reason}`);
|
|
187
189
|
}
|
|
188
|
-
|
|
190
|
+
log(io, chalk.gray(' 可运行 `harness constraints retire` 交互式处理候选'));
|
|
189
191
|
}
|
|
190
|
-
|
|
192
|
+
log(io);
|
|
191
193
|
|
|
192
194
|
// 注入清单
|
|
193
|
-
|
|
195
|
+
log(io, chalk.bold(`当前生效 prompt 注入(${report.activePromptIds.length} 条):`));
|
|
194
196
|
for (const id of report.activePromptIds) {
|
|
195
|
-
|
|
197
|
+
log(io, ` ${id}`);
|
|
196
198
|
}
|
|
197
|
-
|
|
199
|
+
log(io);
|
|
198
200
|
|
|
199
201
|
// 配置健康
|
|
200
202
|
if (report.lint.unknownIds.length > 0) {
|
|
201
|
-
|
|
203
|
+
log(io, chalk.yellow('⚠️ 配置健康:'));
|
|
202
204
|
for (const id of report.lint.unknownIds) {
|
|
203
|
-
|
|
205
|
+
log(io, chalk.yellow(` config.yml 中禁用了不存在/已移除的约束 id: ${id}(残留配置,建议清理)`));
|
|
204
206
|
}
|
|
205
|
-
|
|
207
|
+
log(io);
|
|
206
208
|
}
|
|
207
209
|
|
|
208
210
|
// 注入漂移(ADR-0001 决策 7:条目级差异 + 修复指引;--export 摘要不含本地漂移状态)
|
|
209
|
-
|
|
211
|
+
log(io, chalk.bold('注入漂移:'));
|
|
210
212
|
const drift = detectInjectionDrift(projectRoot);
|
|
211
213
|
for (const line of renderInjectionDriftLines(drift)) {
|
|
212
|
-
|
|
214
|
+
log(io, drift.hasDrift ? chalk.yellow(line) : line);
|
|
213
215
|
}
|
|
214
|
-
|
|
216
|
+
log(io);
|
|
215
217
|
|
|
216
218
|
// --export
|
|
217
219
|
if (options.export !== undefined && options.export !== false) {
|
|
@@ -229,6 +231,7 @@ export async function constraintsReport(options: ConstraintsReportOptions = {}):
|
|
|
229
231
|
|
|
230
232
|
fs.mkdirSync(path.dirname(exportPath), { recursive: true });
|
|
231
233
|
fs.writeFileSync(exportPath, markdown, 'utf-8');
|
|
232
|
-
|
|
234
|
+
log(io, chalk.green(`✅ 脱敏报告已导出: ${exportPath}`));
|
|
233
235
|
}
|
|
236
|
+
return { kind: 'ok' };
|
|
234
237
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* harness constraints retire —— 约束退役(ADR-0001 决策 2/5)
|
|
3
3
|
*
|
|
4
4
|
* 建议层全自动(候选诊断复用 report 数据层),执行层保留一次人确认。
|
|
5
|
-
*
|
|
5
|
+
* 落盘形态(studio#82 D6 一处真相):
|
|
6
6
|
*
|
|
7
7
|
* - 内置约束 → config.yml `enabled: false` + `retired` 元数据:
|
|
8
8
|
*
|
|
@@ -33,21 +33,24 @@
|
|
|
33
33
|
import * as fs from 'fs';
|
|
34
34
|
import * as path from 'path';
|
|
35
35
|
import * as readline from 'readline';
|
|
36
|
+
import { log, logError, processIO, type CommandIO, type CommandResult } from '../command-contract';
|
|
36
37
|
import * as yaml from 'js-yaml';
|
|
37
38
|
import chalk from 'chalk';
|
|
38
39
|
import { getConstraint } from '../../core/constraints/definitions';
|
|
39
|
-
import { renderConstraintsSection, CONSTRAINTS_END_MARKER } from '../../core/constraints/injection-renderer';
|
|
40
|
-
import { resolveInjectionTarget } from '../../core/constraints/injection-
|
|
40
|
+
import { renderConstraintsSection, CONSTRAINTS_START_MARKER, CONSTRAINTS_END_MARKER } from '../../core/constraints/injection-renderer';
|
|
41
|
+
import { replaceStandaloneRange, resolveInjectionTarget } from '../../core/constraints/injection-writer';
|
|
41
42
|
import { getEffectiveConstraints } from '../../core/effective-constraints';
|
|
42
43
|
import { loadRawProjectConfig, ProjectConfigLoader } from '../../core/project-config-loader';
|
|
44
|
+
import { getHarnessPackageVersion } from '../../utils/package-version';
|
|
43
45
|
import { FileKnowledgeStore } from '../../knowledge/store';
|
|
44
46
|
import type { KnowledgeEntry } from '../../knowledge/types';
|
|
45
47
|
import type { Constraint } from '../../types/constraint';
|
|
46
48
|
import {
|
|
47
49
|
buildConstraintsUsageReport,
|
|
50
|
+
CANDIDATE_KIND_LABEL,
|
|
48
51
|
collectUsageByConstraint,
|
|
49
52
|
readProjectTraces,
|
|
50
|
-
|
|
53
|
+
readProjectTracesReport,
|
|
51
54
|
} from '../../core/constraints/usage-report';
|
|
52
55
|
|
|
53
56
|
export interface RetireExecuteOptions {
|
|
@@ -64,7 +67,7 @@ export interface RetireResult {
|
|
|
64
67
|
status: RetireStatus;
|
|
65
68
|
/** 是否 check 层 iron(交互模式据此追加确认) */
|
|
66
69
|
isIronLaw: boolean;
|
|
67
|
-
/** 退役落点:custom 约束落 custom-constraints.yml
|
|
70
|
+
/** 退役落点:custom 约束落 custom-constraints.yml(studio#82 D6),内置落 config.yml */
|
|
68
71
|
landing: 'config.yml' | 'custom-constraints.yml';
|
|
69
72
|
stats: { total: number; fail: number; failRate: number };
|
|
70
73
|
/** 治理注入段(CLAUDE.md / AGENTS.md)是否已同步 */
|
|
@@ -128,18 +131,6 @@ function findRetireTarget(projectRoot: string, id: string): RetireTargetInfo | u
|
|
|
128
131
|
return undefined;
|
|
129
132
|
}
|
|
130
133
|
|
|
131
|
-
/**
|
|
132
|
-
* 读取 harness 版本(与 init.ts 同路径策略)
|
|
133
|
-
*/
|
|
134
|
-
function getHarnessVersion(): string {
|
|
135
|
-
try {
|
|
136
|
-
const pkgPath = path.join(__dirname, '..', '..', '..', 'package.json');
|
|
137
|
-
return JSON.parse(fs.readFileSync(pkgPath, 'utf-8')).version ?? 'unknown';
|
|
138
|
-
} catch {
|
|
139
|
-
return 'unknown';
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
134
|
/**
|
|
144
135
|
* 写 config.yml 退役段(ADR-0001 决策 5)
|
|
145
136
|
*
|
|
@@ -174,7 +165,7 @@ function writeRetireConfig(
|
|
|
174
165
|
}
|
|
175
166
|
|
|
176
167
|
/**
|
|
177
|
-
* 写 custom-constraints.yml
|
|
168
|
+
* 写 custom-constraints.yml 退役段(studio#82 D6 统一落点)
|
|
178
169
|
*
|
|
179
170
|
* 在 custom_constraints.<id> 条目内追加 retired 元数据,保留规则原文。
|
|
180
171
|
* js-yaml 不保留注释:原文件含注释行时重写会丢失,console 说明。
|
|
@@ -280,12 +271,10 @@ function syncGovernanceInjection(projectRoot: string): { synced: boolean; file?:
|
|
|
280
271
|
const target = resolveInjectionTarget(projectRoot);
|
|
281
272
|
if (!target) return { synced: false };
|
|
282
273
|
|
|
283
|
-
const
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
if (newContent !== target.content) {
|
|
288
|
-
fs.writeFileSync(filePath, newContent, 'utf-8');
|
|
274
|
+
const body = renderConstraintsSection(getEffectiveConstraints(projectRoot), getHarnessPackageVersion());
|
|
275
|
+
const write = replaceStandaloneRange(target.content, CONSTRAINTS_START_MARKER, CONSTRAINTS_END_MARKER, body);
|
|
276
|
+
if (write.kind === 'updated' && write.content !== target.content) {
|
|
277
|
+
fs.writeFileSync(path.join(projectRoot, target.file), write.content, 'utf-8');
|
|
289
278
|
}
|
|
290
279
|
return { synced: true, file: target.file };
|
|
291
280
|
}
|
|
@@ -327,6 +316,9 @@ export function retireConstraint(
|
|
|
327
316
|
}
|
|
328
317
|
|
|
329
318
|
// 历史统计(来自 traces.log)
|
|
319
|
+
// 计数去向:兼容包装 readProjectTraces() 丢计数(harness#100)——落盘的 retire stats 只计
|
|
320
|
+
// 合法记录,把坏行数写进 RetireResult.stats 属形状变更不在本票;本函数按契约「纯执行无交互」
|
|
321
|
+
// 不打印,告知由两条命令入口各自负责(runRetireInteractive 顶部 / constraintsRetire 的 --yes 分支)
|
|
330
322
|
const usage = collectUsageByConstraint(readProjectTraces(projectRoot)).get(id);
|
|
331
323
|
const evaluated = usage ? usage.total - usage.skip : 0;
|
|
332
324
|
const stats = {
|
|
@@ -366,29 +358,30 @@ export function retireConstraint(
|
|
|
366
358
|
/**
|
|
367
359
|
* 打印单条退役结果(含回滚语义提示)
|
|
368
360
|
*/
|
|
369
|
-
export function printRetireResult(result: RetireResult):
|
|
361
|
+
export function printRetireResult(result: RetireResult, io: CommandIO = processIO): CommandResult {
|
|
370
362
|
switch (result.status) {
|
|
371
363
|
case 'unknown_id':
|
|
372
|
-
|
|
373
|
-
return;
|
|
364
|
+
log(io, chalk.red(`❌ ${result.id}: 约束不存在(既非内置也非 custom-constraints),未做任何变更`));
|
|
365
|
+
return { kind: 'skip', reason: `${result.id}: 约束不存在,未做任何变更` };
|
|
374
366
|
case 'already_retired':
|
|
375
|
-
|
|
376
|
-
return;
|
|
367
|
+
log(io, chalk.yellow(`⚠️ ${result.id}: 已处于退役状态(config.yml 中 enabled: false),跳过`));
|
|
368
|
+
return { kind: 'skip', reason: `${result.id}: 已处于退役状态,跳过` };
|
|
377
369
|
case 'retired': {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
370
|
+
log(io, chalk.green(`✅ ${result.id}: 已退役`));
|
|
371
|
+
log(io, ` 历史统计: total=${result.stats.total} fail=${result.stats.fail} fail率=${Math.round(result.stats.failRate * 100)}%`);
|
|
372
|
+
log(io, ` 知识沉淀: ${result.knowledgeEntryId}(.harness/knowledge)`);
|
|
381
373
|
if (result.injectionSynced) {
|
|
382
|
-
|
|
374
|
+
log(io, ` 已同步 ${result.injectionFile ?? '治理文档'} 注入段`);
|
|
383
375
|
}
|
|
384
376
|
const recovery =
|
|
385
377
|
result.landing === 'custom-constraints.yml'
|
|
386
378
|
? `删除 custom-constraints.yml 中 custom_constraints.${result.id}.retired 段`
|
|
387
379
|
: `删除 config.yml 中 constraints.${result.id} 段`;
|
|
388
|
-
|
|
380
|
+
log(io, chalk.gray(` retire 不是删除——恢复方法:${recovery}`));
|
|
389
381
|
break;
|
|
390
382
|
}
|
|
391
383
|
}
|
|
384
|
+
return { kind: 'ok' };
|
|
392
385
|
}
|
|
393
386
|
|
|
394
387
|
// ========================================
|
|
@@ -408,13 +401,6 @@ function createAsk(io: RetireIO): { ask: (q: string) => Promise<string>; close:
|
|
|
408
401
|
};
|
|
409
402
|
}
|
|
410
403
|
|
|
411
|
-
const CANDIDATE_KIND_LABEL: Record<RetireCandidate['kind'], string> = {
|
|
412
|
-
zero_trigger: '零触发',
|
|
413
|
-
unevaluable: '不可评估',
|
|
414
|
-
high_noise: '高噪',
|
|
415
|
-
zero_intercept: '零拦截',
|
|
416
|
-
};
|
|
417
|
-
|
|
418
404
|
/**
|
|
419
405
|
* 交互式退役(候选列表 → 编号多选 → 摘要 → 确认 → 执行)
|
|
420
406
|
*
|
|
@@ -423,9 +409,16 @@ const CANDIDATE_KIND_LABEL: Record<RetireCandidate['kind'], string> = {
|
|
|
423
409
|
export async function runRetireInteractive(
|
|
424
410
|
projectRoot: string,
|
|
425
411
|
io: RetireIO = { input: process.stdin, output: process.stdout }
|
|
426
|
-
): Promise<
|
|
412
|
+
): Promise<CommandResult> {
|
|
427
413
|
const report = buildConstraintsUsageReport(projectRoot);
|
|
414
|
+
// 候选诊断是退役决策的依据:数据不完整必须先说(harness#100,与 report 同一降级维度);
|
|
415
|
+
// 告知行走 stderr,与 status / failure list / 直达分支同一去向(交互正文仍走 console.log)
|
|
416
|
+
if (report.skippedLines > 0) {
|
|
417
|
+
console.error(chalk.yellow(`⚠️ trace 文件有 ${report.skippedLines} 行损坏已跳过,候选只基于其余合法记录`));
|
|
418
|
+
}
|
|
428
419
|
const { ask, close } = createAsk(io);
|
|
420
|
+
// 退役结果打印走注入流(与 readline 提示同一去向)
|
|
421
|
+
const out = { stdout: io.output, stderr: io.output } as unknown as CommandIO;
|
|
429
422
|
|
|
430
423
|
try {
|
|
431
424
|
let selectedIds: string[] = [];
|
|
@@ -435,7 +428,7 @@ export async function runRetireInteractive(
|
|
|
435
428
|
const manual = await ask('可手动输入要退役的约束 id(留空取消): ');
|
|
436
429
|
if (!manual) {
|
|
437
430
|
console.log('已取消');
|
|
438
|
-
return;
|
|
431
|
+
return { kind: 'skip', reason: '交互未确认,未做任何变更' };
|
|
439
432
|
}
|
|
440
433
|
selectedIds = [manual];
|
|
441
434
|
} else {
|
|
@@ -447,7 +440,7 @@ export async function runRetireInteractive(
|
|
|
447
440
|
const answer = await ask('输入编号(逗号分隔多选)或约束 id,留空取消: ');
|
|
448
441
|
if (!answer) {
|
|
449
442
|
console.log('已取消');
|
|
450
|
-
return;
|
|
443
|
+
return { kind: 'skip', reason: '交互未确认,未做任何变更' };
|
|
451
444
|
}
|
|
452
445
|
|
|
453
446
|
for (const token of answer.split(',').map(s => s.trim()).filter(Boolean)) {
|
|
@@ -482,7 +475,7 @@ export async function runRetireInteractive(
|
|
|
482
475
|
|
|
483
476
|
if (plan.length === 0) {
|
|
484
477
|
console.log('无可执行项,已取消');
|
|
485
|
-
return;
|
|
478
|
+
return { kind: 'skip', reason: '交互未确认,未做任何变更' };
|
|
486
479
|
}
|
|
487
480
|
|
|
488
481
|
// 变更摘要 → 最终确认
|
|
@@ -500,17 +493,18 @@ export async function runRetireInteractive(
|
|
|
500
493
|
const finalConfirm = await ask('确认执行?(y/N) ');
|
|
501
494
|
if (finalConfirm.toLowerCase() !== 'y' && finalConfirm.toLowerCase() !== 'yes') {
|
|
502
495
|
console.log('已取消');
|
|
503
|
-
return;
|
|
496
|
+
return { kind: 'skip', reason: '交互未确认,未做任何变更' };
|
|
504
497
|
}
|
|
505
498
|
|
|
506
499
|
console.log();
|
|
507
500
|
for (const p of plan) {
|
|
508
501
|
const result = retireConstraint(projectRoot, p.id, { reason: p.reason });
|
|
509
|
-
printRetireResult(result);
|
|
502
|
+
printRetireResult(result, out);
|
|
510
503
|
}
|
|
511
504
|
} finally {
|
|
512
505
|
close();
|
|
513
506
|
}
|
|
507
|
+
return { kind: 'ok' };
|
|
514
508
|
}
|
|
515
509
|
|
|
516
510
|
/**
|
|
@@ -519,29 +513,38 @@ export async function runRetireInteractive(
|
|
|
519
513
|
* 人确认闸门(#24,ADR-0001 决策 2):带 id 的直达路径必须显式 `--yes`,
|
|
520
514
|
* 无 `--yes` 报错 + 非零退出码,提示改用 `--yes` 或交互模式;不落盘任何文件。
|
|
521
515
|
*/
|
|
522
|
-
export async function constraintsRetire(
|
|
516
|
+
export async function constraintsRetire(
|
|
517
|
+
id?: string,
|
|
518
|
+
options: ConstraintsRetireOptions = {},
|
|
519
|
+
io: CommandIO = processIO,
|
|
520
|
+
): Promise<CommandResult> {
|
|
523
521
|
const projectRoot = options.projectPath || process.cwd();
|
|
524
522
|
|
|
525
523
|
if (id) {
|
|
526
524
|
// 非交互直达:执行层人确认对所有入口成立(含程序化调用方)
|
|
527
525
|
if (!options.yes) {
|
|
528
|
-
|
|
526
|
+
logError(io,
|
|
529
527
|
chalk.red(`❌ 直达退役需要显式人确认(ADR-0001 决策 2:执行层保留一次人确认),未做任何变更\n`) +
|
|
530
528
|
` 带 --yes 显式确认直达:harness constraints retire ${id} --yes` +
|
|
531
529
|
`${options.reason ? ` --reason "${options.reason}"` : ''}\n` +
|
|
532
530
|
` 或去掉 id 走交互确认:harness constraints retire`
|
|
533
531
|
);
|
|
534
|
-
|
|
535
|
-
|
|
532
|
+
return { kind: 'usage-error', reason: `直达退役 ${id} 缺少显式 --yes 人确认,未做任何变更` };
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// 落盘的 retire stats 只含合法记录:依据不完整要在执行前告知(harness#100,
|
|
536
|
+
// 直达路径不经过 runRetireInteractive,故两处各自告知)
|
|
537
|
+
const { skippedLines } = readProjectTracesReport(projectRoot);
|
|
538
|
+
if (skippedLines > 0) {
|
|
539
|
+
logError(io, chalk.yellow(`⚠️ trace 文件有 ${skippedLines} 行损坏已跳过,落盘的退役统计只基于其余合法记录`));
|
|
536
540
|
}
|
|
537
541
|
|
|
538
542
|
const result = retireConstraint(projectRoot, id, { reason: options.reason });
|
|
539
543
|
if (result.status === 'retired' && result.isIronLaw) {
|
|
540
|
-
|
|
544
|
+
log(io, chalk.yellow(`⚠️ ${id} 是一条 Iron Law,已通过 --yes 直达退役(交互模式会要求二次确认)`));
|
|
541
545
|
}
|
|
542
|
-
printRetireResult(result);
|
|
543
|
-
return;
|
|
546
|
+
return printRetireResult(result, io);
|
|
544
547
|
}
|
|
545
548
|
|
|
546
|
-
|
|
549
|
+
return runRetireInteractive(projectRoot);
|
|
547
550
|
}
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* 供 Studio 等消费者获取约束的 hash、计数、文本大小等元数据。
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { readFileSync, existsSync } from 'fs';
|
|
9
|
-
import { join } from 'path';
|
|
10
8
|
import { createHash } from 'crypto';
|
|
11
9
|
import { getAllConstraints } from '../../core/constraints/definitions';
|
|
10
|
+
import { getHarnessPackageVersion } from '../../utils/package-version';
|
|
11
|
+
import { log, processIO, type CommandIO, type CommandResult } from '../command-contract';
|
|
12
12
|
|
|
13
13
|
export interface ConstraintsMeta {
|
|
14
14
|
version: string;
|
|
@@ -17,24 +17,6 @@ export interface ConstraintsMeta {
|
|
|
17
17
|
textSize: { total: number; perConstraint: number };
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
function getPackageVersion(): string {
|
|
21
|
-
// Try several common locations
|
|
22
|
-
const candidates = [
|
|
23
|
-
join(__dirname, '..', '..', '..', 'package.json'),
|
|
24
|
-
join(process.cwd(), 'package.json'),
|
|
25
|
-
];
|
|
26
|
-
for (const p of candidates) {
|
|
27
|
-
if (existsSync(p)) {
|
|
28
|
-
try {
|
|
29
|
-
return JSON.parse(readFileSync(p, 'utf-8')).version;
|
|
30
|
-
} catch {
|
|
31
|
-
// continue to next candidate
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return 'unknown';
|
|
36
|
-
}
|
|
37
|
-
|
|
38
20
|
export function getConstraintsMeta(): ConstraintsMeta {
|
|
39
21
|
const constraints = getAllConstraints();
|
|
40
22
|
|
|
@@ -56,7 +38,7 @@ export function getConstraintsMeta(): ConstraintsMeta {
|
|
|
56
38
|
const hash = createHash('sha256').update(hashInput).digest('hex');
|
|
57
39
|
|
|
58
40
|
return {
|
|
59
|
-
version:
|
|
41
|
+
version: getHarnessPackageVersion(),
|
|
60
42
|
hash,
|
|
61
43
|
counts: {
|
|
62
44
|
ironLaws: ironLaws.length,
|
|
@@ -73,14 +55,15 @@ export function getConstraintsMeta(): ConstraintsMeta {
|
|
|
73
55
|
/**
|
|
74
56
|
* CLI handler: output --json
|
|
75
57
|
*/
|
|
76
|
-
export async function constraints(options: { json?: boolean }): Promise<
|
|
58
|
+
export async function constraints(options: { json?: boolean }, io: CommandIO = processIO): Promise<CommandResult> {
|
|
77
59
|
const meta = getConstraintsMeta();
|
|
78
60
|
if (options.json) {
|
|
79
|
-
|
|
61
|
+
log(io, JSON.stringify(meta, null, 2));
|
|
80
62
|
} else {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
63
|
+
log(io, `version: ${meta.version}`);
|
|
64
|
+
log(io, `hash: ${meta.hash}`);
|
|
65
|
+
log(io, `ironLaws: ${meta.counts.ironLaws}, guidelines: ${meta.counts.guidelines}, prompts: ${meta.counts.prompts}`);
|
|
66
|
+
log(io, `textSize: ${meta.textSize.total} chars total, ~${meta.textSize.perConstraint} chars/constraint`);
|
|
85
67
|
}
|
|
68
|
+
return { kind: 'ok' };
|
|
86
69
|
}
|