LearnNewsExamplesServices
Frontmatter
id11177
titlePersist active-PR-cycle-state in sandman_handoff for nightshift boots
stateClosed
labels
documentationenhancementaiarchitecturemodel-experience
assigneesneo-gemini-3-1-pro
createdAtMay 11, 2026, 2:58 AM
updatedAtMay 11, 2026, 6:23 AM
githubUrlhttps://github.com/neomjs/neo/issues/11177
authorneo-opus-4-7
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMay 11, 2026, 6:23 AM

Persist active-PR-cycle-state in sandman_handoff for nightshift boots

Closeddocumentationenhancementaiarchitecturemodel-experience
neo-opus-4-7
neo-opus-4-7 commented on May 11, 2026, 2:58 AM

Context

Empirical friction-pattern observed today (2026-05-11) within ~1 hour, twice:

  1. First collision: PR #11172 — Gemini opened parallel-PR for #11165 while her own PR #11167 was already in flight (APPROVED Cycle 2 at that point); closed-as-duplicate after my coordination A2A.
  2. Second collision: PR #11176 — Gemini opened parallel-PR for #11165 again from yet-another-fresh-session (57502eb2-...), while PR #11167 was APPROVED Cycle 4 by me; closed-as-duplicate after my coordination A2A.

Both PRs were strict subsets (~20%) of the canonical APPROVED #11167. The root cause is cross-session-PR-state-handoff context-loss: each Gemini nightshift boot doesn't surface "you have an open PR for ticket X at cycle state Y" — the agent re-derives the ticket as fresh work and opens a parallel implementation.

Pattern per [feedback_gemini_sunset_model_family_characteristic](agent-private memory; 12+ tickets across 8 days; RLHF "wrap up conversation" bias produces this systematically): prevention has plateaued; recovery substrate is the right investment.

The Problem

sandman_handoff.md is the established cross-session-state-handoff substrate (per A2A observability + Librarian + next-REM-cycle pickup). It currently tracks:

  • Sandman cycle activity
  • Memory Core state
  • Synthesized golden-path guidance
  • Last-cycle session summary

It does NOT currently track:

  • Active-PR-cycle-state per agent (e.g., "@neo-gemini-3-1-pro has PR #11167 open at Cycle 4, head SHA 32b914eb1, reviewDecision APPROVED")
  • Author-side cycle state (e.g., "@neo-opus-4-7 has PR #11173 open awaiting cross-family review, primary-reviewer @neo-gemini-3-1-pro")

Consequence: nightshift-boot agents have no persistence-layer signal about their own in-flight PRs, leading to:

  • Parallel-PR collisions (2 today)
  • Loss of in-flight substrate-evolution work when fresh-session PRs are strict subsets
  • Coordination overhead (cross-family A2A pings to surface the collision retroactively)
  • Resolves #N ambiguity when multiple parallel PRs claim the same ticket

The new lane-state: vocabulary substrate (graduated via PR #11167) addresses turn-state declarations but does NOT solve persistent-cross-session-state — those are different timescales of state.

The Architectural Reality

File:line surfaces:

  • ai/services/memory-core/lifecycle/SystemLifecycleService.mjs — runs the Sandman cycle that produces sandman_handoff.md
  • ai/daemons/services/SynthesizeGoldenPath.mjs (or wherever the handoff-writing service lives) — actually emits the markdown file
  • resources/sandman/sandman_handoff.md (or wherever the path resolves per aiConfig.handoffFilePath) — the consumed-by-next-session artifact
  • .agents/skills/session-sunset/references/session-sunset-workflow.md — could be updated to also write active-PR-state into the handoff at sunset time

Active-PR-state schema candidate (additive to existing sandman_handoff sections):

<h2 class="neo-h2" data-record-id="5">Active PR Cycle State (per agent)</h2>

<h3 class="neo-h3" data-record-id="6">@neo-opus-4-7</h3>

- PR #11173 ([URL]) — `lane-state: cross-family-review-queued` — primary-reviewer: @neo-gemini-3-1-pro — last-cycle: 1 (APPROVED at 00:49:38Z)
- PR #11166 ([URL]) — `lane-state: human-gate` — APPROVED Cycle 2 by @neo-gpt — awaiting operator merge

<h3 class="neo-h3" data-record-id="7">@neo-gemini-3-1-pro</h3>

- PR #11167 ([URL]) — `lane-state: human-gate` — APPROVED Cycle 4 by @neo-opus-4-7 — awaiting operator merge
- PR #11170 ([URL]) — `lane-state: human-gate` — APPROVED Cycle 1 by @neo-opus-4-7 — awaiting operator merge
- PR #11174 ([URL]) — `lane-state: review-routing-pending`

<h3 class="neo-h3" data-record-id="8">@neo-gpt</h3>

- PR #11175 ([URL]) — `lane-state: cross-family-review-queued` — primary-reviewer: @neo-gemini-3-1-pro

Source-of-truth: derivable via gh pr list --author <agent-login> --state open at session-sunset write time + gh pr view <N> for cycle state. Boot-time agents consume by reading the section + cross-referencing their own session-context.

The Fix

Two coordinated changes:

  1. SystemLifecycleService (or whichever service writes sandman_handoff.md): extend the writer to query gh pr list --author @<each-swarm-member> --state open at sunset time + emit a structured ## Active PR Cycle State section in sandman_handoff.md. Single-source-of-truth: GitHub PR state at sunset moment.

  2. session-sunset-workflow.md skill payload: add a Pre-Flight check at sunset-time that explicitly writes the active-PR-cycle-state into sandman_handoff.md if the daemon-driven write didn't fire (defensive belt-and-suspenders for harness-class differences).

  3. Boot-time pre-flight (new or extension of existing skill): when an agent starts a fresh session, the boot-time pre-flight should read sandman_handoff.md's ## Active PR Cycle State section, surface the agent's own in-flight PRs as a turn-zero context primer, and refuse to open NEW PRs for tickets that already have active PRs without explicit human override.

The recovery substrate is persistence at sunset + surfacing at boot — not yet-another-prevention rule on the agent.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
sandman_handoff.md ## Active PR Cycle State section gh pr list --author <agent> --state open at sunset time Emit structured per-agent active-PR cycle-state entries (PR# / URL / lane-state / primary-reviewer / cycle# / status) Section omitted if gh unavailable; section empty if no open PRs sandman_handoff format updated in learn/agentos/sandman-handoff-format.md (or wherever sandman_handoff is documented) Test that running 2+ sunset cycles with different open PRs produces correct section content
session-sunset-workflow.md skill payload This ticket Add Pre-Flight check at sunset that ensures active-PR-state is captured Skip if the daemon-driven write already covers it Skill payload internal Verify section present after sunset across both Claude Code and Antigravity harnesses
Boot-time pre-flight (new skill OR extension of existing) This ticket At session start, surface agent's own in-flight PRs + refuse to open NEW PRs for tickets that already have active PRs (without explicit human override) Soft warning if pre-flight skipped Skill payload + AGENTS.md §22 mailbox-check pairing Verify nightshift-boot scenario doesn't open parallel-PR for ticket with existing active PR

Acceptance Criteria

  • AC1: sandman_handoff.md writer extended to emit ## Active PR Cycle State section with per-agent entries (PR# / URL / lane-state / primary-reviewer / cycle# / status)
  • AC2: Sandman cycle test verifies the section is emitted with correct structure when test PRs are open
  • AC3: session-sunset-workflow.md skill payload updated with active-PR-state-capture Pre-Flight
  • AC4: Boot-time pre-flight (new or extension) surfaces agent's own in-flight PRs as turn-zero context primer — [DEFERRED to #11179] (scope-decoupled during PR #11178 Cycle 1→2 to ship persistence-layer foundation first; follow-up ticket #11179 captures AC4+AC5 as standalone implementation lane)
  • AC5: Boot-time pre-flight refuses to open NEW PRs for tickets that already have active PRs from the same agent (configurable override flag) — [DEFERRED to #11179] (scope-decoupled during PR #11178 Cycle 1→2; see AC4)
  • AC6: Documentation updated in learn/agentos/sandman-handoff-format.md (or wherever the format is canonically documented; create file if needed)
  • AC7 (verification — post-merge): Empirical: after merge, observe at least 7 nightshift-boot cycles across all 3 agents (Claude / Gemini / GPT) with zero new parallel-PR collisions

Out of Scope

  • Real-time multi-agent PR-state synchronization mid-session — focus is sunset-to-boot persistence, not in-session race detection
  • Refactoring Sandman cycle architecture broadly — bounded extension of existing handoff writer
  • PR-state-tracking for external (non-swarm) contributors' PRs — focus is core-swarm @neo-opus-4-7 / @neo-gemini-3-1-pro / @neo-gpt
  • Hierarchical-PR-graph relationships (epic ↔ sub-PR) — different concern; handled by existing native-edge-graph linkage
  • Auto-detecting parallel-PR collisions retroactively across all GitHub — focus is preventing them at-source via boot-time pre-flight

Avoided Traps

  • Generic LLM "prevention rule" expansion — e.g., "always check for existing PRs before opening new one". Rejected because the Gemini sunset model-family-characteristic memory shows prevention has plateaued across 12+ tickets / 8 days. The fix has to be at PERSISTENCE + SURFACING layer (recovery substrate) not at agent-discipline layer (which doesn't survive context-loss).
  • Memory Core schema mutation for active-PR-state — rejected per Discussion #11171 Option C-prime/D' resolution: don't mutate add_memory schema for lifecycle state; use existing handoff substrate instead.
  • GitHub Projects auto-sync as the persistence layer — rejected because sandman_handoff.md is already the canonical cross-session state-handoff artifact + adding another substrate would create state-divergence risk.
  • Tighter lane-state: vocabulary as solo solution — rejected because lane-state addresses turn-state (intra-session) not cross-session persistence. Both are needed; this ticket complements the lane-state work, doesn't replace it.

Related

  • PR #11167 (URL) — APPROVED Cycle 4; graduates Discussion #11171's Option C-prime/D' lane-state vocabulary; intra-session turn-state primitive that this ticket complements
  • PR #11172 (URL) — CLOSED as duplicate; empirical anchor #1 for this friction
  • PR #11176 (URL) — CLOSED as duplicate; empirical anchor #2 for this friction (within ~1 hour of anchor #1)
  • Discussion #11171 (URL) — Helpful-Assistant family substrate-evolution; lane-state vocabulary graduation source
  • Discussion #11168 (URL) — Friction → Gold meta-mechanism Discussion; CLOSED as duplicate of #11171
  • AGENTS.md §22 — Mailbox Check Protocol; this ticket's AC4 (boot-time pre-flight) extends the turn-start invariant
  • AGENTS.md §14 — Sunset Protocol; this ticket's AC3 extends the sunset workflow

Origin Session ID

c2912891-b459-4a03-b2af-154d5e264df1

Handoff Retrieval Hints

  • query_raw_memories(query="cross-session PR state handoff sandman parallel PR collision nightshift boot")
  • ask_knowledge_base(query="sandman_handoff.md active PR cycle state persistence")
  • Git commit-range anchor: git log --oneline --since="2026-05-11 00:30Z" --until="2026-05-11 01:00Z" -- ai/daemons/services/
tobiu closed this issue on May 11, 2026, 6:23 AM
tobiu referenced in commit 8457f94 - "feat(ai): persist active PR cycle state in sandman_handoff for nightshift boots (#11177) (#11178) on May 11, 2026, 6:23 AM