This repository was archived by the owner on May 26, 2026. It is now read-only.
feat(KR-3 ST1): iso_node_* typed-graph tool family#9
Merged
Conversation
Ships 4 model-facing MCP tools that replace Hermes' flat memory.set /
memory.append / memory.get with a typed-node API backed by Plan 02's
kronicle.agent_scratchpad_entries:
* iso_node_create — append a typed node (18 canonical IsoKron entity
kinds: Decision / Gotcha / Pattern / Convention / Concept / Ticket /
FailedAttempt / AcceptanceTest / GamingPattern / Project / Component
/ Milestone / CrossCut / ExternalDependency / Resource / Tool /
Schema / KronicleBlock). v0.1 packs node_kind into content_inline
header so iso_node_read / search recover it without schema changes
(dedicated column lands in KR-3a if read patterns firm up).
* iso_node_read — point read by entry_id; searches own + cross-agent
caches (KR-3a will add a dedicated single-row substrate fetch).
* iso_node_search — node_kind filter + free-text substring (FTS in
KR-3a) + optional cross_agent_only inclusion + server-side limit
cap (max 50 per spec).
* iso_node_supersede — append-only revision; inherits node_kind from
the original entry; attempts the supersession write + the
kora.node.superseded chain event (both deferred behind their
existing BUILD_DEVIATIONS entries).
Write paths route through scratchpad.write_scratchpad_entry which
still defers behind ScratchpadWriteNotAvailableError. The tool
handlers catch the defer + return a structured envelope
{"ok": False, "deferred": True, "deviation_id":
"D-kr2-st3-no-scratchpad-write-mcp-tool", "message": ...} so the
model gets an in-band signal rather than an exception. Read paths
are fully functional (work today against the existing read surface).
Provider wiring:
* get_tool_schemas returns the 4 schemas in OpenAI function-call
format (matches mem0/honcho/etc. existing memory providers).
* handle_tool_call dispatches "iso_node_*" by prefix to the new
handler; unknown tool names fall through to the ABC default's
clear "Provider isokron does not handle tool X" error.
Capability gating (Plan 04 actorHasCapability Python mirror) ships
in KR-6 — until then the in-module assert_kora_can_perform helper
is a stub that always allows and logs every invocation tagged with
the new BUILD_DEVIATIONS entry D-kr3-st1-capability-check-deferred
so operators can grep how often the stub is being relied on. Spec
§ ST1 explicitly pre-authorized this deferral path.
Tests (22 new):
* Schema validity (well-formed shape, 18-node-kind enum sync,
OpenAI function-call format).
* Content packing/unpacking round-trip + legacy / null fallback.
* Capability check stub logs the deviation ID.
* iso_node_create: deferred-write envelope shape; invalid node_kind
rejection; invalid scratchpad_kind rejection; missing required
fields.
* iso_node_read: hits own cache; hits cross-agent cache; returns
error on missing entry.
* iso_node_search: node_kind filter; case-insensitive text query;
server-side limit cap; cross_agent_only inclusion.
* iso_node_supersede: inherits original's node_kind; errors when
original is missing.
* Dispatch: unknown tool raises; provider.handle_tool_call routes
iso_node_* by prefix.
ST1 skeleton test updated: test_tool_schemas_empty_at_st1 replaced
with test_tool_schemas_exposes_iso_node_family (the family is the
new tool surface).
Local gates:
* ty check — 7,337 diagnostics, zero-delta vs KR-2 ST4 baseline.
* pytest tests/plugins/memory/ — 270/270 passing (22 new ST1 + 248
pre-ST1).
* Full suite via xdist (-n auto): 24,535 / 157 fail / 43 err / 129
skip. xdist isolation noise in tests/tools/* (kanban + others
pass in isolation — same family as ST2-ST4 documented noise);
none touch plugins/memory/isokron/.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 21, 2026
rafe-walker
added a commit
that referenced
this pull request
May 22, 2026
Phase 2 Feature 5 frontend. Pairs with CC#3 KR-FEAT-SLACK-DM (#119). - Backend /api/slack-dm/recent stub (4 messages spanning happy path + filtered_non_joshua). - SlackDMPanel.tsx (stats + filter pills + newest-first timeline + expandable rows). - Dashboard card #9 (MessageCircle icon) + nav + 15 backend tests. 4-layer security contract (extending standard 3-layer with a 4th walk-payload guard for Slack-specific tokens): no raw U... Slack user IDs + channel_id stub shape + plain-text rendering (with dangerouslySetInnerHTML ban) + Slack token/signing-secret walk-payload sweep. Layout: 9 cards = clean 3+3+3 with lg:grid-cols-3 — landed the symmetry sweet spot, no orphans. 219/219 admin-panel tests pass across 20 suites; tsc + vite clean.
Merged
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
KR-3 ST1 ships the
iso_node_*typed-graph tool family — 4 model-facing MCP tools that replace Hermes' flatmemory.set/memory.append/memory.getsurface with a typed-node API backed by Plan 02'skronicle.agent_scratchpad_entries.iso_node_createiso_node_readentry_idiso_node_searchnode_kind+ free-text substring +cross_agent_onlyiso_node_supersedenode_kind); emitskora.node.supersededv0.1 simplification per spec § 32:
iso_node_*operates only against the scratchpad surface. Full read-across the 17 entity tables lands in KR-3a once read patterns + permissions firm up. The model still gets a richer memory surface than flat MEMORY.md, just scoped to Kora's own scratchpad.Deferred-write envelopes
Write paths route through
scratchpad.write_scratchpad_entrywhich still raisesScratchpadWriteNotAvailableError(KR-2 ST3 deferral). The tool handlers catch the defer and return a structured envelope:{ "ok": false, "deferred": true, "deviation_id": "D-kr2-st3-no-scratchpad-write-mcp-tool", "message": "[kora.isokron.todo] ..." }In-band signal to the model rather than an exception escape. When K-8 ships the Sea MCP write tool,
write_scratchpad_entrybody swaps to the MCP call and these envelopes naturally turn into{"ok": true, "entry_id": "..."}— handler code stays unchanged.Capability gating
Each handler asserts the relevant
cap_*viaassert_kora_can_perform(e.g.iso_node_create→cap_write_agent_scratchpad). The Python mirror of TS-sideassertKoraCanPerformships in KR-6 (Constitution pre-screen middleware); until thenassert_kora_can_performis a no-op stub that logs every call tagged with new BUILD_DEVIATIONS entryD-kr3-st1-capability-check-deferredso operators can grep how often the stub is being relied on. Spec § ST1 explicitly pre-authorized this deferral.v0.1 content encoding
The substrate's
kronicle.agent_scratchpad_entries.scratchpad_kindis a closed 7-value enum, separate from the broader 18 IsoKron entity kinds. v0.1 packsnode_kind+titleinto thecontent_inlineheader so reads can recover it without schema changes:The body delimiter (
\n---\n) lets the model include arbitrary markdown without breaking the parse. Legacy / non-iso_node entries surface as body-only (nonode_kind/title).What landed
plugins/memory/isokron/tools/__init__.pyISO_NODE_TOOL_SCHEMAS,NODE_KINDS,assert_kora_can_perform,handle_iso_node_tool_call).plugins/memory/isokron/tools/iso_node.pyplugins/memory/isokron/provider.pyget_tool_schemasnow returns the 4 iso_node schemas;handle_tool_calldispatchesiso_node_*by prefix; falls through to ABC default for unknown tool names.BUILD_DEVIATIONS.mdD-kr3-st1-capability-check-deferredunder Open — closes when KR-6 ships the PythonassertKoraCanPerformmirror.tests/plugins/memory/test_iso_node_tools.pytests/plugins/memory/test_isokron_provider_skeleton.pytest_tool_schemas_empty_at_st1→test_tool_schemas_exposes_iso_node_family(asserts the 4 expected names + OpenAI shape).Test plan
22 new tests, all passing:
Schemas + registration (3):
test_iso_node_schemas_are_well_formed— 4 schemas, OpenAI function-call shapetest_node_kinds_canonical_list_has_18_entries— 17 IsoKron + KronicleBlocktest_iso_node_create_schema_enum_matches_node_kinds— JSON Schema enum in sync with PythonNODE_KINDStupleContent packing (3):
test_pack_then_unpack_round_trips_fieldstest_unpack_handles_legacy_unpacked_contenttest_unpack_handles_null_content_inlineCapability stub (1):
test_assert_kora_can_perform_stub_logs_deviation_id— log line carries both the deviation ID + the capability nameiso_node_create(4):deviation_idnode_kindscratchpad_kindiso_node_read(3):iso_node_search(4):node_kindlimitcap (max 50)cross_agent_onlyincludes other actor_kinds (critic, oracle, etc.)iso_node_supersede(2):node_kindfrom the original entry — verified by checking the deferred submission actually ran (means lookup succeeded + packing happened before the write defer)Dispatch (2):
provider.handle_tool_callroutesiso_node_*by prefixGates
ty check— 7,337 diagnostics, zero-delta vs KR-2 ST4 baseline.pytest tests/plugins/memory/— 270/270 passing (22 new ST1 + 248 pre-ST1).-n auto): 24,535 / 157 failed / 43 errors / 129 skipped. Sametests/tools/*+tests/tui_gateway/*xdist isolation noise as KR-2 ST2-ST4; the failing kanban tests pass in isolation. None of the failures touchplugins/memory/isokron/.Rule-6 / BUILD_DEVIATIONS / Open asks
D-kr3-st1-capability-check-deferred— closes when KR-6 ships the PythonactorHasCapabilitymirror.D-kr2-st2-capability-matrix-mirror← K-7,D-kr2-st3-no-scratchpad-write-mcp-tool← K-8 (affectsiso_node_create+iso_node_supersedewrites),D-kr2-st4-no-chain-emit-mcp-tool← K-9 (affectsiso_node_supersede'skora.node.supersededevent).raise <DeferredError>tomcp_client.invoke(...). Tool handlers stay unchanged.Standing by for KR-3 ST2 dispatch (iso_link_* family — typed edges; ST2 recon on RelationLink table name + schema).
🤖 Generated with Claude Code