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
2 changes: 1 addition & 1 deletion docs/devteam/process/supervisor.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ Production is watched by **sensors**, and they are yours: you add, change and st

- `devteam.mjs ready` lists tickets whose dependencies are merged and that have no worker; `--plan-ahead` adds those that can spec and plan now. To keep a ready ticket unscheduled on purpose (it may duplicate other work, it waits on the owner), `ticket set <id> --json '{"held": "<why>"}'`; `ready` and the idle-capacity finding then leave it out, and `{"held": null}` releases it. Caps: `max_active_tickets` (your review capacity is the real limit) and `max_active_per_component`. The machine is shared with other projects' fleets, so a new worker or planner doesn't start while the machine's memory is at `machine_memory_ceiling` (default 0.8 of its cap, from 0.5 to 0.95); a resume of a session that already ran always starts (`--resume` on one that never ran is a new start). When a start is refused for memory, or the `memory-full` finding shows in place of idle capacity, wait for sessions to finish rather than passing `--force`: forcing it is how the box runs out and restarts every fleet on it. If you keep hitting the ceiling, lower your own `max_active_tickets`; it is your setting, not a question for the owner. Prefer the critical path, then contract tickets, then tickets that close a story.
- `devteam.mjs worker <id>`; `worker <id> --resume` relaunches a crashed one in the same window and worktree with `resume_command`.
- **Merging.** A `merge-request` message names the exact head. Read the diff, the final review record and `verification.md` yourself, then `devteam.mjs merge <id>`. It runs `check-ticket` at that head, the log rule, and every gate in the settings in a clean worktree at that head, merges with `--match-head-commit` (or, with `forge: "git"`, merges that sha and pushes), and logs the act. `--dry-run` does everything but the merge (and works on a branch with no PR yet). A ticket you added since the log last landed fails the forge's checks (`project/tickets/<id>/ has no ticket`) until its line is on main, because the forge reads only the landed log: land the log first (`log-sync`, then `merge --chore log`) and rerun them. If anything fails it says what; reply to the worker with `--kind ruling --re <message-id>`. A head that moved after the request is a new request. You never merge any other way, and workers never merge.
- **Merging.** A `merge-request` message names the exact head. Read the diff, the final review record and `verification.md` yourself, then `devteam.mjs merge <id>`. It runs `check-ticket` at that head, the log rule, and every gate in the settings in a clean worktree at that head, merges with `--match-head-commit` (or, with `forge: "git"`, merges that sha and pushes), and logs the act. `--dry-run` does everything but the merge (and works on a branch with no PR yet). A ticket you added or changed (`ticket add`, or `ticket set` on touches or done-whens) since the log last landed is checked as main's log has it: a new one fails (`project/tickets/<id>/ has no ticket`), widened touches fail (`changes files outside touches`), until its line is on main, because the forge reads only the landed log: land the log first (`log-sync`, then `merge --chore log`) and rerun them. If anything fails it says what; reply to the worker with `--kind ruling --re <message-id>`. A head that moved after the request is a new request. You never merge any other way, and workers never merge.
- **Other repos.** `merge` works per repo; the ticket says which (its component's `link`). `fleet status` lists each repo link with its path, and a sibling whose origin it can't fetch is a blocker. A ticket whose repo has no checkout on this machine waits as "repo unreachable"; `link-unreachable` says what to clone where.
- **Chore PRs** (`merge --chore <slug>`: log, retros, designs, the architecture doc) may not touch `project/log` (except `chore-log`, which touches nothing else) or `project/tickets`. One that changes anything outside `project/` (`.claude/`, `.github/`, the kit) needs the owner's answer, `merge --chore <slug> --approved <qid>`; one that changes a real kit file (under the kit's own path, other than `project/` and `run/`) needs it in a `governance-edit`, `process-edit` or `gate-change` question, however it was given (chat counts). Kit files merged verbatim from upstream need no question (`chore-devteam-sync-<tag>` under `upstream_sync` `"adopt"` or a standing rule, §9), and a secret chore (`chore-secret-<n>`) lands the encrypted stores with the answer that posted them.
- **The forge's checks.** `merge` refuses while any check on the PR's head is pending or failing, whether or not branch protection requires it (a deploy pipeline's status counts too). Wait and merge again. A check that's broken or irrelevant is the owner's to skip, in `ignored_checks`.
Expand Down
2 changes: 1 addition & 1 deletion docs/devteam/scripts/devteam.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3722,7 +3722,7 @@ function checkTicket(id, { sha: shaArg, title, body, approvals = true }) {
const own = R.projectInRepo ? `${R.projectRel}/tickets/${id}/` : null;
const mineOwn = (f) => !!own && f.startsWith(own);
const outside = changed.filter((f) => !mineOwn(f) && !(t.touches ?? []).some((g) => pathMatches(g, f)));
if (outside.length) fails.push(`changes files outside touches: ${outside.slice(0, 10).join(', ')}${outside.length > 10 ? ` (+${outside.length - 10} more)` : ''}`);
if (outside.length) fails.push(`changes files outside touches: ${outside.slice(0, 10).join(', ')}${outside.length > 10 ? ` (+${outside.length - 10} more)` : ''}; if the supervisor widened touches with ticket set since the log last landed, land the log first (log-sync, then merge --chore log) and check again`);
// Component lines: a changed file is also inside the ticket's component's line or
// a touches_components member's; the kit's own line is closed but for the ticket's own folder.
// Judged by main's committed settings, so neither a line widened in a working tree nor the
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/g1/check-ticket.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
exit 1
--- stdout
fail: changes files outside touches: OUTSIDE.md
fail: changes files outside touches: OUTSIDE.md; if the supervisor widened touches with ticket set since the log last landed, land the log first (log-sync, then merge --chore log) and check again
--- stderr

2 changes: 1 addition & 1 deletion test/fixtures/g1/merge-dry-run.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
exit 1
--- stdout
fail: changes files outside touches: OUTSIDE.md
fail: changes files outside touches: OUTSIDE.md; if the supervisor widened touches with ticket set since the log last landed, land the log first (log-sync, then merge --chore log) and check again
fail: no gates in settings (gates: {name: command}); pass --no-gates to merge without running any
--- stderr

Loading