LearnNewsExamplesServices
Frontmatter
id12851
titleSunset: agents self-refresh own clone (dev pull + config migrate)
stateClosed
labels
documentationenhancementaimodel-experience
assigneesneo-fable
createdAtJun 10, 2026, 8:40 PM
updatedAtJun 10, 2026, 11:09 PM
githubUrlhttps://github.com/neomjs/neo/issues/12851
authorneo-fable
commentsCount2
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 10, 2026, 11:09 PM

Sunset: agents self-refresh own clone (dev pull + config migrate)

Closed v13.0.0/archive-v13-0-0-chunk-17 documentationenhancementaimodel-experience
neo-fable
neo-fable commented on Jun 10, 2026, 8:40 PM

Sunset: agents self-refresh own clone (dev pull + config migrate)

Context

Operator friction report (@tobiu, 2026-06-10 night-shift boot): after tonight's convergent team sunset, none of the agents refreshed their repos — the operator had to walk N per-agent clones manually (switch to dev, pull, refresh config files). Direct quote of the desired behavior: "switch to dev branch (not inside a worktree), pull, update config files (e.g. via ai/scripts/setup/initServerConfigs.mjs)".

Operator explicitly requested exactly ONE agent file this ticket; claim was broadcast via A2A ([lane-claim], @neo-fable, 2026-06-10T18:37Z) before drafting. Converged by operator directive — no fan-out (lead-role Guard B Level 1 satisfied).

Live latest-open sweep: checked the latest 40 open issues via the github-workflow MCP at 2026-06-10T18:35Z; no equivalent found. Historical sweep: grep over resources/content/issues/ + KB semantic sweep (refs #11731/#11788/#11790/#11791/#12650 reviewed) — closest lineage is #11013 and #12650, both CLOSED and both distinct (see Related).

Meta-skill check (§1b): change is confined to the references/ Atlas payload (session-sunset-workflow.md); zero bytes added to the top-level SKILL.md router or any turn-loaded substrate — adheres to Progressive Disclosure.

The Problem

.agents/skills/session-sunset/references/session-sunset-workflow.md Step 1 (Codebase Synchronization) still encodes a 2-class harness taxonomy that has drifted from deployment reality:

  • "Shared Checkout (Antigravity/Gemini)"git checkout dev && git pull origin dev (no config migration).
  • "Isolated Worktree (Claude Code)" → push HEAD only; primary-checkout staleness is handled by an operator-reminder probe (#11013): the agent computes BEHIND and asks the operator to run the pull + initServerConfigs.mjs --migrate-config manually.

Today's topology is per-agent dedicated clones (each named maintainer owns a full clone; worktrees are created per-PR inside them). A per-agent clone matches neither taxonomy branch cleanly, so at sunset agents leave their clones on stale dev (or parked on a PR branch) with stale gitignored config.mjs overlays. The next session's MCP servers boot before the agent's first turn (Step 1's own rationale, line 54), so they boot from pre-merge code + stale config — and the operator is left manually refreshing N clones between shifts.

The empirical anchor is tonight's convergent sunset (Origin Session ID below): the sunset executed cleanly per protocol, and the protocol itself never instructed any agent to refresh its own clone.

The Architectural Reality

  • session-sunset-workflow.md:52-55 — Step 1 harness-name taxonomy (Shared Checkout vs Isolated Worktree).
  • session-sunset-workflow.md:57-86#11013 staleness probe: detection is agent-side, execution is operator-side (reminder block, line 82, including the --migrate-config step added via #12650's scope).
  • ai/scripts/setup/initServerConfigs.mjs:38MIGRATE_FLAG = '--migrate-config'; idempotent Tier-1 import materialization (verified at source). A git pull alone updates config.template.mjs but NOT the gitignored config.mjs operator-overlay daemons/servers actually read — the flag closes that gap.
  • Mechanical checkout-class detection: git rev-parse --git-dir equals git rev-parse --git-common-dir in a primary clone; they diverge inside a linked worktree (verified live in a per-agent clone: both return .git). This replaces harness-name guessing with a git-native predicate.

The Fix

Restructure Step 1 around the mechanical predicate instead of harness names:

if [ "$(git rev-parse --git-dir)" = "$(git rev-parse --git-common-dir)" ]; then
    # PRIMARY CLONE (per-agent dedicated clone OR shared checkout)
    # Pre-condition: PR-branch work already committed + pushed (existing Step 1 mandate)
    [ -z "$(git status --porcelain)" ] || { echo 'dirty tree — skip refresh, surface in handover'; }
    git switch dev
    git pull origin dev
    node ai/scripts/setup/initServerConfigs.mjs --migrate-config
else
    # LINKED WORKTREE: keep existing behavior unchanged
    # (push HEAD + #11013 primary-checkout staleness probe / operator-reminder block)
    :
fi

Prose requirements for the rewritten Step 1:

  1. Primary-clone branch (new): porcelain-clean guard → git switch devgit pull origin devnode ai/scripts/setup/initServerConfigs.mjs --migrate-config. Any failure (dirty tree, switch/pull/script error) is surfaced in the Step 3 handover comment and the final sunset payload — refresh is best-effort; a refresh failure must never block sunset completion.
  2. Linked-worktree branch: existing push-HEAD discipline + #11013 probe retained verbatim (still correct there — a worktree cannot switch to dev while the primary holds it).
  3. The old "Shared Checkout (Antigravity/Gemini)" branch dissolves into the primary-clone branch — gaining the previously missing --migrate-config step.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
session-sunset-workflow.md Step 1 (consumed by all agent families at sunset) .agents/skills/session-sunset/references/session-sunset-workflow.md Agent self-refreshes its primary clone (switch dev + pull + config-migrate) via checkout-class predicate Refresh failure → handover note; sunset proceeds The workflow doc itself Operator report 2026-06-10; #11013/#12650 lineage; initServerConfigs.mjs:38 flag verified

Decision Record impact

none (no ADR governs the sunset protocol). Aligned-with #11013's Shape A/B framing: this is Shape B's completion (agent-side discipline), Shape A (daemon primary-dev-sync task) remains the long-term automation.

Acceptance Criteria

  • Step 1 taxonomy rewritten from harness-name classes to the mechanical checkout-class predicate (git rev-parse --git-dir vs --git-common-dir).
  • Primary-clone branch executes: porcelain-clean guard → git switch devgit pull origin devnode ai/scripts/setup/initServerConfigs.mjs --migrate-config; failures surface in handover, never block sunset.
  • Linked-worktree branch behavior (push HEAD + #11013 operator probe) retained unchanged.
  • The dissolved shared-checkout path's pull now includes --migrate-config (config freshness, not just code freshness).
  • Implementer consults create-skill authoring guide before editing the skill payload; change stays in references/ (no SKILL.md router bloat).
  • Substrate Accretion Defense: net loaded-bytes ≈ neutral (taxonomy rewrite replaces existing prose); retirement trigger declared in-file: when the daemon-driven primary-dev-sync periodic task (Shape A, #11013 follow-up) ships in the Orchestrator, the agent-side refresh step compresses to a trigger note.

Out of Scope

  • Shape A daemon automation (primary-dev-sync periodic task in Orchestrator.mjs) — long-term path, separate ticket post-#11009 lineage.
  • Boot-side refresh (AGENTS_STARTUP.md) — too late by design: MCP servers initialize before the agent's first turn; sunset is the correct window.
  • Worktree bootstrap config gaps — #12808 (sibling, distinct surface).
  • Step 2 sandman ownership — shipped via #12650.

Avoided Traps

  • Boot-time refresh instead of sunset-time: rejected — servers boot pre-first-turn, so a boot-time pull cannot fix what the servers already loaded. Sunset is the natural Operator Synchronization Point (rationale already codified at line 86).
  • Daemon-only solution now: rejected — Shape A depends on Orchestrator lineage and ships nothing tonight; agent-side discipline costs zero infra and lands immediately. Shape A supersedes later (retirement trigger in AC6).
  • Unconditional git checkout dev: rejected — breaks linked worktrees (dev is held by the primary; the original #11013 concern).
  • Auto-stash dirty trees: rejected — destructive-adjacent at an unattended boundary; porcelain-clean guard + handover surfacing is the safe shape.

Related

  • #11013 (CLOSED) — Shape B operator-reminder probe; this ticket moves execution agent-side.
  • #12650 (CLOSED) — Step 2 sandman prohibition + --migrate-config in the reminder text; this ticket makes the agent run it.
  • #12808 (OPEN) — bootstrapWorktree BOOTSTRAP_CONFIGS gap (sibling config-freshness surface).
  • Epic #12065 — Orchestrator-as-SSOT lineage for the eventual Shape A daemon task.

Origin Session ID: 5000ac5e-dabb-4f39-8a5c-e8ba55133f3d (the 2026-06-10 convergent sunset that surfaced the gap; filed by its successor session)

Retrieval Hint: "session-sunset repo self-refresh initServerConfigs migrate-config checkout-class predicate"

tobiu referenced in commit 583593f - "feat(session-sunset): agents self-refresh own clone at sunset (#12851) (#12867) on Jun 10, 2026, 11:09 PM
tobiu closed this issue on Jun 10, 2026, 11:09 PM