Skip to content

fix(session): preserve identity and stable instructions across headless resume - #926

Open
breedx wants to merge 7 commits into
mpfaffenberger:mainfrom
breedx:fix/upstream-structural-prompt-prefix
Open

fix(session): preserve identity and stable instructions across headless resume#926
breedx wants to merge 7 commits into
mpfaffenberger:mainfrom
breedx:fix/upstream-structural-prompt-prefix

Conversation

@breedx

@breedx breedx commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Resuming a saved headless conversation should preserve both the agent's identity and its durable instructions. Restore them together from structured message metadata so fresh processes continue the same conversation without rebuilding the prompt from changing hooks or rules, while temporary runtime instructions still expire.

Related upstream work

Change

Conversation identity

  • Add validated, optional runner-owned identity initialization before the conversation starts.
  • Carry versioned identity state on real ModelRequest.metadata, preserving unrelated metadata.
  • Restore centrally through set_message_history: a saved ID wins over a random process default; conflicting explicit identities fail before replacing active history.
  • Preserve identity through automatic history processing and manual compaction.
  • Keep cached agents when durable state is unchanged; invalidate them when restored identity or prompt state changes.
  • Enclose restoration in the existing /quick-resume and /load_context error boundaries, with tests for the interactive picker boundary too.

Durable prompt prefix

  • Persist the authored/plugin body, identity, project rules and prepared model instructions as structured session state.
  • Append temporary instructions only after durable preparation, never into hooks that may copy them into persisted user prompts.
  • Share preparation across construction, first turns and resumed subagents. Preserve existing first-turn main-agent and per-invocation subagent user transformations; reprepare on model or main/subagent scope changes.
  • Reset frozen state on history clear. Explicit /cd refreshes the project's durable contract without discarding history or identity; ordinary resume remains frozen.
  • Read saved prepared system text for compaction overhead and the context UI instead of replaying live hooks. Prepared rules/plugin contributions stay in the system bucket to avoid double-counting inputs after arbitrary hook transformations.

The existing command changes correct load-error handling and explicit project transitions, not new CLI functionality. Given the plugin-first guidance, please coordinate the preferred supported seams before landing, particularly with #832/#839.

Review structure

The existing seven commits remain intact, with no new code introduced by this consolidation. Review identity through f119b757, then the incremental prefix range f119b757..aeef90cc. The latter includes the structural prefix implementation and the reviewed project-transition/accounting correction. The combined head remains aeef90cc, targeting main from base ce1fe372 (0.0.827).

Validation

Local qualification used Linux / Python 3.13.13 and unchanged upstream dependencies in a dedicated environment. HOME/XDG were disposable, no credentials inherited, and socket connect/DNS/bind blocked, including subprocess fixtures. Model calls use local Pydantic FunctionModel fixtures.

  • Named-session and raw-pickle identity tests run through three fresh processes without caller-side identity repair. Both fail on unpatched upstream with three distinct IDs and pass with the patch; message counts increase 2 → 4 → 6.
  • Real headless execution → named persistence → restore across three fresh subprocesses keeps instruction bytes and identity stable despite changed hook/rule input.
  • Prefix/preparation controls on identity-only code: 11 failed, 1 passed, establishing the need for the prefix behavior.
  • Fresh review found stale project rules after /cd and live-hook accounting that underestimated saved instructions. Both added regressions fail before correction and pass at the reviewed head.
  • Combined focused identity/prefix/cache/preparation/loading/headless/accounting suite: 56 passed, with the existing quick-resume deprecation warning.
  • Consumer/token/core regression selection: 67 passed.
  • Broad local selection: 1646 passed, 1 failed, 4 warnings. The sole failure is the unchanged midnight-sensitive session-browser TODAY assertion, reproduced on unpatched upstream.
  • Changed-file Ruff lint, formatting and diff checks passed. A fresh reviewer independently reproduced controls and validation.

Current CI evidence

On the unchanged combined head, quality and Windows encoding checks passed. The full macOS job reported 7,871 passed, 1 failed, 14 skipped, 28 warnings. Its only failure is test_open_project_and_select_session: the fixture subtracts one/two hours from the current time, then requires TODAY, which fails immediately after midnight when both entries are correctly yesterday. This PR does not modify that test or hide the failure.

The CI job is labeled Python 3.13 but its test environment shows Python 3.14.7. Stream/CLI coroutine warnings reproduce locally on base; the existing autosave setter remains deprecated. CI warning categories were inspected, but not all have independent base controls. Marking this ready for review does not mean CI is green or authorize a merge.

Compatibility and boundaries

Metadata-free histories retain the current/default identity and rebuild the durable prompt once; the next checkpoint persists that state. No old identity or unsafe durable/temporary boundary is parsed from prose. Existing old messages are not rewritten or repaired, and session filenames, serialization formats and migration policy are unchanged.

Prompt hooks and project rules become durable conversation state: later edits do not silently replace the saved contract. Start/reset a conversation to adopt a new contract, or explicitly use /cd to refresh it for the selected project. Successful /cd intentionally changes the prefix. Model preparation is keyed by model and main/subagent scope; temporary suffixes and subagent execution context remain per-run.

No retry/history-custody fix, MCP change, dependency/package-version change, live-provider cache validation or measured cost-saving claim is included. This proposal preserves stable bytes; provider cache reuse remains provider-dependent.

Persist durable body, rules and model preparation in message metadata. Keep temporary policy outside the frozen prefix and share preparation across first turns and subagents. Invalidate cached agents when restored durable state changes.
…nstructions

Keep ordinary resume frozen, but let /cd intentionally rebuild the durable project contract without dropping history or identity. Read stored prepared system text for compaction and context accounting; avoid replaying live hooks or double-counting rules.
@breedx

breedx commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

The new resume regressions pass in upstream CI, but the full suite hits an existing midnight-sensitive session-browser assertion. I reproduced the same failure on unpatched ce1fe372; it is a wall-clock fixture issue, not a failure of persisted identity or structural prompt restoration.

The CI test environment is Python 3.14.7 despite its 3.13 label; local controls were Python 3.13.13. Deprecation/resource/coroutine warnings were inspected, but not all CI warnings have independent base controls. The full suite is not claimed green. #926 remains a dependent draft awaiting #925 acceptance and subsequent requalification.

@breedx breedx changed the title fix(prompt): preserve structural headless prefix across processes fix(session): preserve identity and stable instructions across headless resume Sep 8, 2026
@breedx
breedx marked this pull request as ready for review September 8, 2026 12:25
@breedx

breedx commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Consolidated the identity and structural-prefix proposals here so reviewers can evaluate reliable headless resume in one place. #925 is now closed as superseded; there is no longer a separate prerequisite PR. The head remains aeef90c and all seven commits are unchanged. This PR is ready for review, not a claim of green CI: the previously documented midnight-sensitive session-browser assertion remains the only recorded full-suite failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant