177b5596b5
Co-authored-by: nova28 <17953305+nova28@users.noreply.github.com> Co-authored-by: Carlos Florencio <carlosmflorencio@gmail.com>
133 lines
7.6 KiB
Markdown
133 lines
7.6 KiB
Markdown
---
|
|
status: draft
|
|
system: tasks
|
|
requirements:
|
|
- REQ-TASKS-PLAN-APPEND-006
|
|
created: 2026-09-05
|
|
owners:
|
|
- kandev
|
|
---
|
|
|
|
# Task plan append-mode agent text System Design
|
|
|
|
## Purpose and boundaries
|
|
|
|
This design owns `REQ-TASKS-PLAN-APPEND-006`: every agent-facing string that describes a
|
|
plan write, the class rule that binds them, the truncation warning's rewrite, and the
|
|
acknowledgement. It defines no composition, locking or size-limit behavior — those stay in
|
|
[the main design](plan-write-append-mode.md), which this file was split out of on
|
|
2026-09-05 when that file reached its 32,768-byte lint ceiling. No content was dropped in
|
|
the move.
|
|
|
|
Split here rather than compressed away because the alternative was deleting Build guidance
|
|
that closed earlier review findings, which would have reopened them. The companion-file
|
|
pattern follows `external-id-idempotency-operations.md` in this same directory.
|
|
|
|
## Requirement mapping
|
|
|
|
| Requirement | Design section |
|
|
| --- | --- |
|
|
| `REQ-TASKS-PLAN-APPEND-006` | [Agent-facing description and acknowledgement](#agent-facing-description-and-acknowledgement) |
|
|
|
|
## Agent-facing description and acknowledgement
|
|
|
|
`REQ-TASKS-PLAN-APPEND-006` covers the tool registration in
|
|
`internal/mcp/server/server.go` and the existing runtime warning and acknowledgement
|
|
paths. The description an agent reads is the place where the choice between modes is
|
|
explained, so it is contract, not commentary.
|
|
|
|
**`AC-TASKS-PLAN-APPEND-006.9` binds a CLASS of strings, not a list.** No agent-facing
|
|
text describing a plan write may claim that no append mode exists or prescribe
|
|
read-then-resend. Two review rounds enumerated these texts and each list came up one
|
|
short, so the criterion is stated over the class: Build sweeps `origin/main` for the
|
|
claim and fixes what it finds, rather than trusting any enumeration including this one.
|
|
On 2026-09-05 the sweep matched five strings, all of which change: the
|
|
`update_task_plan_kandev` description (`server.go:1846`) and its `content` parameter
|
|
(`:1848`); `create_task_plan_kandev`'s `content` parameter (`:1832`) **and its own tool
|
|
description** (`:1830`); and both branches of the truncation warning. Site `:1830` is the
|
|
one both earlier enumerations missed — it says the tool replaces everything "same as
|
|
update_task_plan_kandev through a different door" and tells the caller to read the plan
|
|
first, so the equivalence turns false the moment `update` gains `append` and the second
|
|
clause is exactly the prescription `006.9` removes. Treat that list as of its date.
|
|
|
|
The `update_task_plan_kandev` description asserts there is no partial update, append or
|
|
section-patch mode, and that sending only a new section "will silently delete everything
|
|
else"; left alone it argues against the mode being added. Its `content` parameter also
|
|
carries the 256 KiB cap sentence from `plan-content-size-limit`, which stays and applies
|
|
to the composed document once `append` exists (`REQ-TASKS-PLAN-APPEND-007`). Rewritten,
|
|
the description must name both modes and the default (`AC-TASKS-PLAN-APPEND-006.1`),
|
|
keep the deletion warning **scoped to `replace`** rather than dropping it (`006.2`), and
|
|
state that `append` inserts a blank line before the fragment (`006.3`), is not
|
|
idempotent so a resubmission adds it again (`006.4`), and does not require reading the
|
|
plan first (`006.5`). The `mode` parameter's own description carries the two accepted
|
|
values and the default. The deletion warning must survive because replace is still the
|
|
destructive path; softening it to make room for append would trade one silent data loss
|
|
for another.
|
|
|
|
Both `create_task_plan_kandev` strings deny the mode exists and prescribe the
|
|
read-then-resend pattern this capability removes, on the same tool
|
|
`AC-TASKS-PLAN-APPEND-005.2` makes *reject* a mode by naming
|
|
`update_task_plan_kandev`'s append. `AC-TASKS-PLAN-APPEND-006.9` fixes the replacement.
|
|
The boundary Build must hold: the `mode` property, if declared, states only that its
|
|
value is rejected, per
|
|
[the two sibling surfaces](plan-write-append-mode.md#the-two-sibling-surfaces-which-behave-differently-on-purpose),
|
|
which explains why this tool's schema declares it at all — the platform's generic
|
|
argument-schema validator would otherwise shadow `createTaskPlanHandler`'s own,
|
|
correctly-worded rejection with a generic error naming neither tool.
|
|
|
|
### The truncation warning is the most urgent of them
|
|
|
|
`planTruncationWarning` in `internal/mcp/handlers/task_plan_guard.go` renders both of
|
|
its branches around this sentence:
|
|
|
|
> Plan writes REPLACE THE ENTIRE DOCUMENT — there is no partial update or append mode.
|
|
|
|
Shipping append while leaving that in place denies the mode at the one moment an agent
|
|
has just destroyed content and would most benefit from being told it exists, and steers
|
|
it back toward the replace path that caused the loss. `AC-TASKS-PLAN-APPEND-006.7` and
|
|
`006.8` require that sentence replaced by one naming `append` as the way to add a
|
|
section without resubmitting the document.
|
|
|
|
Everything else in that warning must survive, for reasons recorded in its doc comment
|
|
rather than obvious: it deliberately does not tell the caller to "recover" the content
|
|
through an MCP tool, because no plan tool reads a past revision and
|
|
`get_task_plan_kandev` would hand back the truncated document; it names where the prior
|
|
content lives; and it tells the caller not to rewrite from memory. Naming `append`
|
|
strengthens that advice rather than competing with it — the caller is told what to do
|
|
instead of what just failed. Keep the rune counts, the percentage, the two branches on
|
|
whether the prior revision number is known, and the response field.
|
|
|
|
This is Go string content, not localized UI copy, so the i18n rules do not reach it.
|
|
`AC-TASKS-PLAN-APPEND-005.1` excludes this wording from the replace-mode freeze
|
|
precisely so the two criteria do not contradict each other.
|
|
|
|
### Acknowledgement
|
|
|
|
The acknowledgement needs **no change**, verified rather than assumed. `planWriteAck`
|
|
in `internal/mcp/server/handlers.go` already prefers the stored `content` length over
|
|
what the call sent, renders it as bytes, and already appends a line stating that plan
|
|
content is omitted and should be read back with `get_task_plan_kandev`. That is exactly
|
|
`AC-TASKS-PLAN-APPEND-006.6`, satisfied by existing behavior on both modes.
|
|
|
|
Build must not add plan content to that acknowledgement. Doing so would return the
|
|
accumulated document on every append and give back the response-leg saving this
|
|
capability exists to obtain — the ack omits content deliberately, because echoing the
|
|
stored plan to the agent that just wrote it was measured as the largest single
|
|
contributor to context growth in plan-heavy sessions.
|
|
|
|
## Test strategy
|
|
|
|
**Description tests** assert the class rule by ITERATION, not by naming strings: walk
|
|
every registered plan-tool description and parameter description plus both rendered
|
|
warning branches, and assert none carries the no-append claim or the read-then-resend
|
|
prescription (`AC-TASKS-PLAN-APPEND-006.9`). A per-string test would have passed against
|
|
a spec that missed one, which is what happened twice. This must not exempt
|
|
`update_task_plan_kandev`'s own strings from the walk — the tool whose description most
|
|
recently carried the banned claim is exactly the one a special-cased test would stop
|
|
checking. Also assert the warning names `append` while still stating where the prior
|
|
content lives and that the caller must not rewrite from memory (`006.7`, `006.8`), and
|
|
that `create_task_plan_kandev`'s texts point at `update_task_plan_kandev`, and that its
|
|
`mode` property (whether or not the schema declares one) states only that the value is
|
|
rejected, never a functioning capability. Assert on substantive clauses, not whole
|
|
strings, so they do not become punctuation change-detectors.
|