@@ -140,3 +140,117 @@ Rule: An issue is closed only by explicit merge of a PR with "Closes #N" OR by e
140140Action (Hypatia): When asked to close an issue, confirm via a reply on the issue thread before doing so.
141141Action (gitbot): Never use GitHub's "close issue" API directly; only close via PR merge with "Closes #N" keywords.
142142
143+ ## Agent operations notes
144+
145+ Practical guidance for agents (Claude / other) operating in this repo,
146+ captured from parallel-bot session experience. Read once; saves turns.
147+
148+ ### CI signal reliability
149+
150+ ** "PR merged" does NOT mean "build green".** Auto-merge on this repo
151+ currently fires even when ` build ` or ` lint ` is failing — multiple
152+ recently-merged PRs (#334 , #335 , #336 , #344 ) landed with ` build ` red,
153+ and the red persisted until PR #346 's ` FnExtern ` interp fix. If you
154+ inherit a session reasoning about a recently-merged PR, do not assume
155+ its CI was green; check ` mcp__github__pull_request_read ` with method
156+ ` get_check_runs ` for the actual statuses, and check whether ` main `
157+ itself is currently red before treating a build failure on your own
158+ PR as something * you* introduced.
159+
160+ ### Reading CI logs
161+
162+ ` WebFetch ` against the GitHub Actions UI returns the React skeleton,
163+ not the log content. The fast paths for an agent are:
164+
165+ * ` mcp__github__pull_request_read ` with method ` get_check_runs ` —
166+ per-job status (queued / in_progress / success / failure) with
167+ ` details_url ` . Sufficient for "did the build pass".
168+ * ` mcp__github__pull_request_read ` with method ` get_status ` —
169+ combined commit status.
170+ * For actual log lines on a failed run, hand back to the user with
171+ ` gh run view --log-failed <run-id> ` ; do not loop trying to scrape
172+ the UI.
173+
174+ ### Known-failing baseline checks
175+
176+ These checks currently fail on * every* PR for repo-wide reasons, not
177+ because of any individual PR's changes. Do not waste turns
178+ investigating them on a per-PR basis:
179+
180+ * ` vscode-smoke ` — npm 404 on ` @hyperpolymath/affine-vscode ` (the
181+ in-editor harness depends on a not-yet-published npm package).
182+ * ` migration-assistant ` — was fixed by #342 , but any branch created
183+ from a base older than #342 will still see it red until rebased.
184+ * ` governance / Language / package anti-pattern policy ` — flags the
185+ approved TypeScript exemptions (` affinescript-deno-test/*.ts ` ,
186+ ` editors/vscode/test/*.js ` , etc., all documented in this file's
187+ exemptions tables); the check has no allowlist for them.
188+ * The Hypatia security-scan bot comment — 143 findings; the bulk are
189+ the same TypeScript exemption hits + pre-existing root files. A
190+ real new finding will show as a * delta* in the count; otherwise
191+ ignore.
192+
193+ If a check from this list * changes status* on a PR (e.g.
194+ ` vscode-smoke ` suddenly passes, or Hypatia surfaces a new class of
195+ finding), that's signal worth investigating.
196+
197+ ### Branching discipline with concurrent merges
198+
199+ When multiple agents are spawned in parallel, branch-creation time
200+ can lag ` main ` by hours and a stale base will silently revert other
201+ agents' work at merge time. ** Before pushing any branch, run:**
202+
203+ ```
204+ git fetch origin main
205+ git rebase origin/main
206+ ```
207+
208+ Not just at branch-creation; immediately before push, after any
209+ in-session work. This guards against parallel-merge drift. Claude 1's
210+ STDLIB-04c branch (#337 ) accidentally reverted #334 and #335 because
211+ its base was stale; force-rebased to fix. Cheap to prevent, expensive
212+ to clean up.
213+
214+ ### Post-squash-merge branch divergence
215+
216+ When a PR is squash-merged, the squashed commit on ` main ` gets a
217+ * new* SHA, distinct from any of the source-branch commits. If you
218+ then reset your local branch to ` main ` (or simply re-resolve it),
219+ ` git status ` reports N "ahead of origin/branch" — but those N
220+ commits are just the main-side commits the obsolete remote
221+ branch-tip never saw, not unpushed work.
222+
223+ Recognising the situation:
224+
225+ * The branch was already merged (PR closed, ` merged: true ` ).
226+ * The local working tree matches ` main ` .
227+ * The remote branch still points at the * pre-merge* tip
228+ (` origin/<branch> ` is an old SHA, not the squashed one).
229+ * ` git log origin/<branch>..HEAD ` lists commits that look like
230+ other people's work.
231+
232+ Safe fix — pick the one matching intent:
233+
234+ ```
235+ git push origin --delete <branch> # done with the branch
236+ git push --force-with-lease origin <branch> # align the remote to main
237+ ```
238+
239+ ` --force-with-lease ` is safe here because nothing on the remote
240+ branch is unmerged work; force-push without ` --lease ` only matters
241+ if someone else pushed concurrently, which is irrelevant for an
242+ already-merged branch you're cleaning up.
243+
244+ ### Test-fixture hygiene for latent bug surfaces
245+
246+ When you add a stdlib ` extern fn ` (or any other new declaration
247+ shape), add a test that feeds it to * every* downstream consumer
248+ (parse, resolve, typecheck, interp, every codegen target that
249+ shouldn't reject it). The PR #346 ` FnExtern ` interp bug had survived
250+ since the interpreter was written because no test had ever fed an
251+ inline ` extern fn ` to ` Interp.eval_program ` — STDLIB-04a's tests
252+ were the first, and only then did the missing match arm fire.
253+
254+ Treat "first user of an existing-but-untested declaration shape" as a
255+ class-level surface, not a single test case.
256+
0 commit comments