Repository navigation
feat(connector): whole messages, schedules, channels, team status - #2443
Conversation
…nd team status - sam_chat_read returns whole messages (streamed chunks assembled in the ProjectData DO) with tool/thought activity summaries, boundary-safe cursors and the latest user/assistant messages; unit:'rows' keeps the stored-row paging - sam_chat_message_get reads one whole message by offset; sam_chats_search adds whole-message excerpts - request_human_input questions (attention markers) now appear in sam_chat_read, sam_chat_interactions and sam_work_changes; the inbox selects chats with questions before its recency cap and notification items carry their marker id and options; the D1 session index picks up marker changes and prefers questions over system markers - sam_team_status: bounded lineage/channel team view with state, waits, PR head/checks, agent-reported evidence and measured usage - migration 0208 indexes tasks.parent_task_id and coordination channels Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- sam_schedules_list/get/create/update/cancel over the ProjectData one-off schedules and cron triggers: DST-safe local times, idempotent creates, distinct accepted/admitted/started/outcome phases, project-scoped reads - sam_channels_list/history/get and sam_channel_subscription_cancel: bounded channel reads with rosters and subscribers, agent-dm hidden by default, cancel limited to subscriptions of chats the caller controls - scheduled starts spend the Connector start budget; audit, receipts and instructions cover the new writes - trigger pause/resume extracted into services/trigger-status.ts - connector read limits split into a dependency-free definition module - tests: DO whole-message reader, transcript operations, attention visibility, inbox selection, D1 summary sync, notification dedup, team status, schedules, channels Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- public Connector guide: reading chats/teams/channels, scheduling work, agent questions in per-chat reads and the inbox, read limits pointer - admin settings guide: Connector read limits table - API reference notes and api-reference skill: new tools and semantics - fix: REST trigger PATCH resuming with a new cron took the next fire from the old cron (regression test through the real route) - fix: one malformed one-off schedule row no longer fails the whole list Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keeps the schedule and channel operation tests on real migration SQL while satisfying the source-contract-test gate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sam_task_get and get_task_details listed the newest raw streamed chunks as recent assistant messages, and the final-message read still had tests written against the raw-row reader. One whole-message read now serves both fields, and the tests run the real transcript reader on SQLite. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pers Review fixes: - sam_team_status fits the Connector response: agent text is shortened first (new admin setting connector.teamTextChars), then the lowest-ranked tasks are left out; both are disclosed, and counts and usage still cover every task read. - sam_inbox_get checks at most limit chats per page, questions first, and each list's cursor moves only past chats the page used. - One run rule and scan page size for every whole-message reader. - One row parser that logs content-free reasons (team reads no longer log validation messages that could quote agent text). - DIRECT_CHANNEL_RANGE_END lives in shared for API and web. - Response byte budgets in one module; attention categories checked against HUMAN_INPUT_CATEGORIES and shared with inbox notifications; session lookups chunk by the shared bind limit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…l-existing-505new
- ProjectData migration 070 indexes attention markers by created_at and resolved_at, and the session summary delta selects changed sessions and sessions with changed markers as two indexed row sets (an OR scanned every session on every sync). A plan test pins it. - An archived transcript read shares one R2 deadline across its pages instead of starting a fresh one per page. - A whole message is sliced from its chunks; the full text is built only for a focused search. - Archived chats (SQLite and compact R2) are tested to page exactly as they did live. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…; docs - Workers test calls sam_chat_read, sam_chat_message_get, sam_team_status, the schedule tools and sam_channels_list through the real /connect/mcp adapter into the real ProjectData object, including a non-member refused with not_found. - Scheduled starts share the start budget with sam_chat_start; scheduled messages to a chat do not spend it. - The latest request off the page is returned itself, cut to its share. - Schedule operation kinds pinned; authorization tests assert codes. - Search excerpts look up each chat's transcript owner once; connector.searchContextResults is capped at 5. - Docs: team activity states, team trimming, inbox paging, recent replies in task details, connector.teamTextChars. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The shared deadline for one archived read moved into compactArchiveReadDeadline, so the R2 timeout setting is still read only by the archive modules the omitted-var coverage probe exercises. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reuses the existing per-row isolation helper instead of an inline loop, which keeps the module within the 500-line limit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ved reads Fix verification review: - Results are measured as the Connector response carries them: the structured copy plus the escaped text copy, where quotes and backslashes cost twice again. Pages of quote-heavy text no longer overflow the response cap (tested with the adapter's envelope). - Team status lists as many tasks as fit and shortens agent text only when that lists more; empty agent text is null and the untrusted-text guidance is stated once, so a default 40-task team fits. - An archived read that runs out of its R2 time returns what it read with a resume cursor (transcript pages, single messages and comment context) instead of failing. - Inbox cursors from before questions were listed separately continue their questions from the old position. - sam_task_get and /sam get_task_details report the same final reply. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the
|
Confirmation review (all LOW): - sam_channel_history shortens every post until a page of multi-byte or quote-heavy text fits one response; no post is skipped. - sam_chats_search leaves out the last excerpts, and says how many, when all of them would not fit. - A read that ran out of archive time reports mayContinueInNewerPage as null (unknown) instead of false. - mapRows logs the id of a row it skips (rule 50), which the schedule list now relies on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CI found two consequences of this branch: - Resolving an attention marker returned SQLite rowsWritten, which on a Durable Object also counts index entries, so migration 070's new index changed the reported count. The resolve functions now return the number of markers resolved (RETURNING), independent of indexes. - Pull request states always carried headSha and checksUpdatedAt, even when unknown, which grew byte-bounded agent context enough to drop an idea update. They are now included only when known. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…l-existing-505new
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@coderabbitai review |
|
|



Summary
Implements idea
01M5PRH5C9ZBZ1C21AYQ8QWMC5(SAM task01M5SKY95H590EWADCMP505NEW): make the user-level SAM Connector (/connect/mcp) usable for coordinating a team of agents from ChatGPT or Claude. All changes go through the shared operations registry, so the Connector stays a thin adapter.sam_chat_readnow returns whole messages by default. Streamed chunks are assembled inside the ProjectData Durable Object (durable-objects/project-data/logical-transcript*.ts,logical-message.ts). Pages break only between messages, so each chunk appears exactly once across pages. Tool calls, hidden thoughts and plans become boundedactivityentries instead of being dropped. The first page names the latest user request and assistant reply.limitcounts messages, and role filters scan a bounded, disclosed window instead of returning empty pages. Long messages are capped withtruncated+nextOffset, and the newsam_chat_message_getreads the rest by offset. Thinking is withheld unless requested.unit: "rows"keeps the previous stored-row paging for diagnostics.sam_chats_searchattaches whole-message excerpts to the top results.sam_task_getnow returns the complete latest assistant reply.sam_schedules_list,sam_schedule_get,sam_schedule_create,sam_schedule_updateandsam_schedule_cancelsit over the existing one-off ProjectData schedules and cron triggers. Wall-clock input is converted to UTC with explicit DST gap and overlap handling. Creates are idempotent (Connector receipt plus a DO idempotency key). Scheduled starts spend the same start budget assam_chat_start. Responses keep acceptance, admission, execution receipt, task outcome and owner notification separate, and report unknowns as unknown. Recurring schedules can be paused, resumed or edited, but not deleted, through the Connector.sam_channels_list,sam_channel_history,sam_channel_get(roster + subscribers) andsam_channel_subscription_cancel(only for chats the caller can write). Peer posts are fenced as untrusted text. Humans still cannot post to channels: that needs a new human actor for channel events, and it is filed for a decision as Idea01M5SR2HB56YT0VFY6BB6TCNCK.sam_team_status(scope: task, chat or coordination channel) returns bounded lineage, state with observation freshness, blockers and agent questions, PR head/CI state, evidence labelled agent-claimed vs control-plane, and measured usage. Values SAM does not record are reported as such: per-task tokensunavailable, deployed SHAnot_recorded, provider subscription limitsprovider_reported_last_observed. Nothing is estimated.request_human_inputquestions now appear aspendingAttentioninsam_chat_read(owners and shared writers only), asattentioninsam_chat_interactions, and insam_work_changesfingerprints.sam_inbox_getselects chats with open questions ahead of the recency cap, and its notifications carry the marker ID, category and options. Underneath: marker create/resolve now refresh the D1 session summary, the summary prefers answerable questions over other markers, and notification dedup keeps the newest marker's metadata. Answering still needssam_agent_answer, which the Connector instructions require the user to confirm.Review-driven changes (local specialist review, see below):
sam_inbox_getchecks at mostlimitchats per page (questions first); team status lists as many tasks as fit the response, shortening agent text (new settingconnector.teamTextChars) only when that lists more, with disclosure; results are sized by what the adapter actually sends (both copies of the result, including the escaped text copy); ProjectData migration070indexes attention-marker changes and the summary delta reads them as two indexed row sets; archived transcript reads share one R2 deadline and, when it runs out, return what they read with a resume cursor;sam_task_get/get_task_detailsrecentAssistantMessagesare whole replies (they were raw streamed chunks); shared helpers instead of copies (run rule, row parser that logs content-free reasons, response byte budget,DIRECT_CHANNEL_RANGE_ENDinpackages/shared).Adjacent fixes found on the way:
PATCH /api/projects/:id/triggers/:triggerIdresuming with a new cron computed the next fire from the old cron (sharedservices/trigger-status.ts), and the DO schedule list now skips one malformed row instead of failing the whole read (rule 50).Read limits are admin settings in the
Connectorcategory (connector.*,services/connector-read-settings-definition.ts), not new Worker env vars. Migration0208adds two partial indexes ontasks(parent_task_id,(project_id, coordination_channel)).Tool schema changes and compatibility
sam_chat_message_get,sam_team_status,sam_schedules_list,sam_schedule_get,sam_channels_list,sam_channel_history,sam_channel_get. New write tools:sam_schedule_create,sam_schedule_update,sam_schedule_cancel(destructive),sam_channel_subscription_cancel(write). Read-only connections see no write tools.sam_chat_read: new optionalunit(messagesdefault,rowslegacy). The default response shape changes to logical messages (paginationUnit: "logical_messages"). Cursor format is unchanged, and legacy mid-message cursors are flagged. The workspace-agent path is unchanged.sam_chats_search(excerpt,excerptCoverage),sam_chat_interactions(attention) andsam_inbox_get(question,coverage, cursorattentionkey).sam_inbox_getpages check at mostlimitchats, questions first; older inbox cursors still parse.sam_task_get:finalAssistantMessageis the complete latest reply andrecentAssistantMessagesare whole replies, newest first (same field names and shape, plus optionalpartialBefore/truncated).sam_team_statusresults carrycounts.listed,truncated,omittedandagentTextShortenedTowhen a team is too large for one response; a task without agent text hassummary: null, and the untrusted-text guidance is stated once (untrustedTextGuidance).Validation
pnpm lintpnpm typecheckpnpm test.claude/rules/47-control-loop-io-budget.md)Local validation (branch head after review fixes):
pnpm check:fast(format ratchet, ESLint, type-boundary ratchet) andtsc --noEmitforapps/apiandapps/web: pass.quality:source-contract-tests,quality:do-migration-safety,quality:migration-safety,quality:migration-ordering,quality:runtime-tunables,quality:wrangler-bindings, file-size check for new files: pass.apps/apiunit suite on12580f35f: 13,889 tests, 0 failures (JSON reportersuccess: true). The changes after it, in2ae748061(channel and search fitting, the unknown continuation flag, logging the skipped row's id), were verified with the affected unit files (622 tests, plus 50 project-event tests); CI runs the full suite on the head. An earlier run found one failure, the omitted-var coverage guard flagging a new read ofPROJECT_DATA_ARCHIVE_R2_TIMEOUT_MS; it was fixed inbc2e2c09b.582789824. (1) Resolving an attention marker returned SQLiterowsWritten, which on a Durable Object also counts index entries, so migration 070 changed the count; it now returns the number of markers resolved. (2) Pull-request states always carried nullheadShaandchecksUpdatedAt, which grew byte-bounded agent context enough to drop an idea update; they now appear only when known.tests/workers/connector-whole-message-team-tools.test.ts(new; real/connect/mcpadapter into the real ProjectData Durable Object), plusconnector-oauth,notification-dedup-do,workflow-runs,session-summary-index-sync,project-data-compact-archive(all pass; re-run after the last fixes: 61 tests in the four affected files) andsam-grounding-runtimeunder the SAM runtime config (35 pass).team-status.test.ts), inbox per-page cap (connector-operations.test.ts), indexed summary delta and migration 070 (session-summary-sync.test.tsplan test), shared archive R2 deadline (logical-transcript-archive.test.ts), scheduled-start budget in both directions (execution.test.ts), off-page latest fitting (connector-transcript.test.ts), excerpt owner memo (connector-transcript.test.ts), recent-replies page budget (task-final-assistant-message.test.ts), plus the earlier dedup metadata, summary priority, inbox question-first, legacy cursor, writer gate, schedule list isolation and trigger PATCH checks.I/O per call (rule 60):
sam_chat_read5 (owner) or 8 (shared writer);sam_chat_message_get2–3;sam_chats_searchabout 3 plus up toconnector.searchContextResults(default 3, max 5) excerpt reads, owner looked up once per chat;sam_inbox_getat most 10 (4 D1, at mostlimitInteractionStore reads, 1 Notification; was 9);sam_team_statusabout 8–12;sam_task_getone whole-message read (was two raw reads); schedule and channel tools 2–5. Inbox, search and team status are cross-project or project-wide aggregations (budget 20).Candidate selection (rule 47): the ProjectData session-summary delta now also selects sessions whose attention markers were created or resolved since the last sync. Expected volume is the number of marker changes since the previous debounced sync (small, still capped by the existing
LIMIT); per-candidate cost is unchanged (one D1 upsert). Both halves are index range searches (migration 070, pinned by a query-plan test).Staging Verification (REQUIRED for all code changes — merge-blocking)
N/A: staging skipped by explicit user authorization for this task ("User explicitly authorizes SKIPPING STAGING for this task. Do not add a staging deployment/test gate."). Verification is local unit/integration tests, CI, specialist review, and read-only/owned-fixture checks against production after deploy.
Staging Verification Evidence
N/A: staging skipped by explicit user authorization. Production verification evidence is added after deploy.
UI Compliance Checklist (Required for UI changes)
N/A: no UI change. The only
apps/webedit importsDIRECT_CHANNEL_RANGE_ENDfrompackages/sharedinstead of defining the same value locally (apps/web/src/lib/query-options/automation.ts); web typecheck andautomation-flows.test.tsxpass, and the CI visual audit runs because the path changed.UI Screenshot Evidence
N/A: no UI changes.
End-to-End Verification (Required for multi-component changes)
.claude/rules/10-e2e-verification.md)Data Flow Trace
POST /connect/mcp(routes/connector-mcp.ts:createConnectorServer) →operations/registry.ts→samChatRead.run(operations/platform-operations.ts) →authorizeProjectOperation→readChat(operations/chat-core.ts):writerPendingRequests(InteractionStore viaconnectorPendingInteractions;pendingAttentioninoperations/attention-core.ts→services/project-data.ts:listActiveAttentionMarkers→durable-objects/project-data/attention.ts) andreadChatMessages(operations/chat-transcript.ts) →services/project-data.ts:getLogicalTranscriptPage→ DOarchiveSourceGetLogicalTranscript/archiveTargetGetLogicalTranscript(durable-objects/project-data/index.ts) →readLogicalTranscriptPage(logical-transcript.ts) oversourceTranscriptReader/targetTranscriptReader(message-context.ts) → byte budget (operations/response-budget.ts) → envelope size check inconnector-mcp.ts.request_human_input(routes/mcp/human-input-tool.ts) → DOcreateAttentionMarker→scheduleSummarySync→session-summary-sync.ts:SESSION_SUMMARY_DELTA_SQL→ D1session_summaries.attention_json(summary prefers answerable questions,attention.ts:getAttentionSummary) →sam_inbox_get(operations/connector-read-core.ts:inboxGet); Notification DO dedup keeps the newest marker's metadata (durable-objects/notification.ts) → inboxquestion.sam_team_status(operations/team-operations.ts) →teamStatus(operations/team-core.ts) →readTeamTasks(operations/team-lineage.ts, recursive CTE on the migration 0208 index) +listAgentActivityTasks, DOgetSessionsByTaskIds,getPullRequestStates,agent_sessions,compute_usage,listProjectCredentialLimits→fitTasks.sam_schedule_create(operations/schedule-operations.ts) →createSchedule(operations/schedule-writes.ts) →executeConnectorWrite(services/connector-execution.ts: receipt, write and start budgets) → DOcreateProjectSchedule(one-off) orcreateTrigger(services/trigger-create.ts, recurring) →sam_schedule_get(operations/schedule-reads.ts:getSchedule→schedule-core.ts:findSchedule).sam_channels_list/sam_channel_history/sam_channel_get(operations/channel-operations.ts) → DOlistProjectEventChannels/getProjectEventChannelHistory/listProjectEventChannelSubscribers+ D1 roster (channel-core.ts:channelRoster);sam_channel_subscription_cancel→requireSubscriptionCanceller→ DOcancelProjectEventSubscription.Capability test across the boundaries:
apps/api/tests/workers/connector-whole-message-team-tools.test.ts.Untested Gaps
schedule-operations.test.ts), not through the Workers adapter path.01M5SR2HB56YT0VFY6BB6TCNCKand01M5SR2Q7PH4FEK8YDYDQDJ10M): human channel posting, inbox coverage of shared chats, /sam access to the new reads, newest-first channel history, cron UTC-offset zones, per-task token counts, per-member privacy of schedule text and direct channels. Deployed commit is reported asnot_recorded.Post-Mortem (Required for bug fix PRs)
N/A: not a bug fix. This PR is a feature; the two adjacent fixes (trigger PATCH next-fire cron, schedule list row isolation) carry regression tests.
Specialist Review Evidence (Required for agent-authored PRs)
needs-human-reviewlabel added and merge deferred to human01M5SR2Q7PH4FEK8YDYDQDJ10M(item 6). LOW:agent-dm.*participant check (same idea); team status shows that a question exists without its text, by design.80e09af88). MEDIUM per-page R2 deadline: one budget per archived read (80e09af88), returning what was read when it runs out (8a4cb8338). LOW/MEDIUM whole-run concatenation: only the requested slice is built (80e09af88).limitchats per page, questions first (eed17870f). HIGH unindexed summary-sync subquery: migration 070 plus a plan test (80e09af88). MEDIUM excerpt owner lookup per hit: one lookup per chat, andconnector.searchContextResultscapped at 5 (85c57625d). LOW sequentialfindSchedule: kept, because a parallel lookup would add a D1 query to every one-off read.parseRowsSkippingInvalid. MEDIUMDIRECT_CHANNEL_RANGE_ENDmoved topackages/shared. MEDIUM unused type alias removed. LOW shared UTF-8 helper reused. All ineed17870f.connector.teamTextCharssetting. LOW attention category length: categories validated againstHUMAN_INPUT_CATEGORIES. LOW bind chunk size: uses the shared D1 limit. All ineed17870f.tools/callslice through the real adapter and Durable Object, schedule kinds pinned,sam_chat_message_getnon-member case. LOW: exact error codes, and the real DO RPC exercised. Commits80e09af88and85c57625d.85c57625d,8a4cb8338).85c57625d).8a4cb8338. A confirmation pass found every one of those findings resolved and four new LOWs, all fixed in2ae748061: channel pages and search excerpts are now fitted to the response, an out-of-time continuation is reported as unknown, and skipped schedule rows are logged with their id.CodeRabbit Review Evidence (Required for agent-authored PRs)
CodeRabbit Notes
Requested at 2026-10-25 17:22:44 UTC by applying the
coderabbit-reviewlabel after the PR left draft with CI green; the trusted bridge workflow (run40216177798) succeeded. CodeRabbit answered at 17:22:58 UTC: "Action not completed: Review rate limited". It had also posted a "Review limit reached" notice when the draft opened at 16:23 UTC. CodeRabbit did not review. Per.claude/rules/25-review-merge-gate.md, the rate-limit outcome is recorded and the PR proceeds on its remaining gates; it was not re-triggered.Production Deployment and Verification
Merged as
a3a802caab12fabf18fa8e785f06ea1e94183452at 2026-10-25 17:37:34 UTC.skill-form-dialog-agent-models.test.tsx), which passed 3 of 3 runs locally, and the re-run passed.DATABASE.vm_provisioning_leases: 1 -> 0 (100.000% decrease exceeds 50% churning-table limit). Migration 0208 (twoCREATE INDEXstatements ontasks) was applied at 18:18:36 UTC. The Worker was not deployed.placedat 18:19:00.872 UTC, between the gate's two counts, and placement deletes its provisioning lease (releaseVmProvisioningLease). The lease count is still 0, and both new indexes exist. No restore was run; the printed time-travel restore would have erased legitimate production writes.sam-api-prodat 18:38:58 UTC with annotationcommit:a3a802caab12fabf18fa8e785f06ea1e94183452, version3a8b3d4e-7561-460f-a77a-26aa1431e487at 100% of traffic.healthy, and the app returns 200./.well-known/oauth-protected-resource/connect/mcpreturns 200 with resourcehttps://api.simple-agent-manager.org/connect/mcpand scopessam.read sam.write.POST /connect/mcpreturns 401 with the Bearerresource_metadatachallenge.get_task_detailscallssamTaskGet. Before the deploy,recentAssistantMessagesheld five one-chunk fragments of a single reply. After the deploy it holds five whole replies, newest first, assembled by the ProjectData logical transcript reader.search_messages(samChatsSearch) andget_linked_context(samLinkedContextGet) return without errors.tools/callthrough/connect/mcpitself. No production Connector token or OAuth client is available to this workspace; the smoke token is staging-only by design. The adapter path is covered bytests/workers/connector-whole-message-team-tools.test.ts, which uses the real adapter, a PAT and a real Durable Object.Exceptions (If any)
Agent Preflight (Required)
Classification
External References
N/A: no new external APIs. Internal contracts only; IANA time zone conversion uses the runtime
Intl.DateTimeFormatalready used by the web automation page.Codebase Impact Analysis
apps/api/src/durable-objects/project-data/(logical transcript readers, attention summary, summary sync, schedule list isolation, compact archive deadline),apps/api/src/durable-objects/migrations.ts(ProjectData migration 070, additive indexes),apps/api/src/durable-objects/notification.ts(dedup metadata),apps/api/src/lib/runtime-validation.ts+apps/api/src/services/workflow-run-read.ts(shared row parser),packages/shared/src/types/project-event-channels.ts+apps/web/src/lib/query-options/automation.ts(shared constant),apps/api/src/operations/(chat, transcript, attention, inbox, team, schedule, channel operations; registry),apps/api/src/services/(project-data wrappers, connector execution/receipts, connector read settings, trigger status, final assistant message, agent activity),apps/api/src/routes/connector-mcp.ts(instructions),apps/api/src/routes/triggers/crud.ts(PATCH next fire),apps/api/src/db/migrations/0208_*+schema.ts,packages/shared/src/types/pull-requests.ts(optional fields).Documentation & Specs
Updated
apps/www/src/content/docs/docs/guides/sam-connector.md,apps/www/src/content/docs/docs/guides/admin-settings.md,apps/www/src/content/docs/docs/reference/api.md,.claude/skills/api-reference/SKILL.md. Nospecs/edits (outside a spec context, rule 01).Constitution & Risk Check
Principle XI: new limits are typed admin settings with code defaults (no env vars). Remaining constants are structural (DO page size inside a bounded scan, D1 bind chunking, response-cap share) and named. Principle X: one implementation per operation; REST and Connector share the schedule/trigger services. Risks: default
sam_chat_readresponse shape change (mitigated byunit: "rows"); added DO scan work per read (bounded byconnector.transcriptScanRows, disclosed incoverage); new write tools (task:write, session-writer checks, receipts, idempotency, start budget); attention visibility (writer-gated question text).🤖 Generated with Claude Code