@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
|
@@ -9,8 +9,11 @@ import * as fs from 'fs';
|
|
|
9
9
|
import * as path from 'path';
|
|
10
10
|
import { TraceCollector } from '../../monitoring/traces';
|
|
11
11
|
import { TraceAnalyzer } from '../../monitoring/trace-analyzer';
|
|
12
|
+
import { readJsonl } from '../../utils/jsonl';
|
|
12
13
|
import { DEFAULT_TRACE_FILE } from '../../types/trace';
|
|
14
|
+
import type { ExecutionTrace } from '../../types/trace';
|
|
13
15
|
import type { TraceSummary, TraceAnomaly } from '../../types/trace';
|
|
16
|
+
import { log, logError, processIO, type CommandIO, type CommandResult } from '../command-contract';
|
|
14
17
|
|
|
15
18
|
export interface StatusOptions {
|
|
16
19
|
/** 项目路径 */
|
|
@@ -26,42 +29,38 @@ export interface StatusOptions {
|
|
|
26
29
|
/**
|
|
27
30
|
* 显示 Harness 状态
|
|
28
31
|
*/
|
|
29
|
-
export async function status(options: StatusOptions): Promise<
|
|
32
|
+
export async function status(options: StatusOptions, io: CommandIO = processIO): Promise<CommandResult> {
|
|
30
33
|
const projectPath = options.projectPath || process.cwd();
|
|
31
34
|
const harnessDir = path.join(projectPath, '.harness');
|
|
32
35
|
const tracesPath = path.join(projectPath, DEFAULT_TRACE_FILE);
|
|
33
36
|
const statePath = path.join(harnessDir, '.state.json');
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
log(io, chalk.blue('📊 Harness 状态'));
|
|
39
|
+
log(io);
|
|
37
40
|
|
|
38
41
|
// 检查是否初始化
|
|
39
42
|
if (!fs.existsSync(harnessDir)) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return;
|
|
43
|
+
log(io, chalk.yellow('⚠️ 未初始化'));
|
|
44
|
+
log(io, chalk.gray('💡 运行 harness init 初始化项目'));
|
|
45
|
+
return { kind: 'ok' };
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
// 检查 trace 文件
|
|
46
49
|
if (!fs.existsSync(tracesPath)) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return;
|
|
50
|
+
log(io, chalk.yellow('⚠️ 暂无 Trace 记录'));
|
|
51
|
+
log(io, chalk.gray('💡 运行 harness check 开始记录'));
|
|
52
|
+
return { kind: 'ok' };
|
|
50
53
|
}
|
|
51
54
|
|
|
52
|
-
// 读取 trace
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
//
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
} catch {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
}).filter(Boolean);
|
|
55
|
+
// 读取 trace 文件:坏行策略 skip(原 null + filter(Boolean) 语义不变,harness#82)
|
|
56
|
+
// traceCount 保持原始非空行数口径(合法 + 跳过),与改前显示逐字节一致;
|
|
57
|
+
// filter(Boolean) 沿用原语义:parse 成功但值为 falsy 的行(如 "null")不进分析
|
|
58
|
+
// 计数去向:harness#100——skippedLines 另起一行走 stderr 告知(口径不改,只补告知)。
|
|
59
|
+
// 不经 TraceCollector.readReport():本命令按 -p 的 projectPath 直读读链正本,且要的是
|
|
60
|
+
// records + skippedLines 的原始行数口径;下面另建的 collector/analyzer 只用于 summarize/detectAnomalies
|
|
61
|
+
const { records, skippedLines } = readJsonl<ExecutionTrace>(tracesPath, 'skip');
|
|
62
|
+
const traces = records.filter(Boolean);
|
|
63
|
+
const traceCount = records.length + skippedLines;
|
|
65
64
|
|
|
66
65
|
// 创建收集器和分析器
|
|
67
66
|
const collector = new TraceCollector({ traceFile: tracesPath });
|
|
@@ -72,71 +71,77 @@ export async function status(options: StatusOptions): Promise<void> {
|
|
|
72
71
|
const anomalies = analyzer.detectAnomalies(summaries);
|
|
73
72
|
|
|
74
73
|
// 基本统计
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
log(io, chalk.gray(`记录数: ${traceCount} 条`));
|
|
75
|
+
log(io);
|
|
76
|
+
|
|
77
|
+
// 数据不完整必须让看报告的人知道(harness#100):诊断信息走 stderr,
|
|
78
|
+
// stdout 报告体口径与字节不变;无损坏零噪声
|
|
79
|
+
if (skippedLines > 0) {
|
|
80
|
+
logError(io, `⚠️ trace 文件有 ${skippedLines} 行损坏已跳过,上述记录数含坏行,统计只基于其余合法记录`);
|
|
81
|
+
}
|
|
77
82
|
|
|
78
83
|
if (options.anomalies) {
|
|
79
84
|
// 只显示异常
|
|
80
85
|
if (anomalies.length === 0) {
|
|
81
|
-
|
|
86
|
+
log(io, chalk.green('✅ 未发现异常'));
|
|
82
87
|
} else {
|
|
83
|
-
|
|
84
|
-
|
|
88
|
+
log(io, chalk.yellow(`⚠️ 发现 ${anomalies.length} 个异常:`));
|
|
89
|
+
log(io);
|
|
85
90
|
anomalies.forEach((a: TraceAnomaly) => {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
+
log(io, chalk.yellow(` ${a.constraintId}`));
|
|
92
|
+
log(io, chalk.gray(` 类型: ${a.type}`));
|
|
93
|
+
log(io, chalk.gray(` 当前值: ${a.data?.currentRate ?? (a as any).current ?? 'N/A'}`));
|
|
94
|
+
log(io, chalk.gray(` 阈值: ${a.data?.threshold ?? (a as any).threshold ?? 'N/A'}`));
|
|
95
|
+
log(io);
|
|
91
96
|
});
|
|
92
97
|
|
|
93
98
|
// 下一步建议
|
|
94
|
-
|
|
95
|
-
|
|
99
|
+
log(io, chalk.blue('💡 下一步建议:'));
|
|
100
|
+
log(io, chalk.gray(' 运行 harness status --detail 查看详情'));
|
|
96
101
|
}
|
|
97
|
-
return;
|
|
102
|
+
return { kind: 'ok' };
|
|
98
103
|
}
|
|
99
104
|
|
|
100
105
|
// 显示约束统计
|
|
101
|
-
|
|
102
|
-
|
|
106
|
+
log(io, chalk.blue('📈 约束统计:'));
|
|
107
|
+
log(io);
|
|
103
108
|
|
|
104
109
|
// Iron Laws
|
|
105
110
|
const ironLawSummaries = summaries.filter((s: TraceSummary) => s.level === 'iron_law');
|
|
106
111
|
if (ironLawSummaries.length > 0) {
|
|
107
|
-
|
|
112
|
+
log(io, chalk.red('🔴 Iron Laws:'));
|
|
108
113
|
ironLawSummaries.forEach((s: TraceSummary) => {
|
|
109
114
|
const status = s.passRate >= 1 ? '✅' : '❌';
|
|
110
|
-
|
|
115
|
+
log(io, ` ${status} ${s.constraintId}`);
|
|
111
116
|
if (options.detail) {
|
|
112
|
-
|
|
117
|
+
log(io, chalk.gray(` 检查: ${s.totalChecks} | 通过: ${(s.passRate * 100).toFixed(0)}% | 失败: ${(s.failRate * 100).toFixed(0)}%`));
|
|
113
118
|
}
|
|
114
119
|
});
|
|
115
|
-
|
|
120
|
+
log(io);
|
|
116
121
|
}
|
|
117
122
|
|
|
118
123
|
// Guidelines
|
|
119
124
|
const guidelineSummaries = summaries.filter((s: TraceSummary) => s.level === 'guideline');
|
|
120
125
|
if (guidelineSummaries.length > 0) {
|
|
121
|
-
|
|
126
|
+
log(io, chalk.yellow('🟡 Guidelines:'));
|
|
122
127
|
guidelineSummaries.forEach((s: TraceSummary) => {
|
|
123
128
|
const status = s.passRate >= 0.8 ? '✅' : s.passRate >= 0.5 ? '⚠️' : '❌';
|
|
124
|
-
|
|
129
|
+
log(io, ` ${status} ${s.constraintId}`);
|
|
125
130
|
if (options.detail) {
|
|
126
|
-
|
|
131
|
+
log(io, chalk.gray(` 检查: ${s.totalChecks} | 通过: ${(s.passRate * 100).toFixed(0)}% | 失败: ${(s.failRate * 100).toFixed(0)}%`));
|
|
127
132
|
}
|
|
128
133
|
});
|
|
129
|
-
|
|
134
|
+
log(io);
|
|
130
135
|
}
|
|
131
136
|
|
|
132
137
|
// 异常检测
|
|
133
138
|
if (anomalies.length > 0) {
|
|
134
|
-
|
|
135
|
-
|
|
139
|
+
log(io, chalk.yellow(`⚠️ 发现 ${anomalies.length} 个异常`));
|
|
140
|
+
log(io);
|
|
136
141
|
anomalies.slice(0, 3).forEach((a: TraceAnomaly) => {
|
|
137
|
-
|
|
142
|
+
log(io, chalk.yellow(` - ${a.constraintId}: ${a.type}`));
|
|
138
143
|
});
|
|
139
|
-
|
|
144
|
+
log(io);
|
|
140
145
|
}
|
|
141
146
|
|
|
142
147
|
// 更新状态文件
|
|
@@ -147,12 +152,13 @@ export async function status(options: StatusOptions): Promise<void> {
|
|
|
147
152
|
fs.writeFileSync(statePath, JSON.stringify(state, null, 2));
|
|
148
153
|
|
|
149
154
|
// 下一步建议
|
|
150
|
-
|
|
155
|
+
log(io, chalk.blue('💡 下一步建议:'));
|
|
151
156
|
if (anomalies.length > 0) {
|
|
152
|
-
|
|
157
|
+
log(io, chalk.gray(' harness status --detail # 查看详细状态'));
|
|
153
158
|
} else if (traceCount >= 100) {
|
|
154
|
-
|
|
159
|
+
log(io, chalk.gray(' • 状态良好,继续保持!'));
|
|
155
160
|
} else {
|
|
156
|
-
|
|
161
|
+
log(io, chalk.gray(' • 继续积累数据,记录越多分析越准确'));
|
|
157
162
|
}
|
|
163
|
+
return { kind: 'ok' };
|
|
158
164
|
}
|
|
@@ -6,6 +6,8 @@ import * as fs from 'fs/promises';
|
|
|
6
6
|
import { existsSync } from 'fs';
|
|
7
7
|
import * as path from 'path';
|
|
8
8
|
import { loadRawProjectConfig } from '../../../core/project-config-loader';
|
|
9
|
+
import { hasGovernanceContract } from '../../../core/constraints/injection-writer';
|
|
10
|
+
import { DEFAULT_SKIP_DIRS } from '../../../utils/file-walk';
|
|
9
11
|
import {
|
|
10
12
|
readPackageJsonLite,
|
|
11
13
|
getConfigDescription,
|
|
@@ -222,7 +224,8 @@ async function getGovernanceInfo(projectPath: string): Promise<GovernanceInfo> {
|
|
|
222
224
|
|
|
223
225
|
try {
|
|
224
226
|
const claude = await fs.readFile(path.join(projectPath, 'CLAUDE.md'), 'utf-8');
|
|
225
|
-
|
|
227
|
+
// 契约在场判定收口 injection-writer.hasGovernanceContract(#83,与 presence/landing 同谓词)
|
|
228
|
+
if (hasGovernanceContract(claude)) {
|
|
226
229
|
info.hasClaudeGovernance = true;
|
|
227
230
|
info.ironLaws = countConstraintBullets(claude, 'Iron Laws');
|
|
228
231
|
info.guidelines = countConstraintBullets(claude, 'Guidelines');
|
|
@@ -293,7 +296,7 @@ async function countContextDocs(projectPath: string, srcDirs: string[]): Promise
|
|
|
293
296
|
}
|
|
294
297
|
for (const entry of entries) {
|
|
295
298
|
if (!entry.isDirectory()) continue;
|
|
296
|
-
if (
|
|
299
|
+
if (DEFAULT_SKIP_DIRS.includes(entry.name)) continue;
|
|
297
300
|
const entryPath = path.join(dir, entry.name);
|
|
298
301
|
if (existsSync(path.join(entryPath, 'CONTEXT.md'))) {
|
|
299
302
|
found.add(entryPath);
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import * as fs from 'fs/promises';
|
|
6
6
|
import * as path from 'path';
|
|
7
|
+
import { DEFAULT_SKIP_DIRS } from '../../../utils/file-walk';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* 创建 CONTEXT.md 模板
|
|
@@ -53,7 +54,7 @@ export async function findExistingContextFiles(projectPath: string, srcDirs: str
|
|
|
53
54
|
return;
|
|
54
55
|
}
|
|
55
56
|
for (const entry of entries) {
|
|
56
|
-
if (entry
|
|
57
|
+
if (DEFAULT_SKIP_DIRS.includes(entry)) continue;
|
|
57
58
|
const entryPath = path.join(dir, entry);
|
|
58
59
|
const stat = await fs.stat(entryPath);
|
|
59
60
|
if (stat.isDirectory()) {
|
|
@@ -90,7 +91,7 @@ export async function getLatestTsMtime(dirPath: string): Promise<number | null>
|
|
|
90
91
|
return;
|
|
91
92
|
}
|
|
92
93
|
for (const entry of entries) {
|
|
93
|
-
if (entry
|
|
94
|
+
if (DEFAULT_SKIP_DIRS.includes(entry)) continue;
|
|
94
95
|
const entryPath = path.join(dir, entry);
|
|
95
96
|
const stat = await fs.stat(entryPath);
|
|
96
97
|
if (stat.isDirectory()) {
|
|
@@ -17,12 +17,14 @@ import * as fs from 'fs/promises';
|
|
|
17
17
|
import { existsSync } from 'fs';
|
|
18
18
|
import * as path from 'path';
|
|
19
19
|
import {
|
|
20
|
-
aggregateToSourceSubdir,
|
|
21
|
-
readCapabilitiesEntries,
|
|
22
20
|
isCapabilityListingFormat,
|
|
23
21
|
checkCapabilityCounts,
|
|
24
22
|
updateCapabilityCounts,
|
|
23
|
+
type CapabilityDefinitionSource,
|
|
25
24
|
} from '../../../core/constraints/capabilities-parser';
|
|
25
|
+
import { COMMAND_DEFINITIONS } from '../definitions';
|
|
26
|
+
import { GATE_DEFINITIONS } from '../../../gates/definitions';
|
|
27
|
+
import { reconcileCapabilities } from '../../../core/constraints/capabilities-reconcile';
|
|
26
28
|
import { detectSourceRoots } from '../../../utils/detect-source-roots';
|
|
27
29
|
import { getCapabilitiesMode } from '../../../core/project-config-loader';
|
|
28
30
|
import { getSourceDirs, scanSourceModules, getRequiredContextDirs } from './project-reader';
|
|
@@ -35,6 +37,7 @@ import {
|
|
|
35
37
|
import { createContextMd, findExistingContextFiles, getLatestTsMtime } from './context-syncer';
|
|
36
38
|
import { buildAgentsMd } from './agents-syncer';
|
|
37
39
|
import { extractPreserveBlocks, composeAgentsMd } from './preserve-block';
|
|
40
|
+
import { log, processIO, type CommandIO, type CommandResult } from '../../command-contract';
|
|
38
41
|
|
|
39
42
|
export interface SyncDocsOptions {
|
|
40
43
|
/** 项目路径 */
|
|
@@ -51,12 +54,28 @@ export interface SyncDocsOptions {
|
|
|
51
54
|
compact?: boolean;
|
|
52
55
|
}
|
|
53
56
|
|
|
57
|
+
/**
|
|
58
|
+
* 能力清单计数源(harness#88)
|
|
59
|
+
*
|
|
60
|
+
* core 的 capabilities-parser 不再值导入定义表(单向分层),命令/门禁计数由
|
|
61
|
+
* cli 侧在此组装后注入;两张表都是纯数据模块(ADR-0002 命令形状单一来源)。
|
|
62
|
+
*/
|
|
63
|
+
const CAPABILITY_DEFINITIONS: CapabilityDefinitionSource = {
|
|
64
|
+
commands: COMMAND_DEFINITIONS,
|
|
65
|
+
gates: GATE_DEFINITIONS,
|
|
66
|
+
};
|
|
67
|
+
|
|
54
68
|
/**
|
|
55
69
|
* 同步文档
|
|
56
70
|
*/
|
|
57
|
-
export async function syncDocs(
|
|
71
|
+
export async function syncDocs(
|
|
72
|
+
options: SyncDocsOptions,
|
|
73
|
+
io: CommandIO = processIO,
|
|
74
|
+
): Promise<CommandResult> {
|
|
58
75
|
const projectPath = options.projectPath || process.cwd();
|
|
59
76
|
const isCheck = options.check === true;
|
|
77
|
+
// 漂移译成 kind:--check 下判定失败;写入模式下漂移已被修掉 → 退出码面不变(历史行为)
|
|
78
|
+
const drift = (reason: string): CommandResult => (isCheck ? { kind: 'fail', reason } : { kind: 'ok' });
|
|
60
79
|
const isJson = options.json === true;
|
|
61
80
|
const capsMode = getCapabilitiesMode(projectPath);
|
|
62
81
|
|
|
@@ -68,22 +87,22 @@ export async function syncDocs(options: SyncDocsOptions): Promise<boolean> {
|
|
|
68
87
|
const compacted = compactCapabilitiesContent(content);
|
|
69
88
|
if (compacted !== content) {
|
|
70
89
|
await fs.writeFile(capsPath, compacted, 'utf-8');
|
|
71
|
-
if (!isJson)
|
|
90
|
+
if (!isJson) log(io, chalk.green('✅ 已将 CAPABILITIES.md 文件表格折叠为目录条目'));
|
|
72
91
|
} else {
|
|
73
|
-
if (!isJson)
|
|
92
|
+
if (!isJson) log(io, chalk.green('✅ CAPABILITIES.md 无需折叠'));
|
|
74
93
|
}
|
|
75
|
-
return
|
|
94
|
+
return { kind: 'ok' };
|
|
76
95
|
} catch {
|
|
77
|
-
if (!isJson)
|
|
78
|
-
return
|
|
96
|
+
if (!isJson) log(io, chalk.red('❌ CAPABILITIES.md 不存在,无法折叠'));
|
|
97
|
+
return drift('CAPABILITIES.md 不存在,无法折叠');
|
|
79
98
|
}
|
|
80
99
|
}
|
|
81
100
|
|
|
82
101
|
if (!isJson) {
|
|
83
102
|
if (isCheck) {
|
|
84
|
-
|
|
103
|
+
log(io, chalk.blue('🔍 检查文档新鲜度...'));
|
|
85
104
|
} else {
|
|
86
|
-
|
|
105
|
+
log(io, chalk.blue('📝 同步文档...'));
|
|
87
106
|
}
|
|
88
107
|
}
|
|
89
108
|
|
|
@@ -103,7 +122,7 @@ export async function syncDocs(options: SyncDocsOptions): Promise<boolean> {
|
|
|
103
122
|
currentModules.push(...modules);
|
|
104
123
|
} catch {
|
|
105
124
|
if (!isJson) {
|
|
106
|
-
|
|
125
|
+
log(io, chalk.yellow(`⚠️ 未找到 ${srcDir} 目录,跳过`));
|
|
107
126
|
}
|
|
108
127
|
}
|
|
109
128
|
}
|
|
@@ -130,77 +149,31 @@ export async function syncDocs(options: SyncDocsOptions): Promise<boolean> {
|
|
|
130
149
|
|
|
131
150
|
if (capsIsCapabilityListing) {
|
|
132
151
|
// 能力清单格式:委托 FreshnessRunner 对比计数
|
|
133
|
-
const countCheck = checkCapabilityCounts(projectPath);
|
|
152
|
+
const countCheck = checkCapabilityCounts(projectPath, CAPABILITY_DEFINITIONS);
|
|
134
153
|
capCountMismatches = countCheck.mismatches;
|
|
135
154
|
// 不填充 result.added/removed(文件级对比不适用于此格式)
|
|
136
155
|
} else {
|
|
137
|
-
//
|
|
156
|
+
// 传统的文件表格格式:覆盖/幽灵判定统一走 capabilities-reconcile(ADR-0009),
|
|
157
|
+
// 与 capability_sync / docs_freshness 检查器共享同一份规则,check 与 fix 口径必然一致
|
|
138
158
|
const getBasename = (f: string) => {
|
|
139
159
|
const clean = f.endsWith('/') ? f.slice(0, -1) : f;
|
|
140
160
|
return clean.split('/').pop()!;
|
|
141
161
|
};
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
162
|
+
const verdict = reconcileCapabilities({
|
|
163
|
+
content: capsContent,
|
|
164
|
+
populationFiles: currentModules.map((m) => m.file),
|
|
165
|
+
fileExists: (rel) => existsSync(path.join(projectPath, rel)),
|
|
166
|
+
sourceRoots: detectSourceRoots(projectPath),
|
|
167
|
+
});
|
|
147
168
|
if (capsMode === 'module') {
|
|
148
|
-
// module
|
|
149
|
-
|
|
150
|
-
const entries = readCapabilitiesEntries(capabilitiesPath, { includeDirs: true });
|
|
151
|
-
const fileEntries = entries.filter(e => !e.endsWith('/'));
|
|
152
|
-
const dirEntries = entries.filter(e => e.endsWith('/'));
|
|
153
|
-
const uncoveredDirs = new Set<string>();
|
|
154
|
-
for (const m of currentModules) {
|
|
155
|
-
const covered =
|
|
156
|
-
fileEntries.includes(m.file) || dirEntries.some(d => m.file.startsWith(d));
|
|
157
|
-
if (!covered) {
|
|
158
|
-
const root = srcDirs.find(d => m.file.startsWith(d + '/')) || srcDirs[0] || '';
|
|
159
|
-
uncoveredDirs.add(aggregateToSourceSubdir(root, m.file));
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
result.added = [...uncoveredDirs];
|
|
169
|
+
// module 模式:added 为聚合后的「未覆盖目录」,需人工登记目录条目
|
|
170
|
+
result.added = verdict.uncoveredDirs;
|
|
163
171
|
} else {
|
|
164
|
-
result.added =
|
|
165
|
-
.filter(
|
|
166
|
-
m =>
|
|
167
|
-
!existingDirs.some(d => m.file.startsWith(d)) &&
|
|
168
|
-
!existingFileNames.includes(getBasename(m.file))
|
|
169
|
-
)
|
|
170
|
-
.map(m => getBasename(m.file));
|
|
171
|
-
}
|
|
172
|
-
// removed:basename 对比 + 全路径存在性兜底(#33)。
|
|
173
|
-
// 表格格式承诺 ts|tsx|js|jsx,但扫描只覆盖 .ts/.tsx——
|
|
174
|
-
// 指向真实存在文件的登记行(.js/.jsx 等扫描盲区)不得误判为「已删除」。
|
|
175
|
-
// 兜底按 basename 豁免;路径不存在的幽灵行进不了豁免,由下方清扫按完整路径补入 removed。
|
|
176
|
-
const sourceRoots = detectSourceRoots(projectPath);
|
|
177
|
-
const entryExists = (entry: string): boolean =>
|
|
178
|
-
existsSync(path.join(projectPath, entry)) ||
|
|
179
|
-
sourceRoots.some(root => existsSync(path.join(projectPath, root, entry)));
|
|
180
|
-
|
|
181
|
-
const registeredEntries = readCapabilitiesEntries(capabilitiesPath);
|
|
182
|
-
const livePathBasenames = new Set(
|
|
183
|
-
registeredEntries
|
|
184
|
-
.filter(e => !e.endsWith('/') && e.includes('/') && entryExists(e))
|
|
185
|
-
.map(getBasename)
|
|
186
|
-
);
|
|
187
|
-
result.removed = existingFileNames.filter(
|
|
188
|
-
f => !currentBasenames.includes(f) && !livePathBasenames.has(f)
|
|
189
|
-
);
|
|
190
|
-
|
|
191
|
-
// 幽灵条目清扫(2026-08-08 studio CI 4 连红事故):上方按 basename 对比,
|
|
192
|
-
// 同名碰撞时幽灵不可见(如 agent-configs/routes.ts 已删但 agents/routes.ts 仍存在,
|
|
193
|
-
// basename routes.ts 仍在扫描结果中,永远不会被判 removed)。
|
|
194
|
-
// 这里按完整路径直接判存在性(与 docs_freshness 检查器同语义:项目根 + 源码根前缀)。
|
|
195
|
-
for (const entry of registeredEntries) {
|
|
196
|
-
// 纯文件名条目(无路径)无法用存在性判定,交由上方 basename 对比
|
|
197
|
-
if (!entry.includes('/') || entryExists(entry)) continue;
|
|
198
|
-
const basename = entry.split('/').pop()!;
|
|
199
|
-
// basename 对比已覆盖(无碰撞场景)时不重复加入
|
|
200
|
-
if (!result.removed.includes(basename) && !result.removed.includes(entry)) {
|
|
201
|
-
result.removed.push(entry);
|
|
202
|
-
}
|
|
172
|
+
result.added = verdict.uncoveredFiles.map((f) => getBasename(f));
|
|
203
173
|
}
|
|
174
|
+
// removed:文件与目录条目一起查(幽灵目录行若不清除,docs_freshness 从严后
|
|
175
|
+
// check 会持续报失败而 fix 修不掉——check/fix 必须同规则才能收敛)
|
|
176
|
+
result.removed = verdict.deadEntries;
|
|
204
177
|
}
|
|
205
178
|
|
|
206
179
|
// 4. 检查 CONTEXT.md(缺失 + 过时)
|
|
@@ -342,55 +315,55 @@ export async function syncDocs(options: SyncDocsOptions): Promise<boolean> {
|
|
|
342
315
|
}
|
|
343
316
|
}
|
|
344
317
|
|
|
345
|
-
|
|
346
|
-
return
|
|
318
|
+
log(io, JSON.stringify(jsonOutput, null, 2));
|
|
319
|
+
return hasIssues ? drift('文档不是最新的(详见 --json 输出 issues 字段)') : { kind: 'ok' };
|
|
347
320
|
}
|
|
348
321
|
|
|
349
322
|
// 6. 人读输出模式
|
|
350
323
|
if (capsIsCapabilityListing && hasCapIssues) {
|
|
351
|
-
|
|
352
|
-
capCountMismatches.forEach(m =>
|
|
324
|
+
log(io, chalk.yellow(`\n📊 CAPABILITIES.md 计数不一致:`));
|
|
325
|
+
capCountMismatches.forEach(m => log(io, chalk.gray(` - ${m}`)));
|
|
353
326
|
}
|
|
354
327
|
|
|
355
328
|
if (result.added.length > 0) {
|
|
356
329
|
if (capsMode === 'module') {
|
|
357
|
-
|
|
358
|
-
result.added.forEach(d =>
|
|
359
|
-
|
|
330
|
+
log(io, chalk.yellow(`\n📄 CAPABILITIES.md 未登记以下模块(目录):`));
|
|
331
|
+
result.added.forEach(d => log(io, chalk.gray(` + ${d}`)));
|
|
332
|
+
log(io,
|
|
360
333
|
chalk.gray(' 请在 CAPABILITIES.md 中为这些目录登记一行目录条目(如 `| 模块名 | src/xxx/ | 说明 |`)')
|
|
361
334
|
);
|
|
362
335
|
} else {
|
|
363
|
-
|
|
364
|
-
result.added.forEach(f =>
|
|
336
|
+
log(io, chalk.yellow(`\n📄 CAPABILITIES.md 缺少以下模块:`));
|
|
337
|
+
result.added.forEach(f => log(io, chalk.gray(` + ${f}`)));
|
|
365
338
|
}
|
|
366
339
|
}
|
|
367
340
|
|
|
368
341
|
if (result.removed.length > 0) {
|
|
369
|
-
|
|
370
|
-
result.removed.forEach(f =>
|
|
342
|
+
log(io, chalk.yellow(`\n📄 CAPABILITIES.md 包含已删除的模块:`));
|
|
343
|
+
result.removed.forEach(f => log(io, chalk.gray(` - ${f}`)));
|
|
371
344
|
}
|
|
372
345
|
|
|
373
346
|
if (result.contextMissing.length > 0) {
|
|
374
|
-
|
|
375
|
-
result.contextMissing.forEach(d =>
|
|
347
|
+
log(io, chalk.yellow(`\n📋 缺少 CONTEXT.md:`));
|
|
348
|
+
result.contextMissing.forEach(d => log(io, chalk.gray(` - ${d}/CONTEXT.md`)));
|
|
376
349
|
}
|
|
377
350
|
|
|
378
351
|
if (result.contextStale.length > 0) {
|
|
379
|
-
|
|
380
|
-
result.contextStale.forEach(d =>
|
|
352
|
+
log(io, chalk.yellow(`\n📋 CONTEXT.md 可能过时(源码比文档新):`));
|
|
353
|
+
result.contextStale.forEach(d => log(io, chalk.gray(` - ${d}/CONTEXT.md`)));
|
|
381
354
|
}
|
|
382
355
|
|
|
383
356
|
if (hasAgentsIssues) {
|
|
384
|
-
|
|
357
|
+
log(io,
|
|
385
358
|
chalk.yellow(agentsMdExists
|
|
386
359
|
? `\n🤖 AGENTS.md 与当前项目状态不一致:`
|
|
387
360
|
: `\n🤖 缺少 AGENTS.md(agent 导读):`)
|
|
388
361
|
);
|
|
389
|
-
|
|
362
|
+
log(io, chalk.gray(` - AGENTS.md`));
|
|
390
363
|
}
|
|
391
364
|
|
|
392
365
|
if (agentsMdMalformedPreserve.length > 0) {
|
|
393
|
-
|
|
366
|
+
log(io,
|
|
394
367
|
chalk.yellow(
|
|
395
368
|
`\n⚠️ AGENTS.md 中 PRESERVE 标记块未闭合(不予保留,重新生成将丢弃): ${agentsMdMalformedPreserve.join(', ')}`
|
|
396
369
|
)
|
|
@@ -398,37 +371,37 @@ export async function syncDocs(options: SyncDocsOptions): Promise<boolean> {
|
|
|
398
371
|
}
|
|
399
372
|
|
|
400
373
|
if (!hasIssues) {
|
|
401
|
-
|
|
402
|
-
return
|
|
374
|
+
log(io, chalk.green('✅ 所有文档都是最新的'));
|
|
375
|
+
return { kind: 'ok' };
|
|
403
376
|
}
|
|
404
377
|
|
|
405
378
|
// 7. 检查模式:只报告,不修改
|
|
406
379
|
if (isCheck) {
|
|
407
|
-
|
|
408
|
-
return
|
|
380
|
+
log(io, chalk.red('\n❌ 文档不是最新的,请运行 harness sync-docs 更新'));
|
|
381
|
+
return drift('文档不是最新的,请运行 harness sync-docs 更新');
|
|
409
382
|
}
|
|
410
383
|
|
|
411
384
|
// 8. 写入模式:更新文档
|
|
412
385
|
if (capsIsCapabilityListing && hasCapIssues) {
|
|
413
|
-
capsContent = updateCapabilityCounts(capsContent,
|
|
386
|
+
capsContent = updateCapabilityCounts(capsContent, CAPABILITY_DEFINITIONS);
|
|
414
387
|
await fs.writeFile(capabilitiesPath, capsContent, 'utf-8');
|
|
415
|
-
|
|
388
|
+
log(io, chalk.green(`\n✅ 已更新 CAPABILITIES.md 计数`));
|
|
416
389
|
}
|
|
417
390
|
|
|
418
391
|
if (!capsIsCapabilityListing && hasTableIssues) {
|
|
419
392
|
await updateCapabilitiesFile(capabilitiesPath, currentModules, existingFiles, result, capsMode);
|
|
420
|
-
|
|
393
|
+
log(io, chalk.green(`\n✅ 已更新 CAPABILITIES.md`));
|
|
421
394
|
}
|
|
422
395
|
|
|
423
396
|
for (const dir of result.contextMissing) {
|
|
424
397
|
await createContextMd(projectPath, dir);
|
|
425
|
-
|
|
398
|
+
log(io, chalk.green(`✅ 已创建 ${dir}/CONTEXT.md`));
|
|
426
399
|
}
|
|
427
400
|
|
|
428
401
|
if (hasAgentsIssues && agentsMdExpected !== null) {
|
|
429
402
|
await fs.writeFile(path.join(projectPath, 'AGENTS.md'), agentsMdExpected, 'utf-8');
|
|
430
|
-
|
|
403
|
+
log(io, chalk.green(agentsMdExists ? `✅ 已更新 AGENTS.md` : `✅ 已生成 AGENTS.md`));
|
|
431
404
|
}
|
|
432
405
|
|
|
433
|
-
return
|
|
406
|
+
return hasIssues ? drift('写入模式已修复漂移(历史面:退出码仍为 0)') : { kind: 'ok' };
|
|
434
407
|
}
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
import * as fs from 'fs/promises';
|
|
6
6
|
import { existsSync } from 'fs';
|
|
7
7
|
import * as path from 'path';
|
|
8
|
-
import { loadRawProjectConfig } from '../../../core/project-config-loader';
|
|
8
|
+
import { loadRawProjectConfig, resolveContextFiles } from '../../../core/project-config-loader';
|
|
9
9
|
import { detectSourceRoots } from '../../../utils/detect-source-roots';
|
|
10
|
-
import { findTsSourceFiles, isTsSourceFile } from '../../../utils/file-walk';
|
|
10
|
+
import { DEFAULT_SKIP_DIRS, findTsSourceFiles, isTsSourceFile } from '../../../utils/file-walk';
|
|
11
11
|
|
|
12
12
|
export interface ModuleInfo {
|
|
13
13
|
name: string;
|
|
@@ -65,28 +65,27 @@ export function formatScriptCommand(pm: 'pnpm' | 'yarn' | 'npm', name: string):
|
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
67
|
* 获取需要 CONTEXT.md 的目录列表
|
|
68
|
+
*
|
|
69
|
+
* context_files 三态语义(工单 84):enabled 且非空 → 配置目录;
|
|
70
|
+
* enabled 但无目标 → 工具流兜底回落自动探测(回落保留在调用方,不进访问器);
|
|
71
|
+
* 未配置 → 空列表。
|
|
68
72
|
*/
|
|
69
73
|
export async function getRequiredContextDirs(projectPath: string): Promise<string[]> {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
// Fallback: auto-discover from source roots
|
|
79
|
-
return detectSourceRoots(projectPath);
|
|
80
|
-
}
|
|
81
|
-
} catch {
|
|
82
|
-
// 配置不存在或无法解析
|
|
74
|
+
const resolution = resolveContextFiles(projectPath);
|
|
75
|
+
if (resolution.state === 'enabled') {
|
|
76
|
+
return resolution.dirs;
|
|
77
|
+
}
|
|
78
|
+
if (resolution.state === 'enabled-empty') {
|
|
79
|
+
// Fallback: auto-discover from source roots
|
|
80
|
+
return detectSourceRoots(projectPath);
|
|
83
81
|
}
|
|
84
82
|
return [];
|
|
85
83
|
}
|
|
86
84
|
|
|
87
85
|
/**
|
|
88
86
|
* 获取源码扫描目录列表
|
|
89
|
-
* 优先从 governance.context_files.required_dirs
|
|
87
|
+
* 优先从 governance.context_files.required_dirs 读取;未配置或配置为空时
|
|
88
|
+
* 回落自动探测(detectSourceRoots),并非固定 ['src']
|
|
90
89
|
*/
|
|
91
90
|
export async function getSourceDirs(projectPath: string): Promise<string[]> {
|
|
92
91
|
const requiredDirs = await getRequiredContextDirs(projectPath);
|
|
@@ -108,8 +107,8 @@ export async function scanSourceModules(srcDir: string, projectPath: string): Pr
|
|
|
108
107
|
}
|
|
109
108
|
|
|
110
109
|
for (const entry of entries) {
|
|
111
|
-
//
|
|
112
|
-
if (entry
|
|
110
|
+
// 跳过依赖/旁测/构建产物目录(名单正本见 utils/file-walk)
|
|
111
|
+
if (DEFAULT_SKIP_DIRS.includes(entry)) continue;
|
|
113
112
|
|
|
114
113
|
const entryPath = path.join(srcDir, entry);
|
|
115
114
|
const stat = await fs.stat(entryPath);
|