Submit Boundary
Status: Design landing Reference epics: INK-830 ADRs: ADR-017
What the submit boundary is
Section titled “What the submit boundary is”The submit boundary is the world model’s single enforcement point for every modification to the workspace. Any operation that writes to the workspace — creating a page, editing a block, adding a tag, creating a derivation link, promoting a candidate to canonical, importing content, executing a scheduled task’s write — crosses the submit boundary. On that transit, the world model’s invariants are applied: provenance is recorded, derivation links are attached, deviation records are produced when conflicts appear, the retroactive-revision queue is updated when revised sources affect derived content.
“Submit” is shorthand for the conceptual boundary. The literal tools that cross it — create_page, edit_block, add_relation, record_derivation, promote_to_canonical, import-pipeline writes, scheduled-task writes — are many; the boundary they cross is one.
What the boundary requires
Section titled “What the boundary requires”At the boundary, every crossing write must carry:
- Origin. Always populated from the caller’s identity.
authoredfor user writes,agent-producedfor agent writes,importedfor import-pipeline writes,observedfor recorded workspace events. See Provenance §origin. - Lifecycle. Always populated, defaulting from call context. Agent writes cannot default to or pass through
canonical— agent-authored content always lands ascandidate(ordraftwhere applicable), and only an authored act promotes it. See Provenance §lifecycle. - Derivation links. Attached when the write produces content inferred from other workspace content. See Derivation Links.
- Deviation records. Produced whenever the write conflicts with existing canonical content. See Deviation Records.
- Retroactive-revision queue updates. Emitted when the write revises content that other content was derived from. See Retroactive Revision.
These requirements are not optional or contextual. A write missing any one of them is not expressible. The boundary does not offer a “fast path” for simple edits or a “privileged path” for imports — every write is subject to the same machinery.
How the boundary is enforced
Section titled “How the boundary is enforced”Enforcement lives in two places that work together: the domain holds the invariant, and the adapter constructs the write that satisfies it.
Domain invariant
Section titled “Domain invariant”The domain exposes a single construct — the world write — that represents any modification to the workspace’s world. Workspace-modifying operations are not expressible in the domain except by constructing a world write. The world write cannot be constructed without origin, lifecycle, and the other required fields populated, and the construction itself validates them.
This is the architectural enforcement point. Tools that want to modify the workspace must produce a world write; the world write refuses to be constructed malformed; therefore no write reaches storage without the full machinery. There is no back door. No bypass. Read-only operations do not produce world writes; mixed read-write operations either split into separate tools or declare their write portion as boundary-crossing.
The domain layer owns this construct and its validation rules. Per the Clean Architecture + DDD stance committed in the world-model decisions, the domain depends on nothing outside itself — not on storage, not on the runtime, not on the MCP bridge. The invariant is stated in domain terms and persists across any infrastructure change.
Adapter mechanism
Section titled “Adapter mechanism”Tool implementations are not expected to construct world writes by hand or re-implement provenance machinery. The tool-adapter layer (the tool-registration surface on the Rust MCP server, plus its Python-native counterpart for sidecar-local tools) does that work.
When a tool is registered, the registration declares its relationship to the submit boundary:
- Whether the tool crosses the boundary at all.
- Which of its arguments is the content being written (the payload that flows into the world write).
- How derivation sources are supplied — explicit argument (the common agent-inference case), inferred from the agent’s reasoning trace, or not applicable (most editing tools, import tools).
- What kind of write it performs — creation, modification, promotion, retirement.
When the agent invokes a boundary-crossing tool, the adapter uses the registration metadata to construct the world write on the tool’s behalf:
- Origin from the caller’s identity (agent-produced for agent-invoked, authored for user-invoked, imported for import pipelines, observed for event-recording callers).
- Lifecycle from the call context (candidate for agent writes, canonical-allowed only for authored writes, draft for imports per ADR-018).
- Derivation from the declared sources mechanism.
- Deviation from examination of the target against existing canonical content.
- Retroactive revision from examination of the target against the derivation graph’s inbound edges.
The tool implementation receives an already-validated world write and executes it against storage.
This division holds:
- Tool authors declare boundary-crossing shape once, at registration. They do not re-implement provenance per tool.
- The adapter cannot accidentally bypass the boundary because the only way to hand a write through to storage is through the domain’s world write, which the domain validates.
- New tools — Rust, Python sidecar, later-added tools of any provenance — participate in the boundary by registering correctly.
See ADR-017 for the architectural rationale.
Who goes through the boundary
Section titled “Who goes through the boundary”Every workspace-modifying actor. No exceptions.
| Caller | Origin populated as | Typical lifecycle |
|---|---|---|
| User (direct editing surfaces) | authored | draft or canonical per user action |
| User (through the agent, dictating content) | agent-produced (per ADR-018) | candidate |
| World Agent (conversational turn) | agent-produced | candidate |
| World Agent (scheduled autonomous task) | agent-produced | candidate |
| Import pipeline | imported | draft (imports land as draft) |
| Event/observation recorder | observed | not applicable (observed content is not part of authored lifecycle) |
The same construct, the same invariants, for all of them. The agent cannot launder user-dictated content as authored (see ADR-018); imports cannot sneak in as canonical; scheduled tasks have no privilege beyond conversational runs.
Agent writes default to candidate, always
Section titled “Agent writes default to candidate, always”The lifecycle defaulting rule is explicit: agent-produced writes never land directly as canonical. They land as candidate (or draft, where applicable), and only an authored act can promote them.
This is both a domain invariant — the world write construction refuses origin: agent-produced, lifecycle: canonical as a constructed combination — and a consequence of the adapter’s call-context rule: the adapter cannot populate lifecycle: canonical for a write whose caller identity is the agent. The two mechanisms back each other up.
The author dictating content “verbatim” to the agent is not an exception. The agent still writes; the origin is still agent-produced; the lifecycle is still candidate. The author can promote it to canonical in the same session immediately after, but that promotion is a separate, authored act with its own world write crossing the boundary. See ADR-018.
Submit denials are not deviations
Section titled “Submit denials are not deviations”Writes can be rejected for reasons unrelated to world-model disagreement:
- The agent lacks the permission-system capability required to perform the write (see ADR-008 (capability-based permission model)).
- The target entity does not exist, is soft-deleted, or is otherwise malformed.
- The write itself is malformed — missing required content, violating domain rules unrelated to the boundary.
None of these produce a deviation record. Deviation records capture disagreement between content and content, not the agent being told “you can’t do that.” The submit-boundary adapter rejects the write with a typed error; the agent surfaces the error through its ordinary error-handling path; no entry is made in the deviation record store.
What the boundary is not
Section titled “What the boundary is not”- Not a review surface. The boundary enforces invariants and records provenance; it does not ask anyone for permission to proceed. Author review of candidate content happens after the write lands, on the author’s own time.
- Not a conflict detector for agent correctness. Deviation records name content-vs-content disagreements. An agent that produced a wrong inference because it failed to retrieve a relevant page is not a deviation; it is an agent problem, caught by other observability surfaces.
- Not a transaction coordinator for side-effects. The adapter composes the world write, validates, and executes against storage. External side-effects (emails, cloud syncs, etc.) are orchestrated by the caller, not by the submit-boundary adapter itself.
- Not a single Rust tool. The boundary is a concept realized by domain+adapter machinery. Many tools cross it; “submit” names the crossing, not the tool.
Worked example
Section titled “Worked example”Every write in the worked example flows through this boundary:
- Moment 1 — Import. The import pipeline constructs world writes with
origin: imported, lifecycle: draftfor each page it creates. The adapter populates origin from the import pipeline’s caller identity and lifecycle from call context. - Moment 2 — Agent derivation. The agent’s page-creation tool crosses the boundary. The adapter populates
origin: agent-produced, lifecycle: candidate, attaches 35 derivation links from the declared sources argument, examines the target for conflicts (none here), and produces no deviation record. The domain refuses any attempt to construct the write with missing fields. - Moment 3 — Source edit. The author’s edit is an authored world write; retroactive-revision queue entries are emitted as a side effect of the boundary transit.
- Moment 4 — Scheduled task + author resolution. The scheduled task’s detection emits a deviation record directly to the record store (not through a world write). The author’s resolving edit does cross the boundary as an ordinary authored write. The two outputs — the resolution edit and the record’s status update — are persisted as separate operations.
What this page does not do
Section titled “What this page does not do”- Does not describe the individual boundary-crossing tools. See the tool catalog.
- Does not describe the tool-adapter layer’s internals. See Systems › Agent › Tool Adapter (Wave 4 placeholder — existing content stands until then).
- Does not describe the storage tables that hold world writes post-execution. See Database Schema.
- Does not describe the retroactive-revision or deviation-record mechanics in detail. See their respective pages.
Was this page helpful?
Thanks for your feedback!