@dommaker/harness 1.2.3 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/README.md +0 -2
- package/bin/harness.js +86 -32
- package/dist/cli/command-contract.d.ts +83 -0
- package/dist/cli/command-contract.d.ts.map +1 -0
- package/dist/cli/command-contract.js +66 -0
- package/dist/cli/command-contract.js.map +1 -0
- package/dist/cli/commands/acceptance.d.ts +3 -2
- package/dist/cli/commands/acceptance.d.ts.map +1 -1
- package/dist/cli/commands/acceptance.js +28 -24
- package/dist/cli/commands/acceptance.js.map +1 -1
- package/dist/cli/commands/analyze-sessions.d.ts +2 -1
- package/dist/cli/commands/analyze-sessions.d.ts.map +1 -1
- package/dist/cli/commands/analyze-sessions.js +25 -24
- package/dist/cli/commands/analyze-sessions.js.map +1 -1
- package/dist/cli/commands/check.d.ts +14 -2
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/check.js +76 -61
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/command.d.ts +5 -1
- package/dist/cli/commands/command.d.ts.map +1 -1
- package/dist/cli/commands/command.js +26 -17
- package/dist/cli/commands/command.js.map +1 -1
- package/dist/cli/commands/constraints-report.d.ts +2 -1
- package/dist/cli/commands/constraints-report.d.ts.map +1 -1
- package/dist/cli/commands/constraints-report.js +37 -33
- package/dist/cli/commands/constraints-report.js.map +1 -1
- package/dist/cli/commands/constraints-retire.d.ts +6 -5
- package/dist/cli/commands/constraints-retire.d.ts.map +1 -1
- package/dist/cli/commands/constraints-retire.js +50 -52
- package/dist/cli/commands/constraints-retire.js.map +1 -1
- package/dist/cli/commands/constraints.d.ts +2 -1
- package/dist/cli/commands/constraints.d.ts.map +1 -1
- package/dist/cli/commands/constraints.js +10 -27
- package/dist/cli/commands/constraints.js.map +1 -1
- package/dist/cli/commands/contract.d.ts +3 -2
- package/dist/cli/commands/contract.d.ts.map +1 -1
- package/dist/cli/commands/contract.js +45 -42
- package/dist/cli/commands/contract.js.map +1 -1
- package/dist/cli/commands/definitions.d.ts +11 -11
- package/dist/cli/commands/definitions.d.ts.map +1 -1
- package/dist/cli/commands/definitions.js +30 -215
- package/dist/cli/commands/definitions.js.map +1 -1
- package/dist/cli/commands/failure.d.ts +5 -4
- package/dist/cli/commands/failure.d.ts.map +1 -1
- package/dist/cli/commands/failure.js +33 -26
- package/dist/cli/commands/failure.js.map +1 -1
- package/dist/cli/commands/init.d.ts +7 -5
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +147 -211
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/knowledge.d.ts +21 -15
- package/dist/cli/commands/knowledge.d.ts.map +1 -1
- package/dist/cli/commands/knowledge.js +237 -199
- package/dist/cli/commands/knowledge.js.map +1 -1
- package/dist/cli/commands/passes-gate.d.ts +8 -2
- package/dist/cli/commands/passes-gate.d.ts.map +1 -1
- package/dist/cli/commands/passes-gate.js +44 -66
- package/dist/cli/commands/passes-gate.js.map +1 -1
- package/dist/cli/commands/performance.d.ts +2 -1
- package/dist/cli/commands/performance.d.ts.map +1 -1
- package/dist/cli/commands/performance.js +20 -18
- package/dist/cli/commands/performance.js.map +1 -1
- package/dist/cli/commands/posteval-plan.d.ts +5 -1
- package/dist/cli/commands/posteval-plan.d.ts.map +1 -1
- package/dist/cli/commands/posteval-plan.js +26 -15
- package/dist/cli/commands/posteval-plan.js.map +1 -1
- package/dist/cli/commands/release.d.ts +6 -1
- package/dist/cli/commands/release.d.ts.map +1 -1
- package/dist/cli/commands/release.js +73 -77
- package/dist/cli/commands/release.js.map +1 -1
- package/dist/cli/commands/report.d.ts +2 -1
- package/dist/cli/commands/report.d.ts.map +1 -1
- package/dist/cli/commands/report.js +9 -5
- package/dist/cli/commands/report.js.map +1 -1
- package/dist/cli/commands/review.d.ts +3 -2
- package/dist/cli/commands/review.d.ts.map +1 -1
- package/dist/cli/commands/review.js +33 -29
- package/dist/cli/commands/review.js.map +1 -1
- package/dist/cli/commands/sdd.d.ts +2 -1
- package/dist/cli/commands/sdd.d.ts.map +1 -1
- package/dist/cli/commands/sdd.js +7 -5
- package/dist/cli/commands/sdd.js.map +1 -1
- package/dist/cli/commands/security.d.ts +3 -2
- package/dist/cli/commands/security.d.ts.map +1 -1
- package/dist/cli/commands/security.js +29 -26
- package/dist/cli/commands/security.js.map +1 -1
- package/dist/cli/commands/spec-baseline-check.d.ts +2 -1
- package/dist/cli/commands/spec-baseline-check.d.ts.map +1 -1
- package/dist/cli/commands/spec-baseline-check.js +15 -11
- package/dist/cli/commands/spec-baseline-check.js.map +1 -1
- package/dist/cli/commands/spec.d.ts +7 -2
- package/dist/cli/commands/spec.d.ts.map +1 -1
- package/dist/cli/commands/spec.js +61 -51
- package/dist/cli/commands/spec.js.map +1 -1
- package/dist/cli/commands/status.d.ts +2 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +57 -53
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/sync-docs/agents-syncer.d.ts.map +1 -1
- package/dist/cli/commands/sync-docs/agents-syncer.js +31 -16
- package/dist/cli/commands/sync-docs/agents-syncer.js.map +1 -1
- package/dist/cli/commands/sync-docs/context-syncer.d.ts.map +1 -1
- package/dist/cli/commands/sync-docs/context-syncer.js +3 -2
- package/dist/cli/commands/sync-docs/context-syncer.js.map +1 -1
- package/dist/cli/commands/sync-docs/index.d.ts +2 -1
- package/dist/cli/commands/sync-docs/index.d.ts.map +1 -1
- package/dist/cli/commands/sync-docs/index.js +68 -88
- package/dist/cli/commands/sync-docs/index.js.map +1 -1
- package/dist/cli/commands/sync-docs/project-reader.d.ts +6 -1
- package/dist/cli/commands/sync-docs/project-reader.d.ts.map +1 -1
- package/dist/cli/commands/sync-docs/project-reader.js +14 -16
- package/dist/cli/commands/sync-docs/project-reader.js.map +1 -1
- package/dist/cli/commands/update-user-model.d.ts +2 -1
- package/dist/cli/commands/update-user-model.d.ts.map +1 -1
- package/dist/cli/commands/update-user-model.js +31 -45
- package/dist/cli/commands/update-user-model.js.map +1 -1
- package/dist/cli/commands/validate.d.ts +4 -3
- package/dist/cli/commands/validate.d.ts.map +1 -1
- package/dist/cli/commands/validate.js +28 -26
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/session-mining/transcript.d.ts +7 -1
- package/dist/cli/session-mining/transcript.d.ts.map +1 -1
- package/dist/cli/session-mining/transcript.js +21 -14
- package/dist/cli/session-mining/transcript.js.map +1 -1
- package/dist/completion-checkers/index.d.ts +3 -3
- package/dist/completion-checkers/index.js +3 -3
- package/dist/completion-checkers/phase-format.d.ts +1 -1
- package/dist/completion-checkers/phase-format.js +2 -2
- package/dist/completion-checkers/phase-format.js.map +1 -1
- package/dist/completion-checkers/tdd-chain.d.ts +1 -1
- package/dist/completion-checkers/tdd-chain.js +2 -2
- package/dist/completion-checkers/tdd-chain.js.map +1 -1
- package/dist/completion-checkers/types.d.ts +5 -5
- package/dist/completion-checkers/types.d.ts.map +1 -1
- package/dist/completion-checkers/types.js +2 -2
- package/dist/context/session-manager.d.ts.map +1 -1
- package/dist/context/session-manager.js +19 -32
- package/dist/context/session-manager.js.map +1 -1
- package/dist/core/constraints/agent-prompt-renderer.d.ts.map +1 -1
- package/dist/core/constraints/agent-prompt-renderer.js +1 -4
- package/dist/core/constraints/agent-prompt-renderer.js.map +1 -1
- package/dist/core/constraints/capabilities-parser.d.ts +24 -7
- package/dist/core/constraints/capabilities-parser.d.ts.map +1 -1
- package/dist/core/constraints/capabilities-parser.js +32 -28
- package/dist/core/constraints/capabilities-parser.js.map +1 -1
- package/dist/core/constraints/capabilities-reconcile.d.ts +67 -0
- package/dist/core/constraints/capabilities-reconcile.d.ts.map +1 -0
- package/dist/core/constraints/capabilities-reconcile.js +105 -0
- package/dist/core/constraints/capabilities-reconcile.js.map +1 -0
- package/dist/core/constraints/checker.d.ts +21 -43
- package/dist/core/constraints/checker.d.ts.map +1 -1
- package/dist/core/constraints/checker.js +64 -115
- package/dist/core/constraints/checker.js.map +1 -1
- package/dist/core/constraints/checkers/capability-sync.d.ts +4 -3
- package/dist/core/constraints/checkers/capability-sync.d.ts.map +1 -1
- package/dist/core/constraints/checkers/capability-sync.js +29 -69
- package/dist/core/constraints/checkers/capability-sync.js.map +1 -1
- package/dist/core/constraints/checkers/context-doc-sync.d.ts +4 -2
- package/dist/core/constraints/checkers/context-doc-sync.d.ts.map +1 -1
- package/dist/core/constraints/checkers/context-doc-sync.js +13 -22
- package/dist/core/constraints/checkers/context-doc-sync.js.map +1 -1
- package/dist/core/constraints/checkers/docs-freshness.d.ts.map +1 -1
- package/dist/core/constraints/checkers/docs-freshness.js +37 -63
- package/dist/core/constraints/checkers/docs-freshness.js.map +1 -1
- package/dist/core/constraints/checkers/governance-presence.d.ts +2 -2
- package/dist/core/constraints/checkers/governance-presence.d.ts.map +1 -1
- package/dist/core/constraints/checkers/governance-presence.js +7 -28
- package/dist/core/constraints/checkers/governance-presence.js.map +1 -1
- package/dist/core/constraints/checkers/no-test-simplification.d.ts.map +1 -1
- package/dist/core/constraints/checkers/no-test-simplification.js +4 -3
- package/dist/core/constraints/checkers/no-test-simplification.js.map +1 -1
- package/dist/core/constraints/checkers/types.d.ts +2 -2
- package/dist/core/constraints/context-builder.d.ts +15 -14
- package/dist/core/constraints/context-builder.d.ts.map +1 -1
- package/dist/core/constraints/context-builder.js +32 -96
- package/dist/core/constraints/context-builder.js.map +1 -1
- package/dist/core/constraints/doc-freshness/runner.d.ts.map +1 -1
- package/dist/core/constraints/doc-freshness/runner.js +2 -1
- package/dist/core/constraints/doc-freshness/runner.js.map +1 -1
- package/dist/core/constraints/git-evidence.d.ts +60 -0
- package/dist/core/constraints/git-evidence.d.ts.map +1 -0
- package/dist/core/constraints/git-evidence.js +88 -0
- package/dist/core/constraints/git-evidence.js.map +1 -0
- package/dist/core/constraints/injection-drift.d.ts +3 -20
- package/dist/core/constraints/injection-drift.d.ts.map +1 -1
- package/dist/core/constraints/injection-drift.js +10 -57
- package/dist/core/constraints/injection-drift.js.map +1 -1
- package/dist/core/constraints/injection-writer.d.ts +113 -0
- package/dist/core/constraints/injection-writer.d.ts.map +1 -0
- package/dist/core/constraints/injection-writer.js +228 -0
- package/dist/core/constraints/injection-writer.js.map +1 -0
- package/dist/core/constraints/usage-report.d.ts +22 -1
- package/dist/core/constraints/usage-report.d.ts.map +1 -1
- package/dist/core/constraints/usage-report.js +27 -20
- package/dist/core/constraints/usage-report.js.map +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +4 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/project-config-loader.d.ts +32 -1
- package/dist/core/project-config-loader.d.ts.map +1 -1
- package/dist/core/project-config-loader.js +39 -9
- package/dist/core/project-config-loader.js.map +1 -1
- package/dist/core/validators/passes-gate.d.ts +15 -64
- package/dist/core/validators/passes-gate.d.ts.map +1 -1
- package/dist/core/validators/passes-gate.js +84 -222
- package/dist/core/validators/passes-gate.js.map +1 -1
- package/dist/core/validators/test-output.d.ts +58 -0
- package/dist/core/validators/test-output.d.ts.map +1 -0
- package/dist/core/validators/test-output.js +109 -0
- package/dist/core/validators/test-output.js.map +1 -0
- package/dist/failure/recorder.d.ts +7 -1
- package/dist/failure/recorder.d.ts.map +1 -1
- package/dist/failure/recorder.js +13 -9
- package/dist/failure/recorder.js.map +1 -1
- package/dist/gates/acceptance.d.ts +1 -48
- package/dist/gates/acceptance.d.ts.map +1 -1
- package/dist/gates/acceptance.js +6 -38
- package/dist/gates/acceptance.js.map +1 -1
- package/dist/gates/checker-gate.d.ts.map +1 -1
- package/dist/gates/checker-gate.js +6 -11
- package/dist/gates/checker-gate.js.map +1 -1
- package/dist/gates/command.d.ts.map +1 -1
- package/dist/gates/command.js +10 -22
- package/dist/gates/command.js.map +1 -1
- package/dist/gates/contract.d.ts.map +1 -1
- package/dist/gates/contract.js +22 -61
- package/dist/gates/contract.js.map +1 -1
- package/dist/gates/performance.d.ts.map +1 -1
- package/dist/gates/performance.js +13 -31
- package/dist/gates/performance.js.map +1 -1
- package/dist/gates/review.d.ts.map +1 -1
- package/dist/gates/review.js +21 -53
- package/dist/gates/review.js.map +1 -1
- package/dist/gates/security.d.ts.map +1 -1
- package/dist/gates/security.js +14 -32
- package/dist/gates/security.js.map +1 -1
- package/dist/gates/types.d.ts +28 -5
- package/dist/gates/types.d.ts.map +1 -1
- package/dist/gates/types.js +38 -1
- package/dist/gates/types.js.map +1 -1
- package/dist/hooks/bootstrap.d.ts +2 -0
- package/dist/hooks/bootstrap.d.ts.map +1 -1
- package/dist/hooks/bootstrap.js +5 -2
- package/dist/hooks/bootstrap.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -4
- package/dist/index.js.map +1 -1
- package/dist/knowledge/audit.d.ts +7 -2
- package/dist/knowledge/audit.d.ts.map +1 -1
- package/dist/knowledge/audit.js +59 -79
- package/dist/knowledge/audit.js.map +1 -1
- package/dist/knowledge/flywheel-metrics.d.ts +39 -0
- package/dist/knowledge/flywheel-metrics.d.ts.map +1 -0
- package/dist/knowledge/flywheel-metrics.js +47 -0
- package/dist/knowledge/flywheel-metrics.js.map +1 -0
- package/dist/knowledge/import.d.ts.map +1 -1
- package/dist/knowledge/import.js +4 -14
- package/dist/knowledge/import.js.map +1 -1
- package/dist/knowledge/index-generator.d.ts.map +1 -1
- package/dist/knowledge/index-generator.js +18 -15
- package/dist/knowledge/index-generator.js.map +1 -1
- package/dist/knowledge/ingest.d.ts.map +1 -1
- package/dist/knowledge/ingest.js +9 -4
- package/dist/knowledge/ingest.js.map +1 -1
- package/dist/knowledge/migration.d.ts.map +1 -1
- package/dist/knowledge/migration.js +11 -8
- package/dist/knowledge/migration.js.map +1 -1
- package/dist/knowledge/reference-tracker.d.ts.map +1 -1
- package/dist/knowledge/reference-tracker.js +12 -9
- package/dist/knowledge/reference-tracker.js.map +1 -1
- package/dist/knowledge/store.d.ts +15 -0
- package/dist/knowledge/store.d.ts.map +1 -1
- package/dist/knowledge/store.js +59 -10
- package/dist/knowledge/store.js.map +1 -1
- package/dist/monitoring/context-tracker.d.ts.map +1 -1
- package/dist/monitoring/context-tracker.js +11 -20
- package/dist/monitoring/context-tracker.js.map +1 -1
- package/dist/monitoring/index.d.ts +1 -1
- package/dist/monitoring/index.d.ts.map +1 -1
- package/dist/monitoring/index.js +1 -2
- package/dist/monitoring/index.js.map +1 -1
- package/dist/monitoring/trace-analyzer.d.ts +15 -0
- package/dist/monitoring/trace-analyzer.d.ts.map +1 -1
- package/dist/monitoring/trace-analyzer.js +19 -2
- package/dist/monitoring/trace-analyzer.js.map +1 -1
- package/dist/monitoring/traces.d.ts +21 -2
- package/dist/monitoring/traces.d.ts.map +1 -1
- package/dist/monitoring/traces.js +38 -29
- package/dist/monitoring/traces.js.map +1 -1
- package/dist/release/index.d.ts +3 -0
- package/dist/release/index.d.ts.map +1 -0
- package/dist/release/index.js +7 -0
- package/dist/release/index.js.map +1 -0
- package/dist/release/integrity.d.ts +65 -0
- package/dist/release/integrity.d.ts.map +1 -0
- package/dist/release/integrity.js +151 -0
- package/dist/release/integrity.js.map +1 -0
- package/dist/sdd/index-generator.js +10 -11
- package/dist/sdd/index-generator.js.map +1 -1
- package/dist/test-setup/project-fixture.d.ts +48 -0
- package/dist/test-setup/project-fixture.d.ts.map +1 -0
- package/dist/test-setup/project-fixture.js +106 -0
- package/dist/test-setup/project-fixture.js.map +1 -0
- package/dist/types/constraint.d.ts +0 -18
- package/dist/types/constraint.d.ts.map +1 -1
- package/dist/types/constraint.js.map +1 -1
- package/dist/types/failure.d.ts +7 -0
- package/dist/types/failure.d.ts.map +1 -1
- package/dist/types/failure.js +8 -1
- package/dist/types/failure.js.map +1 -1
- package/dist/types/passes-gate.d.ts +10 -25
- package/dist/types/passes-gate.d.ts.map +1 -1
- package/dist/types/project-config.d.ts +1 -1
- package/dist/types/session.d.ts +6 -5
- package/dist/types/session.d.ts.map +1 -1
- package/dist/utils/exec.d.ts +10 -0
- package/dist/utils/exec.d.ts.map +1 -1
- package/dist/utils/exec.js +12 -0
- package/dist/utils/exec.js.map +1 -1
- package/dist/utils/file-walk.d.ts +9 -1
- package/dist/utils/file-walk.d.ts.map +1 -1
- package/dist/utils/file-walk.js +10 -1
- package/dist/utils/file-walk.js.map +1 -1
- package/dist/utils/frontmatter.d.ts +73 -0
- package/dist/utils/frontmatter.d.ts.map +1 -0
- package/dist/utils/frontmatter.js +141 -0
- package/dist/utils/frontmatter.js.map +1 -0
- package/dist/utils/jsonl.d.ts +92 -0
- package/dist/utils/jsonl.d.ts.map +1 -0
- package/dist/utils/jsonl.js +166 -0
- package/dist/utils/jsonl.js.map +1 -0
- package/dist/utils/package-version.d.ts +16 -0
- package/dist/utils/package-version.d.ts.map +1 -0
- package/dist/utils/package-version.js +63 -0
- package/dist/utils/package-version.js.map +1 -0
- package/package.json +1 -1
- package/src/CONTEXT.md +7 -2
- package/src/__tests__/acceptance-gate.test.ts +3 -1
- package/src/__tests__/checker-extra.test.ts +7 -1218
- package/src/__tests__/context-files-resolution.test.ts +116 -0
- package/src/__tests__/effective-constraints.test.ts +10 -13
- package/src/__tests__/exec.test.ts +35 -1
- package/src/__tests__/failure-recorder.test.ts +9 -0
- package/src/__tests__/layering.test.ts +152 -0
- package/src/__tests__/passes-gate-extra.test.ts +0 -145
- package/src/__tests__/passes-gate.test.ts +142 -106
- package/src/__tests__/public-exports.test.ts +3 -0
- package/src/__tests__/skip-semantics.test.ts +5 -9
- package/src/cli/__tests__/command-contract.test.ts +170 -0
- package/src/cli/command-contract.ts +108 -0
- package/src/cli/commands/CONTEXT.md +22 -7
- package/src/cli/commands/__tests__/acceptance.test.ts +40 -33
- package/src/cli/commands/__tests__/analyze-sessions.test.ts +35 -29
- package/src/cli/commands/__tests__/bin-exit-mapping.test.ts +101 -0
- package/src/cli/commands/__tests__/check-drift.test.ts +27 -34
- package/src/cli/commands/__tests__/check-skip-output.test.ts +21 -24
- package/src/cli/commands/__tests__/check.test.ts +378 -382
- package/src/cli/commands/__tests__/command.test.ts +85 -70
- package/src/cli/commands/__tests__/constraints-report.test.ts +100 -71
- package/src/cli/commands/__tests__/constraints-retire.test.ts +152 -95
- package/src/cli/commands/__tests__/contract.test.ts +27 -34
- package/src/cli/commands/__tests__/failure.test.ts +31 -34
- package/src/cli/commands/__tests__/init-injection.test.ts +58 -28
- package/src/cli/commands/__tests__/init.test.ts +77 -48
- package/src/cli/commands/__tests__/knowledge-flywheel-consistency.test.ts +108 -0
- package/src/cli/commands/__tests__/knowledge.test.ts +96 -38
- package/src/cli/commands/__tests__/passes-gate.test.ts +43 -45
- package/src/cli/commands/__tests__/performance.test.ts +22 -23
- package/src/cli/commands/__tests__/posteval-plan.test.ts +39 -38
- package/src/cli/commands/__tests__/project-path-anchoring.test.ts +157 -0
- package/src/cli/commands/__tests__/project-path-convention.test.ts +169 -0
- package/src/cli/commands/__tests__/registry.test.ts +69 -35
- package/src/cli/commands/__tests__/release.test.ts +224 -74
- package/src/cli/commands/__tests__/report-extra.test.ts +16 -16
- package/src/cli/commands/__tests__/report.test.ts +25 -25
- package/src/cli/commands/__tests__/review.test.ts +33 -31
- package/src/cli/commands/__tests__/security.test.ts +23 -27
- package/src/cli/commands/__tests__/spec-baseline-check.test.ts +20 -20
- package/src/cli/commands/__tests__/spec.test.ts +41 -29
- package/src/cli/commands/__tests__/status-extra.test.ts +18 -18
- package/src/cli/commands/__tests__/status-skipped-lines.test.ts +72 -0
- package/src/cli/commands/__tests__/status.test.ts +34 -34
- package/src/cli/commands/__tests__/sync-docs-agents.test.ts +108 -86
- package/src/cli/commands/__tests__/sync-docs.test.ts +72 -74
- package/src/cli/commands/__tests__/update-user-model.test.ts +62 -33
- package/src/cli/commands/__tests__/validate.test.ts +27 -29
- package/src/cli/commands/acceptance.ts +35 -24
- package/src/cli/commands/analyze-sessions.ts +25 -24
- package/src/cli/commands/check.ts +88 -65
- package/src/cli/commands/command.ts +30 -17
- package/src/cli/commands/constraints-report.ts +37 -34
- package/src/cli/commands/constraints-retire.ts +58 -55
- package/src/cli/commands/constraints.ts +10 -27
- package/src/cli/commands/contract.ts +51 -42
- package/src/cli/commands/definitions.ts +37 -223
- package/src/cli/commands/failure.ts +35 -27
- package/src/cli/commands/init.ts +166 -220
- package/src/cli/commands/knowledge.ts +250 -203
- package/src/cli/commands/passes-gate.ts +58 -68
- package/src/cli/commands/performance.ts +23 -18
- package/src/cli/commands/posteval-plan.ts +29 -15
- package/src/cli/commands/release.ts +75 -78
- package/src/cli/commands/report.ts +9 -5
- package/src/cli/commands/review.ts +39 -29
- package/src/cli/commands/sdd.ts +7 -5
- package/src/cli/commands/security.ts +35 -26
- package/src/cli/commands/spec-baseline-check.ts +16 -11
- package/src/cli/commands/spec.ts +66 -53
- package/src/cli/commands/status.ts +59 -53
- package/src/cli/commands/sync-docs/agents-syncer.ts +31 -15
- package/src/cli/commands/sync-docs/context-syncer.ts +3 -2
- package/src/cli/commands/sync-docs/index.ts +73 -100
- package/src/cli/commands/sync-docs/project-reader.ts +17 -18
- package/src/cli/commands/update-user-model.ts +33 -45
- package/src/cli/commands/validate.ts +31 -25
- package/src/cli/session-mining/__tests__/transcript.test.ts +118 -0
- package/src/cli/session-mining/transcript.ts +26 -8
- package/src/completion-checkers/CONTEXT.md +1 -1
- package/src/completion-checkers/__tests__/contract-presence.test.ts +1 -1
- package/src/completion-checkers/__tests__/phase-format.test.ts +1 -1
- package/src/completion-checkers/__tests__/tdd-chain.test.ts +2 -2
- package/src/completion-checkers/index.ts +3 -3
- package/src/completion-checkers/phase-format.ts +2 -2
- package/src/completion-checkers/tdd-chain.ts +2 -2
- package/src/completion-checkers/types.ts +5 -5
- package/src/context/session-manager.ts +19 -33
- package/src/core/CONTEXT.md +9 -6
- package/src/core/constraints/__tests__/capabilities-reconcile.test.ts +200 -0
- package/src/core/constraints/__tests__/capability-counts.test.ts +94 -0
- package/src/core/constraints/__tests__/git-evidence.test.ts +208 -0
- package/src/core/constraints/__tests__/injection-drift.test.ts +3 -10
- package/src/core/constraints/__tests__/injection-writer.test.ts +231 -0
- package/src/core/constraints/__tests__/trace-injection.test.ts +71 -0
- package/src/core/constraints/__tests__/usage-report.test.ts +112 -0
- package/src/core/constraints/agent-prompt-renderer.ts +2 -6
- package/src/core/constraints/capabilities-parser.ts +53 -35
- package/src/core/constraints/capabilities-reconcile.ts +166 -0
- package/src/core/constraints/checker.ts +75 -130
- package/src/core/constraints/checkers/__tests__/capability-sync.test.ts +214 -0
- package/src/core/constraints/checkers/__tests__/context-doc-sync.test.ts +77 -0
- package/src/core/constraints/checkers/__tests__/docs-freshness.test.ts +117 -0
- package/src/{__tests__ → core/constraints/checkers/__tests__}/governance-presence.test.ts +83 -9
- package/src/core/constraints/checkers/__tests__/iron-flags.test.ts +50 -0
- package/src/core/constraints/checkers/__tests__/no-bypass-checkpoint.test.ts +76 -0
- package/src/{__tests__ → core/constraints/checkers/__tests__}/no-hardcoded-credentials.test.ts +4 -3
- package/src/core/constraints/checkers/__tests__/no-test-simplification.test.ts +58 -0
- package/src/core/constraints/checkers/__tests__/three-state-consistency.test.ts +145 -0
- package/src/core/constraints/checkers/capability-sync.ts +29 -88
- package/src/core/constraints/checkers/context-doc-sync.ts +15 -25
- package/src/core/constraints/checkers/docs-freshness.ts +40 -69
- package/src/core/constraints/checkers/governance-presence.ts +7 -25
- package/src/core/constraints/checkers/no-test-simplification.ts +4 -3
- package/src/core/constraints/checkers/types.ts +2 -2
- package/src/core/constraints/context-builder.ts +39 -91
- package/src/core/constraints/doc-freshness/runner.ts +2 -1
- package/src/core/constraints/git-evidence.ts +120 -0
- package/src/core/constraints/injection-drift.ts +13 -60
- package/src/core/constraints/injection-writer.ts +212 -0
- package/src/core/constraints/usage-report.ts +36 -17
- package/src/core/index.ts +4 -2
- package/src/core/project-config-loader.ts +49 -9
- package/src/core/validators/__tests__/passes-gate.test.ts +2 -56
- package/src/core/validators/__tests__/test-output.test.ts +372 -0
- package/src/core/validators/passes-gate.ts +86 -248
- package/src/core/validators/test-output.ts +128 -0
- package/src/failure/__tests__/recorder.test.ts +168 -0
- package/src/failure/recorder.ts +13 -11
- package/src/gates/CONTEXT.md +6 -3
- package/src/gates/__tests__/acceptance-types-single-source.test.ts +68 -0
- package/src/gates/__tests__/acceptance.test.ts +4 -86
- package/src/gates/__tests__/effective-gates.test.ts +3 -8
- package/src/gates/__tests__/test-verdict-consistency.test.ts +140 -0
- package/src/gates/acceptance.ts +19 -84
- package/src/gates/checker-gate.ts +8 -7
- package/src/gates/command.ts +10 -16
- package/src/gates/contract.ts +22 -61
- package/src/gates/performance.ts +10 -22
- package/src/gates/review.ts +21 -41
- package/src/gates/security.ts +10 -22
- package/src/gates/types.ts +70 -5
- package/src/hooks/CONTEXT.md +1 -1
- package/src/hooks/bootstrap.ts +5 -2
- package/src/index.ts +11 -6
- package/src/knowledge/CONTEXT.md +8 -3
- package/src/knowledge/__tests__/audit-labels.test.ts +44 -0
- package/src/knowledge/__tests__/flywheel-metrics.test.ts +135 -0
- package/src/knowledge/__tests__/import.test.ts +44 -0
- package/src/knowledge/__tests__/index-generator.test.ts +55 -2
- package/src/knowledge/__tests__/ingest.test.ts +85 -0
- package/src/knowledge/__tests__/migration.test.ts +47 -0
- package/src/knowledge/__tests__/reference-tracker.test.ts +16 -0
- package/src/knowledge/__tests__/store.test.ts +194 -0
- package/src/knowledge/audit.ts +67 -71
- package/src/knowledge/flywheel-metrics.ts +71 -0
- package/src/knowledge/import.ts +4 -18
- package/src/knowledge/index-generator.ts +20 -15
- package/src/knowledge/ingest.ts +9 -4
- package/src/knowledge/migration.ts +11 -8
- package/src/knowledge/reference-tracker.ts +12 -8
- package/src/knowledge/store.ts +64 -11
- package/src/monitoring/CONTEXT.md +8 -3
- package/src/monitoring/__tests__/skipped-lines-report.test.ts +178 -0
- package/src/monitoring/__tests__/traces.test.ts +57 -0
- package/src/monitoring/context-tracker.ts +11 -23
- package/src/monitoring/index.ts +1 -1
- package/src/monitoring/trace-analyzer.ts +21 -2
- package/src/monitoring/traces.ts +39 -36
- package/src/release/CONTEXT.md +24 -0
- package/src/release/__tests__/barrel.test.ts +60 -0
- package/src/release/__tests__/integrity.test.ts +157 -0
- package/src/release/index.ts +2 -0
- package/src/release/integrity.ts +141 -0
- package/src/sdd/__tests__/index-generator.test.ts +71 -0
- package/src/sdd/index-generator.ts +9 -9
- package/src/test-setup/__tests__/project-fixture.test.ts +178 -0
- package/src/test-setup/project-fixture.ts +87 -0
- package/src/tools/CONTEXT.md +6 -0
- package/src/tools/__tests__/registry.test.ts +221 -0
- package/src/types/__tests__/types.test.ts +4 -5
- package/src/types/constraint.ts +0 -25
- package/src/types/failure.ts +8 -0
- package/src/types/passes-gate.ts +10 -30
- package/src/types/project-config.ts +1 -1
- package/src/types/session.ts +5 -5
- package/src/utils/__tests__/frontmatter.test.ts +206 -0
- package/src/utils/__tests__/jsonl-skip-disposition.test.ts +175 -0
- package/src/utils/__tests__/jsonl.test.ts +187 -0
- package/src/utils/__tests__/package-version.test.ts +97 -0
- package/src/utils/exec.ts +15 -0
- package/src/utils/file-walk.ts +11 -2
- package/src/utils/frontmatter.ts +121 -0
- package/src/utils/jsonl.ts +167 -0
- package/src/utils/package-version.ts +27 -0
- package/dist/cli/commands/doc-freshness-check.d.ts +0 -53
- package/dist/cli/commands/doc-freshness-check.d.ts.map +0 -1
- package/dist/cli/commands/doc-freshness-check.js +0 -352
- package/dist/cli/commands/doc-freshness-check.js.map +0 -1
- package/dist/types/index.d.ts +0 -14
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -39
- package/dist/types/index.js.map +0 -1
- package/src/__tests__/long-running.test.ts +0 -17
- package/src/__tests__/passes-gate-extension.test.ts +0 -151
- package/src/cli/commands/__tests__/doc-freshness-check.test.ts +0 -168
- package/src/cli/commands/doc-freshness-check.ts +0 -386
- package/src/spec/CONTEXT.md +0 -11
- package/src/types/index.ts +0 -47
|
@@ -43,6 +43,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
43
43
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
44
|
exports.knowledgeList = knowledgeList;
|
|
45
45
|
exports.knowledgeSearch = knowledgeSearch;
|
|
46
|
+
exports.knowledgeSearchCommand = knowledgeSearchCommand;
|
|
46
47
|
exports.knowledgeImport = knowledgeImport;
|
|
47
48
|
exports.knowledgeDecay = knowledgeDecay;
|
|
48
49
|
exports.knowledgeStats = knowledgeStats;
|
|
@@ -63,13 +64,15 @@ const query_1 = require("../../knowledge/query");
|
|
|
63
64
|
const lifecycle_1 = require("../../knowledge/lifecycle");
|
|
64
65
|
const import_1 = require("../../knowledge/import");
|
|
65
66
|
const audit_1 = require("../../knowledge/audit");
|
|
67
|
+
const flywheel_metrics_1 = require("../../knowledge/flywheel-metrics");
|
|
66
68
|
const migration_1 = require("../../knowledge/migration");
|
|
67
69
|
const index_generator_1 = require("../../knowledge/index-generator");
|
|
70
|
+
const command_contract_1 = require("../command-contract");
|
|
68
71
|
/**
|
|
69
72
|
* 知识库列表
|
|
70
73
|
*/
|
|
71
|
-
async function knowledgeList(options) {
|
|
72
|
-
const store = new store_1.FileKnowledgeStore({ baseDir: getKnowledgeDir(options.projectPath) });
|
|
74
|
+
async function knowledgeList(options, io = command_contract_1.processIO) {
|
|
75
|
+
const store = new store_1.FileKnowledgeStore({ baseDir: getKnowledgeDir(options.projectPath, io) });
|
|
73
76
|
const filter = { excludeArchived: false };
|
|
74
77
|
if (options.type) {
|
|
75
78
|
filter.types = options.type.split(',');
|
|
@@ -82,54 +85,72 @@ async function knowledgeList(options) {
|
|
|
82
85
|
}
|
|
83
86
|
const entries = store.list(filter);
|
|
84
87
|
if (options.json) {
|
|
85
|
-
|
|
86
|
-
return;
|
|
88
|
+
(0, command_contract_1.log)(io, JSON.stringify({ total: entries.length, entries }, null, 2));
|
|
89
|
+
return { kind: 'ok' };
|
|
87
90
|
}
|
|
88
91
|
if (entries.length === 0) {
|
|
89
|
-
|
|
90
|
-
return;
|
|
92
|
+
(0, command_contract_1.log)(io, chalk_1.default.yellow('知识库为空'));
|
|
93
|
+
return { kind: 'ok' };
|
|
91
94
|
}
|
|
92
|
-
|
|
95
|
+
(0, command_contract_1.log)(io, chalk_1.default.blue(`📚 知识库 (${entries.length} 条)\n`));
|
|
93
96
|
for (const entry of entries) {
|
|
94
97
|
const maturityColor = entry.maturity === 'proven' ? chalk_1.default.green
|
|
95
98
|
: entry.maturity === 'verified' ? chalk_1.default.cyan
|
|
96
99
|
: entry.maturity === 'archived' ? chalk_1.default.gray
|
|
97
100
|
: chalk_1.default.yellow;
|
|
98
|
-
|
|
99
|
-
|
|
101
|
+
(0, command_contract_1.log)(io, ` ${maturityColor(`[${entry.maturity}]`)} ${chalk_1.default.bold(entry.title)}`);
|
|
102
|
+
(0, command_contract_1.log)(io, ` ${chalk_1.default.gray(`id: ${entry.id} | type: ${entry.type} | layer: ${entry.layer}`)}`);
|
|
100
103
|
if (entry.tags.length > 0) {
|
|
101
|
-
|
|
104
|
+
(0, command_contract_1.log)(io, ` ${chalk_1.default.gray(`tags: ${entry.tags.join(', ')}`)}`);
|
|
102
105
|
}
|
|
103
106
|
}
|
|
107
|
+
return { kind: 'ok' };
|
|
104
108
|
}
|
|
105
109
|
/**
|
|
106
110
|
* 知识库搜索
|
|
107
111
|
*/
|
|
108
|
-
async function knowledgeSearch(query, options) {
|
|
109
|
-
const store = new store_1.FileKnowledgeStore({ baseDir: getKnowledgeDir(options.projectPath) });
|
|
112
|
+
async function knowledgeSearch(query, options, io = command_contract_1.processIO) {
|
|
113
|
+
const store = new store_1.FileKnowledgeStore({ baseDir: getKnowledgeDir(options.projectPath, io) });
|
|
110
114
|
const queryEngine = new query_1.KnowledgeQuery(store);
|
|
111
115
|
const matched = queryEngine.search(query, { limit: options.limit || 20 });
|
|
112
116
|
if (options.json) {
|
|
113
|
-
|
|
114
|
-
return;
|
|
117
|
+
(0, command_contract_1.log)(io, JSON.stringify({ query, total: matched.length, entries: matched }, null, 2));
|
|
118
|
+
return { kind: 'ok' };
|
|
115
119
|
}
|
|
116
120
|
if (matched.length === 0) {
|
|
117
|
-
|
|
118
|
-
return;
|
|
121
|
+
(0, command_contract_1.log)(io, chalk_1.default.yellow(`未找到匹配 "${query}" 的知识条目`));
|
|
122
|
+
return { kind: 'ok' };
|
|
119
123
|
}
|
|
120
|
-
|
|
124
|
+
(0, command_contract_1.log)(io, chalk_1.default.blue(`🔍 搜索 "${query}" (${matched.length} 条结果)\n`));
|
|
121
125
|
for (const entry of matched) {
|
|
122
|
-
|
|
126
|
+
(0, command_contract_1.log)(io, ` ${chalk_1.default.bold(entry.title)} ${chalk_1.default.gray(`[${entry.maturity}]`)}`);
|
|
123
127
|
const preview = entry.content.slice(0, 100).replace(/\n/g, ' ');
|
|
124
|
-
|
|
128
|
+
(0, command_contract_1.log)(io, ` ${chalk_1.default.gray(preview)}${entry.content.length > 100 ? '...' : ''}`);
|
|
125
129
|
}
|
|
130
|
+
return { kind: 'ok' };
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* knowledge search 子命令入口(候选7):缺参闸门 + limit 强转编组,
|
|
134
|
+
* 自 definitions.ts 的 args 复印块移回命令模块(interface/测试面所在)。
|
|
135
|
+
*/
|
|
136
|
+
async function knowledgeSearchCommand(positionals, options, io = command_contract_1.processIO) {
|
|
137
|
+
const query = positionals[0];
|
|
138
|
+
if (!query) {
|
|
139
|
+
(0, command_contract_1.logError)(io, '请提供搜索关键词');
|
|
140
|
+
return { kind: 'usage-error', reason: 'knowledge search 缺少关键词位置参数' };
|
|
141
|
+
}
|
|
142
|
+
return knowledgeSearch(String(query), {
|
|
143
|
+
projectPath: options.projectPath,
|
|
144
|
+
json: options.json,
|
|
145
|
+
limit: parseInt(String(options.limit), 10),
|
|
146
|
+
});
|
|
126
147
|
}
|
|
127
148
|
/**
|
|
128
149
|
* 知识库导入(冷启动)
|
|
129
150
|
*/
|
|
130
|
-
async function knowledgeImport(options) {
|
|
151
|
+
async function knowledgeImport(options, io = command_contract_1.processIO) {
|
|
131
152
|
const projectPath = options.projectPath || process.cwd();
|
|
132
|
-
const store = new store_1.FileKnowledgeStore({ baseDir: getKnowledgeDir(options.projectPath) });
|
|
153
|
+
const store = new store_1.FileKnowledgeStore({ baseDir: getKnowledgeDir(options.projectPath, io) });
|
|
133
154
|
const sources = options.sources
|
|
134
155
|
? options.sources.split(',')
|
|
135
156
|
: ['code', 'git', 'docs'];
|
|
@@ -141,60 +162,62 @@ async function knowledgeImport(options) {
|
|
|
141
162
|
if (options.reset) {
|
|
142
163
|
importer.resetState();
|
|
143
164
|
if (!options.json) {
|
|
144
|
-
|
|
165
|
+
(0, command_contract_1.log)(io, chalk_1.default.yellow('🔄 已重置导入状态'));
|
|
145
166
|
}
|
|
146
167
|
}
|
|
147
168
|
if (!options.json) {
|
|
148
|
-
|
|
169
|
+
(0, command_contract_1.log)(io, chalk_1.default.blue(`📥 开始导入知识 (源: ${sources.join(', ')})...`));
|
|
149
170
|
}
|
|
150
171
|
const results = await importer.importAll();
|
|
151
172
|
const totalImported = results.reduce((sum, r) => sum + r.entries.length, 0);
|
|
152
173
|
const totalErrors = results.reduce((sum, r) => sum + r.errors.length, 0);
|
|
153
174
|
if (options.json) {
|
|
154
|
-
|
|
155
|
-
return;
|
|
175
|
+
(0, command_contract_1.log)(io, JSON.stringify({ totalImported, totalErrors, results }, null, 2));
|
|
176
|
+
return { kind: 'ok' };
|
|
156
177
|
}
|
|
157
178
|
for (const result of results) {
|
|
158
179
|
if (result.entries.length > 0) {
|
|
159
|
-
|
|
180
|
+
(0, command_contract_1.log)(io, chalk_1.default.green(` ✅ ${result.source.type}: ${result.entries.length} 条`));
|
|
160
181
|
}
|
|
161
182
|
if (result.errors.length > 0) {
|
|
162
183
|
for (const err of result.errors) {
|
|
163
|
-
|
|
184
|
+
(0, command_contract_1.log)(io, chalk_1.default.red(` ❌ ${result.source.type}: ${err.message}`));
|
|
164
185
|
}
|
|
165
186
|
}
|
|
166
187
|
}
|
|
167
|
-
|
|
188
|
+
(0, command_contract_1.log)(io, chalk_1.default.green(`\n✅ 导入完成: ${totalImported} 条,${totalErrors} 个错误`));
|
|
189
|
+
return { kind: 'ok' };
|
|
168
190
|
}
|
|
169
191
|
/**
|
|
170
192
|
* 知识库衰减周期
|
|
171
193
|
*/
|
|
172
|
-
async function knowledgeDecay(options) {
|
|
173
|
-
const store = new store_1.FileKnowledgeStore({ baseDir: getKnowledgeDir(options.projectPath) });
|
|
194
|
+
async function knowledgeDecay(options, io = command_contract_1.processIO) {
|
|
195
|
+
const store = new store_1.FileKnowledgeStore({ baseDir: getKnowledgeDir(options.projectPath, io) });
|
|
174
196
|
const lifecycle = new lifecycle_1.KnowledgeLifecycle(store);
|
|
175
197
|
if (!options.json) {
|
|
176
|
-
|
|
198
|
+
(0, command_contract_1.log)(io, chalk_1.default.blue('🔄 运行衰减周期...'));
|
|
177
199
|
}
|
|
178
200
|
const changes = lifecycle.runDecayCycle();
|
|
179
201
|
if (options.json) {
|
|
180
|
-
|
|
181
|
-
return;
|
|
202
|
+
(0, command_contract_1.log)(io, JSON.stringify({ changes }, null, 2));
|
|
203
|
+
return { kind: 'ok' };
|
|
182
204
|
}
|
|
183
205
|
if (changes.length === 0) {
|
|
184
|
-
|
|
185
|
-
return;
|
|
206
|
+
(0, command_contract_1.log)(io, chalk_1.default.green('✅ 没有需要衰减的知识条目'));
|
|
207
|
+
return { kind: 'ok' };
|
|
186
208
|
}
|
|
187
|
-
|
|
209
|
+
(0, command_contract_1.log)(io, chalk_1.default.yellow(`📉 ${changes.length} 条知识发生衰减:\n`));
|
|
188
210
|
for (const change of changes) {
|
|
189
|
-
|
|
190
|
-
|
|
211
|
+
(0, command_contract_1.log)(io, ` ${change.entryId}: ${chalk_1.default.red(change.from)} → ${chalk_1.default.green(change.to)}`);
|
|
212
|
+
(0, command_contract_1.log)(io, ` ${chalk_1.default.gray(change.reason)}`);
|
|
191
213
|
}
|
|
214
|
+
return { kind: 'ok' };
|
|
192
215
|
}
|
|
193
216
|
/**
|
|
194
217
|
* 知识库统计
|
|
195
218
|
*/
|
|
196
|
-
async function knowledgeStats(options) {
|
|
197
|
-
const store = new store_1.FileKnowledgeStore({ baseDir: getKnowledgeDir(options.projectPath) });
|
|
219
|
+
async function knowledgeStats(options, io = command_contract_1.processIO) {
|
|
220
|
+
const store = new store_1.FileKnowledgeStore({ baseDir: getKnowledgeDir(options.projectPath, io) });
|
|
198
221
|
const entries = store.list({ excludeArchived: false });
|
|
199
222
|
const active = entries.filter(e => e.maturity !== 'archived');
|
|
200
223
|
const byType = {};
|
|
@@ -205,53 +228,52 @@ async function knowledgeStats(options) {
|
|
|
205
228
|
byMaturity[entry.maturity] = (byMaturity[entry.maturity] || 0) + 1;
|
|
206
229
|
byLayer[entry.layer] = (byLayer[entry.layer] || 0) + 1;
|
|
207
230
|
}
|
|
208
|
-
//
|
|
209
|
-
|
|
210
|
-
const refCoverage = active.length > 0 ? Math.round(withRefs / active.length * 100) : 0;
|
|
211
|
-
const avgRefs = active.length > 0
|
|
212
|
-
? Math.round(active.reduce((sum, e) => sum + e.referencedBy.length, 0) / active.length * 10) / 10
|
|
213
|
-
: 0;
|
|
214
|
-
let consumptionHitRate = 0;
|
|
231
|
+
// 飞轮指标:计算唯一实现在 knowledge/flywheel-metrics,此处只做 fs 读取 + 展示层单位映射
|
|
232
|
+
let dailyConsumptionEvents = 0;
|
|
215
233
|
try {
|
|
216
234
|
const statsPath = path.join(store.getBaseDir(), '.consumption-stats.json');
|
|
217
235
|
if (fs.existsSync(statsPath)) {
|
|
218
236
|
const stats = JSON.parse(fs.readFileSync(statsPath, 'utf-8'));
|
|
219
|
-
|
|
220
|
-
consumptionHitRate = active.length > 0 ? Math.min(Math.round(dailyEvents / active.length * 100), 100) : 0;
|
|
237
|
+
dailyConsumptionEvents = stats.dailyEvents || 0;
|
|
221
238
|
}
|
|
222
239
|
}
|
|
223
240
|
catch { /* best-effort */ }
|
|
241
|
+
const metrics = (0, flywheel_metrics_1.evaluateFlywheel)({ entries: active, dailyConsumptionEvents });
|
|
242
|
+
const refCoverage = Math.round(metrics.refCoverage * 100);
|
|
243
|
+
const avgRefs = Math.round(metrics.avgRefs * 10) / 10;
|
|
244
|
+
const consumptionHitRate = Math.round(metrics.consumptionHitRate * 100);
|
|
224
245
|
const flywheel = { refCoverage, avgRefs, consumptionHitRate };
|
|
225
246
|
if (options.json) {
|
|
226
|
-
|
|
227
|
-
return;
|
|
247
|
+
(0, command_contract_1.log)(io, JSON.stringify({ total: entries.length, byType, byMaturity, byLayer, flywheel }, null, 2));
|
|
248
|
+
return { kind: 'ok' };
|
|
228
249
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
250
|
+
(0, command_contract_1.log)(io, chalk_1.default.blue(`📊 知识库统计\n`));
|
|
251
|
+
(0, command_contract_1.log)(io, chalk_1.default.bold(` 总计: ${entries.length} 条 (活跃: ${active.length})\n`));
|
|
252
|
+
(0, command_contract_1.log)(io, chalk_1.default.bold(' 按类型:'));
|
|
232
253
|
for (const [type, count] of Object.entries(byType)) {
|
|
233
|
-
|
|
254
|
+
(0, command_contract_1.log)(io, ` ${type}: ${count}`);
|
|
234
255
|
}
|
|
235
|
-
|
|
256
|
+
(0, command_contract_1.log)(io, chalk_1.default.bold('\n 按成熟度:'));
|
|
236
257
|
for (const [maturity, count] of Object.entries(byMaturity)) {
|
|
237
258
|
const color = maturity === 'proven' ? chalk_1.default.green : maturity === 'archived' ? chalk_1.default.gray : chalk_1.default.yellow;
|
|
238
|
-
|
|
259
|
+
(0, command_contract_1.log)(io, ` ${color(maturity)}: ${count}`);
|
|
239
260
|
}
|
|
240
|
-
|
|
261
|
+
(0, command_contract_1.log)(io, chalk_1.default.bold('\n 按层级:'));
|
|
241
262
|
for (const [layer, count] of Object.entries(byLayer)) {
|
|
242
|
-
|
|
263
|
+
(0, command_contract_1.log)(io, ` ${layer}: ${count}`);
|
|
243
264
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
265
|
+
(0, command_contract_1.log)(io, chalk_1.default.bold('\n 飞轮指标:'));
|
|
266
|
+
(0, command_contract_1.log)(io, ` 引用覆盖: ${refCoverage}%`);
|
|
267
|
+
(0, command_contract_1.log)(io, ` 平均引用: ${avgRefs}`);
|
|
268
|
+
(0, command_contract_1.log)(io, ` 消费命中率: ${consumptionHitRate}%`);
|
|
269
|
+
return { kind: 'ok' };
|
|
248
270
|
}
|
|
249
271
|
/**
|
|
250
272
|
* 设计时知识沉淀:写入 KnowledgeStore + 同步 Prisma Document(Studio UI 可见)
|
|
251
273
|
*
|
|
252
274
|
* 调用 Studio API POST /api/knowledge/upsert(内部端点,无 auth)
|
|
253
275
|
*/
|
|
254
|
-
async function knowledgeUpsert(options) {
|
|
276
|
+
async function knowledgeUpsert(options, io = command_contract_1.processIO) {
|
|
255
277
|
const apiPort = process.env.API_PORT || '3001';
|
|
256
278
|
const url = `http://localhost:${apiPort}/api/knowledge/upsert`;
|
|
257
279
|
// Read content from file if --file specified
|
|
@@ -261,14 +283,14 @@ async function knowledgeUpsert(options) {
|
|
|
261
283
|
content = fs.readFileSync(options.file, 'utf-8');
|
|
262
284
|
}
|
|
263
285
|
catch (e) {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
286
|
+
(0, command_contract_1.logError)(io, chalk_1.default.red(`Failed to read file: ${options.file}`));
|
|
287
|
+
(0, command_contract_1.logError)(io, chalk_1.default.red(String(e)));
|
|
288
|
+
return { kind: 'fail', reason: `无法读取 --file ${options.file}: ${String(e)}` };
|
|
267
289
|
}
|
|
268
290
|
}
|
|
269
291
|
if (!options.scope || !options.title || !content) {
|
|
270
|
-
|
|
271
|
-
|
|
292
|
+
(0, command_contract_1.logError)(io, chalk_1.default.red('--scope, --title, and --content (or --file) are required'));
|
|
293
|
+
return { kind: 'usage-error', reason: '--scope/--title/--content(--file) 缺一不可' };
|
|
272
294
|
}
|
|
273
295
|
try {
|
|
274
296
|
const res = await fetch(url, {
|
|
@@ -284,100 +306,103 @@ async function knowledgeUpsert(options) {
|
|
|
284
306
|
});
|
|
285
307
|
if (!res.ok) {
|
|
286
308
|
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
287
|
-
|
|
288
|
-
|
|
309
|
+
(0, command_contract_1.logError)(io, chalk_1.default.red(`API error ${res.status}: ${err.error || res.statusText}`));
|
|
310
|
+
return { kind: 'fail', reason: `upsert API error ${res.status}: ${err.error || res.statusText}` };
|
|
289
311
|
}
|
|
290
312
|
const result = await res.json();
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
313
|
+
(0, command_contract_1.log)(io, chalk_1.default.green(`✅ Knowledge upserted`));
|
|
314
|
+
(0, command_contract_1.log)(io, ` KnowledgeStore: ${result.knowledgeStore?.action} → ${result.knowledgeStore?.entryId}`);
|
|
315
|
+
(0, command_contract_1.log)(io, ` Studio UI: ${result.prismaDocument?.action} → ${result.prismaDocument?.docId || 'skipped'}`);
|
|
316
|
+
return { kind: 'ok' };
|
|
294
317
|
}
|
|
295
318
|
catch (e) {
|
|
296
319
|
if (e?.code === 'ECONNREFUSED') {
|
|
297
|
-
|
|
320
|
+
(0, command_contract_1.logError)(io, chalk_1.default.red(`Cannot reach Studio API at ${url}. Is the API running?`));
|
|
298
321
|
}
|
|
299
322
|
else {
|
|
300
|
-
|
|
323
|
+
(0, command_contract_1.logError)(io, chalk_1.default.red(`Upsert failed: ${e.message}`));
|
|
301
324
|
}
|
|
302
|
-
|
|
325
|
+
return { kind: 'fail', reason: `knowledge upsert 失败: ${e?.code === 'ECONNREFUSED' ? `Studio API 不可达 ${url}` : e.message}` };
|
|
303
326
|
}
|
|
304
327
|
}
|
|
305
328
|
/**
|
|
306
329
|
/**
|
|
307
330
|
* RAG 同步:扫描 .harness/knowledge-docs/ 输出需要 ingest 的文件列表
|
|
308
331
|
*/
|
|
309
|
-
async function knowledgeSyncRag(options) {
|
|
332
|
+
async function knowledgeSyncRag(options, io = command_contract_1.processIO) {
|
|
310
333
|
const projectPath = options.projectPath || process.cwd();
|
|
311
334
|
const docsDir = `${projectPath}/.harness/knowledge-docs`;
|
|
312
335
|
if (!fs.existsSync(docsDir)) {
|
|
313
|
-
|
|
314
|
-
return;
|
|
336
|
+
(0, command_contract_1.log)(io, chalk_1.default.yellow('No .harness/knowledge-docs/ directory'));
|
|
337
|
+
return { kind: 'ok' };
|
|
315
338
|
}
|
|
316
339
|
const files = fs.readdirSync(docsDir).filter(f => f.endsWith('.md'));
|
|
317
340
|
if (files.length === 0) {
|
|
318
|
-
|
|
319
|
-
return;
|
|
341
|
+
(0, command_contract_1.log)(io, chalk_1.default.gray('No knowledge docs found'));
|
|
342
|
+
return { kind: 'ok' };
|
|
320
343
|
}
|
|
321
344
|
if (options.json) {
|
|
322
|
-
|
|
323
|
-
return;
|
|
345
|
+
(0, command_contract_1.log)(io, JSON.stringify({ directory: docsDir, files }, null, 2));
|
|
346
|
+
return { kind: 'ok' };
|
|
324
347
|
}
|
|
325
|
-
|
|
348
|
+
(0, command_contract_1.log)(io, chalk_1.default.blue(`📄 RAG sync candidates: ${files.length} files in ${docsDir}\n`));
|
|
326
349
|
for (const file of files) {
|
|
327
|
-
|
|
350
|
+
(0, command_contract_1.log)(io, chalk_1.default.cyan(` ${file}`));
|
|
328
351
|
}
|
|
329
|
-
|
|
330
|
-
|
|
352
|
+
(0, command_contract_1.log)(io);
|
|
353
|
+
(0, command_contract_1.log)(io, chalk_1.default.gray('Run `mcp__local-rag__ingest_file` for each to sync to RAG'));
|
|
354
|
+
return { kind: 'ok' };
|
|
331
355
|
}
|
|
332
356
|
/**
|
|
333
357
|
* 知识同步状态:检测所有 tracked scope 的新鲜度
|
|
334
358
|
*/
|
|
335
|
-
async function knowledgeSyncStatus(options) {
|
|
359
|
+
async function knowledgeSyncStatus(options, io = command_contract_1.processIO) {
|
|
336
360
|
const apiPort = process.env.API_PORT || '3001';
|
|
337
361
|
const url = `http://localhost:${apiPort}/api/knowledge/sync-status`;
|
|
338
362
|
try {
|
|
339
363
|
const res = await fetch(url);
|
|
340
364
|
if (!res.ok) {
|
|
341
365
|
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
342
|
-
|
|
343
|
-
|
|
366
|
+
(0, command_contract_1.logError)(io, chalk_1.default.red(`API error ${res.status}: ${err.error || res.statusText}`));
|
|
367
|
+
return { kind: 'fail', reason: `sync-status API error ${res.status}: ${err.error || res.statusText}` };
|
|
344
368
|
}
|
|
345
369
|
const data = await res.json();
|
|
346
370
|
if (options.json) {
|
|
347
|
-
|
|
348
|
-
return;
|
|
371
|
+
(0, command_contract_1.log)(io, JSON.stringify(data, null, 2));
|
|
372
|
+
return { kind: 'ok' };
|
|
349
373
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
374
|
+
(0, command_contract_1.log)(io, chalk_1.default.blue(`🔄 KnowledgeSync Status\n`));
|
|
375
|
+
(0, command_contract_1.log)(io, chalk_1.default.bold(`Tracked scopes: ${data.trackedScopes?.join(', ') || 'none'}`));
|
|
376
|
+
(0, command_contract_1.log)(io, chalk_1.default.bold(`Stale entries: ${data.stale?.length || 0}`));
|
|
353
377
|
if (data.stale?.length > 0) {
|
|
354
|
-
|
|
378
|
+
(0, command_contract_1.log)(io, chalk_1.default.yellow(`\n⚠️ Stale knowledge:\n`));
|
|
355
379
|
for (const s of data.stale) {
|
|
356
|
-
|
|
380
|
+
(0, command_contract_1.log)(io, chalk_1.default.yellow(` ${s.scope} (${s.title}): ${s.stalenessHours}h old, files changed: ${s.changedFiles.join(', ')}`));
|
|
357
381
|
}
|
|
358
382
|
}
|
|
359
383
|
else {
|
|
360
|
-
|
|
384
|
+
(0, command_contract_1.log)(io, chalk_1.default.green('\n✅ All knowledge fresh'));
|
|
361
385
|
}
|
|
362
386
|
if (data.healed?.length > 0) {
|
|
363
|
-
|
|
387
|
+
(0, command_contract_1.log)(io, chalk_1.default.cyan(`\n🩹 Auto-healed: ${data.healed.join(', ')}`));
|
|
364
388
|
}
|
|
365
389
|
}
|
|
366
390
|
catch (e) {
|
|
367
391
|
if (e?.code === 'ECONNREFUSED') {
|
|
368
|
-
|
|
392
|
+
(0, command_contract_1.logError)(io, chalk_1.default.red(`Cannot reach Studio API at ${url}`));
|
|
369
393
|
}
|
|
370
394
|
else {
|
|
371
|
-
|
|
395
|
+
(0, command_contract_1.logError)(io, chalk_1.default.red(`Sync check failed: ${e.message}`));
|
|
372
396
|
}
|
|
373
|
-
|
|
397
|
+
return { kind: 'fail', reason: `knowledge sync status 检查失败: ${e?.code === 'ECONNREFUSED' ? `Studio API 不可达 ${url}` : e.message}` };
|
|
374
398
|
}
|
|
399
|
+
return { kind: 'ok' };
|
|
375
400
|
}
|
|
376
401
|
/**
|
|
377
402
|
* 飞轮健康检查 — 零 token 检测知识飞轮数据流状态
|
|
378
403
|
*/
|
|
379
|
-
async function knowledgeHealth(options) {
|
|
380
|
-
const baseDir = options.dir || getKnowledgeDir(options.projectPath);
|
|
404
|
+
async function knowledgeHealth(options, io = command_contract_1.processIO) {
|
|
405
|
+
const baseDir = options.dir || getKnowledgeDir(options.projectPath, io);
|
|
381
406
|
const store = new store_1.FileKnowledgeStore({ baseDir });
|
|
382
407
|
const entries = store.list({ excludeArchived: true });
|
|
383
408
|
const issues = [];
|
|
@@ -409,18 +434,16 @@ async function knowledgeHealth(options) {
|
|
|
409
434
|
else {
|
|
410
435
|
issues.push({ severity: 'info', entry: '-', detail: `消费追踪数据不存在(${statsPath})` });
|
|
411
436
|
}
|
|
412
|
-
// D4:
|
|
413
|
-
const
|
|
414
|
-
const refCoverage =
|
|
415
|
-
const avgRefs =
|
|
416
|
-
? Math.round(entries.reduce((sum, e) => sum + e.referencedBy.length, 0) / entries.length * 10) / 10
|
|
417
|
-
: 0;
|
|
437
|
+
// D4: 飞轮指标(计算唯一实现在 knowledge/flywheel-metrics;人口为本命令的 excludeArchived 切片)
|
|
438
|
+
const metrics = (0, flywheel_metrics_1.evaluateFlywheel)({ entries });
|
|
439
|
+
const refCoverage = Math.round(metrics.refCoverage * 100);
|
|
440
|
+
const avgRefs = Math.round(metrics.avgRefs * 10) / 10;
|
|
418
441
|
// 健康分计算
|
|
419
442
|
const totalIssues = issues.filter(i => i.severity === 'error').length * 3
|
|
420
443
|
+ issues.filter(i => i.severity === 'warn').length * 1;
|
|
421
444
|
const healthScore = Math.max(0, 100 - totalIssues);
|
|
422
445
|
if (options.json) {
|
|
423
|
-
|
|
446
|
+
(0, command_contract_1.log)(io, JSON.stringify({
|
|
424
447
|
healthScore,
|
|
425
448
|
summary: {
|
|
426
449
|
total: entries.length,
|
|
@@ -432,70 +455,94 @@ async function knowledgeHealth(options) {
|
|
|
432
455
|
},
|
|
433
456
|
issues: issues.slice(0, 50),
|
|
434
457
|
}, null, 2));
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
458
|
+
return { kind: 'ok' };
|
|
459
|
+
}
|
|
460
|
+
(0, command_contract_1.log)(io, chalk_1.default.blue('🏥 飞轮健康检查\n'));
|
|
461
|
+
(0, command_contract_1.log)(io, chalk_1.default.bold(` 健康分: ${healthScore >= 80 ? chalk_1.default.green(healthScore) : healthScore >= 60 ? chalk_1.default.yellow(healthScore) : chalk_1.default.red(healthScore)}/100`));
|
|
462
|
+
(0, command_contract_1.log)(io, chalk_1.default.bold(` 活跃条目: ${entries.length}`));
|
|
463
|
+
(0, command_contract_1.log)(io);
|
|
464
|
+
(0, command_contract_1.log)(io, chalk_1.default.bold(' 数据流状态:'));
|
|
465
|
+
(0, command_contract_1.log)(io, ` 引用密度: ${lowRefEntries === 0 ? chalk_1.default.green('✓') : chalk_1.default.yellow(`⚠ ${lowRefEntries} 个零引用 verified`)}`);
|
|
466
|
+
(0, command_contract_1.log)(io, ` 新鲜度: ${staleEntries === 0 ? chalk_1.default.green('✓') : chalk_1.default.yellow(`⚠ ${staleEntries} 个过期 draft`)}`);
|
|
467
|
+
(0, command_contract_1.log)(io, ` 消费追踪: ${consumptionData ? chalk_1.default.green('✓') : chalk_1.default.gray('○ 未启用')}`);
|
|
468
|
+
(0, command_contract_1.log)(io);
|
|
469
|
+
(0, command_contract_1.log)(io, chalk_1.default.bold(' 飞轮指标:'));
|
|
470
|
+
(0, command_contract_1.log)(io, ` 引用覆盖: ${refCoverage}%`);
|
|
471
|
+
(0, command_contract_1.log)(io, ` 平均引用: ${avgRefs}`);
|
|
472
|
+
(0, command_contract_1.log)(io);
|
|
450
473
|
if (issues.length > 0) {
|
|
451
|
-
|
|
474
|
+
(0, command_contract_1.log)(io, chalk_1.default.bold(` 问题 (前 20):`));
|
|
452
475
|
for (const issue of issues.slice(0, 20)) {
|
|
453
476
|
const sevColor = issue.severity === 'error' ? chalk_1.default.red
|
|
454
477
|
: issue.severity === 'warn' ? chalk_1.default.yellow
|
|
455
478
|
: chalk_1.default.gray;
|
|
456
|
-
|
|
479
|
+
(0, command_contract_1.log)(io, ` ${sevColor(`[${issue.severity}]`)} ${issue.entry}: ${issue.detail}`);
|
|
457
480
|
}
|
|
458
481
|
if (issues.length > 20) {
|
|
459
|
-
|
|
482
|
+
(0, command_contract_1.log)(io, chalk_1.default.gray(` ... 还有 ${issues.length - 20} 条`));
|
|
460
483
|
}
|
|
461
484
|
}
|
|
462
485
|
else {
|
|
463
|
-
|
|
486
|
+
(0, command_contract_1.log)(io, chalk_1.default.green(' ✓ 无问题'));
|
|
487
|
+
}
|
|
488
|
+
return { kind: 'ok' };
|
|
489
|
+
}
|
|
490
|
+
/** 缺省知识库数据根(相对用户 home) */
|
|
491
|
+
const KNOWLEDGE_DATA_DIR = path.join('.harness', 'knowledge');
|
|
492
|
+
/** 旧缺省数据根(曾寄居 studio home),仍有数据时兼容沿用,免迁移 */
|
|
493
|
+
const LEGACY_KNOWLEDGE_DATA_DIR = path.join('.studio', 'knowledge');
|
|
494
|
+
let legacyKnowledgeDirNotified = false;
|
|
495
|
+
function hasKnowledgeData(dir) {
|
|
496
|
+
try {
|
|
497
|
+
return fs.existsSync(dir) && fs.readdirSync(dir).length > 0;
|
|
498
|
+
}
|
|
499
|
+
catch {
|
|
500
|
+
return false;
|
|
464
501
|
}
|
|
465
502
|
}
|
|
466
|
-
function getKnowledgeDir(projectPath) {
|
|
503
|
+
function getKnowledgeDir(projectPath, io) {
|
|
467
504
|
if (projectPath)
|
|
468
505
|
return `${projectPath}/.harness/knowledge`;
|
|
469
506
|
if (process.env.KNOWLEDGE_BASE_DIR)
|
|
470
507
|
return process.env.KNOWLEDGE_BASE_DIR;
|
|
471
|
-
|
|
508
|
+
const defaultDir = path.join(os.homedir(), KNOWLEDGE_DATA_DIR);
|
|
509
|
+
const legacyDir = path.join(os.homedir(), LEGACY_KNOWLEDGE_DATA_DIR);
|
|
510
|
+
if (hasKnowledgeData(legacyDir)) {
|
|
511
|
+
if (!legacyKnowledgeDirNotified) {
|
|
512
|
+
legacyKnowledgeDirNotified = true;
|
|
513
|
+
// stderr:不污染 --json 的 stdout 输出
|
|
514
|
+
(0, command_contract_1.logError)(io, chalk_1.default.yellow(`⚠ 缺省知识库根已改为 ${defaultDir};旧目录 ${legacyDir} 仍有数据,本次沿用(免迁移,可用 KNOWLEDGE_BASE_DIR 覆盖)`));
|
|
515
|
+
}
|
|
516
|
+
return legacyDir;
|
|
517
|
+
}
|
|
518
|
+
return defaultDir;
|
|
472
519
|
}
|
|
473
520
|
/**
|
|
474
521
|
* 知识库质量审计
|
|
475
522
|
*/
|
|
476
|
-
async function knowledgeAudit(options) {
|
|
523
|
+
async function knowledgeAudit(options, io = command_contract_1.processIO) {
|
|
477
524
|
const audit = new audit_1.KnowledgeAudit({
|
|
478
|
-
baseDir: options.dir || getKnowledgeDir(options.projectPath),
|
|
525
|
+
baseDir: options.dir || getKnowledgeDir(options.projectPath, io),
|
|
479
526
|
shortContentThreshold: options.threshold ? parseInt(options.threshold, 10) : undefined,
|
|
480
527
|
});
|
|
481
528
|
const isDryRun = options.dryRun && !options.fix;
|
|
482
529
|
if (!options.json && !isDryRun) {
|
|
483
|
-
|
|
530
|
+
(0, command_contract_1.log)(io, chalk_1.default.blue('🔍 知识库质量审计...\n'));
|
|
484
531
|
}
|
|
485
532
|
const report = audit.run({ autoFix: options.fix && !isDryRun });
|
|
486
533
|
if (options.json) {
|
|
487
|
-
|
|
488
|
-
return;
|
|
534
|
+
(0, command_contract_1.log)(io, JSON.stringify(report, null, 2));
|
|
535
|
+
return { kind: 'ok' };
|
|
489
536
|
}
|
|
490
537
|
// Summary
|
|
491
|
-
|
|
492
|
-
|
|
538
|
+
(0, command_contract_1.log)(io, chalk_1.default.bold(` 总条目: ${report.totalEntries}`));
|
|
539
|
+
(0, command_contract_1.log)(io, chalk_1.default.bold(` 健康分: ${report.healthScore.before}/100`));
|
|
493
540
|
if (report.autoFixed > 0) {
|
|
494
|
-
|
|
495
|
-
|
|
541
|
+
(0, command_contract_1.log)(io, chalk_1.default.green(` 自动修复: ${report.autoFixed} 条`));
|
|
542
|
+
(0, command_contract_1.log)(io, chalk_1.default.bold(` 修复后: ${report.healthScore.after}/100`));
|
|
496
543
|
}
|
|
497
|
-
|
|
498
|
-
// Dimension scores
|
|
544
|
+
(0, command_contract_1.log)(io);
|
|
545
|
+
// Dimension scores(Record 全键标注 → 编译期闭环,#109)
|
|
499
546
|
const dimLabels = {
|
|
500
547
|
structure: 'D1 结构完整性',
|
|
501
548
|
content: 'D2 内容质量',
|
|
@@ -503,105 +550,95 @@ async function knowledgeAudit(options) {
|
|
|
503
550
|
maturity: 'D4 成熟度健康',
|
|
504
551
|
freshness: 'D5 新鲜度',
|
|
505
552
|
flywheel: 'D6 飞轮验证',
|
|
553
|
+
incremental: 'D7 增量存活',
|
|
506
554
|
};
|
|
507
|
-
|
|
555
|
+
(0, command_contract_1.log)(io, chalk_1.default.bold(' 维度评分:'));
|
|
508
556
|
for (const [key, dim] of Object.entries(report.dimensions)) {
|
|
509
|
-
const label = dimLabels[key]
|
|
557
|
+
const label = dimLabels[key];
|
|
510
558
|
const scoreColor = dim.score >= 80 ? chalk_1.default.green : dim.score >= 60 ? chalk_1.default.yellow : chalk_1.default.red;
|
|
511
|
-
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
// Issues by rule
|
|
515
|
-
const ruleLabels = {
|
|
516
|
-
'frontmatter-missing': 'frontmatter 缺失',
|
|
517
|
-
'test-data-pollution': '测试数据污染',
|
|
518
|
-
'daily-audit-noise': '每日审计噪音',
|
|
519
|
-
'zero-content-proven': '零内容 proven',
|
|
520
|
-
'short-content': '短内容',
|
|
521
|
-
'maturity-inflation': '成熟度虚高',
|
|
522
|
-
'title-duplicate': '标题重复',
|
|
523
|
-
'source-refs-bloat': 'sourceReferences 膨胀',
|
|
524
|
-
'fragment-cluster': '碎片集群',
|
|
525
|
-
'promotion-blocked': 'promotion 受阻',
|
|
526
|
-
'orphan-draft': '孤儿 draft',
|
|
527
|
-
'stale-entry': '过期条目',
|
|
528
|
-
};
|
|
559
|
+
(0, command_contract_1.log)(io, ` ${label}: ${scoreColor(`${dim.score}/100`)} (${dim.issues} 问题)`);
|
|
560
|
+
}
|
|
561
|
+
(0, command_contract_1.log)(io);
|
|
562
|
+
// Issues by rule(label 正本在 audit.ts 规则定义,AUDIT_RULE_LABELS 编译期闭环,#109)
|
|
529
563
|
for (const [rule, count] of Object.entries(report.summary)) {
|
|
530
564
|
if (count === 0)
|
|
531
565
|
continue;
|
|
532
|
-
const label =
|
|
533
|
-
|
|
566
|
+
const label = audit_1.AUDIT_RULE_LABELS[rule];
|
|
567
|
+
(0, command_contract_1.log)(io, ` ${chalk_1.default.red(`${label}: ${count}`)}`);
|
|
534
568
|
}
|
|
535
569
|
// Detail (first 20)
|
|
536
570
|
if (report.issues.length > 0) {
|
|
537
|
-
|
|
571
|
+
(0, command_contract_1.log)(io, chalk_1.default.bold(`\n 问题详情 (前 20 条):\n`));
|
|
538
572
|
for (const issue of report.issues.slice(0, 20)) {
|
|
539
573
|
const severityColor = issue.severity === 'critical' ? chalk_1.default.red
|
|
540
574
|
: issue.severity === 'high' ? chalk_1.default.yellow
|
|
541
575
|
: chalk_1.default.gray;
|
|
542
|
-
|
|
543
|
-
|
|
576
|
+
(0, command_contract_1.log)(io, ` ${severityColor(`[${issue.severity}]`)} ${issue.entryId}: ${issue.title}`);
|
|
577
|
+
(0, command_contract_1.log)(io, ` ${chalk_1.default.gray(issue.detail)} → ${issue.action}`);
|
|
544
578
|
}
|
|
545
579
|
if (report.issues.length > 20) {
|
|
546
|
-
|
|
580
|
+
(0, command_contract_1.log)(io, chalk_1.default.gray(`\n ... 还有 ${report.issues.length - 20} 条`));
|
|
547
581
|
}
|
|
548
582
|
}
|
|
549
583
|
if (!options.fix && report.issues.length > 0) {
|
|
550
|
-
|
|
584
|
+
(0, command_contract_1.log)(io, chalk_1.default.yellow(`\n 使用 --fix 自动修复`));
|
|
551
585
|
}
|
|
552
586
|
// Auto-rebuild index after audit (files may have changed)
|
|
553
|
-
const baseDir = options.dir || getKnowledgeDir(options.projectPath);
|
|
587
|
+
const baseDir = options.dir || getKnowledgeDir(options.projectPath, io);
|
|
554
588
|
const idxGen = new index_generator_1.KnowledgeIndexGenerator(baseDir);
|
|
555
589
|
idxGen.regenerate();
|
|
556
590
|
if (!options.json) {
|
|
557
|
-
|
|
591
|
+
(0, command_contract_1.log)(io, chalk_1.default.gray(` 📇 索引已重建`));
|
|
558
592
|
}
|
|
593
|
+
return { kind: 'ok' };
|
|
559
594
|
}
|
|
560
595
|
/**
|
|
561
596
|
* 知识库快照(KR4 存活率追踪)
|
|
562
597
|
*/
|
|
563
|
-
function knowledgeSnapshot(options) {
|
|
564
|
-
const store = new store_1.FileKnowledgeStore({ baseDir: options.dir || getKnowledgeDir(options.projectPath) });
|
|
598
|
+
function knowledgeSnapshot(options, io = command_contract_1.processIO) {
|
|
599
|
+
const store = new store_1.FileKnowledgeStore({ baseDir: options.dir || getKnowledgeDir(options.projectPath, io) });
|
|
565
600
|
const snapPath = store.snapshot();
|
|
566
601
|
if (options.json) {
|
|
567
|
-
|
|
568
|
-
return;
|
|
602
|
+
(0, command_contract_1.log)(io, JSON.stringify({ snapshotPath: snapPath }));
|
|
603
|
+
return { kind: 'ok' };
|
|
569
604
|
}
|
|
570
|
-
|
|
605
|
+
(0, command_contract_1.log)(io, chalk_1.default.green(`✅ 快照已保存: ${snapPath}`));
|
|
606
|
+
return { kind: 'ok' };
|
|
571
607
|
}
|
|
572
608
|
/**
|
|
573
609
|
* 知识库迁移 — 为现有条目添加 AS-021 新字段
|
|
574
610
|
*/
|
|
575
|
-
function knowledgeMigrate(options) {
|
|
576
|
-
const baseDir = options.dir || getKnowledgeDir(options.projectPath);
|
|
611
|
+
function knowledgeMigrate(options, io = command_contract_1.processIO) {
|
|
612
|
+
const baseDir = options.dir || getKnowledgeDir(options.projectPath, io);
|
|
577
613
|
if (options.json) {
|
|
578
614
|
const result = (0, migration_1.migrateKnowledgeEntries)(baseDir);
|
|
579
|
-
|
|
580
|
-
return;
|
|
615
|
+
(0, command_contract_1.log)(io, JSON.stringify(result, null, 2));
|
|
616
|
+
return { kind: 'ok' };
|
|
581
617
|
}
|
|
582
|
-
|
|
618
|
+
(0, command_contract_1.log)(io, chalk_1.default.blue('🔄 迁移知识条目(添加 consumptionMode/origin 字段)\n'));
|
|
583
619
|
const result = (0, migration_1.migrateKnowledgeEntries)(baseDir);
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
620
|
+
(0, command_contract_1.log)(io, chalk_1.default.green(` 总计: ${result.total} 条`));
|
|
621
|
+
(0, command_contract_1.log)(io, chalk_1.default.green(` 已迁移: ${result.migrated} 条`));
|
|
622
|
+
(0, command_contract_1.log)(io, chalk_1.default.gray(` 已跳过: ${result.skipped} 条`));
|
|
587
623
|
if (result.errors.length > 0) {
|
|
588
|
-
|
|
624
|
+
(0, command_contract_1.log)(io, chalk_1.default.red(`\n 错误: ${result.errors.length} 条`));
|
|
589
625
|
for (const err of result.errors.slice(0, 5)) {
|
|
590
|
-
|
|
626
|
+
(0, command_contract_1.log)(io, chalk_1.default.red(` ${err}`));
|
|
591
627
|
}
|
|
592
628
|
}
|
|
593
629
|
if (result.migrated === 0 && result.errors.length === 0) {
|
|
594
|
-
|
|
630
|
+
(0, command_contract_1.log)(io, chalk_1.default.green('\n✅ 所有条目已是最新,无需迁移'));
|
|
595
631
|
}
|
|
596
632
|
else if (result.migrated > 0) {
|
|
597
|
-
|
|
633
|
+
(0, command_contract_1.log)(io, chalk_1.default.green(`\n✅ 迁移完成`));
|
|
598
634
|
}
|
|
635
|
+
return { kind: 'ok' };
|
|
599
636
|
}
|
|
600
637
|
/**
|
|
601
638
|
* 知识库索引重建 — 生成 _index.md 供 Agent grep 使用,同时同步 index.json
|
|
602
639
|
*/
|
|
603
|
-
function knowledgeIndex(options) {
|
|
604
|
-
const baseDir = options.dir || getKnowledgeDir(options.projectPath);
|
|
640
|
+
function knowledgeIndex(options, io = command_contract_1.processIO) {
|
|
641
|
+
const baseDir = options.dir || getKnowledgeDir(options.projectPath, io);
|
|
605
642
|
const gen = new index_generator_1.KnowledgeIndexGenerator(baseDir);
|
|
606
643
|
const beforeSize = (() => {
|
|
607
644
|
const indexPath = path.join(baseDir, '_index.md');
|
|
@@ -614,20 +651,21 @@ function knowledgeIndex(options) {
|
|
|
614
651
|
const afterSize = Buffer.byteLength(output, 'utf-8');
|
|
615
652
|
const lineCount = output.split('\n').filter(l => !l.startsWith('#')).length;
|
|
616
653
|
if (options.json) {
|
|
617
|
-
|
|
654
|
+
(0, command_contract_1.log)(io, JSON.stringify({
|
|
618
655
|
path: path.join(baseDir, '_index.md'),
|
|
619
656
|
entries: lineCount,
|
|
620
657
|
size: afterSize,
|
|
621
658
|
previousSize: beforeSize,
|
|
622
659
|
}));
|
|
623
|
-
return;
|
|
660
|
+
return { kind: 'ok' };
|
|
624
661
|
}
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
662
|
+
(0, command_contract_1.log)(io, chalk_1.default.blue(`📇 索引已重建`));
|
|
663
|
+
(0, command_contract_1.log)(io, chalk_1.default.gray(` 路径: ${path.join(baseDir, '_index.md')}`));
|
|
664
|
+
(0, command_contract_1.log)(io, chalk_1.default.green(` 条目: ${lineCount}`));
|
|
665
|
+
(0, command_contract_1.log)(io, chalk_1.default.green(` 大小: ${(afterSize / 1024).toFixed(1)} KB`));
|
|
629
666
|
if (beforeSize > 0) {
|
|
630
|
-
|
|
667
|
+
(0, command_contract_1.log)(io, chalk_1.default.gray(` 旧大小: ${(beforeSize / 1024).toFixed(1)} KB`));
|
|
631
668
|
}
|
|
669
|
+
return { kind: 'ok' };
|
|
632
670
|
}
|
|
633
671
|
//# sourceMappingURL=knowledge.js.map
|