@dommaker/harness 0.13.0 → 0.13.2
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 +169 -0
- package/bin/harness-knowledge-capture.js +99 -0
- package/bin/harness-knowledge-check.js +149 -0
- package/bin/harness-knowledge-track.js +92 -0
- package/bin/harness-knowledge-track.sh +47 -0
- package/bin/harness-sensitive-check.sh +67 -0
- package/dist/cli/commands/init.js +34 -2
- package/dist/cli/commands/init.js.map +1 -1
- package/package.json +6 -3
- package/src/CONTEXT.md +34 -0
- package/src/__tests__/acceptance-gate.test.ts +364 -0
- package/src/__tests__/annotation-checker.test.ts +183 -0
- package/src/__tests__/architecture-engine.test.ts +619 -0
- package/src/__tests__/checker-extra.test.ts +1627 -0
- package/src/__tests__/checker.test.ts +1268 -0
- package/src/__tests__/checkpoint.test.ts +697 -0
- package/src/__tests__/clean-state-extra.test.ts +301 -0
- package/src/__tests__/clean-state.test.ts +169 -0
- package/src/__tests__/constraint-doctor.test.ts +410 -0
- package/src/__tests__/constraint-evolver.test.ts +404 -0
- package/src/__tests__/constraint-handler.test.ts +136 -0
- package/src/__tests__/context/progressive-loader.test.ts +131 -0
- package/src/__tests__/contract-gate.test.ts +321 -0
- package/src/__tests__/cross-project-checker.test.ts +318 -0
- package/src/__tests__/cso-validator.test.ts +205 -0
- package/src/__tests__/detect-source-roots.test.ts +98 -0
- package/src/__tests__/doctor-evolver.test.ts +381 -0
- package/src/__tests__/error-classifier.test.ts +304 -0
- package/src/__tests__/exec.test.ts +83 -0
- package/src/__tests__/extend-exceptions.test.ts +149 -0
- package/src/__tests__/failure-recorder.test.ts +335 -0
- package/src/__tests__/hooks-pipeline.test.ts +214 -0
- package/src/__tests__/interceptor.test.ts +89 -0
- package/src/__tests__/iron-laws.test.ts +246 -0
- package/src/__tests__/long-running.test.ts +17 -0
- package/src/__tests__/passes-gate-check.test.ts +138 -0
- package/src/__tests__/passes-gate-extension.test.ts +151 -0
- package/src/__tests__/passes-gate-extra.test.ts +238 -0
- package/src/__tests__/passes-gate.test.ts +231 -0
- package/src/__tests__/performance-analyzer.test.ts +501 -0
- package/src/__tests__/performance-collector.test.ts +276 -0
- package/src/__tests__/performance-gate.test.ts +74 -0
- package/src/__tests__/presets.test.ts +104 -0
- package/src/__tests__/project-config-loader-extra.test.ts +269 -0
- package/src/__tests__/project-config-loader.test.ts +127 -0
- package/src/__tests__/review-gate.test.ts +92 -0
- package/src/__tests__/security-gate.test.ts +100 -0
- package/src/__tests__/session-startup.test.ts +334 -0
- package/src/__tests__/spec-validator.test.ts +57 -0
- package/src/__tests__/token-budget.test.ts +252 -0
- package/src/__tests__/trace-analyzer-extra.test.ts +307 -0
- package/src/__tests__/trace-analyzer.test.ts +131 -0
- package/src/__tests__/trace-collector.test.ts +258 -0
- package/src/__tests__/traces.test.ts +347 -0
- package/src/agents/CONTEXT.md +21 -0
- package/src/agents/__tests__/lifecycle.test.ts +248 -0
- package/src/agents/index.ts +2 -0
- package/src/agents/lifecycle.ts +201 -0
- package/src/agents/types.ts +46 -0
- package/src/architecture/CONTEXT.md +22 -0
- package/src/architecture/constraint-engine.ts +356 -0
- package/src/architecture/cross-project-checker.ts +563 -0
- package/src/cli/commands/CONTEXT.md +24 -0
- package/src/cli/commands/__tests__/acceptance.test.ts +180 -0
- package/src/cli/commands/__tests__/check.test.ts +598 -0
- package/src/cli/commands/__tests__/command.test.ts +149 -0
- package/src/cli/commands/__tests__/contract.test.ts +151 -0
- package/src/cli/commands/__tests__/failure.test.ts +199 -0
- package/src/cli/commands/__tests__/flow.test.ts +343 -0
- package/src/cli/commands/__tests__/init.test.ts +306 -0
- package/src/cli/commands/__tests__/passes-gate.test.ts +256 -0
- package/src/cli/commands/__tests__/performance.test.ts +116 -0
- package/src/cli/commands/__tests__/posteval-plan.test.ts +201 -0
- package/src/cli/commands/__tests__/report-extra.test.ts +98 -0
- package/src/cli/commands/__tests__/report.test.ts +109 -0
- package/src/cli/commands/__tests__/review.test.ts +153 -0
- package/src/cli/commands/__tests__/security.test.ts +147 -0
- package/src/cli/commands/__tests__/spec.test.ts +193 -0
- package/src/cli/commands/__tests__/status-extra.test.ts +223 -0
- package/src/cli/commands/__tests__/status.test.ts +306 -0
- package/src/cli/commands/__tests__/sync-docs.test.ts +335 -0
- package/src/cli/commands/__tests__/validate.test.ts +139 -0
- package/src/cli/commands/acceptance.ts +111 -0
- package/src/cli/commands/analyze-sessions.ts +488 -0
- package/src/cli/commands/check.ts +441 -0
- package/src/cli/commands/command.ts +90 -0
- package/src/cli/commands/constraints.ts +86 -0
- package/src/cli/commands/contract.ts +168 -0
- package/src/cli/commands/failure.ts +117 -0
- package/src/cli/commands/flow.ts +275 -0
- package/src/cli/commands/index.ts +26 -0
- package/src/cli/commands/init.ts +832 -0
- package/src/cli/commands/knowledge.ts +391 -0
- package/src/cli/commands/passes-gate.ts +158 -0
- package/src/cli/commands/performance.ts +108 -0
- package/src/cli/commands/posteval-plan.ts +85 -0
- package/src/cli/commands/release.ts +159 -0
- package/src/cli/commands/report.ts +198 -0
- package/src/cli/commands/review.ts +118 -0
- package/src/cli/commands/security.ts +122 -0
- package/src/cli/commands/spec.ts +158 -0
- package/src/cli/commands/status.ts +169 -0
- package/src/cli/commands/sync-docs.ts +743 -0
- package/src/cli/commands/update-user-model.ts +527 -0
- package/src/cli/commands/validate.ts +222 -0
- package/src/constraints/__tests__/lifecycle-runner.test.ts +246 -0
- package/src/constraints/__tests__/registry.test.ts +196 -0
- package/src/constraints/index.ts +3 -0
- package/src/constraints/lifecycle-runner.ts +184 -0
- package/src/constraints/registry.ts +134 -0
- package/src/constraints/types.ts +59 -0
- package/src/context/CONTEXT.md +28 -0
- package/src/context/__tests__/compaction.test.ts +169 -0
- package/src/context/__tests__/file-budget.test.ts +142 -0
- package/src/context/__tests__/knowledge-injector.test.ts +148 -0
- package/src/context/__tests__/progressive-loader.test.ts +264 -0
- package/src/context/__tests__/session-manager.test.ts +300 -0
- package/src/context/__tests__/token-budget.test.ts +338 -0
- package/src/context/__tests__/token-pipeline.test.ts +178 -0
- package/src/context/__tests__/tool-output-budget.test.ts +95 -0
- package/src/context/compaction.ts +202 -0
- package/src/context/file-budget.ts +142 -0
- package/src/context/index.ts +15 -0
- package/src/context/knowledge-injector.ts +168 -0
- package/src/context/progressive-loader.ts +260 -0
- package/src/context/session-manager.ts +343 -0
- package/src/context/token-budget.ts +295 -0
- package/src/context/token-pipeline.ts +265 -0
- package/src/context/tool-output-budget.ts +178 -0
- package/src/context/types.ts +160 -0
- package/src/core/CONTEXT.md +26 -0
- package/src/core/constraints/__tests__/default-executors.test.ts +57 -0
- package/src/core/constraints/__tests__/interceptor.test.ts +251 -0
- package/src/core/constraints/__tests__/prompt-injection.test.ts +89 -0
- package/src/core/constraints/check-cache.ts +96 -0
- package/src/core/constraints/checker.ts +1169 -0
- package/src/core/constraints/default-executors.ts +92 -0
- package/src/core/constraints/definitions.ts +1119 -0
- package/src/core/constraints/doc-freshness/__tests__/runner.test.ts +551 -0
- package/src/core/constraints/doc-freshness/auto-fix.ts +69 -0
- package/src/core/constraints/doc-freshness/runner.ts +486 -0
- package/src/core/constraints/index.ts +78 -0
- package/src/core/constraints/interceptor.ts +220 -0
- package/src/core/constraints/prompt-injection.ts +73 -0
- package/src/core/index.ts +23 -0
- package/src/core/project-config-loader.ts +252 -0
- package/src/core/session/__tests__/startup.test.ts +281 -0
- package/src/core/session/clean-state.ts +178 -0
- package/src/core/session/index.ts +15 -0
- package/src/core/session/startup.ts +253 -0
- package/src/core/spec/__tests__/validator.test.ts +379 -0
- package/src/core/spec/index.ts +7 -0
- package/src/core/spec/validator.ts +383 -0
- package/src/core/validators/__tests__/passes-gate.test.ts +131 -0
- package/src/core/validators/checkpoint.ts +547 -0
- package/src/core/validators/cso.ts +124 -0
- package/src/core/validators/index.ts +25 -0
- package/src/core/validators/passes-gate.ts +613 -0
- package/src/dashboard/CONTEXT.md +21 -0
- package/src/dashboard/__tests__/data.test.ts +115 -0
- package/src/dashboard/__tests__/stats.test.ts +156 -0
- package/src/dashboard/data.ts +113 -0
- package/src/dashboard/index.ts +3 -0
- package/src/dashboard/stats.ts +127 -0
- package/src/dashboard/types.ts +113 -0
- package/src/evolution/CONTEXT.md +22 -0
- package/src/evolution/__tests__/auto-evolve.test.ts +320 -0
- package/src/evolution/auto-evolve.ts +98 -0
- package/src/evolution/index.ts +1 -0
- package/src/failure/CONTEXT.md +24 -0
- package/src/failure/classifier.ts +156 -0
- package/src/failure/constraint-handler.ts +173 -0
- package/src/failure/index.ts +35 -0
- package/src/failure/recorder.ts +201 -0
- package/src/failure/types.ts +165 -0
- package/src/gates/CONTEXT.md +27 -0
- package/src/gates/__tests__/acceptance.test.ts +608 -0
- package/src/gates/__tests__/command.test.ts +206 -0
- package/src/gates/__tests__/performance.test.ts +381 -0
- package/src/gates/__tests__/review.test.ts +302 -0
- package/src/gates/__tests__/security.test.ts +332 -0
- package/src/gates/acceptance.ts +493 -0
- package/src/gates/command.ts +444 -0
- package/src/gates/contract.ts +260 -0
- package/src/gates/index.ts +67 -0
- package/src/gates/performance.ts +359 -0
- package/src/gates/review.ts +169 -0
- package/src/gates/security.ts +244 -0
- package/src/gates/types.ts +159 -0
- package/src/governance/CONTEXT.md +22 -0
- package/src/governance/__tests__/executor.test.ts +249 -0
- package/src/governance/executor.ts +229 -0
- package/src/governance/index.ts +13 -0
- package/src/governance/types.ts +53 -0
- package/src/hooks/CONTEXT.md +23 -0
- package/src/hooks/__tests__/bootstrap.test.ts +184 -0
- package/src/hooks/bootstrap.ts +144 -0
- package/src/hooks/index.ts +15 -0
- package/src/hooks/pipeline.ts +157 -0
- package/src/hooks/registry.ts +88 -0
- package/src/hooks/types.ts +80 -0
- package/src/index.ts +198 -0
- package/src/knowledge/CONTEXT.md +29 -0
- package/src/knowledge/__tests__/doctor.test.ts +272 -0
- package/src/knowledge/__tests__/import.test.ts +376 -0
- package/src/knowledge/__tests__/ingest.test.ts +125 -0
- package/src/knowledge/__tests__/lifecycle-hooks.test.ts +137 -0
- package/src/knowledge/__tests__/lifecycle.test.ts +248 -0
- package/src/knowledge/__tests__/lint.test.ts +401 -0
- package/src/knowledge/__tests__/query.test.ts +185 -0
- package/src/knowledge/__tests__/reference-tracker.test.ts +129 -0
- package/src/knowledge/__tests__/store.test.ts +238 -0
- package/src/knowledge/doctor.ts +104 -0
- package/src/knowledge/import.ts +505 -0
- package/src/knowledge/index.ts +16 -0
- package/src/knowledge/ingest.ts +126 -0
- package/src/knowledge/lifecycle-hooks.ts +199 -0
- package/src/knowledge/lifecycle.ts +175 -0
- package/src/knowledge/lint.ts +360 -0
- package/src/knowledge/query.ts +150 -0
- package/src/knowledge/reference-tracker.ts +99 -0
- package/src/knowledge/store.ts +264 -0
- package/src/knowledge/types.ts +139 -0
- package/src/llm/CONTEXT.md +21 -0
- package/src/llm/__tests__/adapter.test.ts +172 -0
- package/src/llm/adapter.ts +149 -0
- package/src/llm/index.ts +2 -0
- package/src/llm/types.ts +81 -0
- package/src/monitoring/CONTEXT.md +29 -0
- package/src/monitoring/__tests__/context-tracker.test.ts +172 -0
- package/src/monitoring/__tests__/knowledge-doctor.test.ts +276 -0
- package/src/monitoring/__tests__/knowledge-evolver.test.ts +365 -0
- package/src/monitoring/__tests__/performance-analyzer.test.ts +137 -0
- package/src/monitoring/__tests__/performance-collector.test.ts +332 -0
- package/src/monitoring/__tests__/traces.test.ts +190 -0
- package/src/monitoring/constraint-doctor.ts +499 -0
- package/src/monitoring/constraint-evolver.ts +573 -0
- package/src/monitoring/context-tracker.ts +148 -0
- package/src/monitoring/index.ts +23 -0
- package/src/monitoring/knowledge-doctor.ts +323 -0
- package/src/monitoring/knowledge-evolver.ts +289 -0
- package/src/monitoring/performance-analyzer.ts +450 -0
- package/src/monitoring/performance-collector.ts +348 -0
- package/src/monitoring/trace-analyzer.ts +470 -0
- package/src/monitoring/traces.ts +339 -0
- package/src/presets/__tests__/standard.test.ts +104 -0
- package/src/presets/index.ts +16 -0
- package/src/presets/standard.ts +163 -0
- package/src/safety/CONTEXT.md +23 -0
- package/src/safety/__tests__/input-guardrail.test.ts +105 -0
- package/src/safety/__tests__/output-guardrail.test.ts +108 -0
- package/src/safety/__tests__/sandbox.test.ts +158 -0
- package/src/safety/__tests__/tool-guardrail.test.ts +127 -0
- package/src/safety/index.ts +5 -0
- package/src/safety/input-guardrail.ts +133 -0
- package/src/safety/output-guardrail.ts +174 -0
- package/src/safety/sandbox.ts +148 -0
- package/src/safety/tool-guardrail.ts +176 -0
- package/src/safety/types.ts +124 -0
- package/src/spec/CONTEXT.md +19 -0
- package/src/spec/__tests__/annotation-checker.test.ts +289 -0
- package/src/spec/annotation-checker.ts +342 -0
- package/src/tools/CONTEXT.md +25 -0
- package/src/tools/__tests__/loader.test.ts +252 -0
- package/src/tools/__tests__/registry.test.ts +157 -0
- package/src/tools/core/__tests__/core.test.ts +122 -0
- package/src/tools/core/index.ts +201 -0
- package/src/tools/core/package.json +7 -0
- package/src/tools/core/pnpm-lock.yaml +232 -0
- package/src/tools/definitions/core/code/fingerprint.sh +273 -0
- package/src/tools/definitions/core/code/fingerprint.yml +72 -0
- package/src/tools/definitions/core/code/parse.yml +68 -0
- package/src/tools/definitions/core/code/register-language.sh +475 -0
- package/src/tools/definitions/core/code/register-language.yml +74 -0
- package/src/tools/definitions/core/docker/build.yml +73 -0
- package/src/tools/definitions/core/docker/run.yml +81 -0
- package/src/tools/definitions/core/file/copy.yml +88 -0
- package/src/tools/definitions/core/file/read.yml +69 -0
- package/src/tools/definitions/core/file/write.yml +75 -0
- package/src/tools/definitions/core/git/branch.yml +61 -0
- package/src/tools/definitions/core/git/cleanup-worktree.yml +50 -0
- package/src/tools/definitions/core/git/clone.yml +69 -0
- package/src/tools/definitions/core/git/commit.yml +65 -0
- package/src/tools/definitions/core/git/push.yml +79 -0
- package/src/tools/definitions/core/git/worktree.yml +96 -0
- package/src/tools/definitions/core/notification/notify.sh +152 -0
- package/src/tools/definitions/core/notification/notify.yml +60 -0
- package/src/tools/definitions/core/npm/build.yml +75 -0
- package/src/tools/definitions/core/npm/install.yml +58 -0
- package/src/tools/definitions/core/npm/test.yml +75 -0
- package/src/tools/definitions/core/validation/check-reuse.yml +170 -0
- package/src/tools/definitions/core/validation/validate-handlers.yml +118 -0
- package/src/tools/definitions/core/validation/validate-readme-stats.yml +155 -0
- package/src/tools/definitions/core/validation/validate-yaml-syntax.yml +134 -0
- package/src/tools/definitions/ext/browser/browser-automate.sh +255 -0
- package/src/tools/definitions/ext/browser/browser-automate.yml +166 -0
- package/src/tools/definitions/ext/browser/browser-close.sh +104 -0
- package/src/tools/definitions/ext/browser/browser-close.yml +55 -0
- package/src/tools/definitions/ext/browser/browser-mcp-debug.sh +682 -0
- package/src/tools/definitions/ext/browser/browser-mcp-debug.yml +167 -0
- package/src/tools/definitions/ext/browser/browser-start.sh +101 -0
- package/src/tools/definitions/ext/browser/browser-start.yml +62 -0
- package/src/tools/definitions/registry.json +795 -0
- package/src/tools/definitions/std/README.md +350 -0
- package/src/tools/definitions/std/analysis/analyze-codebase.yml +72 -0
- package/src/tools/definitions/std/analysis/analyze-diff.yml +182 -0
- package/src/tools/definitions/std/analysis/analyze-git-diff.yml +70 -0
- package/src/tools/definitions/std/analysis/analyze-impact.yml +78 -0
- package/src/tools/definitions/std/analysis/analyze-requirements.yml +105 -0
- package/src/tools/definitions/std/analysis/brainstorm-options.yml +106 -0
- package/src/tools/definitions/std/analysis/build-graph.yml +154 -0
- package/src/tools/definitions/std/analysis/clarify-requirements.yml +90 -0
- package/src/tools/definitions/std/analysis/detect-context.yml +109 -0
- package/src/tools/definitions/std/analysis/detect-layers.yml +125 -0
- package/src/tools/definitions/std/analysis/generate-tour.yml +102 -0
- package/src/tools/definitions/std/analysis/search-enhance.yml +105 -0
- package/src/tools/definitions/std/backlog/add.yml +51 -0
- package/src/tools/definitions/std/backlog/decide.yml +39 -0
- package/src/tools/definitions/std/backlog/github-sync.yml +161 -0
- package/src/tools/definitions/std/backlog/list.yml +53 -0
- package/src/tools/definitions/std/backlog/load.yml +46 -0
- package/src/tools/definitions/std/backlog/resolve.yml +37 -0
- package/src/tools/definitions/std/backlog/update.yml +42 -0
- package/src/tools/definitions/std/bugfix/diagnose.yml +68 -0
- package/src/tools/definitions/std/bugfix/fix.yml +66 -0
- package/src/tools/definitions/std/bugfix/verify.yml +69 -0
- package/src/tools/definitions/std/constraint/check-decomposition.yml +103 -0
- package/src/tools/definitions/std/constraint/check-feature-list.yml +77 -0
- package/src/tools/definitions/std/constraint/check-progress.yml +97 -0
- package/src/tools/definitions/std/constraint/generate-report.yml +147 -0
- package/src/tools/definitions/std/deploy/commit-push.yml +33 -0
- package/src/tools/definitions/std/deploy/deploy-backend.yml +37 -0
- package/src/tools/definitions/std/deploy/deploy-frontend.yml +37 -0
- package/src/tools/definitions/std/deploy/rollback.yml +148 -0
- package/src/tools/definitions/std/design/analyze-architecture-impact.yml +113 -0
- package/src/tools/definitions/std/design/design-api.yml +55 -0
- package/src/tools/definitions/std/design/design-architecture.yml +97 -0
- package/src/tools/definitions/std/design/design-db.yml +81 -0
- package/src/tools/definitions/std/design/generate-spec.yml +182 -0
- package/src/tools/definitions/std/development/develop-api.yml +85 -0
- package/src/tools/definitions/std/development/develop-backend.yml +88 -0
- package/src/tools/definitions/std/development/develop-frontend.yml +87 -0
- package/src/tools/definitions/std/development/develop-shared-types.yml +74 -0
- package/src/tools/definitions/std/development/develop-task.yml +122 -0
- package/src/tools/definitions/std/development/develop-tests.yml +76 -0
- package/src/tools/definitions/std/development/execute-batch.yml +152 -0
- package/src/tools/definitions/std/development/fix-issues.yml +100 -0
- package/src/tools/definitions/std/development/implement-task.yml +124 -0
- package/src/tools/definitions/std/development/review-fix-cycle.yml +232 -0
- package/src/tools/definitions/std/evolution/implement.yml +125 -0
- package/src/tools/definitions/std/evolution/prioritize.yml +112 -0
- package/src/tools/definitions/std/evolution/report-gap.yml +166 -0
- package/src/tools/definitions/std/file/read.yml +21 -0
- package/src/tools/definitions/std/governance/aggregate-opinions.sh +201 -0
- package/src/tools/definitions/std/governance/aggregate-opinions.yml +79 -0
- package/src/tools/definitions/std/governance/audit-task.yml +178 -0
- package/src/tools/definitions/std/governance/cast-vote.yml +129 -0
- package/src/tools/definitions/std/governance/collect-issues.yml +16 -0
- package/src/tools/definitions/std/governance/create-signed-document.yml +23 -0
- package/src/tools/definitions/std/governance/create-voting-session.yml +101 -0
- package/src/tools/definitions/std/governance/define-stance.sh +243 -0
- package/src/tools/definitions/std/governance/define-stance.yml +82 -0
- package/src/tools/definitions/std/governance/generate-review-report.yml +23 -0
- package/src/tools/definitions/std/governance/impeach.yml +179 -0
- package/src/tools/definitions/std/governance/multi-stance-review.yml +154 -0
- package/src/tools/definitions/std/governance/prepare-artifact.yml +20 -0
- package/src/tools/definitions/std/governance/review-spec-approval.yml +262 -0
- package/src/tools/definitions/std/governance/rollback.yml +186 -0
- package/src/tools/definitions/std/governance/stance-review.yml +149 -0
- package/src/tools/definitions/std/governance/track-effect.yml +199 -0
- package/src/tools/definitions/std/governance/vote-tally.yml +144 -0
- package/src/tools/definitions/std/patch/execute.yml +51 -0
- package/src/tools/definitions/std/planning/generate-tasks.yml +36 -0
- package/src/tools/definitions/std/planning/load-tasks.yml +44 -0
- package/src/tools/definitions/std/planning/split-batch.yml +481 -0
- package/src/tools/definitions/std/planning/split-tasks.yml +359 -0
- package/src/tools/definitions/std/planning/update-tasks.yml +51 -0
- package/src/tools/definitions/std/planning/validate-tasks.yml +46 -0
- package/src/tools/definitions/std/project/decide-next-workflow.yml +38 -0
- package/src/tools/definitions/std/project/load-state.yml +31 -0
- package/src/tools/definitions/std/project/save-state.yml +32 -0
- package/src/tools/definitions/std/quality/check-quality.yml +241 -0
- package/src/tools/definitions/std/quality/debug-systematic.yml +163 -0
- package/src/tools/definitions/std/quality/handle-feedback.yml +108 -0
- package/src/tools/definitions/std/quality/review-code.yml +128 -0
- package/src/tools/definitions/std/quality/review-spec.yml +140 -0
- package/src/tools/definitions/std/quality/review-task.yml +190 -0
- package/src/tools/definitions/std/quality/run-tests.yml +80 -0
- package/src/tools/definitions/std/quick/analyze.yml +56 -0
- package/src/tools/definitions/std/quick/implement.yml +67 -0
- package/src/tools/definitions/std/quick/verify.yml +71 -0
- package/src/tools/definitions/std/verification/verify_completion.yml +113 -0
- package/src/tools/definitions/std/verification/wait-condition.yml +107 -0
- package/src/tools/index.ts +5 -0
- package/src/tools/loader.ts +216 -0
- package/src/tools/paths.ts +15 -0
- package/src/tools/registry.ts +128 -0
- package/src/tools/types.ts +46 -0
- package/src/types/__tests__/types.test.ts +86 -0
- package/src/types/checkpoint.ts +174 -0
- package/src/types/constraint.ts +335 -0
- package/src/types/cso.ts +37 -0
- package/src/types/enforcement.ts +48 -0
- package/src/types/index.ts +59 -0
- package/src/types/iron-law.ts +50 -0
- package/src/types/passes-gate.ts +185 -0
- package/src/types/performance.ts +295 -0
- package/src/types/project-config.ts +251 -0
- package/src/types/session.ts +132 -0
- package/src/types/spec.ts +91 -0
- package/src/types/trace.ts +228 -0
- package/src/utils/detect-source-roots.ts +114 -0
- package/src/utils/exec.ts +61 -0
- package/src/verification/CONTEXT.md +23 -0
- package/src/verification/__tests__/loop.test.ts +303 -0
- package/src/verification/__tests__/rules-based.test.ts +240 -0
- package/src/verification/index.ts +3 -0
- package/src/verification/loop.ts +137 -0
- package/src/verification/rules-based.ts +153 -0
- package/src/verification/types.ts +81 -0
|
@@ -0,0 +1,1268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* checker.ts 测试
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { ConstraintChecker, checkConstraints, checkConstraint } from '../core/constraints/checker';
|
|
6
|
+
import type { ConstraintContext } from '../types/constraint';
|
|
7
|
+
import { writeFileSync, mkdirSync, rmSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
|
|
10
|
+
describe('ConstraintChecker', () => {
|
|
11
|
+
const checker = ConstraintChecker.getInstance();
|
|
12
|
+
const tempDir = join(process.cwd(), 'temp-test-checker');
|
|
13
|
+
|
|
14
|
+
beforeAll(() => {
|
|
15
|
+
// 创建临时测试目录
|
|
16
|
+
mkdirSync(tempDir, { recursive: true });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
afterAll(() => {
|
|
20
|
+
// 清理临时测试目录
|
|
21
|
+
try {
|
|
22
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
23
|
+
} catch {
|
|
24
|
+
// ignore
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe('Iron Laws', () => {
|
|
29
|
+
it('should check no_bypass_checkpoint with skip patterns', async () => {
|
|
30
|
+
// 创建包含 skip 的文件
|
|
31
|
+
const skipFile = join(tempDir, 'skip-test.ts');
|
|
32
|
+
writeFileSync(skipFile, 'test.skip("skipped test", () => {});');
|
|
33
|
+
|
|
34
|
+
const context: ConstraintContext = {
|
|
35
|
+
operation: 'code_implementation',
|
|
36
|
+
changedFiles: [skipFile],
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const result = await checker.check(
|
|
40
|
+
{ id: 'no_bypass_checkpoint', level: 'iron_law', rule: 'NO BYPASS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
41
|
+
context
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
expect(result.satisfied).toBe(false);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should pass no_bypass_checkpoint without skip patterns', async () => {
|
|
48
|
+
const normalFile = join(tempDir, 'normal-test.ts');
|
|
49
|
+
writeFileSync(normalFile, 'test("normal test", () => { expect(true).toBe(true); });');
|
|
50
|
+
|
|
51
|
+
const context: ConstraintContext = {
|
|
52
|
+
operation: 'code_implementation',
|
|
53
|
+
changedFiles: [normalFile],
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const result = await checker.check(
|
|
57
|
+
{ id: 'no_bypass_checkpoint', level: 'iron_law', rule: 'NO BYPASS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
58
|
+
context
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
expect(result.satisfied).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should check no_self_approval with test evidence', async () => {
|
|
65
|
+
const contextWithTest: ConstraintContext = {
|
|
66
|
+
operation: 'code_implementation',
|
|
67
|
+
hasTest: true,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const contextWithoutTest: ConstraintContext = {
|
|
71
|
+
operation: 'code_implementation',
|
|
72
|
+
hasTest: false,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const resultWithTest = await checker.check(
|
|
76
|
+
{ id: 'no_self_approval', level: 'iron_law', rule: 'NO SELF APPROVAL', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
77
|
+
contextWithTest
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const resultWithoutTest = await checker.check(
|
|
81
|
+
{ id: 'no_self_approval', level: 'iron_law', rule: 'NO SELF APPROVAL', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
82
|
+
contextWithoutTest
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
expect(resultWithTest.satisfied).toBe(true);
|
|
86
|
+
expect(resultWithoutTest.satisfied).toBe(false);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should check no_completion_without_verification', async () => {
|
|
90
|
+
const contextWithEvidence: ConstraintContext = {
|
|
91
|
+
operation: 'code_implementation',
|
|
92
|
+
hasVerificationEvidence: true,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const contextWithoutEvidence: ConstraintContext = {
|
|
96
|
+
operation: 'code_implementation',
|
|
97
|
+
hasVerificationEvidence: false,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const resultWithEvidence = await checker.check(
|
|
101
|
+
{ id: 'no_completion_without_verification', level: 'iron_law', rule: 'NO COMPLETION', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
102
|
+
contextWithEvidence
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const resultWithoutEvidence = await checker.check(
|
|
106
|
+
{ id: 'no_completion_without_verification', level: 'iron_law', rule: 'NO COMPLETION', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
107
|
+
contextWithoutEvidence
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
expect(resultWithEvidence.satisfied).toBe(true);
|
|
111
|
+
expect(resultWithoutEvidence.satisfied).toBe(false);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('Guidelines', () => {
|
|
116
|
+
it('should check no_any_type with any in file', async () => {
|
|
117
|
+
const anyFile = join(tempDir, 'any-test.ts');
|
|
118
|
+
writeFileSync(anyFile, 'const x: any = "test";');
|
|
119
|
+
|
|
120
|
+
const context: ConstraintContext = {
|
|
121
|
+
operation: 'code_implementation',
|
|
122
|
+
changedFiles: [anyFile],
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const result = await checker.check(
|
|
126
|
+
{ id: 'no_any_type', level: 'guideline', rule: 'NO ANY', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
127
|
+
context
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
expect(result.satisfied).toBe(false);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should pass no_any_type without any type', async () => {
|
|
134
|
+
const safeFile = join(tempDir, 'safe-test.ts');
|
|
135
|
+
writeFileSync(safeFile, 'const x: string = "test";');
|
|
136
|
+
|
|
137
|
+
const context: ConstraintContext = {
|
|
138
|
+
operation: 'code_implementation',
|
|
139
|
+
changedFiles: [safeFile],
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const result = await checker.check(
|
|
143
|
+
{ id: 'no_any_type', level: 'guideline', rule: 'NO ANY', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
144
|
+
context
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
expect(result.satisfied).toBe(true);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('should check capability_sync without CAPABILITIES.md', async () => {
|
|
151
|
+
// 注意:tempDir 在 harness 仓库内,如果有缓存的变更,会检查到代码变更
|
|
152
|
+
// 所以需要创建一个无代码变更的场景或创建 CAPABILITIES.md
|
|
153
|
+
const context: ConstraintContext = {
|
|
154
|
+
operation: 'commit',
|
|
155
|
+
projectPath: tempDir,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// 创建 CAPABILITIES.md 文件确保测试通过
|
|
159
|
+
const fs = require('fs');
|
|
160
|
+
const path = require('path');
|
|
161
|
+
const capabilitiesPath = path.join(tempDir, 'CAPABILITIES.md');
|
|
162
|
+
fs.writeFileSync(capabilitiesPath, '# Capabilities\n');
|
|
163
|
+
|
|
164
|
+
const result = await checker.check(
|
|
165
|
+
{ id: 'capability_sync', level: 'guideline', rule: 'CAPABILITY SYNC', message: 'test', trigger: 'commit', enforcement: 'test' },
|
|
166
|
+
context
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
// 有 CAPABILITIES.md 文件,应该通过
|
|
170
|
+
expect(result.satisfied).toBe(true);
|
|
171
|
+
|
|
172
|
+
// 清理
|
|
173
|
+
fs.unlinkSync(capabilitiesPath);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('should check no_fix_without_root_cause', async () => {
|
|
177
|
+
const contextWithInvestigation: ConstraintContext = {
|
|
178
|
+
operation: 'code_implementation',
|
|
179
|
+
hasRootCauseInvestigation: true,
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const contextWithoutInvestigation: ConstraintContext = {
|
|
183
|
+
operation: 'code_implementation',
|
|
184
|
+
hasRootCauseInvestigation: false,
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const resultWith = await checker.check(
|
|
188
|
+
{ id: 'no_fix_without_root_cause', level: 'guideline', rule: 'NO FIX', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
189
|
+
contextWithInvestigation
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
const resultWithout = await checker.check(
|
|
193
|
+
{ id: 'no_fix_without_root_cause', level: 'guideline', rule: 'NO FIX', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
194
|
+
contextWithoutInvestigation
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
expect(resultWith.satisfied).toBe(true);
|
|
198
|
+
expect(resultWithout.satisfied).toBe(false);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('should check no_code_without_test', async () => {
|
|
202
|
+
const contextWithFailingTest: ConstraintContext = {
|
|
203
|
+
operation: 'code_implementation',
|
|
204
|
+
hasFailingTest: true,
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const contextWithoutTest: ConstraintContext = {
|
|
208
|
+
operation: 'code_implementation',
|
|
209
|
+
hasFailingTest: false,
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const resultWith = await checker.check(
|
|
213
|
+
{ id: 'no_code_without_test', level: 'guideline', rule: 'NO CODE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
214
|
+
contextWithFailingTest
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
const resultWithout = await checker.check(
|
|
218
|
+
{ id: 'no_code_without_test', level: 'guideline', rule: 'NO CODE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
219
|
+
contextWithoutTest
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
expect(resultWith.satisfied).toBe(true);
|
|
223
|
+
expect(resultWithout.satisfied).toBe(false);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it('should check reuse-first guidelines', async () => {
|
|
227
|
+
const contextWithReuseCheck: ConstraintContext = {
|
|
228
|
+
operation: 'code_implementation',
|
|
229
|
+
hasReuseCheck: true,
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
const contextWithoutReuseCheck: ConstraintContext = {
|
|
233
|
+
operation: 'code_implementation',
|
|
234
|
+
hasReuseCheck: false,
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
const resultWith = await checker.check(
|
|
238
|
+
{ id: 'no_creation_without_reuse_check', level: 'guideline', rule: 'REUSE FIRST', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
239
|
+
contextWithReuseCheck
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
const resultWithout = await checker.check(
|
|
243
|
+
{ id: 'no_creation_without_reuse_check', level: 'guideline', rule: 'REUSE FIRST', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
244
|
+
contextWithoutReuseCheck
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
expect(resultWith.satisfied).toBe(true);
|
|
248
|
+
expect(resultWithout.satisfied).toBe(false);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
describe('New Iron Laws', () => {
|
|
253
|
+
it('should check incremental_progress', async () => {
|
|
254
|
+
const contextWithSingleTask: ConstraintContext = {
|
|
255
|
+
operation: 'code_implementation',
|
|
256
|
+
hasSingleTask: true,
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const contextWithMultipleTasks: ConstraintContext = {
|
|
260
|
+
operation: 'code_implementation',
|
|
261
|
+
hasSingleTask: false,
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
const resultWith = await checker.check(
|
|
265
|
+
{ id: 'incremental_progress', level: 'iron_law', rule: 'ONE TASK', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
266
|
+
contextWithSingleTask
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
const resultWithout = await checker.check(
|
|
270
|
+
{ id: 'incremental_progress', level: 'iron_law', rule: 'ONE TASK', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
271
|
+
contextWithMultipleTasks
|
|
272
|
+
);
|
|
273
|
+
|
|
274
|
+
expect(resultWith.satisfied).toBe(true);
|
|
275
|
+
expect(resultWithout.satisfied).toBe(false);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it('should check verify_external_capability', async () => {
|
|
279
|
+
const contextVerified: ConstraintContext = {
|
|
280
|
+
operation: 'api_change',
|
|
281
|
+
hasExternalCapabilityVerification: true,
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
const contextNotVerified: ConstraintContext = {
|
|
285
|
+
operation: 'api_change',
|
|
286
|
+
hasExternalCapabilityVerification: false,
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
const resultVerified = await checker.check(
|
|
290
|
+
{ id: 'verify_external_capability', level: 'iron_law', rule: 'VERIFY', message: 'test', trigger: 'api_change', enforcement: 'test' },
|
|
291
|
+
contextVerified
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
const resultNotVerified = await checker.check(
|
|
295
|
+
{ id: 'verify_external_capability', level: 'iron_law', rule: 'VERIFY', message: 'test', trigger: 'api_change', enforcement: 'test' },
|
|
296
|
+
contextNotVerified
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
expect(resultVerified.satisfied).toBe(true);
|
|
300
|
+
expect(resultNotVerified.satisfied).toBe(false);
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
describe('Exception handling', () => {
|
|
305
|
+
it('should apply exception for no_fix_without_root_cause with simple_typo', async () => {
|
|
306
|
+
const context: ConstraintContext = {
|
|
307
|
+
operation: 'code_implementation',
|
|
308
|
+
hasRootCauseInvestigation: false,
|
|
309
|
+
isSimpleTypo: true,
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
const result = await checker.check(
|
|
313
|
+
{
|
|
314
|
+
id: 'no_fix_without_root_cause',
|
|
315
|
+
level: 'guideline',
|
|
316
|
+
rule: 'NO FIX',
|
|
317
|
+
message: 'test',
|
|
318
|
+
trigger: 'code_implementation',
|
|
319
|
+
enforcement: 'test',
|
|
320
|
+
exceptions: ['simple_typo'],
|
|
321
|
+
},
|
|
322
|
+
context
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
expect(result.satisfied).toBe(true);
|
|
326
|
+
expect(result.message).toContain('豁免');
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
it('should apply exception for scalability_required', async () => {
|
|
330
|
+
const context: ConstraintContext = {
|
|
331
|
+
operation: 'code_implementation',
|
|
332
|
+
hasReuseCheck: false,
|
|
333
|
+
scalabilityRequired: true,
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
const result = await checker.check(
|
|
337
|
+
{
|
|
338
|
+
id: 'simplest_solution_first',
|
|
339
|
+
level: 'guideline',
|
|
340
|
+
rule: 'SIMPLEST FIRST',
|
|
341
|
+
message: 'test',
|
|
342
|
+
trigger: 'code_implementation',
|
|
343
|
+
enforcement: 'test',
|
|
344
|
+
exceptions: ['scalability_required'],
|
|
345
|
+
},
|
|
346
|
+
context
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
expect(result.satisfied).toBe(true);
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
it('should apply exception for security_required', async () => {
|
|
353
|
+
const context: ConstraintContext = {
|
|
354
|
+
operation: 'code_implementation',
|
|
355
|
+
hasReuseCheck: false,
|
|
356
|
+
securityRequired: true,
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
const result = await checker.check(
|
|
360
|
+
{
|
|
361
|
+
id: 'simplest_solution_first',
|
|
362
|
+
level: 'guideline',
|
|
363
|
+
rule: 'SIMPLEST FIRST',
|
|
364
|
+
message: 'test',
|
|
365
|
+
trigger: 'code_implementation',
|
|
366
|
+
enforcement: 'test',
|
|
367
|
+
exceptions: ['security_required'],
|
|
368
|
+
},
|
|
369
|
+
context
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
expect(result.satisfied).toBe(true);
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
it('should apply exception for performance_required', async () => {
|
|
376
|
+
const context: ConstraintContext = {
|
|
377
|
+
operation: 'code_implementation',
|
|
378
|
+
hasReuseCheck: false,
|
|
379
|
+
performanceRequired: true,
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
const result = await checker.check(
|
|
383
|
+
{
|
|
384
|
+
id: 'simplest_solution_first',
|
|
385
|
+
level: 'guideline',
|
|
386
|
+
rule: 'SIMPLEST FIRST',
|
|
387
|
+
message: 'test',
|
|
388
|
+
trigger: 'code_implementation',
|
|
389
|
+
enforcement: 'test',
|
|
390
|
+
exceptions: ['performance_required'],
|
|
391
|
+
},
|
|
392
|
+
context
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
expect(result.satisfied).toBe(true);
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
it('should apply exception for reliability_required', async () => {
|
|
399
|
+
const context: ConstraintContext = {
|
|
400
|
+
operation: 'code_implementation',
|
|
401
|
+
hasReuseCheck: false,
|
|
402
|
+
reliabilityRequired: true,
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
const result = await checker.check(
|
|
406
|
+
{
|
|
407
|
+
id: 'simplest_solution_first',
|
|
408
|
+
level: 'guideline',
|
|
409
|
+
rule: 'SIMPLEST FIRST',
|
|
410
|
+
message: 'test',
|
|
411
|
+
trigger: 'code_implementation',
|
|
412
|
+
enforcement: 'test',
|
|
413
|
+
exceptions: ['reliability_required'],
|
|
414
|
+
},
|
|
415
|
+
context
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
expect(result.satisfied).toBe(true);
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
it('should apply exception for config_value_error', async () => {
|
|
422
|
+
const context: ConstraintContext = {
|
|
423
|
+
operation: 'code_implementation',
|
|
424
|
+
hasRootCauseInvestigation: false,
|
|
425
|
+
isConfigValueError: true,
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
const result = await checker.check(
|
|
429
|
+
{
|
|
430
|
+
id: 'no_fix_without_root_cause',
|
|
431
|
+
level: 'guideline',
|
|
432
|
+
rule: 'NO FIX',
|
|
433
|
+
message: 'test',
|
|
434
|
+
trigger: 'code_implementation',
|
|
435
|
+
enforcement: 'test',
|
|
436
|
+
exceptions: ['config_value_error'],
|
|
437
|
+
},
|
|
438
|
+
context
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
expect(result.satisfied).toBe(true);
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
it('should apply exception for missing_config', async () => {
|
|
445
|
+
const context: ConstraintContext = {
|
|
446
|
+
operation: 'code_implementation',
|
|
447
|
+
hasRootCauseInvestigation: false,
|
|
448
|
+
isMissingConfig: true,
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
const result = await checker.check(
|
|
452
|
+
{
|
|
453
|
+
id: 'no_fix_without_root_cause',
|
|
454
|
+
level: 'guideline',
|
|
455
|
+
rule: 'NO FIX',
|
|
456
|
+
message: 'test',
|
|
457
|
+
trigger: 'code_implementation',
|
|
458
|
+
enforcement: 'test',
|
|
459
|
+
exceptions: ['missing_config'],
|
|
460
|
+
},
|
|
461
|
+
context
|
|
462
|
+
);
|
|
463
|
+
|
|
464
|
+
expect(result.satisfied).toBe(true);
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
it('should apply exception for config_file', async () => {
|
|
468
|
+
const context: ConstraintContext = {
|
|
469
|
+
operation: 'code_implementation',
|
|
470
|
+
hasFailingTest: false,
|
|
471
|
+
isConfigFile: true,
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
const result = await checker.check(
|
|
475
|
+
{
|
|
476
|
+
id: 'no_code_without_test',
|
|
477
|
+
level: 'guideline',
|
|
478
|
+
rule: 'NO CODE',
|
|
479
|
+
message: 'test',
|
|
480
|
+
trigger: 'code_implementation',
|
|
481
|
+
enforcement: 'test',
|
|
482
|
+
exceptions: ['config_file'],
|
|
483
|
+
},
|
|
484
|
+
context
|
|
485
|
+
);
|
|
486
|
+
|
|
487
|
+
expect(result.satisfied).toBe(true);
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
it('should apply exception for type_definition', async () => {
|
|
491
|
+
const context: ConstraintContext = {
|
|
492
|
+
operation: 'code_implementation',
|
|
493
|
+
hasFailingTest: false,
|
|
494
|
+
isTypeDefinition: true,
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
const result = await checker.check(
|
|
498
|
+
{
|
|
499
|
+
id: 'no_code_without_test',
|
|
500
|
+
level: 'guideline',
|
|
501
|
+
rule: 'NO CODE',
|
|
502
|
+
message: 'test',
|
|
503
|
+
trigger: 'code_implementation',
|
|
504
|
+
enforcement: 'test',
|
|
505
|
+
exceptions: ['type_definition'],
|
|
506
|
+
},
|
|
507
|
+
context
|
|
508
|
+
);
|
|
509
|
+
|
|
510
|
+
expect(result.satisfied).toBe(true);
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
it('should apply exception for simple_accessor', async () => {
|
|
514
|
+
const context: ConstraintContext = {
|
|
515
|
+
operation: 'code_implementation',
|
|
516
|
+
hasFailingTest: false,
|
|
517
|
+
isSimpleAccessor: true,
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
const result = await checker.check(
|
|
521
|
+
{
|
|
522
|
+
id: 'no_code_without_test',
|
|
523
|
+
level: 'guideline',
|
|
524
|
+
rule: 'NO CODE',
|
|
525
|
+
message: 'test',
|
|
526
|
+
trigger: 'code_implementation',
|
|
527
|
+
enforcement: 'test',
|
|
528
|
+
exceptions: ['simple_accessor'],
|
|
529
|
+
},
|
|
530
|
+
context
|
|
531
|
+
);
|
|
532
|
+
|
|
533
|
+
expect(result.satisfied).toBe(true);
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
it('should apply exception for pure_display_component', async () => {
|
|
537
|
+
const context: ConstraintContext = {
|
|
538
|
+
operation: 'code_implementation',
|
|
539
|
+
hasFailingTest: false,
|
|
540
|
+
isPureDisplayComponent: true,
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
const result = await checker.check(
|
|
544
|
+
{
|
|
545
|
+
id: 'no_code_without_test',
|
|
546
|
+
level: 'guideline',
|
|
547
|
+
rule: 'NO CODE',
|
|
548
|
+
message: 'test',
|
|
549
|
+
trigger: 'code_implementation',
|
|
550
|
+
enforcement: 'test',
|
|
551
|
+
exceptions: ['pure_display_component'],
|
|
552
|
+
},
|
|
553
|
+
context
|
|
554
|
+
);
|
|
555
|
+
|
|
556
|
+
expect(result.satisfied).toBe(true);
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
it('should apply exception for json_parse_result', async () => {
|
|
560
|
+
const context: ConstraintContext = {
|
|
561
|
+
operation: 'code_implementation',
|
|
562
|
+
changedFiles: [],
|
|
563
|
+
isJsonParseResult: true,
|
|
564
|
+
};
|
|
565
|
+
|
|
566
|
+
const result = await checker.check(
|
|
567
|
+
{
|
|
568
|
+
id: 'no_any_type',
|
|
569
|
+
level: 'guideline',
|
|
570
|
+
rule: 'NO ANY',
|
|
571
|
+
message: 'test',
|
|
572
|
+
trigger: 'code_implementation',
|
|
573
|
+
enforcement: 'test',
|
|
574
|
+
exceptions: ['json_parse_result'],
|
|
575
|
+
},
|
|
576
|
+
context
|
|
577
|
+
);
|
|
578
|
+
|
|
579
|
+
expect(result.satisfied).toBe(true);
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
it('should apply exception for third_party_no_types', async () => {
|
|
583
|
+
const context: ConstraintContext = {
|
|
584
|
+
operation: 'code_implementation',
|
|
585
|
+
changedFiles: [],
|
|
586
|
+
isThirdPartyNoTypes: true,
|
|
587
|
+
};
|
|
588
|
+
|
|
589
|
+
const result = await checker.check(
|
|
590
|
+
{
|
|
591
|
+
id: 'no_any_type',
|
|
592
|
+
level: 'guideline',
|
|
593
|
+
rule: 'NO ANY',
|
|
594
|
+
message: 'test',
|
|
595
|
+
trigger: 'code_implementation',
|
|
596
|
+
enforcement: 'test',
|
|
597
|
+
exceptions: ['third_party_no_types'],
|
|
598
|
+
},
|
|
599
|
+
context
|
|
600
|
+
);
|
|
601
|
+
|
|
602
|
+
expect(result.satisfied).toBe(true);
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
it('should apply exception for legacy_migration', async () => {
|
|
606
|
+
const context: ConstraintContext = {
|
|
607
|
+
operation: 'code_implementation',
|
|
608
|
+
changedFiles: [],
|
|
609
|
+
isLegacyMigration: true,
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
const result = await checker.check(
|
|
613
|
+
{
|
|
614
|
+
id: 'no_any_type',
|
|
615
|
+
level: 'guideline',
|
|
616
|
+
rule: 'NO ANY',
|
|
617
|
+
message: 'test',
|
|
618
|
+
trigger: 'code_implementation',
|
|
619
|
+
enforcement: 'test',
|
|
620
|
+
exceptions: ['legacy_migration'],
|
|
621
|
+
},
|
|
622
|
+
context
|
|
623
|
+
);
|
|
624
|
+
|
|
625
|
+
expect(result.satisfied).toBe(true);
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
it('should apply exception for internal_refactor', async () => {
|
|
629
|
+
const context: ConstraintContext = {
|
|
630
|
+
operation: 'commit',
|
|
631
|
+
projectPath: tempDir,
|
|
632
|
+
isInternalRefactor: true,
|
|
633
|
+
};
|
|
634
|
+
|
|
635
|
+
const result = await checker.check(
|
|
636
|
+
{
|
|
637
|
+
id: 'capability_sync',
|
|
638
|
+
level: 'guideline',
|
|
639
|
+
rule: 'CAPABILITY SYNC',
|
|
640
|
+
message: 'test',
|
|
641
|
+
trigger: 'commit',
|
|
642
|
+
enforcement: 'test',
|
|
643
|
+
exceptions: ['internal_refactor'],
|
|
644
|
+
},
|
|
645
|
+
context
|
|
646
|
+
);
|
|
647
|
+
|
|
648
|
+
expect(result.satisfied).toBe(true);
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
it('should apply exception for bug_fix_only', async () => {
|
|
652
|
+
const context: ConstraintContext = {
|
|
653
|
+
operation: 'commit',
|
|
654
|
+
projectPath: tempDir,
|
|
655
|
+
isBugFixOnly: true,
|
|
656
|
+
};
|
|
657
|
+
|
|
658
|
+
const result = await checker.check(
|
|
659
|
+
{
|
|
660
|
+
id: 'capability_sync',
|
|
661
|
+
level: 'guideline',
|
|
662
|
+
rule: 'CAPABILITY SYNC',
|
|
663
|
+
message: 'test',
|
|
664
|
+
trigger: 'commit',
|
|
665
|
+
enforcement: 'test',
|
|
666
|
+
exceptions: ['bug_fix_only'],
|
|
667
|
+
},
|
|
668
|
+
context
|
|
669
|
+
);
|
|
670
|
+
|
|
671
|
+
expect(result.satisfied).toBe(true);
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
it('should apply exception for performance_optimization', async () => {
|
|
675
|
+
const context: ConstraintContext = {
|
|
676
|
+
operation: 'commit',
|
|
677
|
+
projectPath: tempDir,
|
|
678
|
+
isPerformanceOptimization: true,
|
|
679
|
+
};
|
|
680
|
+
|
|
681
|
+
const result = await checker.check(
|
|
682
|
+
{
|
|
683
|
+
id: 'capability_sync',
|
|
684
|
+
level: 'guideline',
|
|
685
|
+
rule: 'CAPABILITY SYNC',
|
|
686
|
+
message: 'test',
|
|
687
|
+
trigger: 'commit',
|
|
688
|
+
enforcement: 'test',
|
|
689
|
+
exceptions: ['performance_optimization'],
|
|
690
|
+
},
|
|
691
|
+
context
|
|
692
|
+
);
|
|
693
|
+
|
|
694
|
+
expect(result.satisfied).toBe(true);
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
it('should apply exception for redundant_code_cleanup', async () => {
|
|
698
|
+
const context: ConstraintContext = {
|
|
699
|
+
operation: 'commit',
|
|
700
|
+
projectPath: tempDir,
|
|
701
|
+
isRedundantCodeCleanup: true,
|
|
702
|
+
};
|
|
703
|
+
|
|
704
|
+
const result = await checker.check(
|
|
705
|
+
{
|
|
706
|
+
id: 'no_simplification_without_approval',
|
|
707
|
+
level: 'guideline',
|
|
708
|
+
rule: 'NO SIMPLIFICATION',
|
|
709
|
+
message: 'test',
|
|
710
|
+
trigger: 'commit',
|
|
711
|
+
enforcement: 'test',
|
|
712
|
+
exceptions: ['redundant_code_cleanup'],
|
|
713
|
+
},
|
|
714
|
+
context
|
|
715
|
+
);
|
|
716
|
+
|
|
717
|
+
expect(result.satisfied).toBe(true);
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
it('should apply exception for same_effect_refactor', async () => {
|
|
721
|
+
const context: ConstraintContext = {
|
|
722
|
+
operation: 'commit',
|
|
723
|
+
projectPath: tempDir,
|
|
724
|
+
isSameEffectRefactor: true,
|
|
725
|
+
};
|
|
726
|
+
|
|
727
|
+
const result = await checker.check(
|
|
728
|
+
{
|
|
729
|
+
id: 'no_simplification_without_approval',
|
|
730
|
+
level: 'guideline',
|
|
731
|
+
rule: 'NO SIMPLIFICATION',
|
|
732
|
+
message: 'test',
|
|
733
|
+
trigger: 'commit',
|
|
734
|
+
enforcement: 'test',
|
|
735
|
+
exceptions: ['same_effect_refactor'],
|
|
736
|
+
},
|
|
737
|
+
context
|
|
738
|
+
);
|
|
739
|
+
|
|
740
|
+
expect(result.satisfied).toBe(true);
|
|
741
|
+
});
|
|
742
|
+
|
|
743
|
+
it('should apply exception for unused_code_removal', async () => {
|
|
744
|
+
const context: ConstraintContext = {
|
|
745
|
+
operation: 'commit',
|
|
746
|
+
projectPath: tempDir,
|
|
747
|
+
isUnusedCodeRemoval: true,
|
|
748
|
+
};
|
|
749
|
+
|
|
750
|
+
const result = await checker.check(
|
|
751
|
+
{
|
|
752
|
+
id: 'no_simplification_without_approval',
|
|
753
|
+
level: 'guideline',
|
|
754
|
+
rule: 'NO SIMPLIFICATION',
|
|
755
|
+
message: 'test',
|
|
756
|
+
trigger: 'commit',
|
|
757
|
+
enforcement: 'test',
|
|
758
|
+
exceptions: ['unused_code_removal'],
|
|
759
|
+
},
|
|
760
|
+
context
|
|
761
|
+
);
|
|
762
|
+
|
|
763
|
+
expect(result.satisfied).toBe(true);
|
|
764
|
+
});
|
|
765
|
+
});
|
|
766
|
+
|
|
767
|
+
describe('Deprecated functions', () => {
|
|
768
|
+
it('getAllLaws should work', () => {
|
|
769
|
+
const { getAllLaws } = require('../core/constraints/definitions');
|
|
770
|
+
const laws = getAllLaws();
|
|
771
|
+
expect(Array.isArray(laws)).toBe(true);
|
|
772
|
+
expect(laws.length).toBeGreaterThan(0);
|
|
773
|
+
});
|
|
774
|
+
|
|
775
|
+
it('findLawsByTrigger should work', () => {
|
|
776
|
+
const { findLawsByTrigger } = require('../core/constraints/definitions');
|
|
777
|
+
const laws = findLawsByTrigger('code_implementation');
|
|
778
|
+
expect(Array.isArray(laws)).toBe(true);
|
|
779
|
+
});
|
|
780
|
+
|
|
781
|
+
it('getLaw should work', () => {
|
|
782
|
+
const { getLaw } = require('../core/constraints/definitions');
|
|
783
|
+
const law = getLaw('no_bypass_checkpoint');
|
|
784
|
+
expect(law).toBeDefined();
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
it('filterLawsBySeverity should work', () => {
|
|
788
|
+
const { filterLawsBySeverity } = require('../core/constraints/definitions');
|
|
789
|
+
const errors = filterLawsBySeverity('error');
|
|
790
|
+
expect(Array.isArray(errors)).toBe(true);
|
|
791
|
+
|
|
792
|
+
const warnings = filterLawsBySeverity('warning');
|
|
793
|
+
expect(Array.isArray(warnings)).toBe(true);
|
|
794
|
+
|
|
795
|
+
const infos = filterLawsBySeverity('info');
|
|
796
|
+
expect(Array.isArray(infos)).toBe(true);
|
|
797
|
+
});
|
|
798
|
+
});
|
|
799
|
+
|
|
800
|
+
describe('Helper functions', () => {
|
|
801
|
+
it('should check single constraint via checkConstraint', async () => {
|
|
802
|
+
const context: ConstraintContext = {
|
|
803
|
+
operation: 'code_implementation',
|
|
804
|
+
hasTest: true,
|
|
805
|
+
};
|
|
806
|
+
|
|
807
|
+
const result = await checkConstraint('no_self_approval', context);
|
|
808
|
+
expect(result.satisfied).toBe(true);
|
|
809
|
+
});
|
|
810
|
+
|
|
811
|
+
it('should return false for unknown constraint', async () => {
|
|
812
|
+
const context: ConstraintContext = {
|
|
813
|
+
operation: 'code_implementation',
|
|
814
|
+
};
|
|
815
|
+
|
|
816
|
+
const result = await checkConstraint('unknown_constraint', context);
|
|
817
|
+
expect(result.satisfied).toBe(false);
|
|
818
|
+
expect(result.message).toContain('未知的约束');
|
|
819
|
+
});
|
|
820
|
+
});
|
|
821
|
+
|
|
822
|
+
describe('Text pattern constraints', () => {
|
|
823
|
+
it('no_fuzzy_completion_claim should detect Chinese fuzzy words', async () => {
|
|
824
|
+
const context: ConstraintContext = {
|
|
825
|
+
operation: 'code_implementation',
|
|
826
|
+
completionClaimText: '应该没问题,大概完成了',
|
|
827
|
+
};
|
|
828
|
+
|
|
829
|
+
const result = await checker.check(
|
|
830
|
+
{ id: 'no_fuzzy_completion_claim', level: 'iron_law', rule: 'NO FUZZY', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
831
|
+
context
|
|
832
|
+
);
|
|
833
|
+
|
|
834
|
+
expect(result.satisfied).toBe(false);
|
|
835
|
+
});
|
|
836
|
+
|
|
837
|
+
it('no_fuzzy_completion_claim should pass clean text', async () => {
|
|
838
|
+
const context: ConstraintContext = {
|
|
839
|
+
operation: 'code_implementation',
|
|
840
|
+
completionClaimText: '142 tests passed, coverage 87.3%',
|
|
841
|
+
};
|
|
842
|
+
|
|
843
|
+
const result = await checker.check(
|
|
844
|
+
{ id: 'no_fuzzy_completion_claim', level: 'iron_law', rule: 'NO FUZZY', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
845
|
+
context
|
|
846
|
+
);
|
|
847
|
+
|
|
848
|
+
expect(result.satisfied).toBe(true);
|
|
849
|
+
});
|
|
850
|
+
|
|
851
|
+
it('no_fuzzy_completion_claim should pass with empty text', async () => {
|
|
852
|
+
const context: ConstraintContext = {
|
|
853
|
+
operation: 'code_implementation',
|
|
854
|
+
completionClaimText: '',
|
|
855
|
+
};
|
|
856
|
+
|
|
857
|
+
const result = await checker.check(
|
|
858
|
+
{ id: 'no_fuzzy_completion_claim', level: 'iron_law', rule: 'NO FUZZY', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
859
|
+
context
|
|
860
|
+
);
|
|
861
|
+
|
|
862
|
+
expect(result.satisfied).toBe(true);
|
|
863
|
+
});
|
|
864
|
+
|
|
865
|
+
it('no_performative_agreement should detect performative patterns', async () => {
|
|
866
|
+
const context: ConstraintContext = {
|
|
867
|
+
operation: 'design_request',
|
|
868
|
+
taskDescription: '好的,我来做',
|
|
869
|
+
};
|
|
870
|
+
|
|
871
|
+
const result = await checker.check(
|
|
872
|
+
{ id: 'no_performative_agreement', level: 'iron_law', rule: 'NO PERFORMATIVE', message: 'test', trigger: 'design_request', enforcement: 'test' },
|
|
873
|
+
context
|
|
874
|
+
);
|
|
875
|
+
|
|
876
|
+
expect(result.satisfied).toBe(false);
|
|
877
|
+
});
|
|
878
|
+
|
|
879
|
+
it('no_performative_agreement should pass with analysis', async () => {
|
|
880
|
+
const context: ConstraintContext = {
|
|
881
|
+
operation: 'design_request',
|
|
882
|
+
taskDescription: 'This is a detailed analysis of the problem with multiple considerations and proposed solutions.',
|
|
883
|
+
};
|
|
884
|
+
|
|
885
|
+
const result = await checker.check(
|
|
886
|
+
{ id: 'no_performative_agreement', level: 'iron_law', rule: 'NO PERFORMATIVE', message: 'test', trigger: 'design_request', enforcement: 'test' },
|
|
887
|
+
context
|
|
888
|
+
);
|
|
889
|
+
|
|
890
|
+
expect(result.satisfied).toBe(true);
|
|
891
|
+
});
|
|
892
|
+
|
|
893
|
+
it('no_claim_without_evidence should pass with verification evidence', async () => {
|
|
894
|
+
const context: ConstraintContext = {
|
|
895
|
+
operation: 'code_implementation',
|
|
896
|
+
hasVerificationEvidence: true,
|
|
897
|
+
};
|
|
898
|
+
|
|
899
|
+
const result = await checker.check(
|
|
900
|
+
{ id: 'no_claim_without_evidence', level: 'guideline', rule: 'NO CLAIM', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
901
|
+
context
|
|
902
|
+
);
|
|
903
|
+
|
|
904
|
+
expect(result.satisfied).toBe(true);
|
|
905
|
+
});
|
|
906
|
+
|
|
907
|
+
it('no_claim_without_evidence should pass with taskDescription containing test', async () => {
|
|
908
|
+
const context: ConstraintContext = {
|
|
909
|
+
operation: 'code_implementation',
|
|
910
|
+
hasVerificationEvidence: false,
|
|
911
|
+
taskDescription: 'Need to run the test suite to verify',
|
|
912
|
+
};
|
|
913
|
+
|
|
914
|
+
const result = await checker.check(
|
|
915
|
+
{ id: 'no_claim_without_evidence', level: 'guideline', rule: 'NO CLAIM', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
916
|
+
context
|
|
917
|
+
);
|
|
918
|
+
|
|
919
|
+
expect(result.satisfied).toBe(true);
|
|
920
|
+
});
|
|
921
|
+
|
|
922
|
+
it('no_claim_without_evidence should fail without evidence', async () => {
|
|
923
|
+
const context: ConstraintContext = {
|
|
924
|
+
operation: 'code_implementation',
|
|
925
|
+
hasVerificationEvidence: false,
|
|
926
|
+
hasTest: false,
|
|
927
|
+
taskDescription: 'Did some work',
|
|
928
|
+
};
|
|
929
|
+
|
|
930
|
+
const result = await checker.check(
|
|
931
|
+
{ id: 'no_claim_without_evidence', level: 'guideline', rule: 'NO CLAIM', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
932
|
+
context
|
|
933
|
+
);
|
|
934
|
+
|
|
935
|
+
expect(result.satisfied).toBe(false);
|
|
936
|
+
});
|
|
937
|
+
|
|
938
|
+
it('no_delete_without_context should pass with requirement review', async () => {
|
|
939
|
+
const context: ConstraintContext = {
|
|
940
|
+
operation: 'file_deletion',
|
|
941
|
+
hasRequirementReview: true,
|
|
942
|
+
};
|
|
943
|
+
|
|
944
|
+
const result = await checker.check(
|
|
945
|
+
{ id: 'no_delete_without_context', level: 'guideline', rule: 'NO DELETE', message: 'test', trigger: 'file_deletion', enforcement: 'test' },
|
|
946
|
+
context
|
|
947
|
+
);
|
|
948
|
+
|
|
949
|
+
expect(result.satisfied).toBe(true);
|
|
950
|
+
});
|
|
951
|
+
|
|
952
|
+
it('no_delete_without_context should pass with existing design', async () => {
|
|
953
|
+
const context: ConstraintContext = {
|
|
954
|
+
operation: 'file_deletion',
|
|
955
|
+
hasRequirementReview: false,
|
|
956
|
+
hasRequirement: false,
|
|
957
|
+
isExistingDesign: true,
|
|
958
|
+
};
|
|
959
|
+
|
|
960
|
+
const result = await checker.check(
|
|
961
|
+
{ id: 'no_delete_without_context', level: 'guideline', rule: 'NO DELETE', message: 'test', trigger: 'file_deletion', enforcement: 'test' },
|
|
962
|
+
context
|
|
963
|
+
);
|
|
964
|
+
|
|
965
|
+
expect(result.satisfied).toBe(true);
|
|
966
|
+
});
|
|
967
|
+
|
|
968
|
+
it('no_delete_without_context should fail without any context', async () => {
|
|
969
|
+
const context: ConstraintContext = {
|
|
970
|
+
operation: 'file_deletion',
|
|
971
|
+
hasRequirementReview: false,
|
|
972
|
+
hasRequirement: false,
|
|
973
|
+
isExistingDesign: false,
|
|
974
|
+
};
|
|
975
|
+
|
|
976
|
+
const result = await checker.check(
|
|
977
|
+
{ id: 'no_delete_without_context', level: 'guideline', rule: 'NO DELETE', message: 'test', trigger: 'file_deletion', enforcement: 'test' },
|
|
978
|
+
context
|
|
979
|
+
);
|
|
980
|
+
|
|
981
|
+
expect(result.satisfied).toBe(false);
|
|
982
|
+
});
|
|
983
|
+
});
|
|
984
|
+
|
|
985
|
+
describe('Behavior guidelines (always true)', () => {
|
|
986
|
+
it('surgical_changes_only should return true', async () => {
|
|
987
|
+
const context: ConstraintContext = { operation: 'code_implementation' };
|
|
988
|
+
const result = await checker.check(
|
|
989
|
+
{ id: 'surgical_changes_only', level: 'guideline', rule: 'SURGICAL', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
990
|
+
context
|
|
991
|
+
);
|
|
992
|
+
expect(result.satisfied).toBe(true);
|
|
993
|
+
});
|
|
994
|
+
|
|
995
|
+
it('no_model_for_deterministic should return true', async () => {
|
|
996
|
+
const context: ConstraintContext = { operation: 'code_implementation' };
|
|
997
|
+
const result = await checker.check(
|
|
998
|
+
{ id: 'no_model_for_deterministic', level: 'guideline', rule: 'NO MODEL', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
999
|
+
context
|
|
1000
|
+
);
|
|
1001
|
+
expect(result.satisfied).toBe(true);
|
|
1002
|
+
});
|
|
1003
|
+
|
|
1004
|
+
it('no_conflict_blending should return true', async () => {
|
|
1005
|
+
const context: ConstraintContext = { operation: 'code_implementation' };
|
|
1006
|
+
const result = await checker.check(
|
|
1007
|
+
{ id: 'no_conflict_blending', level: 'guideline', rule: 'NO BLEND', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1008
|
+
context
|
|
1009
|
+
);
|
|
1010
|
+
expect(result.satisfied).toBe(true);
|
|
1011
|
+
});
|
|
1012
|
+
|
|
1013
|
+
it('read_before_write should return true', async () => {
|
|
1014
|
+
const context: ConstraintContext = { operation: 'code_implementation' };
|
|
1015
|
+
const result = await checker.check(
|
|
1016
|
+
{ id: 'read_before_write', level: 'guideline', rule: 'READ FIRST', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1017
|
+
context
|
|
1018
|
+
);
|
|
1019
|
+
expect(result.satisfied).toBe(true);
|
|
1020
|
+
});
|
|
1021
|
+
|
|
1022
|
+
it('first_principles_first should return true', async () => {
|
|
1023
|
+
const context: ConstraintContext = { operation: 'code_implementation' };
|
|
1024
|
+
const result = await checker.check(
|
|
1025
|
+
{ id: 'first_principles_first', level: 'guideline', rule: 'PRINCIPLES', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1026
|
+
context
|
|
1027
|
+
);
|
|
1028
|
+
expect(result.satisfied).toBe(true);
|
|
1029
|
+
});
|
|
1030
|
+
|
|
1031
|
+
it('fix_the_problem_not_the_gate should return true', async () => {
|
|
1032
|
+
const context: ConstraintContext = { operation: 'code_implementation' };
|
|
1033
|
+
const result = await checker.check(
|
|
1034
|
+
{ id: 'fix_the_problem_not_the_gate', level: 'guideline', rule: 'FIX PROBLEM', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1035
|
+
context
|
|
1036
|
+
);
|
|
1037
|
+
expect(result.satisfied).toBe(true);
|
|
1038
|
+
});
|
|
1039
|
+
|
|
1040
|
+
it('diagnosis_to_fix_gate should return true', async () => {
|
|
1041
|
+
const context: ConstraintContext = { operation: 'code_implementation' };
|
|
1042
|
+
const result = await checker.check(
|
|
1043
|
+
{ id: 'diagnosis_to_fix_gate', level: 'guideline', rule: 'DIAGNOSIS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1044
|
+
context
|
|
1045
|
+
);
|
|
1046
|
+
expect(result.satisfied).toBe(true);
|
|
1047
|
+
});
|
|
1048
|
+
|
|
1049
|
+
it('follow_conventions should return true', async () => {
|
|
1050
|
+
const context: ConstraintContext = { operation: 'code_implementation' };
|
|
1051
|
+
const result = await checker.check(
|
|
1052
|
+
{ id: 'follow_conventions', level: 'guideline', rule: 'CONVENTIONS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1053
|
+
context
|
|
1054
|
+
);
|
|
1055
|
+
expect(result.satisfied).toBe(true);
|
|
1056
|
+
});
|
|
1057
|
+
});
|
|
1058
|
+
|
|
1059
|
+
describe('Default guideline constraints', () => {
|
|
1060
|
+
it('no_hardcoded_credentials should pass by default', async () => {
|
|
1061
|
+
const context: ConstraintContext = { operation: 'code_implementation' };
|
|
1062
|
+
const result = await checker.check(
|
|
1063
|
+
{ id: 'no_hardcoded_credentials', level: 'guideline', rule: 'NO CREDENTIALS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1064
|
+
context
|
|
1065
|
+
);
|
|
1066
|
+
expect(result.satisfied).toBe(true);
|
|
1067
|
+
});
|
|
1068
|
+
|
|
1069
|
+
it('design_decision_requires_discussion should pass by default', async () => {
|
|
1070
|
+
const context: ConstraintContext = { operation: 'code_implementation' };
|
|
1071
|
+
const result = await checker.check(
|
|
1072
|
+
{ id: 'design_decision_requires_discussion', level: 'guideline', rule: 'DISCUSS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1073
|
+
context
|
|
1074
|
+
);
|
|
1075
|
+
expect(result.satisfied).toBe(true);
|
|
1076
|
+
});
|
|
1077
|
+
});
|
|
1078
|
+
|
|
1079
|
+
describe('Additional Iron Laws (pure context)', () => {
|
|
1080
|
+
it('no_implementation_without_requirement_review should pass with review', async () => {
|
|
1081
|
+
const context: ConstraintContext = { operation: 'code_implementation', hasRequirementReview: true };
|
|
1082
|
+
const result = await checker.check(
|
|
1083
|
+
{ id: 'no_implementation_without_requirement_review', level: 'iron_law', rule: 'REVIEW REQ', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1084
|
+
context
|
|
1085
|
+
);
|
|
1086
|
+
expect(result.satisfied).toBe(true);
|
|
1087
|
+
});
|
|
1088
|
+
|
|
1089
|
+
it('no_implementation_without_requirement_review should fail without review', async () => {
|
|
1090
|
+
const context: ConstraintContext = { operation: 'code_implementation', hasRequirementReview: false };
|
|
1091
|
+
const result = await checker.check(
|
|
1092
|
+
{ id: 'no_implementation_without_requirement_review', level: 'iron_law', rule: 'REVIEW REQ', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1093
|
+
context
|
|
1094
|
+
);
|
|
1095
|
+
expect(result.satisfied).toBe(false);
|
|
1096
|
+
});
|
|
1097
|
+
|
|
1098
|
+
it('no_implementation_without_requirement should pass with requirement', async () => {
|
|
1099
|
+
const context: ConstraintContext = { operation: 'code_implementation', hasRequirement: true };
|
|
1100
|
+
const result = await checker.check(
|
|
1101
|
+
{ id: 'no_implementation_without_requirement', level: 'iron_law', rule: 'REQ EXISTS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1102
|
+
context
|
|
1103
|
+
);
|
|
1104
|
+
expect(result.satisfied).toBe(true);
|
|
1105
|
+
});
|
|
1106
|
+
|
|
1107
|
+
it('no_implementation_without_requirement should fail without requirement', async () => {
|
|
1108
|
+
const context: ConstraintContext = { operation: 'code_implementation', hasRequirement: false };
|
|
1109
|
+
const result = await checker.check(
|
|
1110
|
+
{ id: 'no_implementation_without_requirement', level: 'iron_law', rule: 'REQ EXISTS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1111
|
+
context
|
|
1112
|
+
);
|
|
1113
|
+
expect(result.satisfied).toBe(false);
|
|
1114
|
+
});
|
|
1115
|
+
|
|
1116
|
+
it('must_use_worktree should pass with worktree', async () => {
|
|
1117
|
+
const context: ConstraintContext = { operation: 'code_implementation', hasWorktree: true };
|
|
1118
|
+
const result = await checker.check(
|
|
1119
|
+
{ id: 'must_use_worktree', level: 'iron_law', rule: 'WORKTREE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1120
|
+
context
|
|
1121
|
+
);
|
|
1122
|
+
expect(result.satisfied).toBe(true);
|
|
1123
|
+
});
|
|
1124
|
+
|
|
1125
|
+
it('must_use_worktree should fail without worktree', async () => {
|
|
1126
|
+
const context: ConstraintContext = { operation: 'code_implementation', hasWorktree: false };
|
|
1127
|
+
const result = await checker.check(
|
|
1128
|
+
{ id: 'must_use_worktree', level: 'iron_law', rule: 'WORKTREE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1129
|
+
context
|
|
1130
|
+
);
|
|
1131
|
+
expect(result.satisfied).toBe(false);
|
|
1132
|
+
});
|
|
1133
|
+
|
|
1134
|
+
it('two_stage_review_required should pass with two-stage review', async () => {
|
|
1135
|
+
const context: ConstraintContext = { operation: 'code_implementation', hasTwoStageReview: true };
|
|
1136
|
+
const result = await checker.check(
|
|
1137
|
+
{ id: 'two_stage_review_required', level: 'iron_law', rule: 'TWO STAGE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1138
|
+
context
|
|
1139
|
+
);
|
|
1140
|
+
expect(result.satisfied).toBe(true);
|
|
1141
|
+
});
|
|
1142
|
+
|
|
1143
|
+
it('two_stage_review_required should fail without two-stage review', async () => {
|
|
1144
|
+
const context: ConstraintContext = { operation: 'code_implementation', hasTwoStageReview: false };
|
|
1145
|
+
const result = await checker.check(
|
|
1146
|
+
{ id: 'two_stage_review_required', level: 'iron_law', rule: 'TWO STAGE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1147
|
+
context
|
|
1148
|
+
);
|
|
1149
|
+
expect(result.satisfied).toBe(false);
|
|
1150
|
+
});
|
|
1151
|
+
});
|
|
1152
|
+
|
|
1153
|
+
describe('Additional guidelines (pure context)', () => {
|
|
1154
|
+
it('no_skill_without_test should pass with test', async () => {
|
|
1155
|
+
const context: ConstraintContext = { operation: 'module_creation', hasTest: true };
|
|
1156
|
+
const result = await checker.check(
|
|
1157
|
+
{ id: 'no_skill_without_test', level: 'guideline', rule: 'SKILL TEST', message: 'test', trigger: 'module_creation', enforcement: 'test' },
|
|
1158
|
+
context
|
|
1159
|
+
);
|
|
1160
|
+
expect(result.satisfied).toBe(true);
|
|
1161
|
+
});
|
|
1162
|
+
|
|
1163
|
+
it('no_skill_without_test should fail without test', async () => {
|
|
1164
|
+
const context: ConstraintContext = { operation: 'module_creation', hasTest: false };
|
|
1165
|
+
const result = await checker.check(
|
|
1166
|
+
{ id: 'no_skill_without_test', level: 'guideline', rule: 'SKILL TEST', message: 'test', trigger: 'module_creation', enforcement: 'test' },
|
|
1167
|
+
context
|
|
1168
|
+
);
|
|
1169
|
+
expect(result.satisfied).toBe(false);
|
|
1170
|
+
});
|
|
1171
|
+
|
|
1172
|
+
it('simplest_solution_first should pass with reuse check', async () => {
|
|
1173
|
+
// matches trigger code_implementation
|
|
1174
|
+
const context: ConstraintContext = { operation: 'code_implementation', hasReuseCheck: true };
|
|
1175
|
+
const result = await checker.check(
|
|
1176
|
+
{ id: 'simplest_solution_first', level: 'guideline', rule: 'SIMPLEST', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1177
|
+
context
|
|
1178
|
+
);
|
|
1179
|
+
expect(result.satisfied).toBe(true);
|
|
1180
|
+
});
|
|
1181
|
+
|
|
1182
|
+
it('simplest_solution_first should fail without reuse check', async () => {
|
|
1183
|
+
const context: ConstraintContext = { operation: 'code_implementation', hasReuseCheck: false };
|
|
1184
|
+
const result = await checker.check(
|
|
1185
|
+
{ id: 'simplest_solution_first', level: 'guideline', rule: 'SIMPLEST', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1186
|
+
context
|
|
1187
|
+
);
|
|
1188
|
+
expect(result.satisfied).toBe(false);
|
|
1189
|
+
});
|
|
1190
|
+
});
|
|
1191
|
+
|
|
1192
|
+
describe('Tip constraints', () => {
|
|
1193
|
+
it('readme_required should always pass', async () => {
|
|
1194
|
+
const context: ConstraintContext = { operation: 'module_creation' };
|
|
1195
|
+
const result = await checker.check(
|
|
1196
|
+
{ id: 'readme_required', level: 'tip', rule: 'README', message: 'test', trigger: 'module_creation', enforcement: 'test' },
|
|
1197
|
+
context
|
|
1198
|
+
);
|
|
1199
|
+
expect(result.satisfied).toBe(true);
|
|
1200
|
+
});
|
|
1201
|
+
|
|
1202
|
+
it('doc_required_for_public_api should always pass', async () => {
|
|
1203
|
+
const context: ConstraintContext = { operation: 'export_change' };
|
|
1204
|
+
const result = await checker.check(
|
|
1205
|
+
{ id: 'doc_required_for_public_api', level: 'tip', rule: 'DOC', message: 'test', trigger: 'export_change', enforcement: 'test' },
|
|
1206
|
+
context
|
|
1207
|
+
);
|
|
1208
|
+
expect(result.satisfied).toBe(true);
|
|
1209
|
+
});
|
|
1210
|
+
});
|
|
1211
|
+
|
|
1212
|
+
describe('no_excuse_patterns', () => {
|
|
1213
|
+
it('should detect excuse patterns in completion claim', async () => {
|
|
1214
|
+
const context: ConstraintContext = {
|
|
1215
|
+
operation: 'code_implementation',
|
|
1216
|
+
completionClaimText: '稍后修复这个bug',
|
|
1217
|
+
};
|
|
1218
|
+
|
|
1219
|
+
const result = await checker.check(
|
|
1220
|
+
{ id: 'no_excuse_patterns', level: 'guideline', rule: 'NO EXCUSE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1221
|
+
context
|
|
1222
|
+
);
|
|
1223
|
+
|
|
1224
|
+
expect(result.satisfied).toBe(false);
|
|
1225
|
+
});
|
|
1226
|
+
|
|
1227
|
+
it('should detect excuse patterns in task description', async () => {
|
|
1228
|
+
const context: ConstraintContext = {
|
|
1229
|
+
operation: 'code_implementation',
|
|
1230
|
+
taskDescription: '这是个临时方案,先这样',
|
|
1231
|
+
};
|
|
1232
|
+
|
|
1233
|
+
const result = await checker.check(
|
|
1234
|
+
{ id: 'no_excuse_patterns', level: 'guideline', rule: 'NO EXCUSE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1235
|
+
context
|
|
1236
|
+
);
|
|
1237
|
+
|
|
1238
|
+
expect(result.satisfied).toBe(false);
|
|
1239
|
+
});
|
|
1240
|
+
|
|
1241
|
+
it('should pass with clean text', async () => {
|
|
1242
|
+
const context: ConstraintContext = {
|
|
1243
|
+
operation: 'code_implementation',
|
|
1244
|
+
completionClaimText: 'Fixed by refactoring the validation logic in checker.ts',
|
|
1245
|
+
};
|
|
1246
|
+
|
|
1247
|
+
const result = await checker.check(
|
|
1248
|
+
{ id: 'no_excuse_patterns', level: 'guideline', rule: 'NO EXCUSE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1249
|
+
context
|
|
1250
|
+
);
|
|
1251
|
+
|
|
1252
|
+
expect(result.satisfied).toBe(true);
|
|
1253
|
+
});
|
|
1254
|
+
|
|
1255
|
+
it('should pass with empty text', async () => {
|
|
1256
|
+
const context: ConstraintContext = {
|
|
1257
|
+
operation: 'code_implementation',
|
|
1258
|
+
};
|
|
1259
|
+
|
|
1260
|
+
const result = await checker.check(
|
|
1261
|
+
{ id: 'no_excuse_patterns', level: 'guideline', rule: 'NO EXCUSE', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
1262
|
+
context
|
|
1263
|
+
);
|
|
1264
|
+
|
|
1265
|
+
expect(result.satisfied).toBe(true);
|
|
1266
|
+
});
|
|
1267
|
+
});
|
|
1268
|
+
});
|