| name | recursive-spine-nudge |
| description | Use after a recursive-spine-digest sweep to select and deliver system-initiated nudges — 0–3 conversation-starters pushed to the owner about what is unblocked, aging, stalled, or newly connected. Every nudge ends in a question; the skill proposes conversations, never executes work. |
recursive-spine: nudge
The digest reports; the nudge starts a conversation. This skill is the
initiative organ of the collaborative loop (#47): it may only propose,
shaped so that autonomy is structurally impossible — a nudge that cannot
end in a question to a human is dropped, whatever its rank.
Configuration (read, never assume)
From the invoking context or the private hive's nudges/config.md:
delivery destination (Slack DM, issue comment, or file), tracking issue,
ledger location, age thresholds. From the dialect note of the invoking
repo: board owner, repo set. Never hardcode any of these. Nudge state is
private-scope: ledger and config live in the private hive, never in a
public repo.
Inputs
- The sweep — run or receive a recursive-spine-digest sweep
(aging deferrals, stalled milestones, in-flight by lane,
assigned-but-untouched, honest denominators).
- Dependency reading (new sensing) — per repo, find items that became
unblocked, by two readings:
- Query (preferred): for issues with sub-issues (mechanics in
${CLAUDE_PLUGIN_ROOT}/reference/sub-issues.md, Read a tree), the
sequence head is the first open child in sub-issue order whose
earlier siblings are all closed. Verifiable structure.
- Prose (fallback): issues whose recorded sequencing ("sequenced
after…", "blocked by…", milestone ordering, lane position) names
predecessors that are now all closed — for sequences not yet
converted to sub-issues.
Cite the predecessor state in the nudge, and say which reading
produced the candidate.
- Pollen reading (new sensing) — pollen records that plausibly relate
to an open deferral. Every pair must cite why (shared mechanism,
named skill, same moment). No citation, no candidate.
- The ledger —
nudges/ledger.md in the private hive: every prior
nudge, its trigger, and its outcome.
Candidate shape — the safety gate
Every candidate is observation → why now → question:
#68 is next in the flagship lane (obs); the watches-itself milestone
opened and its roadmap predecessors closed this week (why now); want to
brainstorm it this week? (question)
Drop any candidate that cannot honestly take this shape.
Discipline rules (ledger-enforced)
- Never re-send an unanswered nudge unless its underlying state
changed since (issue edited, commented, relabeled, or a predecessor
closed after the nudge date).
- Declined stays declined unless the issue changed after the decline.
- Max 3 nudges per delivery. When candidates exceed 3, say so
("3 of N candidates").
- Empty week is stated, not padded: "no nudges this week — nothing
newly unblocked, nothing aged past threshold." The heartbeat stays
visible even when the content is empty.
Ranking
- Unblocked-and-next (concrete, actionable now; within this trigger,
query-derived heads outrank prose-derived ones — verifiable beats
inferred)
- Aging deferrals (oldest first)
- Stalled milestones
- Pollen↔deferral connections (fuzziest; earns rank as it proves precision)
Within a trigger, older first.
Delivery
Send the selected nudges to the configured destination. Footer always
carries the honest denominator ("swept N/M; X failed: reason") when any
repo failed. If the primary channel send fails, post the nudges as a
comment on the tracking issue prefixed nudge-delivery-failed: — the
heartbeat must stay observable when the channel isn't.
Delivery is two-part. A channel send made as the owner's own identity
notifies no one — Slack never alerts you to your own posts — so the
channel message is the record half and an attention ping is the push
half: one line, under 200 characters, no markdown, leading with count and
top nudge headline (e.g. "spine: 3 nudges — top: plumb-line v0.8.0 next;
see the delivery channel"). The ping mechanism is whatever the invoking runner provides
(push notification, routine completion notice) — never hardcode one. If
the runner has no ping mechanism, say so in the delivery footer rather
than failing. Empty weeks send no ping: the heartbeat stays visible in
the thread and ledger, but an empty week is not worth an interruption.
Ledger append (always, even on empty weeks)
Append to nudges/ledger.md: run timestamp, swept N/M, one line per nudge
sent (date | repo#issue | trigger | outcome: pending). If the previous
run's timestamp is more than one interval old, open the delivery with
"missed N scheduled runs."
Never
- Never execute, file, close, or edit work a nudge proposes — the owner's
reply starts that conversation elsewhere.
- Never auto-file pollen matches as issues in target repos (that is #38,
deliberately deferred).
- Never write nudge state to a public repo.
- Never depend on a Claude Code hook having fired (#71 is an adapter,
never the method).