Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/source-control/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "source-control",
"version": "0.13.3",
"version": "0.13.4",
"description": "Git and GitHub delivery workflow: /commit (Conventional Commits + Co-Authored-By trailer via safe heredoc mechanics), /pull-request (prep, create, CI monitoring, review-comment triage, merge, CI-log fetch), /babysit-prs (self-pacing fleet loop — safe by default; opt-in worker/autopilot tiers add gate-checked merge and thread resolution behind a deterministic Python engine), /worktree (create, status, cleanup, audit for parallel-session isolation), /setup (check the effective commit-subject / PR-title convention and babysit-prs config, or apply — interview the repo and write the tracked convention config), and /resolve-conflicts (intent-first merge/rebase conflict resolution with a semantic-conflict sweep — never --abort). The commit-subject / PR-title convention is configurable per repo via a tracked .claude/source-control.md config written by a re-runnable setup skill; Conventional Commits is the default when no convention is declared.",
"author": {
"name": "Melodic Software",
Expand Down
19 changes: 19 additions & 0 deletions plugins/source-control/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,25 @@
All notable changes to the `source-control` plugin are documented here. Format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning.

## [0.13.4]

### Fixed

- **`babysit-prs` dynamic `/loop` wakeups now map `recommended_cadence` to a concrete
`ScheduleWakeup.delaySeconds` instead of falling back to the generic `/loop` heuristic.** The
snapshot engine emits `recommended_cadence` (`reference/cadence.md`: active / normal / quiet /
idle) and `reference/loop.md` §5.3 told the orchestrator to "derive the wake interval" from it,
but never gave the string-to-seconds translation — so orchestrators silently fell back to the
generic `/loop` skill's own "lean 1200–1800s" fallback-heartbeat range, overriding the domain
skill's tighter adaptive-cadence contract and leaving PRs with pending CI or blocking feedback
unchecked 4–5x longer than intended. §5.3 now carries a deterministic mapping table
(`active`→300, `normal`→900, `quiet`→3600, `idle`→3600) and states plainly that this signal
ALWAYS wins over the generic heuristic whenever a snapshot supplies it — in babysit dynamic mode
the `ScheduleWakeup` delay is the primary cadence signal, not a fallback heartbeat. The `idle`
row is documented as a ceiling: `ScheduleWakeup` clamps `delaySeconds` to `[60, 3600]`, so
cadence.md's daily `idle` intent truncates to the 3600s hourly ceiling — a genuine daily cadence
needs the durable `/schedule` cron mechanism, not a single-session `/loop` wakeup.

## [0.13.3]

### Fixed
Expand Down
27 changes: 24 additions & 3 deletions plugins/source-control/skills/babysit-prs/reference/loop.md
Original file line number Diff line number Diff line change
Expand Up @@ -362,9 +362,30 @@ git checkout "$PARKING_BRANCH"
At the end of each iteration, schedule the next wake. Cadence has one owner: the engine
recommends, this loop schedules.

**Engine-backed runs (Python present):** derive the wake interval from the snapshot's
`recommended_cadence` — `active` 5 minutes, `normal` 15 minutes, `quiet` hourly, `idle` daily —
per [cadence.md](cadence.md)'s states and thresholds.
**Engine-backed runs (Python present):** the snapshot's `recommended_cadence` is the cadence
signal — map it directly to a concrete `ScheduleWakeup.delaySeconds`. The states behind each value
live in [cadence.md](cadence.md); this table owns the seconds:

| `recommended_cadence` | `ScheduleWakeup.delaySeconds` |
|-----------------------|-------------------------------|
| `active` | 300 |
| `normal` | 900 |
| `quiet` | 3600 |
| `idle` | 3600 (ceiling — see caveat) |

**This mapping ALWAYS wins** over the generic `/loop` skill's own delay-picking heuristic whenever
a snapshot supplies `recommended_cadence`. Read the field out of the snapshot/state JSON and
schedule from this table — do not fall back to the generic skill's "lean 1200–1800s" range. In
babysit dynamic mode the `ScheduleWakeup` delay **is** the primary cadence signal, not a fallback
heartbeat sitting behind some other armed wake event, so the generic skill's heartbeat framing does
not apply here: an `active` cycle schedules at 300s, never 1200–1800s.

**Idle ceiling (a true daily cadence cannot run in single-session `/loop`).** `ScheduleWakeup`
clamps `delaySeconds` to `[60, 3600]`, so cadence.md's `idle` = daily (86400s) truncates to the
3600s ceiling — the same wake interval as `quiet`. This is a documented limitation, not a silent
truncation: within `/loop`, `idle` and `quiet` both wake hourly. A genuine daily babysit cadence
needs the durable `/schedule` cron mechanism (a scheduled routine on a real cron interval), not a
single-session `/loop` wakeup — reach for `/schedule` when that is what is wanted.

**Python-free degrade ladder** (no snapshot available this iteration):

Expand Down
Loading