Skip to content

feat(queue): scaffold and auto-refresh the run log from queue commands - #56

Merged
LeTuR merged 8 commits into
mainfrom
feat/scaffold-run-log
Sep 9, 2026
Merged

feat(queue): scaffold and auto-refresh the run log from queue commands#56
LeTuR merged 8 commits into
mainfrom
feat/scaffold-run-log

Conversation

@LeTuR

@LeTuR LeTuR commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Intent

Make the run log something the queue produces, not something the lead has to remember. AGENTS.md step 5 told the lead to record each orchestration run in orchestration/runs/ as it happens, and two consecutive runs did not: one file existed only because that lead session was being migrated, the other was reconstructed from chat history at the end of the run after the operator asked what had gone wrong. An instruction two leads failed the same way is a tool gap, not a discipline problem — the queue already scaffolds BRIEF.md, task.yaml, progress.jsonl and result.md without being asked, and the run log was the one artefact left to the lead's memory. The task brief explicitly left the design open ('the shape below is the problem, not the prescription') and asked for the choice to be argued, weighing two candidates: scaffolding at 'topic add' from a _TEMPLATE the way orchestration/playbooks/ has one, versus a 'queue.sh run' verb that renders a log from records on demand. I picked a hybrid and both halves are deliberate: 'topic add' opens orchestration/runs/-.md from the tracked _TEMPLATE.md (a pure render-on-demand verb reproduces the original failure — a command the lead must remember to run), and dispatch/collect/shepherd refresh a fenced block inside it (facts must arrive without the lead retyping them). One log per topic, named from the topic slug and open date, so every command finds the same file with no 'current run' pointer to keep in step. Hard constraints from the brief, all deliberate in the diff: (1) the block is REWRITTEN in place, never appended to — collect runs many times over one run and a line appended per pass is a timeline nobody reads, which is the same failure relocated; the block is a pure function of the records (no 'refreshed at' timestamp) so a refresh that changes nothing writes nothing and prints nothing, which is why the loop does not get noisier; (2) everything outside the fence is the lead's judgement — goal, decisions, what went wrong, outcome — and is never read or written by the queue; a log whose fence has been removed is reported as 'left alone' and never written to again; (3) no daemon and no new long-running process — the producers are the commands the lead already runs; (4) orchestration/runs/*.md is gitignored, so logs may carry machine paths and session ids freely, while the tracked _TEMPLATE.md stays generic. Facts chosen for value over volume: the task table, blockers with their kind and reason, the --touches OVERLAP that was accepted rather than serialized (the queue's whole ordering doctrine, and something the last lead typed by hand), and a timeline from timestamps the records already carry. topic add prints the log's path on stderr, not stdout, so 'topic=$(queue.sh topic add ...)' still yields a bare slug. FLEET_RUNS_DIR mirrors FLEET_QUEUE_DIR so selftests do not scaffold into the operator's own orchestration/runs/ — three selftests were leaking there and now export it. A missing template is reported and does not stop intake. Test 12 in scripts/queue-selftest.sh was written FIRST and observed failing for the right reason before any implementation, per the operator's standing rule. Docs updated to describe what now happens rather than what the lead should remember: AGENTS.md step 5 and its runs/ bullet, the fleet-queue skill (new 'The run log' section plus intake and loop steps), scripts/queue.sh's header and Environment block, orchestration/playbooks/_TEMPLATE.md step 1, and .gitignore's own note. ./scripts/check.sh exits 0. Publish method for this task is no-mistakes, per the queue's standing policy.

What Changed

  • queue.sh topic add now opens orchestration/runs/<opened-date>-<topic>.md from the tracked _TEMPLATE.md (printing the path to stderr so topic=$(queue.sh topic add ...) still yields a bare slug), and dispatch/collect/shepherd rewrite a fenced facts block inside that file in place — task table, blockers (with kind/reason), accepted --touches overlaps, and a timeline from record timestamps — as a pure function of the current records, so an unchanged refresh writes and prints nothing; a log whose fence was removed is reported as left alone and never written to again. A new queue.sh run [<topic>] verb exposes that same refresh on demand, and a missing template is reported without stopping intake. Implemented across scripts/lib/queue.py and scripts/queue.sh, with scripts/queue-selftest.sh extended to cover it.
  • Added FLEET_RUNS_DIR (mirroring FLEET_QUEUE_DIR) so selftests scaffold into an isolated directory instead of the operator's real orchestration/runs/; scripts/fleet-status-selftest.sh and scripts/queue-selftest.sh now export it.
  • Updated .gitignore's run-log note, AGENTS.md step 5, FLEET.md, the fleet-queue skill (new "The run log" section plus intake/loop steps), scripts/queue.sh's header and Environment block, and orchestration/runs/_TEMPLATE.md / orchestration/playbooks/{_TEMPLATE,cross-repo-sweep,ship-feature}.md to describe the queue-produced log instead of a lead-remembered one.
  • .github/workflows/ci.yml: drop the runner image's stale google-chrome apt source before apt-get update in the lua install step, so an unrelated stale index no longer fails the whole step.

Risk Assessment

✅ Low: The change implements the run-log feature exactly as scoped in the user intent (one log per topic scaffolded at topic add, a fenced block rewritten in place by dispatch/collect/shepherd, lead prose outside the fence never touched, missing-template reported without blocking intake, FLEET_RUNS_DIR mirroring FLEET_QUEUE_DIR), is covered by a new behavioral test section (19) that exercises the real CLI and asserts on the generated file's content, and the two prior review findings that were auto-fix (fixer field omission, run-log claim renumbering) are verifiably present in this diff; the two findings the user declined in round 2 (stale 'held' blockers, raw landing-kind string) are unchanged from their prior state and not re-raised per instructions.

Testing

Baseline ./scripts/check.sh already passed. I additionally ran the full scripts/queue-selftest.sh (which includes the feature-specific section 19 written first per the operator's TDD rule) end-to-end against a throwaway queue/runs directory, and it passed all ~140 assertions with no failures. I then manually exercised the real queue.sh topic add CLI in a separate sandboxed FLEET_QUEUE_DIR/FLEET_RUNS_DIR to observe the actual generated run-log artifact firsthand: the log opens unprompted, its path goes to stderr only (stdout is unaffected for topic=$(...) capture), and the file content matches the tracked template with a fenced generated-facts block plus the four sections reserved for lead judgement. No source or test files were modified; sandbox temp directories were removed afterward and the worktree is clean (only pre-existing, non-source tool caches .rumdl_cache/ and scripts/lib/__pycache__/ remain untracked, consistent with the check.sh baseline run).

Evidence: Manual CLI walkthrough: topic add scaffolding a run log (stderr path + full generated file contents)
=== topic add ===
topic slug: manual-check
--- stderr (should contain log path) ---
run log opened: /tmp/tmp.6pFz0L7oMn/runs/2026-09-09-manual-check.md

=== contents ===
# Run: `2026-09-09` — `manual-check`

> One run, one topic. `./scripts/queue.sh topic add` opens this file, and
> `dispatch`, `collect`, `shepherd` and `run` refresh the fenced block below
> from the queue's own records as the run goes on.
>
> **Everything outside that fence is yours.** Nothing rewrites it, nothing
> generates it, and it is the reason the file exists — the block says what
> happened, and these sections say what you decided and what it cost.

<!-- fleet:facts -->

<!-- Generated from the queue's records by `./scripts/queue.sh`, and
rewritten in place every time it runs. Write nothing in here;
everything outside this fence is yours and is never touched. -->

- **Topic.** `manual-check` — Manual run-log check
- **Prompt.** `/tmp/tmp.6pFz0L7oMn/queue/manual-check/PROMPT.md`
- **Opened.** 2026-09-09T17:48:41+00:00 · **Status.** planning · **Profile(s).** —

No tasks yet.

<!-- fleet:facts:end -->

## Goal

What this run is meant to achieve, in your words.

## Playbook

`../playbooks/<name>.md`, or "ad hoc".

## Decisions worth keeping

The calls you made and why: what you serialized and on what condition, what you
dispatched together despite an overlap, what you decided not to do at all.

## What went wrong

Where the tooling or the plan failed, and what the next lead should do instead.
A defect written down here is the one that gets fixed.

## Outcome

What shipped, what is pending, what to follow up on. Update the relevant
`registry/context/<repo>.md` if this run changed a project's goals or relations.

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

✅ **Test** - passed

✅ No issues found.

  • ./scripts/check.sh
  • ./scripts/queue-selftest.sh (full suite, run against a throwaway FLEET_QUEUE_DIR/FLEET_RUNS_DIR temp dir) — exit 0, all claims pass, including section 19 'the run log is produced, not remembered' covering: unprompted scaffold on topic add, stderr-only path (stdout stays a bare slug), fenced &lt;!-- fleet:facts --&gt; block populated from real dispatch/collect/reap/shepherd records (task table, branch, artifact, dispatched timeline, accepted --touches overlap), lead prose surviving repeated collect refreshes, three refreshes not appending duplicate lines, queue.sh run naming the maintained log, and a log with its fence stripped being reported 'left alone' and never rewritten again
  • Manual end-to-end run: ./scripts/queue.sh topic add manual-check ... in an isolated FLEET_QUEUE_DIR/FLEET_RUNS_DIR — captured stdout (bare slug manual-check), stderr (run log opened: .../2026-09-09-manual-check.md), and the generated file's full contents, confirming it matches the tracked orchestration/runs/_TEMPLATE.md shape with the fenced facts block and the four lead-owned prose sections (Goal, Playbook, Decisions worth keeping, What went wrong, Outcome)
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@LeTuR
LeTuR force-pushed the feat/scaffold-run-log branch from 77eac0c to 62787e2 Compare September 9, 2026 16:59
`AGENTS.md` step 5 said "record the run in orchestration/runs/ as it
happens". Two consecutive runs did not: one file existed only because
its lead session was being migrated, the other was reconstructed from
chat history at the end. Every other artefact of the loop is scaffolded
without anyone choosing to make it; the run log was the one that was not.

`topic add` now opens `orchestration/runs/<opened>-<topic>.md` from the
tracked template, and `dispatch`, `collect` and `shepherd` rewrite a
fenced block of facts inside it — the task table, what waited on what,
what overlapped anyway, and a timeline from the records' own timestamps.
The block is rewritten rather than appended to, so a refresh that changes
nothing writes nothing. Everything outside the fence is the lead's and is
never touched; remove the fence and the queue reports the file and leaves
it alone. `queue.sh run` is that refresh made explicit.

Claude-Session: https://claude.ai/code/session_01CY4y46iLQZmBhKTnaVyspb
@LeTuR
LeTuR force-pushed the feat/scaffold-run-log branch from 62787e2 to 5ad2ee1 Compare September 9, 2026 17:03
@LeTuR LeTuR changed the title feat(queue): make the run log something the queue produces feat(queue): scaffold and auto-refresh the run log from queue commands Sep 9, 2026
@LeTuR
LeTuR merged commit 59879e1 into main Sep 9, 2026
10 checks passed
@LeTuR
LeTuR deleted the feat/scaffold-run-log branch September 9, 2026 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant