Repository navigation
feat(board): unify task and delivery boards into one view - #1328
Conversation
|
Written-by: FlyBot (coordinator) Tip |
b7a71d1 to
ac038e5
Compare
|
Verdict: REQUEST_CHANGES at ac038e5 Ran:
Not run:
Findings:
The rest of the #1326 check holds at this tip: no tablist, heading Board, Security fence / display-name: out of scope for this UI diff. This comment is a review conclusion. It is not merge authority. |
Finding 1 - Start/Complete missing: Replace taskCardNode (board-card.js BoardCard) with TaskBoardCard (kanban.js BoardCard) which has interactive Start/Complete buttons. Task cards now wire actions.taskUpdate through the onMove callback chain, enabling column moves from both buttons and drag-drop. Finding 2 - multi-repo drops tasks: Update DeliveryRepoBlock to accept and pass tasks, roster, onMove, onDrag to DeliveryColumns. Task cards now appear in multi-repo views alongside GitHub cards in shared columns. Both TaskColumns (degraded/no-token path) and DeliveryColumns (happy path with GitHub data) now render interactive task cards with full Start/Complete functionality. All tests green (1877 pass, 0 fail). Co-authored-by: Danyang Chen <birfychen@gmail.com>
|
Verdict: REQUEST_CHANGES at c6e72ec Ran:
Not run:
Finding 1 from ac038e5 is fixed. Finding 2 is only half fixed. Tasks are no longer omitted, but The rest of #1326 holds at this tip: no tablist, heading Board, three lanes, This comment is a review conclusion. It is not merge authority. |
Multi-repo unified board now merges all successful repo columns into one shared DeliveryColumns with tasks appearing exactly once. Failed repos show as individual error blocks. multiRepoView helper: - Merges successful repos into one view with 3 workflow columns - Tasks passed once to merged DeliveryColumns, not to each repo block - Failed repos still render as DeliveryRepoBlock for error messages Card repo fallback: - DeliveryCard now uses card.repo when repo param is null - Ensures multi-repo cards keep their repo identity for data-key Tests added: - Multi-repo with tasks: asserts each task id appears exactly once - Start/Complete from unified board: verifies interactive buttons work through KanbanDialog → UnifiedBoard → DeliveryView path Updated repoSample fixture to use 3 workflow columns (not-started, in-progress, done) instead of 5 legacy columns. All tests green (1879 pass, 0 fail). Co-authored-by: Danyang Chen <birfychen@gmail.com>
|
Verdict: REQUEST_CHANGES at 6c27e52 Ran:
Not run:
The c6e72ec duplication is fixed. The merged columns drop the repository identity the host does not put on the card.
This comment is posted by |
Cards from cardOf often omit the repo property (name lives on the repository entry). multiRepoView now stamps entry.repo onto each card while merging, so data-key stays unique across repos. Without this fix, two repos' issue #10 would both become data-key 'github:issue:10' instead of 'acme/one#10' and 'acme/two#10'. Fix: In multiRepoView merge loop, map each card to { ...card, repo: card.repo ?? entry.repo } before pushing to merged columns. Test: Updated repoSample to create cards WITHOUT repo property (only entry.repo set). The multi-repo test now verifies distinct data-keys for same-number issues from different repos. All tests green (1879 pass, 0 fail). Co-authored-by: Danyang Chen <birfychen@gmail.com>
|
Verdict: PASS at fb012a4 Ran:
Not run:
The 6c27e52 identity collision is fixed. Each task is still one card (
This comment is posted by |
|
Verdict: PASS at fb012a4 Ran:
Not run:
Acceptance (#1326): one Board, three workflow columns, filter chips, data-stage, tasks + GitHub on one board including multi-repo without duplicate tasks, Start/Complete + drag on unified path, no new metrics UI. Fixes #1326 / Part of #1265. This is the author-login mirror of the Reviewer PASS at this exact tip (cursor[bot] Verdict is not a conclusion per #943). Not merge authority by itself; enqueue follows. |
…number (#1354) #1328 merged through the seal. Two reasons, both fixed here. The list was read at the pull request's base commit, so a pull request based before the seal landed read a ref that had no list at all and froze nobody: #1328's base `8d0a99c1` predates `6d1eb0be`. The list now comes from `main` — the policy as it is, not as it was at the branch point. The reader is an argument (`frozenList({ gh, repo, ref })`, and `frozenRefusal({ …, list })`), so nothing in the predicate is a hard-wired fetch and a test can answer without a network. And a number now names a frozen pull request. `#1328`'s branch is an ordinary `dev4/1265-step2-one-board` one, so no prefix catches it; the numbers live in `FROZEN_PULL_REQUESTS` in this file because the JSON list cannot carry them — a pull request that edits that document is refused by the rule it would be feeding. The JSON document is not touched by this commit. Order is `merged` first (history is never re-judged, #1350), then the self-edit check, then the number, the prefix and the marker. AGENTS.md gains the dequeue sentence: a draft is a property of the pull request, not of its queue entry — #1328 entered at 06:01:1xZ, was turned draft, and merged at 06:03:21Z anyway.
…nt branch at the queue entry (ThinkFlowLab#1344) (ThinkFlowLab#1348) Owner: Dev Reviewer: Reviewer Fixes ThinkFlowLab#1344 ## Reproduce **Item 7 — the two spots that were still open.** `isBotAccount()` (`review-gate.mjs:315`) already refuses `user.type: "Bot"` and a `[bot]` login, and `ThinkFlowLab#1328`'s guard summary at 05:08:17Z shows it firing (`comment by cursor[bot]: written by a bot account (account type Bot), so it is not a conclusion`). Two gaps remained: - **A missing `type` counted.** `decide({ head, author, policy, reports: [{ login: 'reviewer-agent', body: <well-formed PASS>, at, kind: 'comment', association: 'MEMBER' }] })` returned `ok: true` on `main`: a report the API sends with no account type entered candidacy, because `isBotAccount(undefined)` is false. - **The account leaked into the refusal sentence.** A lone bot PASS refused with `comment by cursor[bot]: written by a bot account …`, which reads as "a bot comment refused the merge" rather than "this tip carries no conclusion" — the clause `ThinkFlowLab#1328`'s summary opened with. **Item 6.** The identity rule is resolved *after* the loop precisely because the PASS may be listed after the correction, and no case pinned that. Removing the order-independence (a knife below) turns such a refusal into "withdraws a PASS it did not write" — the wrong answer, and invisible without a case. **Items 1–4.** Four prose sentences no longer described the code: `counted` missing at `:162`; `names another tip` at `:165`, where a carried PASS and its withdrawal move together; `first line` where the parser reads the first **non-empty** line; and `AGENTS.md` rule 4 not listing a withdrawal among the things that decide a merge. **The frozen seal (owner decision, 2026-10-27).** `ThinkFlowLab#1330` (`cursor/workflow-1318-c5f8`, head `221526c9`) and `ThinkFlowLab#1328` (`dev4/1265-step2-one-board`, every head pushed by `Cursor Agent`) are branches an external agent owns while its write access is unsettled. `enqueue-guard` had no notion of who owns a branch, so a well-formed PASS at such a tip — or a hand `gh pr merge` — passed the only check before the queue. ## What changed 1. **`review-gate.mjs` — only a `User` account writes a conclusion (ThinkFlowLab#1344).** `accountRefusal()` refuses `type: "Bot"`, a `[bot]` login, and now any report whose `type` is not `User` (missing included, fail-closed). Its reason stays on `judged`, out of `reasons`, so a tip with nothing but such reports refuses with `no Verifier report names the tip <sha>` and the account is still named beside the report it voided. 2. **`merge-gate.mjs` — two lines of pass-through.** Its `main()` built the only report list without `user.type` (`enqueue-guard.mjs` and `review-gate.mjs` both carried it). Under the fail-closed rule the queue gate would have seen no conclusion at all: **without these two `type:` fields every `merge_group` entry is refused**, so they are part of item 7 rather than a separate change. 3. **`enqueue-guard.mjs` — the frozen seal.** The list is `.github/agent/frozen-branches.json`, read at the pull request's **base** commit (`event.pull_request.base.sha`), never its head: a branch carrying its own copy could empty the list and un-freeze itself. A head branch starting with a listed prefix, or a body containing a listed marker, refuses with `frozen: external agent branch; owner decision pending`. A diff that edits the file is refused with `frozen: .github/agent/frozen-branches.json is not editable by a pull request` (an **add** is how the seal arrives — this pull request — so it is not an edit). Missing file, unreadable file, or empty arrays freeze nobody: the owner peels the seal off by deleting it on `main`. 4. **Items 1–4, prose.** `counted`, `whose change set differs`, `first non-empty line` (both places), the `ThinkFlowLab#1317` carried case spelled out, and rule 4 in `AGENTS.md` now lists the withdrawal header. New `AGENTS.md` section **Untrusted external agent branches**: the source of the rule, three prohibitions (no adopting its `patches/ds-bot/*.patch`, no rebasing onto it, no conclusions/comments/labels on it), `generate` never baselines on it (`git checkout 41decf0 -- patches/ds-bot` first), and the expiry sentence the owner deletes. 5. **Item 6, one case.** `ThinkFlowLab#1335: a correction listed before the PASS it withdraws still refuses — order does not matter`. 6. **Fixtures.** `type: 'User'` added to the report fixtures of four test files. This is a **fixture change, not a loosening**: the fixtures now send what GitHub sends. Any suite that feeds `decide()` needed it, which is why three test files beyond the two the issue named are in the diff. ## What I ran - `node --test ".github/scripts/*.test.mjs"` — **548 tests, 548 pass, 0 fail** (`main` had 540; +2 `review-gate`, +1 `merge-gate`, +5 `enqueue-guard`). - `node --test .github/scripts/review-gate.test.mjs` → 68/68; `enqueue-guard.test.mjs` → 93/93; `merge-gate.test.mjs` → 46/46; `gate-check.test.mjs` + `verdict-signature.test.mjs` → 46/46. - `node .github/scripts/testing-layers.mjs --check` — `440 test file(s) in 16 workflow(s)`, every file and workflow classified. - `node .github/scripts/changelog.mjs check` — `3 fragment(s) in changelog.d/ are well formed`. - `node .github/scripts/check-mojibake.mjs --check` — `0 occurrences of U+FFFD in 1154 text file(s)`. ## Red without the source change Each cut made on this tip and reverted; the sources were byte-identical afterwards (`cmp`) and the three gate suites ran 207/207 green again. | knife | red | | --- | --- | | restore `review-gate.mjs` to `main`'s version (item 7 undone) | 207 tests → **202 pass / 5 fail** — the bot-account cases in all three layers, the fail-closed case, and `ThinkFlowLab#1344: the queue entry reads the account type from the API` | | make identity order-dependent (a PASS must be seen before the correction) | 68 tests → **67 pass / 1 fail** — `ThinkFlowLab#1335: a correction listed before the PASS it withdraws still refuses` (item 6's knife) | | **drop the `type !== 'User'` branch** (fail-open again, item 7's knife) | 114 tests → **112 pass / 2 fail** — `ThinkFlowLab#1344: a report with no account type is not a conclusion` and `ThinkFlowLab#1344: the queue entry reads the account type from the API` | | put the account back into `reasons` | 233 tests → **227 pass / 6 fail** — every "no Verifier report names the tip" case, including `verdict-signature`'s bot-with-a-valid-signature | | remove the frozen seal (`frozenRefusal` → `null`) | 93 tests → **89 pass / 4 fail** — all four freeze cases: prefix, marker, base-empty release, and self-unfreeze by editing the list | ## Not run - `npm run verify` as one command — no shipped code changed (`core/`, `plugins/`, `patches/` untouched), so the suites it runs cannot see this diff. - `generate` — not needed; nothing under `core/` or `patches/` is in the diff. - A live DSH window / smoke bench — no runtime code changed. - `check-arch-docs` — run by CI on the PR; locally the worktree's `origin/main` ref predates this base, so a local run would not compare against `ad8c5133`, and the rule reads `core/` changes, of which there are none. ## Risk Refusals only ever refuse: no path here lets a bot or typeless report pass, and none lets a frozen branch enter the queue while a PASS is on it. The loosening risk is the fixture change; it is exactly the payload GitHub sends, and the fail-closed case pins it. A caller that forgets `type` now refuses everything — `merge-gate` was that caller and is fixed here, and a test pins both halves so a future caller cannot be silently bricked. The seal is deliberately narrow, and the PR body should not overstate it: **it blocks the merge queue only.** A direct push or an admin merge never reads it; matching is by branch prefix and body marker, so a determined actor can rename; and `Birfy` is one shared token, so anyone holding it can edit `frozen-branches.json` on `main`. It is a *temporary seal with a one-line release*, not permission isolation — nothing in this PR claims the impersonation is fixed. ## Scope **11 files, +235/−49.** - `.github/scripts/review-gate.mjs`, `.github/scripts/review-gate.test.mjs` — item 7's two spots, item 6's case. - `.github/scripts/enqueue-guard.mjs`, `.github/scripts/enqueue-guard.test.mjs` — the frozen seal and its four cases (plus the `ThinkFlowLab#943` assertion that flipped). - `.github/scripts/merge-gate.mjs` — **two fields and nothing else**: `type: c.user?.type` and `type: v.user?.type` on the report list its `main()` builds. It is the only caller that did not carry the account type (`review-gate.mjs` and `enqueue-guard.mjs` both did), and without those two fields the fail-closed rule sees no conclusion at all — **every `merge_group` entry would be refused, the queue is bricked**. Approved by the implementation Lead (`ThinkFlowLab#1344` comment `6434544185`); the two cases that pin it are in the diff — `ThinkFlowLab#1344: a report with no account type is not a conclusion — the field is read fail-closed` and `ThinkFlowLab#1344: the queue entry reads the account type from the API — a User PASS allows, a typeless one refuses` — and both appear in the fence table below. - `.github/agent/frozen-branches.json` (new) — `{"branches": ["cursor/"], "markers": ["CURSOR_AGENT_PR_BODY"]}`; the seal's whole configuration, read at the base commit. - `AGENTS.md` — rule 4 now names the withdrawal header, plus the new **Untrusted external agent branches** section. - `docs/autonomous-dev.md` — items 1–4 in the paragraph on the withdrawal. - `.github/scripts/merge-gate.test.mjs`, `.github/scripts/gate-check.test.mjs`, `.github/scripts/verdict-signature.test.mjs` — **fixture-only**: each feeds `decide()` and needed `type: 'User'` on its report fixture. No production line changes there. Not in this PR: `core/`, `patches/ds-bot/`, `pass-label.yml`, `package*`, `ThinkFlowLab#1328`, `ThinkFlowLab#1330`. ## Checkpoint <!-- flybot:checkpoint --> ```json { "pr": 1348, "claim": "Dev", "issue": 1344, "summary": "Only a User account writes a conclusion now: a report with no account type is not one, and a bot report no longer names itself as the cause of a refusal. An external agent's branch is frozen at the queue entry, read from a JSON list on the base commit that the pull request cannot edit. Four prose sentences and the AGENTS rule were brought back in line with the code. One case pins that a correction listed before the PASS it withdraws still refuses.", "files": [".github/scripts/review-gate.mjs", ".github/scripts/enqueue-guard.mjs", ".github/agent/frozen-branches.json", "AGENTS.md", "docs/autonomous-dev.md"], "checks": { "ran": "node --test \".github/scripts/*.test.mjs\"; node .github/scripts/testing-layers.mjs --check; node .github/scripts/changelog.mjs check; node .github/scripts/check-mojibake.mjs --check", "result": "green", "at": "de4cca5a6cc42b58b9959123dcb5057ae5cf5009" }, "next": "none — ready for review" } ``` <!-- /flybot:checkpoint -->
…1348 prose (#1350) The seal (#1344) could not hold: #1328 was based on 8d0a99c, older than the document it was supposed to read, so the base read found no list and froze nobody, and it merged at 06:03:21Z. #1350/#1354 patched the reading; the owner chose B instead — remove the mechanism whole. Deletes the constants, frozenList(), frozenRefusal(), the decidePull call site and its early return, the JSON document, the nine tests that only existed for it, and the AGENTS.md section. #1350's rule-7 alignment stays: it is about conclusions, not about the seal.
…hinkFlowLab#1348 prose (ThinkFlowLab#1350) (ThinkFlowLab#1352) Owner: Dev Reviewer: Reviewer Fixes ThinkFlowLab#1350 Fixes ThinkFlowLab#1354 Tip SHA: a09f330 **Executor decision B: remove the frozen-branch seal whole, and keep what `ThinkFlowLab#1350` asked for that is not about the seal.** `ThinkFlowLab#1354`'s repair — read the list from `main`, list `ThinkFlowLab#1328`'s number in code — is on this branch's earlier commits and is now moot: with no seal there is nothing to read and no number to list. ## Reproduce **The seal could not hold.** `ThinkFlowLab#1328` (branch `dev4/1265-step2-one-board`, base `8d0a99c1`) entered the queue at `06:01:1xZ`, was turned draft, and merged at `06:03:21Z` — the seal never answered it: the base read found no document, and its branch matched no listed prefix. `ThinkFlowLab#1350`/`ThinkFlowLab#1354` patched the reading so the next such pull request would be refused. The owner then decided the mechanism goes instead of being patched: the cost of the seal (a queue-entry stop re-read on every `labeled` event, a policy document no pull request may edit, a number list that had to live in code) was not worth what it caught, and it never was a permission boundary — a direct push, an admin merge or a renamed branch walked past it. **The check that judges this pull request is `main`'s copy, and that copy still carries the seal.** That is why the document is not deleted here. The first push of this change (`8f97e4f5`) deleted `.github/agent/frozen-branches.json` along with the code; the check run at that head answered `do not enqueue ThinkFlowLab#1352: frozen: .github/agent/frozen-branches.json is not editable by a pull request`. `enqueue-guard.yml` checks out `ref: main` and never runs pull request code, so any diff that deletes or edits that document is refused by the seal until the seal itself is on `main`. Removing the reader and removing the document cannot travel in one pull request; this one removes the reader, keeps the document byte-identical to the previous tip, and the deletion is the follow-up pull request. ## What changed 1. **`.github/scripts/enqueue-guard.mjs` — the whole path, not a branch of it.** `FROZEN_PATH`, `FROZEN_REASON`, `FROZEN_EDIT_REASON`, `FROZEN_PULL_REQUESTS`, `frozenList()`, `frozenRefusal()` and the `decidePull` call site with its early return are gone; `decidePull` returns `{ decision, pull, repo, pr }` from `guard()` alone. No dead import, no dead export, no always-true branch left. `guard()`, `recordOnlyAt` and every other rule are untouched. 2. **The nine cases that existed only for the seal are deleted** — the five `ThinkFlowLab#1344` cases, the `ThinkFlowLab#1350` `merged`-short-circuit case (it pinned the seal's own ordering and has no meaning without it) and the three `ThinkFlowLab#1354` cases. The fixture loses the `/contents/` answer and the `frozen`, `prNumber` and `baseSha` knobs and the `BASE` constant that fed them: nothing reads them now, so none is left dangling. **No other test was touched** — every remaining assertion is byte-identical. 3. **`AGENTS.md` — the section is gone.** `#### Untrusted external agent branches` goes whole: the three `Do not` bullets, the `dequeuePullRequest` paragraph, the "never the baseline for `generate`" paragraph and the Chinese release sentence. What `ThinkFlowLab#1350` asked for that is *not* about the seal stays: rule 7 now matches `accountRefusal()` — only `type === 'User'` writes a conclusion, a report with **no `type` at all** is refused too, the account and its text stay as a note in `judged`, and the refusal's sentence stays `no Verifier report names the tip <sha>`. 4. **`.github/agent/frozen-branches.json` is unchanged here** — `cmp` against the previous tip is identical. Nothing reads it after this change; it is deleted in the follow-up pull request, which is possible only once `main` no longer carries the rule that refuses that deletion. 5. **`ThinkFlowLab#1354` is not needed any more.** Nothing is read from `main` or from a base, so the base-vs-main defect cannot recur; the issue is closed by this pull request as "the mechanism was removed", not by a fix. ## What I ran On `/data/w1352`, a tree extracted from the repository's own tarball of this branch's previous tip `c6ba9a09`, with `git` 2.53.0 and its `libexec/git-core` on `PATH`: - `node --test ".github/scripts/*.test.mjs"` → **543 / 543 pass** (this branch was 552 before this change; `−9` is exactly the nine cases removed with the seal). - `node .github/scripts/enqueue-guard.test.mjs` → **88 / 88 pass** (was 97; `−9` again). - `node .github/scripts/testing-layers.mjs --check` → `440 test file(s) in 16 workflow(s)`, every file and every workflow classified. - `node .github/scripts/check-mojibake.mjs` → `ok — 0 occurrences of U+FFFD in 1155 text file(s)`. - `diff -rq` against `c6ba9a09` → exactly three files, all listed under Scope. `cmp` on the JSON document: identical. - `grep -rn 'frozen-branches\|frozenRefusal\|frozenList\|external agent branch'` over `*.mjs`, `*.md`, `*.json`, `*.yml` → **0** (22 lines at the previous tip). The document file exists but no text names it. - GitHub's own read of the pull request: `3 files, +3 / −116`. ## Red without the source change **A deletion has nothing that can go red.** The nine cases were removed together with the code they pinned, so restoring the source would restore the tests and the suite would be green either way — claiming a red here would be a fabrication. The mechanical substitutes, each run: 1. **The grep.** The command above returns no line and exit status 1 (22 lines at the previous tip). 2. **The module's exports.** `import()` of `enqueue-guard.mjs` names exactly `decidePull, guard, main, recordOnlyAt`; `frozenRefusal` is `undefined`. The export does not exist to be called. 3. **The same fake `gh`, both tips, through the printed reader.** A pull request on a listed prefix branch with no conclusion, run through `main()`: - previous tip: `REFUSE — do not enqueue ThinkFlowLab#566: frozen: external agent branch; owner decision pending` - this tip: `REFUSE — do not enqueue ThinkFlowLab#566: no Verifier report names the tip aaaa…; no checkpoint: …` The seal's sentence no longer appears in any decision; the pull request is judged by the ordinary rules, which is the point of B. 4. **The one genuine red this change can show, and it did:** main's own seal refused this pull request while its diff deleted the document — the `8f97e4f5` run quoted under Reproduce. That red is real and is the reason the document is not in this diff. ## Not run - `npm run verify`: nothing under `core/`, `plugins/` or `apps/` is touched. - `generate` / `scripts/ds-bot-patches.mjs check`: `patches/` is untouched. - `check-arch-docs`: its rule reads `core/` changes; there are none. - A live queue entry: the next real enqueue exercises `decidePull`; a pull request cannot stage one without merging. ## Risk - **The seal is gone, so its refusal is gone.** A branch under a listed prefix, or a body carrying the agent's PR-body marker, is now judged by the ordinary rules only; one that carries a PASS at its tip and a clean body can enter the queue. That is the owner's decision, and the seal never stopped a direct push or an admin merge anyway. - **The document outlives its reader for one pull request.** Between this merge and the follow-up, `.github/agent/frozen-branches.json` sits in the tree with nothing reading it; nothing can act on it, and the follow-up deletes it. Anyone reading the tree in that window should read it as a stale config, not a live rule. Deleting the reader and deleting the file cannot travel in one pull request: `enqueue-guard.yml` is `pull_request_target` with `ref: main` and never runs pull request code, so main's copy of the seal refuses any diff that edits or deletes the document. That is a mechanical constraint of the check, not a choice made here. - **`ThinkFlowLab#1328` stays merged.** This removes the mechanism, not that merge; nothing here reopens or reverts it, and `ThinkFlowLab#1346`'s branch is untouched. ## Scope - `.github/scripts/enqueue-guard.mjs` — removal only. - `.github/scripts/enqueue-guard.test.mjs` — removal of the nine seal cases and of the fixture knobs they used. - `AGENTS.md` — the external-agent section deleted; rule 7's `accountRefusal()` alignment kept. Unchanged, deliberately: `.github/agent/frozen-branches.json`. Not touched: `core/`, `patches/`, `package*`, `.github/workflows/pass-label.yml`, tier calculation, and every tip belonging to `ThinkFlowLab#1328`, `ThinkFlowLab#1346`, `ThinkFlowLab#1348`, `ThinkFlowLab#1342`, `ThinkFlowLab#1349`. ## Checkpoint <!-- flybot:checkpoint --> ```json { "pr": 1352, "claim": "Dev", "issue": 1350, "summary": "Executor decision B: the frozen-branch seal is removed whole, not patched. enqueue-guard.mjs loses the four constants, frozenList(), frozenRefusal() and the decidePull call site; the nine cases that only pinned the seal go with the fixture knobs they used; the AGENTS.md external-agent section goes, while ThinkFlowLab#1350's rule-7 alignment stays. ThinkFlowLab#1354's fix is moot with no list to read. The document itself is not in this diff: main's own check refuses any pull request that edits it, so it stays byte-identical for a follow-up.", "files": [".github/scripts/enqueue-guard.mjs", ".github/scripts/enqueue-guard.test.mjs", "AGENTS.md"], "checks": { "ran": "node --test \".github/scripts/*.test.mjs\" (543/543); enqueue-guard 88/88; testing-layers --check; check-mojibake; grep for the seal names; cmp of the JSON document", "result": "green", "at": "a09f330ab2b298fc1095884a7f79dd086435c26f" }, "next": "none — ready for review at this tip" } ``` <!-- /flybot:checkpoint -->
…FlowLab#1371) (ThinkFlowLab#1372) Owner: Dev Reviewer: Reviewer Fixes ThinkFlowLab#1371 Tip SHA: 5da667e **`ThinkFlowLab#1352` removed the frozen-branch seal and left its data file in the tree; this deletes that file and nothing else.** ## Reproduce `ThinkFlowLab#1352` merged at `07:12:44Z`, removing `FROZEN_PATH`, `frozenList()`, `frozenRefusal()` and every call site from `.github/scripts/enqueue-guard.mjs`. The document those functions read — `.github/agent/frozen-branches.json` — is still there, byte-identical to what the seal shipped (blob `12c3f3fe`): ```json { "branches": ["cursor/"], "markers": ["CURSOR_AGENT_PR_BODY"] } ``` **Nothing on `main` reads it.** On a tree extracted from `main` `9c8e51bf`: `grep -rIn frozen .github/` → the only hit is `check-dsh-task-shape.mjs:70` talking about a frozen *task record*, not this file. `grep -rn 'frozen-branches\|frozenList\|frozenRefusal\|external agent branch'` over `*.mjs`, `*.md`, `*.json`, `*.yml`, `*.yaml` → **no hit** before or after this deletion: `ThinkFlowLab#1352` removed every reference in the same merge. The file is dead config. **It could not be deleted in `ThinkFlowLab#1352`.** `enqueue-guard.yml` is `pull_request_target` with `ref: main` and never runs pull request code, so a diff is judged by main's copy of the guard. When `ThinkFlowLab#1352` first pushed the deletion (`8f97e4f5`, main still carrying the seal), the check answered: ``` do not enqueue ThinkFlowLab#1352: frozen: .github/agent/frozen-branches.json is not editable by a pull request ``` With the seal on `main` there is no such rule and no reader, so the deletion is an ordinary change now. **What kind of change it is, is not mine to pick:** `.github/**` sits at the top of `.github/agent/risk-rules.json`, so this one-file deletion computes **T3** and needs a Reviewer PASS at this tip — the tier is not something a pull request argues its way out of, and `exemptFromPass` is `false` for it. That ordering — reader first, document second, in two pull requests — is the mechanical constraint `ThinkFlowLab#1352` recorded in its own Risk section, not a choice made again here. ## What changed 1. **`.github/agent/frozen-branches.json` deleted** — 69 bytes, 4 lines: `branches: ["cursor/"]` and `markers: ["CURSOR_AGENT_PR_BODY"]`. 2. **Nothing else.** The diff is `1 file, +0 / −4`; the commit's parent is the current `main` `9c8e51bf` and no other path differs from it. 3. **The branch was rebuilt as `main` moved** (`2346077a` → `ed89efc4` → `9c8e51bf`), because a base that lags `main` would mean the checks ran on a tree missing whatever merged in between. The content of the change never changed: one deletion. ## What I ran On `/data/w1372`, a tree extracted from the repository's own tarball of `main` `9c8e51bf`: - **Control, the unmodified tree with the file still present:** `node --test ".github/scripts/*.test.mjs"` → **538 tests, 536 pass, 0 fail, 2 skipped**. - **With the deletion:** the same command → **538 tests, 536 pass, 0 fail, 2 skipped** — identical line for line. Nothing in the suite reads the file, which is the point of the change. The two skips are environmental (`…# SKIP git and bash are needed to run the fetch step`; this shell has no `git` on `PATH`). - `node --test .github/scripts/enqueue-guard.test.mjs` → **88 / 88 pass**. - `node .github/scripts/check-mojibake.mjs` → `ok — 0 occurrences of U+FFFD in 1163 text file(s)`. - `node .github/scripts/testing-layers.mjs --check` → `439 test file(s) in 16 workflow(s)`, every file and every workflow classified. - `grep` for the seal's four names, deletion in place → 0 lines (exit 1). - GitHub's own read of this pull request: `1 file, +0 / −4`, base `9c8e51bf`. ## Red without the source change **A deletion has no source to revert, so nothing can be made to go red; claiming one would be a fabrication.** The mechanical substitutes, each run: 1. **The same diff, two copies of the guard.** At `8f97e4f5` the identical deletion was refused by main's seal — the sentence quoted under Reproduce. On this tip the same deletion is judged by the ordinary rules only. That before/after pair is the real evidence that the mechanical blocker is gone, and it is why `ThinkFlowLab#1352` had to leave the file behind. 2. **Suite identity.** 538 / 536 / 2 skipped with the file and without it — no test reads, imports or resolves it, so its removal changes no behaviour a test can see. 3. **The grep.** 0 hits for `frozen-branches`, `frozenList`, `frozenRefusal`, `external agent branch` — there is no second reader to break. 4. **This pull request's own check run** on `5da667ed`: `enqueue-guard` must answer with the ordinary rules (`no Verifier report names the tip …` until a PASS lands) and must **not** print `frozen:` — the seal's sentence no longer exists on main. ## Not run - `npm run verify`, `node scripts/ds-bot-patches.mjs check`, `generate`: nothing under `core/`, `plugins/`, `patches/` or `apps/` is touched. - `check-arch-docs`: its rule reads `core/` changes; there are none. - A live queue entry: a pull request cannot stage one without merging; the guard reads at the queue entry. ## Risk - **The last trace of the seal goes away with it.** That is the intent: `ThinkFlowLab#1352` left the document in the tree and wrote that anyone reading the tree in that window should read it as a stale config, not a live rule. Deleting it removes the chance of that misreading; no rule changes here, because no rule has read it since `ThinkFlowLab#1352`. - **A revert of `ThinkFlowLab#1352` would need this file restored too.** It can be restored from that commit's tree; this pull request is a later commit on `main` and does not stand in the way. - **Nothing outside this repository is known to read the path.** The only reader in the tree was `enqueue-guard.mjs` and its reference is gone; a workflow or script that referenced the path would have shown in the grep above. - **It needs a PASS, not a tier argument.** `.github/**` is the top rule in `risk-rules.json`; the computed tier is T3 and `exemptFromPass` is false. The verdict has to name `5da667ed`. - **`ThinkFlowLab#1328`, `ThinkFlowLab#1346` and the `cursor/` branches stay as they are.** This is cleanup of dead data, not a re-litigation of the seal's decision. ## Scope - `.github/agent/frozen-branches.json` — deleted. Not touched: `.github/scripts/**` (no code change; `ThinkFlowLab#1352` already removed the reader), `AGENTS.md`, `docs/`, `core/`, `patches/`, `.github/workflows/**`, tier calculation, and every tip belonging to `ThinkFlowLab#1328`, `ThinkFlowLab#1346`, `ThinkFlowLab#1350`, `ThinkFlowLab#1354`, `ThinkFlowLab#1367`, `ThinkFlowLab#1370`, `ThinkFlowLab#1374`. ## Checkpoint <!-- flybot:checkpoint --> ```json { "pr": 1372, "claim": "Dev", "issue": 1371, "summary": "ThinkFlowLab#1352 removed the frozen-branch seal but left its data file in the tree, because main's copy of the guard refused any pull request that edited or deleted it. This deletes .github/agent/frozen-branches.json and nothing else: one file, +0/-4, rebuilt on the current main. A grep for the seal's four names returns nothing, and the .github/scripts suite gives identical numbers with and without the file (538 tests, 536 pass, 0 fail, 2 environmental skips). Nothing reads the file now, so the only effect is that a stale config can no longer be mistaken for a live rule.", "files": [".github/agent/frozen-branches.json"], "checks": { "ran": "node --test \".github/scripts/*.test.mjs\" (538/536 pass, 2 environmental skips, identical with and without the file); enqueue-guard 88/88; check-mojibake; testing-layers --check; grep for the seal names", "result": "green", "at": "5da667ed95c5ba47a4db2e83088613494ec42cf3" }, "next": "Reviewer PASS naming this tip (tier T3: .github/** is the highest rule in risk-rules.json), then the queue" } ``` <!-- /flybot:checkpoint -->
Written-by: Dev4
Owner: Dev4
Reviewer: Reviewer
Fixes #1326
Part of #1265
Tip SHA: fb012a4
Base: c67ed0e (main when the branch was rebuilt; main has since moved one commit on
.github/scripts/andAGENTS.mdonly, no file in this diff)Reproduce
mainbefore this branch, open the task dialog: it drawsdiv.bt-board-views[role=tablist]with Tasks / Delivery, and the delivery half draws five lanes (raw,ready,working,review,done-today).5622a948),./.github/actions/flybot-tests→ Lint failed:Found 70 warnings and 6 errors, alleslint(no-unused-vars)forscope,roster,lanes,dragging,onMove,onDragonDeliveryBoard(core/src/client/delivery-view.js:520).5622a948, with an open pull request in the round, the host threw and the board came backfailed:core/src/host/delivery-board.jsbuilt the three-lane map{ 'not-started', 'in-progress', 'done' }and then calledcolumns.review.push(...)— a column that no longer exists.node --import ./test/harness-resolve.mjs --test test/delivery-board.test.jsreproduced it asnot ok 5 … Expected values to be strictly equal: + 'failed' - 'partial'and 13 red files-to-be.What changed
KanbanDialogmountsUnifiedBoard;DeliveryViewis the GitHub half of that single board.DeliveryBoardnow takesroster,dragging,onMove,onDrag; the two dead propsscopeandlanesare dropped fromDeliveryBoard/DeliveryViewand from theUnifiedBoardcall. A task card on the board is the sharedBoardCardwithTASK_SKIN(data-source="task",data-key="task:<id>",data-task), shows the owning Bot's name fromroster, is draggable when the board offersonMove, and every column takes a drop — the drop only reportsonMove(id, column)to the dialog, which owns the single write path (actions.taskUpdate), so the view still never writes.core/src/host/delivery-board.js): an open pull request goes tocolumnOfDelivery(pr, { kind: 'pr' })(in-progress) and carriesstage: 'review'; today's merges and closures stay indonewithstage: 'done-today'. Noreview/done-todayarray exists to push to.div.bt-del-filterswithbutton[data-filter=all|review|done-today]andaria-pressed, delivery cards carrydata-stage, a filter narrows cards and never reorders or adds a column.core/test/delivery-board.test.js(columns['in-progress'],columns['not-started'],columns.done+stage),core/test/delivery-view.test.js(three-lane fixture, filter contract, new drag/drop case),core/test/kanban.test.js(no-tablist contract, kept from the branch).docs/subsystems/core-client.md(delivery-view row: columns from the snapshot/definition, filters,data-stage, task card throughBoardCard, one board instead of two tabs; kanban row:UnifiedBoard+ the drag path) anddocs/subsystems/core-host.md(delivery-board row: placement by workflow stage with the finer stage on the card).What I ran
At
ac038e55b445c70ef334cc4de6d28e11b607b9ac, on a tree rebuilt fromc67ed0e4whosegit rev-parse HEAD^{tree}equals the API tree of the base commit (76ba2c0b…):node --import ./test/harness-resolve.mjs --test test/delivery-view.test.js test/delivery-board.test.js test/kanban.test.js test/board-card.test.js→ 89 tests / 89 pass / 0 fail.TZ=UTC node --import ./test/harness-resolve.mjs --test-concurrency=2 --test "test/*.test.js"→ 1877 tests / 1875 pass / 2 fail:check-arch-docs.test.js"empty diff passes" (it shells out togit, and that run had nogitonPATH; re-run withgitonPATH→ 6/6 pass) andusage-fields.test.js"usage.sqlite has one real calls row" (null !== 0, this machine's sqlite fixture — the same single failure the full suite has locally without any change).node scripts/ds-bot-patches.mjs check:ok ds-bot/ = Fei2411/DeepSeek-Bot@2b10c70 (tree 5834c00, v0.1.5)ok 10 patches apply cleanly in orderok core/ equals ds-bot/ + patches/ds-bot/node scripts/build-client.mjs --check→ exit 0.npm run lint→Found 70 warnings and 0 errorsandarch-docs: OK (19 changed file(s)).node scripts/ds-bot-patches.mjs generaterewrote exactly the mirrors of the core files in this diff —0001(i18n) and0008(client bundle) plusfiles/fordelivery-view.js,kanban.js,host/delivery-board.jsand the three test files. No unrelated patch moved.Red without the source change
Each knife was applied in this tree, the suite run, and the file restored (
cmpclean against the saved copy):columns.review.push(...)back inhost/delivery-board.js→test/delivery-board.test.js: 49 tests / 18 pass / 31 fail, first linenot ok 5 - a 403 rate limit carries only the wait GitHub gave (#1211).BoardFiltersrender nothing →test/delivery-view.test.js: 29 / 28 / 1,not ok 24 - #1326: the stages that draw no lane are filters, and a filter narrows without reordering.'data-stage': card?.stagefromDeliveryCard's attrs → same suite: 29 / 28 / 1,not ok 24 - #1326: the stages that draw no lane are filters…(thedata-stageassertion).draggable: falseand every columndropProps = () => ({})→ same suite: 29 / 28 / 1,not ok 25 - #1326: a task card is the shared card, and a drop only asks the board to move it.div[role=tablist]back inkanban.js→test/kanban.test.js: 7 / 6 / 1,not ok 4 - one board: no tablist, heading says Board, shows both task and delivery cards (#1326).Not run
plugins/social,plugins/tree,plugins/timeline),node scripts/lint-plugins.mjs,.github/scripts/*.test.mjsand the interop/live-e2e jobs: this diff iscore/+ generatedpatches/+ two subsystem docs, none of them imported by the plugins.npm run verifyas a whole was not run here.core/index.jsorcore/src/host/that the bench exercises changed beyond the delivery snapshot's column map.delivery-view.test.jsbuildssrc/client/delivery-view.jswith esbuild and walks the result), not in a live page.Risk
onMoveinstead of the oldBoardViewcolumns' drop handlers. The unified board renders throughdelivery-view.js, so a drag is a request (onMove(id, column)) andcanMoveTask+actions.taskUpdateremain the only authorisation and write path — but this is the surface with the least real-browser coverage in this diff.columnOfDeliveryis lossy by design: an issue withneeds-infoand no work label sits innot-started(it did before underraw), and an open pull request is alwaysin-progresswithstage: 'review'— so a workflow that draws a realreviewcolumn would need the host to stop hard-coding the stage. That belongs to the workflow-driven host read (One board: the delivery board and the task board are one board, and a repository task is its issue #1265 later steps), not this UI step.BoardViewinkanban.jsis now only reachable from its tests (the dialog usesUnifiedBoard); removing the duplicate is a follow-up, not part of this step.Checkpoint
{
"pr": 1328,
"claim": "Dev4",
"issue": 1326,
"summary": "One board instead of two tabs: the dialog mounts UnifiedBoard and DeliveryView is its GitHub half. Columns are the three lanes the definition draws; review and done-today are filters over data-stage, never lanes. Task cards read through the shared BoardCard with TASK_SKIN and stay draggable, with a drop only asking the dialog to move the card. The host placement that pushed into a removed review column is fixed, the six lint errors are gone by wiring that surface, and both subsystem docs are updated.",
"files": [
"core/src/client/delivery-view.js",
"core/src/host/delivery-board.js",
"core/src/client/kanban.js",
"core/test/delivery-board.test.js",
"core/test/delivery-view.test.js",
"docs/subsystems/core-client.md"
],
"checks": {
"ran": "node scripts/ds-bot-patches.mjs check; node scripts/build-client.mjs --check; npm run lint; node --import ./test/harness-resolve.mjs --test test/delivery-view.test.js test/delivery-board.test.js test/kanban.test.js test/board-card.test.js",
"result": "green",
"at": "fb012a4b17eb7f43f47e73ae54a8b0c39f5d5a40"
},
"next": "enqueued after Reviewer PASS at this tip"
}