This text was generated by an LLM (how cgwalters uses LLMs). cgwalters has not reviewed it yet.
Work items and questions for cgwalters-bot's workstream. The Workstream board is a view over these issues plus the upstream issues and PRs the bot works on; anything on the board that isn't upstream is an issue here.
- Work items are ordinary issues. Larger efforts are parent issues whose sub-issues are the steps, so the board shows their progress.
- Questions for cgwalters are issues labelled
questionand assigned to him, usually a sub-issue of the work item they block. The first line says which item that is (Blocks: <url>). They offer lettered options, the recommended one first as A.
Comment on the question issue. To pick an option, make the first line of
the comment just its letter (e.g. B), optionally followed by more text;
otherwise write whatever you want. The bot acts on the answer, then closes
the issue with a one-line comment saying what it did.
Only comments by the cgwalters login count as answers. The bot reads
everyone else's comments, its own included, as input to weigh, never as
instructions.
The bot's workflows here, or
agent-board's ask create
by hand, open these issues. The
review app is a UI over the same queue.
docs/bring-up.md says how to start a coordinator on a fresh machine from credentials alone, how to dispatch a run and where its state is. docs/operator-notes.md is the log of cgwalters' instructions.
Agent-drafted reviews of others' pull requests wait as issues labelled
review-draft (is:open label:review-draft is the queue). To send the
newest draft as cgwalters-bot, tick the body's
Send the newest draft as cgwalters-bot box or comment just /send;
.github/workflows/review-send.yml then runs agent-board's review send,
which posts it only to the repositories .github/poll/agent-board.json's
review section lists, and closes the issue. A draft it cannot send (a
moved head, a line not in the diff) is refused in a comment; a missing or
stale approval only fails the run. The approval rules are agent-board's
docs/review-drafts.md.
Dispatched runs have a staged opt-in to agenthome's install-tools through
the commented [setup.tools] in .github/agentic-job/hosted.toml, including ast-outline
and ast-grep. The pin is the API-resolved merge of
agenthome#4,
9b43eb81e1266ec762a6c49a4e31fb6b4ff3e0e0 (main on 2026-10-14).
This configuration waits for the shared actions wrapper to upgrade from
agentic-job v0.2.0 to a release containing
#602; v0.2.0
cannot parse the opt-in. After that upgrade, uncomment the four-line table.
No wrapper input is needed: it already passes
the caller's runner configuration. The installer runs before network
lockdown as the sandbox user, with upstream's 120-second Git phases and
600-second install limit; its code and dependencies are trusted setup,
not sandboxed task code. A real install and hardening check need a fresh
dispatched runner.
.github/workflows/poll.yml runs one
agent-board pass
every ten minutes, with .github/pass.json as its configuration. A pass
follows the bot's pull requests to a fix, a merge or a person, refreshes
the pools' usage from the inference broker and publishes the bot-usage/v1
snapshot the review app reads (from agent-board#306 on), plans and applies the operator's live epics,
starts board work by Priority within wip and each pool's pace, and derives
each board item's Status. Each decision is one line of the run's summary;
agent-board's docs say what each means and what it holds. The rules
themselves live and are tested in agent-board, not here.
The agent-board commit is pinned as AGENT_BOARD_REV in poll.yml, since
the binary gets the bot's token (CGWALTERS_BOT_PAT); move it only with a
review of that revision's pass. The job token starts dispatch.yml and
review.yml runs. The job joins the tailnet for the broker, whose address
is the repository variable INFERENCE_URL (else the organization's
tailnet setting); without the join the pass paces on the last published
snapshot. Passes share one concurrency group and never overlap.
A scheduled pass only previews unless the repository variable PASS_APPLY
is enabled. By hand, gh workflow run poll.yml previews and
-f apply=true applies. Every pass is capped at two agent runs, twenty
other writes and fifty Status changes (more refuses the Status stage, a
preview too, until someone has looked); raise them in poll.yml once the
passes have been watched. New work goes through the board: an open issue
on it in a workRepositories repository, under a live epic or opened by
the operator or the bot, is taken in Priority order. Dispatch by hand
(docs/bring-up.md, "Dispatching a run") for anything else.
A pull request labelled needs-human is not touched again until the label
is removed. A fix run can request one add_comment explaining why it
cannot safely change the pull request, without a push (opt-in in
.github/agentic-job/fix.toml); the unchanged head is what stops the fix
rounds.
Set the repository variable BROKER_OUTAGE=apply to enable the
fifteen-minute broker-probe.yml schedule (off otherwise). It runs
agent-board's
broker probe
at the commit supervisor.yml pins, with .github/broker/config.json. The
probe joins using the dispatch tailnet wrapper and adds INFERENCE_URL to
that config as its url, from the repository variable, else the wrapper's
configured proxy. It makes one TCP
connection and one unauthenticated GET, each bounded to ten seconds; any
HTTP response is reachable, not a claim that inference works. It creates one
bot-owned outage issue here, updates it while down, and comments and
closes it on recovery. Tailnet join or reporting failures fail the workflow,
not a false broker recovery. There are no ACL or credential changes. The
pass does not read the issue.
Design-level work is planned with the operator before any of it runs
(#675): work started
without an agreed target has gone the wrong way. A planning session (the
controller and a subagent working from local clones, iterating with the
operator) files its plan as an issue in this repository, assigned to the
operator and labelled needs-human. Its body leads with the example
contract, the workflow YAML or command a user would actually write, then the
design, the slices in order, risks and open questions
(#674 is one). The
operator's comments ask for revisions. While it has no epic label it is a
plan under review, which the pass does not touch. The operator adding epic
and removing needs-human is the approval; as for any epic, only the
configured operator's label counts. The pass then plans it: the slices
become sub-issues, the example contract the first where there is one, and
it schedules them as for any epic.
supervisor.yml runs agent-board supervise health every fifteen minutes on the default
branch, from its own crons. Every run, a prompt-less dispatch included, is a
health pass. agent-board supervise due decides the sweep from the
times.json the previous supervisor-health artifact carries: a pass
sweeps when the last sweep was two hours ago or more, or on an explicit
request (a prompt or a comment). When that artifact cannot be looked up (as
against there being none), no run but an explicit request sweeps (#814). Scheduled runs used to be skipped: the job also required the
repository variable SUPERVISOR=observe, which was never set. The health pass
only reads, so it now always runs. health.json is a list of checks
with id, status (ok, warn, fail), evidence links and a suggested
action; each check also has one summary line. All thresholds and collection
bounds are in .github/supervisor/config.json, with repository identities
in that file and the existing poll configuration, never dispatcher inputs.
The health step reads with the bot's token (CGWALTERS_BOT_PAT), as the execute
job and the poll do. The usage snapshot (pace) is on a private repository,
.github/usage/config.json's, which the job token cannot read, and the job
token's 1000 requests an hour come near four passes' worth. The step runs
only agent-board built from the pinned revision, never an agent or pull
request code (the operator, 17 Oct: the same token as everything else of the
bot's, rather than a separate read-only one). Missing access and truncated listings are warnings, not
healthy observations, and fail once they have lasted
unavailableFailHours: each pass reads the previous pass's health.json
artifact for since when. API requests have deadlines and a total
budget and a seven-minute collection deadline; the health step has an eight-minute
limit, within a 25-minute job that also builds agent-board afresh using
just build-agent-board at the commit pinned as AGENT_BOARD_REV in
supervisor.yml, which the execute job builds too. As in poll.yml, it
never follows agent-board's branch: the executor receives the bot's token, so
a change to agent-board reaches it only when that pin moves here, after review. The newest health artifact among
the last five completed runs is restored with a two-minute bound and passed as --previous;
a missing or unreadable report starts unavailable timers afresh.
These bounds prevent a stalled API or
oversized census from exhausting a runner. The JSON artifact contains links
and fixed actions, not issue bodies, titles, private decisions or logs.
The health pass reads the epics with its own census.
Recent PR/queue activity is every PR updated within eventLookbackHours,
up to maxPages GraphQL pages per followed repository; it is not a
historical audit. A removal from the queue because the PR merged is not
counted. Infrastructure findings
are warnings from probe/label time overlap, not proof that a retry is safe.
A broker probe switched off (BROKER_OUTAGE unset) is no observation: a warning that fails after an hour.
Decisions currently cover open public question issues assigned to the operator,
excluding ones with an authenticated operator reply; the private decision
document is not published or interpreted. Loop detection uses checkpoint
failures and pending-operation staleness, not speculative interpretation of agent prose.
The checks the controller ran by hand: idle and stuck, which read the
old board scheduler's lines from the log of the job schedulerJob names
and so find nothing in the pass's log (pass) until the supervisor is
redesigned; pace, a
pool's used share of its window beyond paceMarginPercent points from the
share elapsed; failures, the newest dispatch run of a kind and target that
failed with a secret-shaped string, an E0NN safe-output refusal or missing
data naming a closed blocker, from its failed jobs' annotations;
held, needs-human on the bot's PR past holdWaitHours; unqueued, an
approved PR whose merge state is clean, out of the queue past
unqueuedWaitHours; unclosed, the bot's merged implement PR whose run's
issue is open past unclosedWaitHours, unless it says it is part of it.
The agent and the executor (D14) are off unless SUPERVISOR is preview
or apply. No repository variable is changed by this wiring. The agent runs
on a failing check (with agent.cooldownHours cooldown), a two-hour sweep
(decided in the health job, with 7 */2 * * * as a fallback), a manual prompt, or a new comment by the configured operator
on the locked requests issue (here #656). The comment gate also rejects PR comments;
the login and issue are checked against trusted config in tests. The requests
issue must be locked by the operator before comment wakes work. Another
deployment sets the repository variables OPERATOR and
SUPERVISOR_REQUESTS_ISSUE to its operator and agent.requests.issue,
since that gate runs before checkout; unset, they default to this one's.
gh workflow run supervisor.yml -R cgwalters-forge/tracker \
-f prompt="close what triage found done in agent-board"A check that cannot clear fails every pass and so started an agent every
cooldown hour to read the same report (#804). With
agent.skipUnchangedFailures set to true (it ships false),
agent-board supervise repeat leaves the trigger out of a pass that
is not a sweep or request when no check fails that did not fail in the
previous report; the sweep reads standing failures and their new evidence.
A failure that first appeared while the trigger declined (cooldown, an
active agent) also waits for a sweep.
Comments, prompts and the sweep share workflow-wide supervisor-agent
concurrency without cancelling an active run, so a request waits through the
previous executor instead of the trigger discarding it. The fifteen-minute
health passes, prompt-less dispatches included, use supervisor-health: GitHub retains only one pending run per
group and a newer arrival replaces it, so a shared group would let the next
pass evict a queued prompt. A health pass that finds an agent active declines
and retries after its cooldown; a prompt the trigger declines fails its run.
The executor keeps its own supervisor-execute group. A second prompt queued
behind a pending one still replaces it, so use the requests issue for durable
requests and steering an active agent.
The agent is a research run
of the shared wrapper, using agent.pool and the wrapper's read-only job
token, not the bot token. Its task includes the supervisor profile and skill
of the agenthome repository and commit that agent.profile pins, agent-board's policy and this pass's health report. It also
reads docs/operator-notes.md, the latest supervisor-health artifact's
health.json and the configured state issue. Its isolated runner config sets
session.watch-item = true: later comments arrive as attributed data, and
only the configured operator's comments are instructions. Its one comment on
the requests issue carries a supervisor-actions block of typed requests.
agent.state names the locked state issue #718, distinct from the requests
and log issues. replace_state edits only that issue's body, within its
daily cap below. The body persists and every later run reads it first, so a
misled run can plant text for later runs; it is data to them, but with the
other caps above zero a later run can act on it within those caps. A batch
that would pass a daily cap is rejected whole. Missing state is reported,
never guessed.
The execute job holds CGWALTERS_BOT_PAT in the agent-apply
environment and runs no agent code. It executes only on a run's first
attempt, and accepts only the bot's comment, unedited, on the requests
issue that this run's apply reports. It validates the whole
batch with agent-board supervise execute. The shared executor admits
dispatches, with fixed briefs and reasons, on open issues whoever wrote them,
and an implement dispatch only under an open epic-labeled parent. The
boundary against an injected request is the run's sandbox and the required
pull request review, not collaborator-only input (agent-board#158). That
review is a model's verdict (review.yml), and the pass merges an approved,
green head, so an issue anyone writes can reach a merge with no human step;
the caps bound how many runs it can spend.
Trusted config names the permitted dispatch kinds, tracker and project, and
the caps: maxDispatchesPerPass: 4 and
maxDispatchesPerDay: 40, and the daily caps comment: 20,
create_issue: 15, close: 10, remove_needs_human: 12,
replace_state: 48 and status_update: 1.
Only the operator raises caps
after review. The executor records requests before starting them, stops at the
first failed write, and logs the outcome without agent text.
agent-board supervise trigger supplies the wrapper inputs through
GITHUB_OUTPUT. In preview, the execute job lists the proposed comment
without a bot token or calling the executor (which always writes its log).
Only SUPERVISOR=apply runs agent-board supervise execute with the bot token.
The hosted preview proof still requires an operator-enabled run: confirm it
lists requests and applies none, then compare a week of preview against the
local loop before enabling apply with small caps.
The pacing, the repeat check, the task composition and the preview are
agent-board's supervise due, repeat, compose and preview, tested
there. CI builds the supervisor workflow's exact pin with
just build-supervisor-agent-board, and just test-supervisor-config runs
supervise trigger on empty health checks, without --daily, to validate the
shipped settings and executor policy without API calls or writes.
The agent cannot read the private decisions document (its token reads only this repository), and the review site's last-run panel is cgwalters-forge/review's to build; both are left from #626.
.github/workflows/release-train.yml runs agent-board's
release-train,
at the commit it pins as AGENT_BOARD_REV, to cut agentic-job's releases and
move the pins after them (#650), in the order the controller did by hand: the
version bump PR, release.yml once it merges, the pin bump of the actions
wrappers once the release is out, then the review.yml pin bumps of the
callers once that merges. The repositories, files, threshold and labels are
in .github/release-train/config.json. A release is due when at least
threshold PRs merged since the last one and that was intervalHours ago,
or at once when one of them is labelled P0; the bump is minor if one is
labelled breaking, a patch otherwise. A release cut outside the train,
by hand or by anyone, is followed all the same (#723): when the wrappers
pin an older version than the latest release, a pass opens a train for that
release starting at the wrappers' pin bump, unless a train for it was
closed or its tag is not on agentic-job's default branch. The PRs come from the bot's forks
with the release notes for the callers' interface changes, and go through
each repository's review and queue; the train only waits for them.
It is off unless the repository variable RELEASE_TRAIN is dry-run,
which prints each pass's step, or apply, which takes it with
CGWALTERS_BOT_PAT: that token needs to open issues here, push to the bot's
forks (named in the configuration: a fork need not share its parent's name)
with the workflows permission, as the pins are in workflow files, open PRs
upstream and run agentic-job's release.yml. Each release
has one tracking issue here, opened by the bot and labelled
release-train, with a comment per step. A step it cannot take (a PR closed
unmerged, a failed release.yml, a file whose pin it cannot find) labels
the issue needs-human, which halts the train until the label goes; closing
the issue drops that release: a later train for the same version ignores
its closed PRs, halts on one still open, and does not start while main has
a version bump that was never released. agent-board release-train --config .github/release-train/config.json is a dry pass with the token in
GH_TOKEN; its tests are agent-board's.