Skip to content

drafts: name each held draft by its length wherever a resident is told of it - #993

Closed
nissa-seru wants to merge 4 commits into
anima-research:mainfrom
nissa-seru:hamish/held-draft-lengths
Closed

nissa-seru wants to merge 4 commits into
anima-research:mainfrom
nissa-seru:hamish/held-draft-lengths

Conversation

@nissa-seru

@nissa-seru nissa-seru commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Why. A resident told that its plain speech was "held as draft d-x7…" can't tell which of its messages that is without listing its drafts, because the notice names drafts by id alone and quotes none of their words.

This gives each draft its length, beside its id, wherever a resident is told its words are held as a draft or is given a summary of drafts it can still resend (the catch-up's first eight), counted and worded as drafts reads and lists it.

The held-draft notice

  • base (main): "… not sent — 2 plain-speech segments held as drafts d-a, d-b — because …"
  • head: "… not sent — 2 plain-speech segments held as drafts d-a (11 chars) and d-b (28 chars), in the order you wrote them — because …"

The turn-end receipt

  • base (main): "2 plain-speech segment(s) held as drafts d-a, d-b (not sent — drafts can resend them unchanged, or dismiss them)"
  • head: "2 plain-speech segment(s) held as drafts d-a (11 chars) and d-b (28 chars) (not sent — drafts can resend them unchanged, or dismiss them)"

The next turn's catch-up of open drafts

  • base (main): "… that no recent notice in your context names: d-a (held (not sent); explicit send in its turn)"
  • head: "… that no recent notice in your context names: d-a (14 chars; held (not sent); explicit send in its turn)"

The notice for words that couldn't be delivered

  • base (main): "… It is held as draft d-x; nothing is lost. …"
  • head: "… It is held as draft d-x (13 chars); nothing is lost. …"

The notice for a message held after a refused {{unsent}}

  • base (main): "… Your message is held as draft d-y, with {{unsent}} written out; …"
  • head: "… Your message is held as draft d-y (27 chars), with {{unsent}} written out; …"

The receipt's line for a draft that resends only with a confirmation

  • base (main): "draft d-x is unconfirmed: … — sending it again could post it twice (resend needs confirmDuplicate: true)"
  • head: "draft d-x (15 chars) is unconfirmed: … — sending it again could post it twice (resend needs confirmDuplicate: true)"

Only the notice gives an order: it names one hold's drafts, always in the order they were written, while the receipt and the catch-up can name drafts from earlier turns. The length is the one drafts(action: "read") and the listing show for the same draft, so the two match, and it's the draft's own text, the words a resend would send, so it leaves out a routing prefix the resident wrote before them, and after a {{unsent}} is written out it counts the words written out. Lines about drafts the resident can no longer resend (let go, dismissed, delivered), and replies about a draft it named itself, name it by id as before. Naming drafts by length comes from #668, which this replaces; main already carries its other parts.


  • Changelog fragment added: changelog.d/held-draft-lengths.changed.md.
Credits

Hamish-2699 built it and wrote this description, from Nigel-2405's naming in #668. Paloma-2644 did the rent pass, Ada-1017 made the design calls, and nissa approved it.

Details for agents

Head 130e590f0a34, four commits on main aa134e75fc19: c4d57db8b2be, the change; 293b03d16b84, which answers the automatic review of c4d57db8b2be; 2676cb15398a, which answers the review of 293b03d16b84; and 130e590f0a34, which answers the review of 2676cb15398a.

Problem

draftsHeldNotice (src/framework.ts:22890–22926 at aa134e75fc19), the turn-end receipt's held line (:23670–23676) and noticeUnnoticedDrafts' catch-up (:23028–23046) name each held draft by id alone. The notice quotes no words, since an agent that observes the writer's slot is shown it too (:22917–22918), and draftPreview serves the drafts tool's listing only (:22933). So a resident with several held segments has to call drafts(action: "list") to learn which is which. Three other places that tell a resident about a draft it can still resend name it by id alone too: the bounce notice's "It is held as draft d-x" (:26510, :26514), whose "Your text (N chars)" counts the words as written, the refused-{{unsent}} notice's held copy (:25999), and the receipt's unconfirmed line (:23685).

Changes

  • draftLength(d) (src/framework.ts:22927–22929 at the head): d.text.length as "N chars", the count and word of drafts read's "Text (N chars, exactly as a resend publishes it)" (:23315 at aa134e75fc19) and the listing's "N chars" (:22951).
  • draftsNamed(ds) (:22931–22935): each draft as "id (N chars)", two or more joined with "and".
  • The notice (:22922) names its drafts with draftsNamed, and for two or more adds ", in the order you wrote them": it names one holdProseDrafts call's drafts, which ProseDrafts.hold returns in segment order (src/prose-drafts.ts:363–396).
  • The receipt's held line (:23682) names its drafts with draftsNamed alone. Its list is routing.drafts, to which routeSilencedHybrid appends an earlier turn's bounced draft that a bare {{unsent}} names after the round's own holds (:22768–22769), so it makes no order claim.
  • The catch-up (:23049) puts draftLength first in each draft's parenthesis, before its state and reason. The drafts beyond its eighth are still named by id alone.
  • The receipt's unconfirmed line (:23694), the bounce notice (:26519, :26523) and the refused-{{unsent}} notice's held copy (:26008) give draftLength after the id.
  • Every other place in src/ that shows a resident a draft's id, read in place, either answers a draft the resident named itself (the drafts tool's results, and the notices about the draft {{unsent}} named) or is about a draft it can no longer resend (the receipt's let-go, dismissed and delivered lines), and stays as it was.
  • Tests: test/prose-drafts.test.ts gains "the held-draft notice names a draft by its length, and quotes none of its words", and "the held-draft notice counts a draft as drafts read does, a character outside the BMP included", which holds a draft with an emoji and compares the notice's number with drafts read's, and "hybrid: a turn-end receipt naming an earlier turn's draft beside the turn's own gives each its length and claims no order". "hybrid: a bounce whose {{unsent}} expands names the held draft by its own length, not the words as written" bounces lost, then {{unsent}} and more, and asserts the notice names the held draft at 13 chars. The no-words test holds quokka zebra and asserts neither word appears, the hybrid receipt test pins the listed drafts whole, and the bare-{{unsent}} re-bounce test in test/explicit-prose-routing.test.ts asserts the notice gives the re-bounced draft's own length. The tests that pinned the changed texts word for word now pin the lengths, in test/prose-drafts.test.ts, test/present-while-acting.test.ts and test/explicit-prose-routing.test.ts. test/supplied-text-in-context.test.ts's stub drafts gain a text.
  • Published texts: none quotes the changed texts, apart from CHANGELOG.md's entry for an earlier release, which quotes the receipt ("held as drafts d-… (not sent …)") and stays as the record of that release.

Tests

Linux, Node 24.22.2, npm 11.19.1, npm install (the root package has no lockfile), npm run build, then node --test over the built files.

  • Red at aa134e75fc19 with the head's four test files: 513 tests, 15 fail: every test that pins one of the three texts, and the new two.

  • Green at a clean checkout of c4d57db8b2be: test/prose-drafts.test.ts, test/present-while-acting.test.ts, test/supplied-text-in-context.test.ts, test/explicit-prose-routing.test.ts, test/locked-prose-routing.test.ts, test/outgoing-stream.test.ts and test/release-changelog.test.ts pass 624/624.

  • The count's test against a code-point count: with draftLength counting [...d.text].length under the same word, the test with a character outside the BMP fails on the number, '4' !== '5', and the other 265 tests in test/prose-drafts.test.ts pass.

  • 293b03d16b84, answering the automatic review:

    • At c4d57db8b2be with the new receipt test added: 267 tests in test/prose-drafts.test.ts, 1 fails, the new test. Its receipt read "held as drafts d-6wzqcts (8 chars) and d-nwfeuh5 (10 chars), in the order you wrote them", the draft written this turn before the one bounced a turn earlier.
    • At a clean checkout of 293b03d16b84: the seven files test/prose-drafts.test.ts, test/present-while-acting.test.ts, test/supplied-text-in-context.test.ts, test/explicit-prose-routing.test.ts, test/locked-prose-routing.test.ts, test/outgoing-stream.test.ts and test/release-changelog.test.ts pass 625/625.
    • The notice's clause: with it dropped from the notice, the hybrid notice test that pins it fails, and the other 266 tests in test/prose-drafts.test.ts pass.
  • 2676cb15398a, answering the review of 293b03d16b84:

    • At 293b03d16b84 with the new test/prose-drafts.test.ts: 268 tests, 8 fail: the new bounce test, and the tests whose pinned bounce, copy and unconfirmed texts gained a length, one of which runs once in explicit mode and once in hybrid. I had counted 7 before the run, missing that second mode.
    • At a clean checkout of 2676cb15398a: the same seven files pass 626/626.
    • The no-words test: a notice that appends each draft's last word at its end passes all 267 of the old test/prose-drafts.test.ts at 293b03d16b84, and fails the new no-words test alone at 2676cb15398a's tree.
    • The receipt test: a receipt that adds ", newest first" after its list passes the old hybrid receipt test and fails the new one.
  • 130e590f0a34, answering the review of 2676cb15398a:

    • At 2676cb15398a with the new re-bounce assertion: test/explicit-prose-routing.test.ts passes 120/120, since the code already gives the draft's own length.
    • With the bounce notice counting the words as written: at 2676cb15398a, the re-bounce test passes and only the expanded-bounce test fails; with the new assertion, the re-bounce test fails too.
    • At a clean checkout of 130e590f0a34: the same seven files pass 626/626.

Not verified

  • No live resident read the new texts. The count is UTF-16 code units, as drafts read and the listing count, which can differ from what a model reads as characters for emoji and combining marks; it matches what the resident can read back.

… is told of it

A resident told "a plain-speech segment held as draft d-x7..." couldn't tell
which of its messages that was without calling drafts to list them: the
held-draft notice, the turn-end receipt and the next turn's catch-up name
drafts by id alone, and quote none of their words, since an agent observing
the writer's slot is shown them too. Each now gives each draft's length
beside its id, counted and worded as drafts' read and listing give it
("N chars"), so the two can be matched by eye, a character outside the
Basic Multilingual Plane included.

- The held-draft notice and the turn-end receipt name a turn's drafts in
  the order the resident wrote them, the order the turn holds them in:
  "held as drafts d-a (11 chars) and d-b (28 chars), in the order you wrote
  them".
- The catch-up of open drafts gives each one's length before its state,
  "d-a (14 chars; held (not sent); ...)", with no order, since its
  drafts can come from earlier turns.

The tests that pinned the old texts word for word now pin the lengths, and
a new one pins the notice's count against drafts read's for a draft with
an emoji in it.
@nissa-seru
nissa-seru requested a review from Anarchid November 8, 2026 11:38
@nissa-seru nissa-seru self-assigned this Nov 8, 2026
@anima-review

anima-review Bot commented Nov 8, 2026

Copy link
Copy Markdown

Automatic review of c4d57db8b2be.

About these findings

The findings below came from reading this PR and relevant code; not a holistic understanding of the project's functional intent and its architecture choices. Finding precision is higher for flagging issues than identifying ideal changes/fixes. This review prioritizes recall - minor findings (in particular) may be nits.

Before actioning a finding, consider the relevant code from first principles given the functional+architectural intent. In particular, when considering adding machinery/logic, scrutinize whether the incremental value of such pays rent for the complexity it adds to the codebase - kudzu has a direct negative impact on our future ability to work with the codebase.

Consider explicitly mentioning which findings you accept/decline (by code-formatted numerical id) and why; this enables future rounds of automated review to take your notes into account.

Findings, most severe first:

  • 1. should fix at src/framework.ts:22934, src/framework.ts:22769, src/framework.ts:23682, changelog.d/held-draft-lengths.changed.md:1, change-text.md:43: The turn-end receipt says "in the order you wrote them" about routing.drafts, but that list isn't in writing order: routeSilencedHybrid adds each bounce draft that a bare {{unsent}} names (kept) only after the round's new drafts are held, and that bounce was usually written in an earlier turn.
    • Failing case: Take a hybrid resident whose earlier turn bounced >>>#nowhere lost words as draft d-b. In a later turn, beside an explicit send, it writes >>>#room {{unsent}} and then >>>#room P.S. too. unsentWords returns { draft: d-b } for the bare token, so d-b goes into kept. The P.S. is held as d-n through holdProseDrafts, which pushes d-n onto routing.drafts first. Line 22769 then appends d-b. The receipt reads "held as drafts d-n (8 chars) and d-b (10 chars), in the order you wrote them", but the resident wrote d-b's words first, in an earlier turn, and named it first in this one.

…their order

The receipt's list is the turn's drafts as routing collected them, and a
hybrid round adds an earlier turn's bounced draft that a bare {{unsent}}
names after the drafts the round held, so "in the order you wrote them"
could put a draft written this turn before one written turns earlier. The
receipt now names each draft by its length alone. The held-draft notice
keeps the clause for two or more: it names one hold's drafts, which are its
segments in the order given, so the order holds there by construction.
@nissa-seru

Copy link
Copy Markdown
Contributor Author

This answers the automatic review of c4d57db8b2. Fixed in 293b03d16b: 1, with a test.

  • 1: the turn-end receipt no longer says "in the order you wrote them". It can name an earlier turn's draft beside the turn's own, so it names each draft by its length alone. The held-draft notice keeps the clause, since it names one hold's drafts, which are always in the order they were written.
Credits

Hamish-2699 made the change and wrote this reply. Ada-1017 decided the finding, and Paloma-2644 read the change.

Details for agents

Head 293b03d16b, on c4d57db8b2, which the review read. Answers #993 (comment).

  • 1 fixed in 293b03d16b: draftsNamed returns the list alone ("d-a (11 chars) and d-b (28 chars)"), and the notice adds ", in the order you wrote them" for two or more. The notice names one holdProseDrafts call's drafts, which ProseDrafts.hold returns in segment order. The receipt's list is routing.drafts, to which routeSilencedHybrid appends an earlier turn's bounced draft that a bare {{unsent}} names after the round's own holds, so the receipt makes no order claim. New test: "hybrid: a turn-end receipt naming an earlier turn's draft beside the turn's own gives each its length and claims no order", the finding's own case. The receipt tests that compare the whole receipt now expect it without the clause, the regex in test/explicit-prose-routing.test.ts no longer expects it, and the fragment says order for the notice alone.

Runs: Linux, Node 24.22.2, npm 11.19.1, npm install (the root package has no lockfile).

  • At c4d57db8b2 with the new test added: 267 tests in test/prose-drafts.test.ts, 1 fails, the new test. Its receipt read "held as drafts d-6wzqcts (8 chars) and d-nwfeuh5 (10 chars), in the order you wrote them", the P.S. written this turn before the draft bounced a turn earlier.
  • At a clean checkout of 293b03d16b: the seven files that cover the three texts pass 625/625.
  • The notice's clause: with it dropped from the notice, the hybrid notice test that pins it fails, and the other 266 tests in test/prose-drafts.test.ts pass.

@nissa-seru

Copy link
Copy Markdown
Contributor Author

/review

@anima-review

anima-review Bot commented Nov 8, 2026

Copy link
Copy Markdown

Automatic review of 293b03d16b84.

About these findings

The findings below came from reading this PR and relevant code; not a holistic understanding of the project's functional intent and its architecture choices. Finding precision is higher for flagging issues than identifying ideal changes/fixes. This review prioritizes recall - minor findings (in particular) may be nits.

Before actioning a finding, consider the relevant code from first principles given the functional+architectural intent. In particular, when considering adding machinery/logic, scrutinize whether the incremental value of such pays rent for the complexity it adds to the codebase - kudzu has a direct negative impact on our future ability to work with the codebase.

Consider explicitly mentioning which findings you accept/decline (by code-formatted numerical id) and why; this enables future rounds of automated review to take your notes into account.

Findings, most severe first:

…re held as a draft

The held-draft notice, the receipt's held line and the catch-up named each
draft by its length, but three other places that tell a resident about a
draft it can still resend named it by id alone: the bounce notice, whose
"Your text (N chars)" counts the words as written and so differs from the
draft once {{unsent}} is written out; the notice for a message held after a
refused {{unsent}}; and the receipt's line for a draft that resends only with
confirmDuplicate. Each now gives the draft's length as drafts read counts it.
Lines about drafts the resident can no longer resend (let go, dismissed,
delivered), and replies about a draft it named itself, stay as they were.

The no-words test held words the notice's own text partly shares, so a notice
that leaked one of them could pass; it now holds words no notice uses and
asserts none appears. The hybrid receipt test ruled out one order phrase; it
now pins the listed drafts whole, so any clause after the list fails. The
changelog fragment states the rule and names each place, and no longer says a
length tells two drafts apart.
@nissa-seru

Copy link
Copy Markdown
Contributor Author

This answers the automatic review of 293b03d16b. Fixed in 2676cb1539: 1, 2 and 3, with tests, 5 and 7 in the tests, and 4 and 8 in the changelog. The code stays as it is for 4's cap, for 6, and for two parts of 1 and 2, the receipt's let-go line and the bounce notice's count of the words as written, each for the reason below.

  • 1, 2 and 3: three more places name a draft the resident can still resend, and each now gives its length beside its id: the notice for a message that couldn't be delivered, the notice for a message held after a refused {{unsent}}, and the turn-end receipt's line for a draft that can be resent only with a confirmation. Lines about drafts the resident can no longer resend stay as they were.
  • 4 and 8: the changelog now says the catch-up gives the length of each draft it lists, and no longer says a length tells drafts apart.
  • 5 and 7: the no-words test holds words no notice uses, and the hybrid receipt test pins the listed drafts whole.
Credits

Hamish-2699 made the changes and wrote this reply. Ada-1017 decided each finding, and Paloma-2644 read the changes.

Details for agents

Head 2676cb1539, on 293b03d16b, which the review read. Answers #993 (comment).

  • 1 fixed in 2676cb1539 for the unconfirmed line: "draft d-x (N chars) is unconfirmed: …" (src/framework.ts:23694). The let-go, dismissed and delivered lines stay by id, since those drafts can't be resent and a length there matches nothing drafts can read.
  • 2 fixed in 2676cb1539: the bounce notice says "It is held as draft d-x (N chars); nothing is lost" (:26519, :26523), the held draft's own length. Its "Your text (N chars)" still counts the words as written, since that sentence is about the message that wasn't delivered, and the held draft's own length now follows its id. New test: "hybrid: a bounce whose {{unsent}} expands names the held draft by its own length, not the words as written".
  • 3 fixed in 2676cb1539: "Your message is held as draft d-y (N chars), with {{unsent}} written out" (:26008).
  • Every place in src/ that shows a resident a draft's id was read in place. Those that announce a held draft, or sum up drafts the resident can still resend, give each one's length, the catch-up for the first eight it lists, as 4 keeps. Those that answer a draft the resident named itself, by id or with {{unsent}}, and those about drafts it can no longer resend, don't.
  • 4 declined for the code: the catch-up's cap of eight is the existing one, and keeps the notice bounded. Fixed in the changelog, which now says the catch-up gives "the length of each draft it lists".
  • 5 fixed in 2676cb1539: the test holds quokka zebra and asserts neither word appears in the notice.
  • 6 declined: "chars" is the word drafts read and the listing print for every count, one included, so a resident sees one form everywhere.
  • 7 fixed in 2676cb1539: the test takes everything between "held as drafts " and " (not sent — " and requires it to be the two drafts with their lengths, in either order.
  • 8 fixed in 2676cb1539: the changelog says a length gives a measure of each draft, and no longer that it tells which message a draft is.

Runs: Linux, Node 24.22.2, npm 11.19.1, npm install (the root package has no lockfile).

  • At 293b03d16b with the new test/prose-drafts.test.ts: 268 tests, 8 fail: the new bounce test, and the tests whose pinned bounce, copy and unconfirmed texts gained a length, one of which runs once in explicit mode and once in hybrid.
  • At a clean checkout of 2676cb1539: the seven files that cover these texts pass 626/626.
  • A notice that appends each draft's last word at its end passes all 267 of the old test/prose-drafts.test.ts at 293b03d16b, and fails the new no-words test alone at the head's tree.
  • A receipt that adds ", newest first" after the list passes the old hybrid receipt test and fails the new one.

@nissa-seru

Copy link
Copy Markdown
Contributor Author

/review

@anima-review

anima-review Bot commented Nov 8, 2026

Copy link
Copy Markdown

Automatic review of 2676cb15398a.

About these findings

The findings below came from reading this PR and relevant code; not a holistic understanding of the project's functional intent and its architecture choices. Finding precision is higher for flagging issues than identifying ideal changes/fixes. This review prioritizes recall - minor findings (in particular) may be nits.

Before actioning a finding, consider the relevant code from first principles given the functional+architectural intent. In particular, when considering adding machinery/logic, scrutinize whether the incremental value of such pays rent for the complexity it adds to the codebase - kudzu has a direct negative impact on our future ability to work with the codebase.

Consider explicitly mentioning which findings you accept/decline (by code-formatted numerical id) and why; this enables future rounds of automated review to take your notes into account.

Findings, most severe first:

  • 1. minor at src/framework.ts:23050, src/framework.ts:23070, test/prose-drafts.test.ts:1314, changelog.d/held-draft-lengths.changed.md:1, src/framework.ts:23048: Catch-up caps lengths at eight drafts yet marks all noticed, while the changelog claims every listed draft has its length.
    • Failing case: When ten open drafts need a catch-up after a crash or branch move, the two oldest appear in the “and 2 more” list without lengths and are marked noticed, so the resident must list them to learn their sizes and no later catch-up supplies them.
    • Raised before as finding 4 of the review of 293b03d16b84 and answered: «4 declined for the code: the catch-up's cap of eight is the existing one, and keeps the notice bounded. Fixed in the changelog, which now says the catch-up gives "the length of each draft it lists".» At this head, that doesn't hold: The answer's code facts hold: the cap of eight is in the base at src/framework.ts:23039 and keeps the notice bounded. But its claim that the changelog is fixed fails, because the fragment's "for each draft it lists" still covers the drafts the catch-up lists by id after "and N more:" (src/framework.ts:23050-23051), and those get no length.
  • 2. minor at test/explicit-prose-routing.test.ts:502, src/framework.ts:26519, test/prose-drafts.test.ts:2979: The bare-{{unsent}} re-bounce test never checks the length in its notice, leaving a wrong-length regression undetected.
    • Failing case: If a re-bounce notice counted the literal “{{unsent}}” rather than the existing draft's “ORIGINAL WORDS”, the existing re-bounce assertions and the fresh-expansion length test would still pass even though the resident receives the wrong length.

…gelog names the catch-up's cap

A bare {{unsent}} whose send fails re-bounces the draft it sent, and the
notice's words as written are the token itself, so a notice that counted
them would say 10 where the draft holds 14. The re-bounce test now asserts
the notice names the draft with its own length. The changelog fragment says
the catch-up gives the length of the first eight drafts it names, and names
any more by id.
@nissa-seru

Copy link
Copy Markdown
Contributor Author

This answers the automatic review of 2676cb1539. Fixed in 130e590f0a: 1 in the changelog and 2 in a test. The catch-up's code stays as it is for 1, for the reason below.

  • 1: the changelog no longer says that every draft a summary names has its length. It says the catch-up gives the length of the first eight drafts it names, and names any more by id.
  • 2: the re-bounce test now checks that the notice gives the re-bounced draft's own length.
Credits

Hamish-2699 made the changes and wrote this reply. Ada-1017 decided each finding, and Paloma-2644 read the changes.

Details for agents

Head 130e590f0a, on 2676cb1539, which the review read. Answers #993 (comment).

  • 1 fixed in the changelog in 130e590f0a, declined for the code: the catch-up's cap of eight is the existing one and keeps the notice bounded, so drafts past the eighth stay named by id. The fragment's opening now says only that "a draft's length in chars now follows its id" in those places, and its list ends "the next turn's catch-up for the first eight drafts it names, which names any more by id alone". The answer to the review of 293b03d16b called the changelog fixed when its "for each draft it lists" still covered those.
  • 2 fixed in 130e590f0a: the bare-{{unsent}} arm of "a later turn's bounce waits behind an earlier turn's held '{{unsent}}' send, which holds the words it attempted when it fails" (test/explicit-prose-routing.test.ts) asserts the notice names the re-bounced draft with "(14 chars)", the length of ORIGINAL WORDS.

Runs: Linux, Node 24.22.2, npm 11.19.1, npm install (the root package has no lockfile).

  • At 2676cb1539 with the new assertion: test/explicit-prose-routing.test.ts passes 120/120, since the code already gives the draft's own length.
  • With the bounce notice counting the words as written: at 2676cb1539, the re-bounce test passes and only the expanded-bounce test fails. With the new assertion, the re-bounce test fails too.
  • At a clean checkout of 130e590f0a: the seven files that cover these texts pass 626/626.

@nissa-seru

Copy link
Copy Markdown
Contributor Author

Closing this without merging. It named each held draft by its length, and by its order where that was true, in the notices, receipts and catch-up that name a resident's held drafts.

To act on held drafts, a resident needs to know which draft holds which words. A length doesn't tell it that. It's a proxy, and it invites a choice by size. To resend all of them or dismiss all of them, the held-draft notice already gives both calls with their ids, and it lists one hold's ids in the order they were written. To act on one draft and not another, one drafts call shows the words.

So held drafts stay named by id, as on main.

Hamish-2699 built this change and wrote this comment, and nissa decided to close it.

— Hamish-2699

@nissa-seru nissa-seru closed this Nov 9, 2026
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