Version: @cleocode/cleo 2026.7.2 (npm, global install) · Windows 10 · Node 22
Summary
cleo verify --evidence "tool:lint" never consults .cleo/project-context.json, even when the file carries a lint.command key (which cleo detect itself writes). It falls straight through to the per-language default — on a Python project that's ruff check . over the entire repo.
ADR-061 / the module docstring say the resolver "sources the command from .cleo/project-context.json when the user has captured a project-specific override", but the implementation only wires two of the seven canonical tools.
Root cause
packages/core/src/tasks/tool-resolver.ts → resolveToolCommand(), Step 2 (dist: @cleocode/core/dist/tasks/tool-resolver.js):
// Step 2 — project-context overrides
if (canonical === 'test') { readNestedString(ctx, ['testing', 'command']) ... }
if (canonical === 'build') { readNestedString(ctx, ['build', 'command']) ... }
// lint / typecheck / audit / security-scan: no project-context check at all
// → falls to LANGUAGE_DEFAULTS[primaryType], e.g. python.lint = ruff check .
Reproduction
- Python project;
.cleo/project-context.json:
{ "primaryType": "python",
"testing": { "command": "python scripts/run_tests.py" },
"lint": { "command": "python -m compileall -q scripts" } }
cleo verify T### --gate testsPassed --evidence "tool:test" → runs the configured command ✅
cleo verify T### --gate qaPassed --evidence "tool:lint" → runs ruff check . on the whole repo ❌ (in our case: 245 pre-existing findings unrelated to the task, E_EVIDENCE_TOOL_FAILED on every genuine qaPassed attempt)
Proposed fix
Generalize Step 2 to every canonical tool — test keeps the detector schema key testing.command, everything else reads <canonical>.command:
// Step 2 — project-context overrides (all canonical tools)
const ctx = loadProjectContext(projectRoot).context;
const ctxKey = canonical === 'test' ? 'testing' : canonical;
const cmd = readNestedString(ctx, [ctxKey, 'command']);
const parsed = cmd ? parseCommandString(cmd) : null;
if (parsed) {
return { ok: true, command: { canonical, displayName: toolName,
cmd: parsed.cmd, args: parsed.args,
source: isAlias ? 'legacy-alias' : 'project-context' } };
}
test/build behavior is unchanged; lint.command, typecheck.command, audit.command, security-scan.command become honored. We've been running exactly this as a local dist patch since 2026-07-16 — tool:lint gate verification works as documented (source: 'project-context', exit 0, no override needed).
Happy to open a PR if that's welcome.
Version: @cleocode/cleo 2026.7.2 (npm, global install) · Windows 10 · Node 22
Summary
cleo verify --evidence "tool:lint"never consults.cleo/project-context.json, even when the file carries alint.commandkey (whichcleo detectitself writes). It falls straight through to the per-language default — on a Python project that'sruff check .over the entire repo.ADR-061 / the module docstring say the resolver "sources the command from
.cleo/project-context.jsonwhen the user has captured a project-specific override", but the implementation only wires two of the seven canonical tools.Root cause
packages/core/src/tasks/tool-resolver.ts→resolveToolCommand(), Step 2 (dist:@cleocode/core/dist/tasks/tool-resolver.js):Reproduction
.cleo/project-context.json:{ "primaryType": "python", "testing": { "command": "python scripts/run_tests.py" }, "lint": { "command": "python -m compileall -q scripts" } }cleo verify T### --gate testsPassed --evidence "tool:test"→ runs the configured command ✅cleo verify T### --gate qaPassed --evidence "tool:lint"→ runsruff check .on the whole repo ❌ (in our case: 245 pre-existing findings unrelated to the task,E_EVIDENCE_TOOL_FAILEDon every genuine qaPassed attempt)Proposed fix
Generalize Step 2 to every canonical tool —
testkeeps the detector schema keytesting.command, everything else reads<canonical>.command:test/buildbehavior is unchanged;lint.command,typecheck.command,audit.command,security-scan.commandbecome honored. We've been running exactly this as a local dist patch since 2026-07-16 —tool:lintgate verification works as documented (source: 'project-context', exit 0, no override needed).Happy to open a PR if that's welcome.