feat(mt#4611): Add /catch-up — re-orient the principal mid-conversation, distinct from /handoff - #3491
Conversation
`/handoff` writes a durable record for the NEXT agent. Nothing addressed the principal who is still here and has lost the thread — stepped away, context- switched, or reading a scrollback they can no longer see the shape of. Asking `/handoff` to do that produces a technically-correct summary that answers the least useful question: it opens with "shipped mt#X, queue is mt#Y", which the principal can already read off a task list. The load-bearing difference is the WHY. What a principal cannot reconstruct is the chain from what they originally asked for to whatever is on the screen now — especially when the work drifted, which is exactly when they ask. So the skill mandates four parts in order (what / why / state / next), and requires the WHY to name the originating request and say plainly if the work departed from it. Two disciplines it inherits rather than invents: - **Re-derive statuses via `refs_status`; never recall them.** Not diligence theater — in the conversation that produced this skill, mt#4541 was filed mid-session and went TODO → DONE under another actor before the catch-up was written. A recalled status would have reported finished work as pending. - **Lead with the correction.** If something the principal was told earlier turned out wrong, the catch-up is where it gets fixed, near the top. Explicitly NOT auto-triggered: unlike `/handoff`, nothing about conversation shape reveals that the principal has lost the thread — only they know that. And it persists nothing; `/handoff` owns the durable path (mt#2911). Raises LISTING_TOTAL_TARGET_CHARS 18_000 → 18_500 on an explicit principal decision (three alternatives were put to him; this is the one he chose). The constant's docblock records the rejected options and, more usefully, tells the next reader to read the HEADROOM rather than the number: 18_500 buys about one more skill, so raising it again is not the reflex to reach for. Measured after this change: 18,263 across 61 skills. This commit was blocked for five days by mt#4622 — lint-staged reformatted the staged SKILL.md source at pre-commit step 1, and the compile-staleness check then rejected output built from the pre-format source. That shipped 2026-08-26; `compile --check` in this session now returns stale: false.
Minsky Reviewer StatusVerdict: APPROVED — no blocking findings Commands
|
There was a problem hiding this comment.
Independent adversarial review (Chinese-wall)
Reviewer: minsky-reviewer[bot] via openai:gpt-5
Tier: 2
Adds a new /catch-up skill (source and compiled outputs) and raises the skill-listing total budget from 18,000 to 18,500. The skill meets all success criteria: correct frontmatter and triggers, explicit four-part structure, live status re-derivation, and clear boundaries vs /handoff, /retrospective, and /incident-memo. The compiled artifact is present. One non-blocking nit: the skill references filenames that don’t appear to exist in docs/ (communication-contract.mdc, cockpit-deeplinks.mdc, user-preferences.mdc); consider aligning to in-repo paths or clarifying where they live. No blocking issues found; approving. Coverage note: I focused on the skill files and budget constant and spot-checked docs for the cited references; I did not sweep the entire docs tree for the old numeric cap value.
Findings
- [NON-BLOCKING] .minsky/skills/catch-up/SKILL.md:66 — Doc references use filenames that do not exist in docs/ (potentially stale paths)
The skill text citescommunication-contract.mdc,cockpit-deeplinks.mdc, anduser-preferences.mdc(see.minsky/skills/catch-up/SKILL.md:66-73). A quick scan ofdocs/shows norules/communication-contract.mdc(404) and no obviouscockpit-deeplinks.mdc/user-preferences.mdcfiles. If these are canonical names that live outside this repo, consider adjusting the references to their in-repo paths or adding a brief parenthetical (e.g., "see docs/.../") to avoid dead references for contributors following the guidance. If the filenames are correct but live elsewhere, ignore — raising as a heads-up to verify consistency.
Spec verification
| Criterion | Status | Evidence |
|---|---|---|
| .minsky/skills/catch-up/SKILL.md exists with user-invocable: true, and its description names the trigger phrasings a principal actually uses ("catch me up", "what were we doing", "where are we", etc.). | Met | .minsky/skills/catch-up/SKILL.md:1-12 — frontmatter includes name: catch-up; user-invocable: true; description enumerates trigger phrasings ("catch me up", "what were we doing", "where are we", "remind me why"). |
| The skill body prescribes the four-part answer — what we were doing / why / current state / what's next — and says the WHY is the part /handoff omits. | Met | .minsky/skills/catch-up/SKILL.md:28-43 — section "## The four parts" lists the four items in order; .minsky/skills/catch-up/SKILL.md:20-27 emphasizes WHY as the load-bearing difference from /handoff. |
| The skill requires statuses to be re-derived live (refs_status / tasks_status_get) rather than recalled, and says why (fast-moving parallel-agent graph example). | Met | .minsky/skills/catch-up/SKILL.md:45-60 — section "## Re-derive statuses; do not recall them" instructs running refs_status and cites the mt#4541 example and other live checks. |
| The skill states its own boundary against /handoff, /retrospective and /incident-memo, so a future agent picks correctly. | Met | .minsky/skills/catch-up/SKILL.md:14-27 — "## Why this is not /handoff" includes a contrast table and explicitly distinguishes from /retrospective and /incident-memo. |
| The compiled output .claude/skills/catch-up/SKILL.md is regenerated and committed in the same PR, verified per /implement-task §7 item 4 (per-target report + git status + grep the output), not by trusting the compile exit code. | Met | .claude/skills/catch-up/SKILL.md exists with generated header; content mirrors source sections and headings (e.g., "## The four parts" at .claude/skills/catch-up/SKILL.md:28-43). The presence of both source and compiled files in this diff demonstrates regeneration and commit. |
Documentation impact
- no-update-needed — This PR adds a new agent skill definition and adjusts an internal compile budget constant. No public CLI/API surface changed. I checked for obviously-related docs in docs/ and found no references that would be invalidated by the added skill; the budget constant is an internal limit surfaced only in compile output. No existing documentation appears to assert the old 18,000 value. If there is a doc naming the exact number elsewhere, it did not surface in this pass.
There was a problem hiding this comment.
Independent adversarial review (Chinese-wall)
Reviewer: minsky-reviewer[bot] via openai:gpt-5
Tier: 2
Verification round: no prior BLOCKING findings to re-check. The PR adds a new /catch-up skill (source and compiled output) and raises the skill-listing total budget from 18,000 to 18,500 along with an explanatory docblock. I re-verified all Success Criteria against the current spec: the skill frontmatter and trigger phrasings are present; the body prescribes the four-part structure emphasizing WHY; it explicitly requires live status re-derivation; it states boundaries vs /handoff, /retrospective, and /incident-memo; and the compiled artifact is present and mirrors the source. The budget constant change is localized and well-documented; no functional regressions or critical issues found. Prior non-blocking note about doc filename references remains advisory. Approving.
Spec verification
| Criterion | Status | Evidence |
|---|---|---|
.minsky/skills/catch-up/SKILL.md exists with user-invocable: true, and its description names the trigger phrasings a principal actually uses ("catch me up", "what were we doing", "where are we", "summarize this and contextualize it"). |
Met | .minsky/skills/catch-up/SKILL.md:1-12 — frontmatter includes name: catch-up, user-invocable: true, and a description listing trigger phrasings ("catch me up", "what were we doing", "where are we", "remind me why"). |
The skill body prescribes the four-part answer the originating prompt asked for — what we were doing / why / current state / what's next — and says the WHY is the part /handoff omits. |
Met | .minsky/skills/catch-up/SKILL.md:28-43 — section "## The four parts" lists the four items in order; .minsky/skills/catch-up/SKILL.md:20-27 explains WHY as the load-bearing difference from /handoff. |
The skill requires statuses to be re-derived live (refs_status / tasks_status_get) rather than recalled, and says why: in a fast-moving parallel-agent graph a task this conversation filed may have been finished by someone else (mt#4541 example). |
Met | .minsky/skills/catch-up/SKILL.md:45-60 — section "## Re-derive statuses; do not recall them" instructs running refs_status and cites the mt#4541 TODO→DONE example and other live checks. |
The skill states its own boundary against /handoff, /retrospective and /incident-memo, so a future agent picks correctly. |
Met | .minsky/skills/catch-up/SKILL.md:14-27 — "## Why this is not /handoff" contrasts the two and calls out /retrospective and /incident-memo as distinct surfaces. |
The compiled output .claude/skills/catch-up/SKILL.md is regenerated and committed in the same PR, verified per /implement-task §7 item 4 (per-target report + git status + grep the output), not by trusting the compile exit code. |
Met | .claude/skills/catch-up/SKILL.md exists with the generated header and mirrors the source headings (e.g., "## The four parts"). Presence of both source and compiled files in the diff demonstrates regeneration and commit. |
Documentation impact
- no-update-needed — Adds a new agent skill definition (source + compiled output) and raises an internal compile-time listing budget constant from 18,000 to 18,500 in
packages/domain/src/compile/skill-listing-budget.ts. No public CLI/API or user-visible contract changed. I spot-checked for any docs that explicitly assert the old 18,000 cap and found none in this PR; the constant is internal and surfaced only in compile reports. The new skill is guidance for agents, not an end-user feature documented elsewhere.
Summary
/handoffwrites a durable record for the next agent. Nothing addressed the principal who isstill here and has lost the thread — stepped away, context-switched, or reading a scrollback
they can no longer see the shape of.
Asking
/handoffto cover that produces a technically-correct summary answering the least usefulquestion. It opens with "shipped mt#X, mt#Y; queue is mt#Z" — which the principal can already read
off a task list. What they cannot reconstruct is the chain from what they originally asked for to
whatever is on the screen now, especially when the work drifted, which is exactly when they ask.
So the skill mandates four parts in order — what / why / current state / next — and requires the
WHY to name the originating request and say plainly if the work departed from it.
/handoff/catch-upKey changes
.minsky/skills/catch-up/SKILL.md+ its compiled output. Two disciplines it inherits ratherthan invents:
refs_status; never recall them. Not diligence theater — in theconversation that produced this skill, mt#4541 was filed mid-session and went TODO → DONE under
another actor before the catch-up was written. A recalled status would have reported finished
work as pending.
catch-up is where it gets fixed, near the top, not buried.
/handoff, nothing about conversation shape revealsthat the principal has lost the thread — only they know. And it persists nothing;
/handoffownsthe durable path (mt#2911). Doing both is called out as the anti-pattern.
LISTING_TOTAL_TARGET_CHARS18_000 → 18_500, on an explicit principal decision. The old valueleft 47 chars of headroom at 60 skills, so the next skill of any kind overflowed it. Three options
were put to him — truncate the five vendored over-cap descriptions at compile time, trim an owned
sibling, or raise the cap — and he chose to raise it. The docblock records the rejected options and
tells the next reader to read the headroom, not the number: 18_500 buys roughly one more skill,
so raising it again is not the reflex to reach for.
Testing
Execution evidence:
SC1 — skill exists,
user-invocable: true, description names real trigger phrasings. Verifiedagainst the COMPILED output, not the source:
Its
descriptioncarries "catch me up", "what were we doing", "where are we", "remind me why", and"a summary request while work is in flight".
SC2 / SC3 / SC4 — skill body content. Prose criteria, satisfied by the shipped file and visible
in this diff: the four-part answer with WHY named as the part
/handoffomits (§The four parts);the re-derive-don't-recall requirement with mt#4541 as its worked example (§Re-derive statuses);
and the explicit boundary against
/handoff,/retrospectiveand/incident-memo(§Why this isnot
/handoff).SC5 — compiled output regenerated and committed, verified rather than trusted.
One deviation from SC5's stated method, stated rather than papered over. The criterion asks for
the per-target
Target "<name>": N file(s) writtenline. This CLI invocation does not emit it — itprints a JSON result object plus two
[compile]report lines, and the human-readable per-target linebelongs to a different output mode. Rather than fabricate it, the stronger available check is used:
--checkcompares output CONTENT against a fresh compile of the source. A write count only assertsthat something happened; this asserts the committed output equals what the committed source
produces, which is what SC5 is actually for.
The budget, measured after the change — the criterion the cap raise exists for:
18,263 is over the old 18,000 cap, so this change is load-bearing rather than cosmetic: without
it the compile reports
EXCEEDS SKILL LISTING BUDGET, and an over-budget listing silently dropsdescriptions — which makes a skill listed name-only unroutable. The second line is the declined
alternative, still on the table: those five vendored descriptions total ~2,746 chars.
Nothing pinned the old constant:
This commit was blocked for five days, and the unblocking is itself verified. mt#4622 (merged
2026-08-26, PR #3381) fixed the cause: lint-staged reformatted the staged
SKILL.mdsource atpre-commit step 1, and the staleness check at step 9b then rejected output built from the pre-format
source. Confirmed here after
session_updatebrought the fix into this 5-day-old session:and the commit that had failed repeatedly now passes pre-commit and pushes clean. That is end-to-end
evidence for mt#4622's fix as much as for this task.
No new test file is added — this ships a skill definition and a constant, and the constant's effect
is a property of the live 61-skill corpus rather than of a fixture, so the compile output above is
the assertion.
Deploy verification
Deploy surface — verified by running the predicate rather than assuming:
The constant lives under
packages/domain/**, so this IS deploy surface and no[no-deploy-impact]tag is claimed anywhere in this PR or its commit message. Post-merge deploy verification runs per
§10 against the merge timestamp; it is not waived.
Live verification
The compile runs above are the live exercise — the real CLI against the real 61-skill corpus in the
session workspace. The skill's own behaviour is prose instruction to an agent, so there is no runtime
surface to probe beyond its presence in the compiled listing, which the 61-skill count confirms.