Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Safe EPIC rebinding and native parent validation for active AutoForge runs

Open
#293 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
24/100
Issue type
Feature
Clarity
Clearly specified
Activity status
Active
Tech stack
github, python
Domain
backend, devtools

Research direction

Start with src/autoforge/cli.py, src/autoforge/validation.py, and src/autoforge/engine.py; trace run creation and persisted EPIC identity, then inspect the GitHub client and scheduler ownership, locking, and effect protocols referenced by the issue. Define the native-parent membership policy and safe standalone rebind boundaries before implementation. Done means the acceptance criteria are covered by offline tests, operator documentation is updated, and make check passes.

Written by the indexing model from the issue text.

Description

enhancement

Artifact: implementation-ready standalone issue for AutoForge's REMOTE run identity and recovery. Triggered by the live #257 / PR #279 run; no run state or worktree is changed by creating this issue.

Scope: standalone REMOTE run startup and safe EPIC rebinding; scheduler-owned runs require explicit, conservative handling. Related: #257 (incident), #255 (correct Public Alpha EPIC), #158 (incorrect recorded EPIC), #287 (restrict UPDATE_EPIC next issue to the EPIC's children), #177/#179–#183 (scheduler ownership, native graph, locks and claims). Priority: proposed High for integrity/recovery; maintainer to triage. Not automatically a Public Alpha launch gate.

Problem and reproduced example

A standalone REMOTE run of issue #257 was created with --epic https://github.com/iceboundrock/AutoForge/issues/158, although its GitHub-native parent is #255. The run af-20261022T070620Z-8542c2 has state under .autoforge/AutoForge-issue-257, is associated with PR #279 (autoforge/257), and has an unpushed FIX candidate d1e7fd179302f9f0df3380303bd1dc30f5d30d69. The original run has been kept intact, and its merge gate must remain closed for recovery. This is not a request to edit that run's state.json or restart it.

At the inspected implementation:

  • src/autoforge/cli.py requires run --epic URL --issue URL, but resume and unblock have no target-EPIC parameter.
  • src/autoforge/validation.py:validate_epic_and_issue verifies only that both URLs belong to the same repository, not that the issue is a native child of the selected EPIC.
  • src/autoforge/engine.py:new_run persists epic_url in AutoForgeState at creation. Subsequent phases consume this recorded identity.
  • UPDATE_EPIC can publish a progress comment and splice a managed roadmap section on state.epic_url, so a wrongly recorded EPIC can result in an authorized write to the wrong issue if a run is allowed to proceed after merge.
  • run --force discards/replaces existing nonterminal run state, not a supported migration. Direct JSON editing is unsafe because of persisted phase, effects, evidence and recovery protocols.

The current workaround is to retain the run, keep automatic merge disabled, stop at READY_FOR_MERGE and handle merge/EPIC reporting manually. The product needs a fail-closed prevention path and a supported migration path that preserve evidence.

Deliverables

A. Validate native parent/EPIC at run creation
  1. Before saving any new REMOTE run state or launching an agent, read and validate the repository identity, the target EPIC and issue, and the issue's GitHub-native parent through typed GitHubClient reads. Require full, unambiguous read-back; never infer membership from prose, issue references, labels, roadmap text or title.
  2. For a directly parented issue, require the parent to equal --epic, comparing canonical repository/issue identities. Reject a mismatch with a diagnostic naming the supplied EPIC, the observed parent and the corrected invocation.
  3. Specify and document a backward-compatible membership policy for existing sequential workflows that may use issues without a native parent, legacy task lists or explicitly supported EPIC references. Do not silently accept a mismatch. If a legacy exception is supported, it must be explicit, unambiguous, evidenced on GitHub and tested. Decide whether nested child issues are accepted for standalone runs or refused; do not accidentally change scheduler's direct-child contract.
  4. If parent lookup is unavailable, ambiguous or access-denied, fail closed before state creation; distinguish unsupported API/credential from no parent and wrong parent. Validate open/closed state and issue repository under the same verified identity rules.
  5. Use this checked binding for run --dry-run and ordinary run; dry-run must not persist data, create worktrees, launch providers or perform GitHub writes. Recheck mutable GitHub facts under the controller lock before committing the initial state to avoid a TOCTOU gap.
  6. Reuse the authoritative native graph/snapshot semantics of #179 where appropriate, and coordinate with #287 without duplicating its UPDATE_EPIC next-issue restrictions. Consider independent issue-parent changes after a run starts: never silently retarget a recorded run.
B. Safe operator-controlled EPIC rebinding for an existing run

Design and implement an explicit operation (illustrative UX; exact CLI shape to be decided and documented):

autoforge rebind-epic \
  --from https://github.com/iceboundrock/AutoForge/issues/158 \
  --to https://github.com/iceboundrock/AutoForge/issues/255 \
  --reason "Correct run binding for issue #257" \
  --dry-run

The operation must have all of the following properties:

  1. Explicit authority. Require operator intention, expected previous EPIC, new EPIC and a nonempty reason; tie the change to the existing state directory and exact current issue/run identity. Refuse stale expected-old values. Rebind only the EPIC identity, never the issue, PR, repository or code.
  2. Read-only preview. --dry-run displays old/new EPIC, observed native parent/membership, current phase, pending EPIC-scoped effects, worktree/PR identity and exact refusal/recovery actions. It makes no state, log, filesystem or GitHub writes.
  3. Safe phases and locks. Work under the existing L0 controller authority plus applicable L2/L1 locks per ADR 0008. Refuse if a controller/worker holds the run, if scheduler ownership/claims cannot be reconciled, or if the run is in a phase in which migration would cross a persisted external-effect boundary. Explicitly define permissible phases (e.g., a quiescent BLOCKED run or READY_FOR_MERGE, with no conflicting EPIC-scoped effects) rather than treating all phases as safe.
  4. Effect and recovery integrity. Inspect effect records (including K8 progress/roadmap), acceptance/operator actions, phase observations, persisted completion context, retries and replan transaction, launch/read context, and any immutable recorded identity or digest. Refuse unresolved, planned, sent or uncertain effects tied to the old EPIC unless a provably safe, tested migration rule exists. Never rewrite a sent GitHub effect, relabel ownership or erase evidence. Prefer refusal to speculative migration.
  5. Scheduler namespaces. A scheduler-owned issue's binding/claim/generation and the scheduler's graph are authoritative. Refuse automatic transfer between EPICs while a claim, active invocation, unsettled namespace, or scheduler journal exists. If support cannot be made provably safe in this issue, explicitly scope rebinding to standalone runs and document a separate scheduler migration workflow; do not bypass the scheduler root or ownership checks.
  6. Atomic, recoverable state update. With locks held, verify preconditions, preserve a bounded auditable record or snapshot of the prior state, commit the new binding with the existing atomic state persistence protocol, and record old/new URLs, issue/run identity, operator reason and decision in the run log. Crash/interruption must leave one valid, unambiguous binding. A repeat with the same target must be idempotent and visibly report already-applied; a conflicting repeat must refuse.
  7. No lifecycle reset. Preserve run ID, current issue and PR, branch, reviewed HEAD/base/merge-base, local worktree and unpushed FIX candidate, review findings, review/fix rounds, replan counters, loop/step budgets, validation evidence, configuration fingerprint, effect journal and operator approvals. Do not use run --force, hard reset, force push or reinitialize the run.
  8. Future steps use the new EPIC safely. The next prompt/read context and any eventual UPDATE_EPIC must be bound to the verified new parent; old EPIC read context must not be silently reused. If cached context cannot be safely invalidated without losing evidence, refuse the migration and explain why. Verify no write to the former EPIC occurs after a successful rebind.
  9. No hidden merge escalation. Rebinding must not change safety.allow_merge, grant --allow-merge, enter MERGE, or automatically publish/merge anything. For the concrete #257 example, rebinding (if supported) must preserve the unpushed d1e7fd1 worktree and the current review/effect protocol.
C. Operator documentation and diagnostics
  • Document corrected run --epic ... --issue ... examples, mismatch errors, dry-run, safe phases, refusals, rollback/recovery and the manual fallback when rebinding is not safe.
  • Make status expose the persisted EPIC unambiguously; consider a read-only warning if the current native parent differs, but do not silently repair it.
  • State the distinction between a GitHub native parent, a run's persisted epic_url, and scheduler ownership; changing an issue's parent on GitHub must not mutate an existing run automatically.

Acceptance criteria

  • Starting a standalone run with #257 and incorrect EPIC #158 refuses before writing state or launching an agent; the observed native parent #255 is named in the error.
  • A correctly parented issue is accepted; explicit legacy/no-parent and nested-parent policies are documented and tested; API unavailable/403/404/malformed/truncated parent evidence refuses safely without inventing a parent.
  • Fresh-run dry-run and real start agree on binding validation and do not leave a TOCTOU window before persistence.
  • A documented rebind dry-run of a quiescent, eligible existing standalone run explains the proposed change without changing a byte of state/log/journal/worktree or GitHub.
  • Applying an eligible rebind atomically changes only the intended durable EPIC binding and the explicitly defined audit metadata; it preserves PR/review/fix/effect identity and the unpushed candidate; repeat is idempotent.
  • Rebind refuses for active controller/worker, unsatisfied scheduler claims, uncertain or existing EPIC-target writes, stale expected-old EPIC, incomplete GitHub evidence, unsafe lifecycle phase and incompatible stored context, with actionable diagnostics and unchanged state.
  • Fault-injection tests cover crash/interruption at each persistence boundary, idempotent retry and concurrent resume/scheduler admission; no half-migrated state, duplicate publication or write to the wrong EPIC.
  • A resumed run after a successful permitted rebind reads the new EPIC and never sends progress/roadmap writes to the old one; no implicit merge enablement or counter reset.
  • Offline tests cover #257/#158 → #255 regression, parent drift, missing/nested parents, aliases/URLs, genuine denial vs no parent, pending K8/K9/operator actions, REVIEW/FIX/BLOCKED/READY_FOR_MERGE/UPDATE_EPIC boundary conditions and scheduler-owned namespaces.
  • Update relevant docs/usage.md, workflow/operator guidance and CLI help; make check passes in a proper Git checkout.

Out of scope

  • Modifying the currently BLOCKED #257 run, its worktree/candidate or PR #279 as part of implementing this issue.
  • Automatic repair on resume, unblock or status.
  • Changing the scheduler claim protocol, merge gate or UPDATE_EPIC next-issue eligibility (#287 owns the latter).
  • Broadening authority to migrate issue ownership or to rewrite previously published GitHub objects.

Delivery: ship a reviewed implementation with offline proofs and a documented recovery path. Prefer a conservative first release restricted to standalone runs over an unsafe general EPIC migration operation.

Dominant language
Python
Stars
0
Forks
0
Avg merge
5h 51m
Merged PRs (30d)
66

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from iceboundrock/AutoForge

All issues in iceboundrock/AutoForge

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.