Repository navigation
feat: render a milestone status on the task root - #43
Merged
Merged
Conversation
added 5 commits
October 8, 2026 16:04
A root that only shows the label of the last kind cannot say what the task last reported, so the delegation contract gives every root a status that later milestones render. Migration 0009 adds the nullable column, and roots stored before it read NULL.
The route pins the shape section 9 asks for before it exists: a status-only milestone edits the owned root and answers that root's ts, a replay answers from its receipt, a status is stored and rendered by later milestones, an unowned root keeps its text, a 301-character status is refused and a failed root edit is retryable. The storage test pins the column the same way.
A milestone that carries only a status now edits the owned root and answers that root's ts, so a wave's root reads as a live board while its replies stay for what needs the owner. The status is stored with the root and every later milestone renders it; an owned root is edited only when its rendered text differs, and an unowned one is never edited. A failed edit of a root-only milestone answers 500 and deletes the receipt, because that edit is the milestone and the sender's retry must run; a milestone with a reply still posts it and logs the failure as before.
P1 of the A3 review: a milestone with a status and text whose chat.update Slack refused still got its reply, but the status was never stored, so every later milestone rendered the root without it. Contract section 9 stores the latest status on the root; storing it with the old root text keeps the rendered text different, so the next milestone retries the edit with it.
…root-status # Conflicts: # packages/core/src/progress.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Row A3 of wave bloop-delegation-3:
POST /progressimplements contract section 9, the root status. Root-only milestones post no reply, an owned root renders and stores the latest status, and a receipt answers the root's ts on the first call and on every replay.Commits, in dependency order
c95d493migration:0009_progress_root_status.sqladds the nullablestatuscolumn, with the schema tests.5d9b807test: the route and storage tests, which fail on the base tree.497590dfeat: the route stores and renders the status, and the README lists the field.Verify
{ok, ts: <root ts>}with no reply posted:progress root status > edits the owned root for a root-only milestone and answers that root without a reply(the fake Slack answers the root171.1and a reply171.2, so the answer is the root's ts, and only the root post and thechat.updateare recorded).progress root status > answers the replay of a root-only milestone from its receipt without a Slack call(the retry recorder records no call).status_too_long:progress root status > refuses a status longer than 300 characters after redaction without clamping it(301 refused, 300 accepted, and a 400+ char raw status that redacts to[secret]accepted, so the bound is the redacted one).progress root status > stores the status of a root-only milestone on a thread it does not own and leaves it alone(nochat.update, the row keepsroot_text, the receipt carries555.000).progress root status > answers 500 when Slack refuses the root edit a root-only milestone is, and lets the retry through(the receipt is dropped and the same id runs the update again).progress root status > renders the stored status on a later milestone that sends none(the root readsRelease 42 · Blocked · 2 of 5 landed).D1 migration schema > applies every migration file in wrangler's order,> applies one statement batch per migration fileand> leaves the status of the roots stored before it null.bun run verifygreen: format:check, lint, typecheck, 380 tests across 17 files, knip, deploy:dry and audit (0 vulnerabilities).The new tests fail on the base: with
packages/core/src/progress.tsrestored fromf28de36, the two suites report8 fail / 77 pass, the sevenprogress root statustests plusslack progress root storage > keeps the latest status of a root and leaves a root stored without one without a status.Not covered
bloop-notify's--statusflag and its root-only client (row D8).