Skip to content

refactor(tui): adopt command shapes in session lifecycle slice (FEAT-023) - #5902

Merged
Hmbown merged 8 commits into
Hmbown:mainfrom
aboimpinto:feat/FEAT-023-adopt-command-shapes-in-tui-session-lifecycle-slice
Sep 6, 2026
Merged

refactor(tui): adopt command shapes in session lifecycle slice (FEAT-023)#5902
Hmbown merged 8 commits into
Hmbown:mainfrom
aboimpinto:feat/FEAT-023-adopt-command-shapes-in-tui-session-lifecycle-slice

Conversation

@aboimpinto

@aboimpinto aboimpinto commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Summary

FEAT-023 converts the TUI session lifecycle slice to portable command shapes while keeping the production files in codewhale-tui:

  • /branch
  • /compact
  • /fork
  • /load
  • /new
  • /purge
  • /save
  • /sessions
  • /tree

Baseline: current origin/main at a58ef2d52. The branch is eight signed commits ahead with no merge commits.

This PR:

  • adds the contract-owned CommandSessionLifecycleContext facet and portable lifecycle DTOs;
  • adds SESSION_LIFECYCLE with exact restricted-envelope projection;
  • keeps CommandCapabilities storage at u16 while allocating the next free identity (SESSION_LIFECYCLE, bit 13);
  • keeps /compact and /purge pure with CommandCapabilities::NONE and no host context bundle;
  • declares only SESSION_LIFECYCLE for the seven host-dependent handlers;
  • keeps concrete App, session manager, journal, picker, persistence, configuration, Work-state, and reset behavior inside SessionLifecycleAdapter;
  • registers all nine handlers through the public contextual dispatch seam;
  • retains the root session migration frontier for FEAT-024 through FEAT-026;
  • moves TUI-bound acceptance and persistence-regression suites outside the future movable groups/session directory;
  • makes portable handlers the single transition-gate authority and pins exact gate order/call counts.

Tracking: EPIC-006 / FEAT-023 in umbrella #5316.

Dependency boundary

Portable lifecycle handlers do not access concrete App, SessionManager, session journals, picker views, configuration, history cells, host callbacks, or service locators. Missing lifecycle authority fails closed with:

Command capability unavailable: session_lifecycle

The remaining staged dependencies are explicit:

  • FEAT-037 owns CommandResult, AppAction, synchronization mapping, and mode conversion;
  • FEAT-016 owns the shared registry bridge/import boundary needed before physical group moves;
  • FEAT-043 owns the final physical session-group move and keeps TUI acceptance/regression fixtures host-side.

No new crate dependency and no physical production-file move occur here. codewhale-command-contract remains independent of codewhale-tui.

Behavior and scope

  • Structural migration only: command names, aliases, registry order, parsing, check order, messages, actions, persistence behavior, and output remain unchanged.
  • Active-session and explicit-source forks use distinct portable receipts so explicit spawn_depth is mandatory rather than silently defaulted.
  • Out-of-scope session control, export, and structcopy commands remain for FEAT-024, FEAT-025, and FEAT-026.
  • No localization extraction (FEAT-036), shared outcome move (FEAT-037), or physical group move (FEAT-043).
  • No Gherkin expectations changed.

Testing

  • cargo fmt --all -- --check
  • strict Clippy for codewhale-command-contract and codewhale-tui with --all-targets --all-features --locked -D warnings
  • command-contract tests — 47 passed
  • portable lifecycle handlers — 8 passed
  • retained lifecycle regressions through public dispatch — 29 passed
  • adapter/public dispatch lifecycle coverage — 8 passed
  • restricted-envelope coverage — 1 passed
  • public dispatch seam — 2 passed
  • session acceptance scenarios with long-running-tests — 11 passed
  • full TUI library — 11,694 passed
  • migration fixtures — 56 passed; frontier remains [config, core, debug, session]
  • command-boundary fixtures — 8 passed
  • CI wiring tests — 11 passed
  • git diff --check
  • final-head upstream CI workspace matrix — Linux, macOS, Windows, lint, safety, integrations, DCO, OHOS, npm smoke, web checks, and security checks all passed; conditional jobs skipped as expected

The full TUI run used RUST_MIN_STACK=8388608, --test-threads=1, and removed the harness TMUX marker so terminal-policy tests observed their intended fixtures.

Checklist

  • This PR adds a new layer/module/abstraction — CommandSessionLifecycleContext replaces direct host access for exactly nine lifecycle handlers
  • Updated docs or comments as needed
  • Added or updated tests where relevant
  • TUI behavior is unchanged; existing acceptance scenarios pass
  • All eight commits carry DCO Signed-off-by trailers
  • Harvested/co-authored credit uses a GitHub numeric noreply address — N/A; no harvested/co-authored commits

No-Issue: FEAT-023 is tracked in umbrella issue #5316, which remains open for the remaining EPIC-006 work.

Paulo Aboim Pinto

Paulo Aboim Pinto added 7 commits September 5, 2026 22:27
…ECYCLE bit, and envelope slot

- One contract-owned lifecycle facet with exact-minimum synchronous delegates
  for the nine session lifecycle commands (D2); basic CommandSessionContext
  unchanged
- SESSION_LIFECYCLE = bit 13 (next non-conflicting bit after PLUGIN, D3) plus
  one independently optional envelope slot with duplicate-rejection builder
- Portable values: SessionSyncPayload, SessionBranchOutcome, SessionForkReceipt,
  SessionSaveReceipt, SessionNewReceipt, SessionArchiveReceipt, TreeBodyProjection
- 4 new contract tests: capability identity, object safety + full outcome
  transport, error/empty-state transport, envelope slot semantics

Generated with Claude Code

Signed-off-by: Paulo Aboim Pinto <paulo.aboim.pinto@gmail.com>
- Adapter implements CommandSessionLifecycleContext over App via the shared
  CommandHost (D4): branch hint/branch-to, tree projections, save, active and
  explicit fork, fresh session, load validation, picker open, archive/restore,
  prune - each preserving baseline check/mutation order and exact host-error text
- Bundle wired: thirteen slots, SESSION_LIFECYCLE exposure branch, test parts,
  all-capability projection
- 8 adapter tests (Tasks 3.2/3.4): transition blocking before I/O, save/fork
  history preservation, explicit-fork spawn depth, busy-work atomicity, draft
  blockers, load shape validation without state application, picker/archive/
  prune with active-session protection, tree projections for all states
- TUI lib suite green 11682/11682 (4-thread bounded, CI RUST_MIN_STACK)

Generated with Claude Code

Signed-off-by: Paulo Aboim Pinto <paulo.aboim.pinto@gmail.com>
- Pure registrations (D3): /compact and /purge declare NONE and compose their
  receipts/actions without any host context bundle (Tasks 4.1-4.2)
- Contextual registrations: /branch, /fork, /load, /new, /save, /sessions,
  /tree declare SESSION_LIFECYCLE only and own parsing, branch order, exact
  messages, guidance appends, and action mapping from portable receipts
  (Tasks 4.3-4.6)
- Missing lifecycle authority returns exactly the safe capability-unavailable
  error; no .expect(), no partial fallback
- sync_session_action maps the portable payload into the temporary SyncSession
  action (D6); from_command_mode made crate-visible
- 11 new composition/parity tests (2 pure + 9 lifecycle_portable); full TUI lib
  suite green 11693/11693 (4-thread bounded, CI RUST_MIN_STACK); locale parity PASS

Generated with Claude Code

Signed-off-by: Paulo Aboim Pinto <paulo.aboim.pinto@gmail.com>
…ispatch seam

- groups/session/mod.rs now registers /branch /compact /fork /load /new /purge
  /save /sessions /tree via ContextualCommand::from_contract (Tasks 6.1)
- Pure (/compact, /purge) and lifecycle-only declarations exact; out-of-scope
  control/export/structcopy entries remain legacy for FEAT-024/025/026
- Legacy lifecycle bodies removed from the nine leaves and session.rs
  (single authoritative portable path); feat015 legacy allowlist extended
- Public-seam tests prove exact capability declarations, pure dispatch,
  adapter reachability, and unchanged usage/error strings (Task 6.2)
- Migration fixtures + live gate PASS (frontier [config, core, debug, session]
  unchanged), boundary + CI-wiring + locale gates PASS (Tasks 6.3/6.4)
- Full TUI lib suite green 11666/11666 (4-thread bounded, CI RUST_MIN_STACK)

Generated with Claude Code

Signed-off-by: Paulo Aboim Pinto <paulo.aboim.pinto@gmail.com>
- Replace late-initialized locals with direct reads after scoped bundle drops
- Workspace clippy --all-targets --all-features -D warnings: exit 0

Signed-off-by: Paulo Aboim Pinto <paulo.aboim.pinto@gmail.com>
Signed-off-by: Paulo Aboim Pinto <paulo.aboim.pinto@gmail.com>
Signed-off-by: Paulo Aboim Pinto <paulo.aboim.pinto@gmail.com>
@aboimpinto
aboimpinto marked this pull request as ready for review September 5, 2026 21:40
@aboimpinto
aboimpinto requested a review from Hmbown as a code owner September 5, 2026 21:40

@Hmbown Hmbown left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind: approve-with-nits. Verified against main (a58ef2d52): CommandCapabilities is u16 with bits 0–12 taken (command-contract/src/handler.rs:20-46), so SESSION_LIFECYCLE = bit 13 is the next free bit and the widening preserves every existing identity — exactly as the PR body states. Scope is law-respecting by construction: command-contract/** + tui/src/commands/** only, no turn_loop.rs, no prompts/text.rs, and lifecycle handlers map into the existing SyncSession action rather than inventing a new authority. Full matrix green, 7/7 commits signed. Nit: the u16→u32 widening is premature while only one new bit is consumed — prefer deferring until bits actually run out, or isolate it in its own commit. The 29 regression + 11 acceptance tests through public dispatch are the right coverage shape.

Keep CommandCapabilities backed by u16 while SESSION_LIFECYCLE uses the available bit 13. The representation can be widened separately when the existing bits are exhausted.

Signed-off-by: Paulo Aboim Pinto <paulo.aboim.pinto@gmail.com>
@aboimpinto

Copy link
Copy Markdown
Contributor Author

Addressed the capability-storage nit in 52a53ce3a: CommandCapabilities remains backed by u16, and SESSION_LIFECYCLE uses the available bit 13. The speculative u32 widening is now deferred until the existing bits are exhausted.

Verified with cargo fmt --all -- --check, all 47 codewhale-command-contract tests, and strict Clippy for that crate with all targets and features.

Paulo Aboim Pinto

@Hmbown
Hmbown merged commit 41fecf8 into Hmbown:main Sep 6, 2026
37 of 38 checks passed
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.

2 participants