prometeu-studio/discussion/workflow/plans/PLN-0037-project-local-studio-state-store-and-restoration.md

218 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: PLN-0037
ticket: studio-project-local-studio-state-under-dot-studio
title: Project-local Studio state store and restoration
status: done
created: 2026-04-04
completed: 2026-04-04
tags: [studio, project-session, project-state, persistence, dot-studio, shell, layout, setup]
---
## Objective
Implement the first accepted wave of project-local Studio state persistence under `.studio/`, using a single-file project-session-owned store that restores setup, shell organization, and editor tabs for a project.
## Background
DEC-0016 normatively locks the following:
- project-local Studio state must live under `.studio/` in the project root;
- the main store must be owned by `StudioProjectSession`;
- the main store must start as a single file;
- wave 1 must include project-local setup, shell layout, open shell/workspace state, and editor restoration;
- project-local activity must remain outside the main store;
- the policy is read on project-session open, restore on shell mount, and save on shell/project close;
- missing or invalid persisted state must fall back to safe defaults without blocking project open.
The current codebase already has a `StudioProjectSession` boundary plus a `MainView` shell and an `EditorWorkspace` with in-memory tab/session state, but it has no project-local persistence contract for those concerns.
## Scope
### Included
- Propagate DEC-0016 into Studio specifications.
- Introduce a project-session-owned single-file state store under `.studio/`.
- Load project-local setup when a project session opens.
- Restore shell layout and open shell/workspace state when the project shell mounts.
- Restore editor open tabs and active tab from project-local persisted state.
- Save the main project-session store when the shell or project session closes.
- Fall back to default values when persisted state is absent, unknown, or invalid.
- Add tests for store parsing, fallback behavior, session ownership, shell restoration, and editor tab restoration.
### Excluded
- Project-local activity persistence changes.
- General autosave or global incremental persistence for the main store.
- Multi-file store layout under `.studio/`.
- New settings UI for project-local setup editing.
- Persistence of ephemeral hover state, derived cache, heavy logs, or recomputable operational output.
## Execution Steps
### Step 1 - Propagate DEC-0016 into Studio specs
**What:** Add normative spec coverage for the project-local Studio state store and its wave-1 boundaries.
**How:** Update the existing shell and editor specs, and add a dedicated Studio persistence spec if needed, so the repository explicitly states:
- `.studio/` is the project-local root for the main Studio state store;
- `StudioProjectSession` owns load/save lifecycle for the store;
- the store begins as a single file;
- wave-1 categories are `projectLocalSetup`, `shellLayout`, `openShellState`, and `editorRestoration`;
- `project-local activity` is excluded from the main store;
- read/restore/save policy and default fallback behavior are normative.
The preferred propagation shape is:
- update [`docs/specs/studio/1. Studio Shell and Workspace Layout Specification.md`](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/specs/studio/1.%20Studio%20Shell%20and%20Workspace%20Layout%20Specification.md) for shell/session ownership and restore/save timing;
- update [`docs/specs/studio/5. Code Editor Workspace Specification.md`](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/specs/studio/5.%20Code%20Editor%20Workspace%20Specification.md) to replace the current “no cross-session tab restoration” rule with the accepted wave-1 restoration contract;
- add a new dedicated spec such as [`docs/specs/studio/8. Project-Local Studio State Specification.md`](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/specs/studio/8.%20Project-Local%20Studio%20State%20Specification.md) to hold the store schema boundary and exclusions.
**File(s):**
- `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/specs/studio/1. Studio Shell and Workspace Layout Specification.md`
- `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/specs/studio/5. Code Editor Workspace Specification.md`
- `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/specs/studio/8. Project-Local Studio State Specification.md`
- `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/specs/studio/README.md` if the new spec must be indexed
### Step 2 - Define the project-session state store contract and single-file codec
**What:** Create the main persisted-state model and the single-file read/write boundary used by `StudioProjectSession`.
**How:** Introduce a small persistence module or package in `prometeu-studio` that defines:
- a versioned root DTO for the main state file;
- wave-1 category DTOs for `projectLocalSetup`, `shellLayout`, `openShellState`, and `editorRestoration`;
- a file path convention under `.studio/`;
- loader/writer logic that returns safe defaults when the file is absent, unreadable, schema-incompatible, or invalid.
The implementation must keep `project-local activity` out of this file and must not broaden the schema to cache-like or transient UI data.
**File(s):**
- `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/main/java/p/studio/projectsessions/`
- a new package for state persistence such as `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/main/java/p/studio/projectstate/`
- corresponding test files under `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/test/java/p/studio/`
### Step 3 - Extend StudioProjectSession to load setup and expose restorable state
**What:** Move the main store lifecycle into the project-session boundary.
**How:** Update `StudioProjectSession` and `StudioProjectSessionFactory` so opening a project session:
- loads the main store from `.studio/`;
- exposes the loaded state to shell/workspace consumers through explicit accessors or a dedicated session-owned state service;
- makes project-local setup available before workspace-specific UI mounts.
The session boundary must remain the owner of the persistence lifecycle; `MainView` and workspaces may consume the state but must not redefine load semantics.
**File(s):**
- `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java`
- `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java`
- any new project-session-owned state service under `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/main/java/p/studio/projectsessions/` or `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/main/java/p/studio/projectstate/`
### Step 4 - Restore shell layout and open shell/workspace state from the session store
**What:** Apply persisted shell organization when the project shell mounts and capture it again when the shell closes.
**How:** Update `MainView` and any shell controls it owns so they can:
- restore the selected/open workspace state from the session store instead of hardcoding the default assets workspace when persisted state exists;
- restore accepted shell layout properties such as splitter positions or equivalent shell-level geometry once the relevant shell surfaces are mounted;
- collect the latest shell state before the shell or project session closes so `save on close` persists the canonical snapshot.
If a specific shell surface does not yet expose restorable layout state, introduce the minimal shell-owned API needed to read/write that state without making the shell controls own persistence themselves.
**File(s):**
- `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/main/java/p/studio/window/MainView.java`
- shell controls under `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/main/java/p/studio/controls/shell/`
- application/window close wiring where the current Studio shell lifecycle is finalized
### Step 5 - Restore editor open tabs and active tab through an editor-owned snapshot contract
**What:** Persist and restore the editor workspaces accepted wave-1 restoration state.
**How:** Refactor the editor workspace so it can:
- export a pure restoration snapshot containing open tab paths and active tab path;
- accept a restoration snapshot when the workspace mounts under a project session;
- reopen supported files through `prometeu-vfs` using those persisted paths;
- fall back safely when a previously open file no longer exists or is no longer supported;
- preserve the active-tab choice when restoration succeeds.
This step must not broaden into persistence of editor-local transient data beyond what DEC-0016 accepts.
**File(s):**
- `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWorkspace.java`
- `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorOpenFileSession.java`
- `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorTabStrip.java` if small UI adjustments are needed for restore-first behavior
### Step 6 - Wire save-on-close and category-scoped checkpoints if any are required
**What:** Make the accepted save policy real in the application lifecycle.
**How:** Ensure the main store is serialized:
- when the project shell closes;
- and when the project session closes through its normal lifecycle.
Do not introduce general autosave for the main store.
Only add checkpoint saves if a specific accepted category proves it cannot safely rely on close-time persistence alone, and keep that logic isolated to that category.
**File(s):**
- `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/main/java/p/studio/window/MainView.java`
- `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java`
- any shell/window lifecycle integration surface that currently owns project-window close behavior
### Step 7 - Add tests for defaults, restoration, and persistence boundaries
**What:** Lock the decision through automated tests.
**How:** Add tests that verify:
- missing `.studio/` falls back to defaults;
- invalid or schema-incompatible persisted content falls back to defaults;
- project-local setup is loaded at project-session open;
- shell/workspace state is restored from persisted state when present;
- editor open tabs and active tab restore correctly;
- `project-local activity` is not part of the main store contract;
- saving the main store happens on the accepted close boundary.
**File(s):**
- `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/test/java/p/studio/projectsessions/`
- `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/test/java/p/studio/window/`
- `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/test/java/p/studio/workspaces/editor/`
- tests for the new persistence package under `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/test/java/p/studio/projectstate/`
## Test Requirements
### Unit Tests
- Persisted-state codec tests for versioned single-file read/write behavior.
- Fallback tests for absent, invalid, and schema-incompatible state files.
- Session-service tests proving default values are exposed when persisted state is unusable.
- Editor snapshot tests proving only open-tab paths and active-tab identity are persisted.
### Integration Tests
- `StudioProjectSessionFactory` tests that verify setup is loaded during session open.
- Shell or window tests that verify persisted workspace selection and shell state are applied on mount.
- Editor workspace tests that reopen tabs from persisted paths and preserve the active tab when possible.
- Close-lifecycle tests that verify the main store is written when the shell or session closes.
### Manual Verification
- Open a project with no `.studio/` state and confirm the Studio boots with defaults.
- Configure project-local setup such as a Prometeu runtime path, close the shell, reopen the project, and confirm the setup is restored.
- Open multiple editor tabs, switch the active tab, close the project, reopen it, and confirm the same tabs and active tab are restored.
- Change shell/workspace organization that is in scope for wave 1, close the project, reopen it, and confirm that layout/workspace state is restored.
- Corrupt or remove the persisted state file and confirm the project still opens with defaults instead of failing.
## Acceptance Criteria
- [ ] Studio specs normatively describe the `.studio/` single-file project-session store and its exclusions.
- [ ] `StudioProjectSession` owns loading of project-local setup and access to the main state store.
- [ ] The main store is persisted as a single file under `.studio/`.
- [ ] Wave-1 categories are implemented without admitting excluded categories such as activity history or derived cache.
- [ ] Shell/workspace state restores on shell mount and saves on shell/project close.
- [ ] Editor open tabs and active tab restore from persisted project-local state.
- [ ] Missing or invalid persisted state falls back to safe defaults without blocking project open.
## Dependencies
- Accepted decision [`DEC-0016-project-local-studio-state-under-dot-studio.md`](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/discussion/workflow/decisions/DEC-0016-project-local-studio-state-under-dot-studio.md)
- Existing project-session boundary in `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/main/java/p/studio/projectsessions/`
- Existing editor tab/session behavior in `/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/prometeu-studio/src/main/java/p/studio/workspaces/editor/`
## Risks
- The current shell controls may not yet expose enough structured state to restore all accepted wave-1 layout fields cleanly.
- Editor restoration may need a small refactor to separate pure restore snapshots from current UI-driven open-file behavior.
- A new persistence spec may overlap with current shell/editor specs unless propagation boundaries are written carefully.
- Save-on-close behavior may depend on application/window lifecycle code not yet centralized in one obvious surface.