Summary
start-goal --guided can classify a project as registry_without_goal even when an active-state file for the requested Goal id still exists in a legacy or alternate state location. The packet then proceeds with the normal connect_if_needed bootstrap and identity-onboarding route. This makes an operator-initiated reset ambiguous: an orphaned state is neither a connected Goal nor a clearly failed deletion, yet a later host session can create a new lane and Todo projection under the same Goal id.
This is separate from #4800. That issue proposes host-neutral paths and an explicit migration. This issue asks for a safety fence whenever registry and state artifacts disagree, including during the transition period.
Observed behavior
A Pi session trace on LoopX 1.0.5 showed this sequence:
- The project registry existed but had no entry for the requested Goal id.
- An active-state file for the same id still existed in the legacy state location.
start-goal --guided reported goal_found: false, state_file_exists: true, and connection_state: "registry_without_goal".
- The returned guided transaction still exposed
connect_if_needed (bootstrap) and fresh-agent registration commands. In this case the generated registration command also retained the legacy global runtime path.
- A subsequently started Pi session received the normal guided packet and created a fresh agent lane, Todos, and state writebacks for the same id. Later
diagnose reported healthy state, so the discontinuity was not surfaced.
The Pi extension itself does not autonomously call its startLoopx helper: that helper is reached from the /loopx command handler. Its session JSONL records the resulting synthetic guided packet, but not the slash-command invocation or source, which made attribution difficult. Regardless of the source of that command, the CLI packet should not treat an orphaned active-state candidate as ordinary absence.
Expected behavior
When no matching registry Goal exists but one or more state candidates exist for the requested id:
- Return a distinct, blocking connection state such as
orphaned_goal_state; do not return a bootstrap, agent-registration, Todo, quota, or host-activation continuation.
- Identify candidates using both the current and configured legacy state locations, without silently merging or copying them.
- Provide a preview-only, explicit resolution route: inspect, back up, then choose one of archive/delete/migrate/adopt. Any destructive action must require explicit confirmation.
- Once a Goal is deleted, archived, or migrated, revoke the former Goal instance for host bindings. A newly bootstrapped Goal with the same human-readable id must have a new opaque instance/generation id; guided packets, bindings, and quota calls should validate that instance id.
- Surface the mismatch in
diagnose until it is resolved.
Reproduction shape
- Create a valid project registry with no Goal entry named
sample-goal.
- Leave an
ACTIVE_GOAL_STATE.md for sample-goal in a legacy or alternate project state directory.
- Run:
loopx --format json start-goal --guided --project . \
--goal-id sample-goal --host-surface pi --goal-text "sample"
- Observe
registry_without_goal together with state_file_exists: true and a bootstrap-oriented continuation.
Acceptance criteria
- A regression test covers the registry-missing-goal + extant-state-file case.
- Guided output is non-mutating and has no activation path in that state.
- Resolution commands are explicit, previewable, backed up, and leave exactly one writable authority.
- Host bindings cannot continue or attach across a Goal deletion/rebootstrap merely because the Goal id is reused.
diagnose flags unresolved orphan state instead of returning a clean result.
No repository paths, user data, credentials, or raw session logs are required to reproduce this behavior.
Summary
start-goal --guidedcan classify a project asregistry_without_goaleven when an active-state file for the requested Goal id still exists in a legacy or alternate state location. The packet then proceeds with the normalconnect_if_neededbootstrap and identity-onboarding route. This makes an operator-initiated reset ambiguous: an orphaned state is neither a connected Goal nor a clearly failed deletion, yet a later host session can create a new lane and Todo projection under the same Goal id.This is separate from #4800. That issue proposes host-neutral paths and an explicit migration. This issue asks for a safety fence whenever registry and state artifacts disagree, including during the transition period.
Observed behavior
A Pi session trace on LoopX 1.0.5 showed this sequence:
start-goal --guidedreportedgoal_found: false,state_file_exists: true, andconnection_state: "registry_without_goal".connect_if_needed(bootstrap) and fresh-agent registration commands. In this case the generated registration command also retained the legacy global runtime path.diagnosereported healthy state, so the discontinuity was not surfaced.The Pi extension itself does not autonomously call its
startLoopxhelper: that helper is reached from the/loopxcommand handler. Its session JSONL records the resulting synthetic guided packet, but not the slash-command invocation or source, which made attribution difficult. Regardless of the source of that command, the CLI packet should not treat an orphaned active-state candidate as ordinary absence.Expected behavior
When no matching registry Goal exists but one or more state candidates exist for the requested id:
orphaned_goal_state; do not return a bootstrap, agent-registration, Todo, quota, or host-activation continuation.diagnoseuntil it is resolved.Reproduction shape
sample-goal.ACTIVE_GOAL_STATE.mdforsample-goalin a legacy or alternate project state directory.registry_without_goaltogether withstate_file_exists: trueand a bootstrap-oriented continuation.Acceptance criteria
diagnoseflags unresolved orphan state instead of returning a clean result.No repository paths, user data, credentials, or raw session logs are required to reproduce this behavior.