Files
kandev/docs/specs/tasks/requirements/plan-write-append-mode.md
T
2026-09-06 15:10:10 +01:00

20 KiB

status, system, created, owners
status system created owners
draft tasks 2026-09-01
kandev

Task plan append-mode write Requirements

Overview

update_task_plan_kandev replaces the whole plan document. There is no partial write at any layer, so a caller adding a section must read the whole plan and send it back with the addition attached. One write therefore costs the size of the entire plan, and a run costs the square of the number of writes in it.

The plan is also a task's only durable memory across a context reset, so it grows monotonically for as long as the task runs. On this instance the largest stored revision is 158,393 characters, so the two effects compound in production, not in theory.

This capability adds a second write mode in which the caller submits only the fragment it wants to add and the system composes the stored document. It changes what a caller must send and what the system must guarantee about composing it, not what a plan is, how revisions are numbered, or how the browser edits one.

The tasks system owns this capability because the durable artifact is the plan and its revision history, not the MCP surface exposing the write. The missing-task boundary stays owned by REQ-TASKS-DOCUMENTS-001.

Write serialization and truncation reporting belong to plan-write-consistency; the stored-content size limit to plan-content-size-limit, both in this canon. This capability composes inside the per-task write lock the first established, and REQ-TASKS-PLAN-APPEND-007 measures an append against the second. REQ-TASKS-PLAN-APPEND-003 still states in full what append requires of serialization, so this contract stays readable and testable on its own.

Prior art

Recorded in full, with both search receipts, in the system design under Prior art.

Terminology

  • Plan write: an operation that upserts the task plan HEAD row and writes or merges a revision.
  • HEAD: the single task_plans row for a task, holding the current content.
  • Mode: the requested composition behavior of an agent plan update, either replace or append.
  • Fragment: the content a caller submits in append mode; an addition to the stored document, not the whole of it.
  • Composed content: the content a plan write commits in append mode, formed from the stored content and the fragment.
  • Stored content: the plan content in effect for that task at the instant the composing write reads it inside the serialized write path.
  • Agent write path: the MCP tools create_task_plan_kandev and update_task_plan_kandev.
  • Browser write path: the WebSocket actions handled by wsCreateTaskPlan and wsUpdateTaskPlan.
  • Truncation guard: the existing check reporting a write that retains less than half the characters of the content it replaces.
  • Whitespace: a character whose Unicode White_Space property is true. This set is normative wherever this document says "whitespace"; it includes U+0085 NEL and U+00A0 no-break space, so a hand-rolled " \t\r\n" test does not satisfy this contract.
  • Whitespace-only line: a line whose characters are all whitespace, excluding the line terminator.
  • Size limit: the maximum stored plan content a single write may commit, owned by plan-content-size-limit and unchanged here.

Requirements

REQ-TASKS-PLAN-APPEND-001: A caller selects the write mode explicitly and an

unrecognized mode changes nothing

Intent: The default must stay what every existing caller relies on, and an unrecognized value must not be interpreted: treating it as replace would let one typo overwrite a plan with a fragment, the destructive outcome this capability exists to remove.

Acceptance criteria

  • AC-TASKS-PLAN-APPEND-001.1: When an agent plan update omits the mode or supplies an empty mode, the system shall treat the write as replace.
  • AC-TASKS-PLAN-APPEND-001.2: When an agent plan update supplies the mode replace or append, the system shall perform that mode.
  • AC-TASKS-PLAN-APPEND-001.3: When an agent plan update supplies any other mode value, including a value differing only in letter case such as Append or APPEND, the system shall reject the request as a validation error, name the two accepted values in the error, leave the stored plan content, title and revision history unchanged, and create no revision.
  • AC-TASKS-PLAN-APPEND-001.4: When an agent plan update supplies no content, or supplies content that is empty, the system shall reject the request as a validation error in either mode and create no revision.
  • AC-TASKS-PLAN-APPEND-001.5: When an agent plan update in append mode supplies a fragment consisting only of whitespace as this document defines it, the system shall reject the request as a validation error and create no revision, because such a fragment can only add separator noise to a document from which it cannot be removed.
  • AC-TASKS-PLAN-APPEND-001.6: When an agent plan update in append mode targets a task that has no plan, the system shall reject the request with the same plan-not-found outcome that replace produces for that task, and shall not create a plan.
  • AC-TASKS-PLAN-APPEND-001.7: When one request violates more than one criterion, the system shall report exactly one failure, selected in this order: mode validity (AC-TASKS-PLAN-APPEND-001.3); task-reach authorization (AC-TASKS-PLAN-APPEND-005.6); content validity (AC-TASKS-PLAN-APPEND-001.4, AC-TASKS-PLAN-APPEND-001.5); plan existence (AC-TASKS-PLAN-APPEND-001.6); failure to read the stored content (AC-TASKS-PLAN-APPEND-003.5); the size limit (AC-TASKS-PLAN-APPEND-007.2). In every case the stored plan content, title and revision history are unchanged and no revision is created. Missing-task is not in this order; it stays owned by REQ-TASKS-DOCUMENTS-001.

REQ-TASKS-PLAN-APPEND-002: An append composes the stored document with a separator

that cannot join two lines

Intent: Downstream consumers count headings. A fragment beginning with a heading appended onto the last line of the stored content yields a line that is no longer a heading, so any consumer counting ## headings silently reads one fewer. Stated over headings generally, not one consumer's heading text, so the rule outlives any counter built on it. The separator is contract, not implementation.

Acceptance criteria

  • AC-TASKS-PLAN-APPEND-002.1: When a plan write in append mode commits, the composed content shall consist of the stored content, then a separator, then the fragment, in that order. The only characters the system may add are the separator itself; the only ones it may remove are the edge whitespace that AC-TASKS-PLAN-APPEND-002.2, AC-TASKS-PLAN-APPEND-002.3 and AC-TASKS-PLAN-APPEND-002.5 each require it to remove. Beyond those it shall perform no insertion, reordering or removal, and shall not examine or alter any interior character of either body. This criterion frames its siblings rather than contradicting them.
  • AC-TASKS-PLAN-APPEND-002.2: When both the stored content and the fragment contain a non-whitespace character, the composed content shall contain exactly one empty line between the last non-empty line of the stored content and the first non-empty line of the fragment, regardless of how many line endings the stored content ends with or the fragment begins with. Leading spaces and tabs on the fragment's first non-empty line shall be preserved.
  • AC-TASKS-PLAN-APPEND-002.3: When the stored content is empty or contains only whitespace, the composed content shall be the fragment with its leading empty and whitespace-only lines removed, shall preserve leading spaces and tabs on the fragment's first non-empty line, and shall not begin with a blank line.
  • AC-TASKS-PLAN-APPEND-002.4: When a plan write in append mode commits, the composed content shall preserve the fragment's trailing characters as submitted, and the system shall neither add nor remove a trailing line ending.
  • AC-TASKS-PLAN-APPEND-002.5: When a plan write in append mode commits, the composed content shall preserve every character of the stored content that precedes its trailing whitespace. Trailing whitespace on the stored content's final line may be dropped.
  • AC-TASKS-PLAN-APPEND-002.6: When a plan write in append mode supplies a title, the system shall apply it exactly as replace does; when it supplies none, the system shall leave the stored title unchanged.

REQ-TASKS-PLAN-APPEND-003: An append reads and commits against the same state, and

never commits a fragment alone

Intent: An append is a read-modify-write. If the read runs outside the serialization that orders plan writes, two concurrent appends read the same stored content and the second commit overwrites the first, losing a section while both callers are told the write succeeded. The replace-only API prevented that by construction; it must not return one layer down, invisible.

Acceptance criteria

  • AC-TASKS-PLAN-APPEND-003.1: When a plan write in append mode commits, the stored content it composed from shall be the plan content in effect for that task at the instant that same write commits, not content read before another write to the same task committed.
  • AC-TASKS-PLAN-APPEND-003.2: When two plan writes in append mode for the same task run concurrently and both report success, the resulting plan content shall contain both fragments in full.
  • AC-TASKS-PLAN-APPEND-003.3: When plan writes for the same task run concurrently, the resulting plan content shall equal the result of performing those writes one after another in some order. The system shall not guarantee which order, and shall not guarantee that the order matches the order in which the callers submitted them.
  • AC-TASKS-PLAN-APPEND-003.4: When a plan write in append mode runs concurrently with one in replace mode for the same task, the system shall apply AC-TASKS-PLAN-APPEND-003.3 to that pair. A replace committing between an append's read and that append's commit would otherwise be discarded entirely, leaving content matching no serial order. Serializing appends against each other alone does not satisfy this criterion.
  • AC-TASKS-PLAN-APPEND-003.5: When the stored content for an append cannot be read, the system shall fail the write, create no revision, leave the stored plan unchanged rather than committing the fragment as the whole document, and report the failure distinguishably from AC-TASKS-PLAN-APPEND-001.6's plan-not-found outcome, exposing no storage detail.
  • AC-TASKS-PLAN-APPEND-003.6: When the same append request is submitted more than once, the system shall append the fragment once per accepted request. An append is not idempotent and repeated fragments shall not be deduplicated.

REQ-TASKS-PLAN-APPEND-004: The truncation guard does not judge an append

Intent: The guard catches a replace that dropped content. An append cannot drop content, since the composition contains the stored content in full, so running the guard there yields only a false warning and a needless revision split, teaching an agent to distrust an otherwise reliable warning.

Acceptance criteria

  • AC-TASKS-PLAN-APPEND-004.1: When a plan write in append mode commits, the system shall emit no truncation warning, whatever the ratio between the fragment's length and the stored content's length.
  • AC-TASKS-PLAN-APPEND-004.2: When a plan write in append mode commits, the system shall not force a new revision on the truncation guard's account, and shall leave the write eligible for the existing coalescing rules.
  • AC-TASKS-PLAN-APPEND-004.3: When a plan write in append mode commits, the response shall carry no truncation warning field and no prior revision number field, matching a non-truncating write's shape today.

REQ-TASKS-PLAN-APPEND-005: Replace-mode behavior and every other plan surface are

unchanged

Intent: This capability adds a mode. A regression in the default would cost more than the change saves, and surfaces never asked to change must not drift.

Acceptance criteria

  • AC-TASKS-PLAN-APPEND-005.1: When a plan write runs in replace mode, the stored content, stored title, revision numbering, revision coalescing, truncation detection, forced-revision behavior, emitted events and response shape shall be identical to those produced before this capability existed. The wording of the truncation warning is excluded from this freeze and owned by REQ-TASKS-PLAN-APPEND-006; its trigger condition, the counts it reports and the response field carrying it are frozen here.
  • AC-TASKS-PLAN-APPEND-005.2: When a caller supplies a non-empty mode to create_task_plan_kandev, the system shall reject the request as a validation error naming update_task_plan_kandev as the tool that offers append, store nothing, and leave stored content, title and revision history unchanged. It shall not ignore the value, which would commit the fragment as the entire plan. An absent or empty mode is treated as absent, leaving that tool's behavior unchanged, consistent with AC-TASKS-PLAN-APPEND-001.1.
  • AC-TASKS-PLAN-APPEND-005.3: The browser write path shall have no mode field in its payload contract and shall ignore an unrecognized field rather than reject it — that path's existing behavior for any unknown field, and therefore what "unchanged" means for it. It never sends a mode, so it takes the replace default. The asymmetry with AC-TASKS-PLAN-APPEND-005.2 is deliberate.
  • AC-TASKS-PLAN-APPEND-005.4: When a plan write in append mode commits, the system shall emit the same events, in the same order, that a replace write committing the same resulting content emits.
  • AC-TASKS-PLAN-APPEND-005.5: When a plan write in append mode commits, it shall create or coalesce exactly one revision as a replace write does, and the stored revision content shall be the composed content, not the fragment.
  • AC-TASKS-PLAN-APPEND-005.6: When a plan write in append mode runs, the system shall apply the same task-reach authorization replace applies, and shall not read the stored content of a task the caller cannot reach.

REQ-TASKS-PLAN-APPEND-006: Every agent-facing text describing plan writes admits

that append exists

Intent: A caller decides between the two modes from the text the system shows it. Several texts today assert there is no append mode, spread across both plan tools' descriptions and content parameters and the truncation warning shown after a write destroyed content. Left alone they argue against the mode; the warning does so at the worst moment, steering a caller who just lost content away from the remedy, and the create tool while prescribing the read-then-resend pattern this capability removes. Softened too far, they drop the warning that keeps the replace path safe. Enumerating these texts has twice missed one, so AC-TASKS-PLAN-APPEND-006.9 binds the class instead of a list.

Acceptance criteria

  • AC-TASKS-PLAN-APPEND-006.1: The update_task_plan_kandev description shall name both modes, state which is the default, and state that replace submits the whole document while append submits only an addition.
  • AC-TASKS-PLAN-APPEND-006.2: The update_task_plan_kandev description shall retain, scoped to replace, the warning that the write overwrites the entire document and that sending only a section deletes the rest.
  • AC-TASKS-PLAN-APPEND-006.3: The update_task_plan_kandev description shall state that append places a blank line between the stored content and the fragment.
  • AC-TASKS-PLAN-APPEND-006.4: The update_task_plan_kandev description shall state that an append is not idempotent and that resubmitting it adds the fragment again.
  • AC-TASKS-PLAN-APPEND-006.5: The update_task_plan_kandev description shall state that append does not require the caller to read the plan first.
  • AC-TASKS-PLAN-APPEND-006.6: When a plan write in append mode succeeds, the acknowledgement returned to the caller shall report the size of the stored document after the write rather than the size of the submitted fragment.
  • AC-TASKS-PLAN-APPEND-006.7: The truncation warning shall not state or imply that no partial update or append mode exists.
  • AC-TASKS-PLAN-APPEND-006.8: The truncation warning shall name append as the way to add a section without resubmitting the whole document, while continuing to state where the pre-write content lives, that the MCP plan tools cannot fetch it, and that the caller must not rewrite the plan from memory.
  • AC-TASKS-PLAN-APPEND-006.9: No agent-facing text describing a plan write shall state or imply that no partial update or append mode exists, or direct a caller who wants to add a section to read the plan and resubmit it. This binds every tool and parameter description on the agent write path, not only those above. On create_task_plan_kandev each shall still state that this tool replaces the whole plan and name update_task_plan_kandev in append mode as the way to add a section, and its schema MAY declare a mode parameter that only rejects, keeping AC-TASKS-PLAN-APPEND-005.2's message reaching the caller.

REQ-TASKS-PLAN-APPEND-007: An append is measured against the document it will store

Intent: The size limit measures what the caller submitted. In append the caller submits a fragment but the system stores the composition, so measuring the submission would let a small fragment commit an oversized document, defeating an existing limit.

Acceptance criteria

  • AC-TASKS-PLAN-APPEND-007.1: When a plan write in append mode is admitted, the system shall evaluate the size limit against the composed content, not against the submitted fragment.
  • AC-TASKS-PLAN-APPEND-007.2: When the composed content would exceed the size limit, the system shall reject the write, store nothing, create no revision, and leave the stored plan content and title unchanged. Composed content whose size is exactly the limit shall be accepted, matching the existing check's boundary.
  • AC-TASKS-PLAN-APPEND-007.3: When the system rejects an append for exceeding the size limit, the size it reports shall be that of the composed content, so a caller is not told a fragment far below the limit exceeded it.
  • AC-TASKS-PLAN-APPEND-007.4: When the system evaluates the size limit for an append, it shall do so against the same stored content that write composed from, inside the region that serializes plan writes for the task, so the value admitted is the value committed.
  • AC-TASKS-PLAN-APPEND-007.5: When a plan write runs in replace mode, the size limit's value, the point at which it is evaluated and the error it produces shall be unchanged.

Out of scope

  • The plan size limit itself. Its value and error are owned by plan-content-size-limit. REQ-TASKS-PLAN-APPEND-007 fixes only which content an append is measured against; nothing here raises, lowers or removes the ceiling, nor bounds growth below it.
  • Revision compaction and server-side collapse. An append creates or coalesces a revision as any other write does; none is merged, pruned or rewritten.
  • Automatic collapse of spent detail. Collapsing stays a deliberate read-then-replace by the caller: per concepts/agents-md-pattern.md, automating the full rewrite is what erodes detail, so only accumulation becomes cheap.
  • A section-patch or replace-a-named-heading mode. Only whole-document replace and end-of-document append are defined.
  • An idempotency key for appends. AC-TASKS-PLAN-APPEND-003.6 states the non-idempotence rather than removing it; deduplication needs a caller-supplied key and a store for it — a separate contract.
  • A mode on create_task_plan_kandev or on the browser write path. Fixed by AC-TASKS-PLAN-APPEND-005.2 and AC-TASKS-PLAN-APPEND-005.3.
  • Reading a past revision through MCP. Unchanged: no plan tool returns one.
  • Prepend, or insertion at any position other than the end.