@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
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
import type { ConstraintCheck } from './types';
|
|
6
6
|
|
|
7
|
+
// m 标志必需:真实 diff 首行恒为 `diff --git`,缺 m 则 ^ 永不命中删除行(铁律静默失效)
|
|
7
8
|
const DELETED_TEST_PATTERNS = [
|
|
8
|
-
/^-\s*(test|it|describe)\s*\(
|
|
9
|
-
/^-\s*expect\s*\(
|
|
10
|
-
/^-\s*\/\/\s*test
|
|
9
|
+
/^-\s*(test|it|describe)\s*\(/m, // 删除 test/it/describe
|
|
10
|
+
/^-\s*expect\s*\(/m, // 删除 expect
|
|
11
|
+
/^-\s*\/\/\s*test/m, // 删除注释的 test
|
|
11
12
|
];
|
|
12
13
|
|
|
13
14
|
export const noTestSimplification: ConstraintCheck = {
|
|
@@ -29,8 +29,8 @@ export interface CheckEnv {
|
|
|
29
29
|
/**
|
|
30
30
|
* 证据提供者组:git diff / 源码扫描的 memoized I/O
|
|
31
31
|
*
|
|
32
|
-
* 由调用方绑定后传入 buildCheckEnv
|
|
33
|
-
* run
|
|
32
|
+
* 由调用方绑定后传入 buildCheckEnv(#87:git 两项绑 GitEvidence adapter 实例,
|
|
33
|
+
* 一次 run 一份,命令级 memo 在 adapter 层);工厂本身不做 memoization。
|
|
34
34
|
*/
|
|
35
35
|
export interface EvidenceProviders {
|
|
36
36
|
/** staged 全量 diff */
|
|
@@ -4,55 +4,25 @@
|
|
|
4
4
|
* 从仓库状态(git diff / traces / 文档标记)推断 ConstraintContext:
|
|
5
5
|
* 触发条件 + 各类证据标志。此前散落在 cli/commands/check.ts,
|
|
6
6
|
* 迁入 core 供 CLI 与其他调用方共用。
|
|
7
|
+
*
|
|
8
|
+
* 架构评审 #87:本模块只做装配不做取证——git 证据一律经 git-evidence
|
|
9
|
+
* adapter 取(缺省真 git adapter,调用方可注入与 checker 层同源的那一份),
|
|
10
|
+
* 因此此处不再有 child_process / raw execSync。
|
|
7
11
|
*/
|
|
8
12
|
|
|
9
13
|
import * as fs from 'fs';
|
|
10
14
|
import * as path from 'path';
|
|
11
|
-
import { execSync } from 'child_process';
|
|
12
|
-
import { execAsync } from '../../utils/exec';
|
|
13
15
|
import { detectSourceRoots } from '../../utils/detect-source-roots';
|
|
16
|
+
import { readJsonl } from '../../utils/jsonl';
|
|
14
17
|
import { DEFAULT_TRACE_FILE } from '../../types/trace';
|
|
18
|
+
import type { ExecutionTrace } from '../../types/trace';
|
|
15
19
|
import type { ConstraintContext, ConstraintTrigger } from '../../types/constraint';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* 从 git diff 获取变更的文件
|
|
19
|
-
*/
|
|
20
|
-
export async function getChangedFiles(staged: boolean, projectPath?: string): Promise<string[]> {
|
|
21
|
-
try {
|
|
22
|
-
const command = staged ? 'git diff --cached --name-only' : 'git diff --name-only';
|
|
23
|
-
const { stdout } = projectPath
|
|
24
|
-
? await execAsync(command, { cwd: projectPath })
|
|
25
|
-
: await execAsync(command);
|
|
26
|
-
return String(stdout).trim().split('\n').filter(Boolean);
|
|
27
|
-
} catch {
|
|
28
|
-
return [];
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* 一次性列出 HEAD 中存在的所有目录(工单 18:替代逐文件 git ls-tree)
|
|
34
|
-
*
|
|
35
|
-
* 返回 null 表示命令失败(按惯例视所有目录为"新")。
|
|
36
|
-
*/
|
|
37
|
-
export function listHeadDirs(projectPath: string): Set<string> | null {
|
|
38
|
-
try {
|
|
39
|
-
const output = execSync('git ls-tree -r --name-only HEAD', { cwd: projectPath, stdio: 'pipe', encoding: 'utf-8' });
|
|
40
|
-
const dirs = new Set<string>();
|
|
41
|
-
for (const file of String(output).split('\n')) {
|
|
42
|
-
if (!file) continue;
|
|
43
|
-
const parts = file.split('/');
|
|
44
|
-
for (let i = 1; i < parts.length; i++) {
|
|
45
|
-
dirs.add(parts.slice(0, i).join('/'));
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return dirs;
|
|
49
|
-
} catch {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
20
|
+
import { createGitEvidence, splitFileNames, type GitEvidence } from './git-evidence';
|
|
53
21
|
|
|
54
22
|
/**
|
|
55
23
|
* 检查文件所在目录是否在 git HEAD 中不存在(即新目录)
|
|
24
|
+
*
|
|
25
|
+
* headDirs 由 git-evidence adapter 取证(null = 命令失败,按惯例视所有目录为"新")。
|
|
56
26
|
*/
|
|
57
27
|
export function isNewDirectory(headDirs: Set<string> | null, filePath: string): boolean {
|
|
58
28
|
if (headDirs === null) return true; // 命令失败 = 假定为新
|
|
@@ -71,10 +41,17 @@ const CODE_FILE_REGEX = /\.(?:ts|tsx|js|jsx|mjs|cjs|py|go|rs|java|kt|rb|php|cs|c
|
|
|
71
41
|
*
|
|
72
42
|
* ADR-0001:变更包含代码文件时,在主推断之外附加 code_implementation
|
|
73
43
|
* (返回数组 [主推断, 'code_implementation'];主推断逻辑保持不变)。
|
|
44
|
+
*
|
|
45
|
+
* 新目录判定所需的 HEAD 目录集经 git 证据 adapter 取(#87):
|
|
46
|
+
* 调用方注入即与 checker 层同一份证据,缺省走真 git adapter。
|
|
74
47
|
*/
|
|
75
48
|
export function detectTrigger(
|
|
76
49
|
changedFiles: string[],
|
|
77
|
-
options: {
|
|
50
|
+
options: {
|
|
51
|
+
trigger?: ConstraintTrigger;
|
|
52
|
+
projectPath?: string;
|
|
53
|
+
evidence?: GitEvidence;
|
|
54
|
+
}
|
|
78
55
|
): ConstraintTrigger | ConstraintTrigger[] {
|
|
79
56
|
if (options.trigger) return options.trigger;
|
|
80
57
|
|
|
@@ -89,7 +66,10 @@ export function detectTrigger(
|
|
|
89
66
|
const hasModuleChange = changedFiles.some(f =>
|
|
90
67
|
sourceRoots.some(root => f.startsWith(root + '/') || f.startsWith(root + '\\')) && !f.includes('__tests__')
|
|
91
68
|
);
|
|
92
|
-
|
|
69
|
+
// 工单 18 的批量语义保留在 adapter 层:一次 ls-tree,且仅在有模块变更时才取证
|
|
70
|
+
const headDirs = hasModuleChange
|
|
71
|
+
? (options.evidence ?? createGitEvidence(projectPath)).headDirs()
|
|
72
|
+
: null;
|
|
93
73
|
const hasModuleCreation = changedFiles.some(f =>
|
|
94
74
|
sourceRoots.some(root => f.startsWith(root + '/') || f.startsWith(root + '\\')) &&
|
|
95
75
|
isNewDirectory(headDirs, f)
|
|
@@ -111,22 +91,11 @@ export function detectTrigger(
|
|
|
111
91
|
export async function detectFailingTest(projectPath: string): Promise<boolean> {
|
|
112
92
|
try {
|
|
113
93
|
const traceFile = path.join(projectPath, DEFAULT_TRACE_FILE);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
// 检查最近 20 条记录是否有 fail
|
|
121
|
-
const recent = lines.slice(-20);
|
|
122
|
-
return recent.some(line => {
|
|
123
|
-
try {
|
|
124
|
-
const trace = JSON.parse(line);
|
|
125
|
-
return trace.result === 'fail';
|
|
126
|
-
} catch {
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
});
|
|
94
|
+
// 坏行策略:skip(原逐行 catch→false 语义不变);只 parse 最近 20 行
|
|
95
|
+
// 计数去向:豁免(harness#100)——布尔证据探测,坏行只会让证据变少(判定方向保守),
|
|
96
|
+
// 消费面是 check 的 pass/fail 判定,没有可挂计数的输出位
|
|
97
|
+
const { records } = readJsonl<ExecutionTrace>(traceFile, 'skip', { tail: 20 });
|
|
98
|
+
return records.some(trace => trace.result === 'fail');
|
|
130
99
|
} catch {
|
|
131
100
|
return false;
|
|
132
101
|
}
|
|
@@ -161,22 +130,12 @@ export function detectRootCauseInvestigation(projectPath: string): boolean {
|
|
|
161
130
|
export async function detectVerificationEvidence(projectPath: string): Promise<boolean> {
|
|
162
131
|
try {
|
|
163
132
|
const traceFile = path.join(projectPath, DEFAULT_TRACE_FILE);
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
// 检查最近 10 条记录是否有 pass
|
|
171
|
-
const recent = lines.slice(-10);
|
|
172
|
-
return recent.some(line => {
|
|
173
|
-
try {
|
|
174
|
-
const trace = JSON.parse(line);
|
|
175
|
-
return trace.result === 'pass';
|
|
176
|
-
} catch {
|
|
177
|
-
return false;
|
|
178
|
-
}
|
|
179
|
-
});
|
|
133
|
+
// 坏行策略:skip(原逐行 catch→false 语义不变);只 parse 最近 10 行
|
|
134
|
+
// tail 在 parse 之前截断 → 坏行会占用尾部槽位(#82 裁决范围外的既有口径,本票不改)
|
|
135
|
+
// 计数去向:豁免(harness#100)——同 detectFailingTest:布尔证据探测无计数输出位,
|
|
136
|
+
// 坏行只会让证据变少
|
|
137
|
+
const { records } = readJsonl<ExecutionTrace>(traceFile, 'skip', { tail: 10 });
|
|
138
|
+
return records.some(trace => trace.result === 'pass');
|
|
180
139
|
} catch {
|
|
181
140
|
return false;
|
|
182
141
|
}
|
|
@@ -209,21 +168,6 @@ export function detectRequirement(projectPath: string): boolean {
|
|
|
209
168
|
return indicators.some(f => fs.existsSync(path.join(projectPath, f)));
|
|
210
169
|
}
|
|
211
170
|
|
|
212
|
-
/**
|
|
213
|
-
* 检测是否在 git worktree 中
|
|
214
|
-
*/
|
|
215
|
-
export function detectWorktree(projectPath: string): boolean {
|
|
216
|
-
try {
|
|
217
|
-
const gitDir = path.join(projectPath, '.git');
|
|
218
|
-
if (fs.existsSync(gitDir)) {
|
|
219
|
-
const content = fs.readFileSync(gitDir, 'utf-8');
|
|
220
|
-
// 实际 worktree 的 .git 是文件(指向主 repo),不是目录
|
|
221
|
-
return content.startsWith('gitdir:');
|
|
222
|
-
}
|
|
223
|
-
} catch { /* ignore */ }
|
|
224
|
-
return false;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
171
|
/**
|
|
228
172
|
* 检测是否有复用检查
|
|
229
173
|
* 检查 .harness/reuse/ 目录或相关文档
|
|
@@ -244,15 +188,20 @@ export function detectReuseCheck(projectPath: string): boolean {
|
|
|
244
188
|
|
|
245
189
|
/**
|
|
246
190
|
* 构建约束上下文:变更文件 + 触发条件推断 + 证据标志检测
|
|
191
|
+
*
|
|
192
|
+
* options.evidence(#87):git 证据适配器。调用方(CLI check)注入同一实例给
|
|
193
|
+
* checkConstraints,即可让 context-builder 与 checker 层共用同一证据来源。
|
|
247
194
|
*/
|
|
248
195
|
export async function buildConstraintContext(options: {
|
|
249
196
|
projectPath?: string;
|
|
250
197
|
staged: boolean;
|
|
251
198
|
trigger?: ConstraintTrigger;
|
|
199
|
+
evidence?: GitEvidence;
|
|
252
200
|
}): Promise<ConstraintContext> {
|
|
253
201
|
const projectPath = options.projectPath || process.cwd();
|
|
254
|
-
const
|
|
255
|
-
const
|
|
202
|
+
const evidence = options.evidence ?? createGitEvidence(projectPath);
|
|
203
|
+
const changedFiles = splitFileNames(evidence.changedFileNames(options.staged));
|
|
204
|
+
const inferred = detectTrigger(changedFiles, { trigger: options.trigger, projectPath, evidence });
|
|
256
205
|
const triggers = Array.isArray(inferred) ? inferred : [inferred];
|
|
257
206
|
|
|
258
207
|
return {
|
|
@@ -266,6 +215,5 @@ export async function buildConstraintContext(options: {
|
|
|
266
215
|
hasVerificationEvidence: await detectVerificationEvidence(projectPath),
|
|
267
216
|
hasReuseCheck: detectReuseCheck(projectPath),
|
|
268
217
|
hasRequirement: detectRequirement(projectPath),
|
|
269
|
-
hasWorktree: detectWorktree(projectPath),
|
|
270
218
|
};
|
|
271
219
|
}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { existsSync, readFileSync, readdirSync } from 'fs';
|
|
9
9
|
import { join } from 'path';
|
|
10
10
|
import { detectSourceRoots } from '../../../utils/detect-source-roots';
|
|
11
|
+
import { DEFAULT_SKIP_DIRS } from '../../../utils/file-walk';
|
|
11
12
|
import type {
|
|
12
13
|
DocFreshnessCheck,
|
|
13
14
|
DocFreshnessConfig,
|
|
@@ -238,7 +239,7 @@ export class FreshnessRunner {
|
|
|
238
239
|
if (!check.skip_reverse_check) {
|
|
239
240
|
// 从文档目录中推断要扫描的根目录集
|
|
240
241
|
const rootDirs = this.inferRootDirs(docDirs, ctx.projectPath);
|
|
241
|
-
const excludeSet = new Set(check.exclude ||
|
|
242
|
+
const excludeSet = new Set(check.exclude || DEFAULT_SKIP_DIRS);
|
|
242
243
|
|
|
243
244
|
for (const rootDir of rootDirs) {
|
|
244
245
|
const absRoot = join(ctx.projectPath, rootDir);
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* git 证据适配器(架构评审 #87)
|
|
3
|
+
*
|
|
4
|
+
* 全仓唯一的 git 取证点:context-builder(触发推断)与 checker 层(CheckEnv 证据)
|
|
5
|
+
* 共用同一实例 = 共用同一证据来源。此前两处各自抓真 git,一次 CLI check 里
|
|
6
|
+
* `git diff --cached --name-only` 实跑两遍。
|
|
7
|
+
*
|
|
8
|
+
* seam 上的两个真 adapter:
|
|
9
|
+
* - 缺省 realGitCommandRunner:真 git 子进程
|
|
10
|
+
* - 注入 runner:委托/计数/命令表(测试与定制场景)
|
|
11
|
+
*
|
|
12
|
+
* memo 落在实例层(命令 → 结果,含失败结果),实例生命周期 = 一次 check run,
|
|
13
|
+
* 因此不存在隐式全局(工单 18 的 run 级收益保留,形状改为显式传递)。
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { execSync } from 'child_process';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* git 命令执行器:返回 trim 后的 stdout,失败抛错(由 adapter 归类为「无该证据」)
|
|
20
|
+
*
|
|
21
|
+
* command 恒为本模块内的固定字面量,cwd 来自调用方(非 shell 拼接),无注入面。
|
|
22
|
+
*/
|
|
23
|
+
export type GitCommandRunner = (command: string, cwd: string) => string;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* git 证据:一次 run 内的 git 事实快照,同类命令至多执行一次
|
|
27
|
+
*
|
|
28
|
+
* 判定语义与原 context-builder / checker 私有实现逐条对齐:
|
|
29
|
+
* - diff 类命令失败 → 空串(无变更证据)
|
|
30
|
+
* - ls-tree 失败 → null(调用方按「所有目录都是新目录」处理)
|
|
31
|
+
*/
|
|
32
|
+
export interface GitEvidence {
|
|
33
|
+
/** 取证基准目录(git 命令的 cwd) */
|
|
34
|
+
readonly projectPath: string;
|
|
35
|
+
/** staged 全量 diff(`git diff --cached`) */
|
|
36
|
+
stagedDiff(): string;
|
|
37
|
+
/** 变更文件名列表,\n 分隔(staged → `git diff --cached --name-only`) */
|
|
38
|
+
changedFileNames(staged: boolean): string;
|
|
39
|
+
/** HEAD 中存在的目录集合;命令失败 → null */
|
|
40
|
+
headDirs(): Set<string> | null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** 与 utils/exec.runCommand 同一缓冲上限(大 diff 不 ENOBUFS) */
|
|
44
|
+
const GIT_MAX_BUFFER = 1024 * 1024;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 真 git adapter:同步 spawn,失败抛错交由 memo 归类
|
|
48
|
+
*
|
|
49
|
+
* execSync 声明返回 string | Buffer(Buffer 无 trim),故显式归一为 string——
|
|
50
|
+
* 与迁移前 context-builder 的 `String(output)` 取值语义一致。
|
|
51
|
+
*/
|
|
52
|
+
export const realGitCommandRunner: GitCommandRunner = (command, cwd) =>
|
|
53
|
+
String(
|
|
54
|
+
execSync(command, { cwd, stdio: 'pipe', encoding: 'utf-8', maxBuffer: GIT_MAX_BUFFER })
|
|
55
|
+
).trim();
|
|
56
|
+
|
|
57
|
+
const STAGED_DIFF = 'git diff --cached';
|
|
58
|
+
const STAGED_DIFF_NAMES = 'git diff --cached --name-only';
|
|
59
|
+
const UNSTAGED_DIFF_NAMES = 'git diff --name-only';
|
|
60
|
+
const HEAD_TREE = 'git ls-tree -r --name-only HEAD';
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 从 `git ls-tree -r --name-only HEAD` 输出提取 HEAD 中存在的所有目录
|
|
64
|
+
*
|
|
65
|
+
* 工单 18 批量语义:一次命令替代逐文件 ls-tree。
|
|
66
|
+
*/
|
|
67
|
+
export function parseHeadDirs(treeOutput: string): Set<string> {
|
|
68
|
+
const dirs = new Set<string>();
|
|
69
|
+
for (const file of treeOutput.split('\n')) {
|
|
70
|
+
if (!file) continue;
|
|
71
|
+
const parts = file.split('/');
|
|
72
|
+
for (let i = 1; i < parts.length; i++) {
|
|
73
|
+
dirs.add(parts.slice(0, i).join('/'));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return dirs;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* 构造 git 证据 adapter(生产侧唯一构造点)
|
|
81
|
+
*
|
|
82
|
+
* @param projectPath 取证目录
|
|
83
|
+
* @param run 命令执行器,缺省真 git;测试注入计数/替身执行器即可脱离子进程
|
|
84
|
+
*/
|
|
85
|
+
export function createGitEvidence(
|
|
86
|
+
projectPath: string,
|
|
87
|
+
run: GitCommandRunner = realGitCommandRunner
|
|
88
|
+
): GitEvidence {
|
|
89
|
+
type CommandResult = { ok: boolean; stdout: string };
|
|
90
|
+
const memo = new Map<string, CommandResult>();
|
|
91
|
+
|
|
92
|
+
const once = (command: string): CommandResult => {
|
|
93
|
+
let result = memo.get(command);
|
|
94
|
+
if (!result) {
|
|
95
|
+
try {
|
|
96
|
+
result = { ok: true, stdout: run(command, projectPath) };
|
|
97
|
+
} catch {
|
|
98
|
+
result = { ok: false, stdout: '' };
|
|
99
|
+
}
|
|
100
|
+
memo.set(command, result);
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
projectPath,
|
|
107
|
+
stagedDiff: () => once(STAGED_DIFF).stdout,
|
|
108
|
+
changedFileNames: (staged: boolean) =>
|
|
109
|
+
once(staged ? STAGED_DIFF_NAMES : UNSTAGED_DIFF_NAMES).stdout,
|
|
110
|
+
headDirs: () => {
|
|
111
|
+
const result = once(HEAD_TREE);
|
|
112
|
+
return result.ok ? parseHeadDirs(result.stdout) : null;
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** 变更文件名列表 → 路径数组(git 无输出时为空集合) */
|
|
118
|
+
export function splitFileNames(names: string): string[] {
|
|
119
|
+
return names.split('\n').filter(Boolean);
|
|
120
|
+
}
|
|
@@ -17,18 +17,18 @@
|
|
|
17
17
|
* 两处均无标记段 = 未注入,不算漂移(report 一句话提示,check 不警告)。
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import * as fs from 'fs';
|
|
21
20
|
import * as path from 'path';
|
|
22
21
|
import { getEffectiveConstraints } from '../effective-constraints';
|
|
22
|
+
import { getHarnessPackageVersion } from '../../utils/package-version';
|
|
23
|
+
import { CONSTRAINTS_END_MARKER, renderConstraintsSection } from './injection-renderer';
|
|
23
24
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
resolveInjectionTarget,
|
|
26
|
+
readIfExists,
|
|
27
|
+
countGovernanceHeadings,
|
|
28
|
+
type InjectionFile,
|
|
29
|
+
} from './injection-writer';
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
const INJECTION_FILES = ['CLAUDE.md', 'AGENTS.md'] as const;
|
|
31
|
-
export type InjectionFile = (typeof INJECTION_FILES)[number];
|
|
31
|
+
export type { InjectionFile };
|
|
32
32
|
|
|
33
33
|
/** 注入漂移检测结果 */
|
|
34
34
|
export interface InjectionDrift {
|
|
@@ -57,20 +57,6 @@ export const INJECTION_DRIFT_FIX_HINT = '重跑 `npx @dommaker/harness init` 同
|
|
|
57
57
|
const VERSION_LINE_RE = /<!-- version: ([^ ]+) -->/;
|
|
58
58
|
const ENTRY_LINE_RE = /^- \*\*.+?\*\*: .+$/;
|
|
59
59
|
const GROUP_HEADING_RE = /^### .+$/;
|
|
60
|
-
const GOVERNANCE_HEADING_RE = /^## Governance Rules[ \t]*$/gm;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* 读取当前 harness 包版本(与 init 注入时写入的版本同源)
|
|
64
|
-
*/
|
|
65
|
-
function getPackageVersion(): string {
|
|
66
|
-
try {
|
|
67
|
-
const pkgPath = path.join(__dirname, '..', '..', '..', 'package.json');
|
|
68
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
69
|
-
return pkg.version ?? 'unknown';
|
|
70
|
-
} catch {
|
|
71
|
-
return 'unknown';
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
60
|
|
|
75
61
|
/**
|
|
76
62
|
* 提取参与条目级比对的"有效行":注入条目(- **id**: text)与分组标题(### ...)。
|
|
@@ -83,48 +69,15 @@ function significantLines(section: string): string[] {
|
|
|
83
69
|
.filter(l => ENTRY_LINE_RE.test(l) || GROUP_HEADING_RE.test(l));
|
|
84
70
|
}
|
|
85
71
|
|
|
86
|
-
function readIfExists(filePath: string): string | null {
|
|
87
|
-
try {
|
|
88
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
89
|
-
return typeof content === 'string' ? content : null;
|
|
90
|
-
} catch {
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* 解析治理约束注入段落点(studio #307,ADR 2026-08-21 落点模型)
|
|
97
|
-
*
|
|
98
|
-
* 与 init 的 setupGovernanceConstraints 路由一致:CLAUDE.md 含标记段优先
|
|
99
|
-
* (旧模型仓豁免),否则看 AGENTS.md(新模型仓注入段在 PRESERVE:governance 内);
|
|
100
|
-
* 两处均无完整标记段 → null(未注入)。
|
|
101
|
-
*
|
|
102
|
-
* detectInjectionDrift 与 constraints retire 的注入段同步共用本路由。
|
|
103
|
-
*/
|
|
104
|
-
export function resolveInjectionTarget(
|
|
105
|
-
projectRoot: string
|
|
106
|
-
): { file: InjectionFile; content: string; startIdx: number; endIdx: number } | null {
|
|
107
|
-
for (const file of INJECTION_FILES) {
|
|
108
|
-
const content = readIfExists(path.join(projectRoot, file));
|
|
109
|
-
if (content === null) continue;
|
|
110
|
-
const startIdx = content.indexOf(CONSTRAINTS_START_MARKER);
|
|
111
|
-
const endIdx = content.indexOf(CONSTRAINTS_END_MARKER);
|
|
112
|
-
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
|
|
113
|
-
return { file, content, startIdx, endIdx };
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
72
|
/**
|
|
120
73
|
* 检测约束注入段漂移
|
|
121
74
|
*
|
|
122
75
|
* @param projectRoot 项目根路径
|
|
123
|
-
* @param currentVersion 当前 harness
|
|
76
|
+
* @param currentVersion 当前 harness 版本(缺省经 getHarnessPackageVersion 正本读取;测试可显式传入)
|
|
124
77
|
*/
|
|
125
78
|
export function detectInjectionDrift(
|
|
126
79
|
projectRoot: string,
|
|
127
|
-
currentVersion: string =
|
|
80
|
+
currentVersion: string = getHarnessPackageVersion()
|
|
128
81
|
): InjectionDrift {
|
|
129
82
|
const result: InjectionDrift = {
|
|
130
83
|
hasDrift: false,
|
|
@@ -141,7 +94,7 @@ export function detectInjectionDrift(
|
|
|
141
94
|
readIfExists(path.join(projectRoot, 'CLAUDE.md')) ??
|
|
142
95
|
readIfExists(path.join(projectRoot, 'AGENTS.md'));
|
|
143
96
|
if (legacy !== null) {
|
|
144
|
-
result.duplicateHeading = (legacy
|
|
97
|
+
result.duplicateHeading = countGovernanceHeadings(legacy) > 1;
|
|
145
98
|
}
|
|
146
99
|
result.notInjected = true;
|
|
147
100
|
return result;
|
|
@@ -150,8 +103,8 @@ export function detectInjectionDrift(
|
|
|
150
103
|
result.injectionFile = target.file;
|
|
151
104
|
const { content, startIdx, endIdx } = target;
|
|
152
105
|
|
|
153
|
-
//
|
|
154
|
-
const headingCount = (content
|
|
106
|
+
// 重复章节:全文统计治理标题数(严格计数 injection-writer.countGovernanceHeadings,#83)
|
|
107
|
+
const headingCount = countGovernanceHeadings(content);
|
|
155
108
|
result.duplicateHeading = headingCount > 1;
|
|
156
109
|
|
|
157
110
|
const actualSection = content.slice(startIdx, endIdx + CONSTRAINTS_END_MARKER.length);
|