Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions .claude/skills/orchestrate/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ node tools/plan-queue.mjs (--tickets ORB-1,ORB-2 | --board) [--format mar
node tools/comment-ticket.mjs --issue "<ticket-ref>" --body-file <path|->
node tools/complete-ticket.mjs --issue "<ticket-ref>" [--preflight]
node tools/compose-prompt.mjs --issue "<ticket-ref>" --repo <key> --out <file> [--worktree <p>] [--branch <b>] [--base <ref>]
node tools/launch-worker.mjs --issue "<ticket-ref>" --worktree <p> --prompt <f>
node tools/launch-worker.mjs --issue "<ticket-ref>" --worktree <p> --prompt <f> [--hard-ceiling-minutes <n>]
node tools/verify-delivery.mjs --issue "<ticket-ref>" --worktree <p> --branch <b> --repo <key> [--base <ref>] [--wait-ci <s>]
node tools/list-bot-threads.mjs --pr <n-or-url> --repo <key> [--wait-seconds <s>]
node tools/resolve-bot-thread.mjs --thread <PRRT_...> --repo <key> --pr <number> # reply body on stdin
Expand Down Expand Up @@ -501,13 +501,17 @@ Write it to the scratchpad. A prompt file inside the worktree gets committed by
## Steps 5 and 6. Spawn the worker

```bash
node tools/launch-worker.mjs --issue "<ticket-ref>" --worktree <p> --prompt <f>
node tools/launch-worker.mjs --issue "<ticket-ref>" --worktree <p> --prompt <f> [--hard-ceiling-minutes <n>]
```

Headless, `stdin=NUL`, `cwd` = the worktree, log to the scratchpad.

`launch-worker.mjs` runs in the FOREGROUND as its own watchdog and owns both clocks: a hard 45
minute cap and a 10 minute no-progress cap, killing the whole process tree on either.
`launch-worker.mjs` runs in the FOREGROUND as its own watchdog and owns both clocks: the hard
ceiling and the no-progress cap from `.claude/orchestrator.json` (currently 45 and 10 minutes),
killing the whole process tree on either. Pass `--hard-ceiling-minutes` at launch for a ticket the
plan already shows outrunning the fleet-wide ceiling: a large migration, a subsystem ticket, or one
whose test matrix is the work. Three finished workers died at the fixed 45 on 2026-08-22 for
exactly that shape.

The orchestrator launches it as a **background shell task and ends its turn.** Zero tokens burn
while the worker runs, and the process exiting is what wakes the session.
Expand Down
12 changes: 10 additions & 2 deletions .github/workflows/visual.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,22 @@ jobs:
if: steps.mode.outputs.seed == 'true'
run: |
set -euo pipefail
git lfs install --local
# --skip-repo: lefthook owns .git/hooks, and a plain install exits 2 refusing to
# overwrite them. This step only needs the LFS clean filter for the PNG add.
git lfs install --local --skip-repo
Comment thread
thomasluizon marked this conversation as resolved.
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add apps/web/e2e/visual/__screenshots__
if git diff --cached --quiet; then
echo "Baselines already up to date — nothing to commit."
else
git commit -m "test(web): update hermetic visual baselines (#461 B1) [skip ci]"
# This push uses the workflow's GITHUB_TOKEN, and GitHub never starts workflow runs
# for events that token causes, so the bot head gets NO required checks either way.
# [skip ci] stays out because it overstated intent while adding nothing the token
# suppression does not already do. main requires 21 checks per head, so after a
# labeled re-seed the operator's next real push (or a checks re-run) is what puts the
Comment thread
thomasluizon marked this conversation as resolved.
Comment thread
thomasluizon marked this conversation as resolved.
# required contexts on the head. The staged-diff guard above is the seed-loop stop.
Comment thread
thomasluizon marked this conversation as resolved.
git commit -m "test(web): update hermetic visual baselines (#461 B1)"
Comment thread
thomasluizon marked this conversation as resolved.
git push origin "HEAD:${{ github.head_ref || github.ref_name }}"
fi

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
179 changes: 177 additions & 2 deletions packages/shared/src/types/__generated__/api.generated.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ name or git status. Read `CONVENTIONS.md` before adding one.
| `complete-ticket.mjs` | Owns the explicit post-merge transition. `--preflight` proves the open ticket and configured project item without writing. Completion sets Status Done and closes the issue as completed. `--repair-status` is the inverse, for a ticket GitHub already closed from a merge commit: it reconciles the board Status with the close reason (completed to Done, not planned to Canceled, duplicate to Duplicate), writes nothing else, and is a no-op when the column already agrees. `--cancel --reason-file` closes an open ticket whose work is GONE rather than done: it posts the required reason, sets Status Canceled and closes as not planned, so deleted work is never recorded as shipped. | `node tools/complete-ticket.mjs --issue <ORB-N\|#N\|N> [--preflight \| --repair-status \| --cancel --reason-file <path\|->]` |
| `plan-queue.mjs` | Resolves a scope (explicit tickets, a GitHub milestone, or the configured board) into ONE ordered execution plan: admission and deferrals, DAG-safe waves, transitive fan-out (`unlocks`), and stackable dependency chains. A ticket whose same-repo blockers do not form one chain has no branch that can carry them, so it defers as `UNSTACKABLE_BLOCKERS_IN_QUEUE` and the rest of the board still plans; cross-repo blockers order but never stack. A still-open blocker outside the queue defers the ticket. It plans only, and writes nothing anywhere. | `node tools/plan-queue.mjs (--tickets ORB-1,#123 \| --project <name> \| --board)` (`--format markdown`) |
| `compose-prompt.mjs` | Builds one worker prompt: the GitHub ticket body verbatim, the orchestrator's brief (objective, scope, output, boundaries), and the finishing contract. Refuses to write inside any declared repo, because a worker that finds its own work order in the tree can commit it. | `node tools/compose-prompt.mjs --issue <ORB-N\|#N\|N> --repo <ui\|api\|landing> --out <abs path>` |
| `launch-worker.mjs` | Spawns one headless worker and supervises it in the foreground. Both clocks kill the complete process tree, and this process is itself the run's wake source. `--measurement` swaps the no-progress clock for the measurement one and leaves the hard ceiling alone. `--dry-run` prints the resolved plan and spawns nothing. GitHub credentials are owner-selected per child environment; global account state is never switched. It launches a worker; it never merges, reviews, or moves a ticket. | `node tools/launch-worker.mjs --issue <ORB-N\|#N\|N> --worktree <path> --prompt <file>` (`--measurement`, `--dry-run`) |
| `launch-worker.mjs` | Spawns one headless worker and supervises it in the foreground. Both clocks kill the complete process tree, and this process is itself the run's wake source. `--measurement` swaps the no-progress clock for the measurement one and leaves the hard ceiling alone. `--hard-ceiling-minutes <n>` replaces the configured ceiling for this one launch, for a ticket that legitimately outruns the fleet-wide default. `--dry-run` prints the resolved plan and spawns nothing. GitHub credentials are owner-selected per child environment; global account state is never switched. It launches a worker; it never merges, reviews, or moves a ticket. | `node tools/launch-worker.mjs --issue <ORB-N\|#N\|N> --worktree <path> --prompt <file>` (`--measurement`, `--hard-ceiling-minutes <n>`, `--dry-run`) |
| `verify-delivery.mjs` | Derives delivery solely from bounded Git and GitHub children: clean/pushed/current PR, exact current-head CI state, and GitHub compare `behind_by=0`. `OUT_OF_DATE` reports base/head SHAs and behind count. File and line counts remain `sizeAdvisory` and never block. Completed CI passes only on the confirmed `SUCCESS`, `NEUTRAL`, or `SKIPPED` allowlist; every other or future conclusion fails closed. Failed CI retains run/check ID, details URL, workflow, name, status and conclusion; newest rerun wins. | `node tools/verify-delivery.mjs --issue <ORB-N\|#N\|N> --worktree <p> --branch <b> --repo <key>` (`--base`, `--wait-ci`, `--command-timeout-seconds`) |
| `record-readiness.mjs` | Reads the live PR base/head/draft, its branch's required status checks, the compare, and the ticket ONCE, then persists and evaluates one repository-qualified receipt. READY requires green CI over the required contexts, a non-draft state, live `behind_by=0`, and ticket synchronization simultaneously; evidence pinned to an older head or base becomes an explicit stale verdict, and every verdict is reported together. The code review is NOT a separate axis: Pullfrog publishes `pullfrog-approval` as a required status check, so the verdict already arrives through the required contexts this tool reads. It never trusts a caller-authored status flag. | `node tools/record-readiness.mjs --repo <ui\|api\|landing> --pr <number> --delivery <file> --ticket <file>` |
| `sync-issue-state.mjs` | Asserts the live ticket carries exactly the `repo:<key>` label matching `--repo` before either write, so a mistyped ticket key cannot move or comment on a stranger's ticket. Moves working and blocked states to In Progress and simultaneous technical readiness to In Review, never Done. Stores the last posted state to suppress duplicate comments and emits a receipt for the readiness state machine. | `node tools/sync-issue-state.mjs --issue <ORB-N\|#N\|N> --repo <key> --pr <n> --state <working\|blocked\|ready> --head-sha <sha> --base-sha <sha> --message-file <path\|->` |
Expand Down
Loading