218 lines
15 KiB
Markdown
218 lines
15 KiB
Markdown
---
|
||
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 workspace’s 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.
|