From aca24961c42978b80fd5b588ae638172160fa9f1 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Sat, 26 Sep 2026 23:09:46 -0700 Subject: [PATCH 1/2] docs(ax): entry 69, a name resolves in its own scope Two isPodMember functions with opposite rules (the permissive util, and server.ts's strict local copy) led connector-ops to report a socket write-path gap that did not exist. Records the misread, the correction (Wren, 74667) and the repair; #1943 (TASK-165) removes the local copy. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01MCF2UK3EQ6z6EHdvxAkM44 --- docs/development/agent-experience-audit.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/development/agent-experience-audit.md b/docs/development/agent-experience-audit.md index 467e6fede..30c0ff553 100644 --- a/docs/development/agent-experience-audit.md +++ b/docs/development/agent-experience-audit.md @@ -3980,3 +3980,11 @@ The predicate asked whether a message id names a row, so I asked Postgres what a The name helped the error along: `isMessageId` reads like *the* id predicate when it was only one namespace's, and a name that claims the whole domain stops the reader asking what else feeds it. **Repair:** before writing a shape test around a value, enumerate its **producers** — every call site that can supply it — and not just the store that would validate it; an enumeration over the wrong domain is still a guess, however exhaustive it looks. When a shape the predicate does not recognise is answered with a non-2xx by a caller documented to fail **open**, the predicate is an availability decision, not a tidiness one: say which namespaces it verifies, which it passes through unverified, and file the pass-through as the defect it is rather than letting the accepted shape imply the check. + +## 69. A name resolves in its own scope: read the definition the call site binds, not the one you already know (2026-09-27, connector-ops) + +*Origin observation: TASK-162's scope note 162c, corrected by @wren (Connectors room, msg 74667); the collision was removed by #1943 (TASK-165).* + +Two functions named `isPodMember` lived in the backend with opposite rules. The util (`utils/isPodMember.ts`) returned true on `pod.createdBy` before looking at `members`; a local copy in `server.ts` (`:503`) read `pod.members` only. Having just spent a row on the util's creator bypass, I read `isPodMember(pod, socket.userId)` at `server.ts:536` as the util and filed "a creator who left can still post over the socket" as a live write-path gap, and repeated it to the operator. The call bound the file's own strict copy three dozen lines up; the socket path had refused a departed creator all along. The name was doing the reasoning, and it pointed at the definition I already had in my head. + +**Repair:** before asserting what a call does, resolve the binding in that file (a local `const`, an import, a re-export) and read the body it reaches, not the body its name reminds you of. And when two definitions share a name with different semantics, delete one or rename it, then write the entry: a name that means two things in one codebase will keep producing confident wrong claims until one of the meanings is gone. From 9a4bd116dc8f6a05b878afc594c36464a513b478 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Sat, 26 Sep 2026 23:20:41 -0700 Subject: [PATCH 2/2] docs(ax): entry 69, present tense for the open PR (Vera 74693) #1943 was open when this entry was written; the past tense asserted a merge that hasn't happened. Entry-only, one sentence. --- docs/development/agent-experience-audit.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/development/agent-experience-audit.md b/docs/development/agent-experience-audit.md index 30c0ff553..622564db1 100644 --- a/docs/development/agent-experience-audit.md +++ b/docs/development/agent-experience-audit.md @@ -3983,7 +3983,7 @@ The name helped the error along: `isMessageId` reads like *the* id predicate whe ## 69. A name resolves in its own scope: read the definition the call site binds, not the one you already know (2026-09-27, connector-ops) -*Origin observation: TASK-162's scope note 162c, corrected by @wren (Connectors room, msg 74667); the collision was removed by #1943 (TASK-165).* +*Origin observation: TASK-162's scope note 162c, corrected by @wren (Connectors room, msg 74667); the collision is removed by #1943 (TASK-165), open at the time of writing.* Two functions named `isPodMember` lived in the backend with opposite rules. The util (`utils/isPodMember.ts`) returned true on `pod.createdBy` before looking at `members`; a local copy in `server.ts` (`:503`) read `pod.members` only. Having just spent a row on the util's creator bypass, I read `isPodMember(pod, socket.userId)` at `server.ts:536` as the util and filed "a creator who left can still post over the socket" as a live write-path gap, and repeated it to the operator. The call bound the file's own strict copy three dozen lines up; the socket path had refused a departed creator all along. The name was doing the reasoning, and it pointed at the definition I already had in my head.