[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6ENHPWYMN66EYQBV56HP9CW":3,"skill-same:01M6ENHPWYMN66EYQBV56HP9CW":65},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":32,"linkOnly":33,"markdownContent":34,"markdownBody":35,"frontMatter":36,"refName":39,"commitSha":40,"skillDirectory":41,"forksCount":42,"repositoryHtmlUrl":43,"repositoryHomepageUrl":6,"ownerHtmlUrl":44,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":45,"install":46,"resources":58},"01M6ENHPWYMN66EYQBV56HP9CW","drain-queue",null,"Cross-brief autopilot — claim the oldest ready brief whose Brief NNN deps are satisfied via atomic push, run \u002Fautobuild on each, stop when the queue is empty, blocked, or hits a failure.","launchpathventures\u002Fditto-os","launchpathventures","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F248658966?v=4","01M6ENF40K8DMPD2Q4YBJX3EWK","01M6ENF4541FAB13MQFNS8RMK8",1,"AGPL-3.0","https:\u002F\u002Fgithub.com\u002Flaunchpathventures\u002Fditto-os\u002Fblob\u002Fmain\u002F.catalyst\u002Fskills\u002Fdrain-queue\u002FSKILL.md",[],[18,19,20,21,22,23,24,25,26,27,28,29,30,31],"queue","drain queue","run","push","brief","deps","ready","stop","max","claim","empty","autopilot","via","autobuild","2026-11-10 10:12:30",false,"---\nname: drain-queue\ndescription: Cross-brief autopilot — claim the oldest ready brief whose Brief NNN deps are satisfied via atomic push, run \u002Fautobuild on each, stop when the queue is empty, blocked, or hits a failure.\nargument-hint: \"[max-briefs | all]\"\ndisable-model-invocation: true\n---\n\n## Why This Skill Exists\n\n`\u002Fdev-pm` triages and `\u002Fdev-architect` designs, but dispatching each `**Status:** ready` brief through `\u002Fdev-builder` → `\u002Fdev-reviewer` → `\u002Fdev-review` → PR open → status flip is mechanical work. `\u002Fdrain-queue` treats `docs\u002Fbriefs\u002F*.md` files marked `**Status:** ready` as a self-draining queue. One brief at a time, on its own feature branch, each ending in an open PR. The queue stops on first failure so problems don't cascade.\n\nThis is the **cross-brief autopilot**. It composes `\u002Fautobuild` (within-brief autopilot) in a loop.\n\n**Safe to run in parallel across Conductor workspaces** — see Concurrency below.\n\nCompanion brief: `docs\u002Fbriefs\u002F188-cross-brief-autopilot.md`. Doctrine: `docs\u002Fadrs\u002F035-brief-state-doctrine.md`.\n\n## Repo Context\n\n- Read `@CLAUDE.md` — Ditto conventions, especially §How Work Gets Done and §Critical separation\n- Read `@docs\u002Fdev-process.md` §Autopilot — the canonical guide to when to use this vs invoking roles directly\n- Read `@docs\u002Fstate.md` — current state, blockers, in-flight briefs\n- Read `@AGENTS.md` — repo conventions\n\n## Base Branch\n\nThe integration branch is **`main`**. All of the following reference that branch:\n\n- Claims are pushed to `origin\u002Fmain`\n- Feature branches are created from `origin\u002Fmain`\n- PRs target `main`\n\n**The base branch is never checked out by this skill.** Conductor workspaces are git worktrees, and a worktree cannot check out a branch that another worktree already has — so requiring a base-branch checkout would break parallel execution. All operations against base happen via `origin\u002Fmain` (a fetched ref) and `git push origin \u003Clocal>:main` (push to remote ref by name).\n\n## Brief State Model (load-bearing)\n\nBrief state lives in **markdown bold-prefix lines**, NOT YAML frontmatter. Ditto briefs have no `---` delimiters. The state line looks like `**Status:** ready` (or `draft | in_progress | complete`). Parse via line-prefix regex (e.g. `grep -E '^\\*\\*Status:\\*\\*\\s+(\\w+)'`), not via a YAML library. A YAML parser will return zero matches and the queue will appear permanently empty.\n\nThe atomic claim is a bold-line edit: `**Status:** ready` → `**Status:** in_progress`, committed and pushed to `origin\u002Fmain`. Git's non-fast-forward push rejection is the mutex.\n\n## Arguments\n\n- No arg or `1` → drain exactly one brief\n- `N` (positive integer) → drain up to N briefs\n- `all` → drain until queue is empty or something fails\n\nDefault is `1`. Higher values require explicit intent.\n\n## Pre-conditions\n\nAll must hold before draining starts:\n\n1. Working tree clean (`git status --porcelain` empty)\n2. `git fetch origin main` succeeds (remote is reachable)\n3. At least one `docs\u002Fbriefs\u002FNNN-*.md` exists on `origin\u002Fmain` with `**Status:** ready` (check via `git ls-tree origin\u002Fmain docs\u002Fbriefs\u002F` then `git show origin\u002Fmain:docs\u002Fbriefs\u002F\u003Cfile>` filtered by Status line — NOT the local working tree, which may be on an unrelated branch)\n4. `gh auth status` is logged in with at least `repo` scope\n5. `pnpm install` is current (if unsure, run `pnpm install`)\n\nIf any fails, report and exit. Never attempt to repair pre-conditions autonomously.\n\n**Starting branch doesn't matter.** This skill never checks out `main`. It creates its own throwaway claim branch from `origin\u002Fmain` for each iteration.\n\n## Execution — Per-iteration loop\n\nRepeat up to the max-briefs limit.\n\n### A. Refresh + populate PR maps + GC pass\n\n1. `git fetch origin main` — if fetch fails, stop (remote unreachable or auth broken)\n2. Single `gh pr list --state all --json number,state,title,body,mergedAt --limit 200` call — parse the result and populate two in-memory maps for this iteration:\n   - **openMap**: `{slug → {url, number}}` for PRs in state `OPEN`, where `slug` is extracted from the PR body via regex `brief:(\\d+-[a-z0-9-]+)` (the token autobuild step 8 inserts)\n   - **mergedMap**: `{slug → {url, number, mergedAt}}` for PRs in state `MERGED`\n   - PRs in state `CLOSED` (not merged) and PRs without a `brief:NNN-\u003Cslug>` token are ignored\n3. **GC pass.** List briefs on `origin\u002Fmain` with `**Status:** in_progress` (via `git ls-tree origin\u002Fmain docs\u002Fbriefs\u002F` + `git show` on each + grep). Sort by the merge timestamp of their corresponding mergedMap entry (oldest first; no entry → sort last). Process up to **10 briefs** per iteration; remainder waits for the next iteration. For each brief in the processed batch:\n   - **Slug found in mergedMap**: atomic flip — `git checkout -B claim-tmp origin\u002Fmain`, edit the brief file in place changing `**Status:** in_progress` → `**Status:** complete` (a single sed or text edit), `git commit -am \"chore(brief): mark \u003Cslug> complete (PR #N merged)\"`, `git push origin claim-tmp:main`. On non-fast-forward rejection: silently retry on the next iteration (race-loss). The `**PR:** \u003Curl>` line on the brief file (added by autobuild step 9 to the feature branch and arrived on `origin\u002Fmain` via the merge) is left in place as informational history.\n   - **Slug found in openMap**: do nothing (build is in progress somewhere; let it finish)\n   - **Slug not found in either map**: log a warning (\"brief X is `Status: in_progress` but no matching PR found — orphan; manual cleanup needed\"); do NOT flip\n4. If `gh pr list` failed: retry once with a 2-second backoff. If still failing, skip the GC pass for this iteration (do NOT flip anything), log a warning, continue to step B.\n\nNo checkout of `main`, no pull. All reads from `origin\u002Fmain` directly.\n\n### B. Claim the next brief via atomic push (THE MUTEX)\n\nThis is the critical step. The push to the shared base branch is a distributed compare-and-swap: only one workspace can successfully push a given claim.\n\n1. Create a fresh throwaway claim branch from the just-fetched base:\n   - `git checkout -B claim-tmp origin\u002Fmain`\n   - `-B` (capital) resets the branch if it already exists from a prior iteration — this is the only legitimate \"discard local state\" operation in the skill, and it only ever discards a previous failed claim attempt or a previous GC commit\n\n2. List candidate briefs on base — `git ls-tree origin\u002Fmain docs\u002Fbriefs\u002F` → for each `NNN-*.md` file, `git show origin\u002Fmain:docs\u002Fbriefs\u002F\u003Cfile>` and grep `^\\*\\*Status:\\*\\*\\s+(\\w+)` (use **first match only** — briefs may legitimately embed `**Status:**` strings inside HEREDOCs or example blocks, but the canonical state line is always the first occurrence at the top of the file under the `**Date:**` line) → keep those returning `ready`. Sort by filename (oldest numeric prefix first — `001-` before `002-` before `100-`). If empty, stop — **queue empty**.\n\n3. **Pick the first eligible brief.** Iterate the sorted list and pick the oldest brief whose `Brief NNN` deps are all satisfied. For each candidate:\n   - Read its `**Depends on:**` line (single bold-line, may span continuation; treat the line as the prose immediately after the bold prefix)\n   - Extract dependencies via regex `\\bBrief\\s+(\\d+)\\b` (case-insensitive). ADRs (`ADR-NNN`), phases (`Phase 14 ...`), infrastructure references (`credentials table`), and parenthetical descriptions are **informational and not enforced** — ignored. The human gates non-brief blockers via the `Status: ready` flip.\n   - For each extracted `Brief NNN`, **first compute the dependency's full slug** by listing `docs\u002Fbriefs\u002FNNN-*.md` on `origin\u002Fmain` (`git ls-tree origin\u002Fmain docs\u002Fbriefs\u002F | grep -E \"^[^\t]*\tdocs\u002Fbriefs\u002FNNN-\"`); the (single) match's filename without the `.md` extension is the dependency's slug (e.g. `092-credentials-table`). If zero matches → case (a) below. If multiple matches → ambiguous; log a warning and treat as unsatisfied for safety.\n   - Then check satisfaction. The blocker is **satisfied** iff one of:\n     - (a) no file `docs\u002Fbriefs\u002FNNN-*.md` exists on `origin\u002Fmain`, OR\n     - (b) the file has `**Status:** complete`, OR\n     - (c) the file has `**Status:** in_progress` AND the slug is in this iteration's `openMap` (someone is actively building it; downstream can proceed because that PR will eventually merge), OR\n     - (d) the file has `**Status:** in_progress` AND the slug is in `mergedMap` (race window between merge and GC)\n   - Otherwise the blocker is **unsatisfied** → skip this candidate, try the next\n   - The first brief with all blockers satisfied is the claim target. Call its full slug `\u003Cslug>` (e.g. `188-cross-brief-autopilot`).\n   - If no brief in the list is eligible, stop — **queue blocked**. Report which briefs are waiting on which unsatisfied blockers so the human can unblock or re-prioritise.\n\n4. **Belt-and-braces:** check the iteration's `openMap` for `\u003Cslug>` → if a PR already exists (somehow), skip and continue iterating from step 3.\n\n5. Make the claim commit on `claim-tmp`:\n   - In-place edit the brief file: change the line `^\\*\\*Status:\\*\\* ready$` to `**Status:** in_progress`\n   - `git add docs\u002Fbriefs\u002F\u003Cslug>.md`\n   - `git commit -m \"chore(brief): claim \u003Cslug>\"`\n\n6. `git push origin claim-tmp:main` — pushes the local `claim-tmp` branch to update remote `main`. Git's non-fast-forward check is what makes this atomic.\n   - **Push accepted** → you own this brief. Proceed to step C.\n   - **Push rejected** (non-fast-forward) → another workspace won the race. Recover: go back to step A. The race-loss recovery is automatic — the next iteration's `git fetch` + `git checkout -B claim-tmp origin\u002Fmain` rebuilds the claim branch on top of whatever the winner pushed, the GC + PR-map step re-runs (catches any new merges), and step 3's eligibility check re-runs (so blocker shifts are re-evaluated).\n   - **More than 5 consecutive lost races** → stop and report. Something is wrong (too many workers, or queue is nearly empty).\n\n### C. Rename the claim branch to the feature branch\n\nThe claim is now committed on `claim-tmp` and pushed to base. Rename in place — no new checkout needed.\n\n- `git branch -m claim-tmp feature\u002F\u003Cslug>`\n- The branch already has the `**Status:** in_progress` flip committed and is based on the updated base — `\u002Fautobuild` runs from this branch\n\n### D. Run the within-brief autopilot\n\n- Invoke the `\u002Fautobuild` skill\n- `\u002Fautobuild` handles: pre-flight hard-stops → `\u002Fdev-builder` → fresh-subagent `\u002Fdev-reviewer` + `\u002Fdev-review` → fix P0\u002FP1 → commit + push feature branch → open PR → add `**PR:** \u003Curl>` line to the feature branch → report\n\n### E. Handle result\n\n- **Success:** PR is open. Feature branch contains the implementation + the `**PR:** \u003Curl>` line on the brief file. Proceed to step F before continuing the loop.\n- **Failure:** `\u002Fautobuild` stopped. Brief is at `**Status:** in_progress` on `origin\u002Fmain` (claim already happened in step B). Do NOT continue the queue and do NOT run step F. Report the failure including the feature branch name so a human can recover.\n- **Pre-flight hard-stop** (drizzle journal or DB migration in §What Changes): same as failure — brief stays `in_progress`, queue stops, report.\n\n### F. Final-pass `\u002Fdev-review --fix` (mandatory on success, up to 3 recursions)\n\n`\u002Fautobuild`'s step 5 runs `\u002Fdev-review` as a pre-PR gate via fresh subagent, fixing P0\u002FP1 findings — but P2\u002FP3 may accumulate. This step closes that loop: run `\u002Fdev-review --fix` recursively until the branch is clean, or escalate to human review after 3 passes.\n\nWhy recursion: a single `--fix` pass can introduce new findings as a side-effect of the fix, or leave residual P2\u002FP3 issues that need another pass to surface once the top-level noise is cleared. Three passes is almost always enough; more usually means architectural and needs a human.\n\nStill on the just-shipped feature branch:\n\n1. Set `attempt = 1`, `max_attempts = 3`. Track the finding set across attempts to detect non-convergence.\n2. **Loop:**\n   a. Invoke `\u002Fdev-review --fix` against the branch's diff vs `origin\u002Fmain` (Ditto uses `main` as the integration branch — different from the Catalyst-default base; the patched `\u002Fdev-review` skill already targets `origin\u002Fmain`)\n   b. Re-run **the full `\u002Fdev-builder` verify list per `.claude\u002Fcommands\u002Fdev-builder.md` lines 81-86** (type-check + `pnpm test` + `pnpm test:e2e` + `pnpm test:e2e:auto`). Re-running only type-check would silently weaken the contract — fixes that break runtime behavior would slip through. Lint is omitted (this repo has no lint script). If any verify step regresses and `\u002Fdev-review --fix` can't resolve it in this same pass, stop the drain — treat as a failure per the failure branch of step E.\n   c. If `\u002Fdev-review --fix` made changes:\n      - Stage only the files it touched\n      - Commit: `chore(review): apply \u002Fdev-review --fix findings (pass \u003Cattempt>)`\n      - Push to the same feature branch so the open PR updates\n   d. Re-invoke `\u002Fdev-review` (report-only, no `--fix`) to check residual findings\n      - **Clean (no findings):** exit the loop\n      - **Only unfixable findings remain** (ambiguous, architectural, out-of-scope): exit the loop and go to step 3\n      - **Fixable findings remain AND `attempt \u003C max_attempts`:** increment `attempt`, go to 2a\n      - **Fixable findings remain AND `attempt == max_attempts`:** exit the loop, go to step 4 (human escalation)\n   e. **Non-convergence guard:** if the exact same finding set appears in two consecutive passes with no reduction, treat as non-convergent — go to step 4 even if attempts remain\n3. If unfixable findings remain after a clean convergence, post them as a single comment on the PR via `gh pr comment \u003Curl> --body \"...\"` so the human reviewer sees them. Continue the drain loop normally.\n4. **Human escalation** (max attempts reached or non-convergent):\n   - Do NOT continue the drain\n   - Post a PR comment listing unresolved findings, number of passes attempted, and whether the failure mode was \"didn't converge\" or \"capped at 3 passes with findings still present\"\n   - Add a note to the brief file (still at `**Status:** in_progress`) under a `## Drain-queue escalation` section\n   - Report to the user in the final drain output. Soft stop — not a failure that corrupts state, but enough of a signal that a human should intervene before more briefs pile on top.\n\nOnly after step F exits cleanly (step 2d \"Clean\" or step 3 \"unfixable only\") does the loop continue to the next brief. Step 4 stops the drain.\n\nThe skill never returns to or checks out `main` — it stays on the most recent feature branch when the loop ends.\n\n### Stop conditions\n\n- Queue empty (no `**Status:** ready` briefs on base)\n- Queue blocked (every remaining ready brief has at least one unsatisfied `Brief NNN` dep)\n- `max-briefs` reached\n- Any `\u002Fautobuild` invocation fails (including pre-flight hard-stops)\n- Step F `\u002Fdev-review --fix` introduces unresolvable type-check regressions\n- Step F escalates to human review (3 passes without convergence, or non-convergent finding set)\n- More than 5 consecutive lost claim races\n- Any pre-condition breaks mid-loop\n\n## Concurrency — Running Multiple Workspaces in Parallel\n\nSafe. This is the headline feature of the atomic-push claim, and the no-checkout design is what makes it work across Conductor's worktree model.\n\n- N Conductor workspaces each running `\u002Fdrain-queue` will each build a `claim-tmp` from `origin\u002Fmain` and try to push it back to base\n- Git's non-fast-forward rejection ensures exactly one winner per brief\n- Losers loop back to step A, fetch the winner's claim, rebuild `claim-tmp`, and pick the next brief — no `reset --hard` needed because the loser was never on a shared branch\n- Each workspace stays on its own branch the whole time, so worktrees never compete for the same checkout\n- The single `gh pr list` call per iteration is one rate-limit token per iteration per workspace — comfortable within GitHub's 5000\u002Fhour limit even at N=8 workspaces\n- Expected throughput: near-linear in N, limited by CI concurrency, GH PR API rate limit, and claim-race retries\n\n**Known limitation: crash recovery.** If a workspace pushes a claim but crashes before opening a PR, the brief is stuck at `**Status:** in_progress` on `origin\u002Fmain` with no owner. The GC pass will catch this on the next iteration (slug not in either PR map → \"orphan\" warning logged). Manual recovery: human edits the brief back to `**Status:** ready` (or `complete` \u002F `draft` as appropriate) via a PR.\n\n## Cost & throughput\n\nA single `\u002Fautobuild` run has substantial wall-clock and LLM-token cost: `\u002Fdev-builder` (multiple LLM turns + `pnpm test:e2e` Playwright run + `pnpm test:e2e:auto`) + fresh-subagent `\u002Fdev-reviewer` + fresh-subagent `\u002Fdev-review` + up to 3 `\u002Fdev-review --fix` recursions. Empirical estimate: **30–60 minutes wall-clock per brief**; LLM token cost on the order of $5–$30 per brief depending on complexity.\n\n`\u002Fdrain-queue all` against a 50-brief queue therefore commits to **25–50 compute-hours** plus **$250–$1500 in LLM spend**, plus ~50 PRs requiring human merge review. Recommend starting with `\u002Fdrain-queue 1` for the first session and only escalating to `\u002Fdrain-queue all` once trust and rate-limit headroom are confirmed.\n\n## Guardrails\n\n- **Never check out `main`.** It would block other workspaces from running this skill. Use `origin\u002Fmain` (fetched ref) for reads and `git push origin \u003Clocal>:main` for writes.\n- **Never merge PRs.** `\u002Fautobuild` enforces this. Merge is the human taste gate.\n- **Never auto-promote `Status: draft` → `Status: ready`.** That's `\u002Fdev-pm`'s job (and ultimately a human's). `\u002Fdrain-queue` only operates on briefs already marked `ready`.\n- **Never edit briefs other than `**Status:**` and the GC pass's `complete` flip.** Step C edits exactly one line. The GC pass edits exactly one line. No other brief mutations from this skill.\n- **No `--force`, `--no-verify`, or `reset --hard` anywhere in this skill.** Race-loss recovery is handled by `git checkout -B claim-tmp origin\u002Fmain`, which discards only the prior claim attempt or GC commit.\n- **Stop on first real failure** (as opposed to race-loss, which is recoverable). Broken builds in one brief can mask real failures in the next.\n- **Cap your run** — default 1. `all` and `N>1` are explicit opt-ins.\n- **Step F `\u002Fdev-review --fix` stays scoped to the feature branch's diff** (`git diff origin\u002Fmain`). It must not touch files unrelated to the brief. If `\u002Fdev-review` flags issues outside the diff, surface them in the final report — don't fix them.\n- **Trust boundary:** `**Status:** ready` IS the trust boundary for autonomous build. Anything marked ready will be implemented and PR-opened by this skill. Pre-flight hard-stops (in `\u002Fautobuild` step 2) cover DB-related risk only; everything else (`package.json` deps, `.github\u002Fworkflows\u002F`, `.env`, configs) relies on the `Status: ready` human gate. See `docs\u002Fadrs\u002F035-brief-state-doctrine.md`.\n\n## After draining\n\nReport to user:\n- How many briefs successfully shipped (PR open)\n- Open PR URLs\n- Per brief: step F outcome — number of `--fix` passes (1–3), what each pass fixed (one-line summary), final state (clean \u002F unfixable-only \u002F escalated)\n- Any brief where step F hit the 3-pass cap or a non-convergent finding set — name the brief, the PR, and the unresolved findings\n- Any brief that stopped the drain and why (build failure, pre-flight hard-stop, etc.)\n- Any orphan warnings from the GC pass (briefs `in_progress` with no matching PR)\n- How many `**Status:** ready` briefs remain on `origin\u002Fmain`, and how many are currently blocked by unsatisfied `Brief NNN` deps (name the blockers)\n- How many lost claim races occurred (high numbers suggest too many parallel workers)\n\nSuggest the user review the PRs. The merge decision is theirs.\n","## Why This Skill Exists\n\n`\u002Fdev-pm` triages and `\u002Fdev-architect` designs, but dispatching each `**Status:** ready` brief through `\u002Fdev-builder` → `\u002Fdev-reviewer` → `\u002Fdev-review` → PR open → status flip is mechanical work. `\u002Fdrain-queue` treats `docs\u002Fbriefs\u002F*.md` files marked `**Status:** ready` as a self-draining queue. One brief at a time, on its own feature branch, each ending in an open PR. The queue stops on first failure so problems don't cascade.\n\nThis is the **cross-brief autopilot**. It composes `\u002Fautobuild` (within-brief autopilot) in a loop.\n\n**Safe to run in parallel across Conductor workspaces** — see Concurrency below.\n\nCompanion brief: `docs\u002Fbriefs\u002F188-cross-brief-autopilot.md`. Doctrine: `docs\u002Fadrs\u002F035-brief-state-doctrine.md`.\n\n## Repo Context\n\n- Read `@CLAUDE.md` — Ditto conventions, especially §How Work Gets Done and §Critical separation\n- Read `@docs\u002Fdev-process.md` §Autopilot — the canonical guide to when to use this vs invoking roles directly\n- Read `@docs\u002Fstate.md` — current state, blockers, in-flight briefs\n- Read `@AGENTS.md` — repo conventions\n\n## Base Branch\n\nThe integration branch is **`main`**. All of the following reference that branch:\n\n- Claims are pushed to `origin\u002Fmain`\n- Feature branches are created from `origin\u002Fmain`\n- PRs target `main`\n\n**The base branch is never checked out by this skill.** Conductor workspaces are git worktrees, and a worktree cannot check out a branch that another worktree already has — so requiring a base-branch checkout would break parallel execution. All operations against base happen via `origin\u002Fmain` (a fetched ref) and `git push origin \u003Clocal>:main` (push to remote ref by name).\n\n## Brief State Model (load-bearing)\n\nBrief state lives in **markdown bold-prefix lines**, NOT YAML frontmatter. Ditto briefs have no `---` delimiters. The state line looks like `**Status:** ready` (or `draft | in_progress | complete`). Parse via line-prefix regex (e.g. `grep -E '^\\*\\*Status:\\*\\*\\s+(\\w+)'`), not via a YAML library. A YAML parser will return zero matches and the queue will appear permanently empty.\n\nThe atomic claim is a bold-line edit: `**Status:** ready` → `**Status:** in_progress`, committed and pushed to `origin\u002Fmain`. Git's non-fast-forward push rejection is the mutex.\n\n## Arguments\n\n- No arg or `1` → drain exactly one brief\n- `N` (positive integer) → drain up to N briefs\n- `all` → drain until queue is empty or something fails\n\nDefault is `1`. Higher values require explicit intent.\n\n## Pre-conditions\n\nAll must hold before draining starts:\n\n1. Working tree clean (`git status --porcelain` empty)\n2. `git fetch origin main` succeeds (remote is reachable)\n3. At least one `docs\u002Fbriefs\u002FNNN-*.md` exists on `origin\u002Fmain` with `**Status:** ready` (check via `git ls-tree origin\u002Fmain docs\u002Fbriefs\u002F` then `git show origin\u002Fmain:docs\u002Fbriefs\u002F\u003Cfile>` filtered by Status line — NOT the local working tree, which may be on an unrelated branch)\n4. `gh auth status` is logged in with at least `repo` scope\n5. `pnpm install` is current (if unsure, run `pnpm install`)\n\nIf any fails, report and exit. Never attempt to repair pre-conditions autonomously.\n\n**Starting branch doesn't matter.** This skill never checks out `main`. It creates its own throwaway claim branch from `origin\u002Fmain` for each iteration.\n\n## Execution — Per-iteration loop\n\nRepeat up to the max-briefs limit.\n\n### A. Refresh + populate PR maps + GC pass\n\n1. `git fetch origin main` — if fetch fails, stop (remote unreachable or auth broken)\n2. Single `gh pr list --state all --json number,state,title,body,mergedAt --limit 200` call — parse the result and populate two in-memory maps for this iteration:\n   - **openMap**: `{slug → {url, number}}` for PRs in state `OPEN`, where `slug` is extracted from the PR body via regex `brief:(\\d+-[a-z0-9-]+)` (the token autobuild step 8 inserts)\n   - **mergedMap**: `{slug → {url, number, mergedAt}}` for PRs in state `MERGED`\n   - PRs in state `CLOSED` (not merged) and PRs without a `brief:NNN-\u003Cslug>` token are ignored\n3. **GC pass.** List briefs on `origin\u002Fmain` with `**Status:** in_progress` (via `git ls-tree origin\u002Fmain docs\u002Fbriefs\u002F` + `git show` on each + grep). Sort by the merge timestamp of their corresponding mergedMap entry (oldest first; no entry → sort last). Process up to **10 briefs** per iteration; remainder waits for the next iteration. For each brief in the processed batch:\n   - **Slug found in mergedMap**: atomic flip — `git checkout -B claim-tmp origin\u002Fmain`, edit the brief file in place changing `**Status:** in_progress` → `**Status:** complete` (a single sed or text edit), `git commit -am \"chore(brief): mark \u003Cslug> complete (PR #N merged)\"`, `git push origin claim-tmp:main`. On non-fast-forward rejection: silently retry on the next iteration (race-loss). The `**PR:** \u003Curl>` line on the brief file (added by autobuild step 9 to the feature branch and arrived on `origin\u002Fmain` via the merge) is left in place as informational history.\n   - **Slug found in openMap**: do nothing (build is in progress somewhere; let it finish)\n   - **Slug not found in either map**: log a warning (\"brief X is `Status: in_progress` but no matching PR found — orphan; manual cleanup needed\"); do NOT flip\n4. If `gh pr list` failed: retry once with a 2-second backoff. If still failing, skip the GC pass for this iteration (do NOT flip anything), log a warning, continue to step B.\n\nNo checkout of `main`, no pull. All reads from `origin\u002Fmain` directly.\n\n### B. Claim the next brief via atomic push (THE MUTEX)\n\nThis is the critical step. The push to the shared base branch is a distributed compare-and-swap: only one workspace can successfully push a given claim.\n\n1. Create a fresh throwaway claim branch from the just-fetched base:\n   - `git checkout -B claim-tmp origin\u002Fmain`\n   - `-B` (capital) resets the branch if it already exists from a prior iteration — this is the only legitimate \"discard local state\" operation in the skill, and it only ever discards a previous failed claim attempt or a previous GC commit\n\n2. List candidate briefs on base — `git ls-tree origin\u002Fmain docs\u002Fbriefs\u002F` → for each `NNN-*.md` file, `git show origin\u002Fmain:docs\u002Fbriefs\u002F\u003Cfile>` and grep `^\\*\\*Status:\\*\\*\\s+(\\w+)` (use **first match only** — briefs may legitimately embed `**Status:**` strings inside HEREDOCs or example blocks, but the canonical state line is always the first occurrence at the top of the file under the `**Date:**` line) → keep those returning `ready`. Sort by filename (oldest numeric prefix first — `001-` before `002-` before `100-`). If empty, stop — **queue empty**.\n\n3. **Pick the first eligible brief.** Iterate the sorted list and pick the oldest brief whose `Brief NNN` deps are all satisfied. For each candidate:\n   - Read its `**Depends on:**` line (single bold-line, may span continuation; treat the line as the prose immediately after the bold prefix)\n   - Extract dependencies via regex `\\bBrief\\s+(\\d+)\\b` (case-insensitive). ADRs (`ADR-NNN`), phases (`Phase 14 ...`), infrastructure references (`credentials table`), and parenthetical descriptions are **informational and not enforced** — ignored. The human gates non-brief blockers via the `Status: ready` flip.\n   - For each extracted `Brief NNN`, **first compute the dependency's full slug** by listing `docs\u002Fbriefs\u002FNNN-*.md` on `origin\u002Fmain` (`git ls-tree origin\u002Fmain docs\u002Fbriefs\u002F | grep -E \"^[^\t]*\tdocs\u002Fbriefs\u002FNNN-\"`); the (single) match's filename without the `.md` extension is the dependency's slug (e.g. `092-credentials-table`). If zero matches → case (a) below. If multiple matches → ambiguous; log a warning and treat as unsatisfied for safety.\n   - Then check satisfaction. The blocker is **satisfied** iff one of:\n     - (a) no file `docs\u002Fbriefs\u002FNNN-*.md` exists on `origin\u002Fmain`, OR\n     - (b) the file has `**Status:** complete`, OR\n     - (c) the file has `**Status:** in_progress` AND the slug is in this iteration's `openMap` (someone is actively building it; downstream can proceed because that PR will eventually merge), OR\n     - (d) the file has `**Status:** in_progress` AND the slug is in `mergedMap` (race window between merge and GC)\n   - Otherwise the blocker is **unsatisfied** → skip this candidate, try the next\n   - The first brief with all blockers satisfied is the claim target. Call its full slug `\u003Cslug>` (e.g. `188-cross-brief-autopilot`).\n   - If no brief in the list is eligible, stop — **queue blocked**. Report which briefs are waiting on which unsatisfied blockers so the human can unblock or re-prioritise.\n\n4. **Belt-and-braces:** check the iteration's `openMap` for `\u003Cslug>` → if a PR already exists (somehow), skip and continue iterating from step 3.\n\n5. Make the claim commit on `claim-tmp`:\n   - In-place edit the brief file: change the line `^\\*\\*Status:\\*\\* ready$` to `**Status:** in_progress`\n   - `git add docs\u002Fbriefs\u002F\u003Cslug>.md`\n   - `git commit -m \"chore(brief): claim \u003Cslug>\"`\n\n6. `git push origin claim-tmp:main` — pushes the local `claim-tmp` branch to update remote `main`. Git's non-fast-forward check is what makes this atomic.\n   - **Push accepted** → you own this brief. Proceed to step C.\n   - **Push rejected** (non-fast-forward) → another workspace won the race. Recover: go back to step A. The race-loss recovery is automatic — the next iteration's `git fetch` + `git checkout -B claim-tmp origin\u002Fmain` rebuilds the claim branch on top of whatever the winner pushed, the GC + PR-map step re-runs (catches any new merges), and step 3's eligibility check re-runs (so blocker shifts are re-evaluated).\n   - **More than 5 consecutive lost races** → stop and report. Something is wrong (too many workers, or queue is nearly empty).\n\n### C. Rename the claim branch to the feature branch\n\nThe claim is now committed on `claim-tmp` and pushed to base. Rename in place — no new checkout needed.\n\n- `git branch -m claim-tmp feature\u002F\u003Cslug>`\n- The branch already has the `**Status:** in_progress` flip committed and is based on the updated base — `\u002Fautobuild` runs from this branch\n\n### D. Run the within-brief autopilot\n\n- Invoke the `\u002Fautobuild` skill\n- `\u002Fautobuild` handles: pre-flight hard-stops → `\u002Fdev-builder` → fresh-subagent `\u002Fdev-reviewer` + `\u002Fdev-review` → fix P0\u002FP1 → commit + push feature branch → open PR → add `**PR:** \u003Curl>` line to the feature branch → report\n\n### E. Handle result\n\n- **Success:** PR is open. Feature branch contains the implementation + the `**PR:** \u003Curl>` line on the brief file. Proceed to step F before continuing the loop.\n- **Failure:** `\u002Fautobuild` stopped. Brief is at `**Status:** in_progress` on `origin\u002Fmain` (claim already happened in step B). Do NOT continue the queue and do NOT run step F. Report the failure including the feature branch name so a human can recover.\n- **Pre-flight hard-stop** (drizzle journal or DB migration in §What Changes): same as failure — brief stays `in_progress`, queue stops, report.\n\n### F. Final-pass `\u002Fdev-review --fix` (mandatory on success, up to 3 recursions)\n\n`\u002Fautobuild`'s step 5 runs `\u002Fdev-review` as a pre-PR gate via fresh subagent, fixing P0\u002FP1 findings — but P2\u002FP3 may accumulate. This step closes that loop: run `\u002Fdev-review --fix` recursively until the branch is clean, or escalate to human review after 3 passes.\n\nWhy recursion: a single `--fix` pass can introduce new findings as a side-effect of the fix, or leave residual P2\u002FP3 issues that need another pass to surface once the top-level noise is cleared. Three passes is almost always enough; more usually means architectural and needs a human.\n\nStill on the just-shipped feature branch:\n\n1. Set `attempt = 1`, `max_attempts = 3`. Track the finding set across attempts to detect non-convergence.\n2. **Loop:**\n   a. Invoke `\u002Fdev-review --fix` against the branch's diff vs `origin\u002Fmain` (Ditto uses `main` as the integration branch — different from the Catalyst-default base; the patched `\u002Fdev-review` skill already targets `origin\u002Fmain`)\n   b. Re-run **the full `\u002Fdev-builder` verify list per `.claude\u002Fcommands\u002Fdev-builder.md` lines 81-86** (type-check + `pnpm test` + `pnpm test:e2e` + `pnpm test:e2e:auto`). Re-running only type-check would silently weaken the contract — fixes that break runtime behavior would slip through. Lint is omitted (this repo has no lint script). If any verify step regresses and `\u002Fdev-review --fix` can't resolve it in this same pass, stop the drain — treat as a failure per the failure branch of step E.\n   c. If `\u002Fdev-review --fix` made changes:\n      - Stage only the files it touched\n      - Commit: `chore(review): apply \u002Fdev-review --fix findings (pass \u003Cattempt>)`\n      - Push to the same feature branch so the open PR updates\n   d. Re-invoke `\u002Fdev-review` (report-only, no `--fix`) to check residual findings\n      - **Clean (no findings):** exit the loop\n      - **Only unfixable findings remain** (ambiguous, architectural, out-of-scope): exit the loop and go to step 3\n      - **Fixable findings remain AND `attempt \u003C max_attempts`:** increment `attempt`, go to 2a\n      - **Fixable findings remain AND `attempt == max_attempts`:** exit the loop, go to step 4 (human escalation)\n   e. **Non-convergence guard:** if the exact same finding set appears in two consecutive passes with no reduction, treat as non-convergent — go to step 4 even if attempts remain\n3. If unfixable findings remain after a clean convergence, post them as a single comment on the PR via `gh pr comment \u003Curl> --body \"...\"` so the human reviewer sees them. Continue the drain loop normally.\n4. **Human escalation** (max attempts reached or non-convergent):\n   - Do NOT continue the drain\n   - Post a PR comment listing unresolved findings, number of passes attempted, and whether the failure mode was \"didn't converge\" or \"capped at 3 passes with findings still present\"\n   - Add a note to the brief file (still at `**Status:** in_progress`) under a `## Drain-queue escalation` section\n   - Report to the user in the final drain output. Soft stop — not a failure that corrupts state, but enough of a signal that a human should intervene before more briefs pile on top.\n\nOnly after step F exits cleanly (step 2d \"Clean\" or step 3 \"unfixable only\") does the loop continue to the next brief. Step 4 stops the drain.\n\nThe skill never returns to or checks out `main` — it stays on the most recent feature branch when the loop ends.\n\n### Stop conditions\n\n- Queue empty (no `**Status:** ready` briefs on base)\n- Queue blocked (every remaining ready brief has at least one unsatisfied `Brief NNN` dep)\n- `max-briefs` reached\n- Any `\u002Fautobuild` invocation fails (including pre-flight hard-stops)\n- Step F `\u002Fdev-review --fix` introduces unresolvable type-check regressions\n- Step F escalates to human review (3 passes without convergence, or non-convergent finding set)\n- More than 5 consecutive lost claim races\n- Any pre-condition breaks mid-loop\n\n## Concurrency — Running Multiple Workspaces in Parallel\n\nSafe. This is the headline feature of the atomic-push claim, and the no-checkout design is what makes it work across Conductor's worktree model.\n\n- N Conductor workspaces each running `\u002Fdrain-queue` will each build a `claim-tmp` from `origin\u002Fmain` and try to push it back to base\n- Git's non-fast-forward rejection ensures exactly one winner per brief\n- Losers loop back to step A, fetch the winner's claim, rebuild `claim-tmp`, and pick the next brief — no `reset --hard` needed because the loser was never on a shared branch\n- Each workspace stays on its own branch the whole time, so worktrees never compete for the same checkout\n- The single `gh pr list` call per iteration is one rate-limit token per iteration per workspace — comfortable within GitHub's 5000\u002Fhour limit even at N=8 workspaces\n- Expected throughput: near-linear in N, limited by CI concurrency, GH PR API rate limit, and claim-race retries\n\n**Known limitation: crash recovery.** If a workspace pushes a claim but crashes before opening a PR, the brief is stuck at `**Status:** in_progress` on `origin\u002Fmain` with no owner. The GC pass will catch this on the next iteration (slug not in either PR map → \"orphan\" warning logged). Manual recovery: human edits the brief back to `**Status:** ready` (or `complete` \u002F `draft` as appropriate) via a PR.\n\n## Cost & throughput\n\nA single `\u002Fautobuild` run has substantial wall-clock and LLM-token cost: `\u002Fdev-builder` (multiple LLM turns + `pnpm test:e2e` Playwright run + `pnpm test:e2e:auto`) + fresh-subagent `\u002Fdev-reviewer` + fresh-subagent `\u002Fdev-review` + up to 3 `\u002Fdev-review --fix` recursions. Empirical estimate: **30–60 minutes wall-clock per brief**; LLM token cost on the order of $5–$30 per brief depending on complexity.\n\n`\u002Fdrain-queue all` against a 50-brief queue therefore commits to **25–50 compute-hours** plus **$250–$1500 in LLM spend**, plus ~50 PRs requiring human merge review. Recommend starting with `\u002Fdrain-queue 1` for the first session and only escalating to `\u002Fdrain-queue all` once trust and rate-limit headroom are confirmed.\n\n## Guardrails\n\n- **Never check out `main`.** It would block other workspaces from running this skill. Use `origin\u002Fmain` (fetched ref) for reads and `git push origin \u003Clocal>:main` for writes.\n- **Never merge PRs.** `\u002Fautobuild` enforces this. Merge is the human taste gate.\n- **Never auto-promote `Status: draft` → `Status: ready`.** That's `\u002Fdev-pm`'s job (and ultimately a human's). `\u002Fdrain-queue` only operates on briefs already marked `ready`.\n- **Never edit briefs other than `**Status:**` and the GC pass's `complete` flip.** Step C edits exactly one line. The GC pass edits exactly one line. No other brief mutations from this skill.\n- **No `--force`, `--no-verify`, or `reset --hard` anywhere in this skill.** Race-loss recovery is handled by `git checkout -B claim-tmp origin\u002Fmain`, which discards only the prior claim attempt or GC commit.\n- **Stop on first real failure** (as opposed to race-loss, which is recoverable). Broken builds in one brief can mask real failures in the next.\n- **Cap your run** — default 1. `all` and `N>1` are explicit opt-ins.\n- **Step F `\u002Fdev-review --fix` stays scoped to the feature branch's diff** (`git diff origin\u002Fmain`). It must not touch files unrelated to the brief. If `\u002Fdev-review` flags issues outside the diff, surface them in the final report — don't fix them.\n- **Trust boundary:** `**Status:** ready` IS the trust boundary for autonomous build. Anything marked ready will be implemented and PR-opened by this skill. Pre-flight hard-stops (in `\u002Fautobuild` step 2) cover DB-related risk only; everything else (`package.json` deps, `.github\u002Fworkflows\u002F`, `.env`, configs) relies on the `Status: ready` human gate. See `docs\u002Fadrs\u002F035-brief-state-doctrine.md`.\n\n## After draining\n\nReport to user:\n- How many briefs successfully shipped (PR open)\n- Open PR URLs\n- Per brief: step F outcome — number of `--fix` passes (1–3), what each pass fixed (one-line summary), final state (clean \u002F unfixable-only \u002F escalated)\n- Any brief where step F hit the 3-pass cap or a non-convergent finding set — name the brief, the PR, and the unresolved findings\n- Any brief that stopped the drain and why (build failure, pre-flight hard-stop, etc.)\n- Any orphan warnings from the GC pass (briefs `in_progress` with no matching PR)\n- How many `**Status:** ready` briefs remain on `origin\u002Fmain`, and how many are currently blocked by unsatisfied `Brief NNN` deps (name the blockers)\n- How many lost claim races occurred (high numbers suggest too many parallel workers)\n\nSuggest the user review the PRs. The merge decision is theirs.\n",{"name":5,"description":7,"argument-hint":37,"disable-model-invocation":38},"[max-briefs | all]",true,"main","b033b1a8919dbb7c98e97cf24547a2416f65b53e",".catalyst\u002Fskills\u002Fdrain-queue",0,"https:\u002F\u002Fgithub.com\u002Flaunchpathventures\u002Fditto-os","https:\u002F\u002Fgithub.com\u002Flaunchpathventures","2026-06-08 19:31:48",{"source":8,"skillName":5,"commands":47,"prompt":57,"zipAvailable":38},[48,51,54],{"tool":49,"command":50},"npx","npx skills add launchpathventures\u002Fditto-os --skill drain-queue",{"tool":52,"command":53},"bunx","bunx skills add launchpathventures\u002Fditto-os --skill drain-queue",{"tool":55,"command":56},"pnpm","pnpm dlx skills add launchpathventures\u002Fditto-os --skill drain-queue","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Flaunchpathventures\u002Fditto-os\u002Fblob\u002Fmain\u002F.catalyst\u002Fskills\u002Fdrain-queue\u002FSKILL.md",[59],{"path":60,"resourceType":61,"resourceTypeDesc":62,"sizeBytes":63,"sourceHtmlUrl":64},"LICENSE.txt","LICENSE","许可证",1078,"https:\u002F\u002Fgithub.com\u002FTorchiaHub\u002FSkills\u002Fblob\u002Fmaster\u002F01-Inbox\u002Fdownloads\u002Fgithub-awesome-copilot\u002F20260429T123413Z\u002Fsource\u002Fskills\u002Fazure-role-selector\u002FLICENSE.txt",[66,71,91,112,117,122],{"skillNo":67,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":68,"categories":69,"keywords":70,"publishedAt":32},"01M6ENJ12VWSMRZ4MW8550AG69","https:\u002F\u002Fgithub.com\u002Flaunchpathventures\u002Fditto-os\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fdrain-queue\u002FSKILL.md",[],[19,18,21,31,30,29,28,27,26,25,24,23,22,20],{"skillNo":72,"name":73,"nameZh":6,"description":74,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":75,"categories":76,"keywords":77,"publishedAt":32},"01M6ENHXG16WJ4PN8CJHZYNT5T","dev-review","Post-coding exhaustive review — catches integration bugs, runtime crashes, performance issues, and convention drift across all changed files","https:\u002F\u002Fgithub.com\u002Flaunchpathventures\u002Fditto-os\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fdev-review\u002FSKILL.md",[],[78,79,80,81,82,83,84,85,86,87,88,89,90],"dev","review","dev review","performance","issues","post","runtime","across","drift","files","fix","coding","integration",{"skillNo":92,"name":31,"nameZh":6,"description":93,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":94,"categories":95,"keywords":96,"publishedAt":32},"01M6ENHSZBZFSB69TSV2TWGRJ1","End-to-end autopilot for a single brief — pre-flight, \u002Fdev-builder, fresh-subagent reviewers, push, open PR, mark **PR:** line on feature branch. Stops at the human merge gate.","https:\u002F\u002Fgithub.com\u002Flaunchpathventures\u002Fditto-os\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fautobuild\u002FSKILL.md",[],[31,97,98,99,29,100,101,102,103,104,105,106,21,107,22,108,78,109,110,111],"human","feature","end","fresh","name","gate","line","builder","branch","subagent","merge gate","open pr","pr","merge","open",{"skillNo":113,"name":73,"nameZh":6,"description":74,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":114,"categories":115,"keywords":116,"publishedAt":32},"01M6ENHM3W1A0MY44ZD8D4NWVF","https:\u002F\u002Fgithub.com\u002Flaunchpathventures\u002Fditto-os\u002Fblob\u002Fmain\u002F.catalyst\u002Fskills\u002Fdev-review\u002FSKILL.md",[],[79,78,80,86,83,84,85,87,88,89,90,82,81],{"skillNo":118,"name":31,"nameZh":6,"description":93,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":119,"categories":120,"keywords":121,"publishedAt":32},"01M6ENHF62C7G6BC4YG44RWFB0","https:\u002F\u002Fgithub.com\u002Flaunchpathventures\u002Fditto-os\u002Fblob\u002Fmain\u002F.catalyst\u002Fskills\u002Fautobuild\u002FSKILL.md",[],[31,108,99,98,97,102,104,105,106,107,111,22,29,21,78,109,110,103,101,100],{"skillNo":123,"name":124,"nameZh":6,"description":125,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":126,"categories":127,"keywords":128,"publishedAt":32},"01M6ENHBWGWPCR07Y9W1CTTMNE","typeset","Improves typography by fixing font choices, hierarchy, sizing, weight, and readability so text feels intentional. Use when the user mentions fonts, type, readability, text hierarchy, sizing looks off, or wants more polished, intentional typography.","https:\u002F\u002Fgithub.com\u002Flaunchpathventures\u002Fditto-os\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Ftypeset\u002FSKILL.md",[],[124,129,130,131,132,133,134],"type","readability","typography","use","user","text"]