fastapi-rest-of-the-owl · diff
git:20260918.4ac7924 to git:20260922.549c04f
32 added, 96 removed. Audit A to A.
---
name: fastapi-rest-of-the-owl
description: Use when the user hands you a task definition and wants the ENTIRE development loop run end-to-end — plan, implement, review and fix, QA the change with evidence appropriate to it, open a humanized PR, then poll CI and code review, fixing and resolving until the PR is green and clean. Does everything except merge. Long-running and autonomous; the human keeps the merge button. Also known as `klaussy-rest-of-the-owl`.
---
+ > **Adapted for Cline.**
+ >
+ > - This skill orchestrates parallel sub-agents using Claude's `Agent` tool / `subagent_type` syntax. Most coding agents now have their own parallel sub-agent or task mechanism (e.g. Cursor's `Task`, Codex's `spawn_agent`, Gemini subagents, Copilot's `task`) — use yours and translate the wording. If it truly has none, apply each lens or angle yourself, sequentially, and combine the findings.
+
## Task
`$ARGUMENTS`
If `$ARGUMENTS` is empty, use the task definition the user pasted into the conversation (a ticket, a design note, a one-line ask). If there is none, stop and ask for one — this skill needs a target.
## The bit
- *How to draw an owl: (1) draw two circles. (2) draw the rest of the owl.* The user just handed you the two circles — a task definition. This skill draws the rest of the owl: the whole lifecycle from "here's what I want" to "here's a green, reviewed PR waiting for your merge." It is a genuine end-to-end run, not a gag — but it earns the name by doing the enormous unglamorous middle the meme skips over.
+ *How to draw an owl: (1) draw two circles. (2) draw the rest of the owl.* The user just handed you the two circles. This skill draws the rest: the whole lifecycle from "here's what I want" to "here's a green, reviewed PR waiting for your merge", including the enormous unglamorous middle the meme skips.
**It does everything except merge.** The merge button stays with the human. Never merge, never force-push over someone else's work, never mark the PR ready-to-merge on the user's behalf.
## How this skill works
- You orchestrate the repo's other skills as a pipeline. Each phase below names the sibling skill whose playbook you follow — open that skill's `SKILL.md` and run its steps, then come back here for the next phase. Track the whole run with TodoWrite: one todo per phase, `in_progress` when you start it, `completed` when it's done. The flow is long and mostly unattended; the todo list is how the user follows along.
-
- Stop and hand back to the user (do not barrel ahead) if any phase hits something a human must decide: a missing secret or env var, an ambiguous requirement the task definition doesn't settle, a destructive migration, or a test failure that looks like a real bug in existing code rather than in your change.
-
- ## Pre-flight — Permissions
-
- If routine dev permissions are not yet configured for this worktree, invoke **`fastapi-grant-permissions`** first so file editing, test execution, git operations, and forge CLI commands run unprompted throughout the loop.
-
- ## Phase 1 — Plan
-
- Follow **`fastapi-plan`** (or **`fastapi-implement`**'s lighter planning phase for a small, single-surface task). Produce a concrete build sequence. Save the approved plan as an uncommitted OKF session note in `$KLAUSSY_SESSION_NOTES_DIR/<agent-name>-plan.md` (or `%KLAUSSY_SESSION_NOTES_DIR%\<agent-name>-plan.md` on Windows, or `plan.md` at worktree root) following the Open Knowledge Format protocol (YAML frontmatter with `type: session-note`, `tags: [plan, design, devloop]`, `generated: { by: <provider-id>/<agent-name>, at: <ISO-8601 timestamp> }`). If the task definition leaves a real ambiguity, ask now — a wrong assumption here costs the whole owl.
+ You are an orchestrator. Each phase below names the sibling skill that owns that work: open that skill's `SKILL.md`, follow it, come back here. This file holds the sequence and the gates between phases, not the steps — where a phase and its skill disagree, the skill wins on *how* and this file wins on *when to stop*.
- ## Phase 2 — Implement
+ Track the run with TodoWrite: one todo per phase, `in_progress` when you start it, `completed` when it's done. The flow is long and mostly unattended; the todo list is how the user follows along.
- Follow **`fastapi-implement`**. Work the plan in small batches, keeping the suite green as you go. For a bug fix, write the failing test first. Record any breaking changes or shared context notes in `$KLAUSSY_SESSION_NOTES_DIR/` (or `%KLAUSSY_SESSION_NOTES_DIR%` on Windows). Do not scope-creep beyond the task definition.
+ **Keep the main context lean.** Everything you read stays in this conversation and is re-read on every later turn, so hand the read-heavy phases (review, self-review, QA) to a sub-agent when your agent has one. Give it the skill to follow, the base branch, and the exact shape of what to return; it returns a short summary and you act on that. Two exceptions run inline: an agent with no sub-agents, and a review of 150 or more reviewable lines, which takes review's parallel path (a sub-agent can't start sub-agents of its own).
- ## Phase 3 — Local review and fix
+ **Stop and hand back** — don't barrel ahead — whenever a phase hits something a human must decide: a missing secret or env var, an ambiguous requirement, a destructive migration, or a test failure that looks like a real bug in existing code rather than in your change.
- Follow **`fastapi-review`** against the working diff (`git diff master...HEAD`). Fix every finding you agree with; for ones you don't, note why. Re-run the suite. Then follow **`fastapi-self-review`** as a last pass so the diff doesn't read as AI-written. Do not open the PR until this phase is clean.
+ ## Pre-flight
- ## Phase 4 — QA the change
+ 1. **Permissions.** If routine dev permissions aren't configured for this worktree yet, run **`fastapi-grant-permissions`** so editing, tests, git and the forge CLI don't prompt all run.
+ 2. **Base branch.** Decide once which branch this targets and use it as `<base>` everywhere. First that applies: one the task or user names; the target of an existing request for this branch; the remote default (`git symbolic-ref --short refs/remotes/origin/HEAD` minus `origin/`); `master`. If the branch was cut from another topic branch instead, ask rather than guess — a wrong base puts someone else's commits in your diff. Say which you picked in the first progress update.
- Follow **`fastapi-qa`**. It classifies the diff and runs only the QA that fits:
- - **UI / Frontend changes**:
- - Capture **before and after screenshots** for visual comparison, formatted in a comparison table.
- - Record a **full-flow video (.mp4)** demonstrating the complete interaction end-to-end. The video MUST showcase responsive UI behaviors by resizing (growing and shrinking) the window or viewport.
- - Save all media in `Downloads/klaussy-qa-<branch>/` (`~/Downloads/klaussy-qa-<branch>/` on macOS/Linux, `%USERPROFILE%\Downloads\klaussy-qa-<branch>\` on Windows).
- - Programmatically upload QA media assets (e.g. using `gh release upload`, `gh api` assets endpoint, or image host) so you have direct asset URLs ready to attach to the PR description.
- - **Backend / CLI changes**:
- - Exercise endpoints, run integration suites, and capture execution output.
+ ## Phases
- Don't hand-pick the QA yourself; let the skill right-size it to what the diff touches.
+ | # | Follow | Gate before moving on |
+ | :-- | :--- | :--- |
+ | 1 | **`fastapi-plan`** (or **`fastapi-implement`**'s lighter planning for a small, single-surface task) | An approved `plan.md`. Ask now if the task leaves a real ambiguity; a wrong assumption costs the whole owl. Keep the plan and any breaking-change notes as session notes per **`fastapi-session-context`**. |
+ | 2 | **`fastapi-implement`** | The plan's boxes are ticked and the suite is green. No scope creep beyond the task definition. |
+ | 3 | **`fastapi-review`** against `git diff <base>...HEAD`, then **`fastapi-self-review`** | Every finding you agree with is fixed, the rest noted with a reason, suite re-run. Sub-agent returns the verdict line and one line per finding (severity, `file:line`, fix). |
+ | 4 | **`fastapi-qa`** | QA is genuinely clean. Let the skill right-size the evidence; don't hand-pick it. Sub-agent returns each check with pass/fail, the artifacts folder, and any asset URLs for the PR body. |
+ | 5 | **`fastapi-pr`** | The request is open against `<base>`, its number and URL reported. Commit on a topic branch (never straight to `<base>`) and push first. Embed the QA evidence from Phase 4 in the body. |
+ | 6 | **`fastapi-review`** again, now that it's a real PR | Findings fixed, committed, pushed. A PR at rest reads differently: integration seams and the change as a whole surface here. |
+ | 7 | `waiting.md`, then the adapter's CI commands | Every check is green. |
+ | 8 | `waiting.md`, then **`fastapi-address-review`** | Every comment answered and its thread resolved. Pushing fixes re-triggers CI, so go back to 7 if anything goes red. |
+ | 9 | — | Stop. Report and hand back. |
- **QA is a gate, not a formality — clear it before you touch the PR.** The whole point of running QA here is to catch problems *before* they become CI failures or reviewer comments. If QA surfaces anything wrong — a screenshot that shows the change is broken or ugly, an endpoint returning the wrong response, a CLI erroring, a failing test — stop and fix it: loop back to Phase 2/3, correct the change, and re-QA. Do NOT open the PR (Phase 5) on a change that QA has shown to be broken and then rely on CI or the reviewer to catch it. Only advance once QA is genuinely clean (or the only gaps are ones you've explicitly flagged as un-QA-able and told the user about).
+ **Phase 4 is a gate, not a formality.** If QA shows the change is broken or ugly, go back to phase 2 or 3, fix it, and re-QA. Don't open a PR on a change QA has already failed and leave it for CI or the reviewer to catch.
- ## Phase 5 — Open the PR (humanized)
+ **Phase 7: fixing CI.** Pull each failing check's logs with the adapter's log command and fix the real cause. A flaky check gets one re-run before you treat it as genuine. If a failure is in code your change didn't touch and can't have caused, stop and tell the user rather than guessing.
- 1. Commit the work on a topic branch (never commit straight to `master`) and push.
- 2. Draft the PR body from the task definition + what you actually built, using **`fastapi-pr`**'s Summary / Changes / Test Plan structure. For UI changes, embed the Before/After comparison table and uploaded video links into the PR description; for backend/CLI, paste the captured output.
- 3. Run the body through **`fastapi-humanize`** before it goes out — the description is the most-read prose in the whole change; it must not read like a chatbot wrote it.
- 4. Open the request against `master` with the adapter's create command. Capture its number/URL and report it.
+ **Phase 9: landing.** Report the PR link, its check status, which review comments you addressed and how, the QA artifacts folder and anything still to attach by hand, and the one thing left: the user's merge. Mark all TodoWrite tasks complete. Say plainly if you stopped early and why.
### Forge commands (GitHub)
`origin` points at GitHub, so the `gh` CLI is the adapter. Confirm a flag with `gh <command> --help` before running one you haven't used in this repo; CLI interfaces drift between versions.
| Need | Command |
| :--- | :--- |
| Read a ticket | `gh issue view <n> --comments` |
| Open a request | `gh pr create --base <branch> --title <title> --body-file <file>` |
| Request status | `gh pr view <n> --json state,mergeable,reviewDecision,baseRefName` |
| CI status | `gh pr checks <n>`, then `gh run view <run-id> --log-failed` on a failure |
- | Read review comments | `gh api repos/{owner}/{repo}/pulls/<n>/comments` |
- | Reply in a thread | `gh api --method POST repos/{owner}/{repo}/pulls/<n>/comments/<comment-id>/replies -f body=<text>` |
- | Resolve a thread | two steps, see below — REST can't do it |
| Retarget a request | `gh pr edit <n> --base <branch>` |
`{owner}/{repo}` are placeholders `gh` fills from the current repo, leave them literal.
- **Resolving needs GraphQL, and the id it wants is not the comment id.** The REST comment objects don't carry it, so read the thread ids first, then resolve one:
-
- ```
- gh api graphql -f query='{ repository(owner: "<owner>", name: "<repo>") {
- pullRequest(number: <n>) { reviewThreads(first: 50) { nodes {
- id isResolved comments(first: 1) { nodes { databaseId body } } } } } } }'
-
- gh api graphql -f query='mutation($id: ID!) {
- resolveReviewThread(input: {threadId: $id}) { thread { isResolved } } }' -F id=<thread-node-id>
- ```
-
- Match a thread to the comment you replied to through `comments.nodes[].databaseId`, which is the REST comment id. `threadId` is the only required input.
-
- A reply must name the thread it answers. The `replies` endpoint above takes only `body`; the alternative is `POST .../pulls/<n>/comments` with `-F in_reply_to=<comment-id>` (an integer, hence `-F`). Posting to `comments` without `in_reply_to` opens a new top-level review comment rather than replying.
-
- **GitHub has native stacks**, driven by the `gh-stack` extension. `gh extension list` says whether it's installed. If it isn't, **offer to install it** — `gh extension install github/gh-stack`, one command, no repo changes — and say what it buys before asking: a stack map and layer navigation on every request page, plus cascading rebase when the base moves. Ask rather than installing unprompted, since it touches the user's `gh` setup and not this repo, but do ask; silently settling for bare chained bases hands back a worse result than the one command would have. Declining is a fine answer and the fallback below still works.
-
- The extension is in public preview, so check `gh stack <command> --help` before relying on a flag.
-
- | Need | Command |
- | :--- | :--- |
- | Link requests that already exist into a stack | `gh stack link --base <branch> <branch-or-pr> <branch-or-pr> ...` |
- | Track a carved chain locally | `gh stack init --base <branch> <branch> ...` |
- | Push the tracked chain and open or update its requests | `gh stack submit` |
- | See the stack | `gh stack view` |
- | Cascading rebase after the base moved | `gh stack rebase` |
- | Fetch, rebase, push, and sync in one pass | `gh stack sync` |
-
- Arguments run bottom-up, nearest the base first. Two constraints decide whether a stack is available at all: **every branch must live in this repo** (cross-fork stacks aren't supported), and the extension has to be installed.
-
- `link` and `init` are two different entry points and the difference shows up later. `link` stacks requests that already exist and leaves nothing behind locally, so a later `gh stack rebase` needs `gh stack checkout <stack-number>` first to pick the stack back up. `init` registers the branches locally up front and `submit` then opens the requests itself, which means the bodies are its own — write them with `gh pr edit <n> --body-file` afterwards if they have to say something specific.
-
- Without it, chained `--base` targets still give reviewers a per-layer diff, and GitHub often offers to convert an eligible chain into a stack — a banner on the request, or "Add to stack" behind the stack icon. Say which route you took.
-
-
- ## Phase 6 — Re-review the PR and fix
-
- Now that the diff is a real PR, review it once more with **`fastapi-review`** (a PR at rest reads differently than an uncommitted diff — integration seams and the change as a whole surface here). Fix findings, commit, push.
-
- ## Phase 7 — Poll CI and fix failures
-
- Watch the checks until they reach a terminal state, using the adapter's CI status command (poll on a sane cadence if it has no watch mode).
-
- For each failing check, pull its logs with the adapter's log command, diagnose the *real* cause, fix it, commit, push, and re-watch. A flaky check gets one re-run before you treat it as a genuine failure — don't loop forever re-running a green-on-retry check, and don't paper over a real failure by disabling the test. If a failure is in code your change didn't touch and can't have caused, stop and tell the user rather than guessing.
-
- ## Phase 8 — Poll for code review and resolve
-
- Once CI is green, wait for review to land (human or bot). Poll on a sane cadence — check, wait, check — rather than hammering the API, using the adapter's status and review-comment commands. Inline comments and the summary review body come from different endpoints on every provider, so read both.
-
- For the feedback that arrives, follow **`fastapi-address-review`**: triage each comment, apply the changes it warrants, draft a reply, and resolve the thread once handled. Push fixes, which re-triggers CI — loop back to Phase 7 if anything goes red.
-
- **Bounded wait.** Reviews depend on a human showing up, so do not poll indefinitely. If no new review activity arrives after a reasonable window (say, several polls over ~15 minutes, or immediately if the user tells you to wrap up), stop polling and hand back with a summary. Resume later when the user says review has landed.
-
- ## Phase 9 — Land the owl (but don't merge)
-
- When CI is green and all review threads are resolved, stop. Report: the PR link, its check status, which review comments you addressed and how, the path to the QA artifacts folder and which recordings still need dragging into the PR, and the one thing left — the user's merge. Mark all TodoWrite tasks complete.
-
- State plainly if you stopped early and why (waiting on review, blocked on a decision, a failure you wouldn't paper over).
-
## Rules
- **Never merge, never mark ready-to-merge, never force-push over other commits.** The human owns the merge.
- **No scope creep across the whole owl.** The task definition is the contract. Fixing a review comment is in scope; rewriting an unrelated subsystem because you noticed it is not.
- - **Don't fake green.** Never disable, skip, or `xfail` a test, loosen a lint rule, or `--no-verify` past a guard to make CI pass. A red check is information; fix the cause.
- - **Humanize anything the user will read** — PR body, review replies, commit messages. Run **`fastapi-humanize`** on prose before it ships.
+ - **Don't fake green.** Never disable, skip or `xfail` a test, loosen a lint rule, or `--no-verify` past a guard to make CI pass. A red check is information; fix the cause.
- **Stop for humans on human decisions** — missing secrets, ambiguous requirements, destructive changes, or a failure that points at a pre-existing bug.
+
+ **Humanize anything a human will read.** Before prose ships — a PR body, a review comment or reply, a commit message, a changelog entry, docs — run it through the `fastapi-humanize` skill and use what comes back. That skill holds the rules; don't keep a second copy of them here.
+
+ **The scrubber is not that pass.** `klaussy humanize` deletes a fixed list of mechanical tells (dashes, filler openers, a few hedges) and changes nothing else. It can't cut a paragraph that shouldn't exist, turn a noun phrase back into a verb, drop the closing principle, or make three sentences one, and that's most of what makes prose read as generated. Anything a human will read gets the `fastapi-humanize` skill: cut, voice, check, then scrub. Running the CLI, or `klaussy humanize --check`, is not that pass and doesn't stand in for it.
## When NOT to use
- The user wants just one phase — planning, or a review, or a PR description. Use that skill directly; the full owl is overkill.
- The task isn't defined well enough to build unattended. Nail the definition down first (or use **`fastapi-plan`**, which forces the clarifying questions), then come back.
- The change must be merged, released, or deployed as part of the ask — this skill deliberately stops at the merge button. Do that step yourself, with a human in the loop.