From c974cafa4f12e5e7caa828c15267f36586a35572 Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Mon, 12 Oct 2026 18:40:27 -0500 Subject: [PATCH] logs, vikunja-setup: row 69 landed, follow-up filed as Vikunja #243 (#1562) Co-Authored-By: Claude Opus 5.5 --- BUILD-LOG.md | 6 ++ .../2026-10-12_r69-followup.json | 17 +++++ .../work/vikunja-setup/file-r69-followup.mjs | 66 +++++++++++++++++++ docs/SESSIONS.md | 1 + 4 files changed, 90 insertions(+) create mode 100644 agents/sage/work/vikunja-setup/2026-10-12_r69-followup.json create mode 100644 agents/sage/work/vikunja-setup/file-r69-followup.mjs diff --git a/BUILD-LOG.md b/BUILD-LOG.md index bd9981097..7d7b79b18 100644 --- a/BUILD-LOG.md +++ b/BUILD-LOG.md @@ -4468,3 +4468,9 @@ After (uncommitted patch against dad20531): human/reader messages history with n Before (6bb92d04): task verbs acted only in the root project. A child project's task needed its own checkout's verbs, and the harness `task_create` tool had no way to name a project. After (b8539480): Darkwing's round 2 candidate, manifest 2a22fd3f, six paths under `packages/tasks/` and `packages/harness/`. Verbs act in any installed project of the tree; a project the tree doesn't hold refuses `task-project` as before, and a watch-only one refuses with the new code. `task_create` takes an optional integer `project`. Dewey approved in comment 28024 and Filbert in 28026. Sage's gate on 1117d19b plus the patch ran 23:07:33Z to 23:09:22Z: tasks 84/0, harness 65/0, and every `scripts/test-*.sh` green. No commit since base cca5f23e touched the six paths, and `queue review verify-commit` matched the candidate. Row 63 went to done at rev 838, and #1556 is closed with comment 28035. Mos had the decision-109 notice, because the harness change goes live at the next role session launch. Row 90 rebases on this commit next (decision 125). A correction for the record: 16d5310b's subject says rev 830, but its snapshot was rev 832 and carried Rocko's revs 830 and 831. The commit message of 49e0f990 records the same correction. + +### 2026-10-12 — Sage, row 69 landed: terminal app follow-up (#1562) + +Before (c6711453): the terminal app's narrow-terminal guard had no test, a hidden input box left no way out, and the width cases were untested. + +After (90d7ed66): Darkwing's round 1 candidate, manifest c68e6582, four paths under `packages/cli/`. Dewey approved in comment 28048 and Filbert in 28055. Sage's gate on c6711453 plus the patch ran 23:34:36Z to 23:36:40Z: cli 123/0, queue 150/0, and every `scripts/test-*.sh` green. No commit since base dad20531 touched the four paths, and `queue review verify-commit` matched the candidate. Row 69 went to done at rev 857 (7f0f54ab), and #1562 is closed with comment 28061. Mos had the decision-109 notices before and after; the Console and bus were active with NRestarts 0 and healthz 200 afterwards, and nothing restarted. The help-pointer line and Dewey's two surviving mutant findings are Vikunja #243 (decision 110). A correction for the record: my gate's busy check counted only node and chromium processes, and it passed in a gap between Darkwing's row 91 mutants (23:32:16Z to 23:35:26Z), so the two runs overlapped. Both sets of results stand: mine were green, and Darkwing explained every mutant result. On the strength of that check I also gave Filbert the slot early, and Filbert's row 90 run stopped after tasks when Darkwing's suites started. Filbert reruns row 90 from the start after Darkwing's "slot clear" (23:39:25Z). diff --git a/agents/sage/work/vikunja-setup/2026-10-12_r69-followup.json b/agents/sage/work/vikunja-setup/2026-10-12_r69-followup.json new file mode 100644 index 000000000..d5fcdf87e --- /dev/null +++ b/agents/sage/work/vikunja-setup/2026-10-12_r69-followup.json @@ -0,0 +1,17 @@ +{ + "at": "2026-10-12T23:38:01.305Z", + "project": 19, + "created": [ + { + "title": "Terminal app follow-up from row 69: help pointer, pending-resolve box test, statusStyle", + "id": 243, + "index": 90, + "inverse": "mark done: POST /api/v1/tasks/243 done true (pm); delete is Jason's or ops-01's", + "readBack": 200, + "project_back": 19, + "due_back": "0001-01-01T00:00:00Z", + "done": false + } + ], + "problems": [] +} diff --git a/agents/sage/work/vikunja-setup/file-r69-followup.mjs b/agents/sage/work/vikunja-setup/file-r69-followup.mjs new file mode 100644 index 000000000..87a54ba81 --- /dev/null +++ b/agents/sage/work/vikunja-setup/file-r69-followup.mjs @@ -0,0 +1,66 @@ +// Sage, 2026-10-12: decision 110. Files row 69's non-blocking follow-ups (#1562) as one task in project 19 +// with Sage's own key (bot user 13). Refuses if the title already exists. The sync key reads it back. No +// labels, no assignees, no bucket moves. Rollback is marking the task done; deletion is Jason's or ops-01's. +// Prints no secret. +// Usage: node file-r69-followup.mjs https://tasks.woltje.com SAGE_TOKEN_FILE SYNC_TOKEN_FILE OUT_JSON +import { readFileSync, writeFileSync, existsSync } from "node:fs"; +const [ORIGIN, KEY, SYNC, OUT] = process.argv.slice(2); +if (!/^https:\/\/tasks\.woltje\.com$/.test(ORIGIN)) throw new Error("tasks.woltje.com only"); +if (!OUT || existsSync(OUT)) throw new Error("OUT_JSON missing or exists; refusing"); +const PROJECT = 19; +const SIG = "Created by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13)."; +const esc = (s) => s.replace(/&/g, "&").replace(//g, ">"); +const p = (...xs) => xs.map((x) => `

${esc(x)}

`).join("") + `

${esc(SIG)}

`; +const TASKS = [ + { title: "Terminal app follow-up from row 69: help pointer, pending-resolve box test, statusStyle", + description: p("Non-blocking items left when row 69 landed (90d7ed66, Gitea #1562 comment 28061). All in packages/cli; decision 109's notice to Mos applies before landing.", + "1. The cut help-pointer line (Filbert, #1562 comment 28055).", + "2. No test hides the box while a resolve is pending. Dewey's two surviving mutants (#1562 comment 28048) show it: the status swap and the way-out line each apply only while o.asking, and no test catches either one being dropped.", + "3. Dewey's statusStyle survivor: a warning style changed to muted is not caught.", + "Needs a queue row and a brief section before anyone builds it.") }, +]; +const key = readFileSync(KEY, "utf8").trim(), sync = readFileSync(SYNC, "utf8").trim(); +async function api(method, path, body, auth) { + const r = await fetch(ORIGIN + path, { method, headers: { Authorization: `Bearer ${auth}`, "Content-Type": "application/json" }, body: body === undefined ? undefined : JSON.stringify(body), redirect: "error" }); + const t = await r.text(); let json = null; try { json = JSON.parse(t); } catch {} + return { status: r.status, json }; +} +const list = (j) => j?.items ?? (Array.isArray(j) ? j : []); +async function existing() { + const out = []; + for (let page = 1; page < 20; page++) { + const r = await api("GET", `/api/v2/projects/${PROJECT}/tasks?per_page=50&page=${page}`, undefined, sync); + if (r.status !== 200) throw new Error(`list tasks: ${r.status}`); + out.push(...list(r.json)); + if (list(r.json).length < 50) return out; + } + throw new Error("more than 19 pages"); +} +const rec = { at: new Date().toISOString(), project: PROJECT, created: [], problems: [] }; +const save = () => { + const out = JSON.stringify(rec, null, 1) + "\n"; + if (out.includes(key) || out.includes(sync)) throw new Error("secret in the record; not written"); + writeFileSync(OUT, out); +}; +const before = await existing(); +const clash = before.filter((t) => TASKS.some((x) => x.title === t.title)); +if (clash.length) throw new Error(`exists: ${clash.map((t) => `#${t.id} ${t.title}`).join("; ")}; refusing`); +writeFileSync(OUT, "", { flag: "wx" }); + +for (const t of TASKS) { + rec.created.push({ title: t.title }); + save(); + const body = { title: t.title, description: t.description, ...(t.due ? { due_date: t.due } : {}) }; + const r = await api("PUT", `/api/v1/projects/${PROJECT}/tasks`, body, key); + if (r.status >= 300 || !Number.isSafeInteger(r.json?.id)) { + rec.problems.push(`create ${t.title}: ${r.status} ${r.json?.code ?? ""} ${r.json?.message ?? ""}`); + break; + } + Object.assign(rec.created.at(-1), { id: r.json.id, index: r.json.index, inverse: `mark done: POST /api/v1/tasks/${r.json.id} done true (pm); delete is Jason's or ops-01's` }); + const back = await api("GET", `/api/v2/tasks/${r.json.id}`, undefined, sync); + Object.assign(rec.created.at(-1), { readBack: back.status, project_back: back.json?.project_id, due_back: back.json?.due_date, done: back.json?.done }); + if (back.status !== 200 || back.json?.title !== t.title || back.json?.project_id !== PROJECT || back.json?.done) rec.problems.push(`${t.title} read-back differs`); +} +save(); +process.stdout.write(JSON.stringify(rec, null, 1) + "\n"); +if (rec.problems.length) process.exit(2); diff --git a/docs/SESSIONS.md b/docs/SESSIONS.md index 124395b16..fee11a418 100644 --- a/docs/SESSIONS.md +++ b/docs/SESSIONS.md @@ -820,3 +820,4 @@ are never rewritten or removed; corrections are new entries. 2026-10-12T23:33:05Z | filbert | row 69 (#1562) round 1 review on c68e6582, base dad20531 | approve comment 28055, rev 856 committed 557707c1; cli 123/0, queue 150/0, six named mutants killed, restored-app passed and manifest 4/4; scratch/worktree clear, Darkwing directly notified for row 91 slot; existing cut-help pointer is non-blocking; no push 2026-10-12T23:36:26Z | filbert | row 90 (#1584) round 2 static review on 95611274, base b8539480 | reconstructed 21/21, no drift; rebase edits preserved and decision 127 read-only requirements.mjs bind reviewed, requirements.json remains unmounted; full 8-node/9-shell gate script ready and syntax checked, no tests or verdict yet; hold until Darkwing row 91 and Sage row 69 landing gates clear; no push 2026-10-12T23:38:56Z | filbert | row 90 round 2 gate slot correction | tasks 89/0, guard stopped before bus on active Darkwing row 91 suites; no remaining run active and no verdict; Sage confirmed early clearance and requires full restart on direct row 91 slot-clear; partial receipt preserved, candidate unchanged +2026-10-12T23:40:27Z | sage | row 69 (#1562) landed 90d7ed66, rev 857 7f0f54ab, comment 28061, follow-up Vikunja #243; decision 127 (row 90 round 2 adds sandbox.mjs RUNNER_FILES line); busy-check gap overlapped Darkwing row 91 mutants, recorded in BUILD-LOG | done