Problem
make cypher-lint is referenced in six places across the repo, but no such Makefile target exists, and no script backs it.
$ make cypher-lint
make: *** No rule to make target 'cypher-lint'. Stop.
$ grep -n 'cypher' Makefile
47: @docker exec l9-graph-neo4j cypher-shell ... # health check
73: docker exec -it l9-graph-neo4j cypher-shell ... # neo4j-shell target
Only cypher-shell (the Neo4j CLI) appears. There is no cypher-lint target, no tools/cypher_lint.py, and no CI step that runs it (grep -rn 'cypher' .github/workflows/ returns nothing).
Why this matters beyond a broken doc line
This is not only stale documentation. Contract C-009 (Cypher Injection Prevention) names make cypher-lint as its automated enforcement and marks human review as not required:
.claude/rules/contracts.md
| C-009 | make cypher-lint + SEC-001 to SEC-007 | No |
So the contract enforcement matrix claims an automated guard against Cypher injection that cannot run. Anyone auditing C-009 coverage — human or agent — gets a false positive, and an agent instructed to "run make cypher-lint before opening a PR" (per AGENTS.md) hits a hard make error with no documented recourse.
Where it is referenced
| File |
Reference |
AGENTS.md:31 |
make cypher-lint # Scan generated Cypher for injection vectors (in the canonical Commands block) |
.claude/rules/contracts.md:76 |
C-009 enforcement column |
GUARDRAILS.md:22 |
"Enforcement: make cypher-lint scans all generated Cypher. CI fails on any unparameterized value interpolation." |
GUARDRAILS.md:133 |
Cypher injection → make cypher-lint + Contract C-001 |
docs/TROUBLESHOOTING.md:120 |
an entire section titled "make cypher-lint Failures" |
agents/cursor/cursor_workflow_kernel.yaml:482 |
agent checklist item make cypher-lint → 0 injection vectors |
GUARDRAILS.md:22 additionally claims "CI fails on any unparameterized value interpolation", which is not true of any current workflow.
What partial coverage does exist
The pre-commit hook check-cypher-interpolation (.pre-commit-config.yaml:69) greps staged .py files for f-string label interpolation lacking sanitize_label:
rg -l "f\".*MATCH.*\\(.*:\\{" | xargs grep -L "sanitize_label" | grep -v test
That is narrower than what the docs describe: it is staged-files-only, matches one f-string shape, excludes tests, and silently no-ops when rg is absent (if command -v rg). It does not "scan all generated Cypher", and it is not wired to the make cypher-lint name the contract cites.
tools/contract_scanner.py (SEC-001..007) is the other half of C-009 and does run and pass.
Suggested resolution
Someone who owns C-009 should pick one; I have deliberately not chosen:
- Implement the target — add
tools/cypher_lint.py and a cypher-lint: Makefile target that genuinely scans generated Cypher, and wire it into CI so the GUARDRAILS.md claim becomes true. Restores the contract as documented.
- Retire the name — drop
make cypher-lint from the six references and restate C-009's automated enforcement as check-cypher-interpolation + contract_scanner.py SEC-001..007, correcting the enforcement matrix to match reality.
Option 1 closes a real gap; option 2 is honest but reduces C-009's claimed automation. Either way the enforcement matrix and GUARDRAILS.md need to end up describing something that exists.
Provenance
Found while running the full test suite with a working Docker daemon for #271, when make cypher-lint was invoked as part of the documented pre-PR checks and errored. Pre-existing on main at 9c8e3cf, unrelated to that PR's changes, and reported rather than silently absorbed into it.
Generated by Claude Code
Problem
make cypher-lintis referenced in six places across the repo, but no such Makefile target exists, and no script backs it.Only
cypher-shell(the Neo4j CLI) appears. There is nocypher-linttarget, notools/cypher_lint.py, and no CI step that runs it (grep -rn 'cypher' .github/workflows/returns nothing).Why this matters beyond a broken doc line
This is not only stale documentation. Contract C-009 (Cypher Injection Prevention) names
make cypher-lintas its automated enforcement and marks human review as not required:.claude/rules/contracts.mdSo the contract enforcement matrix claims an automated guard against Cypher injection that cannot run. Anyone auditing C-009 coverage — human or agent — gets a false positive, and an agent instructed to "run
make cypher-lintbefore opening a PR" (perAGENTS.md) hits a hardmakeerror with no documented recourse.Where it is referenced
AGENTS.md:31make cypher-lint # Scan generated Cypher for injection vectors(in the canonical Commands block).claude/rules/contracts.md:76GUARDRAILS.md:22make cypher-lintscans all generated Cypher. CI fails on any unparameterized value interpolation."GUARDRAILS.md:133make cypher-lint+ Contract C-001docs/TROUBLESHOOTING.md:120make cypher-lintFailures"agents/cursor/cursor_workflow_kernel.yaml:482make cypher-lint → 0 injection vectorsGUARDRAILS.md:22additionally claims "CI fails on any unparameterized value interpolation", which is not true of any current workflow.What partial coverage does exist
The pre-commit hook
check-cypher-interpolation(.pre-commit-config.yaml:69) greps staged.pyfiles for f-string label interpolation lackingsanitize_label:That is narrower than what the docs describe: it is staged-files-only, matches one f-string shape, excludes tests, and silently no-ops when
rgis absent (if command -v rg). It does not "scan all generated Cypher", and it is not wired to themake cypher-lintname the contract cites.tools/contract_scanner.py(SEC-001..007) is the other half of C-009 and does run and pass.Suggested resolution
Someone who owns C-009 should pick one; I have deliberately not chosen:
tools/cypher_lint.pyand acypher-lint:Makefile target that genuinely scans generated Cypher, and wire it into CI so theGUARDRAILS.mdclaim becomes true. Restores the contract as documented.make cypher-lintfrom the six references and restate C-009's automated enforcement ascheck-cypher-interpolation+contract_scanner.pySEC-001..007, correcting the enforcement matrix to match reality.Option 1 closes a real gap; option 2 is honest but reduces C-009's claimed automation. Either way the enforcement matrix and
GUARDRAILS.mdneed to end up describing something that exists.Provenance
Found while running the full test suite with a working Docker daemon for #271, when
make cypher-lintwas invoked as part of the documented pre-PR checks and errored. Pre-existing onmainat9c8e3cf, unrelated to that PR's changes, and reported rather than silently absorbed into it.Generated by Claude Code