@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
package/src/cli/commands/init.ts
CHANGED
|
@@ -5,18 +5,27 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import chalk from 'chalk';
|
|
8
|
-
import { readFileSync } from 'fs';
|
|
9
8
|
import * as fs from 'fs/promises';
|
|
10
9
|
import * as path from 'path';
|
|
11
10
|
import * as yaml from 'js-yaml';
|
|
12
11
|
import { createExampleCheckpoint, createExampleResolutions } from './validate';
|
|
13
12
|
import { detectSourceRoots } from '../../utils/detect-source-roots';
|
|
13
|
+
import { getHarnessPackageVersion } from '../../utils/package-version';
|
|
14
14
|
import { getEffectiveConstraints } from '../../core/effective-constraints';
|
|
15
|
+
import type { GovernanceConfig } from '../../types/project-config';
|
|
15
16
|
import {
|
|
16
17
|
CONSTRAINTS_START_MARKER,
|
|
17
18
|
CONSTRAINTS_END_MARKER,
|
|
18
19
|
renderConstraintsSection,
|
|
19
20
|
} from '../../core/constraints/injection-renderer';
|
|
21
|
+
import {
|
|
22
|
+
replaceStandaloneRange,
|
|
23
|
+
replaceEnclosedRange,
|
|
24
|
+
cutMarkerBlock,
|
|
25
|
+
resolveGovernanceLanding,
|
|
26
|
+
GOVERNANCE_HEADING,
|
|
27
|
+
} from '../../core/constraints/injection-writer';
|
|
28
|
+
import { log, processIO, type CommandIO, type CommandResult } from '../command-contract';
|
|
20
29
|
|
|
21
30
|
export interface InitOptions {
|
|
22
31
|
/** 项目路径 */
|
|
@@ -67,9 +76,9 @@ const PRESETS = {
|
|
|
67
76
|
};
|
|
68
77
|
|
|
69
78
|
/**
|
|
70
|
-
*
|
|
79
|
+
* 治理预设(形状 = 写入 config.yml 的 governance 段,直接用类型正本)
|
|
71
80
|
*/
|
|
72
|
-
const GOVERNANCE_PRESETS: Record<string,
|
|
81
|
+
const GOVERNANCE_PRESETS: Record<string, GovernanceConfig> = {
|
|
73
82
|
minimal: {
|
|
74
83
|
level: 'minimal',
|
|
75
84
|
docs: {
|
|
@@ -135,117 +144,111 @@ const GOVERNANCE_PRESETS: Record<string, Record<string, unknown>> = {
|
|
|
135
144
|
/**
|
|
136
145
|
* 初始化项目
|
|
137
146
|
*/
|
|
138
|
-
export async function init(options: InitOptions): Promise<
|
|
147
|
+
export async function init(options: InitOptions, io: CommandIO = processIO): Promise<CommandResult> {
|
|
139
148
|
// 只输出代码片段
|
|
140
149
|
if (options.printSnippets) {
|
|
141
|
-
printSnippets();
|
|
142
|
-
return;
|
|
150
|
+
printSnippets(io);
|
|
151
|
+
return { kind: 'ok' };
|
|
143
152
|
}
|
|
144
153
|
|
|
145
|
-
|
|
154
|
+
log(io, chalk.blue('🚀 初始化 harness 配置...'));
|
|
146
155
|
|
|
147
156
|
const projectPath = options.projectPath || process.cwd();
|
|
148
157
|
const configDir = path.join(projectPath, '.harness');
|
|
149
158
|
|
|
150
159
|
// 创建配置目录
|
|
151
160
|
await fs.mkdir(configDir, { recursive: true });
|
|
152
|
-
|
|
161
|
+
log(io, chalk.gray(`配置目录: ${configDir}`));
|
|
153
162
|
|
|
154
163
|
// 选择预设
|
|
155
164
|
const preset = PRESETS[options.preset];
|
|
156
|
-
|
|
165
|
+
log(io, chalk.gray(`预设: ${options.preset}`));
|
|
157
166
|
|
|
158
167
|
// 合并治理配置
|
|
159
168
|
const configData: Record<string, unknown> = { ...preset };
|
|
160
169
|
if (options.governance) {
|
|
161
170
|
configData.governance = GOVERNANCE_PRESETS[options.governance];
|
|
162
|
-
|
|
171
|
+
log(io, chalk.gray(`治理级别: ${options.governance}`));
|
|
163
172
|
}
|
|
164
173
|
|
|
165
174
|
// 写入 harness 版本
|
|
166
|
-
const pkgVersion =
|
|
175
|
+
const pkgVersion = getHarnessPackageVersion();
|
|
167
176
|
configData.harness = { version: pkgVersion };
|
|
168
177
|
|
|
169
178
|
// 写入配置文件(harness 管理的配置,始终重新生成)
|
|
170
179
|
const configPath = path.join(configDir, 'config.yml');
|
|
171
180
|
const configContent = yaml.dump(configData, { indent: 2 });
|
|
172
181
|
await fs.writeFile(configPath, configContent, 'utf-8');
|
|
173
|
-
|
|
182
|
+
log(io, chalk.green(`✅ 已创建配置文件: ${configPath} (v${pkgVersion})`));
|
|
174
183
|
|
|
175
184
|
// 创建检查点示例
|
|
176
|
-
await createExampleCheckpoint(projectPath);
|
|
185
|
+
await createExampleCheckpoint(projectPath, io);
|
|
177
186
|
|
|
178
187
|
// 创建 Resolutions(RKB 狗粮 — 约束 → 已知解法映射)
|
|
179
|
-
await createExampleResolutions(projectPath);
|
|
188
|
+
await createExampleResolutions(projectPath, io);
|
|
180
189
|
|
|
181
190
|
// 创建自定义约束示例
|
|
182
|
-
await createCustomConstraintsExample(projectPath);
|
|
191
|
+
await createCustomConstraintsExample(projectPath, io);
|
|
183
192
|
|
|
184
193
|
// CAPABILITIES.md / CHANGELOG.md 由 sync-docs(AI 治理)管理,init 不创建
|
|
185
194
|
|
|
186
195
|
// 创建 Git hooks
|
|
187
196
|
if (options.gitHooks !== false) {
|
|
188
|
-
await setupGitHooks(projectPath);
|
|
197
|
+
await setupGitHooks(projectPath, io);
|
|
189
198
|
}
|
|
190
199
|
|
|
191
200
|
// 创建 GitHub Actions
|
|
192
201
|
if (options.githubActions !== false) {
|
|
193
|
-
await setupGitHubActions(projectPath);
|
|
202
|
+
await setupGitHubActions(projectPath, io);
|
|
194
203
|
}
|
|
195
204
|
|
|
196
205
|
// 治理相关文件生成
|
|
197
206
|
if (options.governance) {
|
|
198
|
-
await setupGovernance(projectPath, options.governance);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* 获取 harness 包版本
|
|
215
|
-
*/
|
|
216
|
-
function getPackageVersion(): string {
|
|
217
|
-
try {
|
|
218
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
219
|
-
return require('../../../package.json').version;
|
|
220
|
-
} catch {
|
|
221
|
-
return 'unknown';
|
|
222
|
-
}
|
|
207
|
+
await setupGovernance(projectPath, options.governance, io);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
log(io);
|
|
211
|
+
log(io, chalk.green('✅ harness 初始化完成!'));
|
|
212
|
+
log(io);
|
|
213
|
+
log(io, chalk.gray('下一步:'));
|
|
214
|
+
log(io, chalk.gray(' 1. 编辑 .harness/config.yml 自定义配置'));
|
|
215
|
+
log(io, chalk.gray(' 2. 编辑 .harness/custom-constraints.yml 添加项目约束'));
|
|
216
|
+
log(io, chalk.gray(' 3. 正常开发,每次 git commit 会自动检查约束'));
|
|
217
|
+
log(io, chalk.gray(' 4. 运行 harness status 查看状态'));
|
|
218
|
+
log(io);
|
|
219
|
+
log(io, chalk.blue('💡 提示: 使用 harness init --print-snippets 查看配置代码片段'));
|
|
220
|
+
return { kind: 'ok' };
|
|
223
221
|
}
|
|
224
222
|
|
|
225
223
|
/**
|
|
226
224
|
* 输出代码片段
|
|
227
225
|
*/
|
|
228
|
-
function printSnippets(): void {
|
|
229
|
-
|
|
230
|
-
|
|
226
|
+
function printSnippets(io: CommandIO): void {
|
|
227
|
+
log(io, chalk.blue('📄 Harness 配置代码片段'));
|
|
228
|
+
log(io);
|
|
231
229
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
230
|
+
log(io, chalk.yellow('Git pre-commit hook:'));
|
|
231
|
+
log(io, chalk.gray('添加到 .git/hooks/pre-commit'));
|
|
232
|
+
log(io);
|
|
233
|
+
log(io, chalk.cyan(PRE_COMMIT_SNIPPET));
|
|
236
234
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
235
|
+
log(io, chalk.yellow('GitHub Actions:'));
|
|
236
|
+
log(io, chalk.gray('添加到 .github/workflows/*.yml 的 jobs 中'));
|
|
237
|
+
log(io);
|
|
238
|
+
log(io, chalk.cyan(GITHUB_ACTIONS_SNIPPET));
|
|
241
239
|
|
|
242
|
-
|
|
240
|
+
log(io, chalk.blue('💡 提示: 运行 npx @dommaker/harness init 自动创建配置文件'));
|
|
243
241
|
}
|
|
244
242
|
|
|
245
243
|
/**
|
|
246
|
-
* Git pre-commit
|
|
244
|
+
* Git pre-commit 代码片段(#103:打印片段与落盘 hook 的唯一正本;
|
|
245
|
+
* 落盘 hook = `#!/bin/sh` 头 + 本常量,改钩子只改这里)
|
|
247
246
|
*/
|
|
248
247
|
const PRE_COMMIT_SNIPPET = `
|
|
248
|
+
echo "🔍 Running harness checks..."
|
|
249
|
+
|
|
250
|
+
STAGED=$(git diff --cached --name-only --diff-filter=ACMR 2>/dev/null || true)
|
|
251
|
+
|
|
249
252
|
# Harness 约束检查
|
|
250
253
|
npx @dommaker/harness check --staged
|
|
251
254
|
if [ $? -ne 0 ]; then
|
|
@@ -254,7 +257,6 @@ if [ $? -ne 0 ]; then
|
|
|
254
257
|
fi
|
|
255
258
|
|
|
256
259
|
# Plan coverage check (via PostEval)
|
|
257
|
-
STAGED=$(git diff --cached --name-only --diff-filter=ACMR 2>/dev/null || true)
|
|
258
260
|
if command -v npx > /dev/null 2>&1; then
|
|
259
261
|
PLAN_FILES=$(echo "$STAGED" | grep -E 'plans/.*\\.md$|\\.plan\\.md$' || true)
|
|
260
262
|
if [ -n "$PLAN_FILES" ]; then
|
|
@@ -267,6 +269,8 @@ if command -v npx > /dev/null 2>&1; then
|
|
|
267
269
|
done
|
|
268
270
|
fi
|
|
269
271
|
fi
|
|
272
|
+
|
|
273
|
+
echo "✅ All checks passed"
|
|
270
274
|
`;
|
|
271
275
|
|
|
272
276
|
/**
|
|
@@ -287,7 +291,7 @@ const GITHUB_ACTIONS_SNIPPET = `
|
|
|
287
291
|
/**
|
|
288
292
|
* 设置 Git hooks
|
|
289
293
|
*/
|
|
290
|
-
async function setupGitHooks(projectPath: string): Promise<void> {
|
|
294
|
+
async function setupGitHooks(projectPath: string, io: CommandIO): Promise<void> {
|
|
291
295
|
const gitDir = path.join(projectPath, '.git');
|
|
292
296
|
const hooksDir = path.join(gitDir, 'hooks');
|
|
293
297
|
const preCommitPath = path.join(hooksDir, 'pre-commit');
|
|
@@ -295,8 +299,8 @@ async function setupGitHooks(projectPath: string): Promise<void> {
|
|
|
295
299
|
try {
|
|
296
300
|
await fs.access(gitDir);
|
|
297
301
|
} catch {
|
|
298
|
-
|
|
299
|
-
|
|
302
|
+
log(io, chalk.yellow('⚠️ 未检测到 Git 仓库,跳过 Git hooks'));
|
|
303
|
+
log(io, chalk.gray('💡 初始化 Git 后可运行 npx @dommaker/harness init --print-snippets 查看配置'));
|
|
300
304
|
return;
|
|
301
305
|
}
|
|
302
306
|
|
|
@@ -306,52 +310,25 @@ async function setupGitHooks(projectPath: string): Promise<void> {
|
|
|
306
310
|
try {
|
|
307
311
|
await fs.access(preCommitPath);
|
|
308
312
|
// 已存在,输出代码片段
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
+
log(io, chalk.yellow('⚠️ .git/hooks/pre-commit 已存在'));
|
|
314
|
+
log(io, chalk.gray('💡 请手动添加以下内容到文件末尾:'));
|
|
315
|
+
log(io);
|
|
316
|
+
log(io, chalk.cyan(PRE_COMMIT_SNIPPET));
|
|
313
317
|
} catch {
|
|
314
|
-
//
|
|
318
|
+
// 不存在,创建文件:shebang 头 + 共享片段(#103 同源,无第二份文本)
|
|
315
319
|
const preCommitContent = `#!/bin/sh
|
|
316
320
|
# Harness pre-commit hook
|
|
317
|
-
|
|
318
|
-
echo "🔍 Running harness checks..."
|
|
319
|
-
|
|
320
|
-
STAGED=$(git diff --cached --name-only --diff-filter=ACMR 2>/dev/null || true)
|
|
321
|
-
|
|
322
|
-
# 铁律检查
|
|
323
|
-
npx @dommaker/harness check --staged
|
|
324
|
-
if [ $? -ne 0 ]; then
|
|
325
|
-
echo "❌ Iron law check failed"
|
|
326
|
-
exit 1
|
|
327
|
-
fi
|
|
328
|
-
|
|
329
|
-
# Plan coverage check (via PostEval)
|
|
330
|
-
if command -v npx > /dev/null 2>&1; then
|
|
331
|
-
PLAN_FILES=$(echo "$STAGED" | grep -E 'plans/.*\\.md$|\\.plan\\.md$' || true)
|
|
332
|
-
if [ -n "$PLAN_FILES" ]; then
|
|
333
|
-
echo "📋 Checking plan coverage..."
|
|
334
|
-
for plan in $PLAN_FILES; do
|
|
335
|
-
npx @dommaker/harness posteval-plan "$plan" || {
|
|
336
|
-
echo "🛑 Plan coverage incomplete. See above for missed items."
|
|
337
|
-
exit 1
|
|
338
|
-
}
|
|
339
|
-
done
|
|
340
|
-
fi
|
|
341
|
-
fi
|
|
342
|
-
|
|
343
|
-
echo "✅ All checks passed"
|
|
344
|
-
`;
|
|
321
|
+
${PRE_COMMIT_SNIPPET}`;
|
|
345
322
|
await fs.writeFile(preCommitPath, preCommitContent, 'utf-8');
|
|
346
323
|
await fs.chmod(preCommitPath, 0o755);
|
|
347
|
-
|
|
324
|
+
log(io, chalk.green(`✅ 已创建 .git/hooks/pre-commit`));
|
|
348
325
|
}
|
|
349
326
|
}
|
|
350
327
|
|
|
351
328
|
/**
|
|
352
329
|
* 设置 GitHub Actions
|
|
353
330
|
*/
|
|
354
|
-
async function setupGitHubActions(projectPath: string): Promise<void> {
|
|
331
|
+
async function setupGitHubActions(projectPath: string, io: CommandIO): Promise<void> {
|
|
355
332
|
const workflowsDir = path.join(projectPath, '.github', 'workflows');
|
|
356
333
|
const workflowPath = path.join(workflowsDir, 'harness-check.yml');
|
|
357
334
|
|
|
@@ -360,13 +337,13 @@ async function setupGitHubActions(projectPath: string): Promise<void> {
|
|
|
360
337
|
|
|
361
338
|
if (existingFiles.length > 0) {
|
|
362
339
|
// 已有 CI 配置,输出代码片段
|
|
363
|
-
|
|
340
|
+
log(io, chalk.yellow('⚠️ 检测到已存在的 CI 配置:'));
|
|
364
341
|
existingFiles.forEach(f => {
|
|
365
|
-
|
|
342
|
+
log(io, chalk.gray(` - .github/workflows/${f}`));
|
|
366
343
|
});
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
344
|
+
log(io, chalk.gray('💡 请手动添加以下内容到 jobs 中:'));
|
|
345
|
+
log(io);
|
|
346
|
+
log(io, chalk.cyan(GITHUB_ACTIONS_SNIPPET));
|
|
370
347
|
return;
|
|
371
348
|
}
|
|
372
349
|
|
|
@@ -406,7 +383,7 @@ jobs:
|
|
|
406
383
|
`;
|
|
407
384
|
|
|
408
385
|
await fs.writeFile(workflowPath, workflowContent, 'utf-8');
|
|
409
|
-
|
|
386
|
+
log(io, chalk.green(`✅ 已创建 .github/workflows/harness-check.yml`));
|
|
410
387
|
}
|
|
411
388
|
|
|
412
389
|
/**
|
|
@@ -428,14 +405,14 @@ async function findCiWorkflows(workflowsDir: string): Promise<string[]> {
|
|
|
428
405
|
/**
|
|
429
406
|
* 创建自定义约束示例
|
|
430
407
|
*/
|
|
431
|
-
async function createCustomConstraintsExample(projectPath: string): Promise<void> {
|
|
408
|
+
async function createCustomConstraintsExample(projectPath: string, io: CommandIO): Promise<void> {
|
|
432
409
|
const configDir = path.join(projectPath, '.harness');
|
|
433
410
|
const customConstraintsPath = path.join(configDir, 'custom-constraints.yml');
|
|
434
411
|
|
|
435
412
|
// 如果已存在,不覆盖
|
|
436
413
|
try {
|
|
437
414
|
await fs.access(customConstraintsPath);
|
|
438
|
-
|
|
415
|
+
log(io, chalk.gray(`custom-constraints.yml 已存在`));
|
|
439
416
|
return;
|
|
440
417
|
} catch {
|
|
441
418
|
// 文件不存在,创建
|
|
@@ -477,7 +454,7 @@ custom_constraints:
|
|
|
477
454
|
`;
|
|
478
455
|
|
|
479
456
|
await fs.writeFile(customConstraintsPath, content, 'utf-8');
|
|
480
|
-
|
|
457
|
+
log(io, chalk.green(`✅ 已创建自定义约束示例: custom-constraints.yml`));
|
|
481
458
|
}
|
|
482
459
|
|
|
483
460
|
/**
|
|
@@ -513,7 +490,7 @@ function renderOutputStyleSection(): string {
|
|
|
513
490
|
* - 无标记且 `## Output Style` 段为用户自写(特征串不匹配):跳过并提示,不重复追加
|
|
514
491
|
* - 完全没有该段:在文件顶部插入标记版
|
|
515
492
|
*/
|
|
516
|
-
export async function setupClaudeMdOutputStyle(projectPath: string): Promise<void> {
|
|
493
|
+
export async function setupClaudeMdOutputStyle(projectPath: string, io: CommandIO = processIO): Promise<void> {
|
|
517
494
|
const claudeMdPath = path.join(projectPath, 'CLAUDE.md');
|
|
518
495
|
let content: string;
|
|
519
496
|
try {
|
|
@@ -524,20 +501,20 @@ export async function setupClaudeMdOutputStyle(projectPath: string): Promise<voi
|
|
|
524
501
|
}
|
|
525
502
|
|
|
526
503
|
const section = renderOutputStyleSection();
|
|
527
|
-
const
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
const newContent = content.slice(0, startIdx) + section + (after ? '\n' + after : '');
|
|
535
|
-
if (newContent !== content) {
|
|
536
|
-
await fs.writeFile(claudeMdPath, newContent, 'utf-8');
|
|
537
|
-
console.log(chalk.green('✅ 已更新 CLAUDE.md Output Style 段'));
|
|
504
|
+
const write = replaceStandaloneRange(content, OUTPUT_STYLE_START, OUTPUT_STYLE_END, section);
|
|
505
|
+
|
|
506
|
+
if (write.kind === 'updated') {
|
|
507
|
+
// 尾部换行规范化在 writer 内(幂等)。
|
|
508
|
+
if (write.content !== content) {
|
|
509
|
+
await fs.writeFile(claudeMdPath, write.content, 'utf-8');
|
|
510
|
+
log(io, chalk.green('✅ 已更新 CLAUDE.md Output Style 段'));
|
|
538
511
|
}
|
|
539
512
|
return;
|
|
540
513
|
}
|
|
514
|
+
if (write.kind === 'half') {
|
|
515
|
+
log(io, chalk.yellow('⚠️ CLAUDE.md 中 HARNESS_OUTPUT_STYLE 标记残缺(单边或乱序),跳过 Output Style 注入,请人工修复'));
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
541
518
|
|
|
542
519
|
// 检测旧版无标记 `## Output Style` 段
|
|
543
520
|
const legacyMatch = /^## Output Style[ \t]*$/m.exec(content);
|
|
@@ -550,7 +527,7 @@ export async function setupClaudeMdOutputStyle(projectPath: string): Promise<voi
|
|
|
550
527
|
|
|
551
528
|
if (!legacySection.includes(LEGACY_OUTPUT_STYLE_FINGERPRINT)) {
|
|
552
529
|
// 用户自写的同名 section:不动,也不追加(避免重复)
|
|
553
|
-
|
|
530
|
+
log(io, chalk.yellow('⚠️ CLAUDE.md 已存在自定义 "## Output Style" 段,跳过 harness Output Style 注入'));
|
|
554
531
|
return;
|
|
555
532
|
}
|
|
556
533
|
|
|
@@ -559,13 +536,13 @@ export async function setupClaudeMdOutputStyle(projectPath: string): Promise<voi
|
|
|
559
536
|
const after = content.slice(sectionEnd);
|
|
560
537
|
const newContent = before + section + (after.length > 0 ? '\n' + after : '');
|
|
561
538
|
await fs.writeFile(claudeMdPath, newContent, 'utf-8');
|
|
562
|
-
|
|
539
|
+
log(io, chalk.green('✅ 已将 CLAUDE.md Output Style 段迁移为标记化管理'));
|
|
563
540
|
return;
|
|
564
541
|
}
|
|
565
542
|
|
|
566
543
|
// 完全没有该段:插入文件顶部
|
|
567
544
|
await fs.writeFile(claudeMdPath, section + '\n' + content, 'utf-8');
|
|
568
|
-
|
|
545
|
+
log(io, chalk.green('✅ 已在 CLAUDE.md 顶部写入 Output Style 段'));
|
|
569
546
|
}
|
|
570
547
|
|
|
571
548
|
/**
|
|
@@ -584,15 +561,15 @@ const GOVERNANCE_PRESERVE_END = '<!-- /PRESERVE:governance -->';
|
|
|
584
561
|
* 有标记则只替换标记区间,段内其余手写内容(治理契约引言/流程/纪律等)原样保留;
|
|
585
562
|
* 无标记(纯手写段)则在段尾追加注入段,不动手写内容
|
|
586
563
|
* - 无该段:在文件末尾追加
|
|
587
|
-
* -
|
|
564
|
+
* - 段标记残缺(外层或段内 HARNESS_CONSTRAINTS 单边/乱序):不写入,告警交由人工修复(防二次损坏)
|
|
588
565
|
*/
|
|
589
|
-
export async function setupAgentsMdConstraints(projectPath: string): Promise<void> {
|
|
566
|
+
export async function setupAgentsMdConstraints(projectPath: string, io: CommandIO = processIO): Promise<void> {
|
|
590
567
|
const agentsMdPath = path.join(projectPath, 'AGENTS.md');
|
|
591
|
-
const version =
|
|
568
|
+
const version = getHarnessPackageVersion();
|
|
592
569
|
|
|
593
570
|
const constraints = getEffectiveConstraints(projectPath);
|
|
594
571
|
const bodyOnly = renderConstraintsSection(constraints, version);
|
|
595
|
-
const block = `${GOVERNANCE_PRESERVE_BEGIN}\n
|
|
572
|
+
const block = `${GOVERNANCE_PRESERVE_BEGIN}\n${GOVERNANCE_HEADING}\n${bodyOnly}${GOVERNANCE_PRESERVE_END}\n`;
|
|
596
573
|
|
|
597
574
|
let existingContent: string | null = null;
|
|
598
575
|
try {
|
|
@@ -610,57 +587,47 @@ export async function setupAgentsMdConstraints(projectPath: string): Promise<voi
|
|
|
610
587
|
block,
|
|
611
588
|
].join('\n');
|
|
612
589
|
await fs.writeFile(agentsMdPath, skeleton, 'utf-8');
|
|
613
|
-
|
|
590
|
+
log(io, chalk.green(`✅ 已创建 AGENTS.md 并写入治理契约 PRESERVE:governance 段 (v${version})`));
|
|
614
591
|
return;
|
|
615
592
|
}
|
|
616
593
|
|
|
617
|
-
const
|
|
618
|
-
const endIdx = existingContent.indexOf(GOVERNANCE_PRESERVE_END);
|
|
594
|
+
const preserve = cutMarkerBlock(existingContent, GOVERNANCE_PRESERVE_BEGIN, GOVERNANCE_PRESERVE_END);
|
|
619
595
|
|
|
620
|
-
if (
|
|
621
|
-
|
|
622
|
-
const before = existingContent.slice(0, startIdx);
|
|
623
|
-
const blockContent = existingContent.slice(startIdx + GOVERNANCE_PRESERVE_BEGIN.length, endIdx);
|
|
624
|
-
const after = existingContent.slice(endIdx + GOVERNANCE_PRESERVE_END.length).replace(/^\n+/, '');
|
|
625
|
-
|
|
626
|
-
const csIdx = blockContent.indexOf(CONSTRAINTS_START_MARKER);
|
|
627
|
-
const ceIdx = blockContent.indexOf(CONSTRAINTS_END_MARKER);
|
|
628
|
-
let newBlockContent: string;
|
|
629
|
-
if (csIdx !== -1 && ceIdx !== -1 && ceIdx > csIdx) {
|
|
630
|
-
// 只替换标记区间。bodyOnly 自带结尾换行,故剥掉尾部恰好一个前导换行
|
|
631
|
-
// (END 标记行的行尾换行),其余手写内容逐字保留,保证幂等。
|
|
632
|
-
newBlockContent =
|
|
633
|
-
blockContent.slice(0, csIdx) +
|
|
634
|
-
bodyOnly +
|
|
635
|
-
blockContent.slice(ceIdx + CONSTRAINTS_END_MARKER.length).replace(/^\n/, '');
|
|
636
|
-
} else {
|
|
637
|
-
// 纯手写段(无约束标记):段尾追加注入段,手写内容不动
|
|
638
|
-
newBlockContent = blockContent.trimEnd() + '\n\n## Governance Rules\n' + bodyOnly;
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
const newContent =
|
|
642
|
-
before +
|
|
643
|
-
GOVERNANCE_PRESERVE_BEGIN +
|
|
644
|
-
newBlockContent +
|
|
645
|
-
GOVERNANCE_PRESERVE_END +
|
|
646
|
-
'\n' +
|
|
647
|
-
(after ? '\n' + after : '');
|
|
648
|
-
if (newContent !== existingContent) {
|
|
649
|
-
await fs.writeFile(agentsMdPath, newContent, 'utf-8');
|
|
650
|
-
console.log(chalk.green(`✅ 已更新 AGENTS.md 治理契约 PRESERVE:governance 段 (v${version})`));
|
|
651
|
-
}
|
|
596
|
+
if (preserve === 'half') {
|
|
597
|
+
log(io, chalk.yellow('⚠️ AGENTS.md 中 PRESERVE:governance 标记残缺(只有单边),跳过治理契约写入,请人工修复'));
|
|
652
598
|
return;
|
|
653
599
|
}
|
|
654
600
|
|
|
655
|
-
if (
|
|
656
|
-
|
|
601
|
+
if (preserve !== 'absent') {
|
|
602
|
+
// 段内机器管理的只有 HARNESS_CONSTRAINTS 标记区间;其余手写内容原样保留
|
|
603
|
+
const inner = replaceEnclosedRange(preserve.inner, CONSTRAINTS_START_MARKER, CONSTRAINTS_END_MARKER, bodyOnly);
|
|
604
|
+
if (inner.kind === 'half') {
|
|
605
|
+
log(io, chalk.yellow('⚠️ AGENTS.md PRESERVE:governance 段内 HARNESS_CONSTRAINTS 标记残缺(单边或乱序),跳过治理契约写入,请人工修复'));
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
const newInner =
|
|
609
|
+
inner.kind === 'updated'
|
|
610
|
+
? inner.content
|
|
611
|
+
: // 纯手写段(无约束标记):段尾追加注入段,手写内容不动
|
|
612
|
+
preserve.inner.trimEnd() + '\n\n' + GOVERNANCE_HEADING + '\n' + bodyOnly;
|
|
613
|
+
|
|
614
|
+
const write = replaceStandaloneRange(
|
|
615
|
+
existingContent,
|
|
616
|
+
GOVERNANCE_PRESERVE_BEGIN,
|
|
617
|
+
GOVERNANCE_PRESERVE_END,
|
|
618
|
+
GOVERNANCE_PRESERVE_BEGIN + newInner + GOVERNANCE_PRESERVE_END + '\n'
|
|
619
|
+
);
|
|
620
|
+
if (write.kind === 'updated' && write.content !== existingContent) {
|
|
621
|
+
await fs.writeFile(agentsMdPath, write.content, 'utf-8');
|
|
622
|
+
log(io, chalk.green(`✅ 已更新 AGENTS.md 治理契约 PRESERVE:governance 段 (v${version})`));
|
|
623
|
+
}
|
|
657
624
|
return;
|
|
658
625
|
}
|
|
659
626
|
|
|
660
627
|
// 无该段:文件末尾追加
|
|
661
628
|
const newContent = existingContent.trimEnd() + '\n\n' + block;
|
|
662
629
|
await fs.writeFile(agentsMdPath, newContent, 'utf-8');
|
|
663
|
-
|
|
630
|
+
log(io, chalk.green(`✅ 已追加治理契约 PRESERVE:governance 段到 AGENTS.md (v${version})`));
|
|
664
631
|
}
|
|
665
632
|
|
|
666
633
|
/**
|
|
@@ -673,23 +640,15 @@ export async function setupAgentsMdConstraints(projectPath: string): Promise<voi
|
|
|
673
640
|
* - 如果存在 HARNESS_CONSTRAINTS_START/END 标记,替换标记间内容
|
|
674
641
|
* - 如果不存在标记,在文件末尾追加约束段
|
|
675
642
|
*/
|
|
676
|
-
export async function setupClaudeMdConstraints(projectPath: string): Promise<void> {
|
|
643
|
+
export async function setupClaudeMdConstraints(projectPath: string, io: CommandIO = processIO): Promise<void> {
|
|
677
644
|
const claudeMdPath = path.join(projectPath, 'CLAUDE.md');
|
|
678
645
|
|
|
679
|
-
|
|
680
|
-
let version = 'unknown';
|
|
681
|
-
try {
|
|
682
|
-
const pkgPath = path.join(__dirname, '../../../package.json');
|
|
683
|
-
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
684
|
-
version = pkg.version;
|
|
685
|
-
} catch {
|
|
686
|
-
// fallback to 'unknown'
|
|
687
|
-
}
|
|
646
|
+
const version = getHarnessPackageVersion();
|
|
688
647
|
|
|
689
648
|
// 生效约束集 → 渲染期望段(纯函数,与写文件分离)
|
|
690
649
|
const constraints = getEffectiveConstraints(projectPath);
|
|
691
650
|
const bodyOnly = renderConstraintsSection(constraints, version);
|
|
692
|
-
const fullSection =
|
|
651
|
+
const fullSection = GOVERNANCE_HEADING + '\n' + bodyOnly;
|
|
693
652
|
|
|
694
653
|
// 检查 CLAUDE.md 是否存在
|
|
695
654
|
let existingContent: string;
|
|
@@ -704,65 +663,53 @@ export async function setupClaudeMdConstraints(projectPath: string): Promise<voi
|
|
|
704
663
|
if (!fileExists) {
|
|
705
664
|
// 创建新文件
|
|
706
665
|
await fs.writeFile(claudeMdPath, fullSection, 'utf-8');
|
|
707
|
-
|
|
666
|
+
log(io, chalk.green(`✅ 已创建 CLAUDE.md 并写入治理约束 (v${version})`));
|
|
708
667
|
return;
|
|
709
668
|
}
|
|
710
669
|
|
|
711
|
-
const
|
|
712
|
-
const endIdx = existingContent.indexOf(CONSTRAINTS_END_MARKER);
|
|
670
|
+
const write = replaceStandaloneRange(existingContent, CONSTRAINTS_START_MARKER, CONSTRAINTS_END_MARKER, bodyOnly);
|
|
713
671
|
|
|
714
|
-
if (
|
|
715
|
-
//
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
await fs.writeFile(claudeMdPath, newContent, 'utf-8');
|
|
721
|
-
console.log(chalk.green(`✅ 已更新 CLAUDE.md 治理约束 (v${version})`));
|
|
672
|
+
if (write.kind === 'updated') {
|
|
673
|
+
// 替换标记区间含标记本身(保持包括最新版本号),尾部换行规范化在 writer 内
|
|
674
|
+
await fs.writeFile(claudeMdPath, write.content, 'utf-8');
|
|
675
|
+
log(io, chalk.green(`✅ 已更新 CLAUDE.md 治理约束 (v${version})`));
|
|
676
|
+
} else if (write.kind === 'half') {
|
|
677
|
+
log(io, chalk.yellow('⚠️ CLAUDE.md 中 HARNESS_CONSTRAINTS 标记残缺(单边或乱序),跳过治理约束注入,请人工修复'));
|
|
722
678
|
} else {
|
|
723
679
|
// 在文件末尾追加完整段
|
|
724
680
|
const newContent = existingContent.trimEnd() + '\n\n' + fullSection;
|
|
725
681
|
await fs.writeFile(claudeMdPath, newContent, 'utf-8');
|
|
726
|
-
|
|
682
|
+
log(io, chalk.green(`✅ 已追加治理约束到 CLAUDE.md (v${version})`));
|
|
727
683
|
}
|
|
728
684
|
}
|
|
729
685
|
|
|
730
686
|
/**
|
|
731
687
|
* 治理约束段写入落点路由(studio #302,ADR 2026-08-21 落点模型)
|
|
732
688
|
*
|
|
689
|
+
* 判定收口在 core/constraints/injection-writer resolveGovernanceLanding:
|
|
733
690
|
* - 旧模型仓(CLAUDE.md 已有 HARNESS_CONSTRAINTS 标记或 `## Governance Rules` 块):
|
|
734
691
|
* 继续写 CLAUDE.md——init 幂等重跑不破坏既有仓,不制造双份约束正本
|
|
735
692
|
* - 其余(新仓初始化):写 AGENTS.md PRESERVE:governance 段(入库公共面正本)
|
|
736
693
|
*/
|
|
737
694
|
export async function setupGovernanceConstraints(projectPath: string): Promise<void> {
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
// CLAUDE.md 不存在 → 新仓
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
if (
|
|
746
|
-
claudeContent !== null &&
|
|
747
|
-
(claudeContent.includes(CONSTRAINTS_START_MARKER) || /^##\s+Governance Rules/m.test(claudeContent))
|
|
748
|
-
) {
|
|
749
|
-
return setupClaudeMdConstraints(projectPath);
|
|
750
|
-
}
|
|
751
|
-
return setupAgentsMdConstraints(projectPath);
|
|
695
|
+
const { target } = resolveGovernanceLanding(projectPath);
|
|
696
|
+
return target === 'claude-md'
|
|
697
|
+
? setupClaudeMdConstraints(projectPath)
|
|
698
|
+
: setupAgentsMdConstraints(projectPath);
|
|
752
699
|
}
|
|
753
700
|
|
|
754
701
|
/**
|
|
755
702
|
* 设置治理相关文件
|
|
756
703
|
*/
|
|
757
|
-
async function setupGovernance(projectPath: string, level: string): Promise<void> {
|
|
758
|
-
const governance = GOVERNANCE_PRESETS[level]
|
|
704
|
+
async function setupGovernance(projectPath: string, level: string, io: CommandIO): Promise<void> {
|
|
705
|
+
const governance = GOVERNANCE_PRESETS[level];
|
|
759
706
|
if (!governance) return;
|
|
760
707
|
|
|
761
|
-
|
|
762
|
-
|
|
708
|
+
log(io);
|
|
709
|
+
log(io, chalk.blue('📋 设置治理文件...'));
|
|
763
710
|
|
|
764
711
|
// 1. 生成 CHANGELOG.md
|
|
765
|
-
await createChangelog(projectPath, governance);
|
|
712
|
+
await createChangelog(projectPath, governance, io);
|
|
766
713
|
|
|
767
714
|
// 2. 在 CLAUDE.md 中写入 Output Style 段(仅在不存在时创建)
|
|
768
715
|
await setupClaudeMdOutputStyle(projectPath);
|
|
@@ -771,38 +718,37 @@ async function setupGovernance(projectPath: string, level: string): Promise<void
|
|
|
771
718
|
// 旧模型仓 → CLAUDE.md,落点路由见 setupGovernanceConstraints)
|
|
772
719
|
await setupGovernanceConstraints(projectPath);
|
|
773
720
|
|
|
774
|
-
// 4. 生成 CONTEXT.md
|
|
775
|
-
const contextConfig = governance.context_files
|
|
721
|
+
// 4. 生成 CONTEXT.md 文件(预设形状即 GovernanceConfig,无需再 cast)
|
|
722
|
+
const contextConfig = governance.context_files;
|
|
776
723
|
if (contextConfig?.enabled) {
|
|
777
|
-
let requiredDirs =
|
|
724
|
+
let requiredDirs = contextConfig.required_dirs ?? [];
|
|
778
725
|
if (requiredDirs.length === 0) {
|
|
779
726
|
requiredDirs = detectSourceRoots(projectPath);
|
|
780
727
|
}
|
|
781
728
|
for (const dir of requiredDirs) {
|
|
782
|
-
await createContextMd(projectPath, dir);
|
|
729
|
+
await createContextMd(projectPath, dir, io);
|
|
783
730
|
}
|
|
784
731
|
}
|
|
785
732
|
|
|
786
733
|
// 4. 生成治理 CI workflow
|
|
787
|
-
await setupGovernanceWorkflow(projectPath, level);
|
|
734
|
+
await setupGovernanceWorkflow(projectPath, level, io);
|
|
788
735
|
}
|
|
789
736
|
|
|
790
737
|
/**
|
|
791
738
|
* 创建 CHANGELOG.md
|
|
792
739
|
*/
|
|
793
|
-
async function createChangelog(projectPath: string, governance:
|
|
740
|
+
async function createChangelog(projectPath: string, governance: GovernanceConfig, io: CommandIO): Promise<void> {
|
|
794
741
|
const changelogPath = path.join(projectPath, 'CHANGELOG.md');
|
|
795
742
|
|
|
796
743
|
try {
|
|
797
744
|
await fs.access(changelogPath);
|
|
798
|
-
|
|
745
|
+
log(io, chalk.gray(`CHANGELOG.md 已存在`));
|
|
799
746
|
return;
|
|
800
747
|
} catch {
|
|
801
748
|
// 文件不存在,创建
|
|
802
749
|
}
|
|
803
750
|
|
|
804
|
-
const
|
|
805
|
-
const format = (changelogConfig?.format as string) || 'keep-a-changelog';
|
|
751
|
+
const format = governance.changelog?.format || 'keep-a-changelog';
|
|
806
752
|
|
|
807
753
|
let content: string;
|
|
808
754
|
if (format === 'keep-a-changelog') {
|
|
@@ -836,18 +782,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
836
782
|
}
|
|
837
783
|
|
|
838
784
|
await fs.writeFile(changelogPath, content, 'utf-8');
|
|
839
|
-
|
|
785
|
+
log(io, chalk.green(`✅ 已创建 CHANGELOG.md`));
|
|
840
786
|
}
|
|
841
787
|
|
|
842
788
|
/**
|
|
843
789
|
* 在指定目录创建 CONTEXT.md
|
|
844
790
|
*/
|
|
845
|
-
async function createContextMd(projectPath: string, dir: string): Promise<void> {
|
|
791
|
+
async function createContextMd(projectPath: string, dir: string, io: CommandIO): Promise<void> {
|
|
846
792
|
const contextPath = path.join(projectPath, dir, 'CONTEXT.md');
|
|
847
793
|
|
|
848
794
|
try {
|
|
849
795
|
await fs.access(contextPath);
|
|
850
|
-
|
|
796
|
+
log(io, chalk.gray(`${dir}/CONTEXT.md 已存在`));
|
|
851
797
|
return;
|
|
852
798
|
} catch {
|
|
853
799
|
// 文件不存在,创建
|
|
@@ -858,7 +804,7 @@ async function createContextMd(projectPath: string, dir: string): Promise<void>
|
|
|
858
804
|
try {
|
|
859
805
|
await fs.access(dirPath);
|
|
860
806
|
} catch {
|
|
861
|
-
|
|
807
|
+
log(io, chalk.yellow(`⚠️ 目录 ${dir} 不存在,跳过 CONTEXT.md`));
|
|
862
808
|
return;
|
|
863
809
|
}
|
|
864
810
|
|
|
@@ -885,7 +831,7 @@ async function createContextMd(projectPath: string, dir: string): Promise<void>
|
|
|
885
831
|
`;
|
|
886
832
|
|
|
887
833
|
await fs.writeFile(contextPath, content, 'utf-8');
|
|
888
|
-
|
|
834
|
+
log(io, chalk.green(`✅ 已创建 ${dir}/CONTEXT.md`));
|
|
889
835
|
}
|
|
890
836
|
|
|
891
837
|
/**
|
|
@@ -911,14 +857,14 @@ async function findGovernanceCoverage(workflowsDir: string): Promise<string | un
|
|
|
911
857
|
/**
|
|
912
858
|
* 设置治理 CI workflow
|
|
913
859
|
*/
|
|
914
|
-
async function setupGovernanceWorkflow(projectPath: string, level: string): Promise<void> {
|
|
860
|
+
async function setupGovernanceWorkflow(projectPath: string, level: string, io: CommandIO): Promise<void> {
|
|
915
861
|
const workflowsDir = path.join(projectPath, '.github', 'workflows');
|
|
916
862
|
const workflowPath = path.join(workflowsDir, 'harness-governance.yml');
|
|
917
863
|
|
|
918
864
|
// 检查是否已存在
|
|
919
865
|
try {
|
|
920
866
|
await fs.access(workflowPath);
|
|
921
|
-
|
|
867
|
+
log(io, chalk.gray(`harness-governance.yml 已存在`));
|
|
922
868
|
return;
|
|
923
869
|
} catch {
|
|
924
870
|
// 不存在,继续创建
|
|
@@ -927,7 +873,7 @@ async function setupGovernanceWorkflow(projectPath: string, level: string): Prom
|
|
|
927
873
|
// 能力检测:已有 workflow 已跑 harness 治理命令时跳过,避免重复 CI 面
|
|
928
874
|
const coveredBy = await findGovernanceCoverage(workflowsDir);
|
|
929
875
|
if (coveredBy) {
|
|
930
|
-
|
|
876
|
+
log(io, chalk.gray(`治理检查已由 ${coveredBy} 覆盖,跳过创建 harness-governance.yml`));
|
|
931
877
|
return;
|
|
932
878
|
}
|
|
933
879
|
|
|
@@ -972,5 +918,5 @@ ${docsCheckStep}
|
|
|
972
918
|
`;
|
|
973
919
|
|
|
974
920
|
await fs.writeFile(workflowPath, workflowContent, 'utf-8');
|
|
975
|
-
|
|
921
|
+
log(io, chalk.green(`✅ 已创建 .github/workflows/harness-governance.yml`));
|
|
976
922
|
}
|