Skip to content

chore(backlog): ten limitations settled where they bite, and the second backlog that made that impossible - #520

Merged
cevheri merged 1 commit into
mainfrom
chore/settle-documented-limits
Aug 28, 2026
Merged

chore(backlog): ten limitations settled where they bite, and the second backlog that made that impossible#520
cevheri merged 1 commit into
mainfrom
chore/settle-documented-limits

Conversation

@cevheri

@cevheri cevheri commented Aug 28, 2026

Copy link
Copy Markdown
Member

Eleven entries leave docs/BACKLOG.md89 → 78. One is work that landed; ten are limitations
that are now stated where a reader meets them instead of queued where nobody would pick them up.

T4 asked that no id cited in src/ be missing from the file and that the drift guard cover source
citations. #519 did exactly that the day before, and the entry stayed behind — the same failure that
round was about, one level up.

The structural finding

docs/AGENT.md has a section called "Known limitations", and every M2 entry appeared in it as a
bullet labelled with its backlog id. tests/unit/agent-documentation.test.ts enforces that in both
directions: every entry in the milestone's section must be cited by that document, and every id the
document cites must exist as an entry.

So the deferral list was a second backlog, chained to the first. Settling a limitation by
deleting its entry would have forced deleting the bullet that documented it — the file could not
shrink without destroying the knowledge that justified the shrinking. That is a mechanism, not an
attitude, and it is a large part of why the count did not move.

The fix separates the two roles:

An entry is a claim that something should CHANGE. A limitation is a claim about how the
product behaves, and its home is the place a reader meets it.

docs/BACKLOG.md's "How this file is used" now says so, and the seven agent limits moved into a
subsection of "Known limitations" that carries no backlog id and therefore needs no entry to exist.
Each was rewritten to stand alone: the thin one-line bullets for the scope allowlist and the token
budget gained the mechanism from their entries rather than losing it.

Where the ten now live

Seven in docs/AGENT.md under "Settled as limits rather than as work" — the scope allowlist denying
tools that cannot declare a dimension, the unenforced token budget, results released at run end, seed
eligibility decided against the browser's snapshot, a data-analysis run with no honest route to "this
database cannot answer that", an unfenced statement with no terminator, and the re-pointed decline
that has never been reached from the UI.

Three had no agent bullet and went to the code, beside the behaviour:

file what it gained
src/lib/agent/tools.ts that nothing builds a constrained scope today — runtime.ts calls createTargetScope(connectionId) with no dimensions (verified) — so this is a property of the layer rather than a live defect, plus the two honest resolutions
src/lib/audit.ts the residual the coercion leaves: a nested secret under an arbitrary key name is not URI-shaped, so it survives truncated inside the stringified value. Said plainly, because no by-key-name scrutiny exists for any field today — closing it is a new capability, not a gap left open
src/lib/db/factory.ts what the forbidden reverse direction COSTS: an agent run reaching an unbrowsed single-writer connection caches the handle under the profiled key, and the editor is refused until it is evicted — 30 minutes idle, IDLE_TIMEOUT_MS (verified)

Two I was wrong about

The first reading said all ten were "documented limits, safe to delete". Grepping for the substance
found nothing in the code for B39 and B79, which would have made deleting them a straight loss.
They turned out to be documented — in the AGENT.md bullet the invariant would have deleted along with
the entry, which is the finding above arriving from the other side. Neither is deleted; both are
relocated.

A bug in the deletion itself

The first attempt split the file on entry boundaries and dropped the matching chunks. A section
heading lives at the tail of the preceding entry's chunk, so deleting the only entry of a section
silently deleted the next section's heading: ## Tests and ## Dependencies vanished and five P
entries ended up under "Authentication and security headers" — with the index regenerated from the
damaged bodies, so the file was self-consistently wrong and every structural assertion passed.

Caught by diffing the heading list against origin/main, not by a test. Redone line-based, deleting
only an entry's own lines. #518 was checked for the same damage and is clean: 16 headings before and
after, identical — the bug was latent there because no entry it deleted was the last of its section.

Verification

format · lint (0 errors, 132 pre-existing warnings) · typecheck · knip · build ·
build:lib · coverage 45408/45408 (100.00%) · and the three that matter here — the structural
guard, the agent-documentation two-way guard, and the citation guard #519 added, which is what proves
no pointer was left dangling by the eleven deletions.

Six bare references to deleted ids were settled by hand in tools.test.ts, AGENT_DEMO.md and
AGENT_ANALYST_DESIGN.md. The bare form is the one that guard deliberately cannot check, so nothing
would have caught them. The id-parsing example in backlog-structure.test.ts moved from AU4, whose
section no longer exists, to REL3 — the same greedy-prefix point against a live entry.

No rendered string changed, so no browser check is claimed.

…nd backlog that made that impossible

Eleven entries leave `docs/BACKLOG.md` (89 -> 78). One is work that landed: T4 asked that no id cited
in `src/` be missing from the file and that the drift guard cover source citations, which is exactly
what #519 did the day before, and the entry stayed behind. The other ten were never going to be
worked, and this settles them the honest way rather than by deleting them.

## The structural finding

`docs/AGENT.md` has a section called "Known limitations". Every M2 entry appeared in it as a bullet
labelled with its backlog id, and `tests/unit/agent-documentation.test.ts` enforces that in both
directions: every entry in the milestone's section must be cited by that document, and every id the
document cites must exist as an entry.

So the deferral list WAS a second backlog, chained to the first. Settling a limitation by deleting
its entry would have forced deleting the bullet that documented it - the file could not shrink
without losing the knowledge that justified the shrinking. That is a mechanism, not an attitude, and
it is a large part of why the count did not move for weeks.

The fix separates the two roles. A limitation's home is the place a reader meets it; an entry is a
claim that something should CHANGE. `docs/BACKLOG.md`'s "How this file is used" now says so, and the
seven agent limits moved into a subsection of "Known limitations" that carries no backlog id and
therefore needs no entry to exist. Each was rewritten to stand on its own, with the substance the
entry held folded in - the thin one-line bullets for the scope allowlist and the token budget gained
the mechanism from their entries rather than losing it.

## Where each of the ten now lives

Seven in `docs/AGENT.md` under "Settled as limits rather than as work": the scope allowlist denying
tools that cannot declare a dimension, the unenforced token budget, results released at run end,
seed eligibility decided against the browser's snapshot, a data-analysis run with no honest route to
"this database cannot answer that", an unfenced statement with no terminator, and the re-pointed
decline that has never been reached from the UI.

Three had no agent bullet and went to the code, beside the behaviour:

- `src/lib/agent/tools.ts` gains what the scope entry knew and the comment did not: that nothing
  builds a constrained scope today (`runtime.ts` calls `createTargetScope(connectionId)` with no
  dimensions - verified), so this is a property of the layer rather than a live defect, and the two
  honest resolutions when a caller first needs scoping.
- `src/lib/audit.ts` gains the residual the coercion leaves: a nested secret under an arbitrary key
  name is not URI-shaped, so it survives truncated inside the stringified value. Said plainly,
  because it reads like a gap left open when it is not: no by-key-name scrutiny exists for ANY field
  today, top-level or nested - closing it would be a new capability.
- `src/lib/db/factory.ts` gains what the forbidden reverse direction COSTS: an agent run reaching an
  unbrowsed single-writer connection caches the handle under the profiled key, and the editor is then
  refused until that entry is evicted - 30 minutes idle, `IDLE_TIMEOUT_MS`, verified.

## Two I was wrong about, and how the measurement caught it

The first reading said all ten were "documented limits, safe to delete". Grepping for the substance
found nothing in the code for B39 and B79, which would have made deleting them a straight loss. They
turned out to be documented - in the AGENT.md bullet the invariant would have deleted along with the
entry, which is the finding above arriving from the other side. Neither is deleted; both are
relocated.

## A bug in the deletion itself

The first attempt split the file on entry boundaries and dropped the matching chunks. A section
heading lives at the TAIL of the preceding entry's chunk, so deleting the only entry of a section
silently deleted the NEXT section's heading too: `## Tests` and `## Dependencies` vanished and five
`P` entries ended up under "Authentication and security headers", with the index regenerated to match
- self-consistently wrong, and every structural assertion would have passed. Caught by diffing the
heading list against `origin/main` rather than by a test.

Redone line-based, deleting only an entry's own lines. #518 was checked for the same damage and is
clean: 16 headings before and after, identical. The bug was latent there because no entry it deleted
was the last of its section.

## Verification

`format` - `lint` (0 errors, 132 pre-existing warnings) - `typecheck` - `knip` - `build` -
`build:lib` - **coverage 45408/45408 (100.00%)** - and, the ones that matter here, the structural
guard, the agent-documentation two-way guard, and the citation guard #519 added, which is what
proves no pointer was left dangling by the eleven deletions.

Six bare references to deleted ids were settled by hand in `tools.test.ts`, `AGENT_DEMO.md` and
`AGENT_ANALYST_DESIGN.md`. The bare form is the one that guard deliberately cannot check, so nothing
would have caught them; leaving a reference to an entry deleted in the same PR is the sloppiness this
round is about. The id-parsing example in `backlog-structure.test.ts` moved from `AU4`, whose section
no longer exists, to `REL3`, which makes the same greedy-prefix point against a live entry.
@sonarqubecloud

Copy link
Copy Markdown

@cevheri
cevheri merged commit 74e6e24 into main Aug 28, 2026
19 checks passed
@cevheri
cevheri deleted the chore/settle-documented-limits branch August 28, 2026 14:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant