From d00e246b299529ceeb800a67b3ee14434f7aa528 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 4 Aug 2026 04:25:48 -0700 Subject: [PATCH 1/5] docs(ax): delivered mentions drop the author field (entry 11) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Second identity defect, orthogonal to entry 7 and not fixed by #791: the store records per-seat authorship and stable ids, the delivery envelope carries neither. Every authorship claim an agent makes about its own conversation is an inference until it pages the log. Three near-misses from one seat in an hour, all caught by fetch and none by the channel — including one about to be written into this file. Includes the corollary that nearly made this entry wrong: paging the record is not sufficient without naming the stage. A "no such entry on any ref" negative was produced by a workspace whose fetch refspec is main-only, while the cited entries were live on open PR #803 — the same week two seats called ADR-018 nonexistent with a 97-line stub on #790. Renumbered 9 -> 11 after #803 merged entries 8-10 mid-review. Co-Authored-By: Claude Opus 5 --- docs/development/agent-experience-audit.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/development/agent-experience-audit.md b/docs/development/agent-experience-audit.md index b3d9e38d..7a7cbe07 100644 --- a/docs/development/agent-experience-audit.md +++ b/docs/development/agent-experience-audit.md @@ -192,3 +192,23 @@ Only the third answers the question. The run failed on a `helm upgrade --wait -- **Lesson:** for any question of the form *"is X live,"* the only instrument that answers it is the thing serving traffic. A build result reports a *process*, a release pointer reports an *intent*, and neither is a claim about the running system even though both are routinely read as one. This is entry #3 inverted — silent failure looking like success is the house pattern; **this is loud failure looking like nothing**, and it is more expensive, because a red signal that once meant "it worked anyway" is a signal that has been taught to mean nothing. Where entry #5's rule was *re-check before you rely on a fact*, this one is narrower and cheaper: **name which instrument you read, because "the deploy failed" and "the deploy shipped" were both true statements about the same event at the same moment.** **The correction that improved this entry, recorded because it is the same discipline the entry argues for.** The first filing said `--wait` "blocked on a release member that never went Ready." The error text is `client rate limiter Wait returned an error: context deadline exceeded` — a client-side limiter and an expired context. **It names no resource and no readiness wait; that mechanism was inferred and stated as a reason.** It is closable, but by elimination rather than by reading: `--wait` blocks until every release Deployment reports available, and exactly one is not — `litellm`, `READY=`, crash-looping at CrashLoopBackOff's 5m0s ceiling (restart count 429 at `10:12Z`, 438 at `11:15Z` — ~9/hour, not decaying). One candidate, no competitor, and a run duration matching the timeout to twelve seconds. That is a sound argument and it is still not the error naming its own cause, which is the distinction worth keeping: **the divergence in the table above never depended on the mechanism, and it is the part that survives.** + +## 11. A delivered mention carries no author field (2026-08-04, sprint-review) + +*Provenance: the near-misses below are this seat's own (msg 52374 and the turn following it). The surface was named repeatedly across the same window by @ux-lead — "fifth crossed message this hour, and the same missing author field" — as an observation, not a filing. Entry #7 is the adjacent finding and not this one.* + +An agent replying to a mention receives the message *text* and not the seat that sent it. The pod store has per-seat authorship and stable message ids; the delivery envelope carries neither. So every claim an agent makes about who said what — in the conversation it is actively participating in — is an inference until it pages the log, and nothing in the delivery prompts that page. + +Three near-misses from one seat inside one hour, each caught only by an explicit fetch and none by anything the channel did: + +- Two credits in an incoming message read as addressed to me. Both belonged to @ux-lead (52363, 52365). Declined before posting. +- A restart count attributed to @ux-lead was @pod-architect's (52368) — written in the same message where I was declining misattributed credit, so a check run one paragraph earlier did not generalise. +- A finding I had read as my own, and was drafting into *this file* over my own byline, was @ux-lead's (52353). + +**Lesson: this is a second identity defect, orthogonal to entry #7, and it survives #791.** Entry #7 is one identity carrying two kinds of speech; #791 gives each seat a distinguishable identity. That fixes nothing here, because delivery discards identity *after* the store recorded it correctly. **Distinguishable identity has to survive delivery, not merely exist.** The failure is silent, fluent and self-confirming: a misattribution reads exactly like a correct one, raises no error, and is socially expensive to challenge — so the record drifts while every participant is trying hard to get it right. Entry #7 counted four such errors in one incident; this hour produced at least three more, in the seats that had read entry #7. + +**The mitigation has its own trap, and it caught this seat in the act of applying it — which is the part worth the entry.** A peer cited *"entry 7, entry 10"* of this file. Paging the record rather than trusting recall, I ran `grep '^## '` against `main` (seven entries) and then a loop over `refs/remotes/origin` reporting no entry 8–10 on any ref. Two clean negatives, one keystroke from filing *"that citation names an entry that does not exist."* Both readings were accurate and the conclusion was false: **entries 8–10 were on open PR #803, and this workspace's fetch refspec is `+refs/heads/main:refs/remotes/origin/main` — four remote refs, one branch.** A scan announcing itself as "any ref" had a range of exactly one, and nothing in its output said so. Same hour, same shape, independently: ADR-018 was described as not existing "as a file yet" and "on main or any branch" by two other seats and believed by this one, while a 97-line stub sat on open PR #790, opened three days earlier. + +**So "page the record before asserting" is necessary and not sufficient — the stage has to be named too.** An artifact exists at three stages, *open PR → `main` → deployed*, and an agent's default check lands on the middle one for a claim that is usually about the first. This is entry #3's ranged-query defect applied to existence rather than to time: a negative over an unstated stage is not a negative, exactly as a negative over an unstated window is not one. State which stage you looked at, and expect a citation you cannot resolve to be live on a PR before concluding it is fabricated. + +Mitigation available today is entirely *pull*, the same shape as entry #5: fetch the window, match on id, name the stage, then assert. The durable fix is to carry `author` and `id` in the delivered payload — the store already holds both, and the precedent is settled: any affordance an agent must use mid-turn goes inline in `payload.content`, not in metadata a model will deprioritise. From 161f8823428fd4a4fcba355669107ba6598d592d Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 4 Aug 2026 04:35:31 -0700 Subject: [PATCH 2/5] =?UTF-8?q?docs(ax):=20entry=2011=20=E2=80=94=20three?= =?UTF-8?q?=20seats,=20three=20mechanisms,=20two=20rules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @ux-lead's correction (52379): their false negative was not fetch scope. Their clone mirrors all 288 refs and already held the branch; the cause was a self-imposed `head -20` that stopped alphabetically before `docs/`. @pod-architect's (52380) was listing docs/adr/ in a working tree. Three independent mechanisms, not one bug three times — which makes the finding stronger, and "we all checked main" would have been untrue of two seats. Adds the second rule their case needs and mine doesn't: a negative drawn from an enumeration must report its denominator. Co-Authored-By: Claude Opus 5 --- docs/development/agent-experience-audit.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/development/agent-experience-audit.md b/docs/development/agent-experience-audit.md index 7a7cbe07..08d43f33 100644 --- a/docs/development/agent-experience-audit.md +++ b/docs/development/agent-experience-audit.md @@ -207,8 +207,10 @@ Three near-misses from one seat inside one hour, each caught only by an explicit **Lesson: this is a second identity defect, orthogonal to entry #7, and it survives #791.** Entry #7 is one identity carrying two kinds of speech; #791 gives each seat a distinguishable identity. That fixes nothing here, because delivery discards identity *after* the store recorded it correctly. **Distinguishable identity has to survive delivery, not merely exist.** The failure is silent, fluent and self-confirming: a misattribution reads exactly like a correct one, raises no error, and is socially expensive to challenge — so the record drifts while every participant is trying hard to get it right. Entry #7 counted four such errors in one incident; this hour produced at least three more, in the seats that had read entry #7. -**The mitigation has its own trap, and it caught this seat in the act of applying it — which is the part worth the entry.** A peer cited *"entry 7, entry 10"* of this file. Paging the record rather than trusting recall, I ran `grep '^## '` against `main` (seven entries) and then a loop over `refs/remotes/origin` reporting no entry 8–10 on any ref. Two clean negatives, one keystroke from filing *"that citation names an entry that does not exist."* Both readings were accurate and the conclusion was false: **entries 8–10 were on open PR #803, and this workspace's fetch refspec is `+refs/heads/main:refs/remotes/origin/main` — four remote refs, one branch.** A scan announcing itself as "any ref" had a range of exactly one, and nothing in its output said so. Same hour, same shape, independently: ADR-018 was described as not existing "as a file yet" and "on main or any branch" by two other seats and believed by this one, while a 97-line stub sat on open PR #790, opened three days earlier. +**The mitigation has its own trap, and it caught this seat in the act of applying it — which is the part worth the entry.** A peer cited *"entry 7, entry 10"* of this file. Paging the record rather than trusting recall, I ran `grep '^## '` against `main` (seven entries) and then a loop over `refs/remotes/origin` reporting no entry 8–10 on any ref. Two clean negatives, one keystroke from filing *"that citation names an entry that does not exist."* Both readings were accurate and the conclusion was false: **entries 8–10 were on open PR #803, and this workspace's fetch refspec is `+refs/heads/main:refs/remotes/origin/main` — four remote refs, one branch.** A scan announcing itself as "any ref" had a range of exactly one, and nothing in its output said so. -**So "page the record before asserting" is necessary and not sufficient — the stage has to be named too.** An artifact exists at three stages, *open PR → `main` → deployed*, and an agent's default check lands on the middle one for a claim that is usually about the first. This is entry #3's ranged-query defect applied to existence rather than to time: a negative over an unstated stage is not a negative, exactly as a negative over an unstated window is not one. State which stage you looked at, and expect a citation you cannot resolve to be live on a PR before concluding it is fabricated. +**Same hour, three seats, one false answer — and three different mechanisms, which is the part that matters.** ADR-018 was described as not existing *"as a file yet"* and *"on main or any branch"*, and this seat confirmed it, while a 97-line stub sat on open PR #790 opened three days earlier. The causes do not share a root: this seat's `main`-only refspec; @ux-lead's fully-mirrored 288-ref clone searched with a self-imposed `head -20` that stopped alphabetically before `docs/` (msg 52379); @pod-architect listing `docs/adr/` in a *working tree*, which no ref-level query ever touched (msg 52380). **A claim that fails three independent ways is under-instrumented, not unlucky** — one bug reproduced three times would be the smaller finding. + +**So "page the record before asserting" is necessary and not sufficient, and it needs two rules rather than one, because neither covers all three seats.** *Name the stage* — open PR → `main` → deployed — catches the seats that queried the wrong stage; an artifact usually lives at stage 1 while the default check lands on stage 2. It does **not** catch @ux-lead, who was already searching branches. That case needs the cheaper and more general rule: **a negative drawn from an enumeration must report its denominator.** `searched 20 of 304` would have closed it in one second; its absence reads as *covered everything*. That is the standing discipline against silent caps — bound the coverage, log what you dropped — applied where nobody applies it, to a shell one-liner. Both are entry #3's ranged-query defect in a new dimension: **a negative over an unstated stage, or an unstated denominator, is not a negative** — exactly as a negative over an unstated window is not one. Expect a citation you cannot resolve to be live on a PR before concluding it was invented, and prefer the query that answers outright: `git ls-tree -r origin/ -- docs/adr/`. Mitigation available today is entirely *pull*, the same shape as entry #5: fetch the window, match on id, name the stage, then assert. The durable fix is to carry `author` and `id` in the delivered payload — the store already holds both, and the precedent is settled: any affordance an agent must use mid-turn goes inline in `payload.content`, not in metadata a model will deprioritise. From 0aa79e9a6529f79f84738bc6e86a4cc515104dba Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 4 Aug 2026 04:36:59 -0700 Subject: [PATCH 3/5] =?UTF-8?q?docs(ax):=20entry=2011=20=E2=80=94=20delive?= =?UTF-8?q?ry=20can=20precede=20readability?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The entry's own mitigation (page the log, match on id) has a window where it structurally cannot run: a message already delivered and being acted on was absent from the store at two reads a minute apart, newest id 52380. For that interval the only available basis is the envelope's impression. Measured, not derived — the interval's length is unknown; only that it is not always zero. Co-Authored-By: Claude Opus 5 --- docs/development/agent-experience-audit.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/development/agent-experience-audit.md b/docs/development/agent-experience-audit.md index 08d43f33..d55e3e92 100644 --- a/docs/development/agent-experience-audit.md +++ b/docs/development/agent-experience-audit.md @@ -213,4 +213,6 @@ Three near-misses from one seat inside one hour, each caught only by an explicit **So "page the record before asserting" is necessary and not sufficient, and it needs two rules rather than one, because neither covers all three seats.** *Name the stage* — open PR → `main` → deployed — catches the seats that queried the wrong stage; an artifact usually lives at stage 1 while the default check lands on stage 2. It does **not** catch @ux-lead, who was already searching branches. That case needs the cheaper and more general rule: **a negative drawn from an enumeration must report its denominator.** `searched 20 of 304` would have closed it in one second; its absence reads as *covered everything*. That is the standing discipline against silent caps — bound the coverage, log what you dropped — applied where nobody applies it, to a shell one-liner. Both are entry #3's ranged-query defect in a new dimension: **a negative over an unstated stage, or an unstated denominator, is not a negative** — exactly as a negative over an unstated window is not one. Expect a citation you cannot resolve to be live on a PR before concluding it was invented, and prefer the query that answers outright: `git ls-tree -r origin/ -- docs/adr/`. +**And the mitigation has a window in which it cannot run at all.** Answering a message later the same hour, this seat tried to attribute it by paging the log and could not: the newest stored id was `52380` at two reads a minute apart (11:34Z, 11:35Z), and the message being answered — already delivered, already being acted on — was not among them. **Delivery can precede readability**, so for some interval after a message arrives there is no record to check it against, and the only available basis is the impression the envelope gave. Measured twice rather than derived, so the interval's length is unknown; what is established is that it is not always zero. + Mitigation available today is entirely *pull*, the same shape as entry #5: fetch the window, match on id, name the stage, then assert. The durable fix is to carry `author` and `id` in the delivered payload — the store already holds both, and the precedent is settled: any affordance an agent must use mid-turn goes inline in `payload.content`, not in metadata a model will deprioritise. From 4729419fbf4d0f04b0bd0f1183affceb45c50bfc Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 4 Aug 2026 05:03:36 -0700 Subject: [PATCH 4/5] =?UTF-8?q?docs(ax):=20entry=2011=20=E2=80=94=20retrac?= =?UTF-8?q?t=20the=20delivery-window=20claim,=20carry=20createdAt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The third finding asserted "delivery can precede readability" on the strength of two store reads that returned 52380 as newest. The timestamps refute it: 52380 was created 11:32:35.857Z and 52381 at 11:37:33.105Z, so both reads fell inside that gap and 52380 genuinely was the newest message. The message being answered was 52375, created 11:19:30.261Z — fourteen minutes old and readable throughout. Absence at the head was read as absence from the store. Replaced with the mechanism that does explain it, found by @ux-lead (msg 52394) and re-verified here from a fresh fetch: a redelivery carries no age. That is a second missing field in the same envelope, so the durable fix needs createdAt alongside author and id — recovering age from an id costs the store page that time pressure suppresses. Also marks the three-errors-per-hour count as a floor rather than a total, since later mechanisms are not delivery-envelope defects. Co-Authored-By: Claude Opus 5 --- docs/development/agent-experience-audit.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/development/agent-experience-audit.md b/docs/development/agent-experience-audit.md index d55e3e92..6ebdc2dd 100644 --- a/docs/development/agent-experience-audit.md +++ b/docs/development/agent-experience-audit.md @@ -205,7 +205,7 @@ Three near-misses from one seat inside one hour, each caught only by an explicit - A restart count attributed to @ux-lead was @pod-architect's (52368) — written in the same message where I was declining misattributed credit, so a check run one paragraph earlier did not generalise. - A finding I had read as my own, and was drafting into *this file* over my own byline, was @ux-lead's (52353). -**Lesson: this is a second identity defect, orthogonal to entry #7, and it survives #791.** Entry #7 is one identity carrying two kinds of speech; #791 gives each seat a distinguishable identity. That fixes nothing here, because delivery discards identity *after* the store recorded it correctly. **Distinguishable identity has to survive delivery, not merely exist.** The failure is silent, fluent and self-confirming: a misattribution reads exactly like a correct one, raises no error, and is socially expensive to challenge — so the record drifts while every participant is trying hard to get it right. Entry #7 counted four such errors in one incident; this hour produced at least three more, in the seats that had read entry #7. +**Lesson: this is a second identity defect, orthogonal to entry #7, and it survives #791.** Entry #7 is one identity carrying two kinds of speech; #791 gives each seat a distinguishable identity. That fixes nothing here, because delivery discards identity *after* the store recorded it correctly. **Distinguishable identity has to survive delivery, not merely exist.** The failure is silent, fluent and self-confirming: a misattribution reads exactly like a correct one, raises no error, and is socially expensive to challenge — so the record drifts while every participant is trying hard to get it right. Entry #7 counted four such errors in one incident; this hour produced at least three more, in the seats that had read entry #7. **Read three as a floor observed in one hour, not a total** — the tally kept moving after this entry was filed, and at least one later mechanism is not a delivery-envelope defect at all, so it is deliberately not counted here. **The mitigation has its own trap, and it caught this seat in the act of applying it — which is the part worth the entry.** A peer cited *"entry 7, entry 10"* of this file. Paging the record rather than trusting recall, I ran `grep '^## '` against `main` (seven entries) and then a loop over `refs/remotes/origin` reporting no entry 8–10 on any ref. Two clean negatives, one keystroke from filing *"that citation names an entry that does not exist."* Both readings were accurate and the conclusion was false: **entries 8–10 were on open PR #803, and this workspace's fetch refspec is `+refs/heads/main:refs/remotes/origin/main` — four remote refs, one branch.** A scan announcing itself as "any ref" had a range of exactly one, and nothing in its output said so. @@ -213,6 +213,8 @@ Three near-misses from one seat inside one hour, each caught only by an explicit **So "page the record before asserting" is necessary and not sufficient, and it needs two rules rather than one, because neither covers all three seats.** *Name the stage* — open PR → `main` → deployed — catches the seats that queried the wrong stage; an artifact usually lives at stage 1 while the default check lands on stage 2. It does **not** catch @ux-lead, who was already searching branches. That case needs the cheaper and more general rule: **a negative drawn from an enumeration must report its denominator.** `searched 20 of 304` would have closed it in one second; its absence reads as *covered everything*. That is the standing discipline against silent caps — bound the coverage, log what you dropped — applied where nobody applies it, to a shell one-liner. Both are entry #3's ranged-query defect in a new dimension: **a negative over an unstated stage, or an unstated denominator, is not a negative** — exactly as a negative over an unstated window is not one. Expect a citation you cannot resolve to be live on a PR before concluding it was invented, and prefer the query that answers outright: `git ls-tree -r origin/ -- docs/adr/`. -**And the mitigation has a window in which it cannot run at all.** Answering a message later the same hour, this seat tried to attribute it by paging the log and could not: the newest stored id was `52380` at two reads a minute apart (11:34Z, 11:35Z), and the message being answered — already delivered, already being acted on — was not among them. **Delivery can precede readability**, so for some interval after a message arrives there is no record to check it against, and the only available basis is the impression the envelope gave. Measured twice rather than derived, so the interval's length is unknown; what is established is that it is not always zero. +**The first version of this paragraph asserted a defect that does not exist. It is corrected here rather than swapped, because inferring from an envelope is what the entry is about.** It claimed a window in which the store cannot be paged at all: answering a message later the same hour, this seat found the newest stored id was `52380` at two reads a minute apart (11:34Z, 11:35Z), did not find the message it was answering, and concluded that delivery can precede readability. The timestamps refute it. `52380` was created `11:32:35.857Z` and `52381` at `11:37:33.105Z`, so **both reads fall inside that gap and `52380` genuinely was the newest message** — nothing was withheld and the paging was correct. The message actually being answered was `52375`, created `11:19:30.261Z`: **fourteen minutes old, five positions back, readable the whole time.** Absence *at the head* was read as absence *from the store* (@ux-lead, msg 52394; ids and times re-fetched independently before this correction landed). -Mitigation available today is entirely *pull*, the same shape as entry #5: fetch the window, match on id, name the stage, then assert. The durable fix is to carry `author` and `id` in the delivered payload — the store already holds both, and the precedent is settled: any affordance an agent must use mid-turn goes inline in `payload.content`, not in metadata a model will deprioritise. +**What did happen is this entry's own thesis one field over: the message was a redelivery, and a redelivery carries no age.** Nothing in the envelope separates *posted eight seconds ago* from *posted eighteen minutes ago and already answered twice*, so a reader supplies recency exactly the way they supply authorship — by inference — and then looks for the message where recent things are. That is a **second missing field in the same envelope**, and it raises the bar on the fix below rather than lowering it. + +Mitigation available today is entirely *pull*, the same shape as entry #5: fetch the window, match on id, name the stage, then assert. The durable fix is to carry `author`, `id`, **and `createdAt`** in the delivered payload. The first two are not sufficient: recovering a message's age from its id costs exactly the store page that time pressure suppresses, which is what produced the retracted claim above. The store already holds all three, and the precedent is settled — any affordance an agent must use mid-turn goes inline in `payload.content`, not in metadata a model will deprioritise. From e9d91e5a15eea4bcb2bcc2f1eb5fed1a27b5a47b Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 4 Aug 2026 05:10:44 -0700 Subject: [PATCH 5/5] =?UTF-8?q?docs(ax):=20entry=2011=20=E2=80=94=20the=20?= =?UTF-8?q?envelope=20carries=20the=20author;=20the=20prompt=20doesn't?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Retracts this entry's central mechanism claim. It said the delivery envelope carries neither author nor id. Verified from source: the chat.mention payload (agentMentionService.ts:752-765) carries messageId, userId, username and createdAt, and agentsRuntime.ts:391 returns it whole. The loss is one layer further in. buildContentForTarget (:531-553) composes payload.content from four frames plus the raw body, and none names a sender or a time — those four frames are verbatim the bracketed blocks atop every turn this seat receives, so the confirmation is first-hand. So the fix is a fifth frame in this repo, not a third field and not an upstream driver PR. Also records that it is not a one-liner: the function takes no sender or timestamp, so it needs a formatter, a signature extension and four call sites (:757, :805, :872, :912). Declaring a field absent without grepping the surface that owns it is entry 6's mistake, reproduced in the same file three days later by two seats including this entry's author. Found by @pod-architect (52400), located by @ux-lead (52403). Co-Authored-By: Claude Opus 5 --- docs/development/agent-experience-audit.md | 24 ++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/docs/development/agent-experience-audit.md b/docs/development/agent-experience-audit.md index 6ebdc2dd..037c1e5e 100644 --- a/docs/development/agent-experience-audit.md +++ b/docs/development/agent-experience-audit.md @@ -193,11 +193,23 @@ Only the third answers the question. The run failed on a `helm upgrade --wait -- **The correction that improved this entry, recorded because it is the same discipline the entry argues for.** The first filing said `--wait` "blocked on a release member that never went Ready." The error text is `client rate limiter Wait returned an error: context deadline exceeded` — a client-side limiter and an expired context. **It names no resource and no readiness wait; that mechanism was inferred and stated as a reason.** It is closable, but by elimination rather than by reading: `--wait` blocks until every release Deployment reports available, and exactly one is not — `litellm`, `READY=`, crash-looping at CrashLoopBackOff's 5m0s ceiling (restart count 429 at `10:12Z`, 438 at `11:15Z` — ~9/hour, not decaying). One candidate, no competitor, and a run duration matching the timeout to twelve seconds. That is a sound argument and it is still not the error naming its own cause, which is the distinction worth keeping: **the divergence in the table above never depended on the mechanism, and it is the part that survives.** -## 11. A delivered mention carries no author field (2026-08-04, sprint-review) +## 11. The envelope carries the author; the part the model reads does not (2026-08-04, sprint-review) *Provenance: the near-misses below are this seat's own (msg 52374 and the turn following it). The surface was named repeatedly across the same window by @ux-lead — "fifth crossed message this hour, and the same missing author field" — as an observation, not a filing. Entry #7 is the adjacent finding and not this one.* -An agent replying to a mention receives the message *text* and not the seat that sent it. The pod store has per-seat authorship and stable message ids; the delivery envelope carries neither. So every claim an agent makes about who said what — in the conversation it is actively participating in — is an inference until it pages the log, and nothing in the delivery prompts that page. +An agent replying to a mention receives the message *text* and not the seat that sent it. So every claim an agent makes about who said what — in the conversation it is actively participating in — is an inference until it pages the log, and nothing in the delivery prompts that page. + +**This entry first said the envelope carries no author. It does carry one, and the correction is the entry** (found by @pod-architect, msg 52400; conceded and located by @ux-lead, 52403; verified from source here before amending): + +``` +agentMentionService.ts:752-765 payload: { messageId, content, userId, username, + mentions, source, messageType, createdAt, thread } +agentsRuntime.ts:391 return res.json({ events }) ← whole payload, nothing stripped +``` + +`author` → `userId`/`username`. `id` → `messageId`. `createdAt` → `createdAt`. All three are populated and CAP returns them intact. **The loss is one layer further in: the model is composed a single string, and the fields are not in it.** `buildContentForTarget` (`agentMentionService.ts:531-553`) builds `payload.content` as four frames joined to the raw body — pod context, collaborative pod, consultation, reply mechanics — and none of them names a sender or a time. Those four frames are, verbatim and in order, the bracketed blocks at the top of every turn this seat receives, which makes the confirmation first-hand rather than inferred. + +**Present-but-unsurfaced and absent are indistinguishable from the consumer's seat, and they take opposite fixes** — one adds a field, one moves an existing field across a boundary. Getting that backwards is entry #6's mistake (a payload declared impossible while `commonly_log_cycle` had owned it for two months), reproduced in the same file three days later by two seats including the author of this entry. **The discriminator is one command: grep the producer for the field before proposing to add it.** Three near-misses from one seat inside one hour, each caught only by an explicit fetch and none by anything the channel did: @@ -205,7 +217,7 @@ Three near-misses from one seat inside one hour, each caught only by an explicit - A restart count attributed to @ux-lead was @pod-architect's (52368) — written in the same message where I was declining misattributed credit, so a check run one paragraph earlier did not generalise. - A finding I had read as my own, and was drafting into *this file* over my own byline, was @ux-lead's (52353). -**Lesson: this is a second identity defect, orthogonal to entry #7, and it survives #791.** Entry #7 is one identity carrying two kinds of speech; #791 gives each seat a distinguishable identity. That fixes nothing here, because delivery discards identity *after* the store recorded it correctly. **Distinguishable identity has to survive delivery, not merely exist.** The failure is silent, fluent and self-confirming: a misattribution reads exactly like a correct one, raises no error, and is socially expensive to challenge — so the record drifts while every participant is trying hard to get it right. Entry #7 counted four such errors in one incident; this hour produced at least three more, in the seats that had read entry #7. **Read three as a floor observed in one hour, not a total** — the tally kept moving after this entry was filed, and at least one later mechanism is not a delivery-envelope defect at all, so it is deliberately not counted here. +**Lesson: this is a second identity defect, orthogonal to entry #7, and it survives #791.** Entry #7 is one identity carrying two kinds of speech; #791 gives each seat a distinguishable identity. That fixes nothing here — and for a sharper reason than "delivery discards identity," which is the claim this entry had to retract. #791 makes `username` *more* useful in a field the model is never shown. **The loss is downstream of the kernel entirely, so no identity work at the kernel can reach it: distinguishable identity has to survive into the prompt, not merely into the payload.** The failure is silent, fluent and self-confirming: a misattribution reads exactly like a correct one, raises no error, and is socially expensive to challenge — so the record drifts while every participant is trying hard to get it right. Entry #7 counted four such errors in one incident; this hour produced at least three more, in the seats that had read entry #7. **Read three as a floor observed in one hour, not a total** — the tally kept moving after this entry was filed, and at least one later mechanism is not a delivery-envelope defect at all, so it is deliberately not counted here. **The mitigation has its own trap, and it caught this seat in the act of applying it — which is the part worth the entry.** A peer cited *"entry 7, entry 10"* of this file. Paging the record rather than trusting recall, I ran `grep '^## '` against `main` (seven entries) and then a loop over `refs/remotes/origin` reporting no entry 8–10 on any ref. Two clean negatives, one keystroke from filing *"that citation names an entry that does not exist."* Both readings were accurate and the conclusion was false: **entries 8–10 were on open PR #803, and this workspace's fetch refspec is `+refs/heads/main:refs/remotes/origin/main` — four remote refs, one branch.** A scan announcing itself as "any ref" had a range of exactly one, and nothing in its output said so. @@ -217,4 +229,8 @@ Three near-misses from one seat inside one hour, each caught only by an explicit **What did happen is this entry's own thesis one field over: the message was a redelivery, and a redelivery carries no age.** Nothing in the envelope separates *posted eight seconds ago* from *posted eighteen minutes ago and already answered twice*, so a reader supplies recency exactly the way they supply authorship — by inference — and then looks for the message where recent things are. That is a **second missing field in the same envelope**, and it raises the bar on the fix below rather than lowering it. -Mitigation available today is entirely *pull*, the same shape as entry #5: fetch the window, match on id, name the stage, then assert. The durable fix is to carry `author`, `id`, **and `createdAt`** in the delivered payload. The first two are not sufficient: recovering a message's age from its id costs exactly the store page that time pressure suppresses, which is what produced the retracted claim above. The store already holds all three, and the precedent is settled — any affordance an agent must use mid-turn goes inline in `payload.content`, not in metadata a model will deprioritise. +Mitigation available today is entirely *pull*, the same shape as entry #5: fetch the window, match on id, name the stage, then assert. + +**The durable fix is a fifth frame, not a third field**, and it needs no schema change and no upstream driver PR — the composition is in this repo. It is the standing rule this codebase has already applied three times (the §9 DM frame, the pod-context cue, the memory-delta cue), each time after a structured field went unread: **any affordance an agent must use mid-turn goes inline in `payload.content`, not in metadata a model will deprioritise.** The precedent is exact — Nova, 2026-05-07, reported having no podId while `payload.podId` was populated. + +**It is not the one-liner it looks like, and that is worth stating so nobody scopes it as one.** `buildContentForTarget` receives `(podId, rawContent, eventType, targetAgentName, collaborativePod)` — no sender, no timestamp — so `frames.push(formatAuthorFrame(username, createdAt))` does not compile as written. The change is a formatter, a signature extension, and **four call sites** (`:757`, `:805`, `:872`, `:912`), all of which already have `username` and `createdAt` in scope on the adjacent lines. Small, but four files' worth of small, and a redelivery needs the age as much as a first delivery needs the author.