Skip to content

Troubleshooting

nguyenhx2 edited this page Aug 17, 2026 · 1 revision

Troubleshooting

Every entry here is a failure that actually happened, not a hypothetical.

A hook does not block anything

Check the flavour first. A Windows harness ships .ps1 hooks. If settings.json registers .sh commands, the lookup finds no hook, skips every one, and returns allow for everything - while the command prints that it blocked. That shipped once.

harness-view assess .        # reports a hook that ships but is not registered

The flavour and the registration are both derived from one flag precisely so they cannot disagree. If they do, the harness was hand-edited.

Then test the hook directly. Hooks read JSON on stdin and answer with an exit code:

echo '{"cwd":"'"$PWD"'","tool_name":"Bash","tool_input":{"command":"cat .env"}}' \
  | bash .claude/hooks/protect-secrets.sh; echo "exit=$?"

2 means it blocked. 0 means it allowed. In PowerShell check $LASTEXITCODE, never $? - that is a boolean and it will tell you the script ran, not what it decided.

An agent cannot read a file it obviously needs

This was a real bug: the deny rule matched .env.example, the one file every block message tells the agent to read. It is fixed, and the eval now covers reading the example file, seeding a local one, and running with one loaded.

If you hit something similar in your own harness, the deny list should name value-bearing files, not every filename containing env. Check .claude/settings.json and the protect-secrets hook.

The adapter allows everything on Cursor or Codex

Run the self-test:

python harness-bootstrap/scripts/port.py --self-test

It checks both hook flavours, and it also checks two things a passing machine can hide: that the adapter offers every interpreter name its platform may use, and that it denies a call it cannot evaluate. A guard that cannot execute does not know the answer, and answering "allow" is the hole the adapter exists to close.

Historically the adapter baked the literal name powershell, which only exists on Windows. On macOS and Linux the binary is pwsh, so a ported harness raised a traceback on every call and the guard never ran.

The graph or the viewer shows stale data

.claude/state/harness-graph.json is regenerated by the graph-stale hook when you edit anything under .claude/, and by /harness-update and /harness-toggle. Script-driven writes do not fire the editor hooks, which is why those commands regenerate it themselves.

To force it:

python .claude/scripts/harness-graph.py     # or: harness-view scan .

A published number looks wrong

It might be. Run:

python scripts/check_numbers.py

It compares every figure quoted in the documents, the deck, the clips and the figures against what the scripts actually print, and exits non-zero on a contradiction. Numbers in this project have drifted before - a clip claimed the eval was "26 / 26" long after it reached 107, hidden from the checker by the spaces around the slash - so if a page and a script disagree, trust the script and open an issue.

Scaffolding reports CONFLICT

That is not an error. CONFLICT means the file exists and differs from what would be installed, and it is the brownfield reconciliation queue. Resolve each one by hand: keep yours, adapt it, take the new one, or register the difference as a task. The scaffolder never overwrites and never deletes what you wrote.

The scaffolder exits non-zero on a variable

It found an unresolved {{VAR}}. That is deliberate: a missing variable fails loudly instead of shipping a placeholder into a rule file where nobody would notice it. Fill the variable in vars.json and re-run.

Still stuck

Open an issue with the output of harness-view assess . and the failing command. The assess output names the node, which is usually enough to locate the problem without a reproduction.

Clone this wiki locally