Skip to content

feat: Spawn Drift detects drift but nothing regenerates — wire the self-heal PR #125

Description

@Jammy2211

Overview

Spawn Drift is a drift check with no generator behind it. The templates are declared a generated view, but the only thing that ever regenerates them is a human typing /spawn --apply. So the scheduled leg goes red, stays red, and is cleared by hand.

Both legs run identical code — the workflow has no trigger-dependent behaviour beyond the PR-only if: added in #118. The difference is when each runs relative to a human --apply:

date template force-synced dispatch run gap result
2026-07-13 11:08:46Z 11:09:02Z 16 s PASS
2026-07-27 19:30:29Z 19:30:48Z 19 s PASS

A leg fired seconds after the human stamped the templates cannot fail. Every green run in the workflow's history is one of those.

Plan

Mirror the lifecycle_drift.yml self-heal (#116), which solved the same shape of problem — an alarm-only check just emails a human once per push.

On schedule: regenerate and, if the tree differs, open a PR on the affected template repo rather than pushing. Do NOT copy lifecycle_drift's direct bot-push: these are force-synced generated views, so an automated push is a force-push to a published repo's main. A PR keeps the sanctioned-force-push exception a human act while removing the "nothing regenerates" gap — and #118 is the argument for a human seeing what is about to be published.

Detailed implementation plan

Affected Repositories

  • PyAutoMind (primary)

Branch Survey

Repository Current Branch Dirty?
./PyAutoMind main clean

Suggested branch: feature/spawn-drift-self-heal

Implementation Steps

  1. scripts/spawn.py — distinguish the two failure classes, which --check currently collapses into exit 1:
    • 0 clean
    • 1 content drift only → auto-fixable, safe to propose
    • 2 unsafe generation (UNMATCHED or canary hits) → a human decision, must NEVER be auto-PRed
      The distinction is the safety interlock: a canary hit means the generated tree contains instance content, so opening a PR would propose publishing a leak.
  2. .github/workflows/spawn_drift.yml — on schedule/workflow_dispatch, branch on that exit code. On 1: regenerate, push a stable spawn/auto-sync branch to each drifted template repo, open or update a PR. On 2: fail, no PR.
  3. Idempotence: a fixed branch name force-updated each run, so a weekly rerun refreshes the existing PR rather than opening a new one.
  4. Tests for the exit-code contract.

Key Files

  • scripts/spawn.pymain() exit path
  • .github/workflows/spawn_drift.yml
  • tests/test_spawn_template_contract.py

Known external dependency — flagging explicitly

Opening a PR on PyAutoMind-template / PyAutoMemory-template needs a token with write access to those repos; secrets.GITHUB_TOKEN is scoped to PyAutoMind only. The org's established cross-repo token is secrets.PAT_PYAUTOLABS (used by nightly-release.yml and PyAutoHands/release.yml).

Whether that PAT actually grants write to the two template repos cannot be verified from a local session — only a real run reveals it. The workflow therefore fails with an explicit, actionable message rather than silently doing nothing if the push or PR is refused.

Original Prompt

Click to expand starting prompt

draft/maintenance/pyautomind/spawn_drift_has_no_generator.md — filed during the #118 investigation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions