@dommaker/harness 0.16.6 → 0.16.8
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 +54 -14
- package/bin/harness.js +56 -96
- package/dist/architecture/constraint-engine.d.ts.map +1 -1
- package/dist/architecture/constraint-engine.js +0 -4
- package/dist/architecture/constraint-engine.js.map +1 -1
- package/dist/architecture/cross-project-checker.d.ts.map +1 -1
- package/dist/architecture/cross-project-checker.js +5 -25
- package/dist/architecture/cross-project-checker.js.map +1 -1
- package/dist/cli/commands/analyze-sessions.d.ts +2 -0
- package/dist/cli/commands/analyze-sessions.d.ts.map +1 -1
- package/dist/cli/commands/analyze-sessions.js +25 -181
- package/dist/cli/commands/analyze-sessions.js.map +1 -1
- package/dist/cli/commands/check.d.ts +1 -0
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/check.js +24 -216
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/doc-freshness-check.d.ts.map +1 -1
- package/dist/cli/commands/doc-freshness-check.js +14 -28
- package/dist/cli/commands/doc-freshness-check.js.map +1 -1
- package/dist/cli/commands/flow.d.ts.map +1 -1
- package/dist/cli/commands/flow.js +2 -1
- package/dist/cli/commands/flow.js.map +1 -1
- package/dist/cli/commands/init.js +2 -2
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/posteval-plan.d.ts.map +1 -1
- package/dist/cli/commands/posteval-plan.js +0 -1
- package/dist/cli/commands/posteval-plan.js.map +1 -1
- package/dist/cli/commands/release.js +1 -1
- package/dist/cli/commands/release.js.map +1 -1
- package/dist/cli/commands/report.d.ts.map +1 -1
- package/dist/cli/commands/report.js +2 -0
- package/dist/cli/commands/report.js.map +1 -1
- package/dist/cli/commands/spec-baseline-check.d.ts.map +1 -1
- package/dist/cli/commands/spec-baseline-check.js +12 -23
- package/dist/cli/commands/spec-baseline-check.js.map +1 -1
- package/dist/cli/commands/sync-docs/agents-syncer.d.ts +19 -0
- package/dist/cli/commands/sync-docs/agents-syncer.d.ts.map +1 -0
- package/dist/cli/commands/sync-docs/agents-syncer.js +288 -0
- package/dist/cli/commands/sync-docs/agents-syncer.js.map +1 -0
- package/dist/cli/commands/sync-docs/capabilities-syncer.d.ts +37 -0
- package/dist/cli/commands/sync-docs/capabilities-syncer.d.ts.map +1 -0
- package/dist/cli/commands/sync-docs/capabilities-syncer.js +235 -0
- package/dist/cli/commands/sync-docs/capabilities-syncer.js.map +1 -0
- package/dist/cli/commands/sync-docs/context-syncer.d.ts +17 -0
- package/dist/cli/commands/sync-docs/context-syncer.d.ts.map +1 -0
- package/dist/cli/commands/sync-docs/context-syncer.js +143 -0
- package/dist/cli/commands/sync-docs/context-syncer.js.map +1 -0
- package/dist/cli/commands/{sync-docs.d.ts → sync-docs/index.d.ts} +9 -2
- package/dist/cli/commands/sync-docs/index.d.ts.map +1 -0
- package/dist/cli/commands/sync-docs/index.js +338 -0
- package/dist/cli/commands/sync-docs/index.js.map +1 -0
- package/dist/cli/commands/sync-docs/preserve-block.d.ts +24 -0
- package/dist/cli/commands/sync-docs/preserve-block.d.ts.map +1 -0
- package/dist/cli/commands/sync-docs/preserve-block.js +55 -0
- package/dist/cli/commands/sync-docs/preserve-block.js.map +1 -0
- package/dist/cli/commands/sync-docs/project-reader.d.ts +41 -0
- package/dist/cli/commands/sync-docs/project-reader.d.ts.map +1 -0
- package/dist/cli/commands/sync-docs/project-reader.js +183 -0
- package/dist/cli/commands/sync-docs/project-reader.js.map +1 -0
- package/dist/cli/commands/update-user-model.d.ts +2 -0
- package/dist/cli/commands/update-user-model.d.ts.map +1 -1
- package/dist/cli/commands/update-user-model.js +19 -90
- package/dist/cli/commands/update-user-model.js.map +1 -1
- package/dist/cli/commands/validate.d.ts +3 -0
- package/dist/cli/commands/validate.d.ts.map +1 -1
- package/dist/cli/commands/validate.js +6 -39
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/session-mining/corrections.d.ts +17 -0
- package/dist/cli/session-mining/corrections.d.ts.map +1 -0
- package/dist/cli/session-mining/corrections.js +58 -0
- package/dist/cli/session-mining/corrections.js.map +1 -0
- package/dist/cli/session-mining/index.d.ts +13 -0
- package/dist/cli/session-mining/index.d.ts.map +1 -0
- package/dist/{core/spec → cli/session-mining}/index.js +9 -3
- package/dist/cli/session-mining/index.js.map +1 -0
- package/dist/cli/session-mining/text.d.ts +31 -0
- package/dist/cli/session-mining/text.d.ts.map +1 -0
- package/dist/cli/session-mining/text.js +126 -0
- package/dist/cli/session-mining/text.js.map +1 -0
- package/dist/cli/session-mining/transcript.d.ts +28 -0
- package/dist/cli/session-mining/transcript.d.ts.map +1 -0
- package/dist/cli/session-mining/transcript.js +123 -0
- package/dist/cli/session-mining/transcript.js.map +1 -0
- package/dist/constraints/lifecycle-runner.d.ts +1 -1
- package/dist/constraints/lifecycle-runner.d.ts.map +1 -1
- package/dist/context/compaction.d.ts.map +1 -1
- package/dist/context/compaction.js +2 -3
- package/dist/context/compaction.js.map +1 -1
- package/dist/context/knowledge-injector.d.ts.map +1 -1
- package/dist/context/tool-output-budget.d.ts +1 -1
- package/dist/context/tool-output-budget.d.ts.map +1 -1
- package/dist/context/tool-output-budget.js +1 -1
- package/dist/context/tool-output-budget.js.map +1 -1
- package/dist/core/constraints/capabilities-parser.d.ts +24 -0
- package/dist/core/constraints/capabilities-parser.d.ts.map +1 -0
- package/dist/core/constraints/capabilities-parser.js +95 -0
- package/dist/core/constraints/capabilities-parser.js.map +1 -0
- package/dist/core/constraints/checker.d.ts +37 -100
- package/dist/core/constraints/checker.d.ts.map +1 -1
- package/dist/core/constraints/checker.js +150 -737
- package/dist/core/constraints/checker.js.map +1 -1
- package/dist/core/constraints/checkers/always-pass.d.ts +17 -0
- package/dist/core/constraints/checkers/always-pass.d.ts.map +1 -0
- package/dist/core/constraints/checkers/always-pass.js +23 -0
- package/dist/core/constraints/checkers/always-pass.js.map +1 -0
- package/dist/core/constraints/checkers/capability-sync.d.ts +10 -0
- package/dist/core/constraints/checkers/capability-sync.d.ts.map +1 -0
- package/dist/core/constraints/checkers/capability-sync.js +60 -0
- package/dist/core/constraints/checkers/capability-sync.js.map +1 -0
- package/dist/core/constraints/checkers/context-doc-sync.d.ts +6 -0
- package/dist/core/constraints/checkers/context-doc-sync.d.ts.map +1 -0
- package/dist/core/constraints/checkers/context-doc-sync.js +35 -0
- package/dist/core/constraints/checkers/context-doc-sync.js.map +1 -0
- package/dist/core/constraints/checkers/docs-freshness.d.ts +10 -0
- package/dist/core/constraints/checkers/docs-freshness.d.ts.map +1 -0
- package/dist/core/constraints/checkers/docs-freshness.js +111 -0
- package/dist/core/constraints/checkers/docs-freshness.js.map +1 -0
- package/dist/core/constraints/checkers/guideline-flags.d.ts +9 -0
- package/dist/core/constraints/checkers/guideline-flags.d.ts.map +1 -0
- package/dist/core/constraints/checkers/guideline-flags.js +13 -0
- package/dist/core/constraints/checkers/guideline-flags.js.map +1 -0
- package/dist/core/constraints/checkers/index.d.ts +17 -0
- package/dist/core/constraints/checkers/index.d.ts.map +1 -0
- package/dist/core/constraints/checkers/index.js +82 -0
- package/dist/core/constraints/checkers/index.js.map +1 -0
- package/dist/core/constraints/checkers/iron-flags.d.ts +14 -0
- package/dist/core/constraints/checkers/iron-flags.d.ts.map +1 -0
- package/dist/core/constraints/checkers/iron-flags.js +24 -0
- package/dist/core/constraints/checkers/iron-flags.js.map +1 -0
- package/dist/core/constraints/checkers/no-any-type.d.ts +6 -0
- package/dist/core/constraints/checkers/no-any-type.d.ts.map +1 -0
- package/dist/core/constraints/checkers/no-any-type.js +42 -0
- package/dist/core/constraints/checkers/no-any-type.js.map +1 -0
- package/dist/core/constraints/checkers/no-bypass-checkpoint.d.ts +6 -0
- package/dist/core/constraints/checkers/no-bypass-checkpoint.d.ts.map +1 -0
- package/dist/core/constraints/checkers/no-bypass-checkpoint.js +40 -0
- package/dist/core/constraints/checkers/no-bypass-checkpoint.js.map +1 -0
- package/dist/core/constraints/checkers/no-excuse-patterns.d.ts +6 -0
- package/dist/core/constraints/checkers/no-excuse-patterns.d.ts.map +1 -0
- package/dist/core/constraints/checkers/no-excuse-patterns.js +25 -0
- package/dist/core/constraints/checkers/no-excuse-patterns.js.map +1 -0
- package/dist/core/constraints/checkers/no-fuzzy-completion-claim.d.ts +6 -0
- package/dist/core/constraints/checkers/no-fuzzy-completion-claim.d.ts.map +1 -0
- package/dist/core/constraints/checkers/no-fuzzy-completion-claim.js +34 -0
- package/dist/core/constraints/checkers/no-fuzzy-completion-claim.js.map +1 -0
- package/dist/core/constraints/checkers/no-performative-agreement.d.ts +8 -0
- package/dist/core/constraints/checkers/no-performative-agreement.d.ts.map +1 -0
- package/dist/core/constraints/checkers/no-performative-agreement.js +23 -0
- package/dist/core/constraints/checkers/no-performative-agreement.js.map +1 -0
- package/dist/core/constraints/checkers/no-simplification-without-approval.d.ts +6 -0
- package/dist/core/constraints/checkers/no-simplification-without-approval.d.ts.map +1 -0
- package/dist/core/constraints/checkers/no-simplification-without-approval.js +30 -0
- package/dist/core/constraints/checkers/no-simplification-without-approval.js.map +1 -0
- package/dist/core/constraints/checkers/no-test-simplification.d.ts +6 -0
- package/dist/core/constraints/checkers/no-test-simplification.d.ts.map +1 -0
- package/dist/core/constraints/checkers/no-test-simplification.js +29 -0
- package/dist/core/constraints/checkers/no-test-simplification.js.map +1 -0
- package/dist/core/constraints/checkers/test-coverage.d.ts +6 -0
- package/dist/core/constraints/checkers/test-coverage.d.ts.map +1 -0
- package/dist/core/constraints/checkers/test-coverage.js +33 -0
- package/dist/core/constraints/checkers/test-coverage.js.map +1 -0
- package/dist/core/constraints/checkers/types.d.ts +43 -0
- package/dist/core/constraints/checkers/types.d.ts.map +1 -0
- package/dist/core/constraints/checkers/types.js +23 -0
- package/dist/core/constraints/checkers/types.js.map +1 -0
- package/dist/core/constraints/checkers/yagni.d.ts +8 -0
- package/dist/core/constraints/checkers/yagni.d.ts.map +1 -0
- package/dist/core/constraints/checkers/yagni.js +96 -0
- package/dist/core/constraints/checkers/yagni.js.map +1 -0
- package/dist/core/constraints/context-builder.d.ts +67 -0
- package/dist/core/constraints/context-builder.d.ts.map +1 -0
- package/dist/core/constraints/context-builder.js +294 -0
- package/dist/core/constraints/context-builder.js.map +1 -0
- package/dist/core/constraints/definitions/guidelines.d.ts +7 -0
- package/dist/core/constraints/definitions/guidelines.d.ts.map +1 -0
- package/dist/core/constraints/definitions/guidelines.js +641 -0
- package/dist/core/constraints/definitions/guidelines.js.map +1 -0
- package/dist/core/constraints/definitions/iron-laws.d.ts +7 -0
- package/dist/core/constraints/definitions/iron-laws.d.ts.map +1 -0
- package/dist/core/constraints/definitions/iron-laws.js +322 -0
- package/dist/core/constraints/definitions/iron-laws.js.map +1 -0
- package/dist/core/constraints/definitions/tips.d.ts +7 -0
- package/dist/core/constraints/definitions/tips.d.ts.map +1 -0
- package/dist/core/constraints/definitions/tips.js +62 -0
- package/dist/core/constraints/definitions/tips.js.map +1 -0
- package/dist/core/constraints/definitions.d.ts +8 -21
- package/dist/core/constraints/definitions.d.ts.map +1 -1
- package/dist/core/constraints/definitions.js +15 -1048
- package/dist/core/constraints/definitions.js.map +1 -1
- package/dist/core/constraints/doc-freshness/runner.d.ts.map +1 -1
- package/dist/core/constraints/doc-freshness/runner.js +0 -1
- package/dist/core/constraints/doc-freshness/runner.js.map +1 -1
- package/dist/core/constraints/index.d.ts +4 -5
- package/dist/core/constraints/index.d.ts.map +1 -1
- package/dist/core/constraints/index.js +1 -16
- package/dist/core/constraints/index.js.map +1 -1
- package/dist/core/constraints/interceptor.d.ts.map +1 -1
- package/dist/core/constraints/interceptor.js.map +1 -1
- package/dist/core/index.js +0 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/project-config-loader.d.ts +6 -4
- package/dist/core/project-config-loader.d.ts.map +1 -1
- package/dist/core/project-config-loader.js +46 -13
- package/dist/core/project-config-loader.js.map +1 -1
- package/dist/core/validators/check-handlers/command.d.ts +7 -0
- package/dist/core/validators/check-handlers/command.d.ts.map +1 -0
- package/dist/core/validators/check-handlers/command.js +58 -0
- package/dist/core/validators/check-handlers/command.js.map +1 -0
- package/dist/core/validators/check-handlers/file.d.ts +10 -0
- package/dist/core/validators/check-handlers/file.d.ts.map +1 -0
- package/dist/core/validators/check-handlers/file.js +128 -0
- package/dist/core/validators/check-handlers/file.js.map +1 -0
- package/dist/core/validators/check-handlers/http.d.ts +7 -0
- package/dist/core/validators/check-handlers/http.d.ts.map +1 -0
- package/dist/core/validators/check-handlers/http.js +88 -0
- package/dist/core/validators/check-handlers/http.js.map +1 -0
- package/dist/core/validators/check-handlers/output.d.ts +15 -0
- package/dist/core/validators/check-handlers/output.d.ts.map +1 -0
- package/dist/core/validators/check-handlers/output.js +152 -0
- package/dist/core/validators/check-handlers/output.js.map +1 -0
- package/dist/core/validators/checkpoint.d.ts +4 -72
- package/dist/core/validators/checkpoint.d.ts.map +1 -1
- package/dist/core/validators/checkpoint.js +21 -400
- package/dist/core/validators/checkpoint.js.map +1 -1
- package/dist/core/validators/cso.js +1 -1
- package/dist/core/validators/cso.js.map +1 -1
- package/dist/core/validators/passes-gate.js +2 -2
- package/dist/core/validators/passes-gate.js.map +1 -1
- package/dist/dashboard/stats.d.ts.map +1 -1
- package/dist/dashboard/types.d.ts.map +1 -1
- package/dist/evolution/auto-evolve.d.ts +1 -2
- package/dist/evolution/auto-evolve.d.ts.map +1 -1
- package/dist/evolution/auto-evolve.js +2 -1
- package/dist/evolution/auto-evolve.js.map +1 -1
- package/dist/failure/types.d.ts +5 -85
- package/dist/failure/types.d.ts.map +1 -1
- package/dist/failure/types.js +19 -115
- package/dist/failure/types.js.map +1 -1
- package/dist/gates/contract.d.ts.map +1 -1
- package/dist/gates/contract.js.map +1 -1
- package/dist/gates/index.d.ts.map +1 -1
- package/dist/gates/index.js.map +1 -1
- package/dist/gates/performance.js +1 -1
- package/dist/gates/performance.js.map +1 -1
- package/dist/gates/security.d.ts.map +1 -1
- package/dist/gates/security.js +1 -1
- package/dist/gates/security.js.map +1 -1
- package/dist/hooks/bootstrap.d.ts.map +1 -1
- package/dist/hooks/bootstrap.js +6 -48
- package/dist/hooks/bootstrap.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/knowledge/audit.d.ts.map +1 -1
- package/dist/knowledge/doctor.d.ts.map +1 -1
- package/dist/knowledge/doctor.js.map +1 -1
- package/dist/knowledge/import.d.ts.map +1 -1
- package/dist/knowledge/import.js +1 -1
- package/dist/knowledge/import.js.map +1 -1
- package/dist/knowledge/index-generator.d.ts.map +1 -1
- package/dist/knowledge/index-generator.js +0 -1
- package/dist/knowledge/index-generator.js.map +1 -1
- package/dist/knowledge/ingest.d.ts.map +1 -1
- package/dist/knowledge/ingest.js +1 -1
- package/dist/knowledge/ingest.js.map +1 -1
- package/dist/knowledge/lint.d.ts +1 -1
- package/dist/knowledge/lint.d.ts.map +1 -1
- package/dist/knowledge/lint.js +2 -2
- package/dist/knowledge/lint.js.map +1 -1
- package/dist/knowledge/primitives/code-structure.d.ts.map +1 -1
- package/dist/knowledge/primitives/code-structure.js +29 -12
- package/dist/knowledge/primitives/code-structure.js.map +1 -1
- package/dist/knowledge/query.d.ts.map +1 -1
- package/dist/knowledge/query.js.map +1 -1
- package/dist/knowledge/store.d.ts.map +1 -1
- package/dist/llm/adapter.d.ts +3 -3
- package/dist/llm/adapter.d.ts.map +1 -1
- package/dist/llm/adapter.js +3 -3
- package/dist/llm/adapter.js.map +1 -1
- package/dist/monitoring/analyzer-base.d.ts +50 -0
- package/dist/monitoring/analyzer-base.d.ts.map +1 -0
- package/dist/monitoring/analyzer-base.js +146 -0
- package/dist/monitoring/analyzer-base.js.map +1 -0
- package/dist/monitoring/constraint-doctor.d.ts +3 -46
- package/dist/monitoring/constraint-doctor.d.ts.map +1 -1
- package/dist/monitoring/constraint-doctor.js +11 -113
- package/dist/monitoring/constraint-doctor.js.map +1 -1
- package/dist/monitoring/constraint-evolver.d.ts +9 -63
- package/dist/monitoring/constraint-evolver.d.ts.map +1 -1
- package/dist/monitoring/constraint-evolver.js +8 -10
- package/dist/monitoring/constraint-evolver.js.map +1 -1
- package/dist/monitoring/diagnosis-rules.d.ts +18 -0
- package/dist/monitoring/diagnosis-rules.d.ts.map +1 -0
- package/dist/monitoring/diagnosis-rules.js +119 -0
- package/dist/monitoring/diagnosis-rules.js.map +1 -0
- package/dist/monitoring/knowledge-doctor.d.ts.map +1 -1
- package/dist/monitoring/knowledge-doctor.js.map +1 -1
- package/dist/monitoring/performance-analyzer.d.ts +0 -12
- package/dist/monitoring/performance-analyzer.d.ts.map +1 -1
- package/dist/monitoring/performance-analyzer.js +13 -93
- package/dist/monitoring/performance-analyzer.js.map +1 -1
- package/dist/monitoring/performance-collector.d.ts +0 -8
- package/dist/monitoring/performance-collector.d.ts.map +1 -1
- package/dist/monitoring/performance-collector.js +0 -21
- package/dist/monitoring/performance-collector.js.map +1 -1
- package/dist/monitoring/trace-analyzer.d.ts +0 -8
- package/dist/monitoring/trace-analyzer.d.ts.map +1 -1
- package/dist/monitoring/trace-analyzer.js +9 -91
- package/dist/monitoring/trace-analyzer.js.map +1 -1
- package/dist/presets/index.d.ts +1 -1
- package/dist/presets/index.d.ts.map +1 -1
- package/dist/presets/index.js +1 -4
- package/dist/presets/index.js.map +1 -1
- package/dist/presets/standard.d.ts +0 -9
- package/dist/presets/standard.d.ts.map +1 -1
- package/dist/presets/standard.js +1 -16
- package/dist/presets/standard.js.map +1 -1
- package/dist/safety/output-guardrail.d.ts +0 -1
- package/dist/safety/output-guardrail.d.ts.map +1 -1
- package/dist/safety/output-guardrail.js +0 -3
- package/dist/safety/output-guardrail.js.map +1 -1
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/types/constraint.d.ts +5 -59
- package/dist/types/constraint.d.ts.map +1 -1
- package/dist/types/constraint.js +1 -39
- package/dist/types/constraint.js.map +1 -1
- package/dist/types/failure.d.ts +89 -0
- package/dist/types/failure.d.ts.map +1 -0
- package/dist/types/failure.js +121 -0
- package/dist/types/failure.js.map +1 -0
- package/dist/types/index.d.ts +2 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +7 -6
- package/dist/types/index.js.map +1 -1
- package/dist/types/monitoring-types.d.ts +114 -0
- package/dist/types/monitoring-types.d.ts.map +1 -0
- package/dist/types/monitoring-types.js +10 -0
- package/dist/types/monitoring-types.js.map +1 -0
- package/dist/utils/detect-source-roots.js.map +1 -1
- package/dist/utils/file-walk.d.ts +33 -0
- package/dist/utils/file-walk.d.ts.map +1 -0
- package/dist/utils/file-walk.js +89 -0
- package/dist/utils/file-walk.js.map +1 -0
- package/dist/verification/rules-based.d.ts.map +1 -1
- package/dist/verification/rules-based.js.map +1 -1
- package/package.json +3 -7
- package/src/__tests__/checker-extra.test.ts +0 -30
- package/src/__tests__/checker.test.ts +0 -33
- package/src/__tests__/checkpoint.test.ts +46 -46
- package/src/__tests__/constraint-evolver.test.ts +22 -21
- package/src/__tests__/doctor-evolver.test.ts +3 -3
- package/src/__tests__/iron-laws.test.ts +0 -27
- package/src/__tests__/presets.test.ts +1 -40
- package/src/architecture/constraint-engine.ts +0 -5
- package/src/architecture/cross-project-checker.ts +6 -24
- package/src/cli/commands/__tests__/check.test.ts +3 -1
- package/src/cli/commands/__tests__/sync-docs.test.ts +77 -0
- package/src/cli/commands/__tests__/validate.test.ts +5 -0
- package/src/cli/commands/analyze-sessions.ts +31 -185
- package/src/cli/commands/check.ts +26 -225
- package/src/cli/commands/doc-freshness-check.ts +14 -25
- package/src/cli/commands/flow.ts +5 -3
- package/src/cli/commands/init.ts +3 -3
- package/src/cli/commands/posteval-plan.ts +0 -1
- package/src/cli/commands/release.ts +1 -1
- package/src/cli/commands/report.ts +2 -0
- package/src/cli/commands/spec-baseline-check.ts +12 -19
- package/src/cli/commands/sync-docs/agents-syncer.ts +280 -0
- package/src/cli/commands/sync-docs/capabilities-syncer.ts +229 -0
- package/src/cli/commands/sync-docs/context-syncer.ts +108 -0
- package/src/cli/commands/sync-docs/index.ts +355 -0
- package/src/cli/commands/sync-docs/preserve-block.ts +59 -0
- package/src/cli/commands/sync-docs/project-reader.ts +163 -0
- package/src/cli/commands/update-user-model.ts +23 -87
- package/src/cli/commands/validate.ts +6 -40
- package/src/cli/session-mining/corrections.ts +56 -0
- package/src/cli/session-mining/index.ts +13 -0
- package/src/cli/session-mining/text.ts +117 -0
- package/src/cli/session-mining/transcript.ts +107 -0
- package/src/constraints/__tests__/lifecycle-runner.test.ts +1 -1
- package/src/constraints/lifecycle-runner.ts +1 -1
- package/src/context/compaction.ts +2 -3
- package/src/context/knowledge-injector.ts +1 -1
- package/src/context/tool-output-budget.ts +1 -1
- package/src/core/constraints/capabilities-parser.ts +70 -0
- package/src/core/constraints/checker.ts +170 -779
- package/src/core/constraints/checkers/always-pass.ts +22 -0
- package/src/core/constraints/checkers/capability-sync.ts +71 -0
- package/src/core/constraints/checkers/context-doc-sync.ts +36 -0
- package/src/core/constraints/checkers/docs-freshness.ts +116 -0
- package/src/core/constraints/checkers/guideline-flags.ts +30 -0
- package/src/core/constraints/checkers/index.ts +114 -0
- package/src/core/constraints/checkers/iron-flags.ts +62 -0
- package/src/core/constraints/checkers/no-any-type.ts +42 -0
- package/src/core/constraints/checkers/no-bypass-checkpoint.ts +40 -0
- package/src/core/constraints/checkers/no-excuse-patterns.ts +24 -0
- package/src/core/constraints/checkers/no-fuzzy-completion-claim.ts +33 -0
- package/src/core/constraints/checkers/no-performative-agreement.ts +22 -0
- package/src/core/constraints/checkers/no-simplification-without-approval.ts +29 -0
- package/src/core/constraints/checkers/no-test-simplification.ts +28 -0
- package/src/core/constraints/checkers/test-coverage.ts +35 -0
- package/src/core/constraints/checkers/types.ts +54 -0
- package/src/core/constraints/checkers/yagni.ts +65 -0
- package/src/core/constraints/context-builder.ts +262 -0
- package/src/core/constraints/definitions/guidelines.ts +668 -0
- package/src/core/constraints/definitions/iron-laws.ts +333 -0
- package/src/core/constraints/definitions/tips.ts +63 -0
- package/src/core/constraints/definitions.ts +9 -1086
- package/src/core/constraints/doc-freshness/runner.ts +2 -3
- package/src/core/constraints/index.ts +1 -27
- package/src/core/constraints/interceptor.ts +0 -2
- package/src/core/index.ts +1 -1
- package/src/core/project-config-loader.ts +49 -13
- package/src/core/validators/check-handlers/command.ts +58 -0
- package/src/core/validators/check-handlers/file.ts +104 -0
- package/src/core/validators/check-handlers/http.ts +88 -0
- package/src/core/validators/check-handlers/output.ts +165 -0
- package/src/core/validators/checkpoint.ts +32 -407
- package/src/core/validators/cso.ts +1 -1
- package/src/core/validators/passes-gate.ts +2 -2
- package/src/dashboard/stats.ts +1 -1
- package/src/dashboard/types.ts +1 -1
- package/src/evolution/__tests__/auto-evolve.test.ts +1 -2
- package/src/evolution/auto-evolve.ts +3 -3
- package/src/failure/types.ts +5 -161
- package/src/gates/contract.ts +0 -1
- package/src/gates/index.ts +0 -2
- package/src/gates/performance.ts +1 -1
- package/src/gates/security.ts +1 -3
- package/src/hooks/bootstrap.ts +6 -16
- package/src/index.ts +4 -1
- package/src/knowledge/__tests__/lifecycle.test.ts +4 -1
- package/src/knowledge/audit.ts +1 -1
- package/src/knowledge/doctor.ts +0 -1
- package/src/knowledge/import.ts +2 -2
- package/src/knowledge/index-generator.ts +0 -1
- package/src/knowledge/ingest.ts +1 -2
- package/src/knowledge/lint.ts +2 -2
- package/src/knowledge/primitives/__tests__/code-structure-degrade.test.ts +24 -0
- package/src/knowledge/primitives/code-structure.ts +36 -12
- package/src/knowledge/query.ts +0 -3
- package/src/knowledge/store.ts +1 -1
- package/src/llm/adapter.ts +3 -3
- package/src/monitoring/analyzer-base.ts +112 -0
- package/src/monitoring/constraint-doctor.ts +14 -175
- package/src/monitoring/constraint-evolver.ts +20 -92
- package/src/monitoring/diagnosis-rules.ts +132 -0
- package/src/monitoring/knowledge-doctor.ts +0 -1
- package/src/monitoring/performance-analyzer.ts +22 -72
- package/src/monitoring/performance-collector.ts +0 -22
- package/src/monitoring/trace-analyzer.ts +17 -73
- package/src/presets/__tests__/standard.test.ts +2 -17
- package/src/presets/index.ts +1 -3
- package/src/presets/standard.ts +1 -26
- package/src/safety/output-guardrail.ts +0 -4
- package/src/tools/registry.ts +1 -1
- package/src/types/__tests__/types.test.ts +1 -33
- package/src/types/constraint.ts +6 -75
- package/src/types/failure.ts +165 -0
- package/src/types/index.ts +7 -5
- package/src/types/monitoring-types.ts +150 -0
- package/src/utils/detect-source-roots.ts +1 -1
- package/src/utils/file-walk.ts +78 -0
- package/src/verification/rules-based.ts +0 -1
- package/bin/harness-knowledge-capture.js +0 -99
- package/bin/harness-knowledge-check.js +0 -164
- package/bin/harness-knowledge-track.js +0 -118
- package/dist/cli/commands/sync-docs.d.ts.map +0 -1
- package/dist/cli/commands/sync-docs.js +0 -1074
- package/dist/cli/commands/sync-docs.js.map +0 -1
- package/dist/constraints/index.d.ts +0 -4
- package/dist/constraints/index.d.ts.map +0 -1
- package/dist/constraints/index.js +0 -20
- package/dist/constraints/index.js.map +0 -1
- package/dist/core/constraints/doc-freshness/auto-fix.d.ts +0 -23
- package/dist/core/constraints/doc-freshness/auto-fix.d.ts.map +0 -1
- package/dist/core/constraints/doc-freshness/auto-fix.js +0 -59
- package/dist/core/constraints/doc-freshness/auto-fix.js.map +0 -1
- package/dist/core/constraints/prompt-injection.d.ts +0 -16
- package/dist/core/constraints/prompt-injection.d.ts.map +0 -1
- package/dist/core/constraints/prompt-injection.js +0 -69
- package/dist/core/constraints/prompt-injection.js.map +0 -1
- package/dist/core/spec/index.d.ts +0 -7
- package/dist/core/spec/index.d.ts.map +0 -1
- package/dist/core/spec/index.js.map +0 -1
- package/dist/governance/executor.d.ts +0 -45
- package/dist/governance/executor.d.ts.map +0 -1
- package/dist/governance/executor.js +0 -243
- package/dist/governance/executor.js.map +0 -1
- package/dist/governance/index.d.ts +0 -9
- package/dist/governance/index.d.ts.map +0 -1
- package/dist/governance/index.js +0 -13
- package/dist/governance/index.js.map +0 -1
- package/dist/governance/types.d.ts +0 -46
- package/dist/governance/types.d.ts.map +0 -1
- package/dist/governance/types.js +0 -9
- package/dist/governance/types.js.map +0 -1
- package/dist/tools/definitions/definitions/core/code/fingerprint.sh +0 -273
- package/dist/tools/definitions/definitions/core/code/fingerprint.yml +0 -72
- package/dist/tools/definitions/definitions/core/code/parse.yml +0 -68
- package/dist/tools/definitions/definitions/core/code/register-language.sh +0 -475
- package/dist/tools/definitions/definitions/core/code/register-language.yml +0 -74
- package/dist/tools/definitions/definitions/core/docker/build.yml +0 -73
- package/dist/tools/definitions/definitions/core/docker/run.yml +0 -81
- package/dist/tools/definitions/definitions/core/file/copy.yml +0 -88
- package/dist/tools/definitions/definitions/core/file/read.yml +0 -69
- package/dist/tools/definitions/definitions/core/file/write.yml +0 -75
- package/dist/tools/definitions/definitions/core/git/branch.yml +0 -61
- package/dist/tools/definitions/definitions/core/git/cleanup-worktree.yml +0 -50
- package/dist/tools/definitions/definitions/core/git/clone.yml +0 -69
- package/dist/tools/definitions/definitions/core/git/commit.yml +0 -65
- package/dist/tools/definitions/definitions/core/git/push.yml +0 -79
- package/dist/tools/definitions/definitions/core/git/worktree.yml +0 -96
- package/dist/tools/definitions/definitions/core/notification/notify.sh +0 -152
- package/dist/tools/definitions/definitions/core/notification/notify.yml +0 -60
- package/dist/tools/definitions/definitions/core/npm/build.yml +0 -75
- package/dist/tools/definitions/definitions/core/npm/install.yml +0 -58
- package/dist/tools/definitions/definitions/core/npm/test.yml +0 -75
- package/dist/tools/definitions/definitions/core/validation/check-reuse.yml +0 -170
- package/dist/tools/definitions/definitions/core/validation/validate-handlers.yml +0 -118
- package/dist/tools/definitions/definitions/core/validation/validate-readme-stats.yml +0 -155
- package/dist/tools/definitions/definitions/core/validation/validate-yaml-syntax.yml +0 -134
- package/dist/tools/definitions/definitions/ext/browser/browser-automate.sh +0 -255
- package/dist/tools/definitions/definitions/ext/browser/browser-automate.yml +0 -166
- package/dist/tools/definitions/definitions/ext/browser/browser-close.sh +0 -104
- package/dist/tools/definitions/definitions/ext/browser/browser-close.yml +0 -55
- package/dist/tools/definitions/definitions/ext/browser/browser-mcp-debug.sh +0 -682
- package/dist/tools/definitions/definitions/ext/browser/browser-mcp-debug.yml +0 -167
- package/dist/tools/definitions/definitions/ext/browser/browser-start.sh +0 -101
- package/dist/tools/definitions/definitions/ext/browser/browser-start.yml +0 -62
- package/dist/tools/definitions/definitions/registry.json +0 -795
- package/dist/tools/definitions/definitions/std/README.md +0 -350
- package/dist/tools/definitions/definitions/std/analysis/analyze-codebase.yml +0 -72
- package/dist/tools/definitions/definitions/std/analysis/analyze-diff.yml +0 -182
- package/dist/tools/definitions/definitions/std/analysis/analyze-git-diff.yml +0 -70
- package/dist/tools/definitions/definitions/std/analysis/analyze-impact.yml +0 -78
- package/dist/tools/definitions/definitions/std/analysis/analyze-requirements.yml +0 -105
- package/dist/tools/definitions/definitions/std/analysis/brainstorm-options.yml +0 -106
- package/dist/tools/definitions/definitions/std/analysis/build-graph.yml +0 -154
- package/dist/tools/definitions/definitions/std/analysis/clarify-requirements.yml +0 -90
- package/dist/tools/definitions/definitions/std/analysis/detect-context.yml +0 -109
- package/dist/tools/definitions/definitions/std/analysis/detect-layers.yml +0 -125
- package/dist/tools/definitions/definitions/std/analysis/generate-tour.yml +0 -102
- package/dist/tools/definitions/definitions/std/analysis/search-enhance.yml +0 -105
- package/dist/tools/definitions/definitions/std/backlog/add.yml +0 -51
- package/dist/tools/definitions/definitions/std/backlog/decide.yml +0 -39
- package/dist/tools/definitions/definitions/std/backlog/github-sync.yml +0 -161
- package/dist/tools/definitions/definitions/std/backlog/list.yml +0 -53
- package/dist/tools/definitions/definitions/std/backlog/load.yml +0 -46
- package/dist/tools/definitions/definitions/std/backlog/resolve.yml +0 -37
- package/dist/tools/definitions/definitions/std/backlog/update.yml +0 -42
- package/dist/tools/definitions/definitions/std/bugfix/diagnose.yml +0 -68
- package/dist/tools/definitions/definitions/std/bugfix/fix.yml +0 -66
- package/dist/tools/definitions/definitions/std/bugfix/verify.yml +0 -69
- package/dist/tools/definitions/definitions/std/constraint/check-decomposition.yml +0 -103
- package/dist/tools/definitions/definitions/std/constraint/check-feature-list.yml +0 -77
- package/dist/tools/definitions/definitions/std/constraint/check-progress.yml +0 -97
- package/dist/tools/definitions/definitions/std/constraint/generate-report.yml +0 -147
- package/dist/tools/definitions/definitions/std/deploy/commit-push.yml +0 -33
- package/dist/tools/definitions/definitions/std/deploy/deploy-backend.yml +0 -37
- package/dist/tools/definitions/definitions/std/deploy/deploy-frontend.yml +0 -37
- package/dist/tools/definitions/definitions/std/deploy/rollback.yml +0 -148
- package/dist/tools/definitions/definitions/std/design/analyze-architecture-impact.yml +0 -113
- package/dist/tools/definitions/definitions/std/design/design-api.yml +0 -55
- package/dist/tools/definitions/definitions/std/design/design-architecture.yml +0 -97
- package/dist/tools/definitions/definitions/std/design/design-db.yml +0 -81
- package/dist/tools/definitions/definitions/std/design/generate-spec.yml +0 -182
- package/dist/tools/definitions/definitions/std/development/develop-api.yml +0 -85
- package/dist/tools/definitions/definitions/std/development/develop-backend.yml +0 -88
- package/dist/tools/definitions/definitions/std/development/develop-frontend.yml +0 -87
- package/dist/tools/definitions/definitions/std/development/develop-shared-types.yml +0 -74
- package/dist/tools/definitions/definitions/std/development/develop-task.yml +0 -122
- package/dist/tools/definitions/definitions/std/development/develop-tests.yml +0 -76
- package/dist/tools/definitions/definitions/std/development/execute-batch.yml +0 -152
- package/dist/tools/definitions/definitions/std/development/fix-issues.yml +0 -100
- package/dist/tools/definitions/definitions/std/development/implement-task.yml +0 -124
- package/dist/tools/definitions/definitions/std/development/review-fix-cycle.yml +0 -232
- package/dist/tools/definitions/definitions/std/evolution/implement.yml +0 -125
- package/dist/tools/definitions/definitions/std/evolution/prioritize.yml +0 -112
- package/dist/tools/definitions/definitions/std/evolution/report-gap.yml +0 -166
- package/dist/tools/definitions/definitions/std/file/read.yml +0 -21
- package/dist/tools/definitions/definitions/std/governance/aggregate-opinions.sh +0 -201
- package/dist/tools/definitions/definitions/std/governance/aggregate-opinions.yml +0 -79
- package/dist/tools/definitions/definitions/std/governance/audit-task.yml +0 -178
- package/dist/tools/definitions/definitions/std/governance/cast-vote.yml +0 -129
- package/dist/tools/definitions/definitions/std/governance/collect-issues.yml +0 -16
- package/dist/tools/definitions/definitions/std/governance/create-signed-document.yml +0 -23
- package/dist/tools/definitions/definitions/std/governance/create-voting-session.yml +0 -101
- package/dist/tools/definitions/definitions/std/governance/define-stance.sh +0 -243
- package/dist/tools/definitions/definitions/std/governance/define-stance.yml +0 -82
- package/dist/tools/definitions/definitions/std/governance/generate-review-report.yml +0 -23
- package/dist/tools/definitions/definitions/std/governance/impeach.yml +0 -179
- package/dist/tools/definitions/definitions/std/governance/multi-stance-review.yml +0 -154
- package/dist/tools/definitions/definitions/std/governance/prepare-artifact.yml +0 -20
- package/dist/tools/definitions/definitions/std/governance/review-spec-approval.yml +0 -262
- package/dist/tools/definitions/definitions/std/governance/rollback.yml +0 -186
- package/dist/tools/definitions/definitions/std/governance/stance-review.yml +0 -149
- package/dist/tools/definitions/definitions/std/governance/track-effect.yml +0 -199
- package/dist/tools/definitions/definitions/std/governance/vote-tally.yml +0 -144
- package/dist/tools/definitions/definitions/std/patch/execute.yml +0 -51
- package/dist/tools/definitions/definitions/std/planning/generate-tasks.yml +0 -36
- package/dist/tools/definitions/definitions/std/planning/load-tasks.yml +0 -44
- package/dist/tools/definitions/definitions/std/planning/split-batch.yml +0 -481
- package/dist/tools/definitions/definitions/std/planning/split-tasks.yml +0 -359
- package/dist/tools/definitions/definitions/std/planning/update-tasks.yml +0 -51
- package/dist/tools/definitions/definitions/std/planning/validate-tasks.yml +0 -46
- package/dist/tools/definitions/definitions/std/project/decide-next-workflow.yml +0 -38
- package/dist/tools/definitions/definitions/std/project/load-state.yml +0 -31
- package/dist/tools/definitions/definitions/std/project/save-state.yml +0 -32
- package/dist/tools/definitions/definitions/std/quality/check-quality.yml +0 -241
- package/dist/tools/definitions/definitions/std/quality/debug-systematic.yml +0 -163
- package/dist/tools/definitions/definitions/std/quality/handle-feedback.yml +0 -108
- package/dist/tools/definitions/definitions/std/quality/review-code.yml +0 -128
- package/dist/tools/definitions/definitions/std/quality/review-spec.yml +0 -140
- package/dist/tools/definitions/definitions/std/quality/review-task.yml +0 -190
- package/dist/tools/definitions/definitions/std/quality/run-tests.yml +0 -80
- package/dist/tools/definitions/definitions/std/quick/analyze.yml +0 -56
- package/dist/tools/definitions/definitions/std/quick/implement.yml +0 -67
- package/dist/tools/definitions/definitions/std/quick/verify.yml +0 -71
- package/dist/tools/definitions/definitions/std/verification/verify_completion.yml +0 -113
- package/dist/tools/definitions/definitions/std/verification/wait-condition.yml +0 -107
- package/dist/types/iron-law.d.ts +0 -25
- package/dist/types/iron-law.d.ts.map +0 -1
- package/dist/types/iron-law.js +0 -16
- package/dist/types/iron-law.js.map +0 -1
- package/src/cli/commands/sync-docs.ts +0 -1175
- package/src/constraints/index.ts +0 -3
- package/src/core/constraints/__tests__/prompt-injection.test.ts +0 -89
- package/src/core/constraints/doc-freshness/auto-fix.ts +0 -69
- package/src/core/constraints/prompt-injection.ts +0 -73
- package/src/core/spec/index.ts +0 -7
- package/src/governance/CONTEXT.md +0 -22
- package/src/governance/__tests__/executor.test.ts +0 -249
- package/src/governance/executor.ts +0 -229
- package/src/governance/index.ts +0 -13
- package/src/governance/types.ts +0 -53
- package/src/tools/core/package.json +0 -7
- package/src/tools/core/pnpm-lock.yaml +0 -232
- package/src/types/iron-law.ts +0 -50
|
@@ -17,17 +17,14 @@ import {
|
|
|
17
17
|
ConstraintViolationError,
|
|
18
18
|
} from '../../types/constraint';
|
|
19
19
|
import type { ExecutionTrace } from '../../types/trace';
|
|
20
|
-
import { getTraceCollector } from '../../monitoring/traces';
|
|
21
20
|
import { IRON_LAWS, GUIDELINES, TIPS } from './definitions';
|
|
22
|
-
import type { MergedConstraintsConfig
|
|
23
|
-
import { FreshnessRunner, type FreshnessCheckResult } from './doc-freshness/runner';
|
|
21
|
+
import type { MergedConstraintsConfig } from '../../types/project-config';
|
|
24
22
|
import { normalizeTriggers } from '../../utils/exec';
|
|
25
23
|
import { runCommand } from '../../utils/exec';
|
|
26
|
-
import { existsSync, readFileSync, readdirSync, statSync } from 'fs';
|
|
27
24
|
import { join, relative } from 'path';
|
|
28
|
-
import * as yaml from 'js-yaml';
|
|
29
25
|
import { CheckCache } from './check-cache';
|
|
30
|
-
import {
|
|
26
|
+
import { findTsSourceFiles } from '../../utils/file-walk';
|
|
27
|
+
import { getConstraintCheck, type CheckEnv } from './checkers';
|
|
31
28
|
|
|
32
29
|
/**
|
|
33
30
|
* 例外名称 → ConstraintContext 中布尔字段的映射
|
|
@@ -59,6 +56,18 @@ const EXCEPTION_FIELD_MAP: Record<string, keyof ConstraintContext> = {
|
|
|
59
56
|
existing_design: 'isExistingDesign',
|
|
60
57
|
};
|
|
61
58
|
|
|
59
|
+
/**
|
|
60
|
+
* trace 记录器最小接口(工单 15:core→monitoring 循环消除)
|
|
61
|
+
*
|
|
62
|
+
* checker 不再值导入 monitoring/traces 的单例;生产调用方经
|
|
63
|
+
* setTraceRecorder 注入真实收集器,默认 no-op。
|
|
64
|
+
*/
|
|
65
|
+
export interface TraceRecorder {
|
|
66
|
+
record(trace: ExecutionTrace): void;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const NOOP_TRACE_RECORDER: TraceRecorder = { record: () => undefined };
|
|
70
|
+
|
|
62
71
|
/**
|
|
63
72
|
* 约束检查器
|
|
64
73
|
*/
|
|
@@ -68,11 +77,51 @@ export class ConstraintChecker {
|
|
|
68
77
|
/** 自定义约束配置(项目级) */
|
|
69
78
|
private customConfig: MergedConstraintsConfig | null = null;
|
|
70
79
|
|
|
71
|
-
/** 检查结果缓存(S7
|
|
80
|
+
/** 检查结果缓存(S7:src 扫描等重复 I/O,TTL=1s 防跨测试污染) */
|
|
72
81
|
private cache: CheckCache = new CheckCache({ ttlMs: 1000 });
|
|
73
82
|
|
|
83
|
+
/**
|
|
84
|
+
* run 级 memo(工单 18):一次 checkConstraints/checkConstraintsSafe 内
|
|
85
|
+
* git diff 等命令只执行一次;run 外直接调用私有检查方法时不 memo(恒新鲜)。
|
|
86
|
+
*/
|
|
87
|
+
private runCache: Map<string, Promise<string>> | null = null;
|
|
88
|
+
|
|
89
|
+
/** trace 记录器(注入式,默认 no-op;生产入口经 setTraceRecorder 接入真实收集器) */
|
|
90
|
+
private traceRecorder: TraceRecorder = NOOP_TRACE_RECORDER;
|
|
91
|
+
|
|
74
92
|
private constructor() {}
|
|
75
93
|
|
|
94
|
+
/**
|
|
95
|
+
* run 内 memoize;无活动 run 时直接执行(工单 18)
|
|
96
|
+
*/
|
|
97
|
+
private memoRun(key: string, fn: () => Promise<string>): Promise<string> {
|
|
98
|
+
if (!this.runCache) return fn();
|
|
99
|
+
let pending = this.runCache.get(key);
|
|
100
|
+
if (!pending) {
|
|
101
|
+
pending = fn();
|
|
102
|
+
this.runCache.set(key, pending);
|
|
103
|
+
}
|
|
104
|
+
return pending;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* staged 全量 diff(同一次 run 内只执行一次 git 命令,工单 18)
|
|
109
|
+
*/
|
|
110
|
+
private getStagedDiff(projectPath: string): Promise<string> {
|
|
111
|
+
return this.memoRun(`git_diff_staged:${projectPath}`, () =>
|
|
112
|
+
runCommand('git diff --cached', projectPath)
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* staged 变更文件名列表(同一次 run 内只执行一次 git 命令,工单 18)
|
|
118
|
+
*/
|
|
119
|
+
private getStagedDiffNames(projectPath: string): Promise<string> {
|
|
120
|
+
return this.memoRun(`git_diff_staged_names:${projectPath}`, () =>
|
|
121
|
+
runCommand('git diff --cached --name-only', projectPath)
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
76
125
|
/**
|
|
77
126
|
* 获取单例实例
|
|
78
127
|
*/
|
|
@@ -83,6 +132,13 @@ export class ConstraintChecker {
|
|
|
83
132
|
return ConstraintChecker.instance;
|
|
84
133
|
}
|
|
85
134
|
|
|
135
|
+
/**
|
|
136
|
+
* 注入 trace 记录器(工单 15:解耦 core 对 monitoring 的值依赖)
|
|
137
|
+
*/
|
|
138
|
+
setTraceRecorder(recorder: TraceRecorder): void {
|
|
139
|
+
this.traceRecorder = recorder;
|
|
140
|
+
}
|
|
141
|
+
|
|
86
142
|
/**
|
|
87
143
|
* 设置项目级约束配置
|
|
88
144
|
*
|
|
@@ -191,7 +247,7 @@ export class ConstraintChecker {
|
|
|
191
247
|
* 记录约束检查的 trace
|
|
192
248
|
*/
|
|
193
249
|
private recordTrace(
|
|
194
|
-
collector:
|
|
250
|
+
collector: TraceRecorder,
|
|
195
251
|
constraint: Constraint,
|
|
196
252
|
checkResult: ConstraintResult,
|
|
197
253
|
context: ConstraintContext
|
|
@@ -212,679 +268,32 @@ export class ConstraintChecker {
|
|
|
212
268
|
}
|
|
213
269
|
|
|
214
270
|
/**
|
|
215
|
-
*
|
|
271
|
+
* 检查约束前置条件(工单 21:分发至 checkers/ 注册表)
|
|
272
|
+
*
|
|
273
|
+
* 未注册的约束默认通过(保持历史 default 分支语义)。
|
|
216
274
|
*/
|
|
217
275
|
private async checkPrecondition(
|
|
218
276
|
constraint: Constraint,
|
|
219
277
|
context: ConstraintContext
|
|
220
278
|
): Promise<boolean> {
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
switch (constraint.id) {
|
|
224
|
-
// Iron Laws
|
|
225
|
-
case 'no_bypass_checkpoint':
|
|
226
|
-
// 检查代码中是否有 skip/bypass 关键词
|
|
227
|
-
return await this.checkNoBypassCheckpoint(context);
|
|
228
|
-
|
|
229
|
-
case 'no_self_approval':
|
|
230
|
-
// 检查是否有测试证据
|
|
231
|
-
return context.hasTest === true;
|
|
232
|
-
|
|
233
|
-
case 'no_completion_without_verification':
|
|
234
|
-
// 检查是否有验证证据
|
|
235
|
-
return context.hasVerificationEvidence === true;
|
|
236
|
-
|
|
237
|
-
case 'no_test_simplification':
|
|
238
|
-
// 检查是否删除了测试
|
|
239
|
-
return await this.checkNoTestSimplification(projectPath);
|
|
240
|
-
|
|
241
|
-
case 'incremental_progress':
|
|
242
|
-
// 检查是否一次做多个任务(需要 context 提供信息)
|
|
243
|
-
// undefined = 未验证 → Iron Law 必须显式确认
|
|
244
|
-
return context.hasSingleTask === true;
|
|
245
|
-
|
|
246
|
-
case 'verify_external_capability':
|
|
247
|
-
// 检查是否已验证外部能力
|
|
248
|
-
// undefined = 未验证 → Iron Law 必须显式确认
|
|
249
|
-
return context.hasExternalCapabilityVerification === true;
|
|
250
|
-
|
|
251
|
-
case 'no_implementation_without_requirement_review':
|
|
252
|
-
// 检查实现后是否对比需求验证
|
|
253
|
-
return context.hasRequirementReview === true;
|
|
254
|
-
|
|
255
|
-
case 'no_implementation_without_requirement':
|
|
256
|
-
// 检查是否有需求文档
|
|
257
|
-
return context.hasRequirement === true;
|
|
258
|
-
|
|
259
|
-
case 'prefer_worktree':
|
|
260
|
-
// 检查是否在 worktree 中执行
|
|
261
|
-
return context.hasWorktree === true;
|
|
262
|
-
|
|
263
|
-
case 'no_fuzzy_completion_claim':
|
|
264
|
-
// 检查完成声明是否包含模糊词(含"我记得""之前说""大部分"等无验证模式)
|
|
265
|
-
return this.checkNoFuzzyWords(context.completionClaimText || '');
|
|
266
|
-
|
|
267
|
-
case 'no_claim_without_evidence':
|
|
268
|
-
// 检查是否提供了验证证据(test output / file check / spec AC matrix)
|
|
269
|
-
return context.hasVerificationEvidence === true ||
|
|
270
|
-
(context.taskDescription || '').includes('test') ||
|
|
271
|
-
context.hasTest === true;
|
|
272
|
-
|
|
273
|
-
case 'no_delete_without_context':
|
|
274
|
-
// 检查删除前是否审查了设计文档
|
|
275
|
-
return context.hasRequirementReview === true ||
|
|
276
|
-
context.hasRequirement === true ||
|
|
277
|
-
context.isExistingDesign === true;
|
|
278
|
-
|
|
279
|
-
case 'no_performative_agreement':
|
|
280
|
-
// 检查是否有表演性同意(主要由 promptInjection 驱动,这里做辅助检查)
|
|
281
|
-
return this.checkNoPerformativePatterns(context.taskDescription || '');
|
|
282
|
-
|
|
283
|
-
case 'two_stage_review_required':
|
|
284
|
-
// 检查是否完成两阶段审查
|
|
285
|
-
return context.hasTwoStageReview === true;
|
|
286
|
-
|
|
287
|
-
// Guidelines
|
|
288
|
-
case 'no_fix_without_root_cause':
|
|
289
|
-
// 检查是否有根本原因调查
|
|
290
|
-
return context.hasRootCauseInvestigation === true;
|
|
291
|
-
|
|
292
|
-
case 'no_code_without_test':
|
|
293
|
-
// 检查是否有失败的测试
|
|
294
|
-
return context.hasFailingTest === true;
|
|
295
|
-
|
|
296
|
-
case 'no_any_type':
|
|
297
|
-
// 检查代码中是否有 any 类型
|
|
298
|
-
return await this.checkNoAnyType(projectPath, context.changedFiles);
|
|
299
|
-
|
|
300
|
-
case 'simplest_solution_first':
|
|
301
|
-
// 检查是否已检查本地数据源
|
|
302
|
-
return context.hasReuseCheck === true;
|
|
303
|
-
|
|
304
|
-
case 'no_creation_without_reuse_check':
|
|
305
|
-
// 检查是否已进行复用检查
|
|
306
|
-
return context.hasReuseCheck === true;
|
|
307
|
-
|
|
308
|
-
case 'capability_sync':
|
|
309
|
-
// 检查 CAPABILITIES.md 是否更新
|
|
310
|
-
return await this.checkCapabilitySync(projectPath);
|
|
311
|
-
|
|
312
|
-
case 'no_simplification_without_approval':
|
|
313
|
-
// 检查是否简化了逻辑
|
|
314
|
-
return await this.checkNoSimplificationWithoutApproval(projectPath);
|
|
315
|
-
|
|
316
|
-
case 'no_skill_without_test':
|
|
317
|
-
// 检查是否有测试
|
|
318
|
-
return context.hasTest === true;
|
|
319
|
-
|
|
320
|
-
case 'test_coverage_required':
|
|
321
|
-
// 检查测试覆盖率
|
|
322
|
-
return await this.checkTestCoverage(projectPath);
|
|
323
|
-
|
|
324
|
-
case 'context_doc_sync':
|
|
325
|
-
return await this.checkContextDocSync(projectPath);
|
|
326
|
-
|
|
327
|
-
case 'docs_freshness':
|
|
328
|
-
return await this.checkDocsFreshness(projectPath);
|
|
329
|
-
|
|
330
|
-
case 'no_excuse_patterns':
|
|
331
|
-
// 检查是否使用了借口模式
|
|
332
|
-
return this.checkNoExcusePatterns(context.completionClaimText || context.taskDescription || '');
|
|
333
|
-
|
|
334
|
-
case 'yagni_check':
|
|
335
|
-
// 检查是否有过度设计(主要由 promptInjection 驱动)
|
|
336
|
-
return this.checkYagni(projectPath, context.changedFiles);
|
|
337
|
-
|
|
338
|
-
// Mnilax guidelines + first-principles (injectPrompt=true, behavior-level, always pass — post-checked)
|
|
339
|
-
case 'surgical_changes_only':
|
|
340
|
-
case 'no_model_for_deterministic':
|
|
341
|
-
case 'no_conflict_blending':
|
|
342
|
-
case 'read_before_write':
|
|
343
|
-
case 'follow_conventions':
|
|
344
|
-
case 'first_principles_first':
|
|
345
|
-
case 'fix_the_problem_not_the_gate':
|
|
346
|
-
case 'diagnosis_to_fix_gate':
|
|
347
|
-
// Guideline: behavior constraints, enforced via promptInjection + post-check
|
|
348
|
-
return true;
|
|
349
|
-
|
|
350
|
-
// Tips - 总是返回 true(仅提示)
|
|
351
|
-
case 'readme_required':
|
|
352
|
-
return true;
|
|
353
|
-
|
|
354
|
-
case 'doc_required_for_public_api':
|
|
355
|
-
return true;
|
|
356
|
-
|
|
357
|
-
default:
|
|
358
|
-
// 未知约束,默认通过
|
|
359
|
-
return true;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
/**
|
|
364
|
-
* 检查文本中是否包含模糊词
|
|
365
|
-
*/
|
|
366
|
-
private checkNoFuzzyWords(text: string): boolean {
|
|
367
|
-
if (!text) return true; // 没有文本时默认通过(由其他检查覆盖)
|
|
368
|
-
const fuzzyPatterns = [
|
|
369
|
-
/应该没问题/,
|
|
370
|
-
/应该可以/,
|
|
371
|
-
/大概/,
|
|
372
|
-
/可能/,
|
|
373
|
-
/好像/,
|
|
374
|
-
/似乎/,
|
|
375
|
-
/差不多/,
|
|
376
|
-
/基本完成/,
|
|
377
|
-
/大部分/,
|
|
378
|
-
// audit-learned (2026-05-18): unverified completion claims
|
|
379
|
-
/我记得删[过掉]了/,
|
|
380
|
-
/之前说删了/,
|
|
381
|
-
/已删除.*但/,
|
|
382
|
-
/大部分实现/,
|
|
383
|
-
/大部分完成/,
|
|
384
|
-
/已修复.*但/,
|
|
385
|
-
];
|
|
386
|
-
return !fuzzyPatterns.some(p => p.test(text));
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
/**
|
|
390
|
-
* 检查文本中是否包含表演性同意模式
|
|
391
|
-
*/
|
|
392
|
-
private checkNoPerformativePatterns(text: string): boolean {
|
|
393
|
-
if (!text) return true;
|
|
394
|
-
// 检查是否只有"好的/明白了"等同意词,没有后续分析
|
|
395
|
-
const performativeStart = /^(好的[,,]*\s*我[来去]做|明白了[,,]*|没问题[,,]*|ok[,,]*\s*i.?ll)/i;
|
|
396
|
-
// 如果以表演性模式开头,且总长度很短(< 50 字符),视为表演性同意
|
|
397
|
-
if (performativeStart.test(text) && text.length < 100) {
|
|
398
|
-
return false;
|
|
399
|
-
}
|
|
400
|
-
return true;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
/**
|
|
404
|
-
* 检查文本中是否包含借口模式
|
|
405
|
-
*/
|
|
406
|
-
private checkNoExcusePatterns(text: string): boolean {
|
|
407
|
-
if (!text) return true;
|
|
408
|
-
const excusePatterns = [
|
|
409
|
-
/稍后修复/,
|
|
410
|
-
/小问题/,
|
|
411
|
-
/不影响功能/,
|
|
412
|
-
/以后再说/,
|
|
413
|
-
/先这样/,
|
|
414
|
-
/临时方案/,
|
|
415
|
-
/暂时这样/,
|
|
416
|
-
];
|
|
417
|
-
return !excusePatterns.some(p => p.test(text));
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
/**
|
|
421
|
-
* 检查 YAGNI:过度设计信号
|
|
422
|
-
*
|
|
423
|
-
* 检查是否存在只有一个实现的 interface/abstract class。
|
|
424
|
-
* 主要由 promptInjection 驱动,这里是辅助检查。
|
|
425
|
-
*/
|
|
426
|
-
private async checkYagni(
|
|
427
|
-
projectPath?: string,
|
|
428
|
-
changedFiles?: string[]
|
|
429
|
-
): Promise<boolean> {
|
|
430
|
-
// 无上下文时默认通过(主要由 promptInjection 驱动)
|
|
431
|
-
if (!projectPath || !changedFiles || changedFiles.length === 0) return true;
|
|
432
|
-
|
|
433
|
-
try {
|
|
434
|
-
const path = await import('path');
|
|
435
|
-
const fs = await import('fs');
|
|
436
|
-
|
|
437
|
-
for (const file of changedFiles) {
|
|
438
|
-
if (!file.endsWith('.ts') && !file.endsWith('.tsx')) continue;
|
|
439
|
-
|
|
440
|
-
const filePath = path.join(projectPath, file);
|
|
441
|
-
if (!fs.existsSync(filePath)) continue;
|
|
442
|
-
|
|
443
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
444
|
-
|
|
445
|
-
// 检查是否有 export interface/abstract class
|
|
446
|
-
const hasInterface = /export\s+(?:default\s+)?interface\s+(\w+)/g;
|
|
447
|
-
const hasAbstract = /export\s+(?:default\s+)?abstract\s+class\s+(\w+)/g;
|
|
448
|
-
|
|
449
|
-
const interfaces = [...content.matchAll(hasInterface)].map(m => m[1]);
|
|
450
|
-
const abstracts = [...content.matchAll(hasAbstract)].map(m => m[1]);
|
|
451
|
-
|
|
452
|
-
const exportedTypes = [...interfaces, ...abstracts];
|
|
453
|
-
|
|
454
|
-
for (const typeName of exportedTypes) {
|
|
455
|
-
// 检查同一个 typeName 的 implements/extends 出现次数
|
|
456
|
-
const implPattern = new RegExp(`(?:implements|extends)\\s+${typeName}\\b`, 'g');
|
|
457
|
-
// 在整个项目中搜索(简化版:只在 changedFiles 中搜索)
|
|
458
|
-
let implCount = 0;
|
|
459
|
-
for (const f of changedFiles) {
|
|
460
|
-
if (!f.endsWith('.ts') && !f.endsWith('.tsx')) continue;
|
|
461
|
-
const fp = path.join(projectPath, f);
|
|
462
|
-
if (!fs.existsSync(fp)) continue;
|
|
463
|
-
const fc = fs.readFileSync(fp, 'utf-8');
|
|
464
|
-
const matches = fc.match(implPattern);
|
|
465
|
-
if (matches) implCount += matches.length;
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
// 只有一个实现者 → YAGNI 违规
|
|
469
|
-
if (implCount <= 1) {
|
|
470
|
-
return false;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
} catch {
|
|
475
|
-
// 文件读取失败,默认通过
|
|
476
|
-
return true;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
return true;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
/**
|
|
483
|
-
* 检查 no_bypass_checkpoint:检查代码中是否有 skip/bypass 关键词
|
|
484
|
-
*/
|
|
485
|
-
private async checkNoBypassCheckpoint(context: ConstraintContext): Promise<boolean> {
|
|
486
|
-
const changedFiles = context.changedFiles || [];
|
|
487
|
-
|
|
488
|
-
if (changedFiles.length === 0) {
|
|
489
|
-
return true; // 无变更文件,默认通过
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
// 检查文件内容是否有 skip/bypass 关键词
|
|
493
|
-
const bypassPatterns = [
|
|
494
|
-
/\.skip\(/, // Jest/Vitest skip
|
|
495
|
-
/\.bypass\s*=/, // bypass flag
|
|
496
|
-
/skip:\s*true/, // skip option
|
|
497
|
-
/bypass\s*checkpoint/, // explicit bypass
|
|
498
|
-
/\/\/\s*skip/, // comment skip
|
|
499
|
-
];
|
|
500
|
-
|
|
501
|
-
for (const file of changedFiles) {
|
|
502
|
-
if (!existsSync(file)) continue;
|
|
503
|
-
try {
|
|
504
|
-
const content = readFileSync(file, 'utf-8');
|
|
505
|
-
for (const pattern of bypassPatterns) {
|
|
506
|
-
if (pattern.test(content)) {
|
|
507
|
-
return false; // 发现 bypass 关键词
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
} catch {
|
|
511
|
-
// 文件读取失败,忽略
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
return true;
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
/**
|
|
519
|
-
* 检查 no_test_simplification:检查 git diff 是否删除了测试
|
|
520
|
-
*/
|
|
521
|
-
private async checkNoTestSimplification(projectPath: string): Promise<boolean> {
|
|
522
|
-
try {
|
|
523
|
-
// 检查是否有删除测试的 diff
|
|
524
|
-
const diff = await runCommand('git diff --cached', projectPath);
|
|
525
|
-
|
|
526
|
-
// 检查是否删除了测试行
|
|
527
|
-
const deletedTestPatterns = [
|
|
528
|
-
/^-\s*(test|it|describe)\s*\(/, // 删除 test/it/describe
|
|
529
|
-
/^-\s*expect\s*\(/, // 删除 expect
|
|
530
|
-
/^-\s*\/\/\s*test/, // 删除注释的 test
|
|
531
|
-
];
|
|
532
|
-
|
|
533
|
-
for (const pattern of deletedTestPatterns) {
|
|
534
|
-
if (pattern.test(diff)) {
|
|
535
|
-
return false; // 发现删除测试
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
return true;
|
|
540
|
-
} catch {
|
|
541
|
-
return true; // git 命令失败,默认通过
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
/**
|
|
546
|
-
* 检查 no_any_type:grep any 类型
|
|
547
|
-
*/
|
|
548
|
-
private async checkNoAnyType(projectPath: string, changedFiles?: string[]): Promise<boolean> {
|
|
549
|
-
try {
|
|
550
|
-
const filesToCheck = changedFiles && changedFiles.length > 0
|
|
551
|
-
? changedFiles.filter(f => f.endsWith('.ts') || f.endsWith('.tsx'))
|
|
552
|
-
: [];
|
|
553
|
-
|
|
554
|
-
if (filesToCheck.length === 0) {
|
|
555
|
-
return true; // 无 TS 文件变更
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
// 检查是否有 : any 类型
|
|
559
|
-
for (const file of filesToCheck) {
|
|
560
|
-
if (!existsSync(file)) continue;
|
|
561
|
-
try {
|
|
562
|
-
const content = readFileSync(file, 'utf-8');
|
|
563
|
-
// 检查 : any(排除注释和字符串)
|
|
564
|
-
const lines = content.split('\n');
|
|
565
|
-
for (const line of lines) {
|
|
566
|
-
// 跳过注释和字符串
|
|
567
|
-
if (line.trim().startsWith('//') || line.trim().startsWith('*')) continue;
|
|
568
|
-
if (line.includes(': any') && !line.includes('// ') && !line.includes('/*')) {
|
|
569
|
-
return false; // 发现 any 类型
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
} catch {
|
|
573
|
-
// 文件读取失败,忽略
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
return true;
|
|
578
|
-
} catch {
|
|
579
|
-
return true; // 检查失败,默认通过
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
/**
|
|
584
|
-
* 检查 capability_sync:检查 CAPABILITIES.md 是否与代码同步
|
|
585
|
-
*
|
|
586
|
-
* 两步验证:
|
|
587
|
-
* 1. Git diff 检查 — 当前变更的非测试文件是否在文档中有记录(增量检查)
|
|
588
|
-
* 2. 全量扫描 — src/ 下的所有源文件是否都在 CAPABILITIES.md 中(完整性检查)
|
|
589
|
-
*/
|
|
590
|
-
private async checkCapabilitySync(projectPath: string): Promise<boolean> {
|
|
591
|
-
try {
|
|
592
|
-
const capabilitiesPath = join(projectPath, 'CAPABILITIES.md');
|
|
593
|
-
if (!existsSync(capabilitiesPath)) {
|
|
594
|
-
// 检查是否有代码变更,无变更则跳过
|
|
595
|
-
const diff = await runCommand('git diff --cached --name-only', projectPath);
|
|
596
|
-
const changedCodeFiles = diff.split('\n').filter(
|
|
597
|
-
(f: string) => f.endsWith('.ts') || f.endsWith('.tsx') || f.endsWith('.js')
|
|
598
|
-
);
|
|
599
|
-
return changedCodeFiles.length === 0;
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
const listedFiles = this.parseCapabilitiesFiles(capabilitiesPath);
|
|
603
|
-
|
|
604
|
-
// ── Step 1: Git diff 增量检查 ──
|
|
605
|
-
const diff = await runCommand('git diff --cached --name-only', projectPath);
|
|
606
|
-
const changedCodeFiles = diff.split('\n').filter(
|
|
607
|
-
(f: string) => f.endsWith('.ts') || f.endsWith('.tsx') || f.endsWith('.js')
|
|
608
|
-
);
|
|
609
|
-
|
|
610
|
-
if (changedCodeFiles.length > 0 && listedFiles.length > 0) {
|
|
611
|
-
const significantChanges = changedCodeFiles.filter(
|
|
612
|
-
(f: string) => !f.includes('__tests__') && !f.includes('.test.') && !f.includes('.spec.')
|
|
613
|
-
);
|
|
614
|
-
|
|
615
|
-
if (significantChanges.length > 0) {
|
|
616
|
-
const covered = significantChanges.some((changed: string) =>
|
|
617
|
-
listedFiles.some((listed: string) => changed.endsWith(listed) || changed.includes(listed))
|
|
618
|
-
);
|
|
619
|
-
if (!covered) return false;
|
|
620
|
-
}
|
|
621
|
-
}
|
|
279
|
+
const impl = getConstraintCheck(constraint.id);
|
|
280
|
+
if (!impl) return true;
|
|
622
281
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
)
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
return true;
|
|
643
|
-
} catch {
|
|
644
|
-
return true; // 检查失败,默认通过
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
/**
|
|
649
|
-
* 解析 CAPABILITIES.md 中表格的文件路径列
|
|
650
|
-
*/
|
|
651
|
-
private parseCapabilitiesFiles(capabilitiesPath: string): string[] {
|
|
652
|
-
try {
|
|
653
|
-
const content = readFileSync(capabilitiesPath, 'utf-8');
|
|
654
|
-
const files: string[] = [];
|
|
655
|
-
|
|
656
|
-
// 匹配 markdown 表格行中的 .ts/.tsx/.js/.jsx 文件路径(第二列)
|
|
657
|
-
const tableRowRegex = /^\|[^|]+\|\s*([^|]+?\.(?:ts|tsx|js|jsx))\s*\|/gm;
|
|
658
|
-
let match;
|
|
659
|
-
while ((match = tableRowRegex.exec(content)) !== null) {
|
|
660
|
-
files.push(match[1].trim());
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
return files;
|
|
664
|
-
} catch {
|
|
665
|
-
return [];
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
/**
|
|
670
|
-
* 检查 no_simplification_without_approval:检查简化关键词
|
|
671
|
-
*/
|
|
672
|
-
private async checkNoSimplificationWithoutApproval(projectPath: string): Promise<boolean> {
|
|
673
|
-
try {
|
|
674
|
-
const diff = await runCommand('git diff --cached', projectPath);
|
|
675
|
-
|
|
676
|
-
// 检查是否有简化关键词
|
|
677
|
-
const simplificationPatterns = [
|
|
678
|
-
/removed\s*test/i,
|
|
679
|
-
/simplified\s*logic/i,
|
|
680
|
-
/removed\s*validation/i,
|
|
681
|
-
/skip\s*check/i,
|
|
682
|
-
];
|
|
683
|
-
|
|
684
|
-
for (const pattern of simplificationPatterns) {
|
|
685
|
-
if (pattern.test(diff)) {
|
|
686
|
-
return false; // 发现简化关键词
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
return true;
|
|
691
|
-
} catch {
|
|
692
|
-
return true; // 检查失败,默认通过
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
/**
|
|
697
|
-
* 检查 test_coverage_required:读取 coverage 报告
|
|
698
|
-
*/
|
|
699
|
-
private async checkTestCoverage(projectPath: string): Promise<boolean> {
|
|
700
|
-
try {
|
|
701
|
-
// 检查 coverage 报告文件
|
|
702
|
-
const coverageJsonPath = join(projectPath, 'coverage', 'coverage-final.json');
|
|
703
|
-
const coverageSummaryPath = join(projectPath, 'coverage', 'coverage-summary.json');
|
|
704
|
-
|
|
705
|
-
if (!existsSync(coverageJsonPath) && !existsSync(coverageSummaryPath)) {
|
|
706
|
-
return true; // 无 coverage 报告,默认通过
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
// 尝试读取 coverage-summary.json
|
|
710
|
-
if (existsSync(coverageSummaryPath)) {
|
|
711
|
-
const summary = JSON.parse(readFileSync(coverageSummaryPath, 'utf-8'));
|
|
712
|
-
const total = summary.total || {};
|
|
713
|
-
const linesCoverage = total.lines?.pct || 0;
|
|
714
|
-
|
|
715
|
-
// 默认要求 50% 覆盖率(可配置)
|
|
716
|
-
return linesCoverage >= 50;
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
return true;
|
|
720
|
-
} catch {
|
|
721
|
-
return true; // 检查失败,默认通过
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
/**
|
|
726
|
-
* 检查 context_doc_sync:关键目录是否有 CONTEXT.md
|
|
727
|
-
*/
|
|
728
|
-
private async checkContextDocSync(projectPath: string): Promise<boolean> {
|
|
729
|
-
try {
|
|
730
|
-
const configPath = join(projectPath, '.harness', 'config.yml');
|
|
731
|
-
const configContent = readFileSync(configPath, 'utf-8');
|
|
732
|
-
const config = yaml.load(configContent) as Record<string, unknown>;
|
|
733
|
-
const governance = config.governance as Record<string, unknown> | undefined;
|
|
734
|
-
const contextFiles = governance?.context_files as Record<string, unknown> | undefined;
|
|
735
|
-
|
|
736
|
-
if (!contextFiles?.enabled || !Array.isArray(contextFiles.required_dirs)) {
|
|
737
|
-
return true; // 未配置,跳过
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
const requiredDirs = contextFiles.required_dirs as string[];
|
|
741
|
-
for (const dir of requiredDirs) {
|
|
742
|
-
const contextPath = join(projectPath, dir, 'CONTEXT.md');
|
|
743
|
-
if (!existsSync(contextPath)) {
|
|
744
|
-
return false;
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
return true;
|
|
749
|
-
} catch {
|
|
750
|
-
return true; // 配置不存在或解析失败,跳过
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
/**
|
|
755
|
-
* 检查 docs_freshness:CAPABILITIES.md 文件表 + 能力清单格式 + CLAUDE.md + CHANGELOG
|
|
756
|
-
*
|
|
757
|
-
* 1. 文件表格式:检查 CAPABILITIES.md 中列出的文件是否存在(防过期引用)
|
|
758
|
-
* 2. 能力清单格式:通过 FreshnessRunner 配置驱动检查计数/目录
|
|
759
|
-
* 3. 无配置时注入内置默认配置(等价旧硬编码行为)
|
|
760
|
-
*/
|
|
761
|
-
private async checkDocsFreshness(projectPath: string): Promise<boolean> {
|
|
762
|
-
// Step 1: 文件表格式 — 检查列出的文件是否还存在
|
|
763
|
-
const fileTableResult = await this.checkCapabilitiesFreshness(projectPath);
|
|
764
|
-
if (!fileTableResult) return false;
|
|
765
|
-
|
|
766
|
-
// Step 2: 能力清单格式 + CLAUDE.md + CHANGELOG — 通过 FreshnessRunner
|
|
767
|
-
try {
|
|
768
|
-
const configPath = join(projectPath, '.harness', 'config.yml');
|
|
769
|
-
let freshnessConfig: DocFreshnessConfig | undefined;
|
|
770
|
-
let requiredDirs: string[] | undefined;
|
|
771
|
-
|
|
772
|
-
if (existsSync(configPath)) {
|
|
773
|
-
try {
|
|
774
|
-
const raw = yaml.load(readFileSync(configPath, 'utf-8')) as Record<string, unknown>;
|
|
775
|
-
const governance = raw.governance as Record<string, unknown> | undefined;
|
|
776
|
-
freshnessConfig = governance?.doc_freshness as DocFreshnessConfig | undefined;
|
|
777
|
-
|
|
778
|
-
const contextFiles = governance?.context_files as Record<string, unknown> | undefined;
|
|
779
|
-
if (contextFiles?.enabled && Array.isArray(contextFiles.required_dirs)) {
|
|
780
|
-
requiredDirs = contextFiles.required_dirs as string[];
|
|
781
|
-
}
|
|
782
|
-
} catch {
|
|
783
|
-
// 配置解析失败,使用默认
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
const runner = new FreshnessRunner();
|
|
788
|
-
let results: FreshnessCheckResult[];
|
|
789
|
-
|
|
790
|
-
if (freshnessConfig?.checks && freshnessConfig.checks.length > 0) {
|
|
791
|
-
results = runner.runAll(freshnessConfig, projectPath, { requiredDirs });
|
|
792
|
-
} else {
|
|
793
|
-
const builtIn = this.getBuiltInDocFreshnessConfig(requiredDirs);
|
|
794
|
-
results = runner.runAll({ checks: builtIn }, projectPath, { requiredDirs });
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
if (!results.every(r => r.pass)) return false;
|
|
798
|
-
} catch {
|
|
799
|
-
// FreshnessRunner 失败不影响整体
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
return true;
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
/**
|
|
806
|
-
* 获取内置默认文档新鲜度检查配置
|
|
807
|
-
*
|
|
808
|
-
* 等价旧硬编码的 checkCapabilitiesFreshness + checkClaudeMdFreshness 行为。
|
|
809
|
-
* 仅当项目未提供 governance.doc_freshness 配置时使用。
|
|
810
|
-
*/
|
|
811
|
-
private getBuiltInDocFreshnessConfig(_requiredDirs?: string[]): DocFreshnessCheck[] {
|
|
812
|
-
return [
|
|
813
|
-
// CONTEXT.md 存在性 — key directories must have CONTEXT.md
|
|
814
|
-
{ type: 'context_docs' },
|
|
815
|
-
// CHANGELOG 版本 vs package.json 版本 — prevents version drift
|
|
816
|
-
{ type: 'changelog_version' },
|
|
817
|
-
];
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
/**
|
|
821
|
-
* 检查 CAPABILITIES.md 是否与源码同步(文件表格式)
|
|
822
|
-
*
|
|
823
|
-
* 检查 CAPABILITIES.md 中列出的文件路径是否仍然存在于磁盘上(防过期引用)。
|
|
824
|
-
* 多根查找:支持不同项目的源码根(harness=src/, studio=apps/api/src/ 等)。
|
|
825
|
-
* 无表格行(能力清单格式)时跳过。
|
|
826
|
-
*/
|
|
827
|
-
private async checkCapabilitiesFreshness(projectPath: string): Promise<boolean> {
|
|
828
|
-
try {
|
|
829
|
-
const capabilitiesPath = join(projectPath, 'CAPABILITIES.md');
|
|
830
|
-
if (!existsSync(capabilitiesPath)) return true;
|
|
831
|
-
const content = readFileSync(capabilitiesPath, 'utf-8');
|
|
832
|
-
|
|
833
|
-
const listedFiles: string[] = [];
|
|
834
|
-
const tableRowRegex = /^\|[^|]+\|\s*([^|]+?\.(?:ts|tsx|js|jsx))\s*\|/gm;
|
|
835
|
-
let match;
|
|
836
|
-
while ((match = tableRowRegex.exec(content)) !== null) {
|
|
837
|
-
listedFiles.push(match[1].trim());
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
if (listedFiles.length === 0) return true;
|
|
841
|
-
|
|
842
|
-
const sourceRoots = detectSourceRoots(projectPath);
|
|
843
|
-
const fileExists = (file: string): boolean => {
|
|
844
|
-
if (existsSync(join(projectPath, file))) return true;
|
|
845
|
-
for (const root of sourceRoots) {
|
|
846
|
-
if (existsSync(join(projectPath, root, file))) return true;
|
|
847
|
-
}
|
|
848
|
-
return false;
|
|
849
|
-
};
|
|
850
|
-
|
|
851
|
-
for (const file of listedFiles) {
|
|
852
|
-
if (!fileExists(file)) return false;
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
return true;
|
|
856
|
-
} catch {
|
|
857
|
-
return true;
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
/**
|
|
862
|
-
* 查找 src/ 目录中的源文件
|
|
863
|
-
*/
|
|
864
|
-
private findSourceFiles(dir: string, projectPath: string): string[] {
|
|
865
|
-
const results: string[] = [];
|
|
866
|
-
let entries: string[];
|
|
867
|
-
try {
|
|
868
|
-
entries = readdirSync(dir);
|
|
869
|
-
} catch {
|
|
870
|
-
return [];
|
|
871
|
-
}
|
|
282
|
+
const projectPath = context.projectPath || process.cwd();
|
|
283
|
+
const env: CheckEnv = {
|
|
284
|
+
context,
|
|
285
|
+
projectPath,
|
|
286
|
+
stagedDiff: () => this.getStagedDiff(projectPath),
|
|
287
|
+
stagedDiffNames: () => this.getStagedDiffNames(projectPath),
|
|
288
|
+
srcScan: (root: string) =>
|
|
289
|
+
this.cache.getSync(`src_scan_${root}`, projectPath, () =>
|
|
290
|
+
findTsSourceFiles(join(projectPath, root), { skipIndex: true }).map((f) =>
|
|
291
|
+
relative(projectPath, f)
|
|
292
|
+
)
|
|
293
|
+
),
|
|
294
|
+
};
|
|
872
295
|
|
|
873
|
-
|
|
874
|
-
if (entry === 'node_modules' || entry === '__tests__' || entry === 'dist') continue;
|
|
875
|
-
const entryPath = join(dir, entry);
|
|
876
|
-
try {
|
|
877
|
-
const stat = statSync(entryPath);
|
|
878
|
-
if (stat.isDirectory()) {
|
|
879
|
-
results.push(...this.findSourceFiles(entryPath, projectPath));
|
|
880
|
-
} else if (entry.endsWith('.ts') && !entry.endsWith('.d.ts') && entry !== 'index.ts') {
|
|
881
|
-
results.push(relative(projectPath, entryPath));
|
|
882
|
-
}
|
|
883
|
-
} catch {
|
|
884
|
-
// ignore
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
return results;
|
|
296
|
+
return await impl.evaluate(env);
|
|
888
297
|
}
|
|
889
298
|
|
|
890
299
|
/**
|
|
@@ -934,59 +343,67 @@ export class ConstraintChecker {
|
|
|
934
343
|
context: ConstraintContext,
|
|
935
344
|
customConfig?: MergedConstraintsConfig | null
|
|
936
345
|
): Promise<ConstraintCheckResult> {
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
tips: [],
|
|
941
|
-
passed: true,
|
|
942
|
-
warningCount: 0,
|
|
943
|
-
tipCount: 0,
|
|
944
|
-
};
|
|
346
|
+
// run 起始:重置 run 级缓存;run 结束(含铁律提前抛出)清空(工单 18)
|
|
347
|
+
this.cache.invalidate();
|
|
348
|
+
this.runCache = new Map();
|
|
945
349
|
|
|
946
|
-
|
|
947
|
-
|
|
350
|
+
try {
|
|
351
|
+
const result: ConstraintCheckResult = {
|
|
352
|
+
ironLaws: [],
|
|
353
|
+
guidelines: [],
|
|
354
|
+
tips: [],
|
|
355
|
+
passed: true,
|
|
356
|
+
warningCount: 0,
|
|
357
|
+
tipCount: 0,
|
|
358
|
+
};
|
|
948
359
|
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
if (!this.matchesTrigger(constraint, context.operation)) continue;
|
|
360
|
+
const traceCollector = this.traceRecorder;
|
|
361
|
+
const constraints = this.getConstraints(customConfig);
|
|
952
362
|
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
363
|
+
// 1. Iron Laws: 必须全部通过
|
|
364
|
+
for (const constraint of Object.values(constraints.ironLaws)) {
|
|
365
|
+
if (!this.matchesTrigger(constraint, context.operation)) continue;
|
|
956
366
|
|
|
957
|
-
|
|
958
|
-
result.
|
|
959
|
-
|
|
367
|
+
const checkResult = await this.check(constraint, context);
|
|
368
|
+
result.ironLaws.push(checkResult);
|
|
369
|
+
this.recordTrace(traceCollector, constraint, checkResult, context);
|
|
370
|
+
|
|
371
|
+
if (!checkResult.satisfied) {
|
|
372
|
+
result.passed = false;
|
|
373
|
+
throw new ConstraintViolationError(checkResult);
|
|
374
|
+
}
|
|
960
375
|
}
|
|
961
|
-
}
|
|
962
376
|
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
377
|
+
// 2. Guidelines: 记录警告
|
|
378
|
+
for (const constraint of Object.values(constraints.guidelines)) {
|
|
379
|
+
if (!this.matchesTrigger(constraint, context.operation)) continue;
|
|
966
380
|
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
381
|
+
const checkResult = await this.check(constraint, context);
|
|
382
|
+
result.guidelines.push(checkResult);
|
|
383
|
+
this.recordTrace(traceCollector, constraint, checkResult, context);
|
|
970
384
|
|
|
971
|
-
|
|
972
|
-
|
|
385
|
+
if (!checkResult.satisfied) {
|
|
386
|
+
result.warningCount++;
|
|
387
|
+
}
|
|
973
388
|
}
|
|
974
|
-
}
|
|
975
389
|
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
390
|
+
// 3. Tips: 仅记录
|
|
391
|
+
for (const constraint of Object.values(constraints.tips)) {
|
|
392
|
+
if (!this.matchesTrigger(constraint, context.operation)) continue;
|
|
979
393
|
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
394
|
+
const checkResult = await this.check(constraint, context);
|
|
395
|
+
result.tips.push(checkResult);
|
|
396
|
+
this.recordTrace(traceCollector, constraint, checkResult, context);
|
|
983
397
|
|
|
984
|
-
|
|
985
|
-
|
|
398
|
+
if (!checkResult.satisfied) {
|
|
399
|
+
result.tipCount++;
|
|
400
|
+
}
|
|
986
401
|
}
|
|
987
|
-
}
|
|
988
402
|
|
|
989
|
-
|
|
403
|
+
return result;
|
|
404
|
+
} finally {
|
|
405
|
+
this.runCache = null;
|
|
406
|
+
}
|
|
990
407
|
}
|
|
991
408
|
|
|
992
409
|
/**
|
|
@@ -999,43 +416,51 @@ export class ConstraintChecker {
|
|
|
999
416
|
context: ConstraintContext,
|
|
1000
417
|
customConfig?: MergedConstraintsConfig | null
|
|
1001
418
|
): Promise<ConstraintCheckResult> {
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
tips: [],
|
|
1006
|
-
passed: true,
|
|
1007
|
-
warningCount: 0,
|
|
1008
|
-
tipCount: 0,
|
|
1009
|
-
};
|
|
419
|
+
// run 起始:重置 run 级缓存(工单 18)
|
|
420
|
+
this.cache.invalidate();
|
|
421
|
+
this.runCache = new Map();
|
|
1010
422
|
|
|
1011
|
-
|
|
1012
|
-
|
|
423
|
+
try {
|
|
424
|
+
const result: ConstraintCheckResult = {
|
|
425
|
+
ironLaws: [],
|
|
426
|
+
guidelines: [],
|
|
427
|
+
tips: [],
|
|
428
|
+
passed: true,
|
|
429
|
+
warningCount: 0,
|
|
430
|
+
tipCount: 0,
|
|
431
|
+
};
|
|
1013
432
|
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
const checkResult = await this.check(constraint, context);
|
|
1017
|
-
result.ironLaws.push(checkResult);
|
|
1018
|
-
this.recordTrace(traceCollector, constraint, checkResult, context);
|
|
1019
|
-
if (!checkResult.satisfied) result.passed = false;
|
|
1020
|
-
}
|
|
433
|
+
const traceCollector = this.traceRecorder;
|
|
434
|
+
const constraints = this.getConstraints(customConfig);
|
|
1021
435
|
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
436
|
+
for (const constraint of Object.values(constraints.ironLaws)) {
|
|
437
|
+
if (!this.matchesTrigger(constraint, context.operation)) continue;
|
|
438
|
+
const checkResult = await this.check(constraint, context);
|
|
439
|
+
result.ironLaws.push(checkResult);
|
|
440
|
+
this.recordTrace(traceCollector, constraint, checkResult, context);
|
|
441
|
+
if (!checkResult.satisfied) result.passed = false;
|
|
442
|
+
}
|
|
1029
443
|
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
444
|
+
for (const constraint of Object.values(constraints.guidelines)) {
|
|
445
|
+
if (!this.matchesTrigger(constraint, context.operation)) continue;
|
|
446
|
+
const checkResult = await this.check(constraint, context);
|
|
447
|
+
result.guidelines.push(checkResult);
|
|
448
|
+
this.recordTrace(traceCollector, constraint, checkResult, context);
|
|
449
|
+
if (!checkResult.satisfied) result.warningCount++;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
for (const constraint of Object.values(constraints.tips)) {
|
|
453
|
+
if (!this.matchesTrigger(constraint, context.operation)) continue;
|
|
454
|
+
const checkResult = await this.check(constraint, context);
|
|
455
|
+
result.tips.push(checkResult);
|
|
456
|
+
this.recordTrace(traceCollector, constraint, checkResult, context);
|
|
457
|
+
if (!checkResult.satisfied) result.tipCount++;
|
|
458
|
+
}
|
|
1037
459
|
|
|
1038
|
-
|
|
460
|
+
return result;
|
|
461
|
+
} finally {
|
|
462
|
+
this.runCache = null;
|
|
463
|
+
}
|
|
1039
464
|
}
|
|
1040
465
|
|
|
1041
466
|
/**
|
|
@@ -1133,37 +558,3 @@ export async function checkBeforeExecution(
|
|
|
1133
558
|
|
|
1134
559
|
// 导出单例
|
|
1135
560
|
export const constraintChecker = ConstraintChecker.getInstance();
|
|
1136
|
-
|
|
1137
|
-
// ========================================
|
|
1138
|
-
// 向后兼容的类和函数
|
|
1139
|
-
// ========================================
|
|
1140
|
-
|
|
1141
|
-
/**
|
|
1142
|
-
* @deprecated 使用 ConstraintChecker 代替
|
|
1143
|
-
*/
|
|
1144
|
-
export const IronLawChecker = ConstraintChecker;
|
|
1145
|
-
|
|
1146
|
-
/**
|
|
1147
|
-
* @deprecated 使用 checkConstraint 代替
|
|
1148
|
-
*/
|
|
1149
|
-
export async function checkIronLaw(
|
|
1150
|
-
lawId: string,
|
|
1151
|
-
context: ConstraintContext
|
|
1152
|
-
): Promise<ConstraintResult> {
|
|
1153
|
-
return checkConstraint(lawId, context);
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
|
-
/**
|
|
1157
|
-
* @deprecated 使用 checkConstraints 代替
|
|
1158
|
-
*/
|
|
1159
|
-
export async function checkAllIronLaws(
|
|
1160
|
-
context: ConstraintContext
|
|
1161
|
-
): Promise<ConstraintResult[]> {
|
|
1162
|
-
const result = await checkConstraints(context);
|
|
1163
|
-
return [...result.ironLaws, ...result.guidelines, ...result.tips];
|
|
1164
|
-
}
|
|
1165
|
-
|
|
1166
|
-
/**
|
|
1167
|
-
* @deprecated 使用 constraintChecker 代替
|
|
1168
|
-
*/
|
|
1169
|
-
export const ironLawChecker = constraintChecker;
|