@@ -90,32 +90,52 @@ For the full workflow narrative, conventions, and registry schemas, read
9090 loosely-related changes, split into separate prompt files before issuing.
91914 . ** ` tmp/ ` is scratch.** Never commit anything under it.
9292
93- ## Running tests in a remote (web/mobile) session
94-
95- Two facts, both measured, both worth one line each:
96-
97- 1 . ** Run the suite in parallel.** A remote container has 4 cores and the suites
98- are subprocess-heavy with no single slow test: PyAutoBrain's 554 tests take
99- 96s on one core and 28s on four. ` pytest-xdist ` is installed by the
100- session-start hook, so the command is just:
101-
102- ```
103- python3 -m pytest -q -n auto
104- ```
105-
106- 2 . ** If ` python3 -m pytest ` or ` pytest ` misbehaves, the environment is stale,
107- not the code.** A session holding several organs registers no SessionStart
108- hook (Claude Code reads hooks from the project directory, which is the
109- repos' * parent* ). Knock on the door directly, once, in the first turn:
110-
111- ```
112- bash PyAutoMind/scripts/session_bootstrap.sh # fix it
113- bash PyAutoMind/scripts/session_bootstrap.sh --check # report only
114- ```
115-
116- The symptom to recognise: collection ` ImportError ` s naming ` yaml ` , or
117- ` No module named pytest ` . Both are the session resolving a pytest that is not
118- this workspace's — never a broken test module.
93+ <!-- repos_sync:remote:begin -->
94+ ## Remote sessions (Claude Code on web and mobile)
95+
96+ Three facts, all measured in a web/mobile container, where this file is loaded
97+ and little else is. They ride in every organ because a session may hold any
98+ subset of them — and the session that needs this most is the one holding
99+ several, which is exactly the session no hook fires in.
100+
101+ - ** Bootstrap in the first turn, unconditionally** — before the first test
102+ command, not as a remedy once something looks wrong:
103+
104+ ```
105+ bash PyAutoMind/scripts/session_bootstrap.sh # ~10s cold, ~1s warm
106+ bash PyAutoMind/scripts/session_bootstrap.sh --check # report only
107+ ```
108+
109+ A session holding several organs registers no SessionStart hook — Claude Code
110+ reads project hooks from the project directory, which in that layout is the
111+ repos' * parent* , not a repo — so nothing has set this session up. It was once
112+ phrased as a remedy keyed to ` No module named pytest ` or collection
113+ ` ImportError ` s naming ` yaml ` ; that symptom stopped appearing when the
114+ container image moved to Python 3.12, while the environment is still wrong in
115+ ways that read like a bad command rather than a stale session (`pytest -n
116+ auto` → ` unrecognized arguments: -n`). The bootstrap also ** unshallows the
117+ clones** : a remote session clones shallow, and ` git merge-base --is-ancestor `
118+ then answers "not an ancestor" for a commit whose ancestry is merely absent —
119+ the answer the ship and close-out procedures act on when proving a branch
120+ merged.
121+
122+ - ** Then run the suite in parallel.** 4 cores, subprocess-heavy suites, no
123+ single slow test: about 3.5x. ` python3 -m pytest -q -n auto ` , with
124+ ` pytest-xdist ` supplied by the bootstrap above.
125+
126+ - ** There is no ` gh ` , and installing one does not help.** A remote session
127+ reaches GitHub through the ` mcp__github__* ` tools, already scoped to the
128+ session's repos. ` gh ` installs in two seconds and is a trap: it authenticates,
129+ then 403s every repo-scoped call, because the egress proxy serves neither the
130+ REST repo paths nor GraphQL beyond a pinned set of PR-review operations — a
131+ binary that looks healthy and fails everything that matters. It also defeats
132+ the surface probe, which keys off ` gh auth status ` . Read
133+ ` PyAutoBrain/skills/GITHUB_ACCESS.md ` at the top of any run that touches
134+ GitHub; it maps each ` gh ` operation onto its MCP tool. Spell that path from
135+ the workspace root, as written: a multi-organ session is cwd'd at the repos'
136+ * parent* , so a bare ` skills/… ` reads as a missing file rather than a missing
137+ repo prefix.
138+ <!-- repos_sync:remote:end -->
119139
120140## When you are asked to add a new prompt
121141
0 commit comments