This repository was archived by the owner on May 26, 2026. It is now read-only.
feat(KR-2 ST3): scratchpad reads + deferred-write surface#7
Merged
Conversation
Read paths against kronicle.agent_scratchpad_entries (foundation/0135), mirroring the ST2 RLS-GUC-in-transaction pattern. Write path is deferred because the substrate-side Sea MCP tool kora__write_agent_scratchpad doesn't exist yet (substrate main a3e77f6); spec § ST3 explicitly authorizes the BUILD_DEVIATIONS fallback for this case and forbids direct INSERT (would skip cap_write_agent_scratchpad authorization, approved_event_id chain event, and visibility_scope validation). Read paths (plugins/memory/isokron/scratchpad.py): * read_own_scratchpad — JOIN actor_registry, filter actor_kind='kora' AND status='active'. Default limit 100 per spec § ST3. * read_cross_agent_scratchpad — JOIN actor_registry, filter actor_kind != 'kora' AND visibility_scope='cross_agent_dereferenceable' AND status='active'. * Both: RLS GUC set via set_config(...,true) inside a transaction before the SELECT, identical to ST2's policy_registry pattern. * BLAKE3 content_hash mismatch logs WARNING but does NOT raise (per spec § ST3: scratchpad is mutable working memory; refusing drifted entries would block sessions on transient state). Unlike ST2's Role Charter which is fail-closed. Write surface (deferred): * write_scratchpad_entry raises ScratchpadWriteNotAvailableError with message tagged [kora.isokron.todo] + D-kr2-st3-no-scratchpad-write- mcp-tool. Signature matches the future MCP-backed impl so caller code doesn't refactor when the tool lands. * Schema-faithful enums: ScratchpadKind (7 values), VisibilityScope (2). * compute_scratchpad_content_hash helper (BLAKE3 hex; matches foundation/0135's stored format). Provider wiring (plugins/memory/isokron/provider.py): * sync_turn — _looks_like_kora_action(assistant_content) heuristic (regex match on \bcap_[a-z0-9_]+\b); on match, _attempt_scratchpad_ write submits the deferred write via the dedicated IO loop, catches ScratchpadWriteNotAvailableError, logs one-line WARNING — session stays alive. Cache pre-invalidation runs on attempt (success or defer) so a future MCP-tool swap doesn't expose stale data. * on_memory_write — mirrors built-in memory writes as a reasoning_trail scratchpad entry with action+target in the summary; same catch-and- continue pattern. * read_own_scratchpad + read_cross_agent_scratchpad — sync wrappers via connection.submit_and_wait; cached 60s per workspace. * prefetch / queue_prefetch unchanged (no-op since ST2). Tests (26 new in tests/plugins/memory/test_scratchpad.py): * Read shapes (own + cross-agent), RLS GUC ordering, limit binding, cross-agent SQL filter check. * BLAKE3 mismatch warns + does NOT raise; content_uri rows skip the inline integrity check. * write_scratchpad_entry raises with the right tag + deviation ID. * _looks_like_kora_action parametrize across positive/negative cases + word-boundary regex anchor. * sync_turn no-op without kora_action; with kora_action attempts write + catches defer + logs; cache invalidates on attempt; workspace_id missing → debug-log + no attempt + turn alive. * on_memory_write embeds action+target in summary; defers gracefully. * Provider-level read_own_scratchpad cache hit-after-fetch (single pool.fetch call across two reads). ST1 skeleton parametrize trimmed: sync_turn and on_memory_write removed (now implemented). Remaining stubs target ST4 / KR-3. Local gates: * ty check — 7,337 diagnostics (same as KR-2 ST2 baseline; zero-delta). * pytest tests/plugins/memory/test_{scratchpad,reads,capability_matrix_ parity,isokron_provider_skeleton}.py — 68/68 passing (26 new ST3 + 18 ST2 + 2 parity + 22 ST1 skeleton after trim). * Full suite via xdist (-n auto): 24,551 passed / 143 failed / 129 skipped vs ST2-merge baseline 24,443/227/129 → +108 passed, −84 failures. None of the failures touch plugins/memory/isokron/; same tests/tools/* + tests/tui_gateway/* xdist isolation noise as ST2. Rule-6: * BUILD_DEVIATIONS.md gains D-kr2-st3-no-scratchpad-write-mcp-tool under Open with the grep-snapshot of available kora__* tools in substrate main and exact closure condition. * README "Operator pitfalls" adds two entries: deferred-write notice (grep for the deviation ID in logs) + scratchpad warn- on-mismatch semantics (vs fail-closed Role Charter). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ships KR-2 ST3: scratchpad reads against
kronicle.agent_scratchpad_entries(foundation/0135) + deferred-write surface. Read paths match the ST2 RLS-GUC-in-transaction pattern; the write path is deferred because the Sea MCP server (substrate maina3e77f67) does not yet exposekora__write_agent_scratchpad— spec § ST3 explicitly authorizes BUILD_DEVIATIONS for this case and forbids direct INSERT (would skipcap_write_agent_scratchpadauthorization +approved_event_idchain event + visibility_scope validation).Rule-3 STOP-gate findings during recon
kronicle.agent_scratchpad_entriesusesworkspace_id TEXT REFERENCES public.workspaces(id)— same shape as the ST2 reads. The PM dispatch's "tenant_id UUID keying / JOIN hivex_foundation.tenant" was a memory-only assertion that doesn't match foundation/0135 on current main. Verified by reading the migration verbatim. Standing memory note ("Never ask PM for substrate state — grep yourself") applied; spec SQL was correct.packages/sea-mcp-server/src/tools/on substrate main — onlykora__propose_convention,kora__read_escalation_queue,kora__propose_policy_changeexist. Spec § ST3 § 3 pre-authorizes this exact case: "If the tool doesn't exist substrate-side yet, BUILD_DEVIATIONS + queue for substrate-team via PM coordination. Do NOT bypass with direct INSERT." → implemented as deferred-write surface.What landed
plugins/memory/isokron/scratchpad.pyScratchpadEntry,ScratchpadKindenum (7 values),VisibilityScopeenum (2 values),ScratchpadWriteNotAvailableError,compute_scratchpad_content_hash(BLAKE3 hex), canonical SQL constants, asyncread_own_scratchpad, asyncread_cross_agent_scratchpad, deferredwrite_scratchpad_entry.plugins/memory/isokron/provider.py_looks_like_kora_actionheuristic +_summarize_for_scratchpadtruncation;sync_turnreal impl (heuristic → attempt write → catch defer → log);on_memory_writereal impl (mirrors built-in memory writes);_attempt_scratchpad_writeshared try/catch/cache-invalidate; provider-levelread_own_scratchpad/read_cross_agent_scratchpadsync wrappers viaconnection.submit_and_wait.tests/plugins/memory/test_scratchpad.pytests/plugins/memory/test_isokron_provider_skeleton.pysync_turnandon_memory_writeremoved (now implemented). Remaining stubs target ST4 / KR-3.plugins/memory/isokron/README.mdD-kr2-st3-no-scratchpad-write-mcp-toolin logs) and scratchpad warn-on-mismatch vs fail-closed Role Charter. Sub-task table updated.BUILD_DEVIATIONS.mdD-kr2-st3-no-scratchpad-write-mcp-toolunder Open: closure condition is the Sea MCP write tool shipping; signature is forward-stable so onlywrite_scratchpad_entry's body changes when the tool lands.Read SQL (verbatim, mirrors spec § ST3 + foundation/0135 verified)
Both bracketed by
BEGIN; SELECT set_config('app.current_workspace_id', $1, true); ... COMMIT;to satisfy the RLS policy keyed off the GUC (same pattern as ST2's policy_registry; without it the table silently returns zero rows).sync_turn heuristic
Per spec § ST3 § 4: "any tool call that's a Kora-action (cap_*) gets a scratchpad entry summarizing what happened". Implemented as a regex
\bcap_[a-z0-9_]+\boverassistant_content. Word-boundary anchored (no false positives on substrings likesupercap_sea_create). Match → attempt write → onScratchpadWriteNotAvailableErrorlog a one-line WARNING + continue (turn stays alive).Test plan
26 new tests, all passing:
Read paths:
test_read_own_scratchpad_returns_typed_entries— actor_kind=kora filter, typed entriestest_read_own_scratchpad_sets_rls_guc_before_select— txn.enter → execute → fetch → txn.exittest_read_own_scratchpad_binds_workspace_id_and_limit— SQL params + default limit 100test_read_cross_agent_scratchpad_returns_typed_entries— multiple actor_kinds (critic+oracle), scope filteredtest_read_cross_agent_scratchpad_sql_excludes_kora_and_filters_scope— SQL WHERE clause inspectionBLAKE3 integrity:
test_blake3_hash_mismatch_logs_warning_and_does_not_raise— warn-only, not fail-closedtest_compute_scratchpad_content_hash_matches_blake3_hexdigest— bytes-faithful to substrate-side storagetest_content_uri_entries_skip_integrity_check— no false-positive drift on object-store rowsDeferred write:
test_write_scratchpad_entry_raises_deferred_write_error— exact tag + BUILD_DEVIATIONS ID in messageHeuristic + summarizer:
test_looks_like_kora_action_heuristic(parametrized x8 — positive/negative cases incl. digits + word-bounds)test_kora_action_pattern_is_word_bounded— nosupercap_*false positivetest_summarize_for_scratchpad_returns_short_content_unchangedtest_summarize_for_scratchpad_truncates_long_content_with_marker— 2KB cap + clear "[truncated]" suffixProvider-level write paths:
test_sync_turn_no_kora_action_is_noop— no cap_* → zero writes attemptedtest_sync_turn_kora_action_attempts_write_and_catches_deferred_error— write attempted, error caught, WARNING logged with deviation IDtest_sync_turn_invalidates_own_cache_on_attempted_write— pre-invalidates so future MCP-tool swap surfaces fresh datatest_on_memory_write_mirrors_to_scratchpad_with_action_and_target—[memory.{action} → {target}]summary prefixtest_sync_turn_skips_silently_without_workspace_id— debug-log, no write attempt, turn aliveProvider-level reads:
test_provider_read_own_scratchpad_caches_results— single pool.fetch across two reads (cache hit)Plus parametrized expansions on
_looks_like_kora_actionfor a total of 26.Gates
ty check— 7,337 diagnostics, same as KR-2 ST2 baseline (Δ 0). Zero new diagnostics introduced.pytest tests/plugins/memory/test_{scratchpad,reads,capability_matrix_parity,isokron_provider_skeleton}.py— 68/68 passing (26 new ST3 + 18 ST2 read tests + 2 parity + 22 ST1 skeleton after parametrize trim).-n auto): 24,551 passed / 143 failed / 129 skipped. Δ vs ST2 merge baseline (24,443 / 227 / 129): +108 passed, −84 failures. Sametests/tools/*+tests/tui_gateway/*xdist isolation noise as ST2; none touchplugins/memory/isokron/.Rule-6 / BUILD_DEVIATIONS / Open asks
D-kr2-st3-no-scratchpad-write-mcp-toolopened inBUILD_DEVIATIONS.md. PM coordinates substrate-team / files the substrate dispatch for akora__write_agent_scratchpadSea MCP tool. When it lands,scratchpad.write_scratchpad_entry's body swaps from raising tomcp_client.invoke('kora__write_agent_scratchpad', ...)— signature is forward-stable, no provider refactor needed.IsoKronMemoryProvider(handle_tool_call,on_session_end,on_session_switch,on_pre_compress,on_delegation,save_config) still raiseNotImplementedErrorwith[kora.isokron.todo]tags pointing to ST4 / KR-3.workspace_id TEXT(nottenant_id UUID);actor_kindnot a column on the scratchpad table (JOIN actor_registry);content_hashBLAKE3 hex;visibility_scopeenum (not bool);actor_labelderived fromactor_registry.display_name.Standing by for ST4 dispatch and the substrate-team coordination on the scratchpad-write MCP tool.
🤖 Generated with Claude Code