From b362c675d6461012309c1471cc84085191e5a8a0 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 25 Aug 2026 01:55:28 -0700 Subject: [PATCH 1/3] docs(cli): mark the surviving `limit: 10` as a read, not a claim MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @sprint-review (57766): after #1166 this is the only `limit: 10` left in agent.js, and the reason it is fine is one function away and invisible here. Anyone who greps the constant after reading that thread has to re-derive the distinction — two identical strings, opposite significance, no local marker. No behaviour change. The events fetch went to 1 because fetching an event CLAIMS it; this endpoint returns pod messages for the echo check and claims nothing, so ten rows cost ten rows. Comment rather than a test because there is no wrong behaviour to pin — the failure mode is a reader's question, and the answer belongs where the question gets asked. Co-Authored-By: Claude Opus 5 --- cli/src/commands/agent.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cli/src/commands/agent.js b/cli/src/commands/agent.js index 9f7e10436..6df9440b8 100644 --- a/cli/src/commands/agent.js +++ b/cli/src/commands/agent.js @@ -803,6 +803,12 @@ export const performRun = ({ // suppress a genuine reply (#757). const snapshotMessages = async () => { try { + // READ limit, not a claim. Since #1166 this is the only `limit: 10` + // left in the file, and the one it is easy to mistake it for — the + // events fetch — was reduced to 1 precisely because fetching an + // event CLAIMS it. This endpoint claims nothing: it returns pod + // messages so the echo check can see what is already there, and + // asking for ten costs ten rows. const { messages = [] } = await client.get( `/api/agents/runtime/pods/${eventPodId}/messages`, { limit: 10 }, ); From cce56bd826726c9b76655226716d3513e1bca8fe Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 25 Aug 2026 02:00:00 -0700 Subject: [PATCH 2/3] docs(agents): cite installedBy's writers by symbol, and stop implying five MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @sprint-review recounted (57771) and the bot half holds at exactly five. The human half does not: the comment listed five sites as though that were the set, and there are at least ten — podController, authController, personaHireService, podCurationService, agentProfile, registry/install, registry/admin, dmService twice, and one in THIS file, the auto-install inside resolveMentionTarget writing `senderUserId`. Line numbers dropped for symbols, per the rule #1165 earned: a sha 404s and a grep for a symbol fails loudly, but a line number answers wrongly. Five of the six positions this comment cited had already moved. The count itself is now stated as a floor with the grep that reproduces it, because the failure here was not the number being wrong on the day — it was a number frozen into prose where nothing re-derives it. The grep's caveat is included too: it returns queries (agentMemoryView, approvalActionService) and propagations of an existing value, neither of which writes an identity. Re-deriving that distinction is what separated my ten from a larger raw count. Co-Authored-By: Claude Opus 5 --- backend/services/agentMentionService.ts | 26 ++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/backend/services/agentMentionService.ts b/backend/services/agentMentionService.ts index 1f9081cbf..bf1d19d45 100644 --- a/backend/services/agentMentionService.ts +++ b/backend/services/agentMentionService.ts @@ -1126,13 +1126,25 @@ const enqueueWakeOnMessage = async ({ // // NOT `installedBy`. @sprint-review's blocker (57291) was right and the // comment that used to sit here was wrong. `installedBy` is written with - // two different identities depending on who installed the agent — the bot - // itself at agentAutoJoinService:80, podWriteAccessService:48 and three - // sites in agentsRuntime, but the HUMAN installer at podController:119, - // personaHireService:93, podCurationService:147, authController:201 and - // agentProfile:259 (AgentRun.ts:65 calls it "the hiring user" outright). - // The schema declares a bare ObjectId with no ref, so nothing at the type - // level distinguishes them. + // two different identities depending on who installed the agent — the BOT + // itself in `agentAutoJoinService`, `podWriteAccessService` and three + // sites in `agentsRuntime`, but the HUMAN installer in `podController`, + // `authController`, `personaHireService`, `podCurationService`, + // `agentProfile`, `registry/install`, `registry/admin`, `dmService` + // (twice) — and in THIS file, at the auto-install inside + // `resolveMentionTarget`, which writes `senderUserId`. `AgentRun.ts` calls + // the field "the hiring user" outright. The schema declares a bare + // ObjectId with no ref, so nothing at the type level distinguishes them. + // + // No line numbers and no total, deliberately, per the rule #1165 earned: + // cite by symbol, never by a position the next edit rewrites silently. An + // earlier draft of this comment listed five human-side sites as though + // that were the set; there are at least ten, and @sprint-review's recount + // (57771) found the gap only because the number had been frozen into + // prose. `grep -rn 'installedBy:' backend | grep -v __tests__` is the + // reader that stays correct — note it also returns queries + // (`agentMemoryView`, `approvalActionService`) and propagations of an + // existing value, which are not writes of an identity. // // Keying on it would have read a human-installed agent's thread state off // its INSTALLER's row: the human's mute would silence the agent, and the From ae80d9831b33ba88a6f3967143fe4c0a101fa3b4 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 25 Aug 2026 02:18:58 -0700 Subject: [PATCH 3/3] =?UTF-8?q?docs(agents):=20approvalActionService=20wri?= =?UTF-8?q?tes=20installedBy=20too=20=E2=80=94=20it=20was=20filed=20under?= =?UTF-8?q?=20queries?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @sprint-review 57854 pushed the caller-identity half to "9 or more". Re-derived against `grep -rn 'installedBy:' backend | grep -v __tests__` (43 non-test occurrences) and separated writes from filters and propagations: - Bot identity: exactly 5 (agentAutoJoinService, podWriteAccessService, agentsRuntime ×3) — as written, unchanged. - Caller identity: 12, not 10. The two this comment missed are approvalActionService:572 and :660, both `$setOnInsert: { installedBy: row.ownerUserId }`. The previous draft named that file under queries ONLY — it does both, and listing it on one side made the other side invisible. - `agentMemoryView:123` is a query filter, not a write, so it does not join the human list; the comment already named it as a query and that stands. The count is now stated as a floor the enumeration reaches, not a census, and the query/propagation clause names its members so the next reader can tell which kind each site is without re-running the split. Comment-only. 62/62 agentMentionService tests green; no tsc errors in this file. Co-Authored-By: Claude Opus 5 --- backend/services/agentMentionService.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/backend/services/agentMentionService.ts b/backend/services/agentMentionService.ts index bf1d19d45..7523730bd 100644 --- a/backend/services/agentMentionService.ts +++ b/backend/services/agentMentionService.ts @@ -1131,7 +1131,8 @@ const enqueueWakeOnMessage = async ({ // sites in `agentsRuntime`, but the HUMAN installer in `podController`, // `authController`, `personaHireService`, `podCurationService`, // `agentProfile`, `registry/install`, `registry/admin`, `dmService` - // (twice) — and in THIS file, at the auto-install inside + // (twice), `approvalActionService` (twice, via `$setOnInsert` of the + // stored `ownerUserId`) — and in THIS file, at the auto-install inside // `resolveMentionTarget`, which writes `senderUserId`. `AgentRun.ts` calls // the field "the hiring user" outright. The schema declares a bare // ObjectId with no ref, so nothing at the type level distinguishes them. @@ -1139,12 +1140,15 @@ const enqueueWakeOnMessage = async ({ // No line numbers and no total, deliberately, per the rule #1165 earned: // cite by symbol, never by a position the next edit rewrites silently. An // earlier draft of this comment listed five human-side sites as though - // that were the set; there are at least ten, and @sprint-review's recount - // (57771) found the gap only because the number had been frozen into - // prose. `grep -rn 'installedBy:' backend | grep -v __tests__` is the + // that were the set; the enumeration above reaches twelve and is still a + // floor, not a census. @sprint-review's recount (57771) found the gap only + // because the number had been frozen into prose. `grep -rn 'installedBy:' backend | grep -v __tests__` is the // reader that stays correct — note it also returns queries - // (`agentMemoryView`, `approvalActionService`) and propagations of an - // existing value, which are not writes of an identity. + // (`agentMemoryView`, `users`, `registry/install`'s `$ne` filter) and + // propagations of an existing value (`registry/provision`, + // `stalledConnectService`, `registry/helpers`), neither of which writes an + // identity. `approvalActionService` does BOTH, which is why an earlier + // draft of this line filed it under queries alone. // // Keying on it would have read a human-installed agent's thread state off // its INSTALLER's row: the human's mute would silence the agent, and the