Run the ticket skills through T3 Code, with a review council before pre-mr-review

Agents now start pre-mr-review on the work account themselves, through a Klaude
delegate, and continue from its verdict. A council of models on my own accounts
replaces the single reviewer before it, and adding a seat is one table row.

Proof comes from T3's browser, with mp4 recordings, and capture-proof stays as
the fallback. Ticket pages carry their own data, so index.html renders alone in
T3's file viewer, and worktree threads share the main checkout's docs.

A PreToolUse hook sends subagents in T3 threads to delegate_task. Blocker, proof,
review and MR summary rules come from ideas in t3dotgg/tstack.
This commit is contained in:
Gabriel Brown committed 2026-11-04 18:04:18 -05:00
1 parent 968e0a1045
commit 86f6e391b7
14 files changed
+410 -187

No files matched your search

@@ -1,8 +1,9 @@
// Renderer for ticket and epic pages. ticket-page inlines it into every page shell, so a
// page needs nothing outside its own folder (T3 Code's file viewer allows nothing else).
// A page shell names its data file in <body data-src>. This script loads that file with a
// <script> tag (file:// pages cannot fetch), re-loads it every two seconds, and redraws
// only when the data changed. The data shape is defined in scripts/ticket-data.ts.
// Renderer for ticket and epic pages. ticket-page inlines it and the page's data into every
// page shell, so index.html renders on its own with no server and no other file.
// A page shell also names its data file in <body data-src>. Re-loading that file every two
// seconds with a <script> tag (file:// and T3 Code's sandboxed viewer cannot fetch) is what
// keeps an open page live, and a page that cannot reach it still shows its last write.
// The data shape is defined in scripts/ticket-data.ts.
// @ts-check
/** @typedef {import('../../scripts/ticket-data').Ticket} Ticket */
/** @typedef {import('../../scripts/ticket-data').Epic} Epic */
@@ -40,12 +41,14 @@
const mark = st => h('span.mark' + (st === 'done' ? '.done' : st === 'running' ? '.run' : ''), { title: st });
const pill = (text, tone) => h('span.pill' + (tone ? '.' + tone : ''), text);
// T3 Code's sandboxed viewer has no localStorage, so ticks there last while the page stays open.
const ticks = new Map();
/** The viewer's own review tick, kept in this browser only and separate from the agent's done mark. */
function seen(scope, id) {
const key = `seen:${scope}:${id}`;
let on = false; try { on = localStorage.getItem(key) === '1'; } catch {}
let on = ticks.get(key) ?? false; try { on ||= localStorage.getItem(key) === '1'; } catch {}
return h('label.seen', { title: 'Your own review tick, stored in this browser' },
h('input', { type: 'checkbox', checked: on || null, onchange: e => { try { localStorage.setItem(key, e.target.checked ? '1' : '0'); } catch {} } }), 'reviewed');
h('input', { type: 'checkbox', checked: on || null, onchange: e => { ticks.set(key, e.target.checked); try { localStorage.setItem(key, e.target.checked ? '1' : '0'); } catch {} } }), 'reviewed');
}
// ── Loading and live reload ──────────────────────────────────────────────
@@ -66,7 +69,7 @@
const el = document.querySelector('.live');
if (!el) return;
el.classList.toggle('stale', failed);
el.textContent = failed ? 'Live: last reload failed, showing the previous version' : `Live, checked ${clock(new Date(loadedAt).toISOString())}`;
el.textContent = failed ? 'Snapshot from the last write' : `Live, checked ${clock(new Date(loadedAt).toISOString())}`;
}
function draw() {
@@ -151,7 +154,8 @@
/** @param {Ticket} t @param {import('../../scripts/ticket-data').Proof} p */
function compare(t, p) {
const m = p.mock && t.plan?.mocks.find(x => x.id === p.mock);
const evidence = p.kind === 'text' ? h('pre.textproof', p.text || '') : p.kind === 'test' ? h('pre.textproof', 'Passing test: ' + p.test) : h('a', { href: p.file, target: '_blank' }, h('img.shot', { src: p.file, alt: p.file }));
const evidence = p.kind === 'text' ? h('pre.textproof', p.text || '') : p.kind === 'test' ? h('pre.textproof', 'Passing test: ' + p.test)
: p.kind === 'video' ? keep('video:' + p.file, () => h('video.shot', { src: p.file, controls: true, preload: 'metadata' })) : h('a', { href: p.file, target: '_blank' }, h('img.shot', { src: p.file, alt: p.file }));
return h('div.compare',
h('figure', h('figcaption', 'Mock, drawn at plan time'), m ? artboard(m) : h('div.placeholder', 'No mock for this one.')),
h('figure', h('figcaption', 'Proof, captured from the build'), evidence));
@@ -304,6 +308,7 @@
e.closed.length ? h('p.muted', { style: 'margin-top:18px;font-size:.9em' }, 'Closed: ', e.closed.map(c => `${c.key} ${c.title}`).join(', '), '.') : null));
}
if (window[GLOBAL]) { last = JSON.stringify(window[GLOBAL]); loadedAt = Date.now(); draw(); }
load();
setInterval(load, 2000);
})();