Skip to content

Feat(cli): Following a version-2 task reads as one coloured line per actor, with stage banners and the Engine's round and stage in status #1754

Closed

Description

@daniboomerang

Tier: 1
Project: cli, vinaya
Type: feat

Objectives

O1. vinaya task status --follow colours each line by its actor when standard output is a terminal and NO_COLOR is unset (Developer cyan, code reviewer magenta, security reviewer red, the loop grey, a Principal ruling yellow) and writes the same text with no escape codes otherwise.
O2. Each followed line starts with the local wall-clock time as HH:MM:SS, carries no shell command text, shows paths repository-relative, shows the agent's own notes dimmed, and leaves out the driver's terminal-copy duplicate lines, while the driver log on disk keeps every line it holds today.
O3. Each agent action's start and finish are paired by the action's own call identifier, never by role, kind and subject: a stretch of the log already written when the follow starts shows a finished action as one line carrying the action, its result and its duration, and a live action shows its start line when it starts and, when it finishes, a second completed line naming the action, its start time, its result and its duration, with no earlier line rewritten, in a terminal and when piped alike; a test run the Developer runs inside its own session shows its failed-test count from the run's own summary when it finishes, for Claude Code and Codex alike.
O4. The version-2 driver writes one stage-change line, naming the round and the stage, each time the run moves between develop, local checks, review, ready push, focused checks at ready (the driver's run of the approved explicit Test Plan commands), pull request opened, waiting on required CI, waiting for merge, paused for the Developer, paused for the Operator and paused for the Principal, and every node of the version-2 flow maps to exactly one of those stages.
O5. The follow view prints a banner at each stage-change line with the round, the stage and the median minutes of that stage across at most the 20 newest merged tasks' driver logs on this machine that carry stage-change lines, or "typical unavailable" when fewer than 3 such samples exist; while a stage lasts, the follow loop's own poll tick appends a still-in-stage line every 5 minutes with the elapsed minutes, and one more the moment the stage passes twice its median with the over-typical mark, with no forge read; a paused banner names the pause reason and who must act.
O6. Every other line the loop writes, including progress lines a later change adds, shows in the follow view with its time and the loop's colour and its words unchanged.
O7. vinaya task status and the task_status tool report the round, the stage and the minutes in stage for an Engine run from its newest stage-change line, where they report an empty cell today.
O8. The follow view and the status readers produce every line above from a recorded driver log file alone, with no driver process running.

Documentation

  • apps/cli/specs/loop.md — the driver log section: what the driver writes to the task's driver log and what vinaya task status --follow shows (O2, O4, O5, O6)
  • apps/cli/src/lib/dispatch.ts — the one fixed colour per role and the TTY and NO_COLOR gate the follow view reuses (O1)
  • https://no-color.org — the NO_COLOR convention: present with any value means no colour (O1)

Planner's rationale

Boundary — This task makes the live follow view of a version-2 (Engine) run readable and gives the status readers the Engine round and stage. It changes how the follow view renders the driver log, adds stage-change lines to what the version-2 driver writes, adds a failed-test count to both agents' test-run results, carries each action's call identifier as additive metadata on its driver-log lines (their existing words unchanged), and teaches the status row to read the newest stage-change line for an Engine run. The renderer is one new pure module that turns driver log lines into view lines; the follow command pipes the tailed file through it. Push, test-file and CI-job progress lines are a separate change that writes its lines already worded; this renderer shows any loop line it does not recognise with its time and colour and its words untouched, so that change needs no renderer edit. Pinned files: apps/cli/src/lib/follow-view.ts, apps/cli/tests/lib/follow-view.test.ts, apps/cli/tests/fixtures/follow-view/engine-claude-driver.log, apps/cli/tests/fixtures/follow-view/engine-codex-driver.log, apps/cli/tests/fixtures/follow-view/history-merged-with-stages.log, apps/cli/tests/fixtures/follow-view/history-merged-without-stages.log, apps/cli/tests/ci-shards/shard-5.txt, apps/cli/src/commands/task-status.ts, apps/cli/src/lib/task-status.ts, apps/cli/src/lib/loop-log.ts, apps/cli/src/lib/agent-line.ts, apps/cli/src/lib/agent-stream.ts, apps/cli/src/lib/loop-narration-claude.ts, apps/cli/src/lib/loop-narration-codex.ts, apps/cli/src/lib/dispatch.ts, apps/cli/tests/lib/loop-narration-claude.test.ts, apps/cli/tests/lib/loop-narration-codex.test.ts, apps/cli/tests/lib/task-status.test.ts, processes/vinaya/bin/run-engine.ts, processes/vinaya/tests/run-engine.test.ts, processes/vinaya/loops/dev-review/v2/flow-v2-live.ts, apps/cli/specs/loop.md, .changeset/engine-follow-view.md. Out: the run lifecycle module, since every stage the driver reaches (node starts, the published-pull-request watch, the halted watch's endings and pauses) is narrated from the runner itself; every importer of a pinned file, which calls it unchanged and is in the Surface only because the importer gate requires it; the version-2 flow file and the process definition are unchanged; per-check, per-file and per-job push, test and CI progress, which the companion progress change writes; the standalone version-1 loop's own driver lines and its status path; live progress of a test run the Developer runs inside its own session, since neither agent's stream carries a command's output before the command ends (final count only); the Log server, its events and schema, and the Studio; no new command, flag or configuration key is added.

Dependency rationale — Depends-on: #1748 — the ready-push-tests-in-CI task changes the version-2 ready push, adds the strict required-CI read and its pause classes (infrastructure and queue-without-runner pauses for the Operator) and the deferred-tests state; this task's stage map must cover the flow and pause reasons as that task leaves them, and the focused-checks stage line is written where that task starts the driver's explicit Test Plan run, so it runs after it merges; the two also share apps/cli/specs/loop.md, processes/vinaya/bin/run-engine.ts and processes/vinaya/loops/dev-review/v2/flow-v2-live.ts, which the shared-file gate counts only through a Conflicts-with edge. Conflicts-with: #1748, #1681, #1711, #1720, #1723, #1730 — each shares three or more pinned files (#1748 as above). The version-2 concurrent-testing task (#1681) pins apps/cli/specs/loop.md and processes/vinaya/bin/run-engine.ts; the harness-kernel move (#1711) pins apps/cli/specs/loop.md, processes/vinaya/bin/run-engine.ts and processes/vinaya/tests/run-engine.test.ts; the standalone-driver move (#1720) pins apps/cli/src/lib/dispatch.ts, apps/cli/src/lib/task-status.ts and apps/cli/tests/ci-shards/shard-5.txt; the run-control move (#1723) pins apps/cli/src/commands/task-status.ts, apps/cli/src/lib/dispatch.ts, apps/cli/src/lib/task-status.ts and apps/cli/tests/lib/task-status.test.ts; the kernel adapters move (#1730) pins apps/cli/src/lib/agent-line.ts, apps/cli/src/lib/agent-stream.ts, both narration translators and their two tests. The companion push-progress change shares apps/cli/specs/loop.md and processes/vinaya/loops/dev-review/v2/flow-v2-live.ts with this one, below the threshold, and runs in parallel; it writes ordinary loop lines only and no stage-change line.

Traps to avoid — Do NOT change what the driver log on disk holds for existing lines: the follow view drops shell-command detail lines and terminal-copy duplicates at render time, and the raw file keeps them. Do NOT tell a command detail from a note detail by guessing at its text; mark the command detail when it is written (the stream renderer knows which detail is the command) and render from that mark. Do NOT pair a start and its finish by role, kind and subject, which repeat (two reads of one file, two test runs of one file); both translators already carry the vendor call identifier on an action and its result, and the line renderer drops it today, so keep it as additive metadata on the written line and pair by it, leaving every existing word of the raw line as it is; an action with no finish (a restart mid-action) stays a started line and is never paired with a later run's action. Do NOT rewrite or erase an earlier terminal line: the follower only appends, so a live action's finish is its own completed line. Do NOT read the clock inside the renderer; it takes the current time as an argument so the fixture tests are deterministic, and it converts each ISO timestamp to local HH:MM:SS. Do NOT add a forge read to the follow view: the typical stage minutes come from other tasks' driver logs under the same runtime directory, counting only logs that hold the driver's merged-and-ending line (the published watch's or the halted watch's), reading the 20 newest by modification time, and skipping older logs with no stage-change lines. Do NOT rewrite or drop a loop line the renderer does not recognise; show it with its time and the loop colour. Do NOT write a Log event or change the Log schema for a stage change; the stage-change line goes to the driver log only. Take the paused stage's actor from the pause reason the driver already records, never from the line's wording. Do NOT add a parser that a regular expression over source files proves; prove each objective with tests that feed recorded driver log fixtures (one per agent) through the renderer and assert the exact view lines. Do NOT cite Issue or pull request numbers in code comments or the spec. Keep Claude Code and Codex at parity: every translator change lands in both, with a test each.

Suggested agent-class — high: it spans the version-2 driver, both agent translators, the status reader and a new renderer, and the stage mapping must cover every node of the version-2 flow without changing the flow.

Stop-and-escalate — Stop if the dependency's explicit Test Plan run starts outside processes/vinaya, so the focused-checks stage line has no in-Surface place. Stop if a stage-change line cannot be written without changing the version-2 flow file's nodes or edges. Stop if a pause reason the version-2 driver records names no actor who acts on it. Stop if making the Engine status row read the stage line needs a change to the control store's record schema.

Docs to keep coherent — apps/cli/specs/loop.md: its driver log section says a shell command's text is a detail record beneath its action and that vinaya task status --follow tails the driver log; it must describe the rendered follow view and the stage-change lines. No .vinaya/doc-owners binding matches this Surface (the bindings cover ops.ts, log-sink.ts, dev-review-loop.ts, the log server, Log sync and the eval folder), so the spec is named by judgment.

Check decisions

  • atta-labs/process-version-bump: no governed file changes (the process definition, the flow file, role folders and the action bindings stay as they are), so the check passes with no version bump.
  • changeset-coverage: add the pinned changeset.
  • doc-claims: every AEG:CLAIM line in a changed file is kept true in the same commit, including the driver log claims in apps/cli/specs/loop.md.
  • reader-resolvable-prose: new comments and spec text carry no Issue or pull-request numbers and no tranche slugs.

Premises

  • apps/cli/src/lib/dispatch.ts contains developer: '\x1b[36m', // cyan
  • apps/cli/src/lib/dispatch.ts contains const LOOP_ANSI = '\x1b[90m' // bright black / grey
  • apps/cli/src/lib/agent-line.ts contains const time = options.log ? now.toISOString() : now.toLocaleTimeString('en-GB', { hour12: false })
  • apps/cli/src/lib/agent-line.ts contains running_tests: 'Running tests',
  • apps/cli/src/lib/agent-stream.ts contains if (command !== undefined && command !== '') parts.details.push(...textLines(command, ctx))
  • apps/cli/src/lib/loop-log.ts contains console.error(formatAgentLine('dev-review-loop', text, { mark, unicode: Boolean(process.stderr.isTTY) }))
  • apps/cli/src/commands/task-status.ts contains await followLoopLog(path, parsed.quiet ?
  • apps/cli/src/lib/task-status.ts contains const record = readLoopState(deps, task)
  • apps/cli/src/lib/task-status.ts contains const OVER_TYPICAL_MARK = '⚠'
  • apps/cli/src/lib/loop-narration-claude.ts contains for a result only success or failure
  • processes/vinaya/bin/run-engine.ts contains if (event.type === 'node:start') {
  • processes/vinaya/bin/run-engine.ts contains was ${read}; ending
  • processes/vinaya/bin/run-engine.ts contains while the run was halted; ending
  • apps/cli/src/lib/loop-narration-claude.ts contains id: string | null
  • apps/cli/src/lib/loop-log.ts contains pollIntervalMs: number

Surface

in: apps/cli/src, apps/cli/tests, apps/cli/specs, processes/vinaya, packages/aeg-core/src, .changeset
out: packages/sources/src, apps/log-server, apps/vinaya-portal

Parts

Part 1 (O1, O2, O6, O8) — A pure follow-view renderer turns driver log lines into view lines: local HH:MM:SS time, actor label and colour behind the existing TTY and NO_COLOR gate, command detail lines and terminal-copy duplicates left out, repository-relative paths, dimmed agent notes, and any unrecognised loop line passed through with its time and colour; vinaya task status --follow pipes the tailed file through it, and --quiet keeps its meaning.
Part 2 (O2, O3) — The stream renderer marks a shell-command detail as a command and carries each action's call identifier as additive metadata when the driver log line is written, so the view leaves commands out and pairs actions without reading their text.
Part 3 (O3) — Both translators add a failed-test count, taken from the test run's own summary line, to a finished test run's result, and the renderer pairs each action's start and finish by call identifier under the append-only policy.
Part 4 (O4, O7) — The version-2 driver writes a stage-change line on each node start or pause that changes the stage and when its explicit Test Plan run starts, a stage mapping covers every node of the version-2 flow and every recorded pause reason, a resume on a ruling writes a Principal line, and the status row reads the newest stage-change line for an Engine run's round, stage and minutes.
Part 5 (O5) — The renderer prints a banner at each stage-change line with round, stage and the bounded-history median or typical-unavailable, the follow tick appends still-in-stage lines and the over-typical line until the stage's ending record (the next stage-change line, the driver's ending line or a cancel) and never after it, and a paused banner names the reason and who acts.

Test plan

bun test apps/cli/tests/lib/follow-view.test.ts → pass; the Claude and Codex fixture driver logs render to the exact expected view lines with and without colour; two overlapping actions with identical subjects pair by call identifier; interleaved actors and a restart with an unfinished action render as started lines; a live action appends its completed line; an injected clock drives still-in-stage and over-typical lines; a multi-log history fixture (with older logs carrying no stage lines) yields the median or typical-unavailable; an unrecognised loop line passes through unchanged; replaying a completed log and a cancelled log closes the stage at its existing ending record and appends no still-in-stage line after it
bun test apps/cli/tests/lib/loop-narration-claude.test.ts apps/cli/tests/lib/loop-narration-codex.test.ts → pass; a failed test run's result carries its failed-test count in both
bun test processes/vinaya/tests/run-engine.test.ts → pass; every version-2 flow node and pause reason maps to one stage and a stage change writes one stage-change line
bun test apps/cli/tests/lib/task-status.test.ts apps/cli/tests/commands/task-status.test.ts → pass; an Engine run's row shows its round, stage and minutes
  • [principal] Follow a live version-2 run in a terminal with vinaya task status --issue <n> --follow and confirm the colours, readable lines and stage banners read as intended.

Stop conditions

  • A stage-change line needs a change to the version-2 flow file's nodes or edges.
  • A recorded pause reason names no actor who acts on it.
  • The Engine status row needs a change to the control store's record schema.

Origin

Principal-directed, 2026-10-29: following a version-2 run live was hard to read. The status table showed an empty cell for round, phase and minutes on Engine runs; the driver log carried full ISO timestamps, one raw shell command line per tool call, a start line and a finish line minutes apart for the same action, and every loop line twice (the file copy and the terminal copy the driver's own standard error adds); and the role colours the standalone loop prints were absent. The push, test-file and CI-job progress the Principal also asked for is the companion progress change, split off along the seam between rendering the log and writing new lines into it.

Activity

  1. daniboomerang commented on Oct 29, 2026

    @daniboomerang
    MemberAuthor

    Brief hash: d779f8a04868d3a8e1990059abd94ae590efa5c1a440ad93b66a9cadfdff4858
    For: [model] (coding-agent CLI on a dev machine, dispatched locally, unattended)
    Reason: Suggested agent-class — high: it spans the version-2 driver, both agent translators, the status reader and a new renderer, and the stage mapping must cover every node of the version-2 flow without changing the flow.
    Owner: the Principal
    Goal: Feat(cli): Following a version-2 task reads as one coloured line per actor, with stage banners and the Engine's round and stage in status
    Project: ** cli, vinaya
    Tier: 1

    Closes #1754

    You are the AEG Developer. Run bun apps/cli/src/index.ts doctrine --role developer --print and read its output first. Mandatory.

    Objectives

    O1. vinaya task status --follow colours each line by its actor when standard output is a terminal and NO_COLOR is unset (Developer cyan, code reviewer magenta, security reviewer red, the loop grey, a Principal ruling yellow) and writes the same text with no escape codes otherwise.
    O2. Each followed line starts with the local wall-clock time as HH:MM:SS, carries no shell command text, shows paths repository-relative, shows the agent's own notes dimmed, and leaves out the driver's terminal-copy duplicate lines, while the driver log on disk keeps every line it holds today.
    O3. Each agent action's start and finish are paired by the action's own call identifier, never by role, kind and subject: a stretch of the log already written when the follow starts shows a finished action as one line carrying the action, its result and its duration, and a live action shows its start line when it starts and, when it finishes, a second completed line naming the action, its start time, its result and its duration, with no earlier line rewritten, in a terminal and when piped alike; a test run the Developer runs inside its own session shows its failed-test count from the run's own summary when it finishes, for Claude Code and Codex alike.
    O4. The version-2 driver writes one stage-change line, naming the round and the stage, each time the run moves between develop, local checks, review, ready push, focused checks at ready (the driver's run of the approved explicit Test Plan commands), pull request opened, waiting on required CI, waiting for merge, paused for the Developer, paused for the Operator and paused for the Principal, and every node of the version-2 flow maps to exactly one of those stages.
    O5. The follow view prints a banner at each stage-change line with the round, the stage and the median minutes of that stage across at most the 20 newest merged tasks' driver logs on this machine that carry stage-change lines, or "typical unavailable" when fewer than 3 such samples exist; while a stage lasts, the follow loop's own poll tick appends a still-in-stage line every 5 minutes with the elapsed minutes, and one more the moment the stage passes twice its median with the over-typical mark, with no forge read; a paused banner names the pause reason and who must act.
    O6. Every other line the loop writes, including progress lines a later change adds, shows in the follow view with its time and the loop's colour and its words unchanged.
    O7. vinaya task status and the task_status tool report the round, the stage and the minutes in stage for an Engine run from its newest stage-change line, where they report an empty cell today.
    O8. The follow view and the status readers produce every line above from a recorded driver log file alone, with no driver process running.

    Documentation

    • apps/cli/specs/loop.md — the driver log section: what the driver writes to the task's driver log and what bun apps/cli/src/index.ts task status --follow shows (O2, O4, O5, O6)
    • apps/cli/src/lib/dispatch.ts — the one fixed colour per role and the TTY and NO_COLOR gate the follow view reuses (O1)
    • https://no-color.org — the NO_COLOR convention: present with any value means no colour (O1)

    Premises

    Checked against the code when this task Issue was cut, and again against the default branch at dispatch — facts, not claims.

    • apps/cli/src/lib/dispatch.ts contains developer: '\x1b[36m', // cyan
    • apps/cli/src/lib/dispatch.ts contains const LOOP_ANSI = '\x1b[90m' // bright black / grey
    • apps/cli/src/lib/agent-line.ts contains const time = options.log ? now.toISOString() : now.toLocaleTimeString('en-GB', { hour12: false })
    • apps/cli/src/lib/agent-line.ts contains running_tests: 'Running tests',
    • apps/cli/src/lib/agent-stream.ts contains if (command !== undefined && command !== '') parts.details.push(...textLines(command, ctx))
    • apps/cli/src/lib/loop-log.ts contains console.error(formatAgentLine('dev-review-loop', text, { mark, unicode: Boolean(process.stderr.isTTY) }))
    • apps/cli/src/commands/task-status.ts contains await followLoopLog(path, parsed.quiet ?
    • apps/cli/src/lib/task-status.ts contains const record = readLoopState(deps, task)
    • apps/cli/src/lib/task-status.ts contains const OVER_TYPICAL_MARK = '⚠'
    • apps/cli/src/lib/loop-narration-claude.ts contains for a result only success or failure
    • processes/vinaya/bin/run-engine.ts contains if (event.type === 'node:start') {
    • processes/vinaya/bin/run-engine.ts contains was ${read}; ending
    • processes/vinaya/bin/run-engine.ts contains while the run was halted; ending
    • apps/cli/src/lib/loop-narration-claude.ts contains id: string | null
    • apps/cli/src/lib/loop-log.ts contains pollIntervalMs: number

    2. Context — read before doing anything

    • Backlog Issue: Feat(cli): Following a version-2 task reads as one coloured line per actor, with stage banners and the Engine's round and stage in status #1754, no tranche. Branch task/issue-1754. Depends-on: #1748, Conflicts-with: #1748, #1681, #1711, #1720, #1723, #1730.
    • Read Issue Feat(cli): Following a version-2 task reads as one coloured line per actor, with stage banners and the Engine's round and stage in status #1754 in full for the complete rationale — do not re-derive it.
    • Revision: rendered at cbb621d0e59f2934e08de95039cb94e782d68379 — the checkout's HEAD equaled the remote default branch, and no pinned file below carried an uncommitted change, when these facts were read.
    • Boundary — This task makes the live follow view of a version-2 (Engine) run readable and gives the status readers the Engine round and stage. It changes how the follow view renders the driver log, adds stage-change lines to what the version-2 driver writes, adds a failed-test count to both agents' test-run results, carries each action's call identifier as additive metadata on its driver-log lines (their existing words unchanged), and teaches the status row to read the newest stage-change line for an Engine run. The renderer is one new pure module that turns driver log lines into view lines; the follow command pipes the tailed file through it. Push, test-file and CI-job progress lines are a separate change that writes its lines already worded; this renderer shows any loop line it does not recognise with its time and colour and its words untouched, so that change needs no renderer edit. Pinned files: apps/cli/src/lib/follow-view.ts, apps/cli/tests/lib/follow-view.test.ts, apps/cli/tests/fixtures/follow-view/engine-claude-driver.log, apps/cli/tests/fixtures/follow-view/engine-codex-driver.log, apps/cli/tests/fixtures/follow-view/history-merged-with-stages.log, apps/cli/tests/fixtures/follow-view/history-merged-without-stages.log, apps/cli/tests/ci-shards/shard-5.txt, apps/cli/src/commands/task-status.ts, apps/cli/src/lib/task-status.ts, apps/cli/src/lib/loop-log.ts, apps/cli/src/lib/agent-line.ts, apps/cli/src/lib/agent-stream.ts, apps/cli/src/lib/loop-narration-claude.ts, apps/cli/src/lib/loop-narration-codex.ts, apps/cli/src/lib/dispatch.ts, apps/cli/tests/lib/loop-narration-claude.test.ts, apps/cli/tests/lib/loop-narration-codex.test.ts, apps/cli/tests/lib/task-status.test.ts, processes/vinaya/bin/run-engine.ts, processes/vinaya/tests/run-engine.test.ts, processes/vinaya/loops/dev-review/v2/flow-v2-live.ts, apps/cli/specs/loop.md, .changeset/engine-follow-view.md. Out: the run lifecycle module, since every stage the driver reaches (node starts, the published-pull-request watch, the halted watch's endings and pauses) is narrated from the runner itself; every importer of a pinned file, which calls it unchanged and is in the Surface only because the importer gate requires it; the version-2 flow file and the process definition are unchanged; per-check, per-file and per-job push, test and CI progress, which the companion progress change writes; the standalone version-1 loop's own driver lines and its status path; live progress of a test run the Developer runs inside its own session, since neither agent's stream carries a command's output before the command ends (final count only); the Log server, its events and schema, and the Studio; no new command, flag or configuration key is added.
    • Traps to avoid — Do NOT change what the driver log on disk holds for existing lines: the follow view drops shell-command detail lines and terminal-copy duplicates at render time, and the raw file keeps them. Do NOT tell a command detail from a note detail by guessing at its text; mark the command detail when it is written (the stream renderer knows which detail is the command) and render from that mark. Do NOT pair a start and its finish by role, kind and subject, which repeat (two reads of one file, two test runs of one file); both translators already carry the vendor call identifier on an action and its result, and the line renderer drops it today, so keep it as additive metadata on the written line and pair by it, leaving every existing word of the raw line as it is; an action with no finish (a restart mid-action) stays a started line and is never paired with a later run's action. Do NOT rewrite or erase an earlier terminal line: the follower only appends, so a live action's finish is its own completed line. Do NOT read the clock inside the renderer; it takes the current time as an argument so the fixture tests are deterministic, and it converts each ISO timestamp to local HH:MM:SS. Do NOT add a forge read to the follow view: the typical stage minutes come from other tasks' driver logs under the same runtime directory, counting only logs that hold the driver's merged-and-ending line (the published watch's or the halted watch's), reading the 20 newest by modification time, and skipping older logs with no stage-change lines. Do NOT rewrite or drop a loop line the renderer does not recognise; show it with its time and the loop colour. Do NOT write a Log event or change the Log schema for a stage change; the stage-change line goes to the driver log only. Take the paused stage's actor from the pause reason the driver already records, never from the line's wording. Do NOT add a parser that a regular expression over source files proves; prove each objective with tests that feed recorded driver log fixtures (one per agent) through the renderer and assert the exact view lines. Do NOT cite Issue or pull request numbers in code comments or the spec. Keep Claude Code and Codex at parity: every translator change lands in both, with a test each.

    3. Technical dependencies

    Dependency rationale — Depends-on: #1748 — the ready-push-tests-in-CI task changes the version-2 ready push, adds the strict required-CI read and its pause classes (infrastructure and queue-without-runner pauses for the Operator) and the deferred-tests state; this task's stage map must cover the flow and pause reasons as that task leaves them, and the focused-checks stage line is written where that task starts the driver's explicit Test Plan run, so it runs after it merges; the two also share apps/cli/specs/loop.md, processes/vinaya/bin/run-engine.ts and processes/vinaya/loops/dev-review/v2/flow-v2-live.ts, which the shared-file gate counts only through a Conflicts-with edge. Conflicts-with: #1748, #1681, #1711, #1720, #1723, #1730 — each shares three or more pinned files (#1748 as above). The version-2 concurrent-testing task (#1681) pins apps/cli/specs/loop.md and processes/vinaya/bin/run-engine.ts; the harness-kernel move (#1711) pins apps/cli/specs/loop.md, processes/vinaya/bin/run-engine.ts and processes/vinaya/tests/run-engine.test.ts; the standalone-driver move (#1720) pins apps/cli/src/lib/dispatch.ts, apps/cli/src/lib/task-status.ts and apps/cli/tests/ci-shards/shard-5.txt; the run-control move (#1723) pins apps/cli/src/commands/task-status.ts, apps/cli/src/lib/dispatch.ts, apps/cli/src/lib/task-status.ts and apps/cli/tests/lib/task-status.test.ts; the kernel adapters move (#1730) pins apps/cli/src/lib/agent-line.ts, apps/cli/src/lib/agent-stream.ts, both narration translators and their two tests. The companion push-progress change shares apps/cli/specs/loop.md and processes/vinaya/loops/dev-review/v2/flow-v2-live.ts with this one, below the threshold, and runs in parallel; it writes ordinary loop lines only and no stage-change line.

    4. Technical surface map

    Create:

    • (none — every surface file already exists)

    Modify:

    • apps/cli/src

    • apps/cli/tests

    • apps/cli/specs

    • processes/vinaya

    • packages/aeg-core/src

    • .changeset

    • consumer-tests: none — no consumer test path named yet for @attalabs/aeg-core (apps/log-server), @attalabs/aeg-core (packages/sources); name one before dispatch, or confirm no consumer-facing behavior changed.

    • consumer-tests: apps/cli/tests (covers @attalabs/aeg-core)

    • consumer-tests: processes/vinaya/tests (covers @attalabs/aeg-core)

    Out of surface: packages/sources/src, apps/log-server, apps/vinaya-portal — a change there, or to any path no Surface in: glob covers, is still published: the review-loop driver records each such path in the pull request body's beyond-Surface block, and the reviewers judge it like any change.

    Premise pins

    Premise:

    • apps/cli/specs/loop.md sha256: 8e39119f0c1bacd2803606f758abdcf0d11315a827ad1c6fce26f7ae609f4fbe
    • apps/cli/src/commands/task-status.ts sha256: b78bc16b4bf374d0b6d00a52ff180bdfa6b6a874e12762914e9c5efb3d085005
    • apps/cli/src/lib/agent-line.ts sha256: 94a099309445876c6335fd5894e552a96d4b14367d186f50372bf869ec024127
    • apps/cli/src/lib/agent-stream.ts sha256: 566bd950d8370cb1afc28ecead9efb97392892cfb95deffc07cf0a831fb997f3
    • apps/cli/src/lib/dispatch.ts sha256: 59d045f6467e52e73be4dbc77069e3fa0f03554755615ed09ea0309e78e13f28
    • apps/cli/src/lib/loop-log.ts sha256: a8a557498c34ee420e588a5271415a9d0c4bf7e817d7309cc68821a2b447718d
    • apps/cli/src/lib/loop-narration-claude.ts sha256: dde7cb1ca83dfb2275266a1557ccacb18da682bcf2fc6e53b9e19fe47114403e
    • apps/cli/src/lib/loop-narration-codex.ts sha256: afb65d32edb3b0a171d69f387178276eff5226525637a45891886d8723fb1490
    • apps/cli/src/lib/task-status.ts sha256: 785bc26b1596cfddf0aae1bf64005878bd8acee61a5b8c65e88816afa12c43d3
    • apps/cli/tests/ci-shards/shard-5.txt sha256: 25fa388acdbdb1384276fd91285c8be2df9b4186a681d43ca9d73c84fbfb6626
    • apps/cli/tests/lib/loop-narration-claude.test.ts sha256: 6ebfe80b16bceb03d7b2406c83aa048147bdaabf54e5029a20b76af9f27eede0
    • apps/cli/tests/lib/loop-narration-codex.test.ts sha256: be17373a7375ced939d3c9f454065aa2821a1348a597ac8052a02cc214c15c21
    • apps/cli/tests/lib/task-status.test.ts sha256: 1b63c082cd45ba734c398faf595a13c848433f498a6d15709a868aad3f85f7ab
    • processes/vinaya/bin/run-engine.ts sha256: fccda476c61af214b486ceb7eda518c4450609c4aa605e54a617c6217a7073d7
    • processes/vinaya/loops/dev-review/v2/flow-v2-live.ts sha256: c656885463de8b0e92c0fc8d7d90d136bfc1e64c2f17a1ef8ede29e155dd447b
    • processes/vinaya/tests/run-engine.test.ts sha256: e557f3c3aa80930766a7c666c35d3dbc67bd61fa331c48b7b7a7b9ffad9990d6

    5. Pre-flight checks

    Step 0 (mandatory, verbatim):

    bun install --frozen-lockfile --silent
    
    1. Clean status; parent origin/main; branch suffix literal-matches the task id.
    2. Under the review loop (bun apps/cli/src/index.ts task run), the driver has already run the dispatch-readiness gate plus, on this repository toolchain, its own fuller derivation from its own unsandboxed process before dispatching you (re-derived at render time: it was ready), and dispatches you only when that verdict is READY — a NOT READY verdict refuses the turn before it starts, so being dispatched is the verdict: look for no file and run neither script, whose own gh call fails inside your sandbox. Working manually, with no driver behind you, fall back to roles/developer.md's own items 3/5/7 prose — each a complete, hand-run forge check in its own right.

    On any failure: STOP and report.

    6. Numbered parts — publish once with publish_changes when every Part is done, then open_pull_request

    1. Part 1 (O1, O2, O6, O8): A pure follow-view renderer turns driver log lines into view lines: local HH:MM:SS time, actor label and colour behind the existing TTY and NO_COLOR gate, command detail lines and terminal-copy duplicates left out, repository-relative paths, dimmed agent notes, and any unrecognised loop line passed through with its time and colour; bun apps/cli/src/index.ts task status --follow pipes the tailed file through it, and --quiet keeps its meaning.

      Files (touches @attalabs/vinaya):

      • apps/cli/specs/loop.md
      • apps/cli/src/commands/task-status.ts
      • apps/cli/src/lib/agent-line.ts
      • apps/cli/src/lib/agent-stream.ts
      • apps/cli/src/lib/dispatch.ts
      • apps/cli/src/lib/loop-log.ts
      • apps/cli/src/lib/loop-narration-claude.ts
      • apps/cli/src/lib/loop-narration-codex.ts
      • apps/cli/src/lib/task-status.ts
      • apps/cli/tests/ci-shards/shard-5.txt
      • apps/cli/tests/lib/loop-narration-claude.test.ts
      • apps/cli/tests/lib/loop-narration-codex.test.ts
      • apps/cli/tests/lib/task-status.test.ts

      The pre-push hook runs the affected suite on your one push and refuses it on failure — do not run it yourself per Part.

    2. Part 2 (O2, O3): The stream renderer marks a shell-command detail as a command and carries each action's call identifier as additive metadata when the driver log line is written, so the view leaves commands out and pairs actions without reading their text.

      Files (touches the repo root):

      • processes/vinaya/bin/run-engine.ts
      • processes/vinaya/loops/dev-review/v2/flow-v2-live.ts
      • processes/vinaya/tests/run-engine.test.ts

      The pre-push hook runs the affected suite on your one push and refuses it on failure — do not run it yourself per Part.

    3. Part 3 (O3): Both translators add a failed-test count, taken from the test run's own summary line, to a finished test run's result, and the renderer pairs each action's start and finish by call identifier under the append-only policy.

    4. Part 4 (O4, O7): The version-2 driver writes a stage-change line on each node start or pause that changes the stage and when its explicit Test Plan run starts, a stage mapping covers every node of the version-2 flow and every recorded pause reason, a resume on a ruling writes a Principal line, and the status row reads the newest stage-change line for an Engine run's round, stage and minutes.

    5. Part 5 (O5): The renderer prints a banner at each stage-change line with round, stage and the bounded-history median or typical-unavailable, the follow tick appends still-in-stage lines and the over-typical line until the stage's ending record (the next stage-change line, the driver's ending line or a cancel) and never after it, and a paused banner names the reason and who acts.

    7. Documentation-update list

    .vinaya/doc-owners derivation matched zero bindings against this task's surface — no mechanically-derived doc updates. Confirm no additional doc artifact applies before treating this list as final.

    8. Verification before claiming done

    • Under the review loop, the controller runs the static gates: the commit hook applies safe format and lint fixes to staged files, typechecks affected packages, and runs the Vinaya checks; the pre-push hook runs the affected suite; run_checks and CI provide the authoritative results. Do not hand-run or paste static-gate commands. Working manually, run this repository's declared typecheck, lint/format, build, and documentation-gate commands yourself.
    • The pre-push hook runs the affected suite once, on your one push, and refuses it on failure; CI runs the full suite.
    • Every blast-radius consumer named in §4, re-verified by name.
    • The tier checklist in bun apps/cli/src/index.ts doctrine --role developer --print genuinely satisfied; use the controller's run_checks result, hooks, and CI as gate evidence.

    9. Test Plan

    bun test apps/cli/tests/lib/follow-view.test.ts → pass; the Claude and Codex fixture driver logs render to the exact expected view lines with and without colour; two overlapping actions with identical subjects pair by call identifier; interleaved actors and a restart with an unfinished action render as started lines; a live action appends its completed line; an injected clock drives still-in-stage and over-typical lines; a multi-log history fixture (with older logs carrying no stage lines) yields the median or typical-unavailable; an unrecognised loop line passes through unchanged; replaying a completed log and a cancelled log closes the stage at its existing ending record and appends no still-in-stage line after it
    bun test apps/cli/tests/lib/loop-narration-claude.test.ts apps/cli/tests/lib/loop-narration-codex.test.ts → pass; a failed test run's result carries its failed-test count in both
    bun test processes/vinaya/tests/run-engine.test.ts → pass; every version-2 flow node and pause reason maps to one stage and a stage change writes one stage-change line
    bun test apps/cli/tests/lib/task-status.test.ts apps/cli/tests/commands/task-status.test.ts → pass; an Engine run's row shows its round, stage and minutes
    
    • [principal] Follow a live version-2 run in a terminal with bun apps/cli/src/index.ts task status --issue <n> --follow and confirm the colours, readable lines and stage banners read as intended.

    10. Stop conditions

    • A stage-change line needs a change to the version-2 flow file's nodes or edges.
    • A recorded pause reason names no actor who acts on it.
    • The Engine status row needs a change to the control store's record schema.

    Stop-and-escalate — Stop if the dependency's explicit Test Plan run starts outside processes/vinaya, so the focused-checks stage line has no in-Surface place. Stop if a stage-change line cannot be written without changing the version-2 flow file's nodes or edges. Stop if a pause reason the version-2 driver records names no actor who acts on it. Stop if making the Engine status row read the stage line needs a change to the control store's record schema.

    11. Constraints

    Autonomy: Do not stop to ask clarifying questions. For any ambiguity not covered by a Section 10 stop condition, choose the most reasonable option consistent with this brief, record the choice in the PR body at open, or in a PR comment after open, and continue. Halt only for the explicit Section 10 stop conditions — and when you halt, record the blocker in a PR comment or an Issue comment rather than waiting interactively for input.

    12. Deliverable

    • PR title (exact): Feat(cli): Following a version-2 task reads as one coloured line per actor, with stage banners and the Engine's round and stage in status
    • Open the PR only via the open_pull_request tool (title and body); publish your commits with publish_changes and update the body with update_pull_request_body/refresh_evidence — you hold no gh/git push credential.
    • Publish once, with publish_changes, when every Part is done; then open the pull request with open_pull_request. Publish again only to answer review findings or a red gate — a refused hook, a failing check, a merge conflict.
    • PR body = the Developer's PR report (print it with bun apps/cli/src/index.ts doctrine --template pr-report --print), with Closes #1754 at the top of the header block. This brief stays frozen on the task Issue and never rides in the body.
    • Pre-open: tier checklist satisfied. The documentation gate is the controller's — run_checks and CI run it.
    • Include git diff origin/main...HEAD --stat as context only; Surface is judged by the driver's surface-scope check, never by this hand-run diff. Token use needs no report — the Vinaya log records it.
    • Then STOP. Review and Verification are separate invocations.
  2. daniboomerang commented on Oct 29, 2026

    @daniboomerang
    MemberAuthor

    The dev-review-loop paused: infrastructure — an uncaught error ended round 1's own processing: the ready push was cancelled.

    No pull request exists yet for this task, so the pause is recorded on this Issue instead.
    A Principal ruling is needed before this can continue. Post it as a comment on this Issue whose FIRST line is exactly this marker — the second number is the ordinal, and it must exceed the one this pause recorded:

    <!-- aeg:principal:ruling:1754-1 -->
    Your ruling text here.
    

    Then continue with:

    vinaya task run --issue 1754 --agent claude --model opus --runner atta-engine
    

    The Operator's own task_resume clears this pause too, reading that same ruling from this Issue; task_cancel ends it instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions