4.2 KiB
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.Lockaround 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 removedtest_store.test_parallel_appends_give_whole_lines(96 of 100 lines) andtest_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 anmsvcrtbyte-range lock) in a separate change.
Notes on the cuts
- #12:
session_idfrom theinitevent is now taken only while unset (self.session_id is None), which matches the old "first init wins" behaviour. - #28:
StreamStateis now imported at the top ofcall.pyinstead of lazily inside thess is Nonebranch. - #17: premise holds.
spawnrefuses an existingjobs/<J>.json(cli.py:255) and_executewrites that file before the call starts, so a note that exists afterwards was written by this job. - #11: nothing outside
stream.pyreadrefusedormodel_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.