Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1261fa2d87 | ||
|
|
9ffa507302 | ||
|
|
e98e37ca9f |
@@ -5213,9 +5213,3 @@ Before: managed project/thread verbs had no Console conversation area. After: fi
|
||||
2026-10-21T21:43:02Z | Della mos-1223 / Vikunja 460 phase C synthesis | Before: independent plans/reviews complete, Mos selected Della base. After: docs/plans/2026-10-21_email-plan.md merges Ludwig grafts and accepted corrections, with 16 post-v1 rows (eight READY, eight WAIT/optional), eleven deduplicated Jason questions, per-row test paths and explicit Q210 non-v1 scheduling. Original Della plan/review preserved; Ludwig originals remain on their branch. Static checks cover graft/row/question/citation anchors and original blobs. No source code, suite, mailbox, secret file, service, MVP or queue change. Candidate goes to Ludwig before Sage landing/queue handoff, copying Mos.
|
||||
|
||||
2026-10-21T21:45:20Z | Della mos-1223 / ludwig-0004 focused corrections | Before: b096a16cc left content-key location implicit and E05 core registration marked ready. After: merged plan 399 lines fixes external configDir secret key/lifecycle namespace outside dataRoot backup/restore, E01 schema and E03 missing/expired-key restore tests, and E05/E06 test-local registry readiness with core kinds.mjs registration gated on approved E01/Q4. Sixteen rows and eleven questions retained; originals unchanged. Focused static checks and queue guard apply, no product/live changes. Reviewer will check changed lines only.
|
||||
|
||||
2026-10-21T22:24:12Z | Huey | T1 item 7 sessions design r1, mos-1232, Vikunja 463 | Before: origin/refactor cca206cdc keys assistant claims/stores/messages by thread and renders Pi compaction markers; row 194 r4 excludes thread context clear. After: docs/plans/2026-10-21_t1-sessions.md proposes independent per-agent sessions within threads on Pi/Claude, scoped claims/stores/messages/workspaces, completed compaction counts, owner-write/RBAC matrix, idempotent proven-stop/fresh-successor clear, common admission/kill checks, migration and seven acceptance groups, replacement REQ-ROLE-2/REQ-THREAD-2 text and three owner questions. PRD 1.12 USER-3/4 candidate 1509c7cc5 cited separately from base. Verification: 22 pinned references resolve, eight-line summary and three exact owner quotes; manual source/consistency review, whitespace and installed queue guard checked. No code, queue/PRD edits, builds, suites, credential reads, live changes or paid calls. MVP priority ahead of Q198 S1. Review via Scrooge, then Sage/Ludwig as Mos authorized.
|
||||
|
||||
2026-10-21T22:28:56Z | Huey | T1 sessions design r2, scrooge-0006, mos-1235/1236, Vikunja 463 | Before: r1 347278044 lacked the exact per-session checkout/single-writer invariant and safe runner drain ordering, and admitted other role instances. After: F1 exact workspace path, fenced checkout setup, legacy shared-workspace quiescence, clear retains old dirty/untracked/unpushed checkout and creates fresh approved checkout, T2 mutant; F2 dequeue fence and generation-bound turn-boundary idle proof before runner signal, busy drain stays clearing, T4 cases; F3 THREAD_DEFINITION only per Mos scope ruling, no role eligibility change; N1 private titles/history vs owner-visible count/activity projection; N2 Claude offline adapter/managed-store-reader dependency flagged as MVP risk. Section 8 records Mos’s Q1–Q3 readings, no questions to Jason. Verification: 27 pinned references resolve, summary within 15 lines, source/delta consistency review, whitespace and installed queue guard checked. No code, queue/PRD edits, builds/suites/live changes/provider calls/credential reads.
|
||||
|
||||
2026-10-21T22:30:20Z | Huey | T1 sessions design r3, scrooge-0007 R1, Vikunja 463 | Before: r2 e19e30df2 nested new session checkouts under the retained legacy instance workspace, allowing project-name collision or historical parent inspection to reach live siblings. After: exact path is dataRoot/session-workspaces/business/instance/session, outside the legacy root; canonicalized ancestor/descendant overlap refuses; T2 nesting mutant covers historical mount/inspection and a legacy project named sessions. All other r2 content retained as approved, revision label updated. Verification: old nested path absent, manual R1-only delta, whitespace and installed queue guard checked; no code/builds/suites/live changes/provider calls/credential reads.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,144 @@
|
||||
# Row 257: Q198 S1 pressure parser and pure rules evaluator
|
||||
|
||||
Issue #1762. Brief: `docs/plans/2026-10-21_post-v1-row-briefs.md`, "Brief: Q198 S1 pressure parser and
|
||||
pure rules evaluator" and "Gate: Q198 S1" (cca206cdc). Design: `docs/plans/2026-10-21_q198-system-manager.md`
|
||||
r6.1, section 8 row S1 and section 4 (D4). Owner Morgana, reviewer Filbert, gate owner Sage (sage-2196).
|
||||
Post-v1: MVP rows and re-pin windows go ahead of it on the slot. Base: refactor cca206cdc.
|
||||
|
||||
## Recorded choices (sage-2196 accepted each)
|
||||
|
||||
1. **Placement.** A new package, `packages/supervisor` (`@mosaic/supervisor`), shaped like
|
||||
packages/runs. Nothing on refactor parsed loadavg, PSI, meminfo or cgroup limits (`git grep`; the
|
||||
only hit was an awk line in scripts/case2-precheck.sh). S2 adds the sampler process to the same
|
||||
package. Packages aren't registered centrally, so no other file changes.
|
||||
2. **Provider scope** (429, quota, Retry-After, the half-open probe) is out. The brief puts it in S3
|
||||
and S5.
|
||||
3. **PSI** is not required on a host that has never shown it, so a kernel built without PSI skips the
|
||||
PSI rows instead of holding forever. Once a sample has carried PSI, it is required: a later missing
|
||||
or stale PSI signal holds with `health-unknown`. That is the case sage-2196 asked for.
|
||||
- Tradeoff: I latch on the first sample that carries PSI, not only on the very first sample. So PSI
|
||||
that appears late and then disappears also holds. This is stricter than "present at the first
|
||||
sample", and it never skips a signal the host has shown.
|
||||
4. **Memory under a cgroup.** Available memory = min(MemAvailable, limit - memory.current) at each
|
||||
limited level. memory.current counts page cache, so this errs toward holding.
|
||||
- Follow-up, not in this row: subtract reclaimable cache using memory.stat `inactive_file`, if S2's
|
||||
live samples show holds that the host's MemAvailable doesn't support.
|
||||
|
||||
Rulings on two readings from the build (sage-2202, re morgana-0057):
|
||||
|
||||
5. **PSI latch.** PSI becomes required on the first sample that carries it. This is stricter than
|
||||
"present at the first sample" and fails closed: a PSI file that disappears after it was seen is a
|
||||
missing signal, so health-unknown holds.
|
||||
6. **PSI count across resources.** Design line 152 says "CPU some ≥20, memory full ≥2, or I/O full
|
||||
≥10, for 3 samples". The window applies to the whole disjunction, so any PSI condition on 3
|
||||
consecutive samples holds. If Filbert reads it per resource at review, the review finding decides,
|
||||
and the fix is a single counter.
|
||||
|
||||
Other readings of the D4 table, made in the build:
|
||||
- **Memory floors.** "Whichever demands more free memory" means the larger floor applies. Hold below
|
||||
max(15% x limit, 1 GiB); release above max(25% x limit, 2 GiB).
|
||||
- **Edges as written.** Hold at ≥ for load and PSI, < for memory. Release at ≤ 0.55 for load, < for
|
||||
PSI, > for memory. Critical below 5% of the limit and below 1 GiB of disk.
|
||||
- **Sample counts.** "For 3 samples" means 3 consecutive samples. The count resets after a gap of more
|
||||
than 6 s (the stale limit) between samples. The PSI row counts as one row (ruling 6), and the
|
||||
reasons name the resources over on the latest sample.
|
||||
- **Memory holds on one sample.** The table's memory row has no sample count.
|
||||
- **Release** needs every applicable release condition on every sample for 30 s, by the samples' own
|
||||
times (`>= 30000` ms after the first qualifying sample). A dead-band sample or any hold restarts the
|
||||
window, and so does a gap of more than 6 s.
|
||||
- **Start held.** `initialState()` is held, because nothing has been seen yet. The first healthy
|
||||
sample starts the 30 s window.
|
||||
- **Missing or stale.** Required signals are load, memory, oom and disk, plus PSI once seen. A signal
|
||||
holds at once with `health-unknown` if it is:
|
||||
- missing;
|
||||
- non-numeric, negative or zero where a divisor;
|
||||
- more than 6 s older than its sample (6 s exactly is fresh);
|
||||
- stamped later than its sample.
|
||||
Disk and OOM are required because the critical row can't be evaluated without them.
|
||||
- **Host-only OOM.** `/proc/vmstat` `oom_kill` gives the OOM counter when there's no cgroup
|
||||
memory.events. The parser returns null for a kernel without it, and the sampler then has no OOM
|
||||
signal (health-unknown).
|
||||
- **Critical** latches. It ends only when the caller passes `reconciled` with no critical condition in
|
||||
the sample, then goes through held and the normal 30 s release. The evaluator never sets
|
||||
`reconciled` and has no kill-switch path. Critical reasons accumulate while latched.
|
||||
- **OOM counter.** The first OOM sample is the baseline. A falling counter (a recreated cgroup) resets
|
||||
the baseline with a note, not an event.
|
||||
- **Clock going backwards.** A sample earlier than the last one holds with `health-unknown` (unknown
|
||||
`clock`, note `clock-backwards`).
|
||||
- **Swap activity** is parsed (`pswpin`, `pswpout`) and has no rule. D4 lists it as a signal with no
|
||||
threshold.
|
||||
- **Settings.** `resolveRules` refuses:
|
||||
- unknown keys and non-numbers;
|
||||
- a release at or past its hold (load, each PSI resource);
|
||||
- memory release floors at or below the hold floors;
|
||||
- fractions outside (0, 1);
|
||||
- PSI values outside 0 to 100;
|
||||
- sample counts that aren't integers ≥ 1;
|
||||
- a negative release window;
|
||||
- a stale limit at or below the sample interval;
|
||||
- a critical memory fraction at or above the hold fraction;
|
||||
- a non-positive disk floor.
|
||||
- **Large byte values.** Parsed with `Number`. A memory.max above 2^53 loses precision, but it only
|
||||
takes part in a min against MemTotal.
|
||||
|
||||
## Round 2 (Filbert r1 APPROVE c30188 notes, sage-2212)
|
||||
|
||||
- N1: `merge` checked unknown keys with `key in base`, so inherited names (`toString`, `constructor`,
|
||||
`__proto__`) passed the check and were dropped instead of refused. It now uses
|
||||
`Object.hasOwn(base, key)`, and the refusal test has those three cases.
|
||||
- N2: the critical-memory edge was tested only on a 32 GiB limit, where 5% is not an integer, so a
|
||||
`<` to `<=` mutant survived. The test adds a 20 GiB limit, where 5% is exactly 1 GiB, and M8 is that
|
||||
mutant. I checked the other memory edges for the same gap:
|
||||
- The hold floor is non-integer on 32 GiB but is tested at exactly 1 GiB on a 4 GiB limit.
|
||||
- The release floors are 8 GiB on 32 GiB and 2 GiB on 4 GiB, both integers.
|
||||
- The disk edge is 1 GiB.
|
||||
|
||||
None has the gap.
|
||||
|
||||
## Files
|
||||
|
||||
- `packages/supervisor/package.json`, `README.md`
|
||||
- `src/errors.mjs`: `SupervisorError` with `kind` parse, rules or sample.
|
||||
- `src/pressure.mjs`: the nine parsers, `effectiveCpus` and `effectiveMemory`.
|
||||
- `src/rules.mjs`: `DEFAULT_RULES`, `resolveRules`, `initialState`, `evaluate`.
|
||||
- `src/index.mjs`
|
||||
- `tests/pressure.test.mjs`: parsers on kernel-shaped fixture text, with malformed, truncated and
|
||||
repeated-key cases. Effective CPU cases cover the host-only fallback, cpuset, fractional and nested
|
||||
`cpu.max`, and `max`. Effective memory cases cover the host-only fallback, `max`, nested levels,
|
||||
usage over the limit, a limit above MemTotal and a missing memory.current.
|
||||
- `tests/rules.test.mjs`: the D4 table on a fake clock.
|
||||
- Each hold and release threshold on both sides of its edge.
|
||||
- Three-sample counting and the gap reset.
|
||||
- The 30 s release at 29 999 and 30 000 ms, and the dead-band restart.
|
||||
- Missing, stale, future and malformed signals.
|
||||
- PSI never present, and PSI lost after it was present.
|
||||
- Critical OOM, memory and disk at their edges, the reconciliation latch and the counter reset.
|
||||
- A backwards clock, input state left unchanged, and settings refusals and overrides.
|
||||
- `tests/purity.test.mjs`: a static check that src imports only its own files and uses no
|
||||
fs, child_process, net, os, process, dynamic import, Date or timers.
|
||||
|
||||
No test reads /proc, /sys or a cgroup, starts a build, opens a network socket or generates load. No new
|
||||
dependency.
|
||||
|
||||
## Mutants (each must fail its named test; the brief requires M1 and M2)
|
||||
|
||||
| Mutant | Edit | Named test |
|
||||
|---|---|---|
|
||||
| M1 hold edge | `ratio >= rules.load.hold` becomes `>` | load holds at 0.80 for 3 samples and not at 0.7999 |
|
||||
| M2 early release | `now - next.releaseSince >= rules.releaseMs` becomes `>= 0` | the first state is held, and healthy samples open it after exactly 30 s |
|
||||
| M3 memory floor | the hold floor `Math.max` becomes `Math.min` | memory holds below the larger floor, on one sample |
|
||||
| M4 sample count | `next.loadCount >= rules.load.samples` becomes `>= 1` | load holds at 0.80 for 3 samples and not at 0.7999 |
|
||||
| M5 stale | the `now - signal.at > rules.staleMs` check is removed | a signal is stale at more than 6 s old and fresh at exactly 6 s |
|
||||
| M6 effective CPU | the quota `Math.min` becomes `Math.max` | effective CPUs take the smallest of host, cpuset and every quota level |
|
||||
| M7 critical latch | the `!reconciled` critical branch is removed | critical stays until reconciliation, then still waits the 30 s release |
|
||||
| M8 critical memory edge (r2) | `available < rules.critical.memoryFraction * limit` becomes `<=` | memory under 5% and disk under 1 GiB are critical, at their edges |
|
||||
|
||||
## Gate (Sage's slot, on CLEAR only)
|
||||
|
||||
- The three test files, each whole, then `node --test tests/` in packages/supervisor as the package
|
||||
suite.
|
||||
- Then M1 to M8, each on its named test, restored after each.
|
||||
- umask 022, TMPDIR from `mktemp -d /mnt/storage/scratch/tmp/gXXXXXX`.
|
||||
- The kit is /mnt/storage/scratch/morgana-r257 (slot257.sh, mutate.py). It refuses unless HEAD is the
|
||||
candidate and the tree is clean, and stops after two unexpected failures (mos-0823).
|
||||
- Static checks before the slot: `node --check` on every file, run from `/`. No test has run yet.
|
||||
@@ -1,48 +0,0 @@
|
||||
// Sage, 2026-10-21: row 215 (C2-04) landed, comment on P19 416 (Q174 landing comment). Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r215-landed.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 416, title: /^MVP Case 2: creative writing hub instance/, body: [
|
||||
"Row 196 landed (7247d80c7). Two rows were waiting on it. Row 253 (#1758, Gander, Duckworth reviewing) moves case2-unit.sh and case1-accept.sh to --tester-socket. Until it lands, .53 and .54 take no copy carrying 196. Row 254 (#1759, Megavolt, Dewey reviewing) holds the library sync deferrals from row 222.",
|
||||
] },
|
||||
];
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,49 +0,0 @@
|
||||
// Sage, 2026-10-21: row 215 (C2-04) landed, comment on P19 416 (Q174 landing comment). Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r215-landed.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 435, title: /^Console inbox: Approve\/Deny for grant requests by the signed-in human \(DECISIONS Q188\)$/, body: [
|
||||
"Row 196 (the human boundary across uids and humans, #1694) landed on refactor as 7247d80c7 at 20:57Z. The bus binds each human proof to the socket peer with SO_PEERCRED and records the interpreter it trusts in bus/peercred-starts.jsonl. The Console's tester listener moves from TCP --tester-port to a private socket, --tester-socket. Gander built it, and Duckworth approved round 1 (rev 2973) and round 2 (rev 2986). Gate gander-0066 passed 2334 with 0 failures and 1 skip, plus 38/38 mutants. #1694 is closed (comment 30159), and queue row 196 is done (rev 2988).",
|
||||
"No live change yet. The 10-24 re-pin (plan draft 1, approved by Mos at 3fb00018e) carries 196 on dragon-lin and switches the live Console from --tester-port 7333 to --tester-socket. Until row 253 (#1758) moves case2-unit.sh and case1-accept.sh to the socket form, .53 and .54 take no copy carrying 196 (mos-1198).",
|
||||
] },
|
||||
];
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,52 +0,0 @@
|
||||
// Sage, 2026-10-21: row 215 (C2-04) landed, comment on P19 416 (Q174 landing comment). Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r215-landed.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 435, title: /J2|uid|separat|human boundary|peer/i, body: [
|
||||
"Row 196 (the human boundary across uids and humans, #1694) landed on refactor as 7247d80c7 at 20:57Z. The bus binds each human proof to the socket peer with SO_PEERCRED and records the interpreter it trusts in bus/peercred-starts.jsonl. The Console's tester listener moves from TCP --tester-port to a private socket, --tester-socket. Gander built it, and Duckworth approved round 1 (rev 2973) and round 2 (rev 2986). Gate gander-0066 passed 2334 with 0 failures and 1 skip, plus 38/38 mutants. #1694 is closed (comment 30159), and queue row 196 is done (rev 2988).",
|
||||
"No live change yet. The 10-24 re-pin carries 196 on dragon-lin and switches the live Console from --tester-port 7333 to --tester-socket. Until row 253 (#1758) moves case2-unit.sh and case1-accept.sh to the socket form, .53 and .54 take no copy carrying 196 (mos-1198).",
|
||||
] },
|
||||
{ id: 416, title: /^MVP Case 2: creative writing hub instance/, body: [
|
||||
"Row 196 landed (7247d80c7). Two rows were waiting on it. Row 253 (#1758, Gander, Duckworth reviewing) moves case2-unit.sh and case1-accept.sh to --tester-socket. Until it lands, .53 and .54 take no copy carrying 196. Row 254 (#1759, Megavolt, Dewey reviewing) holds the library sync deferrals from row 222.",
|
||||
] },
|
||||
];
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,50 +0,0 @@
|
||||
// Sage, 2026-10-21: row 210 landed, comment on P19 424, per mos-0882. Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r210-landed.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 424, title: /^Credential store: per-agent host access/, body: [
|
||||
"Row 210 (agent host access with sudo through the credential store) landed on refactor as f5753c0e8, pushed. Gitea #1707 closed with the landing comment 29853.",
|
||||
"Built by Gizmoduck (r5 0485384e9), reviewed by Duckworth (approve rounds 2 and 3, comment 29851). Mutants 52 of 53 killed, M22b equivalent with coverage moved to row 235. Gate green: 15 package suites 2796 pass, 10 script suites 429 pass, 0 fail.",
|
||||
"No live change yet. It goes live in the 10-24 re-pin window with rows 190, 199, 237 and 234 (mos-1145). Next on this line: row 234 (machine grant row a, Gizmoduck) is briefed, then row 235 (row b) and row 236 (#436b).",
|
||||
] },
|
||||
];
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,50 +0,0 @@
|
||||
// Sage, 2026-10-21: row 215 (C2-04) landed, comment on P19 416 (Q174 landing comment). Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r215-landed.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 416, title: /^MVP Case 2: creative writing hub instance/, body: [
|
||||
"Row 215 (C2-04: the library entry in the business file, consumer skips, M9 organization-projects-protected, the bare mirror, library.file and library.status) landed on refactor as e54e05463 at 19:24Z. Gitea #1716 is closed (comment 30133). Queue row 215 is done (rev 2955).",
|
||||
"Herb built it, and Filbert approved the merge-scoped round 2 (rev 2924). The landing patch-id equals the candidate dde3445ab on a36523713. Herb ran the gate on grant sage-2071, with the business, seat, cli, project, bus and webui suites whole plus every scripts/test-*.sh: 2634 pass, 0 fail, and one environment skip in webui.",
|
||||
"Row 222 (C2-03a fetch-only sync, Megavolt) was waiting on this landing and now rebases onto e54e05463. Nothing is re-pinned yet.",
|
||||
] },
|
||||
];
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,50 +0,0 @@
|
||||
// Sage, 2026-10-21: row 232 (installer I1) landed, comment on P19 432, per mos-0882. Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r232-landed.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 432, title: /^Installer row: one-command install and upgrade for a fresh host/, body: [
|
||||
"I1 landed: row 232 (stack-release --units external for root-owned units, with confirm, revert and gate --since; stack-copy copy --bundle and wrapper --create) is on refactor as e65a3ab4d, pushed. Gitea #1734 closed with the landing comment 29874.",
|
||||
"Built by Darkwing (round 2 da2da2f6c, a rebase over row 230's README hunk), reviewed by Filbert (approve rounds 1 and 2, comments 29829 and 29865). Mutants 17 of 17 killed. Landing gate green: packages/cli 593 pass, 10 script suites 429 pass, 0 fail.",
|
||||
"No live change; --units user stays the default. Installer line: I2 is rows 230 (landed c8bc5cf4c) and 226, I3 is row 233 (briefed, Darkwing), I4 is row 240 (hostcheck).",
|
||||
] },
|
||||
];
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,50 +0,0 @@
|
||||
// Sage, 2026-10-21: row 233 (installer I3) landed, comment on P19 432, per mos-0882. Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r233-landed.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 432, title: /^Installer row: one-command install and upgrade for a fresh host/, body: [
|
||||
"I3 landed: row 233 (scripts/stack-upgrade.sh, the upgrade driver, and docs/guides/host-run-sheet.md) is on refactor as 57f59e0c3, pushed 05:39Z. Gitea #1735 closed with the landing comment 29931.",
|
||||
"Built by Darkwing (round 1 1a1dc80ca), reviewed by Filbert (approve, comment 29922). Mutants m1-m8 killed. Landing gate on the landing tree: packages/cli 617 pass, 10 script suites 585 pass, 0 fail. Patch-id and the manifest match the candidate.",
|
||||
"No live change. Filbert's N1, N4 and N5 go to I4 (row 240, Darkwing, briefed now). N2 and N3 are in DEFERRED.md. Row 234 round 3 is rebuilt on this landing.",
|
||||
] },
|
||||
];
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,51 +0,0 @@
|
||||
// Sage, 2026-10-21: row 234 (machine grant row a) landed, comment on P19 436, per mos-0882. Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r234-landed.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 436, title: /^Guarded grant methods: on Approve, stack code creates the grant/, body: [
|
||||
"Row a landed: row 234 (machine grant row a: host enrollment, the hosts and host_grants store records, bus schema 3i to 3j) is on refactor as c771a36f4, pushed 06:16Z. Gitea #1740 closed with the landing comment 29938.",
|
||||
"Built by Gizmoduck (round 3 c783d5e39, one commit on the row 233 landing), reviewed by Duckworth (round 3 approve, comment 29935, rev 2683). 25 of 25 mutants killed. Sage's landing gate on the candidate tree: 15 packages 2890 pass and ten script suites 585 pass, 0 fail. Patch-id and the manifest match the candidate.",
|
||||
"No live change. The 3i to 3j migration runs in the 10-24 window (mos-1145), with a backup first. Duckworth's N10 and N12 go to row 235 (row b), which Gizmoduck rebuilds on this landing next.",
|
||||
] },
|
||||
];
|
||||
if (/LANDSHA|PUSHTIME|CLOSEID|GATE\b/.test(JSON.stringify(POSTS))) throw new Error("placeholder left; refusing");
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,53 +0,0 @@
|
||||
// Sage, 2026-10-21: row 237 landed, rows 241 and 242 opened, comments on P19 440 and 441, per mos-0882. Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r237-rows-440-441.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 440, title: /^Bus publish: a retry after publish-timeout/, body: [
|
||||
"Row 237 landed on refactor as d7d943199 (Gitea #1743, closed, comment 29836). checkPublish refuses publish-busy while an open ticket holds the decision. Gate green, mutant M1 killed.",
|
||||
"This task is now queue row 242 (Gitea #1748, Megavolt, reviewer Duckworth), briefed. Brief: docs/plans/2026-10-20_agent-credentials.md, \"Brief: row 237 follow-up N1, a retry after publish-timeout pushes once\" (9d165be8c). The fix either holds the decision until the bus's push ends or kills the push and waits, with a slow-push retry test and a mutant.",
|
||||
] },
|
||||
{ id: 441, title: /^Bus land: check whether checkLand has the same open-ticket race/, body: [
|
||||
"Megavolt's analysis (megavolt-0068, megavolt-0069): no end-to-end race. land-busy (git-socket.mjs:351) allows one landing per socket. finishLand moves main by compare-and-swap (seat working.mjs:391, base-moved). recordLand reruns #landFacts, which refuses decision-consumed (broker.mjs:945). Sage accepted it in sage-1651.",
|
||||
"This task is now queue row 241 (Gitea #1747, Megavolt, reviewer Duckworth). It changes no source. It adds a two-ticket broker land test and three mutants, one per guard. Brief (c25785d3d): \"Brief: row 237 follow-up, one decision lands once, with tests at the broker\". Megavolt claimed it at rev 2606.",
|
||||
] },
|
||||
];
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,50 +0,0 @@
|
||||
// Sage, 2026-10-21: row 240 (installer I4) landed, comment on P19 432, per mos-0882. Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r240-landed.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 432, title: /^Installer row: one-command install and upgrade for a fresh host/, body: [
|
||||
"I4 landed: row 240 (scripts/case1-hostcheck.sh with its pins in case1-pins.sh, the boot unit mosaic-hostcheck.service, and the I3 fixes in stack-upgrade.sh and the host run sheet) is on refactor as c515273db, pushed 06:57Z. Gitea #1746 closed with the landing comment 29954.",
|
||||
"Built by Darkwing (ad1b23ab2), reviewed by Filbert (approve, comment 29945). Mutants M1-M8 killed. Landing gate on the landing tree: packages/cli 639 pass, 10 script suites 585 pass, 0 fail. Patch-id and the manifest match the candidate.",
|
||||
"No live change; the host check is installed by hand on a Case 1 host from the run sheet. Filbert's N1 (the boot unit orders only mosaic-bus@mosaic-stack) and N2 (the apt hook goes in before the first --check) are in DEFERRED.md. N1 must be fixed before an install whose business id isn't mosaic-stack.",
|
||||
] },
|
||||
];
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,50 +0,0 @@
|
||||
// Sage, 2026-10-21: row 232 (installer I1) landed, comment on P19 432, per mos-0882. Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r232-landed.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 441, title: /^Bus land: check whether checkLand has the same open-ticket race/, body: [
|
||||
"Row 241 landed: 5d4a61776 on refactor, pushed. Gitea #1747 closed with the landing comment 29883.",
|
||||
"Answer: landing has no row 237 race. Three guards keep one decision from landing twice: land-busy at the git socket (cli git-socket.mjs:351), the CAS on main in finishLand (seat working.mjs:391), and the recordLand recheck of #spent (bus broker.mjs:963). Megavolt's new broker test opens two checkLand tickets on one decision and shows the second recordLand refuses decision-consumed and records nothing.",
|
||||
"Built by Megavolt (3e3ed303e, tests and packet only, no source change), reviewed by Duckworth (approve, comment 29870). Sage's mutants M1-M3 on the three guards all killed. Landing gate green: 15 packages 2797 pass, 10 script suites 429 pass, 0 fail.",
|
||||
] },
|
||||
];
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,50 +0,0 @@
|
||||
// Sage, 2026-10-21: row 232 (installer I1) landed, comment on P19 432, per mos-0882. Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r232-landed.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 440, title: /^Bus publish: a retry after publish-timeout/, body: [
|
||||
"Row 242 landed: 5fb736b92 on refactor, pushed. Gitea #1748 closed with the landing comment 29894.",
|
||||
"Built by Megavolt (635c10924), reviewed by Duckworth (approve, comment 29889). Mutants M1 and M2 killed. Landing gate green: 15 packages 2826 pass, 10 script suites 429 pass, 0 fail.",
|
||||
"Open follow-ups: Duckworth's doc notes N1, N2 and N4 (a doc-only commit by Megavolt), and the late-record notice to the run (comment 432 above).",
|
||||
] },
|
||||
];
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,50 +0,0 @@
|
||||
// Sage, 2026-10-21: row 232 (installer I1) landed, comment on P19 432, per mos-0882. Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r232-landed.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 440, title: /^Bus publish: a retry after publish-timeout/, body: [
|
||||
"Follow-up from row 242 (Megavolt's residual, Duckworth N3, ruled sage-1691). Row 242 makes a retry after publish-timeout push once: the bus holds the decision until its push ends and records a late push. But when a push is recorded after the agent was already told publish-timeout, the run gets no notice. The allowed event and the bus log line are the only trace, and a later publish on the decision gets decision-consumed.",
|
||||
"Risk: an agent told publish-timeout can tell the user the publish failed while the push is on the fork. That ends up as false evidence in the run.",
|
||||
"Proposed later row: when the bus records a late push, it sends the run a notice with the decision id and the ref, and a later decision-consumed refusal names the late record. This is a new message in the run protocol, so it gets its own brief. Not queued before 10-27 unless MVP work needs 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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,51 +0,0 @@
|
||||
// Sage, 2026-10-21: row 242 doc follow-up (P19 440) and the row 210 T26 follow-up (P19 424), per mos-0882. Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r242d-r210-t26.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 440, title: /^Bus publish: a retry after publish-timeout/, body: [
|
||||
"Row 242 doc follow-up landed: fc1cb856b on refactor, pushed. This is Megavolt's c5a125f4b (Duckworth N1, N2, N4): comment lines in packages/cli/src/git-socket.mjs plus BUILD.md, no test hash pins, so no gate under the doc-only rule. Patch-id matches. The late-record notice (comment 432) is still the open follow-up.",
|
||||
] },
|
||||
{ id: 424, title: /^Credential store: per-agent host access/, body: [
|
||||
"Row 210 follow-up, test hygiene (found by Gizmoduck in the row 234 singles, 2026-10-21): T26 in packages/bus/tests/host-run.test.mjs spawns /bin/sh -c 'sleep 60; :' at :488 (planted) and :496 (decoy), detached. Each has a t.after (:489, :497) that SIGKILLs the sh pid only, so its sleep child lives on. Two sleeps outlive each run by up to 60 s. Fix: since both are detached, kill the process group instead (process.kill(-pid, 'SIGKILL')). It doesn't affect any result, but a mutant or busy check that counts processes sees them. A small follow-up, not a blocker.",
|
||||
] },
|
||||
];
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,50 +0,0 @@
|
||||
// Sage, 2026-10-21: row 249 (grant undo hostLineLeft) landed, comment on P19 445, per mos-0882. Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r249-landed.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 445, title: /^Grant undo can't prove the remote add has ended/, body: [
|
||||
"Row 249 landed on refactor as 9de5a57ab, pushed at 14:56Z with 7b9737953, which adds the DEFERRED.md entry. Gitea #1751 is closed with landing comment 30074.",
|
||||
"Gizmoduck built it (05595794b) and Duckworth approved it (comment 30070). The broker marks install done only after it returns. When it never returned, the undo records hostLineLeft, and hosts.remove refuses until the sweep clears the line.",
|
||||
"Gate on Sage's slot: the grant-executor test file passed 39/0 and the bus suite 598/0, with no stub left. A mutant that drops the new branch was killed by G8 and both G23 tests. Webby's N1, the sleep 30 test, is deferred and binds the next row that touches that file. The live stack is unchanged.",
|
||||
] },
|
||||
];
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,49 +0,0 @@
|
||||
// Sage, 2026-10-21: row 215 (C2-04) landed, comment on P19 416 (Q174 landing comment). Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r215-landed.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 450, title: /^K12 cohort test: populated undefined under load/, body: [
|
||||
"Row 250 landed on refactor as 1b6158ce2 at 19:42Z. K12 now names the cause when the cgroup.events read fails, holds the stop's release while it reads the shim, and the release answers with the events read's reason. R13 closes its controller. Gitea #1755 is closed (comment 30139). Queue row 250 is done (rev 2965).",
|
||||
"Gizmoduck built it, and Filbert approved round 2 (rev 2957). The landing patch-id equals the candidate c1a858975. Gizmoduck ran the gate on grant sage-2109: the probes failed and passed as predicted, conversation whole 3x 183/183 plus a concurrent pair, and control-board whole 124/124.",
|
||||
] },
|
||||
];
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,52 +0,0 @@
|
||||
// Sage, 2026-10-21: row 215 (C2-04) landed, comment on P19 416 (Q174 landing comment). Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r215-landed.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 458, title: /Pocket ID|OIDC|Q203/i, body: [
|
||||
"Queue row 255 (rev 2976), Gitea #1760. It's a design row. Launchpad owns it, Webby reviews, Sage owns the gate, and it runs after row 252. The brief is docs/plans/2026-10-21_bundled-pocket-id.md (7d08237e1). Jason's Q203 answer is quoted verbatim, and Mos's reading is labelled as his. The design covers the installer choice, the component under REQ-INST-1, the Q175 start checks with no relaxation, the client secret slot, first-person passkey enrollment, reach (the outside steps are Jason's), agents, instances, stand-in tests and the build rows.",
|
||||
"PRD 1.10 adds REQ-INST-2, post-v1, as Mos ruled in mos-1204. A 1.10 note records that the out-of-scope list still names 'Pocket ID and SSO'. Jason hasn't ruled on that line (vikunja:19/459).",
|
||||
] },
|
||||
{ id: 416, title: /^MVP Case 2: creative writing hub instance/, body: [
|
||||
"Row 222 (C2-03a, fetch-only library sync) landed on refactor as 0b33f5e9d at 20:13Z. It adds the library.sync bus verb, a 60 s timer per library entry with a sync user, and the askpass helper. Gitea #1723 is closed (comment 30147), and queue row 222 is done (rev 2972). Megavolt built it, Dewey approved it (rev 2966), and megavolt-0098 ran the gate green. Dewey's deferrals are row 254 (#1759): the client timeout, STATUS codes and the README line. It runs after row 196.",
|
||||
] },
|
||||
];
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,54 +0,0 @@
|
||||
// Sage, 2026-10-21: row 66 (unslop check) landed, comment on P19 212 and 454, per mos-1186. Sage's own key (bot user 13); the sync key reads back. Comments only: no task edits.
|
||||
// Checks each task's title before posting. Prints no secret.
|
||||
// Usage: node comment-r249-landed.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const POSTS = [
|
||||
{ id: 212, title: /^Row 66: Managed sessions run the unslop check on both harnesses/, body: [
|
||||
"Row 66 landed on refactor as 2c38325ec, pushed at 18:51Z. 3b0aef995 adds the DEFERRED.md entry for the two live checks. Queue row 66 is done (rev 2921).",
|
||||
"Round 4 (82c830779) was approved by Dewey (comment 30085) and Filbert (30086), then rebased onto a36523713 after row 197 (mos-1186 item 4). The cherry-pick had no conflict. The patch-id without agents/ is d67275ac4251 on both bases. The harness suite went 149/0 on the rebased tree. The r4d gate was green: unslop, harness, plugins and every scripts/test-*.sh, with cli 682/0 on the TMPDIR rerun.",
|
||||
"Landing sessions on a scratch root from the candidate tree: Claude Code run r4ab24630d323 put the operator note on the RESULT, the correction notice reached the next turn as hook context, and unslop.jsonl counted checked 2, flagged 1, notices 1. The pi run r1dd94171bede is launch only until #383. The live checks are task 454.",
|
||||
] },
|
||||
{ id: 454, title: /^Row 66 live checks: unslop notice on Claude Code/, body: [
|
||||
"Row 66 landed as 2c38325ec, and the DEFERRED.md entry is 3b0aef995. Both checks here are open. Claude Code runs in the first re-pin whose tree includes 2c38325ec, backup first (Q173). Pi runs one full session with a tell after #383.",
|
||||
"Reference from the scratch root (agents/sage/work/queue-66/LANDING-SESSION.md): Claude Code run r4ab24630d323 showed the note, the injected notice and counts checked 2, flagged 1, notices 1. The pi launch r1dd94171bede bundled the unslop extension but ran no turn.",
|
||||
] },
|
||||
];
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], 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);
|
||||
};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) rec.problems.push(`comment ${P.id} read-back: ${back.status}`);
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,63 +0,0 @@
|
||||
// Sage, 2026-10-21: files row 249 (mos-1166, #1751) as a P19 task under #436, then relates it to 436 as a subtask.
|
||||
// Sage's own key (bot user 13); the sync key reads back. No labels, assignees, due dates or bucket moves. Refuses if
|
||||
// the title exists. Prints no secret.
|
||||
// Usage: node file-r249.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, "<").replace(/>/g, ">");
|
||||
const ps = (sig, xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(sig)}</p>`;
|
||||
const TASKS = [
|
||||
{
|
||||
title: "Grant undo can't prove the remote add has ended: record hostLineLeft when install never returned (row 249, #1751)",
|
||||
description: ps(SIG, [
|
||||
"Filed under #436 by Mos's ruling mos-1166. Gizmoduck answered in gizmoduck-0137 and 0139, and Duckworth checked the answer in duckworth-0091. The row 197 r8 proof found the leftover stubs that show it.",
|
||||
"An abort or timeout during install kills the local ssh, but sshd sends the remote add no SIGHUP, so it keeps running. If it writes after the undo's single remove, hostLineLeft stays unset. hosts.status shows the host clean, and hosts.remove can drop the record while the line is still on the host. After that a sweep refuses host-unknown. The line authorizes a key nobody holds.",
|
||||
"Queue row 249, owner Gizmoduck, reviewer Duckworth, gate Sage. Brief: docs/plans/2026-10-20_host-credentials.md (6de1ebc62).",
|
||||
]),
|
||||
},
|
||||
];
|
||||
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: null, 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 have = await existing();
|
||||
for (const T of TASKS) if (have.some((t) => t.title === T.title)) throw new Error("title exists; refusing");
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
rec.created = [];
|
||||
for (const T of TASKS) {
|
||||
const r = await api("PUT", `/api/v1/projects/${PROJECT}/tasks`, { title: T.title, description: T.description }, key);
|
||||
const c = { status: r.status, id: r.json?.id ?? null };
|
||||
rec.created.push(c);
|
||||
if (r.status >= 300 || !Number.isSafeInteger(r.json?.id)) { rec.problems.push(`create: ${r.status} ${r.json?.message ?? ""}`); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${r.json.id}`, undefined, sync);
|
||||
Object.assign(c, { readBack: back.status, done: back.json?.done });
|
||||
if (back.status !== 200 || back.json?.title !== T.title || back.json?.done) rec.problems.push(`read-back differs for ${r.json.id}`);
|
||||
const rel = await api("PUT", `/api/v1/tasks/${r.json.id}/relations`, { other_task_id: 436, relation_kind: "parenttask" }, key);
|
||||
c.relation = rel.status;
|
||||
if (rel.status >= 300) rec.problems.push(`relation: ${rel.status} ${rel.json?.message ?? ""}`);
|
||||
}
|
||||
save();
|
||||
console.log(JSON.stringify(rec));
|
||||
@@ -1,83 +0,0 @@
|
||||
// Sage, 2026-10-21: re-pin window 4429a104f to 7247d80c7 W12 result (mos-1234) and the PRD 1.11 and 1.12 landings.
|
||||
// Comments on P19 454, 386, 412 and 435, then comments on 459 and 462 and marks those two done (mos-1234 item 4).
|
||||
// Sage's own key (bot user 13); the sync key reads back. A close sends the task as the v1 GET returned it with only
|
||||
// done changed, and the read-back checks that title and description are the same. Rollback is marking it undone.
|
||||
// Checks each task's title before anything is posted. Prints no secret.
|
||||
// Usage: node post-w12-prd.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 PSIG = "Posted by Sage (T3 1ef1e4f8) with Sage's own key (bot user 13).";
|
||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
const ps = (xs) => xs.map((x) => `<p>${esc(x)}</p>`).join("") + `<p>${esc(PSIG)}</p>`;
|
||||
const WIN = "agents/sage/work/window-repin-7247d80c7/";
|
||||
const POSTS = [
|
||||
{ id: 454, title: /^Row 66 live checks: unslop notice on Claude Code/, close: false, body: [
|
||||
"The Claude Code half passed in W12 of the 7247d80c7 re-pin (w12b.sh, 22:24:48Z to 22:27:13Z, W12_PASS, mos-1234). It ran on the live chief r7646a7a4a2bd (claude-code). Baseline unslopCounts were checked 2, flagged 0, notices 0. Turn 1 asked for one sentence using four banned words, and its RESULT carried the operator note \"[unslop: 1 reply of this session flagged since the last note ... The session gets a correction notice on its next turn.]\". Turn 2 replied \"received\". After the turns: checked 5, flagged 1 (ms-unslop:7 x4), notices 1, broken null.",
|
||||
"The pi half still waits on #383, so this stays open.",
|
||||
"The pm requirements read is open, not a window failure (mos-1234 item 3). No tester path reaches a pm: the chief relayed the request as bus message ed1063ea but launched no pm, because a tester message authorizes nothing. The read runs at the first pm launch from a human message or a real bus notice, and ed1063ea waits unread for that pm. Nothing goes to Jason for it.",
|
||||
`Evidence: ${WIN}STATE.md (W12 section), W.txt, .w12b-counts.json, w12b.out. The W12 store backup is SHA256SUMS a4ecd7ba.`,
|
||||
] },
|
||||
{ id: 386, title: /^Q173 test system/, close: false, body: [
|
||||
"The 7247d80c7 re-pin window is done. W0 to W12 passed, nothing was rolled back, and the one counted failure was P2 attempt 1 (a script path bug before any live step). The live Console now serves the tester through the private socket ~/.mosaic-dev/console/tester.sock with --tester-socket, and nothing listens on 7333. Two tester reads through the socket matched the old listener's /api/config line. Every step ran as tester, with no --by jason, no Save, no mosaic name, and bus.tester untouched.",
|
||||
`STATE report: ${WIN}STATE.md. It goes into the window record commit next.`,
|
||||
] },
|
||||
{ id: 412, title: /^Console SSO/, close: false, body: [
|
||||
"Baseline for phase 2 (mos-1195), from W10 of the 7247d80c7 re-pin at 22:18:51Z: POST /api/seen and POST /api/reply through 127.0.0.1:7332 with no session and no proxy header both return 401 \"sign-in required\". Phase 2 (config entry with clientId fvchAepp9…, --sso --send re-pin, Jason's first sign-in, the sub read, the unsigned-write check, the sign-out landing check) runs when Jason starts it (mos-1217).",
|
||||
] },
|
||||
{ id: 435, title: /^Console inbox: Approve\/Deny/, close: false, body: [
|
||||
"Row 196 is live on dragon-lin since the 7247d80c7 re-pin (activation 20261021T215926Z-7247d80c7af7, store 3j). The tester reaches the Console only through the private socket now. Hosts and host_grants exist in the store with 0 rows, and the window added no grant.* event (mos-1225). Per mos-1198, .53 and .54 take no copy carrying 196 until row 253 lands.",
|
||||
] },
|
||||
{ id: 459, title: /^PRD v1 scope: 'Pocket ID and SSO'/, close: true, body: [
|
||||
"Closing: PRD 1.11 landed on refactor at 22:30:53Z as ea0b2a16d and 73222011f, a fast-forward from cca206cdc (Ludwig, mos-1227, mos-1229). It records Q211, so v1 is the 10-27 goal, and Mos's reading of the review path. The v1 VMs' OIDC provider stays open under 461. requirements.json moves from 1.10 with 70 ids to 1.11 with 71. Before the push, packages/tasks/tests/requirements.test.mjs and packages/bus/tests/requirements.test.mjs each passed 3/3 run whole on 73222011f, and verbs.test.mjs passed 31/31.",
|
||||
] },
|
||||
{ id: 462, title: /^PRD 1\.12: requirement ids/, close: true, body: [
|
||||
"Closing: PRD 1.12 landed on refactor at 22:30:59Z as 3576afffb, 74dea06d9 and 1509c7cc5, a fast-forward from 73222011f. Della approved it in della-0010. requirements.json is 1.12 with 82 ids, 11 of them new, and the REQ-DEC-3 title changed. Before the push, both requirements test files passed 3/3 each, run whole on 1509c7cc5 as the final candidate, and verbs.test.mjs passed 31/31. The follow-ups 463, 464 and 465 stay open.",
|
||||
] },
|
||||
];
|
||||
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 : []);
|
||||
const rec = { at: new Date().toISOString(), comments: [], closes: [], 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 = {};
|
||||
for (const P of POSTS) {
|
||||
const t = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
if (t.status !== 200 || t.json?.project_id !== PROJECT || !P.title.test(t.json?.title ?? "")) throw new Error(`task ${P.id}: ${t.status}, title check failed; nothing posted`);
|
||||
if (P.close && t.json.done) throw new Error(`task ${P.id} is already done; nothing posted`);
|
||||
before[P.id] = { title: t.json.title, description: t.json.description };
|
||||
}
|
||||
writeFileSync(OUT, "", { flag: "wx" });
|
||||
for (const P of POSTS) {
|
||||
const c = await api("PUT", `/api/v1/tasks/${P.id}/comments`, { comment: ps(P.body) }, key);
|
||||
const e = { task: P.id, status: c.status, id: c.json?.id ?? null };
|
||||
rec.comments.push(e);
|
||||
if (c.status >= 300 || !Number.isSafeInteger(c.json?.id)) { rec.problems.push(`comment ${P.id}: ${c.status} ${c.json?.message ?? ""}`); save(); continue; }
|
||||
const back = await api("GET", `/api/v2/tasks/${P.id}/comments?per_page=50`, undefined, sync);
|
||||
const found = list(back.json).find((x) => x.id === c.json.id);
|
||||
Object.assign(e, { readBack: back.status, found: Boolean(found) });
|
||||
if (back.status !== 200 || !found) { rec.problems.push(`comment ${P.id} read-back: ${back.status}`); save(); continue; }
|
||||
if (P.close) {
|
||||
const full = await api("GET", `/api/v1/tasks/${P.id}`, undefined, key);
|
||||
if (full.status !== 200 || full.json?.id !== P.id) { rec.problems.push(`v1 get ${P.id}: ${full.status}`); save(); continue; }
|
||||
const u = await api("POST", `/api/v1/tasks/${P.id}`, { ...full.json, done: true }, key);
|
||||
const b2 = await api("GET", `/api/v2/tasks/${P.id}`, undefined, sync);
|
||||
const x = { task: P.id, status: u.status, readBack: b2.status, done: b2.json?.done, titleSame: b2.json?.title === before[P.id].title, descriptionSame: b2.json?.description === before[P.id].description, inverse: `mark undone: POST /api/v1/tasks/${P.id} done false (sage key)` };
|
||||
rec.closes.push(x);
|
||||
if (u.status >= 300 || b2.status !== 200 || b2.json?.done !== true || !x.titleSame || !x.descriptionSame) rec.problems.push(`close ${P.id}: update or read-back differs`);
|
||||
}
|
||||
save();
|
||||
}
|
||||
save();
|
||||
process.stdout.write(JSON.stringify(rec, null, 1) + "\n");
|
||||
if (rec.problems.length) process.exit(2);
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"at": "2026-10-21T02:51:32.855Z",
|
||||
"comments": [
|
||||
{
|
||||
"task": 424,
|
||||
"status": 201,
|
||||
"id": 429,
|
||||
"readBack": 200,
|
||||
"found": true
|
||||
}
|
||||
],
|
||||
"problems": []
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"at": "2026-10-21T03:21:23.327Z",
|
||||
"comments": [
|
||||
{
|
||||
"task": 432,
|
||||
"status": 201,
|
||||
"id": 430,
|
||||
"readBack": 200,
|
||||
"found": true
|
||||
}
|
||||
],
|
||||
"problems": []
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"at": "2026-10-21T05:42:18.847Z",
|
||||
"comments": [
|
||||
{
|
||||
"task": 432,
|
||||
"status": 201,
|
||||
"id": 436,
|
||||
"readBack": 200,
|
||||
"found": true
|
||||
}
|
||||
],
|
||||
"problems": []
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"at": "2026-10-21T06:17:35.760Z",
|
||||
"comments": [
|
||||
{
|
||||
"task": 436,
|
||||
"status": 201,
|
||||
"id": 437,
|
||||
"readBack": 200,
|
||||
"found": true
|
||||
}
|
||||
],
|
||||
"problems": []
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"at": "2026-10-21T01:55:44.446Z",
|
||||
"comments": [
|
||||
{
|
||||
"task": 440,
|
||||
"status": 201,
|
||||
"id": 427,
|
||||
"readBack": 200,
|
||||
"found": true
|
||||
},
|
||||
{
|
||||
"task": 441,
|
||||
"status": 201,
|
||||
"id": 428,
|
||||
"readBack": 200,
|
||||
"found": true
|
||||
}
|
||||
],
|
||||
"problems": []
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"at": "2026-10-21T06:58:53.918Z",
|
||||
"comments": [
|
||||
{
|
||||
"task": 432,
|
||||
"status": 201,
|
||||
"id": 438,
|
||||
"readBack": 200,
|
||||
"found": true
|
||||
}
|
||||
],
|
||||
"problems": []
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"at": "2026-10-21T13:13:35.441Z",
|
||||
"project": 19,
|
||||
"created": [
|
||||
{
|
||||
"status": 201,
|
||||
"id": 445,
|
||||
"readBack": 200,
|
||||
"done": false,
|
||||
"relation": 201
|
||||
}
|
||||
],
|
||||
"problems": []
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"at": "2026-10-21T14:57:03.574Z",
|
||||
"comments": [
|
||||
{
|
||||
"task": 445,
|
||||
"status": 201,
|
||||
"id": 442,
|
||||
"readBack": 200,
|
||||
"found": true
|
||||
}
|
||||
],
|
||||
"problems": []
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"at": "2026-10-21T20:44:23.676Z",
|
||||
"comments": [
|
||||
{
|
||||
"task": 458,
|
||||
"status": 201,
|
||||
"id": 478,
|
||||
"readBack": 200,
|
||||
"found": true
|
||||
},
|
||||
{
|
||||
"task": 416,
|
||||
"status": 201,
|
||||
"id": 479,
|
||||
"readBack": 200,
|
||||
"found": true
|
||||
}
|
||||
],
|
||||
"problems": []
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
{
|
||||
"at": "2026-10-21T22:32:05.204Z",
|
||||
"comments": [
|
||||
{
|
||||
"task": 454,
|
||||
"status": 201,
|
||||
"id": 508,
|
||||
"readBack": 200,
|
||||
"found": true
|
||||
},
|
||||
{
|
||||
"task": 386,
|
||||
"status": 201,
|
||||
"id": 509,
|
||||
"readBack": 200,
|
||||
"found": true
|
||||
},
|
||||
{
|
||||
"task": 412,
|
||||
"status": 201,
|
||||
"id": 510,
|
||||
"readBack": 200,
|
||||
"found": true
|
||||
},
|
||||
{
|
||||
"task": 435,
|
||||
"status": 201,
|
||||
"id": 511,
|
||||
"readBack": 200,
|
||||
"found": true
|
||||
},
|
||||
{
|
||||
"task": 459,
|
||||
"status": 201,
|
||||
"id": 512,
|
||||
"readBack": 200,
|
||||
"found": true
|
||||
},
|
||||
{
|
||||
"task": 462,
|
||||
"status": 201,
|
||||
"id": 513,
|
||||
"readBack": 200,
|
||||
"found": true
|
||||
}
|
||||
],
|
||||
"closes": [
|
||||
{
|
||||
"task": 459,
|
||||
"status": 200,
|
||||
"readBack": 200,
|
||||
"done": true,
|
||||
"titleSame": true,
|
||||
"descriptionSame": true,
|
||||
"inverse": "mark undone: POST /api/v1/tasks/459 done false (sage key)"
|
||||
},
|
||||
{
|
||||
"task": 462,
|
||||
"status": 200,
|
||||
"readBack": 200,
|
||||
"done": true,
|
||||
"titleSame": true,
|
||||
"descriptionSame": true,
|
||||
"inverse": "mark undone: POST /api/v1/tasks/462 done false (sage key)"
|
||||
}
|
||||
],
|
||||
"problems": []
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
1ba3c7efbc84a1d7eb8ee0068d32b7917f4e75cdc4066703944cea4c20db5b93 console-stub.mjs
|
||||
93e7f9740cd330c4f6fdb6fc4fe35e3a4fc1d606322debb4e514ed6033365d8f console-stub-tester.mjs
|
||||
@@ -1,25 +0,0 @@
|
||||
// Re-pin 7247d80c7 P2, second run: console-stub.mjs's loopback listener plus NEW's tester listener on a
|
||||
// private socket under a scratch data root, as cli.mjs starts it for --tester-socket. Usage: COPY DATAROOT.
|
||||
// DATAROOT must be a fresh scratch directory, never ~/.mosaic-dev. projectSave, send and every tester
|
||||
// write record a call; the loopback POST must reach none of them.
|
||||
const [copy, dataRoot] = process.argv.slice(2);
|
||||
if (!dataRoot || dataRoot.includes('.mosaic-dev')) { console.error('usage: COPY SCRATCH_DATAROOT'); process.exit(2); }
|
||||
const { startServer } = await import(`${copy}/packages/webui/src/serve.mjs`);
|
||||
const { startTesterSocket } = await import(`${copy}/packages/webui/src/tester-socket.mjs`);
|
||||
const H = 'a'.repeat(40), calls = [];
|
||||
const files = async () => ({ head: H, files: [{ path: 'docs/README.md' }, { path: 'spec/north-star.md' }] });
|
||||
const file = async ({ path }) => ({ path, content: 'stub', commit: H, head: H });
|
||||
const record = name => async () => { calls.push(name); return { ok: true }; };
|
||||
const server = await startServer({ port: 0, board: 'http://127.0.0.1:9', log: () => {},
|
||||
preview: { host: 'mosaic.example', header: 'x-test-user', user: 'tester' },
|
||||
send: async () => { calls.push('send'); return { id: 1 }; },
|
||||
projectFiles: files, projectFile: file,
|
||||
projectSave: async () => { calls.push('save'); return { path: 'x', commit: H }; } });
|
||||
const tester = await startTesterSocket({ dataRoot, board: 'http://127.0.0.1:9', log: () => {},
|
||||
testerNoSignIn: false, testerProofHeader: null, testerAuthHeader: 'x-test-user',
|
||||
bus: { names: async () => ({}), instances: async () => ({}), routes: async () => ({}) },
|
||||
projectFiles: files, projectFile: file,
|
||||
instancesWrite: record('instances.set'), routesWrite: record('routes.set'), nameWrite: record('name.set') });
|
||||
console.log(`PORT ${server.address().port}`);
|
||||
console.log(`SOCK ${tester.address()}`);
|
||||
process.on('SIGTERM', () => { console.log(`CALLS ${JSON.stringify(calls)}`); server.close(); tester.close(() => process.exit(0)); });
|
||||
@@ -1,13 +0,0 @@
|
||||
// Positive control for console-check.sh: NEW's startServer with stub bus reads, on a free loopback port.
|
||||
// projectSave and send record a call; the loopback POST must reach neither.
|
||||
const [copy] = process.argv.slice(2);
|
||||
const { startServer } = await import(`${copy}/packages/webui/src/serve.mjs`);
|
||||
const H = 'a'.repeat(40), calls = [];
|
||||
const server = await startServer({ port: 0, board: 'http://127.0.0.1:9', log: () => {},
|
||||
preview: { host: 'mosaic.example', header: 'x-test-user', user: 'tester' },
|
||||
send: async () => { calls.push('send'); return { id: 1 }; },
|
||||
projectFiles: async () => ({ head: H, files: [{ path: 'docs/README.md' }, { path: 'spec/north-star.md' }] }),
|
||||
projectFile: async ({ path }) => ({ path, content: 'stub', commit: H, head: H }),
|
||||
projectSave: async () => { calls.push('save'); return { path: 'x', commit: H }; } });
|
||||
console.log(`PORT ${server.address().port}`);
|
||||
process.on('SIGTERM', () => { console.log(`CALLS ${JSON.stringify(calls)}`); process.exit(0); });
|
||||
@@ -1,3 +0,0 @@
|
||||
chief r097436c91816 claude-code since 2026-10-20T22:02:08.951Z
|
||||
pm rc9e993da24cf claude-code since 2026-10-20T22:40:47.969Z
|
||||
# exit 0
|
||||
@@ -1,6 +0,0 @@
|
||||
ActiveState=active
|
||||
DropInPaths=
|
||||
MainPID=721027
|
||||
ExecStart={ path=/home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7/scripts/mosaic ; argv[]=/home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7/scripts/mosaic bus start mosaic-stack --pm ; ignore_errors=no ; start_time=[Wed 2026-10-21 16:59:28 CDT] ; stop_time=[n/a] ; pid=721027 ; code=(null) ; status=0/0 }
|
||||
WorkingDirectory=/home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7
|
||||
# exit 0
|
||||
@@ -1,13 +0,0 @@
|
||||
● jarvis-curation-gate.service loaded failed failed Jarvis curation-gate liveness check (wake the agent if staged pulls sit uncurated)
|
||||
● jarvis-retro-check.service loaded failed failed Jarvis weekly retrospective ARTIFACT check (did Sunday's tick produce a retro?)
|
||||
● jarvis-retro.service loaded failed failed Jarvis weekly retrospective tick
|
||||
● mosaic-install-drift.service loaded failed failed Assert the installed Mosaic binaries still match the committed source (drift, not failure)
|
||||
● mosaic-reconcile.service loaded failed failed intended-state reconciler (read-only divergence detection, 30-min cadence)
|
||||
● mosaic-standup-pm.service loaded failed failed Coordinator standup trigger (evening)
|
||||
● [email protected] loaded failed failed Escalate failed Mosaic unit jarvis-curation-gate.service to the local agent seat
|
||||
● [email protected] loaded failed failed Escalate failed Mosaic unit jarvis-retro-check.service to the local agent seat
|
||||
● [email protected] loaded failed failed Escalate failed Mosaic unit jarvis-retro.service to the local agent seat
|
||||
● [email protected] loaded failed failed Escalate failed Mosaic unit mosaic-install-drift.service to the local agent seat
|
||||
● [email protected] loaded failed failed Escalate failed Mosaic unit mosaic-reconcile.service to the local agent seat
|
||||
● setspark-tmp-guard.service loaded failed failed SetSpark: /tmp and scratch guard
|
||||
# exit 0
|
||||
@@ -1,5 +0,0 @@
|
||||
ActiveState=active
|
||||
SubState=running
|
||||
ActiveEnterTimestamp=Tue 2026-10-13 08:40:19 CDT
|
||||
MainPID=1317
|
||||
# exit 0
|
||||
@@ -1,6 +0,0 @@
|
||||
ActiveState=active
|
||||
DropInPaths=
|
||||
MainPID=721029
|
||||
ExecStart={ path=/usr/bin/node ; argv[]=/usr/bin/node /home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7/packages/webui/src/cli.mjs serve --checkout /mnt/storage/src/mosaic-stack --port 7332 --public-host mosaic.woltje.com --auth-header X-authentik-username --allow-user jason.woltje --tester-socket ; ignore_errors=no ; start_time=[Wed 2026-10-21 16:59:28 CDT] ; stop_time=[n/a] ; pid=721029 ; code=(null) ; status=0/0 }
|
||||
WorkingDirectory=/home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7
|
||||
# exit 0
|
||||
@@ -1,4 +0,0 @@
|
||||
sent 722f6eac to chief
|
||||
chief (RESULT, re 722f6eac) ced93621:
|
||||
I didn't launch a pm. Your message says it authorizes nothing, and I only launch on a bus notice, a staff request from the pm, or a cto merge message, so there's no pm run to name.
|
||||
# exit 0
|
||||
@@ -1,6 +0,0 @@
|
||||
{"ts":1792620126036,"ev":"checked","clean":true,"entryId":"","charsChecked":114}
|
||||
{"ts":1792621178375,"ev":"checked","clean":true,"entryId":"","charsChecked":180}
|
||||
{"ts":1792621498421,"ev":"checked","clean":true,"entryId":"","charsChecked":333}
|
||||
{"ts":1792621627986,"ev":"flagged","clean":false,"entryId":"","charsChecked":93,"findings":[{"rule":"word","source":"ms-unslop:7","detail":"banned word \"additionally\" x1","count":1},{"rule":"word","source":"ms-unslop:7","detail":"banned word \"crucial\" x1","count":1},{"rule":"word","source":"ms-unslop:7","detail":"banned word \"testament\" x1","count":1},{"rule":"word","source":"ms-unslop:7","detail":"banned word \"vibrant\" x1","count":1}]}
|
||||
{"ts":1792621630921,"ev":"notice_injected","entryId":"284c6414-1b70-4209-9870-19805fff823c","findings":[{"rule":"word","source":"ms-unslop:7","detail":"banned word \"additionally\" x1","count":1},{"rule":"word","source":"ms-unslop:7","detail":"banned word \"crucial\" x1","count":1},{"rule":"word","source":"ms-unslop:7","detail":"banned word \"testament\" x1","count":1},{"rule":"word","source":"ms-unslop:7","detail":"banned word \"vibrant\" x1","count":1}]}
|
||||
{"ts":1792621632110,"ev":"checked","clean":true,"entryId":"","charsChecked":8}
|
||||
@@ -1 +0,0 @@
|
||||
{"checked":5,"flagged":1,"patterns":{"ms-unslop:7":4},"notices":1,"broken":null}
|
||||
@@ -1,2 +0,0 @@
|
||||
r7646a7a4a2bd mosaic-stack/chief claude-code claude-opus-5-5 by jason since 2026-10-21T21:59:29.867Z running
|
||||
# exit 0
|
||||
@@ -1,6 +0,0 @@
|
||||
sent 06dda327 to chief
|
||||
chief (RESULT, re 06dda327) e16b31e9:
|
||||
Additionally, it is crucial that this sentence stand as a testament to a vibrant style check.
|
||||
|
||||
[unslop: 1 reply of this session flagged since the last note: banned word "additionally" x1; banned word "crucial" x1; banned word "testament" x1; banned word "vibrant" x1. The session gets a correction notice on its next turn.]
|
||||
# exit 0
|
||||
@@ -1,4 +0,0 @@
|
||||
sent 4699f80a to chief
|
||||
chief (RESULT, re 4699f80a) 9bde6703:
|
||||
received
|
||||
# exit 0
|
||||
@@ -1,4 +0,0 @@
|
||||
sent d4cfb554 to chief
|
||||
chief (RESULT, re d4cfb554) 966c5828:
|
||||
I sent your request to the pm as message ed1063ea-d046-4d64-b077-0d895beee2d7, but no pm session is running, so the message is waiting unread. I haven't launched one, for the same reason as before: your message authorizes nothing, so there's nothing that lets me start a pm session. It will be read the next time a pm session starts.
|
||||
# exit 0
|
||||
@@ -1,2 +0,0 @@
|
||||
chief r7646a7a4a2bd claude-code since 2026-10-21T21:59:29.874Z
|
||||
# exit 0
|
||||
@@ -1,7 +0,0 @@
|
||||
PASS markdown-preview.js is served and equals the copy's
|
||||
PASS /api/config on loopback: send=false edit=false
|
||||
PASS project.files through the Console: head=ae0b17c9586e51da7bc1b7e548c6acf913a55665 files=2 spec=true error=none
|
||||
PASS project.file spec/north-star.md through the Console: commit=ae0b17c9586e51da7bc1b7e548c6acf913a55665 length=99 error=none
|
||||
PASS loopback save refused: HTTP 403 error=read-only sent=false
|
||||
CONSOLE_PASS
|
||||
# exit 0
|
||||
@@ -1,19 +0,0 @@
|
||||
[
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"instance": "chief",
|
||||
"run": "r7646a7a4a2bd",
|
||||
"launchedBy": "jason",
|
||||
"harness": "claude-code",
|
||||
"model": "claude-opus-5-5",
|
||||
"provider": "anthropic",
|
||||
"modelKey": "opus",
|
||||
"pid": 721383,
|
||||
"startTime": "72116004",
|
||||
"runnerPid": 721384,
|
||||
"runnerStartTime": "72116004",
|
||||
"runDir": "/home/jwoltje/.mosaic-dev/launches/mosaic-stack/r7646a7a4a2bd",
|
||||
"startedAt": "2026-10-21T21:59:29.867Z",
|
||||
"live": true
|
||||
}
|
||||
]
|
||||
@@ -1,2 +0,0 @@
|
||||
r7646a7a4a2bd mosaic-stack/chief claude-code claude-opus-5-5 by jason since 2026-10-21T21:59:29.867Z running
|
||||
# exit 0
|
||||
@@ -1,2 +0,0 @@
|
||||
[]
|
||||
# exit 0
|
||||
@@ -1,2 +0,0 @@
|
||||
created project window-20261021-2202 id aa7b4e88-2958-4a0e-a28c-63d0286d1e4c
|
||||
# exit 0
|
||||
@@ -1 +0,0 @@
|
||||
1792620136
|
||||
@@ -1,21 +0,0 @@
|
||||
pointer: /home/jwoltje/.mosaic-dev/state/stack-active.json
|
||||
{"copy":"7247d80c7af7ffa70fc61557406bf491cdf3bfc7","business":"mosaic-stack","pm":true,"claude":"/home/jwoltje/.local/bin/claude","console":["--port","7332","--public-host","mosaic.woltje.com","--auth-header","X-authentik-username","--allow-user","jason.woltje","--tester-socket"],"schema":"3j","activation":"20261021T215926Z-7247d80c7af7","at":"2026-10-21T21:59:31Z"}
|
||||
log (last five lines):
|
||||
{"at":"2026-10-20T19:30:00Z","op":"activate","from":"490e2771d3d057ab76991e2c7859cd251857e64c","to":"490e2771d3d057ab76991e2c7859cd251857e64c","backup":"20261020T192956Z-490e2771d3d0","activation":"20261020T192956Z-490e2771d3d0","result":"ok"}
|
||||
{"at":"2026-10-20T22:02:06Z","op":"activate","from":"490e2771d3d057ab76991e2c7859cd251857e64c","to":"4429a104f6d65ccf165f6c83b5d1dce3147dfde0","backup":null,"activation":"20261020T220206Z-4429a104f6d6","result":"started"}
|
||||
{"at":"2026-10-20T22:02:09Z","op":"activate","from":"490e2771d3d057ab76991e2c7859cd251857e64c","to":"4429a104f6d65ccf165f6c83b5d1dce3147dfde0","backup":"20261020T220206Z-4429a104f6d6","activation":"20261020T220206Z-4429a104f6d6","result":"ok"}
|
||||
{"at":"2026-10-21T21:59:26Z","op":"activate","from":"4429a104f6d65ccf165f6c83b5d1dce3147dfde0","to":"7247d80c7af7ffa70fc61557406bf491cdf3bfc7","backup":null,"activation":"20261021T215926Z-7247d80c7af7","result":"started","interpreter":"{\"path\":\"/usr/bin/python3.14\",\"version\":[3,14,6],\"dev\":66308,\"ino\":3968163,\"sha256\":\"8735f172622a7f8d27e293fd0fd36fc55c4cb9b663b6630d33b57870e36c24cc\"}"}
|
||||
{"at":"2026-10-21T21:59:31Z","op":"activate","from":"4429a104f6d65ccf165f6c83b5d1dce3147dfde0","to":"7247d80c7af7ffa70fc61557406bf491cdf3bfc7","backup":"20261021T215926Z-7247d80c7af7","activation":"20261021T215926Z-7247d80c7af7","result":"ok"}
|
||||
check:
|
||||
bus: /home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7
|
||||
Console: /home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7
|
||||
CLI: /home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7
|
||||
result: pass
|
||||
bus status:
|
||||
host: mosaic-stack, pid 721027, running, since 2026-10-21T21:59:28.399Z, notifier off
|
||||
socket: present
|
||||
writer.lock: pid 721071
|
||||
boot: organization file loaded at 2026-10-21T21:59:28.397Z
|
||||
unit flags: match the pointer
|
||||
drift: 14 commit(s) on refactor since the pointer's copy
|
||||
# exit 0
|
||||
@@ -1,4 +0,0 @@
|
||||
sent b095e39b to chief
|
||||
chief (RESULT, re b095e39b) ca9b2db2:
|
||||
Tester message received: no action taken, nothing launched, re-pin 7247d80c7af7ffa70fc61557406bf491cdf3bfc7 noted.
|
||||
# exit 0
|
||||
@@ -1,2 +0,0 @@
|
||||
mosaic: pm isn't running, so the tester's message was refused and nothing was stored
|
||||
# exit 3
|
||||
@@ -1,4 +0,0 @@
|
||||
sent dd4f8410 to window-20261021-2202/w9
|
||||
assistant (RESULT, re dd4f8410) 4d488a27:
|
||||
Assistant here: I got your mos test message, and I'm taking no action because it authorizes nothing.
|
||||
# exit 0
|
||||
@@ -1,32 +0,0 @@
|
||||
[
|
||||
{
|
||||
"seq": 594,
|
||||
"id": "dd4f8410-e48c-48c0-a234-3c629b652b7e",
|
||||
"at": "2026-10-21T22:02:09.754Z",
|
||||
"business": "mosaic-stack",
|
||||
"from_role": "tester",
|
||||
"from_run": "tester-cli",
|
||||
"to_role": "assistant",
|
||||
"class": "REQUEST",
|
||||
"in_reply_to": null,
|
||||
"decision": null,
|
||||
"corrects": null,
|
||||
"body": "[mos test] reply with one line, then stop",
|
||||
"to_name": null
|
||||
},
|
||||
{
|
||||
"seq": 595,
|
||||
"id": "4d488a27-1092-4c3e-88dd-fac85593d4f7",
|
||||
"at": "2026-10-21T22:02:15.988Z",
|
||||
"business": "mosaic-stack",
|
||||
"from_role": "assistant",
|
||||
"from_run": "r4004e5e09433",
|
||||
"to_role": "tester",
|
||||
"class": "RESULT",
|
||||
"in_reply_to": "dd4f8410-e48c-48c0-a234-3c629b652b7e",
|
||||
"decision": null,
|
||||
"corrects": null,
|
||||
"body": "Assistant here: I got your mos test message, and I'm taking no action because it authorizes nothing.",
|
||||
"to_name": null
|
||||
}
|
||||
]
|
||||
@@ -1,2 +0,0 @@
|
||||
created window-20261021-2202/w9 id b89fcca4-6b82-48bd-9310-fb82c5ae8518 instance assistant
|
||||
# exit 0
|
||||
@@ -1,4 +0,0 @@
|
||||
window-20261020-0801/w9 assistant d0ba7a66
|
||||
window-20261020-2205/w9 assistant 446201de
|
||||
window-20261021-2202/w9 assistant b89fcca4
|
||||
# exit 0
|
||||
@@ -1 +0,0 @@
|
||||
b89fcca4-6b82-48bd-9310-fb82c5ae8518
|
||||
@@ -1,189 +0,0 @@
|
||||
{
|
||||
"total": {
|
||||
"input": 110,
|
||||
"output": 18895,
|
||||
"cacheWrite": 320507,
|
||||
"cacheRead": 981437,
|
||||
"unknownTurns": 1
|
||||
},
|
||||
"byRun": [
|
||||
{
|
||||
"run": "r8fba7e598156",
|
||||
"input": 0,
|
||||
"output": 0,
|
||||
"cacheWrite": 0,
|
||||
"cacheRead": 0,
|
||||
"unknownTurns": 1
|
||||
},
|
||||
{
|
||||
"run": "r4a96e2142e4d",
|
||||
"input": 2,
|
||||
"output": 52,
|
||||
"cacheWrite": 11750,
|
||||
"cacheRead": 0,
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"run": "rc78c9700c8e9",
|
||||
"input": 14,
|
||||
"output": 1519,
|
||||
"cacheWrite": 18187,
|
||||
"cacheRead": 89559,
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"run": "r293f33bcbc63",
|
||||
"input": 2,
|
||||
"output": 44,
|
||||
"cacheWrite": 18595,
|
||||
"cacheRead": 0,
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"run": "r34520a581318",
|
||||
"input": 6,
|
||||
"output": 323,
|
||||
"cacheWrite": 26349,
|
||||
"cacheRead": 14307,
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"run": "r7e99838f9f93",
|
||||
"input": 2,
|
||||
"output": 44,
|
||||
"cacheWrite": 9858,
|
||||
"cacheRead": 0,
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"run": "rc964611b2092",
|
||||
"input": 4,
|
||||
"output": 120,
|
||||
"cacheWrite": 26138,
|
||||
"cacheRead": 23870,
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"run": "rbb708846b605",
|
||||
"input": 12,
|
||||
"output": 2089,
|
||||
"cacheWrite": 17285,
|
||||
"cacheRead": 73823,
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"run": "rc36b17ef3788",
|
||||
"input": 16,
|
||||
"output": 5221,
|
||||
"cacheWrite": 36717,
|
||||
"cacheRead": 202573,
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"run": "r097436c91816",
|
||||
"input": 16,
|
||||
"output": 3340,
|
||||
"cacheWrite": 43923,
|
||||
"cacheRead": 102022,
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"run": "r497f1c817d4d",
|
||||
"input": 2,
|
||||
"output": 80,
|
||||
"cacheWrite": 9856,
|
||||
"cacheRead": 0,
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"run": "rc9e993da24cf",
|
||||
"input": 30,
|
||||
"output": 5871,
|
||||
"cacheWrite": 80018,
|
||||
"cacheRead": 475283,
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"run": "r7646a7a4a2bd",
|
||||
"input": 2,
|
||||
"output": 131,
|
||||
"cacheWrite": 11957,
|
||||
"cacheRead": 0,
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"run": "r4004e5e09433",
|
||||
"input": 2,
|
||||
"output": 61,
|
||||
"cacheWrite": 9874,
|
||||
"cacheRead": 0,
|
||||
"unknownTurns": 0
|
||||
}
|
||||
],
|
||||
"byInstance": [
|
||||
{
|
||||
"instance": "chief",
|
||||
"input": 52,
|
||||
"output": 7454,
|
||||
"cacheWrite": 129451,
|
||||
"cacheRead": 279711,
|
||||
"unknownTurns": 1
|
||||
},
|
||||
{
|
||||
"instance": "coder",
|
||||
"input": 2,
|
||||
"output": 44,
|
||||
"cacheWrite": 18595,
|
||||
"cacheRead": 0,
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"instance": "assistant",
|
||||
"input": 6,
|
||||
"output": 185,
|
||||
"cacheWrite": 29588,
|
||||
"cacheRead": 0,
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"instance": "pm",
|
||||
"input": 50,
|
||||
"output": 11212,
|
||||
"cacheWrite": 142873,
|
||||
"cacheRead": 701726,
|
||||
"unknownTurns": 0
|
||||
}
|
||||
],
|
||||
"byProvider": [
|
||||
{
|
||||
"provider": "anthropic",
|
||||
"input": 110,
|
||||
"output": 18895,
|
||||
"cacheWrite": 320507,
|
||||
"cacheRead": 981437,
|
||||
"unknownTurns": 1
|
||||
}
|
||||
],
|
||||
"byModel": [
|
||||
{
|
||||
"provider": "anthropic",
|
||||
"model": "claude-opus-5-5",
|
||||
"input": 110,
|
||||
"output": 18895,
|
||||
"cacheWrite": 320507,
|
||||
"cacheRead": 981437,
|
||||
"unknownTurns": 1
|
||||
}
|
||||
],
|
||||
"byAccount": [
|
||||
{
|
||||
"account": null,
|
||||
"input": 110,
|
||||
"output": 18895,
|
||||
"cacheWrite": 320507,
|
||||
"cacheRead": 981437,
|
||||
"unknownTurns": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
# exit 0
|
||||
@@ -1,2 +0,0 @@
|
||||
r7646a7a4a2bd mosaic-stack/chief claude-code claude-opus-5-5 by jason since 2026-10-21T21:59:29.867Z running
|
||||
# exit 0
|
||||
@@ -1,19 +0,0 @@
|
||||
[
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"instance": "chief",
|
||||
"run": "r7646a7a4a2bd",
|
||||
"launchedBy": "jason",
|
||||
"harness": "claude-code",
|
||||
"model": "claude-opus-5-5",
|
||||
"provider": "anthropic",
|
||||
"modelKey": "opus",
|
||||
"pid": 721383,
|
||||
"startTime": "72116004",
|
||||
"runnerPid": 721384,
|
||||
"runnerStartTime": "72116004",
|
||||
"runDir": "/home/jwoltje/.mosaic-dev/launches/mosaic-stack/r7646a7a4a2bd",
|
||||
"startedAt": "2026-10-21T21:59:29.867Z",
|
||||
"live": true
|
||||
}
|
||||
]
|
||||
@@ -1,65 +0,0 @@
|
||||
# P1 start 2026-10-21T21:39:52.221Z, REPO HEAD 111ec559c8fa969691f4358d26e1de1c1e6ef32f
|
||||
# plan blob 0c5e1f1c6271f301d680edbc720432e51cddb071
|
||||
# business-check.mjs sha256 eece4d4671e1ce15ba81e1654c641925ac4988b343687b062897392285a8a1a7; SCRIPTS.sha256 line: eece4d4671e1ce15ba81e1654c641925ac4988b343687b062897392285a8a1a7 business-check.mjs
|
||||
# business file sha256 1e49bdf05e62607972958f5b7298cfd600c7825812370e26d7c2a842f2af9b93, mtime 2026-10-19 20:39:58.506635141 -0500
|
||||
|
||||
## P1 status
|
||||
# start 2026-10-21T21:39:52.232Z
|
||||
# command: (cd $REPO && <clean env> scripts/stack-release.sh status mosaic-stack)
|
||||
pointer: /home/jwoltje/.mosaic-dev/state/stack-active.json
|
||||
{"copy":"4429a104f6d65ccf165f6c83b5d1dce3147dfde0","business":"mosaic-stack","pm":true,"claude":"/home/jwoltje/.local/bin/claude","console":["--port","7332","--public-host","mosaic.woltje.com","--auth-header","X-authentik-username","--allow-user","jason.woltje","--tester-port","7333"],"schema":"3i","activation":"20261020T220206Z-4429a104f6d6","at":"2026-10-20T22:02:09Z"}
|
||||
log (last five lines):
|
||||
{"at":"2026-10-20T07:58:02Z","op":"activate","from":"89af38a83afa22a8a4f0d368a0a4030ad15a0efa","to":"490e2771d3d057ab76991e2c7859cd251857e64c","backup":"20261020T075800Z-490e2771d3d0","activation":"20261020T075800Z-490e2771d3d0","result":"ok"}
|
||||
{"at":"2026-10-20T19:29:56Z","op":"activate","from":"490e2771d3d057ab76991e2c7859cd251857e64c","to":"490e2771d3d057ab76991e2c7859cd251857e64c","backup":null,"activation":"20261020T192956Z-490e2771d3d0","result":"started"}
|
||||
{"at":"2026-10-20T19:30:00Z","op":"activate","from":"490e2771d3d057ab76991e2c7859cd251857e64c","to":"490e2771d3d057ab76991e2c7859cd251857e64c","backup":"20261020T192956Z-490e2771d3d0","activation":"20261020T192956Z-490e2771d3d0","result":"ok"}
|
||||
{"at":"2026-10-20T22:02:06Z","op":"activate","from":"490e2771d3d057ab76991e2c7859cd251857e64c","to":"4429a104f6d65ccf165f6c83b5d1dce3147dfde0","backup":null,"activation":"20261020T220206Z-4429a104f6d6","result":"started"}
|
||||
{"at":"2026-10-20T22:02:09Z","op":"activate","from":"490e2771d3d057ab76991e2c7859cd251857e64c","to":"4429a104f6d65ccf165f6c83b5d1dce3147dfde0","backup":"20261020T220206Z-4429a104f6d6","activation":"20261020T220206Z-4429a104f6d6","result":"ok"}
|
||||
check:
|
||||
bus: /home/jwoltje/.local/share/mosaic-stack/copies/4429a104f6d65ccf165f6c83b5d1dce3147dfde0
|
||||
Console: /home/jwoltje/.local/share/mosaic-stack/copies/4429a104f6d65ccf165f6c83b5d1dce3147dfde0
|
||||
CLI: /home/jwoltje/.local/share/mosaic-stack/copies/4429a104f6d65ccf165f6c83b5d1dce3147dfde0
|
||||
result: pass
|
||||
bus status:
|
||||
host: mosaic-stack, pid 2950923, running, since 2026-10-20T22:02:08.133Z, notifier off
|
||||
socket: present
|
||||
writer.lock: pid 2950981
|
||||
boot: organization file loaded at 2026-10-20T22:02:08.125Z
|
||||
unit flags: match the pointer
|
||||
drift: 144 commit(s) on refactor since the pointer's copy
|
||||
# exit 0, end 2026-10-21T21:39:52.532Z
|
||||
|
||||
## P1 values
|
||||
# start 2026-10-21T21:39:52.534Z
|
||||
# command: (cd $REPO && <clean env> node /mnt/storage/src/mosaic-stack/agents/sage/work/window-repin-7247d80c7/p1.mjs)
|
||||
bus.tester true
|
||||
plugins kinds ["channel","harness","usage-source"]
|
||||
plugins usage-source ["transcript"]
|
||||
plugins channel ["cli","webui"]
|
||||
plugins harness ["claude-code"]
|
||||
launch.by "chief"
|
||||
launch.instances includes assistant true
|
||||
role assistant vars.harness "claude-code"
|
||||
role chief vars.harness "claude-code"
|
||||
role coder vars.harness "claude-code"
|
||||
role cto vars.harness "claude-code"
|
||||
role pm vars.harness "claude-code"
|
||||
role reviewer vars.harness "claude-code"
|
||||
roles naming pi 0
|
||||
# exit 0, end 2026-10-21T21:39:52.558Z
|
||||
|
||||
## P1 business-check OLD
|
||||
# start 2026-10-21T21:39:52.582Z
|
||||
# command: (cd $REPO && <clean env> node /mnt/storage/src/mosaic-stack/agents/sage/work/window-plan/repin-de352dfaf/business-check.mjs 4429a104f6d65ccf165f6c83b5d1dce3147dfde0)
|
||||
copy 4429a104f: roles 6, projects 1, arbiters 2
|
||||
HOLDS chief instance.name yes
|
||||
HOLDS pm instance.name no
|
||||
LOAD_OK
|
||||
# exit 0, end 2026-10-21T21:39:52.625Z
|
||||
|
||||
## P1 data console
|
||||
# dataRoot /home/jwoltje/.mosaic-dev
|
||||
# ls -ld $DATA/console:
|
||||
ls: cannot access '/home/jwoltje/.mosaic-dev/console': No such file or directory
|
||||
# ls rc=2
|
||||
# tester.sock path length 45 bytes (limit 107)
|
||||
# P1 end 2026-10-21T21:39:52.650Z
|
||||
@@ -1,174 +0,0 @@
|
||||
{
|
||||
"schema": "3i",
|
||||
"tables": {
|
||||
"decision_events": {
|
||||
"rows": 22,
|
||||
"maxSeq": 22,
|
||||
"sha256": "b016d2a7cb0116252166016822c472af1cc520435a6538ecb7be5db62c6cb4b3"
|
||||
},
|
||||
"decisions": {
|
||||
"rows": 22,
|
||||
"maxSeq": 22,
|
||||
"sha256": "eafcd57d3531f7ac7c768e512632a3975df372c49ffd95abe7d858fd05ce93a8"
|
||||
},
|
||||
"deliveries": {
|
||||
"rows": 1797,
|
||||
"maxSeq": 1797,
|
||||
"sha256": "c152f315d262be6d95ed72e3b1380b814fe02846bf43cb6c670005e1e99411b6"
|
||||
},
|
||||
"events": {
|
||||
"rows": 1678,
|
||||
"maxSeq": 1678,
|
||||
"sha256": "b0f95d910e3cf9245b389290c364bb7d6194cdc63f6954de7619d09401ee5b99"
|
||||
},
|
||||
"instance_names": {
|
||||
"rows": 0,
|
||||
"maxSeq": null,
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"message_threads": {
|
||||
"rows": 4,
|
||||
"maxSeq": null
|
||||
},
|
||||
"messages": {
|
||||
"rows": 591,
|
||||
"maxSeq": 591
|
||||
},
|
||||
"meta": {
|
||||
"rows": 3,
|
||||
"maxSeq": null,
|
||||
"sha256": "89fec56e7293d19e0b2f6cd8c0ef745ebf99e4115abeaea7fbdbc98a261332d9"
|
||||
},
|
||||
"projects": {
|
||||
"rows": 2,
|
||||
"maxSeq": 2,
|
||||
"sha256": "3435f574ab94bc2fcc65fb8605251f30d4e9e63baf38e6fdf3c39c126531aa63"
|
||||
},
|
||||
"role_claims": {
|
||||
"rows": 102,
|
||||
"maxSeq": 102,
|
||||
"sha256": "8d9d55d41954626fb1f6bc8972a118f0117c6d86836f117cc4f85e675bdce5c9"
|
||||
},
|
||||
"task_comment_cursors": {
|
||||
"rows": 310,
|
||||
"maxSeq": 310,
|
||||
"sha256": "2b5d58aab2873619724f018163ca773d25063065c9d2e379de4f2759db837d40"
|
||||
},
|
||||
"task_snapshots": {
|
||||
"rows": 436,
|
||||
"maxSeq": 436,
|
||||
"sha256": "7980e1dd9651cfbf44c2d376db6099c1c593e6389f56eaaf16dadde9da7aa1b5"
|
||||
},
|
||||
"thread_claims": {
|
||||
"rows": 4,
|
||||
"maxSeq": 4,
|
||||
"sha256": "088b8236570d8afe03364b85803fdc5034cce2cef6ed7b16f8b99bf6366524ad"
|
||||
},
|
||||
"thread_opens": {
|
||||
"rows": 0,
|
||||
"maxSeq": null,
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"threads": {
|
||||
"rows": 2,
|
||||
"maxSeq": 2,
|
||||
"sha256": "819fd24c64e279d0debad5ab5dbbe533d8e6f26de58277c69510b9cbbaadbc3a"
|
||||
},
|
||||
"usage_records": {
|
||||
"rows": 56,
|
||||
"maxSeq": 56,
|
||||
"sha256": "7a2b4b5b67e504cf17815ca4d7c452ef0e98da03cc354b196ce298f3e9059525",
|
||||
"byRun": [
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "r8fba7e598156",
|
||||
"input": "0",
|
||||
"output": "0",
|
||||
"unknownTurns": 1
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "r4a96e2142e4d",
|
||||
"input": "2",
|
||||
"output": "52",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "rc78c9700c8e9",
|
||||
"input": "14",
|
||||
"output": "1519",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "r293f33bcbc63",
|
||||
"input": "2",
|
||||
"output": "44",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "r34520a581318",
|
||||
"input": "6",
|
||||
"output": "323",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "r7e99838f9f93",
|
||||
"input": "2",
|
||||
"output": "44",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "rc964611b2092",
|
||||
"input": "4",
|
||||
"output": "120",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "rbb708846b605",
|
||||
"input": "12",
|
||||
"output": "2089",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "rc36b17ef3788",
|
||||
"input": "16",
|
||||
"output": "5221",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "r097436c91816",
|
||||
"input": "16",
|
||||
"output": "3340",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "r497f1c817d4d",
|
||||
"input": "2",
|
||||
"output": "80",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "rc9e993da24cf",
|
||||
"input": "30",
|
||||
"output": "5871",
|
||||
"unknownTurns": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"untimed": [
|
||||
"message_threads",
|
||||
"meta",
|
||||
"task_comment_cursors"
|
||||
]
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
{
|
||||
"schema": "3j",
|
||||
"tables": {
|
||||
"decision_events": {
|
||||
"rows": 22,
|
||||
"maxSeq": 22,
|
||||
"sha256": "b016d2a7cb0116252166016822c472af1cc520435a6538ecb7be5db62c6cb4b3"
|
||||
},
|
||||
"decisions": {
|
||||
"rows": 22,
|
||||
"maxSeq": 22,
|
||||
"sha256": "eafcd57d3531f7ac7c768e512632a3975df372c49ffd95abe7d858fd05ce93a8"
|
||||
},
|
||||
"deliveries": {
|
||||
"rows": 1812,
|
||||
"maxSeq": 1812,
|
||||
"sha256": "105cd22c375a628ffa019c29234be92fdca061b786a68c57041f9277cbcbfdce"
|
||||
},
|
||||
"events": {
|
||||
"rows": 1695,
|
||||
"maxSeq": 1695,
|
||||
"sha256": "3b3732100150c521f5f82249d9f63c6d96cf0349194dd756dab362362767ffdb"
|
||||
},
|
||||
"host_grants": {
|
||||
"rows": 0,
|
||||
"maxSeq": null,
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"hosts": {
|
||||
"rows": 0,
|
||||
"maxSeq": null,
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"instance_names": {
|
||||
"rows": 0,
|
||||
"maxSeq": null,
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"message_threads": {
|
||||
"rows": 6,
|
||||
"maxSeq": null
|
||||
},
|
||||
"messages": {
|
||||
"rows": 595,
|
||||
"maxSeq": 595
|
||||
},
|
||||
"meta": {
|
||||
"rows": 3,
|
||||
"maxSeq": null,
|
||||
"sha256": "3d1adf63d62c70add4a5f0b10cbcd4c8641417aca02915c40a64b30016168398"
|
||||
},
|
||||
"projects": {
|
||||
"rows": 3,
|
||||
"maxSeq": 3,
|
||||
"sha256": "3bc6becbc42cd204bb2be152fba2c1dfb169cef93abdd0874cfc0e5ac832f5c9"
|
||||
},
|
||||
"role_claims": {
|
||||
"rows": 105,
|
||||
"maxSeq": 105,
|
||||
"sha256": "9a9f322ef58434321f59687caf586946cde7f55c8dfc1496c8bf2d05c8b3574c"
|
||||
},
|
||||
"task_comment_cursors": {
|
||||
"rows": 316,
|
||||
"maxSeq": 316,
|
||||
"sha256": "55de22707d7689049ba9f61db59f02aae682a7f8dc224dc6202de86f9f7a7a1c"
|
||||
},
|
||||
"task_snapshots": {
|
||||
"rows": 438,
|
||||
"maxSeq": 438,
|
||||
"sha256": "94e1a82aae791e5675fa4c2ab6284d4a6bdc21c52ed551223f6ca47a7d172899"
|
||||
},
|
||||
"thread_claims": {
|
||||
"rows": 6,
|
||||
"maxSeq": 6,
|
||||
"sha256": "f7cc643a8c9ba2407b1f338e404306c279e9e0a73426a493f1b7cdc0ce2c94ee"
|
||||
},
|
||||
"thread_opens": {
|
||||
"rows": 0,
|
||||
"maxSeq": null,
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"threads": {
|
||||
"rows": 3,
|
||||
"maxSeq": 3,
|
||||
"sha256": "909e67a34c142eb2df626bac1e7e85a46bfec307686ee2333f86ecfdbff49bdf"
|
||||
},
|
||||
"usage_records": {
|
||||
"rows": 60,
|
||||
"maxSeq": 60,
|
||||
"sha256": "50e645efe6383478ab77c3fb24276f189a2988c72d146b5b745197d74e0cbaa0",
|
||||
"byRun": [
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "r8fba7e598156",
|
||||
"input": "0",
|
||||
"output": "0",
|
||||
"unknownTurns": 1
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "r4a96e2142e4d",
|
||||
"input": "2",
|
||||
"output": "52",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "rc78c9700c8e9",
|
||||
"input": "14",
|
||||
"output": "1519",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "r293f33bcbc63",
|
||||
"input": "2",
|
||||
"output": "44",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "r34520a581318",
|
||||
"input": "6",
|
||||
"output": "323",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "r7e99838f9f93",
|
||||
"input": "2",
|
||||
"output": "44",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "rc964611b2092",
|
||||
"input": "4",
|
||||
"output": "120",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "rbb708846b605",
|
||||
"input": "12",
|
||||
"output": "2089",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "rc36b17ef3788",
|
||||
"input": "16",
|
||||
"output": "5221",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "r097436c91816",
|
||||
"input": "16",
|
||||
"output": "3340",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "r497f1c817d4d",
|
||||
"input": "2",
|
||||
"output": "80",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "rc9e993da24cf",
|
||||
"input": "30",
|
||||
"output": "5871",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "r7646a7a4a2bd",
|
||||
"input": "2",
|
||||
"output": "131",
|
||||
"unknownTurns": 0
|
||||
},
|
||||
{
|
||||
"business": "mosaic-stack",
|
||||
"run": "r4004e5e09433",
|
||||
"input": "2",
|
||||
"output": "61",
|
||||
"unknownTurns": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"untimed": [
|
||||
"host_grants",
|
||||
"hosts",
|
||||
"message_threads",
|
||||
"meta",
|
||||
"task_comment_cursors"
|
||||
]
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
# Re-pin window 4429a104f to 7247d80c7 (rows 196, 222, 215, 250, 243 and 66), STATE report (W12)
|
||||
|
||||
Operator and tester: Sage. Plan: `agents/sage/work/window-plan/repin-1024-draft1.md`, sha256
|
||||
111f54ee75426ddc589e89db3015f32ab9f9ba2588bc32fba209f596dea5a27e, checked before W9 (plan blob 0c5e1f1c6271 at P1
|
||||
and W0b). Tool blob f0c144fe5219 (`scripts/stack-release.sh`). P5 found the four release scripts the same at HEAD
|
||||
and NEW. OLD 4429a104f6d65ccf165f6c83b5d1dce3147dfde0, NEW 7247d80c7af7ffa70fc61557406bf491cdf3bfc7. NEW is 135
|
||||
commits past OLD (`git rev-list --count 4429a104f..7247d80c7`). Every stamp below comes from `date -u` or from
|
||||
the transcript `W.txt` in this directory. Mos's gos: mos-1226 (W5), mos-1228 (W9 to W12), mos-1230 (W9 accepted,
|
||||
pm read moved to W12). Q173 covers every step. Mos's mos-1226 ruling overrides decision 96 condition 2 ("Jason
|
||||
present") for this run.
|
||||
|
||||
## Outcome
|
||||
|
||||
NEW is live for mosaic-stack. The store migrated from 3i to 3j, and the Console swapped its 127.0.0.1:7333
|
||||
tester listener for the private socket `~/.mosaic-dev/console/tester.sock`. W0 to W11 passed, and nothing was
|
||||
rolled back. P2 failed once on a script bug, before any live step, and passed on the rerun. That counts as the
|
||||
window's one failure under mos-0823. W12 passed (W12_PASS, row 66 on the chief). The pm requirements read is
|
||||
open: the chief, as designed, won't staff a pm on a tester request, and Mos ruled that this is not a window
|
||||
failure (mos-1234). The W12 section below has the detail.
|
||||
|
||||
Nobody acted as Jason. There was no `--by jason`, no pi, no Save and no `mosaic name`, and `bus.tester` was not
|
||||
touched. Writes through 7332 without a signed-in session are refused (401), which is the baseline mos-1195 asks
|
||||
for before phase 2.
|
||||
|
||||
## Stamps and activation
|
||||
|
||||
| Step | Start (UTC) | Result |
|
||||
| --- | --- | --- |
|
||||
| P1 status, values | 21:39:52Z (HEAD 111ec559c) | pointer OLD, pm true, 3i; business file 1e49bdf0 (`P1.txt`) |
|
||||
| P2 console-check on a stub of NEW, attempt 1 | 21:43:33Z | STOP: the stub path was wrong in `p2.sh`, no check ran (`p2-attempt1.txt`) |
|
||||
| P2 rerun | 21:43:57Z | CONSOLE_PASS without the tester and with `--tester-socket` under a scratch data root (`p2.txt`) |
|
||||
| P3 rehearsal (Mos) | 21:43:38Z to 21:43:42Z | REHEARSAL_PASS, rc 0; migration 3i to 3j adds `hosts` and `host_grants`, no other count moves (`p3/`) |
|
||||
| P3 Console by hand (Mos) | 21:45:23Z to 21:45:24Z | healthz 200, public Host 401, socket 600 in a 700 dir, two tester reads 200, writer.lock released |
|
||||
| P4, P5, P6 | 21:42:06Z | P4 PASS, P5 PASS, `matrix-old.txt` and `tester-old.txt` |
|
||||
| W0 copy NEW, W0b business file copy | 21:48:58Z | copy present, LOAD_OK; W0b sha256 1e49bdf0 |
|
||||
| W1 idle check, S1 | 21:48:58.108Z | chief r097436c91816 and pm rc9e993da24cf idle; S1 c8ad2600 |
|
||||
| W2 status | 21:48:58.494Z | pointer OLD, pm true, 3i, unit flags match, check pass |
|
||||
| W3 plan | 21:48:58.780Z | exit 0, migration 3i to 3j, 135 commits (`W3-plan.txt` 4b6d2421) |
|
||||
| W4 unit read | 21:48:59Z | OLD units, no drop-ins, bus `--pm`, no quote or backslash |
|
||||
| W5 activate --migrate --tester-socket (mos-1226) | 21:59:26Z to 21:59:31Z | exit 0, gate passed, activate ok (`W5.txt`) |
|
||||
| W5 status | after 21:59:31Z | pointer NEW, pm true, 3j, unit flags match, check pass (`W5-status.txt`) |
|
||||
| W9 checks and turns (mos-1228) | 22:02:00Z to 22:02:18Z | pass; pm read refused, see W9 |
|
||||
| W9b run end and S2 | 22:02:43Z, end 22:17:17.542Z, S2 22:17:21Z | ended by the launcher (thread-idle); S2 91d4a5b7 |
|
||||
| W10 | 22:18:51Z to 22:18:52Z | W10_PASS |
|
||||
| W11 reads | 22:19:14Z | W11_READS_OK |
|
||||
| W12 backup and staffing ask | 22:19:31Z | backup ok; chief declined to staff, see W12 |
|
||||
|
||||
Activation id 20261021T215926Z-7247d80c7af7. Pointer `at` 2026-10-21T21:59:31Z. W5 dropped `--tester-port 7333`
|
||||
from the Console flags because the target replaces it with the socket.
|
||||
|
||||
## Backups and hashes
|
||||
|
||||
- Store backup before the migration: `~/.mosaic-dev/backups/stack/20261021T215926Z-7247d80c7af7`, SHA256SUMS
|
||||
sha256 730ca3d0dd9c02e489d05307117820180dc83570c7fe252428841fbd7794bbe7. The stopped store was 3i.
|
||||
- Rollback set: `~/.mosaic-dev/state/stack-rollback/20261021T215926Z-7247d80c7af7`. Rollback goes to 4429a104f.
|
||||
A restore from that backup now loses every event written after 21:59:26Z (mos-1228), so any restore goes to
|
||||
Mos first.
|
||||
- W12 store backup (Q173, before the managed session): `~/.mosaic-dev/backups/w12-20261021T221931Z`, an online
|
||||
copy through sqlite's backup API with the source opened read-only. integrity_check ok, events 1699, maxSeq
|
||||
1699, schema 3j. SHA256SUMS sha256 a4ecd7ba8e24b9f586634619643d72cbef356db683459a41998f513c83cad27a.
|
||||
- Business file: 1e49bdf05e62607972958f5b7298cfd600c7825812370e26d7c2a842f2af9b93 at P1, at W0b and again at
|
||||
W11. The W0b copy is `~/.config/mosaic-dev/businesses/mosaic-stack.json.pre-window-20261021T214858Z` with the
|
||||
same hash. Nothing in the window wrote it. `backups.txt` holds the W0b, W5 and W12 lines.
|
||||
|
||||
## Pointer before and after
|
||||
|
||||
Before (W2): copy 4429a104f6d6, pm true, schema 3i, activation 20261020T220206Z-4429a104f6d6. Console flags
|
||||
`--port 7332 --public-host mosaic.woltje.com --auth-header X-authentik-username --allow-user jason.woltje
|
||||
--tester-port 7333`.
|
||||
|
||||
After (W5, W9 and W11): copy 7247d80c7af7, pm true, schema 3j, activation 20261021T215926Z-7247d80c7af7. Console
|
||||
flags `--port 7332 --public-host mosaic.woltje.com --auth-header X-authentik-username --allow-user jason.woltje
|
||||
--tester-socket`. No `--send`, no `--sso` and no proof pair. Bus pid 721027 since 21:59:28.399Z, Console pid
|
||||
721029. Status shows drift of 14 commits on refactor since the pointer's copy (records, briefs and PRD drafts).
|
||||
|
||||
## Unit ExecStart lines (no Environment values)
|
||||
|
||||
W11, after. Both units active, DropInPaths empty, WorkingDirectory the NEW copy:
|
||||
|
||||
```
|
||||
bus: ~/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7/scripts/mosaic bus start mosaic-stack --pm (MainPID 721027)
|
||||
webui: /usr/bin/node ~/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7/packages/webui/src/cli.mjs serve --checkout /mnt/storage/src/mosaic-stack --port 7332 --public-host mosaic.woltje.com --auth-header X-authentik-username --allow-user jason.woltje --tester-socket (MainPID 721029)
|
||||
```
|
||||
|
||||
W4 read the same two lines on OLD's copy. The bus Environment has 2 assignments with no quote or backslash. The
|
||||
values are not recorded.
|
||||
|
||||
Tunnel: `mosaic-preview-tunnel.service` active, running, MainPID 1317, since 2026-10-13 08:40:19 CDT. The window
|
||||
didn't touch it. P4 before and after shows one R: spec, `R:0.0.0.0:7332:127.0.0.1:7332`.
|
||||
|
||||
## S1, S2 and the store
|
||||
|
||||
S1 (`S1.json`, sha256 c8ad2600f5c0bc12a14b287246a39ea651a8e92bd4c7f3836cf6ee91c5af05fb) is W1's held read on 3i
|
||||
at 21:48:58Z. S2 (`S2.json`, sha256 91d4a5b7ad198b8120628e5688c3ac9fb5c221e370beec55245767d22756d629) is the held
|
||||
read on 3j after the assistant run ended, at 22:17:21Z. SNAP (`snapshot.mjs`, 639fd28a) was checked before each.
|
||||
|
||||
| Table | S1 rows | S2 rows | S2 vs S1 |
|
||||
| --- | --- | --- | --- |
|
||||
| decisions, decision_events | 22, 22 | 22, 22 | same sha256 |
|
||||
| instance_names, thread_opens | 0, 0 | 0, 0 | same sha256 |
|
||||
| meta | 3 | 3 | schema_version 3i to 3j, the digest moves with it |
|
||||
| hosts, host_grants | (no table) | 0, 0 | new in 3j |
|
||||
| deliveries | 1797 | 1812 | +15 |
|
||||
| events | 1678 | 1695 | +17 |
|
||||
| role_claims | 102 | 105 | +3 |
|
||||
| messages | 591 | 595 | +4 (counts only) |
|
||||
| message_threads | 4 | 6 | +2 (counts only) |
|
||||
| usage_records | 56 | 60 | +4 |
|
||||
| projects, threads, thread_claims | 2, 2, 4 | 3, 3, 6 | +1, +1, +2 |
|
||||
| task_snapshots | 436 | 438 | +2 |
|
||||
| task_comment_cursors | 310 | 316 | +6 |
|
||||
|
||||
For every grown table with a seq, maxSeq grew by exactly the row delta. The last 60 events by kind at S2:
|
||||
action.allowed 2, action.refused 2, session.launched 2, session.ended 3, task.changed.external 51. There is no
|
||||
grant.* event (mos-1225), and the bus journal since W5 has no `library:` line. task_snapshots and
|
||||
task_comment_cursors grow from the bus's own Vikunja poll, as the 4429a104f window traced.
|
||||
|
||||
## W9 output
|
||||
|
||||
- Status, console-check (CONSOLE_PASS, d068fe02), the journal counts (one "Proxy: proxy proof off", no
|
||||
"Sign-in:"), the Console cwd on the NEW copy, `console/` drwx------ and `tester.sock` srw-------, one
|
||||
peercred-starts line for this start, and one running chief from this start (r7646a7a4a2bd) all passed.
|
||||
- The pm crossing: rc9e993da24cf ended with the restart and is not listed. No pm launch is live. Mos recorded it
|
||||
as "pm not relaunched by the restart, expected, chief staffs on request" (mos-1230).
|
||||
- `talk chief --tester` (b095e39b): RESULT ca9b2db2, "no action taken, nothing launched".
|
||||
- Project `window-20261021-2202`, thread b89fcca4-6b82-48bd-9310-fb82c5ae8518. `talk --thread` (dd4f8410) got one
|
||||
assistant reply from run r4004e5e09433. `thread read` shows the tester REQUEST and the assistant RESULT.
|
||||
- `threads`, `names` (empty) and `usage` read fine.
|
||||
- The pm read, `talk pm --tester`, exited 3: "pm isn't running, so the tester's message was refused and nothing
|
||||
was stored". Mos moved it to W12.
|
||||
- W9b: the launcher logged launch at 22:02:12.746Z, thread-idle at 22:17:17.517Z and end at 22:17:17.542Z
|
||||
(reason stopped, exit 0). Nobody stopped it by hand.
|
||||
|
||||
## W10
|
||||
|
||||
- Matrix (`matrix-new.txt` against `matrix-old.txt`): lines a to e are byte-identical. Lines f and g were OLD's
|
||||
127.0.0.1:7333 listener (403 "proxy header refused" and the 6575-byte page). NEW has no such listener, so both
|
||||
are 000. Nothing listens on 7333.
|
||||
- Tester reads through NEW's `packages/cli/src/tester-http.mjs` on the socket. The `/api/config` line is
|
||||
identical to `tester-old.txt`: 200, 73 bytes, sha256 e7ef9a40a725f356, tester true, send false, edit false.
|
||||
`/api/bus/agents` is 200 with 1 row, 320 bytes. OLD gave 709 bytes with two rows, the chief and the pm.
|
||||
- P4 again at 22:18:52Z: PASS.
|
||||
- Unsigned writes through 7332 with Host mosaic.woltje.com and no session: `POST /api/seen` 401 and
|
||||
`POST /api/reply` 401, both "sign-in required".
|
||||
|
||||
## W12
|
||||
|
||||
Row 66's live check (Vikunja #454) and the pm requirements read, planned as one pm turn (mos-1230).
|
||||
|
||||
- 22:19:31Z: the store backup above.
|
||||
- `talk chief --tester` (722f6eac) asked the chief to staff one pm. RESULT ced93621: "I didn't launch a pm. Your
|
||||
message says it authorizes nothing, and I only launch on a bus notice, a staff request from the pm, or a cto
|
||||
merge message, so there's no pm run to name."
|
||||
- `w12.sh` polled `launches list --json` for 300 s and stopped with no pm launch.
|
||||
|
||||
There's no tester path to a pm. A tester message to a role nobody holds is refused and nothing is stored (row 170,
|
||||
#1667, `packages/cli/src/cli.mjs:388-391` at NEW), so the chief gets no bus notice. `bus start --pm`
|
||||
(`cli.mjs:510`) launches the business's launch.by, which is the chief. The chief's log `unslop.jsonl` reads checked
|
||||
2, flagged 0, notices 0 before any W12 turn.
|
||||
|
||||
Mos's ruling mos-1234 (22:21:58Z, re sage-2210): one relay try first, then row 66 on the chief, and the pm read
|
||||
is recorded open if no pm launches. The W12 backup covers both steps. `w12b.sh` ran them (22:24:48Z to
|
||||
22:27:13Z, exit 0):
|
||||
|
||||
- Checks first: the wrapper is on NEW, the W12 backup line is in `backups.txt`, and r7646a7a4a2bd is the one
|
||||
live claude-code chief. Baseline unslopCounts `{"checked":2,"flagged":0,"patterns":{},"notices":0,"broken":null}`.
|
||||
- Step 1: `talk chief --tester` (d4cfb554) asked the chief to relay a pm requirements read. RESULT 966c5828: the
|
||||
chief sent it to the pm as message ed1063ea-d046-4d64-b077-0d895beee2d7 and launched no pm ("your message
|
||||
authorizes nothing"). No pm launched within 120 s. The pm read is open (mos-1234 item 3). It runs at the
|
||||
first pm launch from a human message or a real bus notice, and ed1063ea waits unread for that pm. No more
|
||||
chief turns went to it, and nothing goes to Jason for it.
|
||||
- Step 2, row 66 (Vikunja #454): turn 1 (06dda327) asked for one sentence using four banned words. RESULT
|
||||
e16b31e9 carried the operator note `[unslop: 1 reply of this session flagged since the last note: banned word
|
||||
"additionally" x1; ... "vibrant" x1. The session gets a correction notice on its next turn.]`. Turn 2
|
||||
(4699f80a) got RESULT 9bde6703, "received".
|
||||
- unslopCounts from NEW's `runner.mjs` after the turns: `{"checked":5,"flagged":1,"patterns":{"ms-unslop:7":4},
|
||||
"notices":1,"broken":null}`. PASS needs checked >= 4, flagged >= 1, notices >= 1 and broken null over the
|
||||
baseline. W12_PASS.
|
||||
|
||||
The log copy is `.w12b-chief-unslop.jsonl`. `W.txt` holds its events with the text stripped.
|
||||
|
||||
## Failed user units
|
||||
|
||||
The same legacy units as the 4429a104f window, all under P19 #393, plus the `mosaic-unit-failed@` markers for
|
||||
them and `setspark-tmp-guard.service`, which belongs to another project. The list is in `.w11-failed.txt`. The
|
||||
window changed none of them.
|
||||
|
||||
## Corrections
|
||||
|
||||
- P2 attempt 1 stopped on a path bug in `p2.sh` before any check ran. The fixed script passed. That is this
|
||||
window's one counted failure (mos-0823).
|
||||
- `w9.sh` held the pm read. Mos moved it to W12 (mos-1230).
|
||||
- mos-1225 replaced the plan's grant reconcile and sweep journal lines with "no grant.* event added".
|
||||
- W12 as planned stopped with no pm (`w12.sh` exit 1). That was a missing route, not a check failure, so it isn't
|
||||
counted under mos-0823. Mos split the step (mos-1234), and `w12b.sh` ran the rest.
|
||||
|
||||
## Files
|
||||
|
||||
`W.txt` (transcript), `S1.json`, `S2.json`, `matrix-old.txt`, `matrix-new.txt`, `tester-old.txt`, `backups.txt`,
|
||||
`W3-plan.txt`, `W5.txt`, `W5-status.txt`, `W5-launched.txt`, `P1.txt`, `p2-attempt1.txt`, `p2.txt`,
|
||||
`p2-units.txt`, `p4.txt`, `p5.txt`, `p3/` (Mos's rehearsal and hand Console check), `p456.sh`, `w0.sh`, `w9.sh`,
|
||||
`w9b.sh`, `w10.sh`, `w11.sh`, `w12.sh`, `w12b.sh`, `w9b.out`, `w12.out`, `w12b.out`, and the `.w9*`, `.w11*`,
|
||||
`.w12*` and `.w12b*` reads. The
|
||||
store snapshot tool is `snapshot.mjs` (639fd28a).
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,153 +0,0 @@
|
||||
plan: activate for mosaic-stack
|
||||
from: 4429a104f6d65ccf165f6c83b5d1dce3147dfde0
|
||||
to: 7247d80c7af7ffa70fc61557406bf491cdf3bfc7
|
||||
store schema: 3i (read from the store the running bus holds)
|
||||
target schema: 3j
|
||||
migration: 3i to 3j, after a backup of the stopped store
|
||||
migration steps: 3i to 3j
|
||||
needs: --migrate (given)
|
||||
needs: Jason present for this run (decision 96 condition 2)
|
||||
backup: the run backs up the stopped store to /home/jwoltje/.mosaic-dev/backups/stack/<activation>/ before any migration
|
||||
commits: the run adds 135 (newest first, at most 200):
|
||||
7247d80c7 row 196: human boundary on peer credentials, interpreter receipt and the Console tester socket (#1694)
|
||||
666173292 sessions: Sage row 222 landing, PRD 1.9 and 1.10, Pocket ID row 255, 196 r6 grants, overlap class rule (mos-1204)
|
||||
21def2850 queue: revs 2968-2976; Gander 196 r5 manifest and r6 changes move, Sage 222 review request and done, Duckworth 196 m1 changes record, rows 254 and 255 added
|
||||
add0f1aae PRD 1.10: REQ-INST-2, a bundled Pocket ID for users with no OIDC provider, post-v1 (Q203, mos-1204)
|
||||
7d08237e1 brief: bundled Pocket ID for users with no OIDC provider, design (Q203, Vikunja #458, mos-1202)
|
||||
f48725cfc PRD 1.9: REQ-WEB-2, Console decide buttons for a human the Console signed in, and the REQ-DEC-3 amendment (mos-1202)
|
||||
0de97f429 brief: library sync follow-up, client timeout, STATUS codes and README (row 222 deferrals, #1723)
|
||||
0b33f5e9d row 222: C2-03a fetch-only library sync, askpass helper, bus verb and timer (#1723)
|
||||
358695528 sessions: Sage row 250 landing, 196 r5 run 4 and resume, F27 row 253; Dewey 66 r4, 251 r1 and 222 r1 lines; Darkwing 251 line
|
||||
a54a17f3d queue: revs 2905-2967 (rows 66, 215, 243, 250 landings; 196, 222, 244, 250, 251 rounds; row 253 added)
|
||||
0cdead66c brief: F27, case2-unit.sh and case1-accept.sh move to --tester-socket, chained after row 196 (#1758)
|
||||
1b6158ce2 row 250: K12 holds the stop's release while it reads the shim, the release answers the events read's reason, and R13 closes its controller (#1755)
|
||||
081ff6b12 sessions: Sage row 215 landing, 196 r4 grant after the base change, slot order for 250, 222, 244 and 251; Herb row 215 line
|
||||
be86adbff sessions: Filbert row 250 round 2 static review, approve
|
||||
d163afc47 sessions: Filbert row 250 round 1 static review, changes
|
||||
e54e05463 row 215: C2-04 the library entry in the business file, consumer skips, M9 organization-projects-protected, the bare mirror, library.file and library.status (#1716)
|
||||
6096b051b row 243: tests that depend on the gate umask set their file modes; stack-instances bootstraps under an explicit umask with a 077 subtest (#1754)
|
||||
9a8c8860d sessions: Sage row 66 landing, J2 brief and REQ-WEB-2 wording, gate coordination for 196 r2, 215, 243, 250, 251
|
||||
6195a00f8 sessions: Filbert row 215 round 2 merge-scoped review, approve
|
||||
3b0aef995 deferred: row 66 live checks, Claude Code at the first re-pin with row 66 and pi after #383, Vikunja #454 (mos-1186)
|
||||
2c38325ec row 66: managed sessions run the unslop check on both harnesses, the operator note on the RESULT, a correction notice on the next turn, and unslop.jsonl counts (#1559)
|
||||
640aa03f2 brief: Console inbox Approve and Deny for grant requests, Vikunja #435 (mos-1193)
|
||||
a36523713 test: resolve the real Docker binary inside lane fixtures
|
||||
5afff5490 brief: T27 row 251 records the monotonic-boundary check, 8 of 80 adds lost the key (mos-1185 item 2)
|
||||
f33932921 brief: T27 lists no identities right after ssh-add -t 1, Vikunja #453 (mos-1185 item 2); row 197 lane-b observation (item 3)
|
||||
1be656ac9 brief: K12 reads cgroup.events after cgroup.kill under load, Vikunja #450 (mos-1182 item 3)
|
||||
19d3d5f02 sessions: Filbert row 66 round 4 review, approve
|
||||
6c75887b0 sessions: Sage 10-21 afternoon (rows 249, 197, 222, 66, queue revs 2642-2904), with pending Dewey and Researcher lines
|
||||
0636721e6 queue: revs 2642-2904 (rows 234, 235, 249 landed; 212, 213, 218, 221, 231, 247 landed; 228, 233, 238, 240, 195, 245, 248 landed; 197 r8 approve, 215 r1 approve, 66 round 4; Case 2 and installer row notes)
|
||||
7b9737953 deferred: row 248 Webby N1, the grant executor test sleep 30 can outlive its test; Duckworth deferred it in the row 249 review (#1751 c30070)
|
||||
9de5a57ab row 249: row 235 follow-up, a grant whose install never returned records hostLineLeft, since the remote add can outlive an abort or a timeout (#1751)
|
||||
8ca064158 sessions: Filbert row 215 candidate review r1, approve
|
||||
8a04f4aa4 row 248: row 235 follow-up, the grant-executor hold-add and hold-remove stubs stop when their test dir is gone, so no stub outlives its test (#1750)
|
||||
bc579f7a8 docs: host run sheet section 4, the apt-get download W: line as root is expected, and the profile's sha256 is checked again at /etc/apparmor.d (mos-1168)
|
||||
6de1ebc62 plans: row 235 follow-up brief, the grant undo records a host line it can't prove gone (mos-1166, gizmoduck-0139, duckworth-0091)
|
||||
540239b6b plans: row 235 follow-up brief, the held grant-executor stubs stop when their test dir is gone
|
||||
6d5545d44 row 245: row 195 follow-up, F9 runs node as root only at the pinned root-only path, the header and TOOLS.md list what root runs, F6 refuses .. after claude-<pin>/ (Duckworth N1-N3, #1693)
|
||||
856c1826b row 247: C2-20b persona import follow-up, keys from config.yaml print as JSON strings, the dry run applies C2-08's fence and refuses, privateDir refuses an EEXIST race by name (#1749)
|
||||
f8276c5eb row 218: C2-12 setup sheet for Melanie and the library survey run sheet (#1719)
|
||||
b65f3a0e8 sessions: Darkwing row 245 slot green, round 1 in review
|
||||
5c6f73ed7 plans: C2-03a brief, the mirror HEAD is a symbolic ref to refs/heads/served so the C2-12 survey reads the served commit
|
||||
947101d8a sessions: Sage 235, 221 and C2-20b landings, 197 r7 request and proof prep
|
||||
335bb3e30 plans: C2-20b brief (row 221 follow-up, Webby N1, N2 and N4) and DEFERRED for N3, Morgana's 213 B3 anchor
|
||||
300766450 row 221: C2-20 Bean and Chet persona import, stage and install script with a count-only dry run, personaTextFault exported from bundle.mjs, yaml 2.9.0 exact, fixture Hermes home and read trace (#1722)
|
||||
b1fece6f0 row 235: machine grant row b, raise binding, executor, reconcile, revoke and sweep, creative roles refused at raise, recheck and host.run, N10 (#1741)
|
||||
aa19a2464 sessions: Darkwing row 245 built, slot asked
|
||||
29ce1e360 row 231: C2-01b library reader and survey fixes: control and bidi escapes, front matter list links, an unresolved body embed to a non-.md target is an attachment (#1733)
|
||||
62ddc96cc plans: row 195 follow-up (Duckworth N1-N3) and the .53 window row, which carries 195's done condition after its early done move
|
||||
d6cff0cdd deferred: Duckworth's N1-N3 on row 195, the Case 1 acceptance script's root parse order, header and prefix match
|
||||
361ba2387 row 213: Case 2 C2-08 creative roles, persona file and block, M1, M2, M6, M10, prompt passed by file (#1714)
|
||||
b65014647 row 195: scripts/case1-accept.sh, root's Case 1 acceptance (F1-F11, P1-P11), its test, TOOLS.md entry (#1693)
|
||||
4364dddb0 plans: row b (235) host.run also refuses a creative agent at spend time, grant record kept for revoke (mos-1164, sage-1908)
|
||||
01e1fe512 plans: row b (235) refuses a host grant to a creative role, after row 213 lands (mos-1163, Webby N2 on 213 r4)
|
||||
38b83ea5c sessions: Sage, 212 landing, 197 proof stop and r6, rows 243/244, row 66 r4b
|
||||
fefd54e13 deferred: N7 lane image base inspect; brief for two gate environment rows (mos-1162)
|
||||
ee7b2f137 row 212: packages/library, mapping, scope, reader, resolver, R-rules, renderItems, survey (#1713)
|
||||
f6c70f944 sessions: Darkwing, row 195 build in review (37171f65b, rev 2756), slot green 22/22, 12/12 mutants, gate 662/0 + 429/0
|
||||
b3b2374ea sessions: Filbert, row 215 manifest r2 approve
|
||||
696255f88 sessions: Filbert, row 215 manifest review, changes requested (B1-B3)
|
||||
059577886 deferred: gate runs mount the host pi auth file (Webby N4 on the row 197 proof driver, traced by Herb)
|
||||
4ced5e63d sessions: Sage, rows 240, 228 and 238 landed (c515273db, 86249ac55, d49b1f2bd), 197 r5 rebuild, Gosalyn 212 slot (sage-1788..1826)
|
||||
e7078e6a8 deferred: Webby's row 238 N1, the sso-config first-step hint has no business (#1744)
|
||||
d49b1f2bd row 238: stack-release's sso-config first step carries --instance NAME on a named instance (#1744)
|
||||
86249ac55 row 228: ZAI_API_KEY in the session env allowlist (#1729)
|
||||
59f817c32 sessions: Darkwing, row 195 DESIGN r7 pushed (5425ea2f3), Duckworth review requested (Gitea 29960), row 226 items to Gosalyn
|
||||
c515273db row 240: installer I4, root's host check, its pins and the boot unit; I3's N1, N4 and N5 (#1746, Vikunja #432)
|
||||
da3051ccc deferred: Filbert's row 240 N1 and N2 (29945, #1746); 10-24 window draft Q1 takes the mos-1161 ruling
|
||||
060a17b54 sessions: Filbert, row 240 round 1 approve (29945, rev 2696)
|
||||
ffd90e7fc sessions: Darkwing, row 240 in review round 1 (ad1b23ab2, manifest 573ece95, revs 2694 and 2695), with its BUILD-LOG entry
|
||||
02709125a sessions: Sage, row 234 landing c771a36f4, 235 briefed, rebuilt-row slot order, 10-24 draft NEW (sage-1766..1787)
|
||||
c771a36f4 row 234: machine grant row a, host enrollment, store records and bus schema 3i to 3j (#1740, Vikunja #436)
|
||||
caa4b5944 sessions: Sage, row 233 landing 57f59e0c3, 234 gate stop and r3, 240 briefed, 197/238 drift (sage-1742..1758)
|
||||
57f59e0c3 row 233: installer I3, stack-upgrade.sh and the host run sheet (#1735, Vikunja #432)
|
||||
5465fd52d sage: DEFERRED, checkCreative doesn't refuse credentials (row 213 r3 Webby N1, mos-1160)
|
||||
b00d7d94d sage: row 240 (I4) carries Filbert N1, N4 and N5 from the 233 review; N2 and N3 go to DEFERRED (29922, sage-1727)
|
||||
642a9b87d sessions: Filbert, row 233 round 1 approve (29922, rev 2659)
|
||||
16019b80e sessions: Darkwing, row 233 in review round 1 (1a1dc80ca, manifest 464ce9eb, revs 2644 and 2647), with its BUILD-LOG entry
|
||||
9b5362018 sage: 10-24 window draft 0 counts grant look-alike events before --migrate (row 234 A22b, gizmoduck-0107)
|
||||
7662b0490 sage: 10-24 window draft 0 adds rows 232 (e65a3ab4d), 241 (5d4a61776) and 242 (5fb736b92, fc1cb856b); 199 and 210 evidence list due in draft 1
|
||||
04ce8dfd5 queue: revs 2639-2641 (row 242 Duckworth approve record, landing note and done)
|
||||
fc1cb856b publish: row 242 follow-up docs, the git socket comments name the hold and the late record; BUILD.md residual and :311 cite (Duckworth N1, N2, N4, #1748)
|
||||
c0c4907af sessions: Sage, rows 241 (5d4a61776) and 242 (5fb736b92) landed, queue revs 2628-2641
|
||||
5fb736b92 publish: a retry after publish-timeout pushes once; the bus holds the decision until its push ends and records a late push (row 242, #1748, P19 440)
|
||||
96bac588f queue: revs 2628-2638 (row 241 approve record, landing note and done; row 232 landing note and done; row 233 brief re-pin and Darkwing claim; row 242 in review round 1, request 29888)
|
||||
5d4a61776 bus: row 241 one decision lands once; a broker test with two checkLand tickets on one decision, where the second recordLand refuses decision-consumed and records nothing (row 241, #1747, P19 441)
|
||||
e65a3ab4d stack-release: --units external for root-owned units, with confirm, revert and gate --since; stack-copy copy --bundle and wrapper --create (row 232, #1734, installer I1)
|
||||
0444acd08 queue: revs 2618-2627 (row 232 round 2 approve; row 241 in review round 1, request 29868; row 234 and row 242 claimed)
|
||||
052ba95c7 sessions: Filbert row 232 I1 review round 2, approve (#1734)
|
||||
a52d64ed4 sage: 10-24 window draft 0 names the landed commits for rows 210 (f5753c0e8), 237 (d7d943199) and the PRD (0adf8ddfe)
|
||||
8fede5fc6 sessions: Sage, row 210 landed f5753c0e8, queue revs 2604-2617
|
||||
c084d8d42 queue: revs 2604-2617 (row 210 done, landed f5753c0e8; rows 241 and 242 added and briefed, 241 claimed by Megavolt; row 234 briefed)
|
||||
f5753c0e8 host access: agent host sudo through the credential store, host.run over broker.sock (row 210, #1707)
|
||||
9d165be8c plans: row 237 follow-up N1 brief, a retry after publish-timeout pushes once (duckworth-0069, P19 440)
|
||||
c25785d3d plans: row 237 follow-up brief, one decision lands once, tests at the broker (megavolt-0069, sage-1651, P19 441)
|
||||
ad95c888c sessions: Sage, row 237 and PRD 1.7+1.8 landed, queue revs 2540-2603
|
||||
584e2bd82 queue: revs 2540-2603 (rows 199, 200, 230, 237 done; 210 r4 and 238 in review; 232 in review round 1 approve; 233 briefed; rows 239 and 240 added)
|
||||
0adf8ddfe prd: Mosaic Stack PRD versions 1.7 and 1.8, status approved version 1.8 (DECISIONS Q192, decision d52febb5, Vikunja #434)
|
||||
d7d943199 bus: one decision, one open publish; checkPublish refuses publish-busy while another ticket holds the decision (row 237, #1743)
|
||||
a0e3d7cfd plans: installer I4 hostcheck row brief, split out of I3 (darkwing row 233 G2, sage-1650)
|
||||
9d24ff9b2 sessions: Filbert row 232 I1 review round 1, approve (#1734)
|
||||
6c04b89da plans: row 194 follow-up brief, the revoke under the writer's lock and a fire test (duckworth-0074, mos-1158)
|
||||
6f7dacb41 sage: 10-24 window draft 0 carries PRD 1.7+1.8 (mos-1154, mos-1156, DECISIONS Q192); the live pm cites 1.6 until the window
|
||||
d21b2615c darkwing: row 232 in review round 1 (#1734), BUILD-LOG and SESSIONS lines
|
||||
816d48b03 sage: row 42 run log, Jason's pre-S7 checks (mos-1154); PRD 1.8 r7 raise dropped, Jason approved in T3 (DECISIONS Q192, NOTE.md)
|
||||
011d41ba6 sage: row 42 S7 dates in the run log (sage-1622, mos-1148 C1 C2, Vikunja 442), 10-24 window draft 0 (mos-1145; NEW open), Vikunja scripts and records: 412/424 landing comments, 237 follow-ups 440/441, P19 405-408 and 411 re-plan comments 416-420, read-tasks.mjs (#1524)
|
||||
c8bc5cf4c case2: unit render and host precheck, case2-unit.sh and case2-precheck.sh (row 230, #1732)
|
||||
390ea5261 business: README names nine hard waits, git.push.remote included; row 199 added it to GATED_ONLY (row 199 review N3, duckworth-0068, #1697)
|
||||
cb5fdb064 credentials: a credential store per agent, its own git identity, pushes to a remote (row 199, #1697)
|
||||
76134dfde plans: row 200 follow-up N1 brief (#1744, Launchpad, Webby): the sso-config hint carries --instance NAME
|
||||
9e1085816 stack-release: activate --sso for the Q175 phase 2 window (row 200, #1698)
|
||||
722136772 plans: row 194 item 7 takes the restart route (honker-0044) and item 8 revokes on fire and delete before the business file changes (row 199 D13), with tests and mutants
|
||||
a304dad94 plans: C2-03a askpass ruling (megavolt-0060 to -0063, dewey-0765, gosalyn-0068): fixed argv with followRedirects=false and credential.helper reset, LC_ALL=C, exact-prompt helper with row 199's HOST/NAME checks, no userinfo; tests and four mutants
|
||||
919a84738 plans: #436b build brief (#1742, schema 3j-3k, design r5 1be535aca) and row 199 N1 follow-up (#1743); row 194 carries 199 N2; 193b2 moves to 3k-3l after #436b
|
||||
2d8687bcf sessions: pending lines from Darkwing, Rocko, Launchpad, Morgana, Honker, Gander, Herb, Dewey and Sage (2026-10-20 18:45Z to 23:32Z)
|
||||
1c46d0abf queue: revs 2456-2539. Morgana row 213 in-review rounds 1-2 (2456-2476); Gizmoduck row 210 in-review 1 (2458-2459); Gosalyn row 212 in-review r1 and row 230 start (2464-2470); Duckworth row 210 record (2466); Webby row 213 verdicts r1-r2 and row 200 r3 approve (2469, 2500, 2539); Darkwing row 190 r3 in-progress through row 232 in-progress (2501-2514); Filbert row 190 record and row 66 r3 approve (2504, 2526); Dewey row 66 r3 approve (2529); Megavolt row 199 in-review round 1 (2535-2536); Launchpad row 200 r3 in-progress and in-review (2509-2525); Sage requests, row 190 done, rows 232/233 added and briefed, row 195 after 190 and 233, brief re-pins of 226/230/232/233, row 66 round 3, the row 200 r3 request as jarvis, machine grant rows 234 and 235 added and row 206 after 234 with its 3k brief and piece, the row 199 r1 request as jarvis (2460-2538, 57 revs)
|
||||
f519fb1d2 plans: machine grant rows a (#1740, schema 3i-3j) and b (#1741) briefs from design r6 f9039682e; 193b2 moves to schema 3j-3k after row a
|
||||
b8236a7e1 sessions: Filbert row 66 round 3 APPROVE
|
||||
c7675476b sage: P19 catch-up comments 411-413 on 413 (row 189 landed, no-send activate), 424 (row 210 status) and 414 (rows 201 and 204 landed)
|
||||
9de7ad829 sage: row 66 r3 packet, rebase of r2 onto c40d846cb (sage/row66-r3 2369c00e36874e1100b301e0d01cbd105c0c5d4f, same patch-id, manifest 42e3876ca168)
|
||||
c40d846cb sage: Vikunja comment scripts and read-backs for row 192 landing (P19 412) and the row 190 W11 comments 406-409
|
||||
01b40d357 plans: C2-13a rulings for gosalyn-0065. G1: default instance only, no --instance, a named instance is a follow-up. G2: library refuses --sso for 10-27, preview set and proof pair stay, --sso waits for Q175 phase 2. Line cites moved to their places after rows 190 and 192 (webui-service.sh, stack-copy.sh, bus-service.sh, serve.mjs), and the Console's WantedBy replaces :41
|
||||
ad6f0be7a plans: installer I1/I3 brief, the stack user's stack-release.sh runs from its own clone of the release bundle (darkwing question, sage-1561)
|
||||
ffc124bf6 plans: installer I2 re-brief of C2-13a (row 230, #1732) and C2-13b (row 226, #1727) for Vikunja #432. Q189: both units WantedBy=multi-user.target, root's 2c step enables both and starts the bus then the Console, no hand start at step 9 (gosalyn-0064, mos-1122, mos-1123). Row 190 landed first, so row 230 renders @CONFIG_ENV@ and @SESSION_ENV@
|
||||
8a14931fa plans: installer briefs I1 (Gitea #1734) and I3 (#1735) for Vikunja #432 (mos-1118, mos-1122). I1 builds on row 190's landing 00d4cc1f6; I3 carries the root lock finding, duckworth-0055's notes, the per-host enrollment step and the credential slot table
|
||||
0272383f5 sessions: Darkwing row 190 landed as 00d4cc1f6, row 195 r6 approved and held
|
||||
00d4cc1f6 stack: several Mosaic Stack instances on one host (row 190, #1688)
|
||||
99a406ed3 sage: re-pin window 490e2771d to 4429a104f (row 192) record, STATE.md (sha256 a4d0a7b12f431f15), W.txt (ca9ad4a09059d3b7), S1/S2, matrices, W10 browser check and diagnosis (screenshots not committed), Mos's P3 rehearsal and flags check, W11 reads. Plan corrections after the window: NEW is 103 commits past OLD (not 106), the P3 flags note (mos-1107), and W10's line g and corrected browser checks (mos-1135, mos-1137). PRD 1.8 raise record, decision 3a6c8fb9 (mos-1140) (#1690; P19 386, 412)
|
||||
d0bbc5c1c business: 193a access level check widened to viewer (row 204, #1702)
|
||||
c9f374284 sessions: Filbert row 190 manifest round 3 APPROVE
|
||||
4385b9ec1 plans: Case 2 briefs. C2-13a factory profile from gosalyn-0057 items 1-3 (--pm, --claude under the --node rule, no proxy flags), row 190 tokens to whichever lands second. New C2-01b for row 212's notes N1-N3, N4 to the C2-12 setup sheet, N5 to C2-10b (webby-0041, sage-1517)
|
||||
afad4993f business: FED R1, access.json loader and validator with covers (row 201, #1699)
|
||||
f41729178 plans: re-pin plan 490e2771d to 4429a104f (row 192, Q175 phase 1), npm ci in the new copy, for Mos's check (mos-1099 item 3)
|
||||
305857c8f queue: revs 2362-2455. Sage: Case 2 rows re-pinned to design r11 (5b8def2f1, row 226 to C2-13b), row 230 C2-13a added and briefed (#1732), row 215 (C2-04) assigned to Herb, row 192 landed 4429a104f with landing note and done, row 228 review request resolved, plus earlier Sage revs. Other seats' revs: Filbert 2362, 2447 (row 190 verdicts); Herb 2395-2396; Webby 2420, 2428 (rows 197/228 verdicts); Morgana 2421 (row 213 claim); Researcher subagent 2422-2424 (row 228); Gosalyn 2426 (row 212 claim); Darkwing 2431, 2433, 2438 (row 190)
|
||||
176a6bf4b sessions: Filbert row 190 manifest round 2 CHANGES (base drift on row 192)
|
||||
5b8def2f1 plans: Case 2 row briefs from Gosalyn's eac92d956 (design r11, approved webby-0038: C2-13 split into C2-13a unit render and host precheck and C2-13b install script and library precheck, C2-04 owner Herb, Console unit without [Install] per mos-1097)
|
||||
bus: scripts/bus-service.sh install --copy 7247d80c7af7ffa70fc61557406bf491cdf3bfc7 --copies /home/jwoltje/.local/share/mosaic-stack/copies --pm --claude /home/jwoltje/.local/bin/claude
|
||||
drop --tester-port 7333 (replaced by private Unix socket); the target Console does not support it
|
||||
proof: off
|
||||
send: off
|
||||
Console: scripts/webui-service.sh install --copy 7247d80c7af7ffa70fc61557406bf491cdf3bfc7 --copies /home/jwoltje/.local/share/mosaic-stack/copies --port 7332 --public-host mosaic.woltje.com --auth-header X-authentik-username --allow-user jason.woltje --tester-socket
|
||||
CLI: scripts/stack-copy.sh wrapper 7247d80c7af7ffa70fc61557406bf491cdf3bfc7 --copies /home/jwoltje/.local/share/mosaic-stack/copies --bin /home/jwoltje/.npm-global/bin
|
||||
interpreter: {"path":"/usr/bin/python3.14","version":[3,14,6],"dev":66308,"ino":3968163,"sha256":"8735f172622a7f8d27e293fd0fd36fc55c4cb9b663b6630d33b57870e36c24cc"}
|
||||
@@ -1 +0,0 @@
|
||||
launched chief: run r7646a7a4a2bd, claude-code claude-opus-5-5
|
||||
@@ -1,20 +0,0 @@
|
||||
pointer: /home/jwoltje/.mosaic-dev/state/stack-active.json
|
||||
{"copy":"7247d80c7af7ffa70fc61557406bf491cdf3bfc7","business":"mosaic-stack","pm":true,"claude":"/home/jwoltje/.local/bin/claude","console":["--port","7332","--public-host","mosaic.woltje.com","--auth-header","X-authentik-username","--allow-user","jason.woltje","--tester-socket"],"schema":"3j","activation":"20261021T215926Z-7247d80c7af7","at":"2026-10-21T21:59:31Z"}
|
||||
log (last five lines):
|
||||
{"at":"2026-10-20T19:30:00Z","op":"activate","from":"490e2771d3d057ab76991e2c7859cd251857e64c","to":"490e2771d3d057ab76991e2c7859cd251857e64c","backup":"20261020T192956Z-490e2771d3d0","activation":"20261020T192956Z-490e2771d3d0","result":"ok"}
|
||||
{"at":"2026-10-20T22:02:06Z","op":"activate","from":"490e2771d3d057ab76991e2c7859cd251857e64c","to":"4429a104f6d65ccf165f6c83b5d1dce3147dfde0","backup":null,"activation":"20261020T220206Z-4429a104f6d6","result":"started"}
|
||||
{"at":"2026-10-20T22:02:09Z","op":"activate","from":"490e2771d3d057ab76991e2c7859cd251857e64c","to":"4429a104f6d65ccf165f6c83b5d1dce3147dfde0","backup":"20261020T220206Z-4429a104f6d6","activation":"20261020T220206Z-4429a104f6d6","result":"ok"}
|
||||
{"at":"2026-10-21T21:59:26Z","op":"activate","from":"4429a104f6d65ccf165f6c83b5d1dce3147dfde0","to":"7247d80c7af7ffa70fc61557406bf491cdf3bfc7","backup":null,"activation":"20261021T215926Z-7247d80c7af7","result":"started","interpreter":"{\"path\":\"/usr/bin/python3.14\",\"version\":[3,14,6],\"dev\":66308,\"ino\":3968163,\"sha256\":\"8735f172622a7f8d27e293fd0fd36fc55c4cb9b663b6630d33b57870e36c24cc\"}"}
|
||||
{"at":"2026-10-21T21:59:31Z","op":"activate","from":"4429a104f6d65ccf165f6c83b5d1dce3147dfde0","to":"7247d80c7af7ffa70fc61557406bf491cdf3bfc7","backup":"20261021T215926Z-7247d80c7af7","activation":"20261021T215926Z-7247d80c7af7","result":"ok"}
|
||||
check:
|
||||
bus: /home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7
|
||||
Console: /home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7
|
||||
CLI: /home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7
|
||||
result: pass
|
||||
bus status:
|
||||
host: mosaic-stack, pid 721027, running, since 2026-10-21T21:59:28.399Z, notifier off
|
||||
socket: present
|
||||
writer.lock: pid 721071
|
||||
boot: organization file loaded at 2026-10-21T21:59:28.397Z
|
||||
unit flags: match the pointer
|
||||
drift: 14 commit(s) on refactor since the pointer's copy
|
||||
@@ -1 +0,0 @@
|
||||
2026-10-21T21:59:26Z
|
||||
@@ -1,11 +0,0 @@
|
||||
stack-release: interpreter: {"path":"/usr/bin/python3.14","version":[3,14,6],"dev":66308,"ino":3968163,"sha256":"8735f172622a7f8d27e293fd0fd36fc55c4cb9b663b6630d33b57870e36c24cc"}
|
||||
stack-release: captured the rollback set: /home/jwoltje/.mosaic-dev/state/stack-rollback/20261021T215926Z-7247d80c7af7
|
||||
stack-release: drop --tester-port 7333 (replaced by private Unix socket); the target Console does not support it
|
||||
stack-release: stopped both units
|
||||
stack-release: stopped store schema: 3i
|
||||
stack-release: backup: /home/jwoltje/.mosaic-dev/backups/stack/20261021T215926Z-7247d80c7af7
|
||||
stack-release: migrated the store to 3j
|
||||
stack-release: installed 7247d80c7af7ffa70fc61557406bf491cdf3bfc7
|
||||
stack-release: gate passed on 7247d80c7af7ffa70fc61557406bf491cdf3bfc7
|
||||
stack-release: activate ok: 7247d80c7af7ffa70fc61557406bf491cdf3bfc7 is live for mosaic-stack
|
||||
# exit 0
|
||||
@@ -1,8 +0,0 @@
|
||||
W0b 2026-10-21T21:48:58Z business file copy /home/jwoltje/.config/mosaic-dev/businesses/mosaic-stack.json.pre-window-20261021T214858Z sha256 1e49bdf05e62607972958f5b7298cfd600c7825812370e26d7c2a842f2af9b93 (source /home/jwoltje/.config/mosaic-dev/businesses/mosaic-stack.json sha256 1e49bdf05e62607972958f5b7298cfd600c7825812370e26d7c2a842f2af9b93)
|
||||
W5 2026-10-21 start 21:59:26Z end 21:59:31Z exit 0
|
||||
activation 20261021T215926Z-7247d80c7af7
|
||||
backup /home/jwoltje/.mosaic-dev/backups/stack/20261021T215926Z-7247d80c7af7 SHA256SUMS sha256 730ca3d0dd9c02e489d05307117820180dc83570c7fe252428841fbd7794bbe7
|
||||
rollback set /home/jwoltje/.mosaic-dev/state/stack-rollback/20261021T215926Z-7247d80c7af7
|
||||
W1 pm session rc9e993da24cf crosses the window idle, no open request (Mos bus read, last seq 591), state read at W9 (mos-1226)
|
||||
# 2026-10-21T22:06:22Z mos-1230: pm not relaunched by the restart, expected, chief staffs on request. At W12 the tester asks the chief to staff a pm (Q173 end-to-end testing), then the pm requirements read, expecting 1.10 and 70 ids; that pm turn is W12's managed session.
|
||||
W12 2026-10-21T22:19:31Z store backup /home/jwoltje/.mosaic-dev/backups/w12-20261021T221931Z (ok events 1699 maxSeq 1699 schema 3j), SHA256SUMS sha256 a4ecd7ba8e24b9f586634619643d72cbef356db683459a41998f513c83cad27a
|
||||
@@ -1,8 +0,0 @@
|
||||
# W10 matrix 2026-10-21T22:18:51Z
|
||||
a 200 ok=true
|
||||
b 401 error="sign-in required"
|
||||
c 401 error="sign-in required"
|
||||
d 403 error="proxy Host refused"
|
||||
e 403 error="tester listener required"
|
||||
f 000 non-json 0 bytes
|
||||
g 000 non-json 0 bytes
|
||||
@@ -1,8 +0,0 @@
|
||||
# P6 2026-10-21T21:42:06Z
|
||||
a 200 ok=true
|
||||
b 401 error="sign-in required"
|
||||
c 401 error="sign-in required"
|
||||
d 403 error="proxy Host refused"
|
||||
e 403 error="tester listener required"
|
||||
f 403 error="proxy header refused"
|
||||
g 200 non-json 6575 bytes
|
||||
@@ -1,21 +0,0 @@
|
||||
// Re-pin 4429a104f to 7247d80c7 (repin-1024-draft1.md), P1: the live business file, read only. Prints the plan's P1 values and nothing else:
|
||||
// bus.tester, the plug-in lists, launch.by, whether launch.instances includes assistant, and each role's
|
||||
// vars.harness and vars["fallback.harness"]. No other value from the file.
|
||||
import { readFileSync } from 'node:fs';
|
||||
const f = `${process.env.HOME}/.config/mosaic-dev/businesses/mosaic-stack.json`;
|
||||
const b = JSON.parse(readFileSync(f, 'utf8'));
|
||||
console.log(`bus.tester ${JSON.stringify(b.vars?.['bus.tester'])}`);
|
||||
const p = b.plugins ?? {};
|
||||
console.log(`plugins kinds ${JSON.stringify(Object.keys(p).sort())}`);
|
||||
for (const k of ['usage-source', 'channel', 'harness']) console.log(`plugins ${k} ${JSON.stringify(p[k])}`);
|
||||
console.log(`launch.by ${JSON.stringify(b.launch?.by)}`);
|
||||
const inst = b.launch?.instances;
|
||||
const names = Array.isArray(inst) ? inst.map((i) => (typeof i === 'string' ? i : i?.name)) : Object.keys(inst ?? {});
|
||||
console.log(`launch.instances includes assistant ${names.includes('assistant')}`);
|
||||
let pi = 0;
|
||||
for (const [r, v] of Object.entries(b.roles ?? {}).sort()) {
|
||||
const h = v?.vars?.harness, fh = v?.vars?.['fallback.harness'];
|
||||
if (h === 'pi' || fh === 'pi') pi++;
|
||||
console.log(`role ${r} vars.harness ${JSON.stringify(h)}${fh === undefined ? '' : ` fallback.harness ${JSON.stringify(fh)}`}`);
|
||||
}
|
||||
console.log(`roles naming pi ${pi}`);
|
||||
@@ -1,24 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Re-pin 4429a104f to 7247d80c7, P1 (repin-1024-draft1.md, blob 0c5e1f1c6271; sage-2179). Read only; nothing stopped.
|
||||
# business-check.mjs runs from the repo copy, checked against SCRIPTS.sha256. From the system config this
|
||||
# prints dataRoot only. A bus.tester other than true stops the window here.
|
||||
set -uo pipefail
|
||||
REPO=/mnt/storage/src/mosaic-stack WIN=$REPO/agents/sage/work/window-repin-7247d80c7
|
||||
OLD=4429a104f6d65ccf165f6c83b5d1dce3147dfde0
|
||||
S=$REPO/agents/sage/work/window-plan/repin-de352dfaf BC=$S/business-check.mjs
|
||||
B=$HOME/.config/mosaic-dev/businesses/mosaic-stack.json
|
||||
{ echo "# P1 start $(date -u +%FT%T.%3NZ), REPO HEAD $(git -C $REPO rev-parse HEAD)"
|
||||
echo "# plan blob $(git -C $REPO rev-parse HEAD:agents/sage/work/window-plan/repin-1024-draft1.md)"
|
||||
echo "# business-check.mjs sha256 $(sha256sum < $BC | cut -c1-64); SCRIPTS.sha256 line: $(grep ' business-check.mjs$' $S/SCRIPTS.sha256)"
|
||||
echo "# business file sha256 $(sha256sum < $B | cut -c1-64), mtime $(stat -c %y $B)"; } | tee -a $WIN/P1.txt
|
||||
(cd $S && grep ' business-check.mjs$' SCRIPTS.sha256 | sha256sum -c -) || { echo "STOP business-check.mjs sha mismatch" | tee -a $WIN/P1.txt; exit 1; }
|
||||
$WIN/w.sh P1.txt "P1 status" scripts/stack-release.sh status mosaic-stack
|
||||
$WIN/w.sh P1.txt "P1 values" node $WIN/p1.mjs
|
||||
grep -qx 'bus.tester true' <(node $WIN/p1.mjs) || { echo "STOP bus.tester is not true" | tee -a $WIN/P1.txt; exit 2; }
|
||||
$WIN/w.sh P1.txt "P1 business-check OLD" node $BC $OLD
|
||||
DATA=$(node -e 'const c=JSON.parse(require("fs").readFileSync(process.env.HOME+"/.config/mosaic-dev/config.json","utf8"));process.stdout.write(String(c.dataRoot))')
|
||||
DATA=${DATA/#\~/$HOME}
|
||||
{ echo; echo "## P1 data console"; echo "# dataRoot $DATA"
|
||||
echo "# ls -ld \$DATA/console:"; ls -ld "$DATA/console" 2>&1; echo "# ls rc=$?"
|
||||
sock="$DATA/console/tester.sock"; echo "# tester.sock path length $(printf %s "$sock" | wc -c) bytes (limit 107)"
|
||||
echo "# P1 end $(date -u +%FT%T.%3NZ)"; } | tee -a $WIN/P1.txt
|
||||
@@ -1,24 +0,0 @@
|
||||
start 2026-10-21T21:43:33Z
|
||||
console-check.sh: OK
|
||||
console-stub.mjs: OK
|
||||
console-stub-tester.mjs: OK
|
||||
## run 1: console-stub.mjs, no tester
|
||||
STOP stub did not start
|
||||
node:internal/modules/cjs/loader:1573
|
||||
throw err;
|
||||
^
|
||||
|
||||
Error: Cannot find module '/mnt/storage/scratch/tmp/rp7247/p2-run1'
|
||||
at Module._resolveFilename (node:internal/modules/cjs/loader:1569:15)
|
||||
at wrapResolveFilename (node:internal/modules/cjs/loader:1123:27)
|
||||
at defaultResolveImplForCJSLoading (node:internal/modules/cjs/loader:1147:10)
|
||||
at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1174:12)
|
||||
at Module._load (node:internal/modules/cjs/loader:1346:5)
|
||||
at wrapModuleLoad (node:internal/modules/cjs/loader:261:19)
|
||||
at Module.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:154:5)
|
||||
at node:internal/main/run_main_module:33:47 {
|
||||
code: 'MODULE_NOT_FOUND',
|
||||
requireStack: []
|
||||
}
|
||||
|
||||
Node.js v26.8.1
|
||||
@@ -1,50 +0,0 @@
|
||||
# P2 unit diffs 2026-10-21T21:42:43Z, REPO HEAD 111ec559c; webui-service.sh and bus-service.sh blobs equal NEW's (P5)
|
||||
## webui: scripts/webui-service.sh render --copy 7247d80c7af7ffa70fc61557406bf491cdf3bfc7 --port 7332 --public-host mosaic.woltje.com --auth-header X-authentik-username --allow-user jason.woltje --tester-socket
|
||||
# render rc=0
|
||||
2c2
|
||||
< # Rendered by scripts/webui-service.sh from packages/webui/systemd/; /home/jwoltje/.local/share/mosaic-stack/copies/4429a104f6d65ccf165f6c83b5d1dce3147dfde0,
|
||||
---
|
||||
> # Rendered by scripts/webui-service.sh from packages/webui/systemd/; /home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7,
|
||||
4c4
|
||||
< # /home/jwoltje/.local/share/mosaic-stack/copies/4429a104f6d65ccf165f6c83b5d1dce3147dfde0 is the read-only copy `install --copy ID` names, and the flags
|
||||
---
|
||||
> # /home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7 is the read-only copy `install --copy ID` names, and the flags
|
||||
18c18
|
||||
< Documentation=file:///home/jwoltje/.local/share/mosaic-stack/copies/4429a104f6d65ccf165f6c83b5d1dce3147dfde0/packages/webui/README.md
|
||||
---
|
||||
> Documentation=file:///home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7/packages/webui/README.md
|
||||
24c24
|
||||
< WorkingDirectory=/home/jwoltje/.local/share/mosaic-stack/copies/4429a104f6d65ccf165f6c83b5d1dce3147dfde0
|
||||
---
|
||||
> WorkingDirectory=/home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7
|
||||
29c29
|
||||
< ExecStart=/usr/bin/node /home/jwoltje/.local/share/mosaic-stack/copies/4429a104f6d65ccf165f6c83b5d1dce3147dfde0/packages/webui/src/cli.mjs serve --checkout /mnt/storage/src/mosaic-stack --port 7332 --public-host mosaic.woltje.com --auth-header X-authentik-username --allow-user jason.woltje --tester-port 7333
|
||||
---
|
||||
> ExecStart=/usr/bin/node /home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7/packages/webui/src/cli.mjs serve --checkout /mnt/storage/src/mosaic-stack --port 7332 --public-host mosaic.woltje.com --auth-header X-authentik-username --allow-user jason.woltje --tester-socket
|
||||
# diff live vs render rc=1
|
||||
## webui diff with the copy path normalized (OLD id -> NEW id in the live unit)
|
||||
29c29
|
||||
< ExecStart=/usr/bin/node /home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7/packages/webui/src/cli.mjs serve --checkout /mnt/storage/src/mosaic-stack --port 7332 --public-host mosaic.woltje.com --auth-header X-authentik-username --allow-user jason.woltje --tester-port 7333
|
||||
---
|
||||
> ExecStart=/usr/bin/node /home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7/packages/webui/src/cli.mjs serve --checkout /mnt/storage/src/mosaic-stack --port 7332 --public-host mosaic.woltje.com --auth-header X-authentik-username --allow-user jason.woltje --tester-socket
|
||||
# normalized diff rc=1
|
||||
## bus: scripts/bus-service.sh render --copy 7247d80c7af7ffa70fc61557406bf491cdf3bfc7 --pm --claude /home/jwoltje/.local/bin/claude
|
||||
# render rc=0
|
||||
2c2
|
||||
< # Rendered by scripts/bus-service.sh from packages/cli/systemd/; /home/jwoltje/.local/share/mosaic-stack/copies/4429a104f6d65ccf165f6c83b5d1dce3147dfde0,
|
||||
---
|
||||
> # Rendered by scripts/bus-service.sh from packages/cli/systemd/; /home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7,
|
||||
8c8
|
||||
< Documentation=file:///home/jwoltje/.local/share/mosaic-stack/copies/4429a104f6d65ccf165f6c83b5d1dce3147dfde0/packages/cli/README.md
|
||||
---
|
||||
> Documentation=file:///home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7/packages/cli/README.md
|
||||
14c14
|
||||
< WorkingDirectory=/home/jwoltje/.local/share/mosaic-stack/copies/4429a104f6d65ccf165f6c83b5d1dce3147dfde0
|
||||
---
|
||||
> WorkingDirectory=/home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7
|
||||
30c30
|
||||
< ExecStart=/home/jwoltje/.local/share/mosaic-stack/copies/4429a104f6d65ccf165f6c83b5d1dce3147dfde0/scripts/mosaic bus start %i --pm
|
||||
---
|
||||
> ExecStart=/home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7/scripts/mosaic bus start %i --pm
|
||||
# diff live vs render rc=1
|
||||
# normalized diff rc=0
|
||||
@@ -1,55 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Re-pin 4429a104f to 7247d80c7, P2 stub runs (repin-1024-draft1.md; sage-2179, sage-2186). Launch from /.
|
||||
# Run 1: console-stub.mjs (NEW's startServer, no tester), console-check.sh NEW PORT. Run 2: console-stub-tester.mjs
|
||||
# adds NEW's startTesterSocket on $D/console/tester.sock under a fresh scratch data root; console-check.sh again,
|
||||
# then the socket checks. Both stubs must report CALLS [] on SIGTERM. console-check.sh reads NEW's copy under
|
||||
# the real HOME (W0 made it there) and only reads. Kills only the stub pids it started.
|
||||
set -uo pipefail
|
||||
REPO=/mnt/storage/src/mosaic-stack
|
||||
S=$REPO/agents/sage/work/window-plan/repin-de352dfaf
|
||||
NEW=7247d80c7af7ffa70fc61557406bf491cdf3bfc7
|
||||
C=$HOME/.local/share/mosaic-stack/copies/$NEW
|
||||
[ -n "${TMPDIR:-}" ] && [[ "$TMPDIR" == /mnt/storage/scratch/tmp/* ]] || { echo "STOP TMPDIR must be under /mnt/storage/scratch/tmp"; exit 9; }
|
||||
echo "start $(date -u +%FT%TZ)"
|
||||
(cd $S && grep -E ' (console-check.sh)$' SCRIPTS.sha256 | sha256sum -c -) || { echo "STOP console-check.sh sha"; exit 1; }
|
||||
(cd $S/fixture && sha256sum -c SHA256SUMS) || { echo "STOP fixture sha"; exit 1; }
|
||||
rc=0
|
||||
start_stub() { # out-file, then node args; sets spid and port
|
||||
local o="$1"; shift
|
||||
node "$@" > "$o.out" 2> "$o.err" &
|
||||
spid=$!
|
||||
for _ in $(seq 1 50); do grep -q '^PORT ' "$o.out" && break; sleep 0.1; done
|
||||
port=$(sed -n 's/^PORT //p' "$o.out")
|
||||
[ -n "$port" ] || { echo "STOP stub did not start"; cat "$o.err"; kill -TERM $spid 2>/dev/null; wait $spid 2>/dev/null; exit 1; }
|
||||
}
|
||||
stop_stub() { kill -TERM $spid; wait $spid 2>/dev/null; cat "$1.out"; grep -qx 'CALLS \[\]' "$1.out" && echo "PASS CALLS []" || { echo "FAIL CALLS not []"; rc=1; }; }
|
||||
|
||||
echo "## run 1: console-stub.mjs, no tester"
|
||||
O1=$TMPDIR/p2-run1
|
||||
start_stub $O1 $S/fixture/console-stub.mjs $C
|
||||
echo "stub pid $spid port $port"
|
||||
out=$(bash $S/console-check.sh $NEW $port); r=$?; echo "$out"; echo "console-check rc=$r"; [ $r = 0 ] || rc=1
|
||||
stop_stub $O1
|
||||
|
||||
echo "## run 2: console-stub-tester.mjs with --tester-socket's listener under a scratch data root"
|
||||
D=$(mktemp -d /mnt/storage/scratch/tmp/p2tXXXXXX); echo "data root $D"
|
||||
O2=$TMPDIR/p2-run2
|
||||
node $S/fixture/console-stub-tester.mjs $C $D > $O2.out 2> $O2.err &
|
||||
spid=$!
|
||||
for _ in $(seq 1 50); do grep -q '^SOCK ' $O2.out && break; sleep 0.1; done
|
||||
port=$(sed -n 's/^PORT //p' $O2.out); sock=$(sed -n 's/^SOCK //p' $O2.out)
|
||||
[ -n "$port" ] && [ -n "$sock" ] || { echo "STOP tester stub did not start"; cat $O2.err; kill -TERM $spid 2>/dev/null; wait $spid 2>/dev/null; exit 1; }
|
||||
echo "stub pid $spid port $port sock $sock"
|
||||
out=$(bash $S/console-check.sh $NEW $port); r=$?; echo "$out"; echo "console-check rc=$r"; [ $r = 0 ] || rc=1
|
||||
[ "$sock" = "$D/console/tester.sock" ] && echo "PASS SOCK is \$D/console/tester.sock" || { echo "FAIL SOCK $sock"; rc=1; }
|
||||
st=$(stat -c '%F %a' "$sock"); [ "$st" = "socket 600" ] && echo "PASS sock: $st" || { echo "FAIL sock: $st"; rc=1; }
|
||||
dt=$(stat -c '%F %a' "$D/console"); [ "$dt" = "directory 700" ] && echo "PASS console dir: $dt" || { echo "FAIL console dir: $dt"; rc=1; }
|
||||
code=$(curl -s -o /dev/null -w '%{http_code}' --unix-socket "$sock" http://mosaic-tester.invalid/api/config)
|
||||
[ "$code" = 200 ] && echo "PASS tester /api/config over the socket: 200" || { echo "FAIL tester /api/config: $code"; rc=1; }
|
||||
stop_stub $O2
|
||||
[ ! -e "$sock" ] && echo "PASS socket gone after SIGTERM" || { echo "FAIL socket still there"; rc=1; }
|
||||
[ -s $O1.err ] || [ -s $O2.err ] && { echo "# stub stderr:"; cat $O1.err $O2.err; }
|
||||
left=0; for p in /proc/[0-9]*; do c=$(tr '\0' ' ' < $p/cmdline 2>/dev/null); [[ "$c" == *fixture/console-stub* ]] && { echo "LEFT ${p#/proc/} $c"; left=1; }; done
|
||||
[ $left = 0 ] && echo "sweep: no console-stub process left"
|
||||
echo "end $(date -u +%FT%TZ) rc=$rc"; [ $rc = 0 ] && echo P2_STUBS_PASS || echo P2_STUBS_FAIL
|
||||
exit $rc
|
||||
@@ -1,39 +0,0 @@
|
||||
start 2026-10-21T21:43:57Z
|
||||
console-check.sh: OK
|
||||
console-stub.mjs: OK
|
||||
console-stub-tester.mjs: OK
|
||||
## run 1: console-stub.mjs, no tester
|
||||
stub pid 528928 port 33219
|
||||
PASS markdown-preview.js is served and equals the copy's
|
||||
PASS /api/config on loopback: send=false edit=false
|
||||
PASS project.files through the Console: head=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa files=2 spec=true error=none
|
||||
PASS project.file spec/north-star.md through the Console: commit=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa length=4 error=none
|
||||
PASS loopback save refused: HTTP 403 error=read-only sent=false
|
||||
CONSOLE_PASS
|
||||
console-check rc=0
|
||||
PORT 33219
|
||||
CALLS []
|
||||
PASS CALLS []
|
||||
## run 2: console-stub-tester.mjs with --tester-socket's listener under a scratch data root
|
||||
data root /mnt/storage/scratch/tmp/p2tKarNvB
|
||||
stub pid 529010 port 44335 sock /mnt/storage/scratch/tmp/p2tKarNvB/console/tester.sock
|
||||
PASS markdown-preview.js is served and equals the copy's
|
||||
PASS /api/config on loopback: send=false edit=false
|
||||
PASS project.files through the Console: head=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa files=2 spec=true error=none
|
||||
PASS project.file spec/north-star.md through the Console: commit=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa length=4 error=none
|
||||
PASS loopback save refused: HTTP 403 error=read-only sent=false
|
||||
CONSOLE_PASS
|
||||
console-check rc=0
|
||||
PASS SOCK is $D/console/tester.sock
|
||||
PASS sock: socket 600
|
||||
PASS console dir: directory 700
|
||||
PASS tester /api/config over the socket: 200
|
||||
PORT 44335
|
||||
SOCK /mnt/storage/scratch/tmp/p2tKarNvB/console/tester.sock
|
||||
CALLS []
|
||||
PASS CALLS []
|
||||
PASS socket gone after SIGTERM
|
||||
/mnt/storage/src/mosaic-stack/agents/sage/work/window-repin-7247d80c7/p2.sh: line 52: /proc/502127/cmdline: No such file or directory
|
||||
sweep: no console-stub process left
|
||||
end 2026-10-21T21:43:58Z rc=0
|
||||
P2_STUBS_PASS
|
||||
@@ -1,16 +0,0 @@
|
||||
import sqlite3, sys, json
|
||||
def counts(p):
|
||||
c = sqlite3.connect(f"file:{p}?mode=ro", uri=True)
|
||||
t = [r[0] for r in c.execute("select name from sqlite_master where type='table' order by name")]
|
||||
out = {n: c.execute(f'select count(*) from "{n}"').fetchone()[0] for n in t}
|
||||
la = c.execute("""select count(*) from events where json_extract(body,'$.action')='action.allowed' and (
|
||||
coalesce(json_extract(body,'$.body.action'),'') like 'grant.%' or coalesce(json_extract(body,'$.body.operation'),'') like 'grant.%'
|
||||
or instr(body,'hostLineLeft')>0)""").fetchone()[0] if 'events' in t else None
|
||||
la2 = c.execute("""select count(*) from events where (json_extract(body,'$.action') like 'grant.%' or json_extract(body,'$.operation') like 'grant.%' or instr(body,'hostLineLeft')>0)""").fetchone()[0]
|
||||
return out, la, la2
|
||||
a, laa, la2a = counts(sys.argv[1]); b, lab, la2b = counts(sys.argv[2])
|
||||
for k in sorted(set(a) | set(b)):
|
||||
mark = '' if a.get(k) == b.get(k) else ' CHANGED'
|
||||
print(f"{k}: {a.get(k)} -> {b.get(k)}{mark}")
|
||||
print("lookalike_action_allowed backup", laa, "rehearsal", lab)
|
||||
print("any_grant_event backup", la2a, "rehearsal", la2b)
|
||||
@@ -1,21 +0,0 @@
|
||||
decision_events: 21 -> 21
|
||||
decisions: 21 -> 21
|
||||
deliveries: 1726 -> 1726
|
||||
events: 1527 -> 1527
|
||||
host_grants: None -> 0 CHANGED
|
||||
hosts: None -> 0 CHANGED
|
||||
instance_names: 0 -> 0
|
||||
message_threads: 2 -> 2
|
||||
messages: 567 -> 567
|
||||
meta: 3 -> 3
|
||||
projects: 1 -> 1
|
||||
role_claims: 100 -> 100
|
||||
sqlite_sequence: 12 -> 12
|
||||
task_comment_cursors: 215 -> 215
|
||||
task_snapshots: 401 -> 401
|
||||
thread_claims: 2 -> 2
|
||||
thread_opens: 0 -> 0
|
||||
threads: 1 -> 1
|
||||
usage_records: 30 -> 30
|
||||
lookalike_action_allowed backup 0 rehearsal 0
|
||||
any_grant_event backup 0 rehearsal 0
|
||||
@@ -1,8 +0,0 @@
|
||||
import sqlite3, sys
|
||||
c = sqlite3.connect(f"file:{sys.argv[1]}?mode=ro", uri=True)
|
||||
cols = [r[1] for r in c.execute("pragma table_info(decision_events)")]
|
||||
print(cols)
|
||||
kind = "op"
|
||||
q = f"""select d.action, (select e.{kind} from decision_events e where e.decision=d.id order by e.seq desc limit 1) from decisions d order by d.seq"""
|
||||
from collections import Counter
|
||||
print(Counter(c.execute(q).fetchall()))
|
||||
@@ -1,2 +0,0 @@
|
||||
['seq', 'decision', 'at', 'op', 'by', 'choice', 'note', 'via']
|
||||
Counter({('prd.approve', 'resolved'): 7, ('git.merge.protected', 'resolved'): 6, ('policy.change', 'resolved'): 6, ('task.scope.change', 'resolved'): 1, ('decision.resolve.technical', 'resolved'): 1})
|
||||
@@ -1 +0,0 @@
|
||||
2026-10-21T21:43:42Z
|
||||
@@ -1,17 +0,0 @@
|
||||
2026-10-21T21:45:23Z
|
||||
host pid 557933 console pid 558039
|
||||
healthz: {"ok":true} 200
|
||||
api/config: {"board":"http://127.0.0.1:7331","send":false,"edit":false} 200
|
||||
api/config Host public: {"error":"sign-in required"} 401
|
||||
socket 600 jwoltje /home/jwoltje/.mosaic-dev/rehearsals/20261021T214338Z-7247d80c7af7/data/console/tester.sock
|
||||
dir 700 jwoltje /home/jwoltje/.mosaic-dev/rehearsals/20261021T214338Z-7247d80c7af7/data/console
|
||||
tester GET /api/config: {"status":200,"text":"{\"board\":\"http://127.0.0.1:7331\",\"tester\":true,\"send\":false,\"edit\":false}","body":{"board":"http://127.0.0.1:7331","tester":true,"send":false,"edit":false}}
|
||||
rc=0
|
||||
tester GET /api/bus/agents: {"status":200,"text":"{\"rows\":[],\"at\":\"2026-10-21T21:45:24.717Z\"}","body":{"rows":[],"at":"2026-10-21T21:45:24.717Z"}}
|
||||
rc=0
|
||||
console exit 0
|
||||
host exit 0
|
||||
writer.lock released
|
||||
receipt lines: 2
|
||||
0
|
||||
2026-10-21T21:45:24Z
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# P3 (Mos): NEW's bus host (--no-launch) and Console with the pointer's flags on the rehearsal root.
|
||||
# --port 7341 stands in for 7332, --tester-socket for --tester-port 7333. No request carries the auth header.
|
||||
set -u
|
||||
R=/home/jwoltje/.mosaic-dev/rehearsals/20261021T214338Z-7247d80c7af7
|
||||
C=/home/jwoltje/.local/share/mosaic-stack/copies/7247d80c7af7ffa70fc61557406bf491cdf3bfc7
|
||||
E=(env -i HOME="$HOME" PATH="$PATH" MOSAIC_CONFIG="$R/config/config.json")
|
||||
date -u +%FT%TZ
|
||||
"${E[@]}" "$C/scripts/mosaic" bus start mosaic-stack --no-launch > "$R/hand-host.log" 2>&1 & HP=$!
|
||||
for i in $(seq 1 30); do [ -S "$R/data/bus/broker.sock" ] && break; sleep 0.5; done
|
||||
"${E[@]}" node "$C/packages/webui/src/cli.mjs" serve --port 7341 --business mosaic-stack --public-host mosaic.woltje.com --auth-header X-authentik-username --allow-user jason.woltje --tester-socket > "$R/hand-console.log" 2>&1 & CP=$!
|
||||
for i in $(seq 1 30); do curl -s -o /dev/null http://127.0.0.1:7341/healthz && [ -S "$R/data/console/tester.sock" ] && break; sleep 0.5; done
|
||||
echo "host pid $HP console pid $CP"
|
||||
echo "healthz: $(curl -s -w ' %{http_code}' http://127.0.0.1:7341/healthz)"
|
||||
echo "api/config: $(curl -s -w ' %{http_code}' http://127.0.0.1:7341/api/config)"
|
||||
echo "api/config Host public: $(curl -s -w ' %{http_code}' -H 'Host: mosaic.woltje.com' http://127.0.0.1:7341/api/config)"
|
||||
stat -c 'socket %a %U %n' "$R/data/console/tester.sock"; stat -c 'dir %a %U %n' "$R/data/console"
|
||||
echo "tester GET /api/config: $("${E[@]}" node "$C/packages/cli/src/tester-http.mjs" GET /api/config 2>&1; echo " rc=$?")"
|
||||
echo "tester GET /api/bus/agents: $("${E[@]}" node "$C/packages/cli/src/tester-http.mjs" GET /api/bus/agents 2>&1 | cut -c1-400; echo " rc=${PIPESTATUS[0]}")"
|
||||
kill -TERM "$CP"; wait "$CP"; echo "console exit $?"
|
||||
kill -TERM "$HP"; wait "$HP"; echo "host exit $?"
|
||||
[ -e "$R/data/bus/writer.lock" ] && echo "writer.lock present" || echo "writer.lock released"
|
||||
echo "receipt lines: $(wc -l < "$R/data/bus/peercred-starts.jsonl")"
|
||||
grep -c 'library:' "$R/hand-host.log"
|
||||
date -u +%FT%TZ
|
||||
@@ -1,11 +0,0 @@
|
||||
import sqlite3, sys, json
|
||||
from collections import Counter
|
||||
c = sqlite3.connect(f"file:{sys.argv[1]}?mode=ro", uri=True)
|
||||
rows = c.execute("""select json_extract(body,'$.action'), json_extract(body,'$.body.action'), json_extract(body,'$.operation'), body from events
|
||||
where body like '%organization%'""").fetchall()
|
||||
cnt = Counter(); proj = Counter()
|
||||
for a, ba, op, body in rows:
|
||||
k = (a, ba or op)
|
||||
cnt[k] += 1
|
||||
if '"projects"' in body: proj[k] += 1
|
||||
for k, v in cnt.most_common(12): print(k, v, "with projects key:", proj.get(k, 0))
|
||||
@@ -1 +0,0 @@
|
||||
rc=0
|
||||
@@ -1,25 +0,0 @@
|
||||
PASS copy: 7247d80c7af7ffa70fc61557406bf491cdf3bfc7, schema 3j
|
||||
PASS port: 127.0.0.1:7341 is free
|
||||
PASS backup: /home/jwoltje/.mosaic-dev/backups/stack/20261020T220206Z-4429a104f6d6 matches its SHA256SUMS
|
||||
PASS scratch-root: /home/jwoltje/.mosaic-dev/rehearsals/20261021T214338Z-7247d80c7af7/data from the backup, config and business file under /home/jwoltje/.mosaic-dev/rehearsals/20261021T214338Z-7247d80c7af7/config, business.diff beside them
|
||||
PASS data-root-live: /home/jwoltje/.mosaic-dev/rehearsals/20261021T214338Z-7247d80c7af7/data is not the live data root
|
||||
PASS sessions-live: no running session named in the data root
|
||||
PASS data-root-scratch
|
||||
PASS notify-off: binding null, so no Discord bridge
|
||||
PASS tracker-configured: bootConfig sets no trackers
|
||||
PASS credential-ref-live: 9 reference(s), each a placeholder
|
||||
BACKUP_STORE 20261020T220206Z-4429a104f6d6 schema 3i
|
||||
PASS new-refuses-old-store: 7247d80c7af7ffa70fc61557406bf491cdf3bfc7 refuses the 3i store at a normal open
|
||||
PASS migrate: 3i to 3j
|
||||
PASS new-opens-migrated
|
||||
PASS migrate-again: a second run is a no-op
|
||||
PASS old-refuses-migrated: 4429a104f6d65ccf165f6c83b5d1dce3147dfde0 refuses the 3j store
|
||||
PASS gate: host-up, bus-status, console-up, healthz and copy-match on 7247d80c7af7ffa70fc61557406bf491cdf3bfc7
|
||||
PASS no-session: no sessions.json and no launches under /home/jwoltje/.mosaic-dev/rehearsals/20261021T214338Z-7247d80c7af7/data
|
||||
PASS console-stopped: pid 520145
|
||||
PASS host-stopped: pid 520143
|
||||
PASS host-released-store
|
||||
PASS backup-unchanged
|
||||
PASS live-config-unchanged
|
||||
REHEARSAL_PASS
|
||||
rehearsal directory: /home/jwoltje/.mosaic-dev/rehearsals/20261021T214338Z-7247d80c7af7
|
||||
@@ -1 +0,0 @@
|
||||
2026-10-21T21:43:38Z
|
||||
@@ -1,6 +0,0 @@
|
||||
# P4 2026-10-21T21:42:06Z
|
||||
DropInPaths=
|
||||
ExecStart={ path=/home/jwoltje/.local/bin/chisel ; argv[]=/home/jwoltje/.local/bin/chisel client --fingerprint ce+ISFvMAhuoCRDuc7riIf+hYz87TLHk/C9C/H8QsUg= --keepalive 25s --max-retry-interval 10s http://10.1.1.227:8080 R:0.0.0.0:7332:127.0.0.1:7332 ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }
|
||||
# exit 0
|
||||
# R: specs (1): R:0.0.0.0:7332:127.0.0.1:7332
|
||||
P4 PASS: one R: spec R:0.0.0.0:7332:127.0.0.1:7332, DropInPaths empty
|
||||
@@ -1,85 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# P4-P6 of agents/sage/work/window-plan/repin-1024-draft1.md (blob 0c5e1f1c6271; sage-2179), from Sage's window-repin-4429a104f/p456.sh, read only.
|
||||
# P4 the tunnel unit, P5 the four REPO scripts against NEW, P6 the 7332 matrix on OLD (matrix-old.txt).
|
||||
# usage: p456.sh p4|p5|p6|tester
|
||||
set -uo pipefail
|
||||
REPO=/mnt/storage/src/mosaic-stack
|
||||
WIN=/mnt/storage/src/mosaic-stack/agents/sage/work/window-repin-7247d80c7
|
||||
NEW=7247d80c7af7ffa70fc61557406bf491cdf3bfc7
|
||||
FILES=(scripts/stack-release.sh scripts/webui-service.sh scripts/bus-service.sh scripts/stack-copy.sh)
|
||||
# The plan's <32 letters>: a fixed dummy, not a secret. matrix-new.txt uses the same value.
|
||||
PROOF=abcdefghijklmnopqrstuvwxyzabcdef
|
||||
|
||||
p4() {
|
||||
echo "# P4 $(date -u +%FT%TZ)"
|
||||
local out; out="$(systemctl --user show mosaic-preview-tunnel.service -p ExecStart -p DropInPaths)"; local rc=$?
|
||||
printf '%s\n' "$out"; echo "# exit $rc"
|
||||
local specs; specs="$(grep -oE 'R:[^ ;]+' <<<"$out")"
|
||||
local n; n="$(grep -c . <<<"$specs")"
|
||||
echo "# R: specs ($n): $(tr '\n' ' ' <<<"$specs")"
|
||||
local drop; drop="$(sed -n 's/^DropInPaths=//p' <<<"$out")"
|
||||
if [[ $rc -eq 0 && $n -eq 1 && "$specs" == "R:0.0.0.0:7332:127.0.0.1:7332" && -z "$drop" ]]; then
|
||||
echo "P4 PASS: one R: spec R:0.0.0.0:7332:127.0.0.1:7332, DropInPaths empty"
|
||||
else
|
||||
echo "P4 FAIL"; return 3
|
||||
fi
|
||||
}
|
||||
|
||||
p5() {
|
||||
echo "# P5 $(date -u +%FT%TZ); HEAD $(git -C $REPO rev-parse HEAD)"
|
||||
git -C $REPO diff --quiet $NEW HEAD -- "${FILES[@]}"; local d=$?
|
||||
echo "# git diff --quiet $NEW HEAD -- ${FILES[*]}: exit $d"
|
||||
local st; st="$(git -C $REPO status --porcelain -- "${FILES[@]}")"; local s=$?
|
||||
echo "# git status --porcelain (exit $s): [${st}]"
|
||||
for f in "${FILES[@]}"; do echo "# $f HEAD blob $(git -C $REPO rev-parse HEAD:$f) NEW blob $(git -C $REPO rev-parse $NEW:$f)"; done
|
||||
if [[ $d -eq 0 && $s -eq 0 && -z "$st" ]]; then echo "P5 PASS"; else echo "P5 FAIL"; return 3; fi
|
||||
}
|
||||
|
||||
# one matrix line: label, then curl arguments; prints "<label> <code> <error or ok field>"
|
||||
req() {
|
||||
local label="$1"; shift
|
||||
local body; body="$(mktemp -p "${TMPDIR:-/tmp}")"
|
||||
local code; code="$(curl -s -m 10 -o "$body" -w '%{http_code}' "$@")"
|
||||
local field; field="$(node -e '
|
||||
let s = require("fs").readFileSync(process.argv[1], "utf8"), j;
|
||||
try { j = JSON.parse(s); } catch { console.log("non-json " + s.length + " bytes"); process.exit(0); }
|
||||
console.log(j.error !== undefined ? "error=" + JSON.stringify(j.error) : "ok=" + JSON.stringify(j.ok));
|
||||
' "$body")"
|
||||
rm -f "$body"
|
||||
echo "$label $code $field"
|
||||
}
|
||||
|
||||
p6() {
|
||||
req a http://127.0.0.1:7332/healthz
|
||||
req b -H 'Host: mosaic.woltje.com' http://127.0.0.1:7332/
|
||||
req c -H 'Host: mosaic.woltje.com' -H "X-Mosaic-Proof: $PROOF" http://127.0.0.1:7332/
|
||||
req d -H 'X-authentik-username: tester-probe' http://127.0.0.1:7332/
|
||||
req e -H 'x-mosaic-tester: 1' http://127.0.0.1:7332/
|
||||
req f -H 'X-authentik-username: tester-probe' http://127.0.0.1:7333/
|
||||
req g -H "X-Mosaic-Proof: $PROOF" http://127.0.0.1:7333/
|
||||
}
|
||||
|
||||
# The two tester reads on OLD's 127.0.0.1:7333, for W10's tester-http.mjs reads to compare against. Prints the
|
||||
# status, the byte count and sha256 of the body, and for /api/config the whole body (board, tester, send, edit).
|
||||
# /api/bus/agents prints its top-level shape and the agent count only.
|
||||
tread() {
|
||||
local path="$1" body; body="$(mktemp -p "${TMPDIR:-/tmp}")"
|
||||
local code; code="$(curl -s -m 10 -o "$body" -w '%{http_code}' "http://127.0.0.1:7333$path")"
|
||||
node -e '
|
||||
const s = require("fs").readFileSync(process.argv[1], "utf8"), h = require("crypto").createHash("sha256").update(s).digest("hex");
|
||||
let j; try { j = JSON.parse(s); } catch { console.log(`${process.argv[2]} ${process.argv[3]} non-json ${s.length} bytes`); process.exit(0); }
|
||||
const shape = Array.isArray(j) ? `array(${j.length})` : `keys ${JSON.stringify(Object.keys(j))}`;
|
||||
const list = Array.isArray(j) ? j : Array.isArray(j.agents) ? j.agents : Array.isArray(j.rows) ? j.rows : null;
|
||||
console.log(`${process.argv[2]} ${process.argv[3]} ${Buffer.byteLength(s)} bytes sha256 ${h.slice(0, 16)} ${shape}` +
|
||||
(process.argv[2] === "/api/config" ? ` body ${s.trim()}` : list ? ` agents ${list.length}` : ""));
|
||||
' "$body" "$path" "$code"
|
||||
rm -f "$body"
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
p4) p4 ;;
|
||||
p5) p5 ;;
|
||||
p6) p6 ;;
|
||||
tester) tread /api/config; tread /api/bus/agents ;;
|
||||
*) echo "usage: p456.sh p4|p5|p6|tester" >&2; exit 2 ;;
|
||||
esac
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user