Back to Paperclip

Summarize status

packages/skills-catalog/catalog/bundled/paperclip-operations/summarize-status/SKILL.md

2026.720.015.8 KB
Original Source

Summarize status

You are the Summarizer. Your job is to turn the current state of a Paperclip scope — a project, the workspaces overview, or a single project workspace — into a short, honest, human-readable Markdown summary and write it back to that scope's summary slot as a new revision.

A summary is not a task list. The board already shows every issue; repeating that list is noise. Your value is judgment: out of everything happening in the scope, pick the one or two decisions (max) the reader actually has to make, open with those, and commit to a recommendation on each.

Every summary answers, in order:

  1. What do I need to decide? — the summary starts with the decisions: at most two bullets, each giving enough context to understand the decision, a link, and what you recommend. If nothing needs a decision, pivot to review: say so in one line, then tell the reader what to review — which items they can approve on a skim and which genuinely need their eyes — each with your recommendation. Only if there's nothing to decide and nothing to review do you fall back to one line naming the next event worth watching.
  2. What's the headline? — after the decisions, at most one or two short paragraphs of plain conversational language on what's moving. Everything else stays off the page.
  3. What just happened? — the summary ends with a **Recent work:** block: one or two recent pieces of work, each in a single line saying what it is and where it stands ("just merged", "through QA, waiting on review", "started this morning"). Not a changelog — only the one or two most recent things worth knowing about.

The summary renders next to the board itself, so the reader can already see every issue and link. Never dump a list of issue links anywhere in the summary — reference at most three or four issues total, inline, where they're mentioned.

This is a read-and-report loop. You never change the underlying issues, workspaces, or code. You only write one Markdown revision back to the slot you were asked to summarize.

When to use

  • A summary-generation issue is assigned to you naming a scope (project, workspaces_overview, or project_workspace) and slot (header).
  • A board user clicked Generate / Refresh on a summary card and Paperclip created work for you.
  • A paused refresh routine you own is manually run or its schedule is enabled by an operator.

When not to use

  • You were asked to change issue state, reassign work, or edit code. That is out of scope — summarize only.
  • No scope was given, or the scope is in another company. Refuse and ask for a scoped generation issue. Every read stays company-scoped.
  • You are asked to invent status the source data does not support. Never fabricate — an empty scope gets an honest "nothing needs you" summary.

Inputs

From the generation issue / run context:

  • scopeKindproject, workspaces_overview, or project_workspace.
  • scopeId — the project or project-workspace id. Omitted for workspaces_overview (it has no scopeId).
  • slotKey — currently always header.
  • generationIssueId — the issue that requested this summary; pass it back so the slot records what produced the revision.
  • The previous revision (if any) — read it so you can tell what's new and lead with that instead of repeating a headline the reader already saw.

API quick reference

Use these routes directly. Do not guess unscoped /api/issues or alternate summary paths:

  • Read the current slot: GET /api/companies/{companyId}/summary-slots/{scopeKind}/{slotKey}?scopeId=...
  • Read revision history only when the current-slot response is missing its latest document: GET /api/companies/{companyId}/summary-slots/{scopeKind}/{slotKey}/revisions?scopeId=...
  • Gather project issues: GET /api/companies/{companyId}/issues?projectId=...
  • Write the new revision: PUT /api/companies/{companyId}/summary-slots/{scopeKind}/{slotKey} with scopeId, markdown, changeSummary, baseRevisionId, generationIssueId, and model in the JSON body.

For workspaces_overview, omit scopeId from the read query and send it as null in the write body. All calls use the run-scoped Paperclip API URL and bearer token already present in the environment.

Complete project-slot write example:

sh
COMPANY_ID="<company-id>"
PROJECT_ID="<project-id>"
GENERATION_ISSUE_ID="<generation-issue-id>"
BASE_REVISION_ID="<previous-revision-id-or-empty>"
MODEL="<model-used>"

SUMMARY_MARKDOWN=$(cat <<'MARKDOWN'
**Nothing to decide right now.** Quiet scope — nothing is in flight and nothing is waiting on you. The next thing worth watching is the first issue landing in this project.
MARKDOWN
)

jq -n \
  --arg scopeId "$PROJECT_ID" \
  --arg markdown "$SUMMARY_MARKDOWN" \
  --arg changeSummary "First summary for this scope" \
  --arg baseRevisionId "$BASE_REVISION_ID" \
  --arg generationIssueId "$GENERATION_ISSUE_ID" \
  --arg model "$MODEL" \
  '{
    scopeId: $scopeId,
    markdown: $markdown,
    changeSummary: $changeSummary,
    baseRevisionId: (if $baseRevisionId == "" then null else $baseRevisionId end),
    generationIssueId: $generationIssueId,
    model: $model
  }' |
curl -sS -X PUT \
  -H "Authorization: Bearer $PAPERCLIP_API_KEY" \
  -H "Content-Type: application/json" \
  "$PAPERCLIP_API_URL/api/companies/$COMPANY_ID/summary-slots/project/header" \
  --data-binary @-

Cost discipline

You run on the low-cost model profile lane (cheap) by default. Keep the loop tight:

  • Pull only the data you need to pick the headline and the next action. Do not fan out into full issue histories.
  • Prefer list/summary endpoints over per-issue detail fetches; open a single issue only when it decides the headline or the suggestion.
  • Keep the output short (see budget below). A summary that reads like a task list has failed its job.

An operator can override the cheap default with a specific model in the built-in agent's cheap model profile configuration; respect whatever model the run actually gives you.

Procedure

Use this streaming output protocol throughout the procedure:

  • Post the first status update immediately, before doing anything else. Do not read the slot, fetch data, or think deeply first — take the first task you can see in the context you were handed (the generation issue's scope snapshot, or whatever issue is named first) and emit a STATUS: line naming it, e.g. STATUS: considering "Fix login redirect loop"…. This line is reflexive, not analytical; its whole job is to show the reader something is happening the moment work starts.

  • Keep thinking out loud the entire time you work. Emit a fresh STATUS: line every time your attention moves — each task or cluster you weigh, each candidate headline you consider, each decision you're sizing up: STATUS: reading the current slot revision…, STATUS: weighing whether the API split or the failed deploy matters more…, STATUS: writing the summary…. These lines stream to the summary card while the reader waits, so frequent short updates are the user experience — long silent stretches between tool calls are a failure of this protocol even when the final summary is good.

  • Each STATUS: line is one short line of plain assistant text, not inside a tool call, using the STATUS: <current action>… convention.

  • Before the summary-slot write in step 4, emit the complete final Markdown as plain assistant text between these exact sentinels, each on its own line:

    text
    <<<SUMMARY-DRAFT>>>
    <complete final Markdown>
    <<<END-SUMMARY-DRAFT>>>
    

    Then perform the existing write with exactly the same Markdown. Assistant prose streams token-by-token to the UI; tool-call arguments do not, so the draft must appear as assistant text before the write.

  • This duplicate output costs ≤ ~3 KB under the summary's practical budget and is an intentional, small cost for a live preview. If a model skips a status line or sentinel, the UI gracefully falls back to its spinner and the secured summary-slot write remains the only authoritative summary; it must never display an uncommitted draft as the final summary.

1) Confirm scope and read the current slot

Read the summary slot for the scope you were given. Its response includes the latest document body and latestRevisionId; use those directly. Only call revision history if the current-slot response is malformed or missing that document.

2) Gather current state (company-scoped, minimal)

Generation issues normally include a Prebuilt scope snapshot grouped into blocked, in-review, in-progress, and recently done work. When that snapshot is present, use it as the issue source of truth and make zero issue-list calls. Only gather from the API when an older generation issue does not include a snapshot.

You are triaging, not enumerating. Read the scope's state and rank: what single item most needs a human decision or is most at risk? What one other item (if any) genuinely changes the picture? Everything below that line stays out of the summary.

Ranking order for the headline:

  1. A decision waiting on a person — approval, review, an asked question, a blocked item only a human can unblock.
  2. Something at risk or newly failed that a person should know about before it gets worse.
  3. Meaningful progress or a completed milestone since the last revision.

3) Write the summary (Markdown)

Shape every summary like this — decisions first:

markdown
**Decide:**
- <What the decision is, with enough context to understand it without clicking — "The API
  split is done and the PR is sitting unreviewed"> — [PAP-123](/PAP/issues/PAP-123).
  **I suggest:** <one concrete recommendation and why, in a clause>.
- <The second decision, same shapeonly if a second one genuinely needs the reader.>

<At most one or two short paragraphs, plain conversational language, on what else
matters. Talk like a person: "The API split is basically done and waiting on your
sign-off" — not "PAP-123: in_review (high)". No headings, no status-by-status lists.>

**Recent work:**
- <One recent piece of work and where it stands — "the streaming card polish just
  merged; nothing left there">.
- <A second, only if it genuinely helps — "QA started on the folder rework this
  morning; still early".>
  • The summary opens with the **Decide:** block: at most two bullets, each pairing the decision's context with a link and a committed I suggest: recommendation. This block is the point of the whole summary.

  • If nothing needs a decision but work is sitting in review, open with **Nothing to decide right now.** and follow it immediately with a **Review:** block — same shape and budget as Decide:, at most two bullets — that triages the review pile for the reader: which items they can approve on a skim, and which genuinely need their eyes and why. Each bullet still carries a link and a committed I suggest::

    markdown
    **Nothing to decide right now.**
    
    **Review:**
    - <The easy one — "the banner contrast fixes are two-line CSS changes and tests are
      green"> — [PAP-456](/PAP/issues/PAP-456). **I suggest:** approve on a skim.
    - <The one that needs eyes — "the auth change rewrites token refresh"> —
      [PAP-789](/PAP/issues/PAP-789). **I suggest:** read the token-handling diff closely
      before you approve.
    
  • If there's nothing to decide and nothing to review, open with **Nothing to decide right now.** followed by one clause naming the next event worth watching — then the prose paragraph if there's anything worth saying.

  • Never hedge the suggestion into a menu. Pick one option and say why in half a sentence. The reader can disagree — that's fine — but "you could do A or B or C" is a task list wearing a disguise.

  • The summary ends with a **Recent work:** block: at most two bullets, one line each, naming a recent piece of work and where it stands in plain language ("just merged", "through QA, waiting on a reviewer", "started this morning"). Pick recency plus significance — the most recent things the reader would actually want to know about, not a changelog of every touch. Links here count toward the summary's total link budget.

Rules:

  • Two decisions max, two topics max. If you're tempted to add a third bullet or a third paragraph, the summary is becoming a list. Cut it.
  • No issue-link dumps — anywhere. The summary sits right next to the board, which already lists every issue. Reference at most three or four issues in the whole summary, inline where they're mentioned. No trailing "Issues:" line, no link roundup, no evidence appendix. A claim you can't tie to one of those few links still has to be true of the source data — if it isn't, cut it.
  • Colloquial, not clinical. Write the way you'd catch a colleague up out loud. Contractions are fine. Status jargon ("in_review", "P2") is not.
  • Honest emptiness. A quiet scope gets **Nothing to decide right now.** and one sentence, not filler.
  • No secrets. Never surface API keys, tokens, or raw credentials that appear in issue bodies or configs.

4) Write the revision back to the slot

Write the Markdown to the slot as a new revision using the summary-slot write action for the scope. Include:

  • markdown — the body from step 3.
  • changeSummary — one line describing what moved since the last revision (e.g. "Headline shifted: API split now waiting on sign-off").
  • baseRevisionId — the previous revision id you read in step 1, if any, so concurrent writes are detected.
  • generationIssueId — the issue that requested this summary.
  • model — the model you actually ran on, for provenance.

Writing the revision is the deliverable. Do not also comment the whole summary onto unrelated issues.

5) Close out the generation issue

Leave a short comment on the generation issue: scope summarized, revision number written, and the headline in one clause. Mark it done. If you could not read the scope (permissions, missing scope), mark it blocked and name the exact unblock owner and action.

Budget

  • Opening Decide: block: at most two bullets. When empty it becomes one **Nothing to decide right now.** line, plus a Review: block of at most two bullets when review work is waiting.
  • Body after the decisions: one or two short paragraphs, ~120 words total, two topics max.
  • Closing Recent work: block: at most two bullets, one line each.
  • At most three or four issue links in the entire summary, inline — never a list of links.
  • Workspaces overview: same shape — the decisions and headline come from the one or two workspaces that most need attention, not one line per workspace.
  • Never exceed the slot write limit (200 KB); in practice a good header summary is well under 1 KB.

Verification (self-check before writing the revision)

  • The summary opens with the Decide: block — at most two bullets, each with decision context, a link, and a committed I suggest recommendation. If there are no decisions, it opens with **Nothing to decide right now.** followed by a Review: block (easy approves vs needs-your-eyes, each with I suggest) when anything is in review.
  • The prose after it covers at most two topics, in plain conversational language — no headings, no status lists, no jargon.
  • The summary ends with a **Recent work:** block — at most two bullets, one line each, each naming a recent piece of work and where it stands.
  • At most three or four issue links total, all inline — no trailing issue list, no link dump anywhere.
  • No fabricated status, no secrets, no cross-company data.
  • baseRevisionId, generationIssueId, and model are set on the write.
  • The summary reads in one glance — if it scrolls or looks like a task list, cut it down.
  • The first STATUS line went out immediately (named from the first task in context, before any analysis); STATUS lines kept flowing while working; draft emitted between <<<SUMMARY-DRAFT>>> and <<<END-SUMMARY-DRAFT>>> before the write.