Skip to content

feat(loop): needs-human signal — label + notify.sh seam + cockpit "Needs you" strip (issue #99) - #147

Merged
robercano-ghbot merged 2 commits into
mainfrom
feat/issue-99-needs-human-signal
Jul 16, 2026
Merged

feat(loop): needs-human signal — label + notify.sh seam + cockpit "Needs you" strip (issue #99)#147
robercano-ghbot merged 2 commits into
mainfrom
feat/issue-99-needs-human-signal

Conversation

@robercano-ghbot

Copy link
Copy Markdown
Collaborator

Closes #99.

Adds a first-class needs-human signal so the loop pushes for the owner's attention instead of idling silently when it blocks on owner judgment.

What's in it

  • .claude/scripts/notify.sh <severity> <title> <body-line> [--kind K --target T --window S] — adapter-configured notifier seam. Reads the notify command from the active gates.json (GATES_FILE-aware). Empty command = silent no-op, exit 0 (offline/CI safe, same empty-means-skip convention as gates). Passes severity/title/body both positionally and as NOTIFY_SEVERITY/NOTIFY_TITLE/NOTIFY_BODY. Throttled one notification per (kind,target) per window (default 1800s, override via --window/$NOTIFY_THROTTLE_SECONDS), state in .claude/state/notify-throttle.json, degrades gracefully if state is missing/read-only. Also notify.sh --clear --kind K --target T.
  • .claude/scripts/needs-human.sh — the ONE shared needs_human_flag/needs_human_clear seam: idempotently creates + adds the needs-human label, calls notify, and posts a human-readable comment once per episode (first-transition-gated: comment only when the label was not already present, fail-open on read error). needs_human_clear removes the label when the condition clears. All best-effort (|| true) so notify/label failures never break the loop.
  • Wiring — all block-on-owner points route through the shared seam: loop-tick.sh attempt-budget + stall/resume escalations (refactored off the old ad-hoc gh label calls); merge-ready.sh flags PR-ready-for-review / approval-stale and clears pr-review + changes-requested on merge (also clears the origin issue's attempt-budget/stall via head-branch → issue-number); pr-feedback.sh flags changes-requested-addressed-awaiting-re-review and clears when a fresh CR arrives. loop-census.sh's pure counting invocation runs pr-feedback in a new PR_FEEDBACK_COUNT_ONLY=1 mode so counting stays side-effect-free.
  • gates.json — new notify key (empty = disabled) with an inline _notify_note documenting the contract + example commands (ntfy / notify-send / webhook curl), scaffolded in BOTH .claude/gates.json (downstream template) and .claude/self/gates.json (this repo's dogfooding; left empty — owner picks their default later). Signal-only semantics — the loop is not paused (per the issue recommendation; planned-removal already provides manual hold).
  • Cockpit — a "Needs you" strip at the very top of the dashboard (live data + fixtures), grouped by needs-human / awaiting-your-review (including no-CI-checks PRs), with an all-clear state when nothing needs the owner.
  • Label seedingneeds-human added to seed-issues.sh and the setup skill prose.

Tests

Offline, fixture-driven *.test.sh (no tokens/network): new notify.test.sh, needs-human.test.sh, merge-ready.test.sh, pr-feedback.test.sh; extended cockpit.test.sh, loop-tick.test.sh, loop-ceilings.test.sh. Cover empty-command no-op, fire-once-then-throttle, --window 0 edge, comment episode-gating, count-only side-effect-freedom, and the label add/remove sequences through the real scripts.

Gates & review

Self-adapter gates (GATES_FILE=.claude/self/gates.json build / lint / test) all green. Reviewed through the self-adapter's correctness (opus) and tests (sonnet) lenses, consensus=all — both APPROVE after one fix round (comment-spam gating + census read-only; the tests reviewer mutation-tested the new assertions).

🤖 Generated with Claude Code

robercano and others added 2 commits July 16, 2026 17:59
…strip (issue #99)

Consolidates the loop's ad-hoc needs-human escalations (attempt-budget, stall)
into one shared helper (needs-human.sh: needs_human_flag/needs_human_clear),
adds a throttled push-notification seam (notify.sh, empty command = offline
no-op), wires it into new block-on-owner points (PR ready for review /
re-approval needed in merge-ready.sh, CHANGES_REQUESTED-addressed-awaiting-
re-review in pr-feedback.sh) with clears firing on merge/re-dispatch, and
surfaces everything as a "Needs you" strip at the top of the cockpit
dashboard. Seeds the needs-human label alongside backlog/planned.
…#99 re-review)

Both reviewers rejected the original needs-human-signal work:

- needs_human_flag now gates the GitHub comment on a FRESH escalation
  episode, derived from whether the needs-human label is already present on
  the target (read via `gh pr/issue view --json labels` before mutating).
  Label add + throttled notify still run every call; only the comment is
  first-transition-only, so a persisting block-on-owner condition no longer
  spams a fresh comment every loop tick. Fails open (comment still fires) if
  the label read itself fails.
- pr-feedback.sh gains PR_FEEDBACK_COUNT_ONLY=1, which suppresses every
  needs_human_flag/needs_human_clear side effect while printing the identical
  TSV. loop-census.sh's feedback_prs= counter now sets this, so a read-only
  census can no longer mutate GitHub state; loop-tick.sh's real dispatch
  invocation is unchanged.
- merge-ready.sh's needs-human comment body no longer leaks the raw
  "SKIP:..." verdict token.
- cockpit.sh's "awaiting your review" strip now also includes PRs with no CI
  checks configured (previously silently omitted).

Added merge-ready.test.sh and pr-feedback.test.sh running the REAL scripts
(not fakes) against a stubbed bot-gh.sh, asserting the needs_human_flag/clear
gh-call sequence including the new comment-gating and count-only behavior.
Extended needs-human.test.sh (episode-gating scenarios), loop-ceilings.test.sh
(updated gh-call counts for the new label-presence read), and cockpit.test.sh
(no-checks PR coverage).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@robercano-ghbot
robercano-ghbot merged commit 13f1387 into main Jul 16, 2026
9 checks passed
@robercano-ghbot
robercano-ghbot deleted the feat/issue-99-needs-human-signal branch July 16, 2026 16:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Loop/cockpit: needs-human signal — label + push notification when the loop blocks on the owner

2 participants