Files
reliquary/docs/workpad/reports/2026-10-17-00-gremlins-mvp-cuts.md
T

4.2 KiB

Gremlins MVP: unrequested-surface calls

  • Author model: claude-sonnet-5-5 · Date: 2026-10-17 · Branch gremlins-mvp @ cfeb1bf
  • Source: phase review §2. The user ruled on the rows below: keep the useful ones, cut the rest, one-line reason each. This commit records the calls; the cuts follow in the next commit.
# Item Call Reason
2 briefs/<J>.md: full prompt per job keep Debugging aid.
3 Ledger torn-last-line repair keep Protects the ledger after a hard stop.
4 In-process threading.Lock around ledger append cut Each spawn is its own process, so it guards nothing; the spec says "without locks".
5 MODEL_RE, aliases refused at init keep An alias would change the fingerprint and break cache hits; B1 asks for a full id.
6 EFFORTS choices, default high keep Trivial argparse guard.
7 Tool deny list (Bash(claude:*), git push/rebase/reset --hard) keep Headless unattended gremlins must not recurse or rewrite history.
8 SPIRE_GREMLIN_CHILD=1 in the child env cut Rider: the refusal it served was dropped, so it is leftover.
11 refused / model_refused status case cut Not in the spec's classify; the harness substitutes unlisted models silently, so error covers it.
12 Stream fields tracked and never read (init, msg_ids, _ids, events, turns) cut Never read.
13 mismatch in usage_from_result cut Rider: computed and never read.
14 wrote_only_5m cut Rider: never called.
16 NAME_RE on base/job names keep Names become file paths.
17 Note detection by mtime with 2 s slack cut Replace with a plain existence check of notes/<J>.md, since spawn refuses an existing job name (#20).
22 base_state in spawn output cut status reports warmth and cache reports the outcome.
23 init defaults cwd to the git toplevel keep cwd is in the fingerprint; a stable default avoids cache misses.
25 stderr to raw/<J>.err keep Cheap debugging aid.
26 Reader join timeout 10 s keep Without it an orphan holding stdout hangs the helper (spec §7 leftover).
28 Unused ss=None injection parameter in call.py cut Used by no caller.

Result

Premises checked in the code before each cut. Tests: uv run --no-project --python 3.12 python -m unittest discover -s tests gave 24 tests, OK (run twice).

File Added Removed
grm/stream.py 9 39
grm/call.py 4 4
grm/cli.py 2 4
grm/launch.py 1 1
Total 16 48

Net code: 32 lines removed (16 added, 48 deleted); no test was removed or changed (none existed only for a cut item).

Kept against the call

  • #4 threading.Lock around ledger append: kept. Premise half true: in production each spawn is its own process, so no two threads of one process append. But with the lock removed test_store.test_parallel_appends_give_whole_lines (96 of 100 lines) and test_cli.test_parallel_spawns (2 of 3 ledger lines) fail, on every run. Appends from separate handles on Windows lose lines. The lock only makes those B3 tests pass in-process; across real processes the same race is unguarded either way (the review's open "Windows append atomicity" item). Cutting it would mean weakening two B3 tests, which the call forbids. Needs a decision: either keep the lock as is, or replace it with a cross-process append (for example a lock file or an msvcrt byte-range lock) in a separate change.

Notes on the cuts

  • #12: session_id from the init event is now taken only while unset (self.session_id is None), which matches the old "first init wins" behaviour.
  • #28: StreamState is now imported at the top of call.py instead of lazily inside the ss is None branch.
  • #17: premise holds. spawn refuses an existing jobs/<J>.json (cli.py:255) and _execute writes that file before the call starts, so a note that exists afterwards was written by this job.
  • #11: nothing outside stream.py read refused or model_refused (code, tests, SKILL.md, templates).
  • #8, #13, #14, #22: no reader in code, tests, SKILL.md or templates. SKILL.md and templates mentioned none of the cut items, so they are unchanged.