@dommaker/harness 1.2.3 → 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 +15 -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 +30 -215
- 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 +33 -26
- 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 +237 -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 +73 -77
- 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 +31 -16
- 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/completion-checkers/index.d.ts +3 -3
- package/dist/completion-checkers/index.js +3 -3
- package/dist/completion-checkers/phase-format.d.ts +1 -1
- package/dist/completion-checkers/phase-format.js +2 -2
- package/dist/completion-checkers/phase-format.js.map +1 -1
- package/dist/completion-checkers/tdd-chain.d.ts +1 -1
- package/dist/completion-checkers/tdd-chain.js +2 -2
- package/dist/completion-checkers/tdd-chain.js.map +1 -1
- package/dist/completion-checkers/types.d.ts +5 -5
- package/dist/completion-checkers/types.d.ts.map +1 -1
- package/dist/completion-checkers/types.js +2 -2
- 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 +7 -1
- package/dist/failure/recorder.d.ts.map +1 -1
- package/dist/failure/recorder.js +13 -9
- 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 +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -4
- 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 +18 -15
- 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 +3 -0
- package/dist/release/index.d.ts.map +1 -0
- package/dist/release/index.js +7 -0
- package/dist/release/index.js.map +1 -0
- package/dist/release/integrity.d.ts +65 -0
- package/dist/release/integrity.d.ts.map +1 -0
- package/dist/release/integrity.js +151 -0
- package/dist/release/integrity.js.map +1 -0
- 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/failure.d.ts +7 -0
- package/dist/types/failure.d.ts.map +1 -1
- package/dist/types/failure.js +8 -1
- package/dist/types/failure.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__/failure-recorder.test.ts +9 -0
- 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__/public-exports.test.ts +3 -0
- 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 +96 -38
- 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 +224 -74
- 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 +108 -86
- 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 +37 -223
- package/src/cli/commands/failure.ts +35 -27
- package/src/cli/commands/init.ts +166 -220
- package/src/cli/commands/knowledge.ts +250 -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 +75 -78
- 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 +31 -15
- 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/completion-checkers/CONTEXT.md +1 -1
- package/src/completion-checkers/__tests__/contract-presence.test.ts +1 -1
- package/src/completion-checkers/__tests__/phase-format.test.ts +1 -1
- package/src/completion-checkers/__tests__/tdd-chain.test.ts +2 -2
- package/src/completion-checkers/index.ts +3 -3
- package/src/completion-checkers/phase-format.ts +2 -2
- package/src/completion-checkers/tdd-chain.ts +2 -2
- package/src/completion-checkers/types.ts +5 -5
- 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 +13 -11
- 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 +11 -6
- 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 +55 -2
- 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 +20 -15
- 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 +24 -0
- package/src/release/__tests__/barrel.test.ts +60 -0
- package/src/release/__tests__/integrity.test.ts +157 -0
- package/src/release/index.ts +2 -0
- package/src/release/integrity.ts +141 -0
- 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/failure.ts +8 -0
- 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
|
@@ -3,9 +3,15 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import * as fs from 'fs';
|
|
6
|
+
import { captureIO, type CapturingIO } from '../../command-contract';
|
|
6
7
|
import * as path from 'path';
|
|
7
8
|
import { syncDocs } from '../sync-docs';
|
|
8
9
|
|
|
10
|
+
let io: CapturingIO;
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
io = captureIO();
|
|
13
|
+
});
|
|
14
|
+
|
|
9
15
|
describe('sync-docs --agents', () => {
|
|
10
16
|
const tempDir = path.join(process.cwd(), 'temp-test-sync-docs-agents');
|
|
11
17
|
|
|
@@ -21,15 +27,8 @@ describe('sync-docs --agents', () => {
|
|
|
21
27
|
}
|
|
22
28
|
});
|
|
23
29
|
|
|
24
|
-
let consoleSpy: jest.SpyInstance;
|
|
25
|
-
|
|
26
30
|
beforeEach(() => {
|
|
27
31
|
jest.clearAllMocks();
|
|
28
|
-
consoleSpy = jest.spyOn(console, 'log').mockImplementation();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
afterEach(() => {
|
|
32
|
-
consoleSpy.mockRestore();
|
|
33
32
|
});
|
|
34
33
|
|
|
35
34
|
/**
|
|
@@ -90,7 +89,7 @@ describe('sync-docs --agents', () => {
|
|
|
90
89
|
const testDir = path.join(tempDir, 'gen-pnpm');
|
|
91
90
|
createFixture(testDir, { pnpm: true });
|
|
92
91
|
|
|
93
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
92
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
94
93
|
|
|
95
94
|
const agentsPath = path.join(testDir, 'AGENTS.md');
|
|
96
95
|
expect(fs.existsSync(agentsPath)).toBe(true);
|
|
@@ -126,7 +125,7 @@ describe('sync-docs --agents', () => {
|
|
|
126
125
|
const testDir = path.join(tempDir, 'gen-npm');
|
|
127
126
|
createFixture(testDir);
|
|
128
127
|
|
|
129
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
128
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
130
129
|
|
|
131
130
|
const content = fs.readFileSync(path.join(testDir, 'AGENTS.md'), 'utf-8');
|
|
132
131
|
expect(content).toContain('npm run build');
|
|
@@ -141,18 +140,18 @@ describe('sync-docs --agents', () => {
|
|
|
141
140
|
const testDir = path.join(tempDir, 'idempotent');
|
|
142
141
|
createFixture(testDir, { pnpm: true, withCapabilities: true });
|
|
143
142
|
|
|
144
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
143
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
145
144
|
const first = fs.readFileSync(path.join(testDir, 'AGENTS.md'), 'utf-8');
|
|
146
145
|
|
|
147
146
|
// 第二次运行:无任何差异
|
|
148
|
-
const secondRun = await syncDocs({ projectPath: testDir, agents: true });
|
|
147
|
+
const secondRun = await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
149
148
|
const second = fs.readFileSync(path.join(testDir, 'AGENTS.md'), 'utf-8');
|
|
150
149
|
expect(second).toBe(first);
|
|
151
|
-
expect(secondRun).
|
|
150
|
+
expect(secondRun).toEqual({ kind: 'ok' });
|
|
152
151
|
|
|
153
152
|
// --check 模式应通过
|
|
154
|
-
const checkResult = await syncDocs({ projectPath: testDir, agents: true, check: true });
|
|
155
|
-
expect(checkResult).
|
|
153
|
+
const checkResult = await syncDocs({ projectPath: testDir, agents: true, check: true }, io);
|
|
154
|
+
expect(checkResult).toEqual({ kind: 'ok' });
|
|
156
155
|
|
|
157
156
|
fs.rmSync(testDir, { recursive: true, force: true });
|
|
158
157
|
});
|
|
@@ -161,9 +160,9 @@ describe('sync-docs --agents', () => {
|
|
|
161
160
|
const testDir = path.join(tempDir, 'check-missing');
|
|
162
161
|
createFixture(testDir, { withCapabilities: true });
|
|
163
162
|
|
|
164
|
-
const result = await syncDocs({ projectPath: testDir, agents: true, check: true });
|
|
165
|
-
expect(result).
|
|
166
|
-
expect(
|
|
163
|
+
const result = await syncDocs({ projectPath: testDir, agents: true, check: true }, io);
|
|
164
|
+
expect(result).toEqual({ kind: 'fail', reason: expect.stringContaining('文档不是最新') });
|
|
165
|
+
expect(io.outText()).toContain('缺少 AGENTS.md');
|
|
167
166
|
// check 模式不写入
|
|
168
167
|
expect(fs.existsSync(path.join(testDir, 'AGENTS.md'))).toBe(false);
|
|
169
168
|
|
|
@@ -175,22 +174,22 @@ describe('sync-docs --agents', () => {
|
|
|
175
174
|
createFixture(testDir, { pnpm: true, withCapabilities: true });
|
|
176
175
|
|
|
177
176
|
// 先生成
|
|
178
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
177
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
179
178
|
|
|
180
179
|
// 漂移 1:手改 AGENTS.md
|
|
181
180
|
fs.appendFileSync(path.join(testDir, 'AGENTS.md'), '\n手动追加的一行\n');
|
|
182
|
-
expect(await syncDocs({ projectPath: testDir, agents: true, check: true })).
|
|
181
|
+
expect(await syncDocs({ projectPath: testDir, agents: true, check: true }, io)).toEqual({ kind: 'fail', reason: expect.stringContaining('文档不是最新') });
|
|
183
182
|
|
|
184
183
|
// 重新生成恢复
|
|
185
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
186
|
-
expect(await syncDocs({ projectPath: testDir, agents: true, check: true })).
|
|
184
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
185
|
+
expect(await syncDocs({ projectPath: testDir, agents: true, check: true }, io)).toEqual({ kind: 'ok' });
|
|
187
186
|
|
|
188
187
|
// 漂移 2:package.json 删除一个 curated 脚本
|
|
189
188
|
const pkgPath = path.join(testDir, 'package.json');
|
|
190
189
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
191
190
|
delete pkg.scripts.lint;
|
|
192
191
|
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
|
|
193
|
-
expect(await syncDocs({ projectPath: testDir, agents: true, check: true })).
|
|
192
|
+
expect(await syncDocs({ projectPath: testDir, agents: true, check: true }, io)).toEqual({ kind: 'fail', reason: expect.stringContaining('文档不是最新') });
|
|
194
193
|
|
|
195
194
|
fs.rmSync(testDir, { recursive: true, force: true });
|
|
196
195
|
});
|
|
@@ -199,8 +198,8 @@ describe('sync-docs --agents', () => {
|
|
|
199
198
|
const testDir = path.join(tempDir, 'no-agents');
|
|
200
199
|
createFixture(testDir, { withCapabilities: true });
|
|
201
200
|
|
|
202
|
-
const result = await syncDocs({ projectPath: testDir });
|
|
203
|
-
expect(result).
|
|
201
|
+
const result = await syncDocs({ projectPath: testDir }, io);
|
|
202
|
+
expect(result).toEqual({ kind: 'ok' });
|
|
204
203
|
expect(fs.existsSync(path.join(testDir, 'AGENTS.md'))).toBe(false);
|
|
205
204
|
|
|
206
205
|
fs.rmSync(testDir, { recursive: true, force: true });
|
|
@@ -210,10 +209,10 @@ describe('sync-docs --agents', () => {
|
|
|
210
209
|
const testDir = path.join(tempDir, 'json-agents');
|
|
211
210
|
createFixture(testDir, { withCapabilities: true });
|
|
212
211
|
|
|
213
|
-
const result = await syncDocs({ projectPath: testDir, agents: true, check: true, json: true });
|
|
214
|
-
expect(result).
|
|
212
|
+
const result = await syncDocs({ projectPath: testDir, agents: true, check: true, json: true }, io);
|
|
213
|
+
expect(result).toEqual({ kind: 'fail', reason: expect.stringContaining('文档不是最新') });
|
|
215
214
|
|
|
216
|
-
const jsonCall =
|
|
215
|
+
const jsonCall = io.outRecords().map(chunk => [chunk] as string[]).find(
|
|
217
216
|
(call: unknown[]) => typeof call[0] === 'string' && call[0].startsWith('{')
|
|
218
217
|
);
|
|
219
218
|
expect(jsonCall).toBeDefined();
|
|
@@ -230,7 +229,7 @@ describe('sync-docs --agents', () => {
|
|
|
230
229
|
createFixture(testDir);
|
|
231
230
|
fs.writeFileSync(path.join(testDir, 'yarn.lock'), '# yarn lockfile v1\n');
|
|
232
231
|
|
|
233
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
232
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
234
233
|
|
|
235
234
|
const content = fs.readFileSync(path.join(testDir, 'AGENTS.md'), 'utf-8');
|
|
236
235
|
expect(content).toContain('yarn dev');
|
|
@@ -242,52 +241,75 @@ describe('sync-docs --agents', () => {
|
|
|
242
241
|
fs.rmSync(testDir, { recursive: true, force: true });
|
|
243
242
|
});
|
|
244
243
|
|
|
245
|
-
describe('
|
|
246
|
-
it('.
|
|
247
|
-
const testDir = path.join(tempDir, '
|
|
244
|
+
describe('知识入口行:模块上下文正本模型', () => {
|
|
245
|
+
it('.harness/CONTEXT.md 存在时生成正本行指向新正本,替代散置指引,--check 无漂移', async () => {
|
|
246
|
+
const testDir = path.join(tempDir, 'canonical-context-model');
|
|
248
247
|
createFixture(testDir, { pnpm: true, withCapabilities: true });
|
|
249
248
|
// 夹具已带散置 src/CONTEXT.md:正本在场时整行替代,与是否残留散置文件无关
|
|
250
|
-
fs.mkdirSync(path.join(testDir, '.
|
|
251
|
-
fs.writeFileSync(path.join(testDir, '.
|
|
249
|
+
fs.mkdirSync(path.join(testDir, '.harness'), { recursive: true });
|
|
250
|
+
fs.writeFileSync(path.join(testDir, '.harness', 'CONTEXT.md'), '# 模块上下文\n\n## src\n\n职责:夹具\n');
|
|
252
251
|
|
|
253
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
252
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
254
253
|
|
|
255
254
|
const content = fs.readFileSync(path.join(testDir, 'AGENTS.md'), 'utf-8');
|
|
256
|
-
expect(content).toContain('模块上下文正本:`.
|
|
255
|
+
expect(content).toContain('模块上下文正本:`.harness/CONTEXT.md`(模块锚点组织),改动代码时同步更新');
|
|
257
256
|
expect(content).not.toContain('各源码目录的 `CONTEXT.md`');
|
|
258
257
|
expect(content).not.toContain('缺失目录可由 `harness sync-docs` 生成模板');
|
|
259
258
|
// 知识库行不受影响
|
|
260
259
|
expect(content).toContain('项目知识库,用 `harness knowledge` 查询');
|
|
261
260
|
|
|
262
261
|
// 幂等 + --check 通过(正本模型下无漂移)
|
|
263
|
-
const second = await syncDocs({ projectPath: testDir, agents: true });
|
|
264
|
-
expect(second).
|
|
265
|
-
expect(await syncDocs({ projectPath: testDir, agents: true, check: true })).
|
|
262
|
+
const second = await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
263
|
+
expect(second).toEqual({ kind: 'ok' });
|
|
264
|
+
expect(await syncDocs({ projectPath: testDir, agents: true, check: true }, io)).toEqual({ kind: 'ok' });
|
|
266
265
|
|
|
267
266
|
fs.rmSync(testDir, { recursive: true, force: true });
|
|
268
267
|
});
|
|
269
268
|
|
|
270
|
-
it('.studio/CONTEXT.md
|
|
269
|
+
it('旧正本 .studio/CONTEXT.md 仍在场时兼容沿用(免迁移),两者同在以 .harness/ 为准', async () => {
|
|
270
|
+
const legacyDir = path.join(tempDir, 'legacy-context-model');
|
|
271
|
+
createFixture(legacyDir, { pnpm: true, withCapabilities: true });
|
|
272
|
+
fs.mkdirSync(path.join(legacyDir, '.studio'), { recursive: true });
|
|
273
|
+
fs.writeFileSync(path.join(legacyDir, '.studio', 'CONTEXT.md'), '# 模块上下文\n\n## src\n\n职责:夹具\n');
|
|
274
|
+
await syncDocs({ projectPath: legacyDir, agents: true }, io);
|
|
275
|
+
expect(fs.readFileSync(path.join(legacyDir, 'AGENTS.md'), 'utf-8'))
|
|
276
|
+
.toContain('模块上下文正本:`.studio/CONTEXT.md`(模块锚点组织),改动代码时同步更新');
|
|
277
|
+
fs.rmSync(legacyDir, { recursive: true, force: true });
|
|
278
|
+
|
|
279
|
+
const bothDir = path.join(tempDir, 'both-context-model');
|
|
280
|
+
createFixture(bothDir, { pnpm: true, withCapabilities: true });
|
|
281
|
+
fs.mkdirSync(path.join(bothDir, '.studio'), { recursive: true });
|
|
282
|
+
fs.writeFileSync(path.join(bothDir, '.studio', 'CONTEXT.md'), '# 旧\n');
|
|
283
|
+
fs.mkdirSync(path.join(bothDir, '.harness'), { recursive: true });
|
|
284
|
+
fs.writeFileSync(path.join(bothDir, '.harness', 'CONTEXT.md'), '# 新\n');
|
|
285
|
+
await syncDocs({ projectPath: bothDir, agents: true }, io);
|
|
286
|
+
const content = fs.readFileSync(path.join(bothDir, 'AGENTS.md'), 'utf-8');
|
|
287
|
+
expect(content).toContain('模块上下文正本:`.harness/CONTEXT.md`');
|
|
288
|
+
expect(content).not.toContain('.studio/CONTEXT.md');
|
|
289
|
+
fs.rmSync(bothDir, { recursive: true, force: true });
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it('正本不存在时保持散置模型行,--check 无漂移', async () => {
|
|
271
293
|
const testDir = path.join(tempDir, 'scattered-context-model');
|
|
272
294
|
createFixture(testDir, { pnpm: true, withCapabilities: true });
|
|
273
295
|
|
|
274
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
296
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
275
297
|
|
|
276
298
|
const content = fs.readFileSync(path.join(testDir, 'AGENTS.md'), 'utf-8');
|
|
277
299
|
expect(content).toContain('各源码目录的 `CONTEXT.md` 是权威模块文档(现有 1 个),改动代码时同步更新');
|
|
278
300
|
expect(content).not.toContain('模块上下文正本');
|
|
279
301
|
|
|
280
|
-
expect(await syncDocs({ projectPath: testDir, agents: true, check: true })).
|
|
302
|
+
expect(await syncDocs({ projectPath: testDir, agents: true, check: true }, io)).toEqual({ kind: 'ok' });
|
|
281
303
|
|
|
282
304
|
fs.rmSync(testDir, { recursive: true, force: true });
|
|
283
305
|
});
|
|
284
306
|
|
|
285
|
-
it('
|
|
286
|
-
const testDir = path.join(tempDir, '
|
|
307
|
+
it('正本路径是目录而非文件时不视为正本', async () => {
|
|
308
|
+
const testDir = path.join(tempDir, 'context-doc-dir');
|
|
287
309
|
createFixture(testDir, { pnpm: true, withCapabilities: true });
|
|
288
|
-
fs.mkdirSync(path.join(testDir, '.
|
|
310
|
+
fs.mkdirSync(path.join(testDir, '.harness', 'CONTEXT.md'), { recursive: true });
|
|
289
311
|
|
|
290
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
312
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
291
313
|
|
|
292
314
|
const content = fs.readFileSync(path.join(testDir, 'AGENTS.md'), 'utf-8');
|
|
293
315
|
expect(content).toContain('各源码目录的 `CONTEXT.md` 是权威模块文档');
|
|
@@ -305,8 +327,8 @@ describe('sync-docs --agents', () => {
|
|
|
305
327
|
fs.mkdirSync(path.join(testDir, '.next'), { recursive: true });
|
|
306
328
|
fs.mkdirSync(path.join(testDir, '.vscode'), { recursive: true });
|
|
307
329
|
|
|
308
|
-
const result = await syncDocs({ projectPath: testDir, agents: true });
|
|
309
|
-
expect(result).
|
|
330
|
+
const result = await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
331
|
+
expect(result).toEqual({ kind: 'ok' }); // AGENTS.md 缺失 → 有问题,但已生成
|
|
310
332
|
|
|
311
333
|
const content = fs.readFileSync(path.join(testDir, 'AGENTS.md'), 'utf-8');
|
|
312
334
|
// 项目名回退到目录名,无 description
|
|
@@ -336,8 +358,8 @@ describe('sync-docs --agents', () => {
|
|
|
336
358
|
'',
|
|
337
359
|
].join('\n'));
|
|
338
360
|
|
|
339
|
-
const result = await syncDocs({ projectPath: testDir, agents: true });
|
|
340
|
-
expect(result).
|
|
361
|
+
const result = await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
362
|
+
expect(result).toEqual({ kind: 'ok' });
|
|
341
363
|
|
|
342
364
|
// src 目录不存在:扫描/统计静默跳过,不中断生成
|
|
343
365
|
const content = fs.readFileSync(path.join(testDir, 'AGENTS.md'), 'utf-8');
|
|
@@ -374,8 +396,8 @@ describe('sync-docs --agents', () => {
|
|
|
374
396
|
scripts: { test: 'jest' },
|
|
375
397
|
}));
|
|
376
398
|
|
|
377
|
-
const result = await syncDocs({ projectPath: testDir, agents: true });
|
|
378
|
-
expect(result).
|
|
399
|
+
const result = await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
400
|
+
expect(result).toEqual({ kind: 'ok' }); // CAPABILITIES.md/AGENTS.md 缺失 → 已生成
|
|
379
401
|
|
|
380
402
|
const content = fs.readFileSync(path.join(testDir, 'AGENTS.md'), 'utf-8');
|
|
381
403
|
expect(content).toContain('| `apps/` | monorepo 应用:api、web |');
|
|
@@ -396,7 +418,7 @@ describe('sync-docs --agents', () => {
|
|
|
396
418
|
createFixture(testDir, { withCapabilities: true });
|
|
397
419
|
fs.writeFileSync(path.join(testDir, 'CLAUDE.md'), '# CLAUDE.md\n\n## Governance Rules\n\n(尚未配置约束)\n');
|
|
398
420
|
|
|
399
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
421
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
400
422
|
|
|
401
423
|
const content = fs.readFileSync(path.join(testDir, 'AGENTS.md'), 'utf-8');
|
|
402
424
|
expect(content).toContain('Governance Rules 块');
|
|
@@ -409,12 +431,12 @@ describe('sync-docs --agents', () => {
|
|
|
409
431
|
const testDir = path.join(tempDir, 'json-idempotent');
|
|
410
432
|
createFixture(testDir, { pnpm: true, withCapabilities: true });
|
|
411
433
|
|
|
412
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
434
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
413
435
|
|
|
414
|
-
const result = await syncDocs({ projectPath: testDir, agents: true, json: true });
|
|
415
|
-
expect(result).
|
|
436
|
+
const result = await syncDocs({ projectPath: testDir, agents: true, json: true }, io);
|
|
437
|
+
expect(result).toEqual({ kind: 'ok' });
|
|
416
438
|
|
|
417
|
-
const jsonCall =
|
|
439
|
+
const jsonCall = io.outRecords().map(chunk => [chunk] as string[]).find(
|
|
418
440
|
(call: unknown[]) => typeof call[0] === 'string' && call[0].startsWith('{')
|
|
419
441
|
);
|
|
420
442
|
expect(jsonCall).toBeDefined();
|
|
@@ -452,9 +474,9 @@ describe('sync-docs --agents', () => {
|
|
|
452
474
|
fs.utimesSync(path.join(testDir, 'src', 'modules', 'CONTEXT.md'), past, past);
|
|
453
475
|
|
|
454
476
|
// json 模式:结构化输出缺失/过时
|
|
455
|
-
const jsonResult = await syncDocs({ projectPath: testDir, agents: true, check: true, json: true });
|
|
456
|
-
expect(jsonResult).
|
|
457
|
-
const jsonCall =
|
|
477
|
+
const jsonResult = await syncDocs({ projectPath: testDir, agents: true, check: true, json: true }, io);
|
|
478
|
+
expect(jsonResult).toEqual({ kind: 'fail', reason: expect.stringContaining('文档不是最新') });
|
|
479
|
+
const jsonCall = io.outRecords().map(chunk => [chunk] as string[]).find(
|
|
458
480
|
(call: unknown[]) => typeof call[0] === 'string' && call[0].startsWith('{')
|
|
459
481
|
);
|
|
460
482
|
expect(jsonCall).toBeDefined();
|
|
@@ -468,11 +490,11 @@ describe('sync-docs --agents', () => {
|
|
|
468
490
|
expect(parsed.agentsMd).toEqual({ file: 'AGENTS.md', exists: false, stale: true });
|
|
469
491
|
|
|
470
492
|
// 人读模式:输出过时提示
|
|
471
|
-
|
|
472
|
-
const humanResult = await syncDocs({ projectPath: testDir, agents: true, check: true });
|
|
473
|
-
expect(humanResult).
|
|
474
|
-
expect(
|
|
475
|
-
expect(
|
|
493
|
+
io = captureIO();
|
|
494
|
+
const humanResult = await syncDocs({ projectPath: testDir, agents: true, check: true }, io);
|
|
495
|
+
expect(humanResult).toEqual({ kind: 'fail', reason: expect.stringContaining('文档不是最新') });
|
|
496
|
+
expect(io.outText()).toContain('可能过时');
|
|
497
|
+
expect(io.outText()).toContain('缺少 CONTEXT.md');
|
|
476
498
|
|
|
477
499
|
fs.rmSync(testDir, { recursive: true, force: true });
|
|
478
500
|
});
|
|
@@ -494,18 +516,18 @@ describe('sync-docs --agents', () => {
|
|
|
494
516
|
const testDir = path.join(tempDir, 'preserve-basic');
|
|
495
517
|
createFixture(testDir, { pnpm: true, withCapabilities: true });
|
|
496
518
|
|
|
497
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
519
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
498
520
|
appendBlock(testDir, MANUAL_BLOCK);
|
|
499
521
|
|
|
500
522
|
// 追加块后构成漂移 → 写入模式重组:生成部分 + PRESERVE 块
|
|
501
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
523
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
502
524
|
const content = fs.readFileSync(path.join(testDir, 'AGENTS.md'), 'utf-8');
|
|
503
525
|
expect(content).toContain(MANUAL_BLOCK);
|
|
504
526
|
// 块位于生成内容之后
|
|
505
527
|
expect(content.indexOf('## 知识入口')).toBeLessThan(content.indexOf('<!-- PRESERVE:manual -->'));
|
|
506
528
|
|
|
507
529
|
// 重组后幂等:--check 通过
|
|
508
|
-
expect(await syncDocs({ projectPath: testDir, agents: true, check: true })).
|
|
530
|
+
expect(await syncDocs({ projectPath: testDir, agents: true, check: true }, io)).toEqual({ kind: 'ok' });
|
|
509
531
|
|
|
510
532
|
fs.rmSync(testDir, { recursive: true, force: true });
|
|
511
533
|
});
|
|
@@ -514,10 +536,10 @@ describe('sync-docs --agents', () => {
|
|
|
514
536
|
const testDir = path.join(tempDir, 'preserve-order');
|
|
515
537
|
createFixture(testDir, { pnpm: true, withCapabilities: true });
|
|
516
538
|
|
|
517
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
539
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
518
540
|
appendBlock(testDir, '<!-- PRESERVE:one -->\n第一块\n<!-- /PRESERVE:one -->');
|
|
519
541
|
appendBlock(testDir, '<!-- PRESERVE:two -->\n第二块\n<!-- /PRESERVE:two -->');
|
|
520
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
542
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
521
543
|
|
|
522
544
|
const content = fs.readFileSync(path.join(testDir, 'AGENTS.md'), 'utf-8');
|
|
523
545
|
expect(content.indexOf('PRESERVE:one')).toBeLessThan(content.indexOf('PRESERVE:two'));
|
|
@@ -531,20 +553,20 @@ describe('sync-docs --agents', () => {
|
|
|
531
553
|
const testDir = path.join(tempDir, 'preserve-drift');
|
|
532
554
|
createFixture(testDir, { pnpm: true, withCapabilities: true });
|
|
533
555
|
|
|
534
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
556
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
535
557
|
appendBlock(testDir, MANUAL_BLOCK);
|
|
536
|
-
await syncDocs({ projectPath: testDir, agents: true }); // 重组为规范形态
|
|
558
|
+
await syncDocs({ projectPath: testDir, agents: true }, io); // 重组为规范形态
|
|
537
559
|
|
|
538
560
|
// 块内手改 → 不报漂移
|
|
539
561
|
const agentsPath = path.join(testDir, 'AGENTS.md');
|
|
540
562
|
const edited = fs.readFileSync(agentsPath, 'utf-8').replace('使用者自有内容', '改过的内容');
|
|
541
563
|
fs.writeFileSync(agentsPath, edited);
|
|
542
|
-
expect(await syncDocs({ projectPath: testDir, agents: true, check: true })).
|
|
564
|
+
expect(await syncDocs({ projectPath: testDir, agents: true, check: true }, io)).toEqual({ kind: 'ok' });
|
|
543
565
|
|
|
544
566
|
// 块外手改(生成部分) → 报漂移;重生成后块仍在、块外改动被还原
|
|
545
567
|
fs.appendFileSync(agentsPath, '\n块外手动追加\n');
|
|
546
|
-
expect(await syncDocs({ projectPath: testDir, agents: true, check: true })).
|
|
547
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
568
|
+
expect(await syncDocs({ projectPath: testDir, agents: true, check: true }, io)).toEqual({ kind: 'fail', reason: expect.stringContaining('文档不是最新') });
|
|
569
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
548
570
|
const regenerated = fs.readFileSync(agentsPath, 'utf-8');
|
|
549
571
|
expect(regenerated).toContain('改过的内容');
|
|
550
572
|
expect(regenerated).not.toContain('块外手动追加');
|
|
@@ -556,11 +578,11 @@ describe('sync-docs --agents', () => {
|
|
|
556
578
|
const testDir = path.join(tempDir, 'preserve-malformed');
|
|
557
579
|
createFixture(testDir, { pnpm: true, withCapabilities: true });
|
|
558
580
|
|
|
559
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
581
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
560
582
|
appendBlock(testDir, '<!-- PRESERVE:broken -->\n没有结束标记');
|
|
561
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
583
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
562
584
|
|
|
563
|
-
expect(
|
|
585
|
+
expect(io.outText()).toContain('未闭合');
|
|
564
586
|
const content = fs.readFileSync(path.join(testDir, 'AGENTS.md'), 'utf-8');
|
|
565
587
|
expect(content).not.toContain('PRESERVE:broken');
|
|
566
588
|
expect(content).not.toContain('没有结束标记');
|
|
@@ -572,9 +594,9 @@ describe('sync-docs --agents', () => {
|
|
|
572
594
|
const testDir = path.join(tempDir, 'preserve-repo-change');
|
|
573
595
|
createFixture(testDir, { pnpm: true, withCapabilities: true });
|
|
574
596
|
|
|
575
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
597
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
576
598
|
appendBlock(testDir, MANUAL_BLOCK);
|
|
577
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
599
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
578
600
|
|
|
579
601
|
// package.json 删除一个 curated 脚本 → 生成部分变化
|
|
580
602
|
const pkgPath = path.join(testDir, 'package.json');
|
|
@@ -582,13 +604,13 @@ describe('sync-docs --agents', () => {
|
|
|
582
604
|
delete pkg.scripts.lint;
|
|
583
605
|
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
|
|
584
606
|
|
|
585
|
-
expect(await syncDocs({ projectPath: testDir, agents: true, check: true })).
|
|
586
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
607
|
+
expect(await syncDocs({ projectPath: testDir, agents: true, check: true }, io)).toEqual({ kind: 'fail', reason: expect.stringContaining('文档不是最新') });
|
|
608
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
587
609
|
|
|
588
610
|
const content = fs.readFileSync(path.join(testDir, 'AGENTS.md'), 'utf-8');
|
|
589
611
|
expect(content).not.toContain('pnpm lint');
|
|
590
612
|
expect(content).toContain(MANUAL_BLOCK);
|
|
591
|
-
expect(await syncDocs({ projectPath: testDir, agents: true, check: true })).
|
|
613
|
+
expect(await syncDocs({ projectPath: testDir, agents: true, check: true }, io)).toEqual({ kind: 'ok' });
|
|
592
614
|
|
|
593
615
|
fs.rmSync(testDir, { recursive: true, force: true });
|
|
594
616
|
});
|
|
@@ -607,16 +629,16 @@ describe('sync-docs --agents', () => {
|
|
|
607
629
|
'<!-- /PRESERVE:governance -->',
|
|
608
630
|
].join('\n');
|
|
609
631
|
|
|
610
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
632
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
611
633
|
appendBlock(testDir, GOVERNANCE_BLOCK);
|
|
612
|
-
await syncDocs({ projectPath: testDir, agents: true });
|
|
634
|
+
await syncDocs({ projectPath: testDir, agents: true }, io);
|
|
613
635
|
|
|
614
636
|
const content = fs.readFileSync(path.join(testDir, 'AGENTS.md'), 'utf-8');
|
|
615
637
|
expect(content).toContain(GOVERNANCE_BLOCK);
|
|
616
638
|
|
|
617
639
|
// 幂等 + --check 通过(块内含 HARNESS_CONSTRAINTS 标记不影响漂移比对)
|
|
618
|
-
expect(await syncDocs({ projectPath: testDir, agents: true })).
|
|
619
|
-
expect(await syncDocs({ projectPath: testDir, agents: true, check: true })).
|
|
640
|
+
expect(await syncDocs({ projectPath: testDir, agents: true }, io)).toEqual({ kind: 'ok' });
|
|
641
|
+
expect(await syncDocs({ projectPath: testDir, agents: true, check: true }, io)).toEqual({ kind: 'ok' });
|
|
620
642
|
|
|
621
643
|
fs.rmSync(testDir, { recursive: true, force: true });
|
|
622
644
|
});
|