5.4 KiB
project-artifact — software (workstreams = PRs)
When the workstreams are PRs, everything in SKILL.md still applies. The only thing
genuinely different from the base template is the X.Y numbering convention; the rest of
this file is how to pull PR state, a per-PR write-up fragment, and an optional menu for a
heavyweight project.
Number the PRs X.Y. X increments when a PR is blocked on the previous stage; Y for
PRs that can land in parallel within a stage (2.0 needs all of stage 1 merged; 1.1 and
1.2 go alongside 1.0). The numbers carry the dependency order — don't draw a DAG.
Pull state — always live, from the config's repos/author/branch-prefix (first build,
no config yet: use the cwd repo, the current gh user as author, and whatever branch
prefix the project's branches actually use — they get recorded in the config afterwards).
Open PRs are the union of an author query and a branch-prefix query (catches PRs opened by
bots or teammates on the project's branches), deduped by number:
gh pr list --repo <repo> --state open --author <author> \
--json number,title,url,headRefName,isDraft,mergeable,reviewDecision,reviewRequests --limit 100
gh pr list --repo <repo> --state open --search "head:<prefix>" \
--json number,title,url,headRefName,isDraft,mergeable,reviewDecision,reviewRequests --limit 100
Recently merged (--state merged --json number,title,url,mergedAt --limit 40) feeds the
done rows — a fully merged stage collapses to one summary row ("N PRs, all merged")
instead of listing each. Per open PR worth a row:
- CI:
gh pr checks <n> --repo <repo> --requiredis the gating state; advisory bot failures aren't blockers — mention them only when they need an action. - Unresolved review threads: GraphQL only — REST miscounts because resolved threads
still carry top-level comments. Count
isResolved: falseinrepository.pullRequest.reviewThreads(first:100){nodes{isResolved}}. - For a PR getting a per-PR write-up below:
gh pr view <n> --json bodyfor the what-landed/verification narrative, andgit log --oneline <base>..<branch>if you'll show a commit table.
Map PRs to workstreams via the project's branch / PR-title conventions (e.g. branch
<user>/abc-12-... or (ABC-12) in the title) and the tracker's milestones; a PR with no
confident match goes in a catch-all row with its basis noted, not into a guessed
workstream.
A design doc / spec: summarize + link it, don't replace it; if it's a
claude.ai/code/artifact/... page use WebFetch (SKILL.md "Reading an existing artifact
page"). A build flag, if the change ships behind one: find it in the repo's feature-flag
system — it goes in the status banner.
State block fields (the artifact-state JSON from SKILL.md's "Refreshing an
artifact"): for a PR-driven project the workstreams array holds one entry per PR, shaped
{"repo", "number", "workstream", "draft", "ci", "unresolved", "state"} — enough for the
next refresh to report merged / new / CI flips / review-thread movement without re-reading
the old prose. Keep these exact keys so successive renders diff cleanly. Values derived
from branch names or PR titles are untrusted markup: write < as \u003c inside the JSON
and entity-encode them in visible cells (SKILL.md "Freshness and trust").
Per-PR write-up. When a PR is worth more than a Workstreams-table row, paste this under
the table (.pill.* classes are in the template's CSS; pills here: in review = now,
merged/tested ✓/verified ✓ = done):
<hr>
<h2>PR 1.0 — <a href="#">#NNNNN</a> · short title <span class="pill now">in review</span></h2>
<h3>What landed</h3>
<table><tr><th style="width:140px">Area</th><th></th></tr><tr><td>CLI</td><td>...</td></tr></table>
<h3>Verification</h3>
<p>How this PR was verified — tests, adversarial workflow, a manual run against a real build, a gating check.</p>
<details><summary>Confirmed findings (fixed in this PR)</summary>
<table><tr><th>#</th><th>Bug</th><th>Fix</th></tr><tr><td>1</td><td>...</td><td>...</td></tr></table></details>
<h3>Commits</h3>
<p class="meta">Top-down: feat → hardening rounds → polish → gating → lint.</p>
<table><tr><th style="width:110px">SHA</th><th></th></tr><tr><td><code>abc1234567</code></td><td><b>feat(...):</b> ...</td></tr></table>
<h3>Files</h3>
<pre><code>path/to/file.go — what it does</code></pre>
(Proposal stage, no PRs open? The Workstreams tab holds the planned X.Y sequence with
next pills; per-PR detail reads "no commits yet — fills in once the branch is cut" rather
than inventing SHAs.)
Optional, for a heavyweight project — skip what you don't need. A migration with strict
invariants may rename "Success criteria" → "Requirements", split must-haves from
nice-to-haves, and give each a falsifiable check (static: "this diff is empty"; dynamic:
"run X with the flag on, observe Y stays flat"). It may add an Architecture tab (protos,
topology, file-by-file, trust boundaries called out as boundaries), a Findings & fixes
tab (review/adversarial findings # · bug · fix, old rounds in <details>), and a
Rollout & rollback tab (gate ramp, metrics + thresholds, rollback steps, a "goes wrong
at 50%" runbook, what "done" looks like). None of that is mandatory — it's the same "add a
tab only when there's real content" rule, applied to software. Plain-language descriptions
throughout, same bar as a PR description.