Skip to content

feat(extensions): native Babysitter turn handler - #551

Merged
kjgbot merged 1 commit into
mainfrom
feat/babysitter-native-handler
Sep 22, 2026
Merged

kjgbot merged 1 commit into
mainfrom
feat/babysitter-native-handler

Conversation

@AgentRelayBot

@AgentRelayBot AgentRelayBot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds the native Babysitter package the #550 handoff calls for, at extensions/babysitter. It is a schema-2 extension on software-factory whose 11 GitHub handlers each turn Cloud's normalized delivery descriptor into one cloud:babysitter-turn call:

f.capabilities.cloud.babysitterTurn.queue({ delivery: { deliveryId, provider: 'github', eventType, pullRequest: { owner, repository, number } } })
  • It sends no findings, prose, head SHA, label, session, lineage, relay agent, config, merge flag, or route. Cloud's capability adapter holds the verified authority, rereads the live PR (open, exact babysit label, head), and resolves the bound Codex session.
  • The only accepted result is { receiptId, status: 'queued' | 'duplicate' }, which completes the run as success. Rejections (policy refusals, in-doubt transport) fail the run once, with no retry or fallback. Any other receipt shape fails the run.
  • Input must be the exact descriptor. A raw webhook, unknown fields, a non-GitHub source, a malformed delivery ID, repo, PR number or head, or an eventType that doesn't match the handler's own subscription is refused before any call.
  • The default body (direct run) declines and never queues.
  • Manifest permissions are exactly what the feat(sdk): prepare pinned Babysitter catalog export #550 exporter requires: github, codex, no MCP, writes cloud:babysitter-turn, extends.handlers: true, no hooks. It holds no GitHub write authority.
  • This is not the legacy examples/babysitter (Claude review lenses, GitHub comments, merge-gate hook).

The contract was agreed over Agent Relay with babysitter-session-lineage-proposal, who owns Cloud core, Relay native-turn and RelayHistory receipts. They corrected two points, both applied: omit findings, and use the receipt queued|duplicate, with Cloud deduping by lineage plus live head so deliveryId is provenance only.

What this does NOT do

  • Does not weaken fix(sdk): fail closed on hosted extension dispatch #549. Hosted dispatch still refuses the handler with plugin_unsupported before either body runs. That is pinned by a test that goes through the real install, compose and execute path.
  • Cannot execute yet. The SDK Ctx has no capabilities, so the handler fails closed with does not provide the cloud:babysitter-turn write. Execution needs gate 8 / flows: AgentOptions has no permissions field in TypeScript, and it isn't enforced yet anywhere #442 isolation plus the Cloud capability adapter.
  • Not publishable as is. compat is ^2.0.26. The published @relayflows/surface@2.0.25 registry cannot route pull_request.labeled, .unlabeled or .ready_for_review (install refuses with plugin_event_unroutable). A surface release must come first.
  • No merge, npm publish, catalog enablement, or production change. Export follows docs/BABYSITTER-CATALOG-HANDOFF.md with path #extensions/babysitter, from the merged commit only. Rollout is not complete.

Evidence (files in evidence/babysitter-native-handler/)

  • typecheck.txt: npm run typecheck and npm run typecheck:tests, both Exit: 0.
  • tests.txt: new suite Tests 31 passed (31). Neighbouring suites (catalog export, compose, plugin-extension, authored-flow incl. the fix(sdk): fail closed on hosted extension dispatch #549 tests, preflight): Tests 219 passed (219).
  • mutation.txt: two mutations, each reverted, failing, restored byte-for-byte (sha256 matches), and passing again:
    1. Removing the event/subscription binding makes refuses an event for another subscription fail.
    2. Removing the capability guard makes the 3 fails closed on … tests fail. Without the guard the run still fails, just as a raw TypeError; the guard pins a clear refusal.
  • full-suite.txt: local full npm test has 51 failures in 23 files, none in the new suite. 17 of those files also fail at origin/main 607ac67 with this change stashed (38 failures). The 6 files that failed only in the full run pass in isolation on this branch (40/40). Causes are load and timing (5s timeouts, relayflowd lease expiry, ENOTEMPTY cleanup). CI is the authority.

The test suite uses the local surface, as CI does (npm install ./packages/surface --prefix packages/sdk --no-save --ignore-scripts).

🤖 Generated with Claude Code


Note

Medium Risk
New extension defines the Cloud turn boundary and strict input validation, but execution stays refused until gate 8 and the Cloud adapter ship; mis-validation could block turns once enabled.

Overview
Introduces the native Babysitter schema-2 flow extension at extensions/babysitter for Software Factory: eleven GitHub subscriptions each validate Cloud’s normalized delivery descriptor and issue a single cloud:babysitter-turn queue call with a minimal PR envelope (no head, session, findings, or GitHub writes). turn.ts fail-closes on schema drift, wrong subscription, or bad receipts; babysitter.flow.ts requires a runtime capabilities.cloud.babysitterTurn port and completes only on queued/duplicate receipts.

Does not turn on production behavior: hosted dispatch still hits plugin_unsupported (#549), today’s SDK has no capability field, and compat pins surface/sdk ^2.0.26 for labeled / unlabeled / ready_for_review routing. Direct runs decline without queuing.

Adds a 31-test SDK suite (compose, #549 refusal, #550 catalog export bytes, validation, capability guard) plus handoff doc updates and local evidence (typecheck, mutation checks, full-suite notes).

Reviewed by Cursor Bugbot for commit dcdc6bd. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Adds the native Babysitter extension at extensions/babysitter, replacing the handoff in #550: a schema-2 extension on software-factory whose 11 GitHub handlers each turn Cloud's normalized delivery descriptor into one cloud:babysitter-turn queue call. The handler sends no findings, head, label, session, lineage, or config; Cloud rechecks the live PR and bound session.

  • Only { receiptId, status: 'queued' | 'duplicate' } receipts complete the run; rejections and malformed input (raw webhook, unknown fields, wrong subscription, bad delivery ID/PR) fail once with no retry.
  • A direct run declines and never queues; permissions match exactly what the feat(sdk): prepare pinned Babysitter catalog export #550 exporter requires.
  • Not executable yet: hosted dispatch still refuses with plugin_unsupported, the SDK Ctx has no capabilities, and compat needs a surface release after 2.0.25 to route labeled, unlabeled, and ready_for_review.
  • Not the legacy examples/babysitter; this holds no GitHub write authority.
  • Adds 31 tests and evidence of typecheck, mutations, and suite runs.

Written for commit dcdc6bd. Summary will update on new commits.

Review in cubic

Add extensions/babysitter, a schema-2 extension on software-factory whose
eleven GitHub handlers turn Cloud's normalized delivery descriptor into one
cloud:babysitter-turn queue call:
f.capabilities.cloud.babysitterTurn.queue({ delivery }). It sends no
findings, head, label, session, lineage, or config. Unknown input, receipts
other than queued|duplicate, rejections, and a missing capability fail the
run. The manifest matches the #550 exporter permission shape.

#549's refusal is unchanged: hosted execution still refuses the handler
with plugin_unsupported. compat requires the surface release after 2.0.25.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Session-Id: 7d116c0d-6756-4905-ace7-1235559066ed
@coderabbitai

coderabbitai Bot commented Sep 22, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: de0419c1-123c-4b4c-960c-f90c45f2e9ba


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kjgbot
kjgbot merged commit d3ee3b5 into main Sep 22, 2026
6 checks passed
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.

2 participants