diff --git a/CLAUDE.md b/CLAUDE.md index 13953a25..cab160b2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -156,6 +156,8 @@ Order every file (components, tests, utils) with the primary logic first — the - **PR creation**: Always Read `.claude/skills/create-pr/SKILL.md` directly and follow it exactly (title format, description length, verification bullets) before opening or updating a PR — regardless of how the task was triggered (explicit `/create-pr`, an auto-delivered instruction block, etc). Don't rely on a paraphrased or summarized version of the skill's rules. +- **Naming a branch or a commit/PR title**: See `docs/git-conventions.md`. + ## Agent skills ### Issue tracker diff --git a/docs/agents/autonomic-issues.md b/docs/agents/autonomic-issues.md index c12e72c9..c8e19cb6 100644 --- a/docs/agents/autonomic-issues.md +++ b/docs/agents/autonomic-issues.md @@ -4,15 +4,15 @@ Two Claude Code Routines work this repo's Linear issue backlog (team `UPL`) so t The paste-ready Routine prompts are at the [bottom of this doc](#routine-prompts); everything above them is the playbook those prompts point into. -## Shared state: the `agent:` labels +## Shared state: the `agent` label + issue status -In-flight state lives as labels **on Linear issues**; an issue's label tells any fresh firing where it is in the pipeline. Meaning and who applies each: `docs/agents/triage-labels.md`. Application mechanics (claim comment, PR swap) are in the Fix firing steps below. The PR title/body carries the Linear identifier (e.g. `UPL-123`, per `docs/agents/issue-tracker.md`) so Linear's GitHub integration transitions the linked issue when the PR merges — that transition happens outside the routine (merging is the maintainer's, per Guardrails), so don't treat it as something the fix firing itself performs. +In-flight state lives on **Linear issues** as one label (`agent`) plus the issue's native status; a fresh firing reads both to know where an issue sits in the pipeline. `agent` marks "an agent currently owns this issue or has an open PR for it" — the stage within that is the status, not a second label: `In Progress` while claimed and being worked, `In Review` once the PR is open. `agent` is a lifecycle marker, standalone from the mutually-exclusive triage-role label group (see `docs/agents/triage-labels.md`). Application mechanics (claim, status transitions) are in the Fix firing steps below. The PR title/body carries the Linear identifier (e.g. `UPL-123`, per `docs/agents/issue-tracker.md`) so Linear's GitHub integration transitions the linked issue when the PR merges — that transition happens outside the routine (merging is the maintainer's, per Guardrails), so don't treat it as something the fix firing itself performs. -**The PR cap**: at run start the fix worker counts non-terminal Linear issues labeled `agent:pr`: `npx linearis issues list --team UPL --label agent:pr --fields identifier,state.name` (`list` excludes `completed` issues by default) then drop any row whose `state.name` is `Canceled` — `--state-type` only accepts one category per call, so filtering the remaining terminal state client-side (e.g. via `jq`) is simpler than issuing four separate `--state-type` calls (`triage`/`backlog`/`unstarted`/`started`). At or above **3**, the review queue is full — end silently. Counting issues rather than PRs stays correct even if a PR-side label is forgotten. Firings can overlap with no mutual exclusion, so this in-prompt count is the enforcement; a rare overshoot-by-one is accepted. +**The PR cap**: at run start the fix worker counts Linear issues labeled `agent` with status `In Review`: `npx linearis issues list --team UPL --label agent --status "In Review"`. At or above **3**, the review queue is full — end silently. Firings can overlap with no mutual exclusion, so this in-prompt count is the enforcement; a rare overshoot-by-one is accepted. -**Coexistence with manual sessions**: agents skip any issue with an assignee or with an open linked PR — assignment means "mine, hands off". Manual-session PRs count against the cap only if the maintainer labels the issue `agent:pr` himself. +**Coexistence with manual sessions**: agents skip any issue with an assignee or with an open linked PR — assignment means "mine, hands off". Manual-session PRs count against the cap only if the maintainer labels the issue `agent` and moves it to `In Review` himself. -**Stale claims**: the triage sweep releases any `agent:wip` older than ~24h (by the claim discussion's timestamp) with no open linked PR: remove the label and leave a "stale claim released" reply in the issue's discussion thread. The fix worker finishes within its firing, so a day-old claim without a PR is dead. +**Stale claims**: the triage sweep releases any issue labeled `agent` with status `In Progress` older than ~24h (by the claim discussion's timestamp) with no open linked PR: remove the label, move the status back to `Todo`, and leave a "stale claim released" reply in the issue's discussion thread. The fix worker finishes within its firing, so a day-old claim without a PR is dead. ## Triage firing @@ -42,16 +42,16 @@ All four hold → label `ready-for-agent`. Missing (a)/(b) → `needs-info`. Mis ## Fix firing -1. **Repair before build**: list Linear issues labeled `agent:pr` (`npx linearis issues list --team UPL --label agent:pr`) and follow each to its open linked PR — use `npx linearis issues read --with-attachments` to find the linked GitHub PR, then `gh pr view ` to check its state; issues are the source of truth, the PR-side label is display convenience and may be missing. If any such PR is conflicted with main or CI-red on its current head, restoring it (merge main in, get CI green through the quality gates) **is** this firing's work — then end. PRs the maintainer has left review comments on are his: leave them untouched. Broken agent PRs always stay counted against the cap — unreviewed PRs are exactly the review debt the cap limits. -2. **Cap check**: same non-completed `agent:pr` count as above; at or above 3 → end silently. +1. **Repair before build**: list Linear issues labeled `agent` with status `In Review` (`npx linearis issues list --team UPL --label agent --status "In Review"`) and follow each to its open linked PR — use `npx linearis issues read --with-attachments` to find the linked GitHub PR, then `gh pr view ` to check its state; the Linear issue is the source of truth, nothing on GitHub needs to mirror it. If any such PR is conflicted with main or CI-red on its current head, restoring it (merge main in, get CI green through the quality gates) **is** this firing's work — then end. PRs the maintainer has left review comments on are his: leave them untouched. Broken agent PRs always stay counted against the cap — unreviewed PRs are exactly the review debt the cap limits. +2. **Cap check**: same `agent` + `In Review` count as above; at or above 3 → end silently. 3. **Pick one issue**: `ready-for-agent` issues, skipping any with an assignee or an open linked PR, ordered by the native `priority` field — Urgent(1) → High(2) → Medium(3) → Low(4) → No priority(0) — oldest first within each rank (`npx linearis issues list --team UPL --label ready-for-agent --fields identifier,priority,createdAt`, sorted client-side since `--order-by` only covers `created`/`updated`). None eligible → end silently. -4. **Claim**: apply `agent:wip` (`npx linearis issues update --labels agent:wip --label-mode add`) and post a claim discussion (timestamp + branch name) via `npx linearis issues discuss --body "..."` before any work. Branch naming: `type-id/slug`, e.g. `fix-448/consolidate-set-types`. +4. **Claim**: apply `agent` and move status to `In Progress` (`npx linearis issues update --labels agent --label-mode add --status "In Progress"`) and post a claim discussion (timestamp + branch name) via `npx linearis issues discuss --body "..."` before any work. Branch naming: see `docs/git-conventions.md` (issue-linked variant, e.g. `fix-448/consolidate-set-types`). 5. **Implement via the implement skill**: Read `.claude/skills/implement/SKILL.md` directly and follow it, with the issue as the spec. Its steps run inside the quality gates (below). -6. **Open the PR** following `.claude/skills/create-pr/SKILL.md` exactly, with the Linear identifier (e.g. `UPL-123`) in the PR title or body per `docs/agents/issue-tracker.md` — not `Closes #N`, which only works for GitHub issues. Swap the issue's `agent:wip` to `agent:pr` via `npx linearis issues update --labels agent:wip --label-mode remove` then `--labels agent:pr --label-mode add`; label the GitHub PR itself `agent:pr` via `gh pr edit --add-label agent:pr` (PR labeling stays on GitHub). One PR per firing — done. +6. **Open the PR** following `.claude/skills/create-pr/SKILL.md` exactly, with the Linear identifier (e.g. `UPL-123`) in the PR title or body per `docs/agents/issue-tracker.md` — not `Closes #N`, which only works for GitHub issues. Move the issue's status from `In Progress` to `In Review` (`npx linearis issues update --status "In Review"`); `agent` stays applied. One PR per firing — done. -**Mid-run bail**: the picked issue turns out not agent-ready (spec gap, missing access, actually a design decision) → re-route it (`needs-info` with questions, or `ready-for-human`) with a comment on what you found, remove `agent:wip`, and pick the next eligible issue — still at most one PR per firing. +**Mid-run bail**: the picked issue turns out not agent-ready (spec gap, missing access, actually a design decision) → re-route it (`needs-info` with questions, or `ready-for-human`) with a comment on what you found, remove `agent` and move status back to `Todo`, and pick the next eligible issue — still at most one PR per firing. -**Failed run**: you worked the issue but can't reach green/tested → comment what was tried and where it got stuck, push the branch for salvage (no PR), remove `agent:wip`, and flip `ready-for-agent` to `ready-for-human`. One honest failure means the issue wasn't actually agent-ready; the maintainer can flip it back after reading the findings. No retry counters. +**Failed run**: you worked the issue but can't reach green/tested → comment what was tried and where it got stuck, push the branch for salvage (no PR), remove `agent` and move status back to `Todo`, and flip `ready-for-agent` to `ready-for-human`. One honest failure means the issue wasn't actually agent-ready; the maintainer can flip it back after reading the findings. No retry counters. ### Quality gates — all four, before flagging for review @@ -77,7 +77,7 @@ Both routines run with push notifications on. The platform sends a push only whe ## Setup checklist (manual, one-time) -1. Create the labels in `docs/agents/triage-labels.md`'s pipeline-labels table (`agent:wip`, `agent:pr`, `epic`) plus the five canonical triage-role labels in **Linear**, team `UPL` — `bug`/`enhancement`/`chore` should already exist there. Priority uses Linear's native `priority` field, not a label — nothing to create for it. Also create the `agent:pr` label in **GitHub** (`chiptus/UpLine`), since PR-side tagging stays there. +1. Create the labels in `docs/agents/triage-labels.md`'s pipeline-labels table (`agent`, `epic`) plus the five canonical triage-role labels in **Linear**, team `UPL` — `bug`/`enhancement`/`chore` should already exist there. Group the five triage-role labels into a single mutually-exclusive Linear label group (team `UPL` → Labels → group these five together); leave the pipeline labels standalone, outside that group. Priority uses Linear's native `priority` field, not a label — nothing to create for it. Pipeline stage within `agent` uses the team's existing `In Progress` / `In Review` statuses — nothing to create for those either. 2. Create the **triage** Routine: daily, Sonnet (a test firing showed Haiku mis-triages — it judges from issue text alone instead of verifying premises in the codebase), this repo only, Default (trusted-network) environment, connectors for GitHub (PR operations) plus `LINEAR_API_TOKEN` available in the environment for `linearis` (see `.agents/skills/linearis/SKILL.md` preflight), push notifications on, prompt below. 3. Create the **fix** Routine: daily ~1h after triage, stronger model, same scoping, push notifications on, prompt below. 4. Routine prompts stay short pointers — evolve the pipeline by editing this doc via PR, not the Routine form. diff --git a/docs/agents/issue-tracker.md b/docs/agents/issue-tracker.md index c9e7f1cd..c1161617 100644 --- a/docs/agents/issue-tracker.md +++ b/docs/agents/issue-tracker.md @@ -9,7 +9,7 @@ Issues for this repo live in Linear, team **UPL**. Use the `linearis` CLI (`npx - **List issues**: `npx linearis issues list --team UPL --fields identifier,title,state.name,labels` with state/label filters as needed — check `usage` for the exact filter flags. - **Comment / discuss**: use the `issues discuss` / `discussions` / `replies` / `reply` commands (threaded discussion), not the deprecated top-level `comments` facade. Record non-trivial progress in a discussion thread and keep the description in sync on status changes. - **Apply / remove labels**: via `issues update` (or the dedicated label flag `usage` documents). -- **Close / change state**: via `issues update --state ...` — Linear states are workflow states, not a boolean open/closed; confirm the state names for this team with `npx linearis` (team/workflow usage) rather than assuming GitHub-style "closed". +- **Close / change state**: via `issues update --status ...` — Linear states are workflow states, not a boolean open/closed; confirm the state names for this team with `npx linearis` (team/workflow usage) rather than assuming GitHub-style "closed". IDs are forgiving: pass a UUID, team key (`UPL`), issue identifier (`UPL-123`), or name interchangeably. Reference tickets by identifier in commits, PR bodies, and comments. diff --git a/docs/agents/triage-labels.md b/docs/agents/triage-labels.md index cda3e3c9..2dd4854d 100644 --- a/docs/agents/triage-labels.md +++ b/docs/agents/triage-labels.md @@ -2,9 +2,9 @@ Every label the autonomic issue pipeline reads or writes, what it means, and who's allowed to apply it. -## Canonical triage-role labels +## Canonical triage-role labels — a mutually-exclusive Linear label group -The skills speak in terms of five canonical triage roles. This table maps those roles to the actual label strings used in this repo's issue tracker. +The skills speak in terms of five canonical triage roles. In Linear these five live together in a single **label group** (Linear's mutually-exclusive label set): applying one automatically clears any other member of the group from the issue, so an issue can never carry two triage-role labels at once. Group setup: `docs/agents/autonomic-issues.md`'s setup checklist. | Label in mattpocock/skills | Label in our tracker | Meaning | | -------------------------- | -------------------- | ---------------------------------------- | @@ -18,16 +18,17 @@ When a skill mentions a role (e.g. "apply the AFK-ready triage label"), use the Edit the right-hand column to match whatever vocabulary you actually use. -## Pipeline labels +## Pipeline labels — lifecycle markers, kept outside the triage group -Repo-specific labels the autonomic pipeline (`docs/agents/autonomic-issues.md`) uses outside the five canonical roles above — not part of the mattpocock/skills vocabulary, so a skill invocation won't look for them here. +Repo-specific labels the autonomic pipeline (`docs/agents/autonomic-issues.md`) uses outside the five canonical roles above — not part of the mattpocock/skills vocabulary, so a skill invocation won't look for them here. These are lifecycle markers, not triage roles: they stay standalone (not in the label group above) because they track pipeline progress alongside a triage-role label, not instead of one — an issue can be `ready-for-agent` and `agent` at the same time. -| Label | Meaning | Applied by | -| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | -| `epic` | Tracking-only parent issue whose work has already been fully split into sub-issues, each carrying its own state label. Stays open only to track them; excluded from triage intake. | Triage firing — self-service, no maintainer confirmation needed | -| `agent:wip` | An agent has claimed the issue this firing. | Fix firing | -| `agent:pr` | An agent PR for this issue is awaiting review. | Fix firing (swapped from `agent:wip` on opening the PR) | -| `wayfinder:*` | Belongs to a separate design/spec workflow, not this pipeline. | Never by this pipeline — triage skips these tickets entirely | +| Label | Meaning | Applied by | +| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | +| `epic` | Tracking-only parent issue whose work has already been fully split into sub-issues, each carrying its own state label. Stays open only to track them; excluded from triage intake. | Triage firing — self-service, no maintainer confirmation needed | +| `agent` | An agent currently owns this issue or has an open PR for it. The stage isn't a separate label — it's the issue's native status: `In Progress` while claimed, `In Review` once the PR is open. | Fix firing | +| `wayfinder:*` | Belongs to a separate design/spec workflow, not this pipeline. | Never by this pipeline — triage skips these tickets entirely | + +(Superseded 2026-09-13: this repo previously tracked the same two stages with separate `agent:wip`/`agent:pr` labels; those labels have been retired in Linear now that status covers the distinction.) ## Priority diff --git a/docs/git-conventions.md b/docs/git-conventions.md new file mode 100644 index 00000000..aa4f3b2b --- /dev/null +++ b/docs/git-conventions.md @@ -0,0 +1,24 @@ +# Git Conventions + +Single source of truth for branch naming and commit/PR title format. Referenced from `CLAUDE.md` and `docs/agents/autonomic-issues.md` instead of restated there. + +## Type + +Shared across branch names and commit/PR titles below: one of `feat`, `fix`, `refactor`, `perf`, `test`, `docs`, `style`, `ci`, `chore`, `revert`. + +## Branch naming + +`/` — e.g. `fix/consolidate-set-types`. + +The autonomic pipeline's issue-linked variant ties a branch to its Linear issue: `-/`, e.g. `fix-448/consolidate-set-types`, where `` is the numeric part of the Linear identifier (`UPL-448` → `448`). + +## Commit message / PR title format + +This repo has no commitlint config — `.claude/skills/create-pr/SKILL.md` is the enforced convention for PR titles, and commit messages should follow the same shape: + +`(): ` + +- **Scope**: the module/feature affected (e.g. `groups`, `voting`, `auth`, `filters`, `components`). +- **Subject**: lowercase, imperative mood, no period. + +See `.claude/skills/create-pr/SKILL.md` for the full PR title/description/verification rules.