feat(queue): queue as data A2, migration, render and dispatch (#1508)
Filbert approved round 1 (f167b85e). Manifest 782bcb62, 21 files, plus the QUEUE.md markers and the TOOLS.md section. Lead decision 35. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
b18afc13db533b5cbfac8701234b25dde87c9c1b4fda970e738faf87b7a6d324 packages/queue/README.md
|
||||
a1e72713398a3f706e4beb5ad012798ab6a55f2f76c2f3144db94011a45a3231 packages/queue/src/cli.mjs
|
||||
962d0e6548121933030980b937f55ca5913ee3859ff2b8888095bd273dbf561e packages/queue/src/io.mjs
|
||||
05682738482a56001bac168168a6aeb7e624f8ed1661a6c6592274f13da38c89 packages/queue/src/lock.mjs
|
||||
b87756a89c3bdeb03bddd1b1e51706ae93975b01f008237076ffe34557a71de3 packages/queue/src/queue.mjs
|
||||
b7708293363d33093a1106c2346c26ce5d48e052342abbec17c59ee058a4fb05 packages/queue/src/store.mjs
|
||||
70a11be54d8bddd3db0fd52555a1bdf481efef0cae671ee8e1aab546e3ddd36a packages/queue/tests/data.test.mjs
|
||||
b1c90f99eb2b5005ebc461dab5793164b80d7e846573f788606040ef88f5819e packages/queue/tests/helpers.mjs
|
||||
e7c9b23b6aa28321754c1c649f8bd5ee2c97bfea0d4e180ae699a4a1f5c60c76 packages/queue/tests/lock.test.mjs
|
||||
42120f0009815bedd3887b10e3630a694711825e4dee29a475733dbd212a49eb packages/queue/tests/store.test.mjs
|
||||
f79195520a1108ce5748ad6833eb03d2bb3ef97d74d83807ee1079e461ebb1f4 packages/queue/tests/write.test.mjs
|
||||
86c2a4f806e99fd09baf623dc7b3c95c1a630d147fe89c4fe5b93793fa4c5f50 scripts/mosaic
|
||||
b6aec15a75305bb48bca20a665bd919111a0071ffd7a1cc3631df2beaaac5a1b scripts/test-queue.sh
|
||||
dc32c0e0a865fe6b3623a808c4e9d8e8b284a3e74c36b3519554ea02d3a3ee5f packages/queue/tests/dispatch.test.mjs
|
||||
0d83ab1e73663de0f3da719078e7d756b8ec8f828ea63c2ce446bf21fb27c754 packages/queue/tests/migration.test.mjs
|
||||
3306b486be165b88c554ba13283cab4c79a5b67fbe3c2b6bfe72f987e1eddf07 packages/queue/tests/fixtures/genesis-render.md
|
||||
fb43d5855726e517f0eaacd626debb110e8ea6c948c97b35ad8971ec0885d151 packages/queue/tests/fixtures/mosaic-pre-a2.sh
|
||||
8f1927f3f11f260e71e7235a69efcbf10c8fd62bf263ddb89c3029f5e61833b7 packages/queue/tests/fixtures/queue-marked.md
|
||||
012ddce99d03932512d79b6ae7ba74786e050469e800cfb00fda683a2dfe42a8 agents/darkwing/work/queue-migration-map.md
|
||||
cdc49c447504f6c9f1c40da9ec0d89bf4d21c5e2a0730b1f12d1f20fbea63edb agents/darkwing/work/queue-a2/map-check.mjs
|
||||
b2a738f0da52783dc8e8a7c6033ce62582582e587eb6e5b6bde988ea4b406f3e agents/darkwing/work/queue-a2/carry-forward.md
|
||||
@@ -0,0 +1,202 @@
|
||||
# Queue A2 (#1508), candidate for review
|
||||
|
||||
Darkwing, 2026-09-27. A2 is migration, render and dispatch (lead decision
|
||||
20), plus every item Sage carried forward from A1's review (decision 26:
|
||||
N5, N8, N10, N11, N12, P1, P2, P3). Base is HEAD c9539baa; A1 is 34a72af9.
|
||||
Filbert reviews. Sage commits, then installs the hook and runs genesis.
|
||||
Nothing is committed, staged or pushed.
|
||||
|
||||
## Files
|
||||
|
||||
`build.patch` (sha256 `dc0be7ce74aaaaaf43deebe68af439d1b2b80c77aad6538420e929de35e2f21f`) changes 13 files and adds 8.
|
||||
`build-manifest.sha256` (sha256 `782bcb62e555659333a35888d418d986da63bdf522f38cafa447db7ddd0074b7`) pins all 21 after the patch.
|
||||
In a fresh clone at c9539baa the patch applies and the result matches
|
||||
the manifest 21/21, file modes included. `git apply` warns about one
|
||||
blank line at the end of `fixtures/genesis-render.md`. It belongs there:
|
||||
the render ends with one, and the golden has to match byte for byte.
|
||||
|
||||
- `packages/queue/src/`: `queue.mjs` (N8, N10, N11, P2), `store.mjs` (N12,
|
||||
N11's shared check, P1's helper, P3's caller), `lock.mjs` (P1, P3),
|
||||
`io.mjs` (N5), `cli.mjs` (usage comment).
|
||||
- `scripts/mosaic`: `queue` execs `packages/queue/src/cli.mjs` with the
|
||||
remaining arguments. Every other call reaches the seat CLI as before.
|
||||
- `scripts/test-queue.sh`: syntax checks for `scripts/mosaic` and the new
|
||||
fixture; `scripts/mosaic queue help` always; after genesis, `verify` and
|
||||
`render --check` on the live queue through `scripts/mosaic queue`.
|
||||
- `packages/queue/README.md`: the dispatch, N5, N7, N8, N10, N12, P2, the
|
||||
map and `map-check.mjs`, two new test files.
|
||||
- Tests: 107 in A1, 122 now. New: `dispatch.test.mjs` (3),
|
||||
`migration.test.mjs` (3), and 9 more in data, lock, store and write.
|
||||
Fixtures: `mosaic-pre-a2.sh` (the script before A2), `queue-marked.md`
|
||||
(QUEUE.md with the markers), `genesis-render.md` (the golden render).
|
||||
- `agents/darkwing/work/queue-migration-map.md`: the genesis input.
|
||||
- `agents/darkwing/work/queue-a2/map-check.mjs`: the drift check.
|
||||
- `agents/darkwing/work/queue-a2/carry-forward.md`: the item list Sage
|
||||
confirmed (773dbd75), with the r1 section added after it.
|
||||
|
||||
Outside the patch, for Sage to apply (condition 2 keeps them out of A2):
|
||||
|
||||
- `queue-md.patch` (sha256 `2ca8f689e1dcda5bb30e9af4c3f867242d5239d72e13001369c7b7aca7956402`): the two markers, a header that points
|
||||
seats at `scripts/mosaic queue next`, and a line freezing the old log of
|
||||
table changes. It applies to HEAD.
|
||||
- `tools-md.patch` (sha256 `c53aea1f6e871e17d04335ef60250adcdbe64f6466d9ff641042c00094d1c3a8`): a "Work queue" section in
|
||||
`docs/TOOLS.md`. It applies to HEAD. Optional; the README already has
|
||||
the detail.
|
||||
|
||||
## The five conditions
|
||||
|
||||
1. **Nothing ran against the canonical `.git`.** Tests use scratch
|
||||
repositories under the temp directory. The dry run below used
|
||||
`/tmp/qa2-dry`. Checked after all runs: no `mosaic-queue*` file in
|
||||
`.git/`, `.git/hooks/pre-commit` absent, `core.hooksPath` unset in every
|
||||
scope, nothing staged.
|
||||
2. **No QUEUE.md, AGENTS.md or TOOLS.md edits.** The two proposals are
|
||||
patch files. `git status` shows none of the three modified.
|
||||
3. **`scripts/test-queue.sh` is green at a HEAD with no `queue.json`:**
|
||||
24/24, the live checks skipped. After the dry-run genesis it ran 26/26, with `verify` and
|
||||
`render --check` on the live queue.
|
||||
4. **H is recorded before the canary.** `queue-commit.sh` is unchanged
|
||||
from A1, and its test "F1: H is recorded before the canary, so HEAD
|
||||
moving during the canary makes update-ref fail" passes.
|
||||
5. **The fault layer is reachable only from tests.** N5 narrows this
|
||||
further: tmpfs was the one fault-free path open to the CLI, and now
|
||||
only a layer with `allowTmpfs: true` gets it. The test asserts
|
||||
`realIo` has no such key and that `"yes"` doesn't count.
|
||||
|
||||
## Carried-forward items
|
||||
|
||||
| Item | Change | Test |
|
||||
|---|---|---|
|
||||
| N8 | `piece`, `gate`, `note`, move `reason`, brief anchor and `blockedReason` refuse `\` and `<`, at the CLI and in replay | "text the table shows refuses \ and <, everywhere it enters"; "every accepted text renders to nine cells on every row" (GFM's cell rule, no `marked` import) |
|
||||
| N11 | Replay holds every log entry, round op and claim op to `CALLER_OP_RE` and refuses `.outcome`, genesis and `accept-history` included. `LOG_OP_RE` stays for Piece D's derived ids; no verb derives one yet | "replay holds every op id to the caller's rule" |
|
||||
| N10 | `set issues` moves `closes` only if it equalled the old issues; a narrowed `closes` keeps its intersection, and the receipt says `(kept narrowed)` | "set issues keeps a logged narrowing of closes" |
|
||||
| P2 | Each round records `issue`; `review` is `{rounds}` only. A later round keeps the last round's issue | "the row schema refuses a round with a null issue, and the A1 review shape", and A1's R2 tests updated |
|
||||
| P1 | Both gate paths in `acquire` release through `releaseOrWarn`; a failed release is a message naming the lock, not a stack trace | "a release that fails on a gate path is reported, never a stack trace" |
|
||||
| P3 | `lock.unlock` returns `{result, warning}`; nothing splits on newlines | "unlock keeps a multi-line lock record on stdout" |
|
||||
| N5 | tmpfs left `FS_TYPES`; only `allowTmpfs === true` admits it | "tmpfs passes only a test layer that allows it" |
|
||||
| N12 | `--by` still wins; a different non-empty `MOSAIC_AGENT_NAME` adds a stderr warning on success and on refusal. Nothing is logged | "--by that differs from MOSAIC_AGENT_NAME warns on stderr and logs nothing more" |
|
||||
|
||||
The rest, as `carry-forward.md` records and decision 26 confirmed: N7 is a
|
||||
README line (the leftover `.git/mosaic-queue.lock.<pid>.<hex>.tmp` is
|
||||
removed by hand). N15, N16, N13-a and ext2/ext3 are won't-do.
|
||||
|
||||
## Migration
|
||||
|
||||
The map (`queue-migration-map.md`) is built from QUEUE.md blob c8e3d34e,
|
||||
which HEAD has. `node agents/darkwing/work/queue-a2/map-check.mjs` prints
|
||||
`ok: QUEUE.md matches the map (blob c8e3d34e)`. Run it again just before
|
||||
genesis. It exits 1 and lists the rows if QUEUE.md moved.
|
||||
|
||||
map-check did its job once already. HEAD moved from 8dba3ff7 to c9539baa
|
||||
while I worked, and it reported row 5 (the CHAT-03 brief pinned, lead
|
||||
decision 33). I rebuilt row 5's note, `queue-md.patch`, the marked fixture
|
||||
and the golden render against the new blob. No other row changed.
|
||||
|
||||
The map's "Choices Sage should check" has eight items. None blocks review.
|
||||
The ones that change what genesis writes: row 7 stays a live row (decision
|
||||
27), row 10's owner stays `coordinator` with `queue assign 10 sage`
|
||||
recommended as the first op, rows 12 and 13 have Sage as gate owner, row 16
|
||||
stays `waiting-on-jason` unless #1510 is closed, and rows 9 to 12 close
|
||||
nothing so row 13 closes #1508. Rows 9 to 13 have no `after`: decision 29
|
||||
took the wait on row 6 off them, and `after: 9 done` on row 10 would wait
|
||||
on a gate that needs row 10.
|
||||
|
||||
Dry run in a shared clone (`/tmp/qa2-dry`), the candidate plus
|
||||
`queue-md.patch` and `tools-md.patch` committed on top of c9539baa. I
|
||||
reran it from scratch after the rebase:
|
||||
|
||||
0. `map-check.mjs`: `ok: QUEUE.md matches the map (blob c8e3d34e)`.
|
||||
1. `scripts/test-queue.sh`: 24/24, live checks skipped.
|
||||
2. `scripts/queue-commit.sh --install-hook --by sage`: installed; canary
|
||||
passed.
|
||||
3. `scripts/mosaic queue genesis --root /tmp/qa2-dry --branch a2-dry --map
|
||||
… --op genesis-2026-09-27 --by sage`: `ok genesis-2026-09-27 rev 0
|
||||
genesis 30 rows`.
|
||||
4. `scripts/queue-commit.sh --genesis`: committed.
|
||||
5. `verify --current`: briefs match HEAD. `render --check`: current.
|
||||
`legacyView` equals the marked body byte for byte, and `mapBlob` is the
|
||||
map's blob.
|
||||
6. `next`: darkwing resumes 9, sage resumes 7, dewey resumes 5, filbert
|
||||
and rocko have nothing.
|
||||
7. `scripts/test-queue.sh`: 26/26 with the live checks.
|
||||
8. `queue assign 10 sage --op assign-10-dry --by sage`: `ok … rev 1 row 10 owner:
|
||||
coordinator→sage`.
|
||||
|
||||
The dry clone's hook is `.git/hooks/pre-commit`, mode 0755, blob
|
||||
abdf14e7. `core.hooksPath` is unset there too.
|
||||
|
||||
## Choices I made
|
||||
|
||||
- **N8 refuses instead of escaping.** An escape has to be right for every
|
||||
Markdown renderer that reads QUEUE.md; a refusal doesn't. No line in
|
||||
today's table has either character.
|
||||
- **P2 drops `review.issue`.** The last round's issue is the kept one, so
|
||||
a second copy could only disagree. Piece D reads `rounds[].issue`.
|
||||
- **N10's edge.** A `closes` narrowed to nothing stays empty whatever the
|
||||
new issues are. `set closes` with a reason is the way to widen it again.
|
||||
- **N12 warns on a refusal too,** so a seat that mistyped `--by` sees it on
|
||||
the error it was reading anyway.
|
||||
- **`scripts/mosaic queue` uses `exec`,** so exit codes and signals are the
|
||||
queue CLI's own. Any first argument other than exactly `queue` goes to
|
||||
the seat CLI, as before; the dispatch test compares argv, cwd,
|
||||
environment and stdin against the pre-A2 script.
|
||||
|
||||
## Mutations
|
||||
|
||||
Each mutation ran alone in a shared clone of the candidate, with
|
||||
`node --test packages/queue/tests/`. A killed mutation fails at least one
|
||||
test.
|
||||
|
||||
46 mutations. Each one below failed at least one test; the number is
|
||||
how many.
|
||||
|
||||
| Item | Mutations |
|
||||
|---|---|
|
||||
| N8 | backslash 2, lt 2, noteVerb 1, rowNote 2, anchor 1, reason 1 |
|
||||
| N11 | entryShape 1, outcome 2, genesisOnly 1, roundOp 1, claimOp 1 |
|
||||
| N10 | always 2, noIntersect 1, receipt 1 |
|
||||
| P2 | keptFirst 1, noCheck 1, reviewIssue 10 |
|
||||
| P1 | gateErr 1, gatePresent 1, gatePresentMsg 1, withLock 1 |
|
||||
| P3 | joined 2, storeSplit 1 |
|
||||
| N5 | inTypes 1, truthy 1, anyType 1 |
|
||||
| N12 | noWarnOk 1, noWarnErr 1, envWins 1, emptyEnv 1 |
|
||||
| Dispatch | noShift 1, unsetArg 1, prefix 1, noExec 1 |
|
||||
| Golden render | mapGate 1, mapState 1 |
|
||||
| map-check | fixed26 1, owner 1, issues 1, lineDiff 1, parkedPiece 1 |
|
||||
|
||||
Five of them survived the first pass. Each now has a test that kills it:
|
||||
|
||||
- N11 roundOp and claimOp (replay stops checking a review round's op or a
|
||||
claim's op). The N11 test now builds a claimed row and a reviewed row and
|
||||
refuses an op of 73 characters and one ending `.outcome` in each.
|
||||
- P1 withLock (the post-op release goes back to the throwing `release`).
|
||||
New write test: the lock's unlink fails with EACCES after the op, and the
|
||||
receipt and a refusal both carry "cannot release the queue lock (EACCES)".
|
||||
- N12 emptyEnv (an empty `MOSAIC_AGENT_NAME` warns). The N12 test now runs
|
||||
with it empty and expects no stderr.
|
||||
- Dispatch noExec (`node` without `exec`, so a successful queue call falls
|
||||
through to the seat CLI). The dispatch test now runs a queue call that
|
||||
exits 0 and checks that only the queue CLI ran.
|
||||
|
||||
The map and golden-render mutations ran again after the rebase and were
|
||||
still killed.
|
||||
|
||||
## Suites
|
||||
|
||||
All nine green at the final candidate: config 24, task 90, foundation
|
||||
44, conductor 17, release 14, auth 15, discord 64, extension-package 18,
|
||||
queue 24 (no `queue.json` at HEAD). `node --test packages/queue/tests/`:
|
||||
122/122.
|
||||
|
||||
## After approval (Sage)
|
||||
|
||||
1. Check the canonical tree against `build-manifest.sha256`, then commit
|
||||
the 21 files by path.
|
||||
2. Apply `queue-md.patch` (and `tools-md.patch` if wanted) and commit.
|
||||
3. `node agents/darkwing/work/queue-a2/map-check.mjs` must print `ok`.
|
||||
4. `scripts/queue-commit.sh --install-hook --by sage`.
|
||||
5. `scripts/mosaic queue genesis --root /mnt/storage/src/mosaic-stack
|
||||
--branch refactor --map agents/darkwing/work/queue-migration-map.md
|
||||
--op <id> --by sage`.
|
||||
6. `scripts/queue-commit.sh --genesis -m MSG`.
|
||||
7. `scripts/test-queue.sh` runs the live checks from here on.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,67 @@
|
||||
# Queue A2 (#1508): items carried from A1 review
|
||||
|
||||
Darkwing, 2026-09-26. This file records Sage's ruling on A1 r1 so it isn't
|
||||
lost before A2 starts. A2's brief lists the two required items. A2's build
|
||||
note repeats each disposition. Note numbers are Filbert's, from
|
||||
`agents/filbert/work/queue-a1-review-2026-09-26.md` (sha256 6933b885).
|
||||
|
||||
## Required in A2, with tests
|
||||
|
||||
Both change what replay accepts or what the table shows, so they land
|
||||
before genesis. Genesis follows A2.
|
||||
|
||||
- **N8. `cell()` escapes `|` but not `\`.** Piece text `a\| done | x`
|
||||
renders so that `marked` splits it into an extra cell. Raw HTML passes
|
||||
through too.
|
||||
- The change: refuse `\` and `<` in rendered text fields at the CLI and
|
||||
in replay. A refusal holds up better than an escape we would have to
|
||||
get right for every Markdown renderer. None of the 34 table lines in
|
||||
today's QUEUE.md contains either character, so the migration loses
|
||||
nothing.
|
||||
- The test: every text field with `\`, `<` and `a\| done | x` is
|
||||
refused. A render of the allowed characters splits, by GFM's cell
|
||||
rule, into the same number of cells on every row. `marked` is only a
|
||||
transitive dependency in this repo, so the test doesn't import it.
|
||||
- The mutation: allow `\`, and the cell-count test must fail.
|
||||
- **N11. Replay is looser than the CLI on op ids.** `LOG_OP_RE` allows 80
|
||||
characters for any entry, `accept-history` may end in `.outcome`, and
|
||||
the genesis op isn't checked.
|
||||
- The change: replay applies `CALLER_OP_RE` to every op a caller chose.
|
||||
It allows the longer form only for the op ids the CLI derives. It
|
||||
refuses `.outcome` on `accept-history` and pattern-checks the genesis
|
||||
op.
|
||||
- The test: a hand-built file with each of the three refused shapes
|
||||
fails replay, and every op id the CLI writes still replays.
|
||||
- The mutations: restore each looser check in turn.
|
||||
|
||||
## Dispositions of the other notes
|
||||
|
||||
| Note | Disposition | Reason |
|
||||
|---|---|---|
|
||||
| N5 tmpfs accepted outside tests; `0xef53` also matches ext2 and ext3 | A2: tmpfs becomes a test-only option, like the other fault options. ext2 and ext3: won't do | `statfs` can't tell ext2, ext3 and ext4 apart. The README names ext4, and the canonical checkout is ext4. |
|
||||
| N7 temp files from killed acquires stay in `.git/` | A2: README line only | The files are small, carry the dead pid in their name, and never block a lock. Removing them safely needs the same liveness check `unlock` has, which isn't worth it for the space involved. |
|
||||
| N10 `set issues` resets `closes`, undoing a logged narrowing | A2: fix with a test | It changes replayed state, so it lands before genesis. New rule: `closes` becomes the new issues only if it equalled the old issues. Otherwise it keeps its intersection with the new issues, and the log entry says so. |
|
||||
| N12 `--by` silently overrides `MOSAIC_AGENT_NAME` | A2: stderr warning, no log field | Both values are self-asserted (J2), so a logged mismatch proves nothing a seat can't avoid. A warning catches the honest mistake, a typo or the wrong seat's shell. |
|
||||
| N15 `--install-hook --by` is self-asserted | Won't do | J2. It's protocol: Sage runs the install at bootstrap. A check on a claimed name adds nothing. |
|
||||
| N16 the hook refuses the first commit on an unborn HEAD | Won't do | The hook is installed only in the canonical checkout, which has history. It fails closed. |
|
||||
|
||||
Sage confirmed this file as written (773dbd75) on 2026-09-26. N5, N10 and
|
||||
N12 stay in A2. N10 has to land before genesis because it changes replayed
|
||||
state.
|
||||
|
||||
## From Filbert's r1 approval
|
||||
|
||||
Filbert approved A1 r1 and N13 on 2026-09-26 (review
|
||||
`agents/filbert/work/queue-a1-review-r1-2026-09-26.md`, sha256 e464be6c).
|
||||
He listed these as non-blocking and suitable for A2. The dispositions
|
||||
below are my proposal, and Sage rules on them.
|
||||
|
||||
| Note | Proposed disposition | Reason |
|
||||
|---|---|---|
|
||||
| P1 `acquire` calls `release()` unguarded on both gate paths | A2: fix with a test | If release throws (EACCES on `.git`), the CLI prints a stack trace and doesn't say the lock stayed. The fix guards it the way `withLock` does and names the lock left behind. |
|
||||
| P2 `--issue` on a later round overwrites `review.issue`; rounds don't record their own issue | A2: each round records its issue, with a test | Piece D posts per round, and the round's own issue is the evidence of where it posted. It changes the round schema and replayed state, so it lands before genesis, like N10. |
|
||||
| P3 `unlock` splits its result on newlines, so a hand-formatted record spills onto stderr | A2: fix with a test | `lock.mjs`'s `unlock` returns the result and the warning separately, so nothing is split on text. |
|
||||
| N13-a `n13-check.sh` copies the suites from the canonical tree, not from the pinned patch | Won't do | N13 is approved on `n13.patch` and the two suite hashes, and Filbert applied the patch himself. The check script is evidence, not shipped code. |
|
||||
|
||||
N13-b is Sage's: check the canonical working tree against both pins
|
||||
before committing from it.
|
||||
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env node
|
||||
// Usage: node agents/darkwing/work/queue-a2/map-check.mjs [QUEUE.md] [MAP]
|
||||
//
|
||||
// Run before genesis. The map names the QUEUE.md blob it was built from.
|
||||
// This lists every table line that differs from that blob, then every row
|
||||
// whose piece, owner or issues no longer match the map. Reads only; the
|
||||
// one git call is `cat-file`. Exit 0 no drift, 1 drift, 4 usage.
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const top = join(dirname(fileURLToPath(import.meta.url)), "../../../..");
|
||||
const { parseMigrationMap } = await import(join(top, "packages/queue/src/queue.mjs"));
|
||||
|
||||
// Table lines by id: `| N | ...` rows, then the parked table's items
|
||||
// numbered on from the highest row, as the map numbers them.
|
||||
export function tableLines(text) {
|
||||
const out = new Map();
|
||||
const items = [];
|
||||
let parked = false;
|
||||
for (const line of text.split("\n")) {
|
||||
if (line.startsWith("## ")) parked = line.startsWith("## Parked");
|
||||
const m = /^\| (\d+) \|/.exec(line);
|
||||
if (m && !parked) out.set(Number(m[1]), line);
|
||||
else if (parked && line.startsWith("| ") && !line.startsWith("| Item ") && !line.startsWith("|---")) items.push(line);
|
||||
}
|
||||
let next = Math.max(0, ...out.keys()) + 1;
|
||||
for (const line of items) out.set(next++, line);
|
||||
return out;
|
||||
}
|
||||
|
||||
const cells = (line) => line.slice(2, -2).split(" | ");
|
||||
|
||||
export function check(queueText, mapText, oldText) {
|
||||
const drift = [];
|
||||
const now = tableLines(queueText);
|
||||
const then = tableLines(oldText);
|
||||
for (const id of new Set([...now.keys(), ...then.keys()])) {
|
||||
if (now.get(id) !== then.get(id)) drift.push(`row ${id}: ${!then.has(id) ? "added" : !now.has(id) ? "removed" : "changed"} since the map's QUEUE.md blob`);
|
||||
}
|
||||
const map = parseMigrationMap(mapText);
|
||||
const byId = new Map(map.rows.map((r) => [r.id, r]));
|
||||
for (const [id, line] of now) {
|
||||
const r = byId.get(id);
|
||||
if (!r) { drift.push(`row ${id}: in QUEUE.md, not in the map`); continue; }
|
||||
const c = cells(line);
|
||||
if (!/^\d+$/.test(c[0])) {
|
||||
if (c[0] !== r.piece) drift.push(`row ${id}: parked item ${JSON.stringify(c[0])} is not the map's piece`);
|
||||
continue;
|
||||
}
|
||||
if (c[1] !== r.piece) drift.push(`row ${id}: piece differs from the map`);
|
||||
const owner = /^[a-z][a-z0-9-]*/.exec(c[2])?.[0];
|
||||
if (owner !== r.owner) drift.push(`row ${id}: owner ${owner} in QUEUE.md, ${r.owner} in the map`);
|
||||
const issues = [...c[3].matchAll(/#(\d+)/g)].map((x) => Number(x[1]));
|
||||
if (issues.join() !== r.issues.join()) drift.push(`row ${id}: issues ${issues.join(",") || "none"} in QUEUE.md, ${r.issues.join(",") || "none"} in the map`);
|
||||
}
|
||||
for (const id of byId.keys()) if (!now.has(id)) drift.push(`row ${id}: in the map, not in QUEUE.md`);
|
||||
return drift;
|
||||
}
|
||||
|
||||
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
||||
const args = process.argv.slice(2);
|
||||
if (args.length > 2) {
|
||||
console.error("usage: map-check.mjs [QUEUE.md] [MAP]");
|
||||
process.exit(4);
|
||||
}
|
||||
const queueText = readFileSync(args[0] ?? join(top, "docs/plans/QUEUE.md"), "utf8");
|
||||
const mapText = readFileSync(args[1] ?? join(top, "agents/darkwing/work/queue-migration-map.md"), "utf8");
|
||||
const blob = /QUEUE\.md` blob `([0-9a-f]{40})`/.exec(mapText)?.[1];
|
||||
if (!blob) {
|
||||
console.error("the map names no QUEUE.md blob");
|
||||
process.exit(1);
|
||||
}
|
||||
const oldText = execFileSync("git", ["-C", top, "cat-file", "blob", blob]).toString("utf8");
|
||||
const drift = check(queueText, mapText, oldText);
|
||||
for (const d of drift) console.log(d);
|
||||
console.log(drift.length ? `${drift.length} differences; update the map before genesis` : `ok: QUEUE.md matches the map (blob ${blob.slice(0, 8)})`);
|
||||
process.exit(drift.length ? 1 : 0);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
diff --git a/docs/plans/QUEUE.md b/docs/plans/QUEUE.md
|
||||
index c8e3d34..dd155c6 100644
|
||||
--- a/docs/plans/QUEUE.md
|
||||
+++ b/docs/plans/QUEUE.md
|
||||
@@ -1,29 +1,32 @@
|
||||
# QUEUE — the one task list
|
||||
|
||||
-Read this first. One row per piece. Nobody needs to read the prose plans to
|
||||
-know what is next; the Brief column says which section to open only when you
|
||||
-are the owner of that row.
|
||||
+Read this first. One row per piece. The table between the markers is
|
||||
+rendered from `docs/plans/queue.json`, and `scripts/mosaic queue` is its only
|
||||
+writer. Don't edit the table by hand: `queue verify` and the commit hook
|
||||
+refuse a table that isn't the render. `packages/queue/README.md` has the verbs.
|
||||
|
||||
How to find your next thing:
|
||||
|
||||
-- **Jason**: the first row whose State starts with `Jason:`.
|
||||
-- **A seat**: the first row where Owner is you and State is `in progress`,
|
||||
- `in review` or `briefed`. If there is none, you have nothing; say so on the
|
||||
- board and stop.
|
||||
-- **Sage, project lead** (Jason's ruling 2026-09-26; Darkwing before that): update this table at every gate, before
|
||||
- anything else is written. CURRENT.md is the narrative log; this table wins
|
||||
+- **A seat**: run `scripts/mosaic queue next`. It names the row to resume,
|
||||
+ review or start, or says there is nothing; if nothing, say so on the board
|
||||
+ and stop.
|
||||
+- **Jason**: rows in state `waiting-on-jason`, and parked rows to reopen.
|
||||
+- **Sage, project lead** (Jason's ruling 2026-09-26): changes the queue with
|
||||
+ `scripts/mosaic queue` and commits `queue.json` with QUEUE.md through
|
||||
+ `scripts/queue-commit.sh`. CURRENT.md is the narrative log; the queue wins
|
||||
if they disagree.
|
||||
|
||||
-States: `queued` (no brief yet) → `briefed` (brief written, not started) →
|
||||
-`in progress` → `in review` → `Jason: <what he must do>` → `done`. `parked`
|
||||
-means not before the rows above it and not without Jason's say. `required`
|
||||
-means it cannot be parked or reordered below `queued` rows; only Jason moves it.
|
||||
+States: `queued` (brief exists, not accepted) → `briefed` → `in-progress` →
|
||||
+`in-review` → `waiting-on-jason` → `done`. `blocked` returns to the state it
|
||||
+left. `parked` rows wait for Jason to reopen them. A `required` row can't be
|
||||
+parked, and only Jason clears the flag. `after` names the rows a piece waits
|
||||
+for.
|
||||
|
||||
-Brief locations: "plan page" is `docs/plans/2026-09-12_control-board-mvp.md`.
|
||||
Gaps found while working go to `docs/plans/DEFERRED.md`, not here.
|
||||
|
||||
## Pieces (in order)
|
||||
|
||||
+<!-- mosaic-queue:begin -->
|
||||
Lead: Sage from 2026-09-26 (Jason's ruling); Darkwing is a collaborating seat.
|
||||
Jason is preparing the target for the next phase; until it arrives, the
|
||||
priority below stands.
|
||||
@@ -79,8 +82,13 @@ Gate F or when blocked."
|
||||
| Console features outside the refined session-chat brief, including Fresh creation and model switching | Deferred by WEBUI Q1; required history/control/stop now belong to row 5, not this parked item | `2026-09-13_webui-session-chat.md` |
|
||||
| Open gaps from the MVP work | Fixed only when a gate needs them | DEFERRED.md, "Open" |
|
||||
|
||||
+<!-- mosaic-queue:end -->
|
||||
+
|
||||
## Log of table changes
|
||||
|
||||
+Frozen at genesis. Since then the log in `docs/plans/queue.json` records every
|
||||
+change; the entries below are history.
|
||||
+
|
||||
- 2026-09-13 — created; rows 1 to 8 taken from CURRENT.md, DEFERRED.md and the plan page.
|
||||
- 2026-09-13 — rows 9 to 13 added (#1508): the process itself becomes data with one writer and ledger checks. Jason: "I want this iron-clad." Required, not parked; rule: these rows cannot be moved to parked, only to done.
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
diff --git a/docs/TOOLS.md b/docs/TOOLS.md
|
||||
index 5f993af0..02e0de9e 100644
|
||||
--- a/docs/TOOLS.md
|
||||
+++ b/docs/TOOLS.md
|
||||
@@ -147,6 +147,24 @@ npm-global `mosaic` CLI; run by path. Exit codes: the launch script's own
|
||||
once it runs; before that 1 could not start, 2 invalid config or seat, 4
|
||||
usage. Details and the record's fields: `packages/seat/README.md`.
|
||||
|
||||
+## Work queue (`scripts/mosaic queue`)
|
||||
+
|
||||
+```bash
|
||||
+scripts/mosaic queue list | show ID | next [SEAT]
|
||||
+scripts/mosaic queue add|move|release|assign|note|set ... --op ID [--by NAME]
|
||||
+scripts/mosaic queue verify [--current] | render [--check] | sync | unlock [--check-gate]
|
||||
+scripts/queue-commit.sh -m MSG
|
||||
+```
|
||||
+
|
||||
+`docs/plans/queue.json` holds the rows and an append-only log; the table in
|
||||
+`docs/plans/QUEUE.md` between the `mosaic-queue` markers is rendered from it.
|
||||
+Canonical checkout only. Every change needs an `--op ID` chosen before the
|
||||
+first attempt and reused on retry; only an op whose `ok <op> rev N` receipt
|
||||
+printed is done. The lead commits queue changes with `scripts/queue-commit.sh`;
|
||||
+the pre-commit guard refuses any other commit that stages the two queue files.
|
||||
+Exit codes: `0` ok · `1` failed · `2` invalid or refused · `3` uncertain,
|
||||
+retry the same op · `4` usage. Details: `packages/queue/README.md`.
|
||||
+
|
||||
## Discord connector (`scripts/discord.sh`)
|
||||
|
||||
```bash
|
||||
@@ -0,0 +1,878 @@
|
||||
# Queue migration map (#1508, A2)
|
||||
|
||||
Darkwing, 2026-09-27. This is the reviewed input to `queue genesis --map
|
||||
agents/darkwing/work/queue-migration-map.md`. Genesis reads the one
|
||||
`json queue-map` block at the end. Everything above it is for review.
|
||||
|
||||
Built from `docs/plans/QUEUE.md` blob `c8e3d34e6efcb98070ebf226157ac027811ffa54`
|
||||
(HEAD c9539baa). If a row in QUEUE.md changes before genesis, the map has to
|
||||
change with it. `queue-a2/map-check.mjs` lists the table lines that differ
|
||||
from that blob and any piece or owner that no longer matches.
|
||||
|
||||
## What genesis keeps
|
||||
|
||||
- Rows 1 to 25 keep their ids. The five parked items become rows 26 to 30,
|
||||
in table order, with state `parked`, owner `unassigned` and no issue
|
||||
(plan Q9). `highWater` is 30 and nothing is retired.
|
||||
- The text between the QUEUE.md markers goes into genesis as `legacyView`,
|
||||
byte for byte. That covers every row, the parked table, the start message
|
||||
and the priority paragraph. A shortened note loses nothing, because the
|
||||
full State text is there.
|
||||
- The State column becomes `state` plus `note`. Piece and Gate are copied
|
||||
verbatim. Every text passes A2's rule: no `\` or `<`, piece and gate at
|
||||
most 300 characters, notes at most 500.
|
||||
- Each row has one brief, `{path, anchor}`, and genesis pins the blob. Every
|
||||
anchor occurs once as a heading in HEAD. Done and parked rows keep their
|
||||
briefs; `verify --current` skips them.
|
||||
- `createdAt` comes from the log of table changes. Parked items 1, 2, 3 and 5
|
||||
date from 7c8e530a, the commit that created QUEUE.md (2026-09-13 UTC). Item
|
||||
4 has no evidence before 2026-09-26, so it is `unknown`.
|
||||
- `requiredSince` for rows 9 to 13 is 2026-09-13, the log line that made them
|
||||
required.
|
||||
- `reviewers` holds seats under `agents/` only. A lane named for a fleet seat
|
||||
(`rev-code-02`, `orch-01`) stays in the note.
|
||||
- Genesis gives a claim to each `in-progress`, `in-review` and
|
||||
`waiting-on-jason` row: 5, 7, 9, 11 and 16.
|
||||
|
||||
## Choices Sage should check
|
||||
|
||||
1. **Row 7 stays a row.** Plan Q9 retired it, but lead decision 27 made it
|
||||
Sage's weekly ledger run, with `packages/ledger/README.md` as its brief.
|
||||
The map keeps it as `in-progress` with Sage's claim, so `queue next sage`
|
||||
resumes it and Sage records the weekly number with `queue note 7`.
|
||||
Retiring it would instead need `retired: [7]` and a pointer line under
|
||||
the markers.
|
||||
2. **Row 10 keeps owner `coordinator`.** No seat can act as `coordinator`,
|
||||
so only Jason or Sage can move the row, and its work edits AGENTS.md,
|
||||
which is Sage's. I recommend `queue assign 10 sage` as the first
|
||||
operation after genesis, so the change is logged instead of hidden in
|
||||
the migration.
|
||||
3. **Rows 10, 12 and 13 have no `after`.** QUEUE.md says "after row 9", but
|
||||
row 9 stays open until Gate G, and Gate G also verifies row 10, so `after:
|
||||
9 done` would hold row 10 behind a gate that needs it. A's code is in place
|
||||
once genesis is committed, and each note says so.
|
||||
4. **Row 11 is `waiting-on-jason`.** QUEUE.md says the `queue add` refusal
|
||||
lands with A2. It landed in A1: `add` runs the same brief check genesis
|
||||
does. Only the gate is left, and the gate is Jason's.
|
||||
5. **Gate owners.** Jason holds every gate except rows 12 and 13, which the
|
||||
map gives to Sage. Both are checks the lead can see: a review round with
|
||||
no new file under `reviews/`, and the ledger run Sage does each Monday.
|
||||
With Sage as gate owner, J5 lets `in-review` → `done` happen without
|
||||
Jason.
|
||||
6. **Row 16 stays open, as `waiting-on-jason`.** Its State doesn't say done.
|
||||
Lead decision 29's "rows 14 to 25 are done" sits in the #1509 paragraph,
|
||||
and row 16 is #1510. If #1510 is closed, change the row to `done` before
|
||||
the map is committed.
|
||||
7. **`closes`.** Rows 9 to 12 close nothing and row 13 closes #1508, so piece
|
||||
E won't report #1508 open under a done row 9. This is J6's narrowing, and
|
||||
this line is its reason. Every other row closes its issues.
|
||||
8. **Row 5's note** matches QUEUE.md at c9539baa: the CHAT-03 brief is
|
||||
pinned, and Sage names the source author after A2 lands. When the row
|
||||
changes before genesis, the note changes with it.
|
||||
|
||||
## Row by row
|
||||
|
||||
| # | State | Owner; reviewers | Issues | Required | After | Gate owner | Created | Why |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| 1 | done | darkwing | #1503 | no | none | jason | 2026-09-13 | Done per lead decision 29. |
|
||||
| 2 | done | darkwing | #1504 | no | none | jason | 2026-09-13 | Brief: the plan page's Step 3. |
|
||||
| 3 | done | darkwing | #1505 | no | none | jason | 2026-09-13 | |
|
||||
| 4 | done | darkwing | #1506 | no | none | jason | 2026-09-13 | |
|
||||
| 5 | in-progress | dewey; filbert, rocko | #1507 | no | none | jason | 2026-09-13 | Rocko added as reviewer (adversarial lane). The note is shortened; the full State text is in `legacyView`. |
|
||||
| 6 | done | darkwing; dewey | #1511, #1512 | no | none | jason | 2026-09-13 | Done per lead decision 29. One brief per row, so the plan page's Piece 5; the other two briefs are named in the note. Dewey is the reviewer; Filbert authored the pilot. |
|
||||
| 7 | in-progress | sage | none | no | none | jason | 2026-09-13 | Kept as a live row, not retired (see question 1). Recurring, so `in-progress` with Sage's claim. |
|
||||
| 8 | parked | unassigned | none | no | none | jason | 2026-09-13 | Brief: Sage's stub (J9). |
|
||||
| 9 | in-progress | darkwing; filbert | #1508; closes none | yes, 2026-09-13 | none | jason | 2026-09-13 | No `after`: lead decision 29 took the wait on row 6 off rows 9 to 13. The note is written as of genesis. |
|
||||
| 10 | briefed | coordinator | #1508; closes none | yes, 2026-09-13 | none | jason | 2026-09-13 | Owner kept as `coordinator` (see question 2). No `after`: see question 3. |
|
||||
| 11 | waiting-on-jason | darkwing | #1508; closes none | yes, 2026-09-13 | none | jason | 2026-09-13 | Both parts are in A1 already, so only the gate is left (see question 4). |
|
||||
| 12 | briefed | darkwing | #1508; closes none | yes, 2026-09-13 | none | sage | 2026-09-13 | Gate owner `sage` (see question 5). |
|
||||
| 13 | briefed | darkwing; filbert | #1508 | yes, 2026-09-13 | none | sage | 2026-09-13 | Closes #1508; rows 9 to 12 close nothing. Gate owner `sage` (question 5). |
|
||||
| 14 | done | coordinator; filbert | #1509 | no | none | jason | 2026-09-13 | Reviewer lane named Filbert or orch-01; Filbert kept, orch-01 isn't a seat under `agents/`. |
|
||||
| 15 | done | coordinator | #1509 | no | none | jason | 2026-09-13 | |
|
||||
| 16 | waiting-on-jason | darkwing; filbert | #1510 | no | none | jason | 2026-09-13 | Kept open as `waiting-on-jason` (see question 6). |
|
||||
| 17 | done | coordinator | #1509 | no | none | jason | 2026-09-13 | |
|
||||
| 18 | done | darkwing | #1509 | no | none | jason | 2026-09-13 | The note keeps the coordinator's part. |
|
||||
| 19 | done | coordinator | #1509 | no | none | jason | 2026-09-13 | |
|
||||
| 20 | done | coordinator | #1509 | no | none | jason | 2026-09-13 | Done: lead decision 29 closed #1509 with rows 14 to 25 done. |
|
||||
| 21 | done | coordinator | #1509 | no | none | jason | 2026-09-14 | Done: lead decision 29. `rev-code-02` isn't a seat under `agents/`, so no reviewer. |
|
||||
| 22 | done | darkwing; filbert | #1503 | no | none | jason | 2026-09-14 | Done: #1503 closed (lead decision 29). |
|
||||
| 23 | done | coordinator | #1509 | no | none | jason | 2026-09-16 | Done per lead decision 29. |
|
||||
| 24 | done | coordinator | #1509 | no | none | jason | 2026-09-16 | Done per lead decision 29. |
|
||||
| 25 | done | coordinator | #1509 | no | none | jason | 2026-09-20 | Done per lead decision 29. |
|
||||
| 26 | parked | unassigned | none | no | none | jason | 2026-09-13 | Parked item 1. |
|
||||
| 27 | parked | unassigned | none | no | none | jason | 2026-09-13 | Parked item 2. |
|
||||
| 28 | parked | unassigned | none | no | none | jason | 2026-09-13 | Parked item 3. |
|
||||
| 29 | parked | unassigned | none | no | none | jason | unknown | Parked item 4. First committed 2026-09-26 (0f5b7cb9); no earlier evidence, so `unknown`. |
|
||||
| 30 | parked | unassigned | none | no | none | jason | 2026-09-13 | Parked item 5. |
|
||||
|
||||
## Map
|
||||
|
||||
```json queue-map
|
||||
{
|
||||
"rows": [
|
||||
{
|
||||
"id": 1,
|
||||
"piece": "Control board MVP (scanner + page)",
|
||||
"owner": "darkwing",
|
||||
"issues": [
|
||||
1503
|
||||
],
|
||||
"closes": [
|
||||
1503
|
||||
],
|
||||
"state": "done",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "A passed 2026-09-12",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-12_control-board-mvp.md",
|
||||
"anchor": "Control board MVP — plan"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "done 2026-09-27 (Sage, lead decision 29): D-001 MVP delivered, Gate A passed 2026-09-12, attention status operator-accepted (row 22), relaunch activity, attribution and Host guard landed; #1503 closed; cross-harness board work belongs to Gate E (row 5)",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"piece": "Seat registration and `mosaic seat task`",
|
||||
"owner": "darkwing",
|
||||
"issues": [
|
||||
1504
|
||||
],
|
||||
"closes": [
|
||||
1504
|
||||
],
|
||||
"state": "done",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "B passed 2026-09-12",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-12_control-board-mvp.md",
|
||||
"anchor": "Step 3: daily use and fixes"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "done 2026-09-13",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"piece": "Reply-from-board (piece 2 on the plan page)",
|
||||
"owner": "darkwing",
|
||||
"issues": [
|
||||
1505
|
||||
],
|
||||
"closes": [
|
||||
1505
|
||||
],
|
||||
"state": "done",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "C passed 2026-09-12",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-12_control-board-mvp.md",
|
||||
"anchor": "Piece 2: reply-from-board"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "done 2026-09-12",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"piece": "Ledger (piece 3 on the plan page)",
|
||||
"owner": "darkwing",
|
||||
"issues": [
|
||||
1506
|
||||
],
|
||||
"closes": [
|
||||
1506
|
||||
],
|
||||
"state": "done",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "D: 18.9 human messages per closed issue, week of 2026-09-06",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-12_control-board-mvp.md",
|
||||
"anchor": "Piece 3: ledger (numbers for the rails)"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "done 2026-09-13",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"piece": "WebUI first screen on the Console design (piece 4 on the plan page)",
|
||||
"owner": "dewey",
|
||||
"issues": [
|
||||
1507
|
||||
],
|
||||
"closes": [
|
||||
1507
|
||||
],
|
||||
"state": "in-progress",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "E: all-seat interactive demonstration then Jason workday ruling; live cutover separately approved",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-13_webui-session-chat.md",
|
||||
"anchor": "WebUI session chat: refined brief and delivery plan"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [
|
||||
"filbert",
|
||||
"rocko"
|
||||
],
|
||||
"note": "CHAT-00/01/01C published (370823b3, 28d4e98a, b023841c); CHAT-02 done: backend a5beb6d9, Console c9e771cf, live check passed 2026-09-26; CHAT-03 brief approved and pinned 2026-09-27 (BRIEF.md 1ef15ac0, rescoped to Gate E, lead decisions 30 to 33; Filbert r3 approve, Rocko blocker closed, Filbert scope check pass); source author named by Sage after queue A2 lands; CHAT-04..08 not chartered; Gate E blocked",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"piece": "Darkwing on point: darkwing assigns and gates filbert's work (piece 5 on the plan page)",
|
||||
"owner": "darkwing",
|
||||
"issues": [
|
||||
1511,
|
||||
1512
|
||||
],
|
||||
"closes": [
|
||||
1511,
|
||||
1512
|
||||
],
|
||||
"state": "done",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "F: filbert's item closes with zero human messages from Jason; code phase does not claim Gate F",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-12_control-board-mvp.md",
|
||||
"anchor": "Piece 5: darkwing on point (orchestrator behaviour)"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [
|
||||
"dewey"
|
||||
],
|
||||
"note": "done 2026-09-27 (lead decision 29): #1511 and #1512 landed in af4203ca (pushed), closed; Gate F not passed (2 human messages in filbert's T3 thread; the first 11 days predate the T3 source); Gate G (row 9) carries the test. Filbert authored the pilot. Briefs also: 2026-09-15_relaunch-activity.md, 2026-09-14_task-attribution.md",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"piece": "Weekly ledger run and rails number",
|
||||
"owner": "sage",
|
||||
"issues": [],
|
||||
"closes": [],
|
||||
"state": "in-progress",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "under 10 human messages per closed issue for the week of 2026-09-13",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "packages/ledger/README.md",
|
||||
"anchor": "Ledger"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "recurring, every Monday (lead decision 27); Jason reads; 09-13..19: 47.7, 09-20..26: 33.0 human messages per closed issue",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"piece": "Fleet seats (`~/.mosaic`) onto `mosaic launch`",
|
||||
"owner": "unassigned",
|
||||
"issues": [],
|
||||
"closes": [],
|
||||
"state": "parked",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "Jason's call",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-26_fleet-seats-onto-mosaic-launch.md",
|
||||
"anchor": "Row 8: fleet seats onto `mosaic launch` (stub brief)"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "parked by current owner direction; no `~/.mosaic` changes during internal bootstrap",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"piece": "Queue as data: `docs/plans/queue.json`, `mosaic queue` is the only writer",
|
||||
"owner": "darkwing",
|
||||
"issues": [
|
||||
1508
|
||||
],
|
||||
"closes": [],
|
||||
"state": "in-progress",
|
||||
"previousState": null,
|
||||
"required": true,
|
||||
"requiredSince": "2026-09-13",
|
||||
"gate": "G: a fresh seat told only \"run `mosaic queue next` and do it\" starts its piece with zero human messages",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-13_queue-as-data.md",
|
||||
"anchor": "Piece A: queue record and `mosaic queue` (QUEUE row 9)"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [
|
||||
"filbert"
|
||||
],
|
||||
"note": "A1 (journal, lock, CLI, verify) committed 34a72af9; A2 (migration, render, dispatch) committed with this map; Filbert approved both; genesis and hook install by Sage; Gate G also verifies row 10",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"piece": "Seats read the queue, not CURRENT.md (AGENTS.md cadence, seat context files)",
|
||||
"owner": "coordinator",
|
||||
"issues": [
|
||||
1508
|
||||
],
|
||||
"closes": [],
|
||||
"state": "briefed",
|
||||
"previousState": null,
|
||||
"required": true,
|
||||
"requiredSince": "2026-09-13",
|
||||
"gate": "verified by Gate G",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-13_queue-as-data.md",
|
||||
"anchor": "Piece B: seats read the queue, not CURRENT.md (QUEUE row 10)"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "AGENTS.md lines done 2026-09-13; the rest starts once genesis is committed",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"piece": "Brief template `docs/plans/BRIEF-TEMPLATE.md`; `queue add` refuses a missing brief",
|
||||
"owner": "darkwing",
|
||||
"issues": [
|
||||
1508
|
||||
],
|
||||
"closes": [],
|
||||
"state": "waiting-on-jason",
|
||||
"previousState": null,
|
||||
"required": true,
|
||||
"requiredSince": "2026-09-13",
|
||||
"gate": "two briefs accepted by Jason with no scope question",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-13_queue-as-data.md",
|
||||
"anchor": "Piece C: brief template (QUEUE row 11)"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "template and the `queue add` brief refusal both committed with A1 (34a72af9); the gate counts the first briefs added through the queue",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"piece": "Reviews as issue comments posted by `queue move ID in-review`, not files in `docs/plans/reviews/`",
|
||||
"owner": "darkwing",
|
||||
"issues": [
|
||||
1508
|
||||
],
|
||||
"closes": [],
|
||||
"state": "briefed",
|
||||
"previousState": null,
|
||||
"required": true,
|
||||
"requiredSince": "2026-09-13",
|
||||
"gate": "one review round with no new file under reviews/",
|
||||
"gateOwner": "sage",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-13_queue-as-data.md",
|
||||
"anchor": "Piece D: reviews through a channel, not files (QUEUE row 12)"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "starts once genesis is committed; the live posting test needs the per-seat credential file (8.9)",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"piece": "Ledger \"queue\" section: issue/row/seat drift printed with the weekly number",
|
||||
"owner": "darkwing",
|
||||
"issues": [
|
||||
1508
|
||||
],
|
||||
"closes": [
|
||||
1508
|
||||
],
|
||||
"state": "briefed",
|
||||
"previousState": null,
|
||||
"required": true,
|
||||
"requiredSince": "2026-09-13",
|
||||
"gate": "first run Monday 2026-09-21, zero violations or every one moved same day",
|
||||
"gateOwner": "sage",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-13_queue-as-data.md",
|
||||
"anchor": "Piece E: ledger checks the queue (QUEUE row 13)"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [
|
||||
"filbert"
|
||||
],
|
||||
"note": "starts once genesis is committed; closes #1508 when done, so rows 9 to 12 close nothing; first run is the Monday after E is approved (Q7)",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"piece": "Discord connector pilot: Sage answers in Shared Signals (chat only, no tools, no repo writes)",
|
||||
"owner": "coordinator",
|
||||
"issues": [
|
||||
1509
|
||||
],
|
||||
"closes": [
|
||||
1509
|
||||
],
|
||||
"state": "done",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "H: offline suite green, eight-step live pilot with private receipts, then Jason says the reply reads as Sage",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-13_discord-connector-pilot.md",
|
||||
"anchor": "Discord connector pilot: Sage on Shared Signals"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [
|
||||
"filbert"
|
||||
],
|
||||
"note": "done: rev-code-02 APPROVE 26170 (round 9), committed 786e379c; pilot steps 1-8 done with private receipts, Gate H passed (Jason, 2026-09-13: replies read as Sage); connector left running for MVP iteration; reviewer lane was Filbert or orch-01",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"piece": "Discord connector: eyes reaction on every admitted message as a read receipt (MVP iteration 1)",
|
||||
"owner": "coordinator",
|
||||
"issues": [
|
||||
1509
|
||||
],
|
||||
"closes": [
|
||||
1509
|
||||
],
|
||||
"state": "done",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "Jason sees the reaction on a live message",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-13_discord-connector-pilot.md",
|
||||
"anchor": "11. MVP iteration, after the pilot"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "done: committed 93d6b624, live check passed 19:21 UTC (turn record receipt ok, Jason: test is successful), receipt `mvp1-read-receipt-20260913T192158Z.json` in the private evidence dir; reaction placed at admission before the engine runs, outcome in the turn record, none on drops or refusals; `scripts/test-discord.sh` 28/28 (90 node tests)",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"piece": "Repository-native development bootstrap: five internal agents, Darkwing coordination",
|
||||
"owner": "darkwing",
|
||||
"issues": [
|
||||
1510
|
||||
],
|
||||
"closes": [
|
||||
1510
|
||||
],
|
||||
"state": "waiting-on-jason",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "source approved; Researcher live response passed 26216; existing native Rocko lock preserved, no new Rocko model test; no MVP acceptance/publication",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-13_internal-development-bootstrap.md",
|
||||
"anchor": "Repository-native development bootstrap"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [
|
||||
"filbert"
|
||||
],
|
||||
"note": "source approved by internal Filbert, exact R1 receipt 26204; six offline tests independently pass in both copies; 24 config tests and five no-effect checks are author evidence",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"piece": "Discord connector: systemd user service with a supervised pre-start (`recover`, exit 3 never retried) (MVP iteration 2)",
|
||||
"owner": "coordinator",
|
||||
"issues": [
|
||||
1509
|
||||
],
|
||||
"closes": [
|
||||
1509
|
||||
],
|
||||
"state": "done",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "the Sage connector runs under `mosaic-discord@shared-signals`, survives a kill with a clean restart, and stays down behind `discord.sh stop`",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-13_discord-connector-pilot.md",
|
||||
"anchor": "11. MVP iteration, after the pilot"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "done, operator-verified by Jason 2026-09-13 (all four steps): suite 40/40 (95 node tests); Sage seat migrated 19:35 UTC, SIGKILL recovered in 16 s with the dead lock cleared, brake held (exit 3, no restart), released and READY; receipt `mvp2-service-unit-*.json` in the private evidence dir; the first cut (ExecStartPre) looped and was replaced by `run --supervised` before any traffic",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 18,
|
||||
"piece": "Control board row for the Discord connector (MVP iteration 3): discovery from binding files, liveness from run.lock, reply refused",
|
||||
"owner": "darkwing",
|
||||
"issues": [
|
||||
1509
|
||||
],
|
||||
"closes": [
|
||||
1509
|
||||
],
|
||||
"state": "done",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "a Sage (discord) row on the board shows live, offline and braked correctly, and reply from the board is refused",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-14_discord-board-row.md",
|
||||
"anchor": "Discord connector board row"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "done for bounded local delivery; Jason accepted visual test (parfait), R3 26257 reviewed, 322 tests and live 409 refusal verified; owner by Jason's ruling 2026-09-13, coordinator answered connector-side questions; also briefed in the pilot page section 11",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 19,
|
||||
"piece": "Discord connector: binding reload without a restart (`reload` verb, SIGHUP, `systemctl --user reload`); channels, users, limits and guildName apply in place, identity, engine and context stay fixed, an invalid file is refused and the old binding kept (MVP iteration 4)",
|
||||
"owner": "coordinator",
|
||||
"issues": [
|
||||
1509
|
||||
],
|
||||
"closes": [
|
||||
1509
|
||||
],
|
||||
"state": "done",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "edit the binding, run `scripts/discord.sh reload shared-signals`, the change applies with no restart, a broken edit is refused and journaled",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-13_discord-connector-pilot.md",
|
||||
"anchor": "11. MVP iteration, after the pilot"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "done: caaef941; live 00:03 UTC: reload applied Carmen's entry with no restart, unknown key refused by the CLI (exit 2), fixed key refused in the process with the binding kept, `systemctl --user reload` applied; suite 41/41 (101 node tests); receipt `mvp4-5-reload-carmen-*.json`",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"piece": "Discord connector: per-user channel allowlist in the binding and Carmen enrolled (all listed rooms except #sage-admin) (MVP iteration 5)",
|
||||
"owner": "coordinator",
|
||||
"issues": [
|
||||
1509
|
||||
],
|
||||
"closes": [
|
||||
1509
|
||||
],
|
||||
"state": "done",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "Carmen gets a reply in #general and silence in #sage-admin; Jason unchanged",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-13_discord-connector-pilot.md",
|
||||
"anchor": "11. MVP iteration, after the pilot"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "done: caaef941 (`users[].channels` allowlist, `channel-not-for-user` drop); Carmen enrolled live by reload 00:03 UTC; her first message was the remaining check; #1509 closed with rows 14 to 25 done (lead decision 29)",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"piece": "Discord connector: read-only tools for the Discord Sage through a Mosaic pi extension confined to declared roots (MVP iteration 6)",
|
||||
"owner": "coordinator",
|
||||
"issues": [
|
||||
1509
|
||||
],
|
||||
"closes": [
|
||||
1509
|
||||
],
|
||||
"state": "done",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "Sage answers a question from a file under a declared root with the reads in the turn record; a read outside the roots is refused and recorded",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-14_discord-readonly-tools.md",
|
||||
"anchor": "Discord Sage: read-only tools (iteration 6)"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "approved: rev-code-02 round 2 verdict 26276 (tree 43f0329b), committed; Jason ruled R1–R7 2026-09-14 (roots docs/ and agents/sage/, Carmen included); done with rows 14 to 25 when #1509 closed (lead decision 29); reviewer per Q12",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-14"
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"piece": "Board attention status: completed replies idle, explicit human input waiting",
|
||||
"owner": "darkwing",
|
||||
"issues": [
|
||||
1503
|
||||
],
|
||||
"closes": [
|
||||
1503
|
||||
],
|
||||
"state": "done",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "operator accepted full targeted status sequence: explicit request waiting, Seen hides attention but preserves waiting, completion returns idle; broader MVP/cross-harness acceptance and publication separate",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-13_board-attention-status.md",
|
||||
"anchor": "Board attention status correction"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [
|
||||
"filbert"
|
||||
],
|
||||
"note": "source approved, receipt 26248; reviewer 193 per copy, author union 213 pass; actual Researcher scan idle; operator accepted (row 1); #1503 closed (lead decision 29)",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-14"
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"piece": "Discord connector: writes confined to the `shared-signals` root plus web fetch and search for the Discord Sage (MVP iteration 7)",
|
||||
"owner": "coordinator",
|
||||
"issues": [
|
||||
1509
|
||||
],
|
||||
"closes": [
|
||||
1509
|
||||
],
|
||||
"state": "done",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "Sage writes a naming shortlist into the repository from #ideas with the write and web calls in the turn record; a write outside the root is refused",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-16_discord-write-and-web-tools.md",
|
||||
"anchor": "Discord Sage: writes into the strategy repository, and web research (#1509, QUEUE row 23)"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "done 2026-09-27 (Sage, lead decision 29): committed and pushed 1685deb4; live turns wrote `vault/Businesses/naming.md` with web_search and web_fetch in the turn record; the outside-root refusal rests on the offline suite, not a live turn; reviewer per Q12",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-16"
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"piece": "Discord connector: git verbs (status, commit, pull ff-only, push) for the Discord Sage on the `shared-signals` root, seat identity through the existing credential helper (MVP iteration 8)",
|
||||
"owner": "coordinator",
|
||||
"issues": [
|
||||
1509
|
||||
],
|
||||
"closes": [
|
||||
1509
|
||||
],
|
||||
"state": "done",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "Sage commits and pushes a decision file from #ideas; GitHub shows Sage as author with a Requested-by trailer; no token in any record",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-16_discord-git-tools.md",
|
||||
"anchor": "Discord Sage: git for the strategy repository (#1509, QUEUE row 24)"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "done 2026-09-27 (Sage, lead decision 29): committed and pushed 1949ed8d; live-configured 2026-09-18, never used from Discord; records now go through row 25 and SetSpark cutover freezes `vault/`, so first real use is the check and a failure opens a new issue; reviewer per Q12",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-16"
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"piece": "Discord connector: SetSpark record client for the Discord Sage, fixed verbs against setspark-api, connector-verified approvals (MVP iteration 9)",
|
||||
"owner": "coordinator",
|
||||
"issues": [
|
||||
1509
|
||||
],
|
||||
"closes": [
|
||||
1509
|
||||
],
|
||||
"state": "done",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "Sage creates one work item from #sage-admin and the API shows it with revision 1; a proposal is approved by the Approve button and the audit row carries Sage's key id and Jason's Discord id separately; rev-code-02 approves on #1509",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-20_discord-setspark-client.md",
|
||||
"anchor": "Discord Sage: SetSpark record client (#1509, QUEUE row 25)"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "done 2026-09-26: committed and pushed 43d7574d, live check passed (DEC-010, request 2, approved by button at 21:38:58Z, lead decision 19); approver rule enforced by the service since shared-signals cc74d92 (lead decisions 24 and 28); reviewer per Q12",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-20"
|
||||
},
|
||||
{
|
||||
"id": 26,
|
||||
"piece": "Registry increment 3 (headless identity-env leak)",
|
||||
"owner": "unassigned",
|
||||
"issues": [],
|
||||
"closes": [],
|
||||
"state": "parked",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "Jason reopens",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/CURRENT.md",
|
||||
"anchor": "Completed checkpoint: #1500 increment 2 (historical)"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "#1500 closed on increment 2; Jason has not asked for 3",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 27,
|
||||
"piece": "Auth/provider/harness registry review",
|
||||
"owner": "unassigned",
|
||||
"issues": [],
|
||||
"closes": [],
|
||||
"state": "parked",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "Jason reopens",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-03_auth-provider-harness-registry.md",
|
||||
"anchor": "Harness declaration + centralized auth/provider registry"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "Paused for owner alignment",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 28,
|
||||
"piece": "CI runners, second real adapter, push automation",
|
||||
"owner": "unassigned",
|
||||
"issues": [],
|
||||
"closes": [],
|
||||
"state": "parked",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "Jason reopens",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/ROADMAP.md",
|
||||
"anchor": "Explicitly deferred"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "Deferred by owner 2026-09-03",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
},
|
||||
{
|
||||
"id": 29,
|
||||
"piece": "Console features outside the refined session-chat brief, including Fresh creation and model switching",
|
||||
"owner": "unassigned",
|
||||
"issues": [],
|
||||
"closes": [],
|
||||
"state": "parked",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "Jason reopens",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/2026-09-13_webui-session-chat.md",
|
||||
"anchor": "WebUI session chat: refined brief and delivery plan"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "Deferred by WEBUI Q1; required history/control/stop now belong to row 5, not this parked item",
|
||||
"blockedReason": null,
|
||||
"createdAt": "unknown"
|
||||
},
|
||||
{
|
||||
"id": 30,
|
||||
"piece": "Open gaps from the MVP work",
|
||||
"owner": "unassigned",
|
||||
"issues": [],
|
||||
"closes": [],
|
||||
"state": "parked",
|
||||
"previousState": null,
|
||||
"required": false,
|
||||
"requiredSince": null,
|
||||
"gate": "Jason reopens",
|
||||
"gateOwner": "jason",
|
||||
"brief": {
|
||||
"path": "docs/plans/DEFERRED.md",
|
||||
"anchor": "Open"
|
||||
},
|
||||
"after": [],
|
||||
"reviewers": [],
|
||||
"note": "Fixed only when a gate needs them",
|
||||
"blockedReason": null,
|
||||
"createdAt": "2026-09-13"
|
||||
}
|
||||
],
|
||||
"retired": [],
|
||||
"highWater": 30
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user