fix(harness): back to opt-in — off unless MEMHUB_HARNESS_EXTRACT is on (v0.76.0) - #270
Conversation
…n (v0.76.0) #260 (v0.69.0) made the harness lane default-on for every install. On costs the person a classifier call per flagged turn and a headless authoring run per moment on THEIR OWN model quota, and files proposals into a shared team rulebook. Felix's call, 2026-09-21: an install should not start that without being asked. Opt-in again. Three gates, flipped together because they are one switch and must never disagree: `extract_enabled` in harness_extract, `harness_extract_on` in rulebook_hook (the error-arc pairing), and the shell `case` in claude-hooks.json that runs before either. The shell gate proceeds only on an explicit on value (1/on/true/yes, any case), so unset, blank and unrecognised all exit before python starts. The empty string moved back with the default, and unrecognised values moved with it: under default-on a typo ran the lane, under opt-in a typo must not start the spend. Tests assert both sides, including the spellings #260 added. Docstrings, the module headers, the rulebook_hook comment and the README moved in the same change. The README section was still titled "(flagged off)" and still ended "With the variable unset, the default, none of this runs" — both false since #260, true again now. `_OFF` is removed; nothing reads it. Anyone who was relying on default-on since v0.69.0 must now set MEMHUB_HARNESS_EXTRACT=1. check-plugin.sh 69 of 72, the same three pre-existing failures as origin/main (codex_history, readers_cli, readers_validation). Nine version files to 0.76.0 (0.74.1 and 0.75.0 are taken by open #268 and #267). Refs ENG-1107, reverts the default from #260. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b35907afc3
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| "type": "command", | ||
| "timeout": 10, | ||
| "command": "IN=$(cat); case \"${MEMHUB_HARNESS_EXTRACT:-}\" in 0|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]|[Nn][Oo]) exit 0 ;; esac; if [ -n \"${CLAUDE_PLUGIN_ROOT:-}\" ] && printf %s \"$IN\" | python3 \"${CLAUDE_PLUGIN_ROOT}/scripts/claude_hook_guard.py\" ignore Stop; then printf %s \"$IN\" | python3 \"${CLAUDE_PLUGIN_ROOT}/scripts/harness_stop.py\" stop; fi" | ||
| "command": "IN=$(cat); case \"${MEMHUB_HARNESS_EXTRACT:-}\" in 1|[Oo][Nn]|[Tt][Rr][Uu][Ee]|[Yy][Ee][Ss]) ;; *) exit 0 ;; esac; if [ -n \"${CLAUDE_PLUGIN_ROOT:-}\" ] && printf %s \"$IN\" | python3 \"${CLAUDE_PLUGIN_ROOT}/scripts/claude_hook_guard.py\" ignore Stop; then printf %s \"$IN\" | python3 \"${CLAUDE_PLUGIN_ROOT}/scripts/harness_stop.py\" stop; fi" |
There was a problem hiding this comment.
Normalize the flag before applying the shell gate
When MEMHUB_HARNESS_EXTRACT contains surrounding whitespace, such as " 1 " or " on ", harness_extract.extract_enabled() strips it and the updated unit test explicitly treats " 1 " as enabled, but this shell case exits before Python runs because it compares the untrimmed value. As a result, a supported enabled value silently leaves the feature disabled when invoked through the actual Stop hook; trim the value here or make the accepted-value semantics consistent across all three gates.
Useful? React with 👍 / 👎.
…-captured Conflicts resolved: - extract_enabled / harness_extract_on: keep #270's opt-in parsing (explicit on-values only) and put the child gate in front of it. - The child flag uses the same on-values, as does transcript_filter.is_harness_child, so the switch reads one way. - Version 0.76.0 -> 0.76.1 in all nine version files. Opt-in makes the child gate matter more, not less: settings.json `env` is where an install opts in with MEMHUB_HARNESS_EXTRACT=1, and that value overrides the child's EXTRACT=0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Ticket: ENG-1107 · Reverts the default from #260
What this decides
#260 (v0.69.0) turned the harness lane on for every install. On costs the person a classifier call per flagged turn and a headless authoring run per moment on their own model quota, and files proposals into a shared team rulebook. Felix's call (2026-09-21): an install should not start that without being asked. Opt-in again —
MEMHUB_HARNESS_EXTRACT=1to turn it on.What changed
Three gates, flipped together — they are one switch and must never disagree:
extract_enabledinharness_extract.pyharness_extract_oninrulebook_hook.py(the error-arc pairing)caseinclaude-hooks.json, which runs before eitherThe shell gate proceeds only on an explicit on value (
1/on/true/yes, any case). Unset, blank and unrecognised all exit before python starts.Unrecognised values changed sides too, not just the empty string. Under default-on a typo ran the lane; under opt-in a typo must not start the spend. Tests assert both sides, keeping the extra spellings #260 added.
Docs moved in the same change — module headers, the
extract_enableddocstring, therulebook_hookcomment, README. Worth noting: the README section was still titled "(flagged off)" and still ended "With the variable unset, the default, none of this runs" — both false since #260, true again with this PR._OFFis removed; nothing reads it.Who this affects
Anyone who has been relying on default-on since v0.69.0 (including our own dogfood machines) stops sensing on update unless they set
MEMHUB_HARNESS_EXTRACT=1.Verification
check-plugin.sh69 of 72, the same three pre-existing failures asorigin/main(codex_history,readers_cli,readers_validation).harness_extract_test,harness_stop_test,claude_hook_guard_testall pass.Nine version files → 0.76.0 (0.74.1 and 0.75.0 are taken by open #268 and #267; whichever merges second rebases its bump).
Not in this PR
The README's harness section still describes the blocking-Stop handoff, while
harness_stop.pynow authors off-thread. That predates this change and is a separate docs fix.🤖 Generated with Claude Code