The pipeline punished what it prescribed: after a failed merge it tells the
author to rebase and restore S7-code-review, and that attempt finished the
budget. On #225 (light track, limit 2) the sequence yellow, green, rebase
produced review-4 on a task whose code review was green and whose CI was
green, with no product change after the verdict — the owner had to
arbitrate work that was already accepted.
A cycle under section 4 is a verdict with blocking findings followed by a
return to the author, so only yellow and red verdicts spend the budget now.
A green verdict returned nothing and consumes nothing, which also removes
any need to mark rebase re-runs specially.
Attempts and cycles are now separate quantities. The attempt number keeps
naming the document, because two runs sharing a number would overwrite each
other's review artefact, while the limit compares blocking cycles only. The
exhaustion comment lists the verdicts it counted, and the guard no longer
strips review-4 — it reports the recount and leaves the decision with the
owner.
Rule 7 of the process gate follows: its document threshold rises above the
cycle limit, because legitimate attempts can exceed cycles and a threshold
equal to the limit would refuse the very rebase the pipeline demands.
Issue: #227
User-Visible: no
The assumptions section is explicitly labelled "technical, free to change",
and it held a requirement that AC3 and a mutant already test as a fact. Read
literally, it invited splitting the write in two — reopening the very window
in which markers move. The point now states the opposite: everything else in
that section is free, this one is normative and lives in section 8.3.
Issue: #220
User-Visible: no
M1: the spec now carries the touch classification TOUCH-SUPPORT.md asks every
editor feature for — "Touch editor: not exposed", with the reason it is a
decision rather than an omission.
M2: the first draft denied adding a config field in one section while planning
to store an anchor in settings in another. Resolved by dropping the anchor:
reordering materialises the placement that was implicit, giving those markers
an explicit space in the same write. No new field, no schema change, and the
marker stays exactly where the user saw it.
Issue: #220
User-Visible: no
The pipeline punished what it prescribed: after a failed merge it tells the
author to rebase and restore S7-code-review, and that attempt finished the
budget. On #225 (light track, limit 2) the sequence yellow, green, rebase
produced review-4 on a task whose code review was green and whose CI was
green, with no product change after the verdict — the owner had to
arbitrate work that was already accepted.
A cycle under section 4 is a verdict with blocking findings followed by a
return to the author, so only yellow and red verdicts spend the budget now.
A green verdict returned nothing and consumes nothing, which also removes
any need to mark rebase re-runs specially.
Attempts and cycles are now separate quantities. The attempt number keeps
naming the document, because two runs sharing a number would overwrite each
other's review artefact, while the limit compares blocking cycles only. The
exhaustion comment lists the verdicts it counted, and the guard no longer
strips review-4 — it reports the recount and leaves the decision with the
owner.
Rule 7 of the process gate follows: its document threshold rises above the
cycle limit, because legitimate attempts can exceed cycles and a threshold
equal to the limit would refuse the very rebase the pipeline demands.
Issue: #227
User-Visible: no
Written on the owner's product decisions of 2026-08-20: mouse only and only in
the editor modes, one warning about the positional `floor` from #210, no
keyboard alternative.
The spec carries the part that is easy to miss — the order of `config.spaces`
is not decoration. It feeds the marker placement fallback, the swipe
neighbour and the numeric `floor`, so reordering tabs must not move a single
marker. That is a named acceptance criterion with a mutant behind it.
Issue: #220
User-Visible: no
Import of a backup holding PDF attachments: the content resolver parses a url
as a url, and the three mutants guarding it are registered. The user-visible
change is documented in 4a84734, which carries both changelog entries — this
merge adds no behaviour of its own.
Code review r2 green (docs/reviews/CODE-REVIEW-225-r2.md). The third pass was
a rebase over #226, not a fix — owner arbitration on the review-4 the cycle
counter raised for it (PROCESS.md §4; counter defect filed as #227).
Issue: #225
User-Visible: no
Review CODE-REVIEW-225-r1.
M1: urlsplit(url).path was trusted even when the url carried a scheme or an
authority, so "https://evil.example/houseplan_files/files/m1/doc.pdf"
resolved onto a local file while _looks_internal kept calling it external —
the mirror image of the inconsistency this resolver exists to prevent. Only a
same-document reference is resolved by its path now.
M2: the three mutants the spec described are registered in
scripts/mutation-gate.mjs instead of living as a one-off manual run. The
traversal entry drops both structural checks at once on purpose: taken one at
a time the defence is layered (sanitize_marker_id turns ".." into "misc") and
the mutant would be equivalent — established by running it.
Issue: #225
User-Visible: no
A backup holding a PDF attachment could not be imported back: legacy links
carry a cache-buster (".../files/m1/doc.pdf?v=1783170649"), and the resolver
compared the raw tail with its sanitized form, so the query made the name
differ from itself. The reference then read as internal by prefix and
non-canonical by name, which is exactly the combination _content_state must
refuse — every such document failed with invalid_content.
Parse the url as a url: the path addresses the file, the query and the
fragment address the transfer. Path segments keep doing the guarding, so
dropping the query cannot widen what a segment is allowed to be.
Issue: #225
User-Visible: yes