studio session persistent
This commit is contained in:
parent
a824b2185f
commit
eb2520fa40
@ -1,9 +0,0 @@
|
||||
{"type":"meta","next_id":{"DSC":9,"AGD":9,"DEC":7,"PLN":5,"LSN":24,"CLSN":1}}
|
||||
{"type":"discussion","id":"DSC-0001","status":"done","ticket":"studio-docs-import","title":"Import docs/studio into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["studio","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0001","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0001-assets-workspace-execution-wave-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0002","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0002-bank-composition-editor-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0003","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0003-mental-model-asset-mutations-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0004","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0004-mental-model-assets-workspace-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0005","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0005-mental-model-studio-events-and-components-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0006","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0006-mental-model-studio-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0007","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0007-pack-wizard-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0008","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0008-project-scoped-state-and-activity-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0016","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0016-studio-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]}
|
||||
{"type":"discussion","id":"DSC-0002","status":"open","ticket":"palette-management-in-studio","title":"Palette Management in Studio","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["studio","legacy-import","palette-management","tile-bank","packer-boundary"],"agendas":[{"id":"AGD-0002","file":"AGD-0002-palette-management-in-studio.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0003","status":"done","ticket":"packer-docs-import","title":"Import docs/packer into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0009","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0009-mental-model-packer-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0010-asset-identity-and-runtime-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0011-foundations-workspace-runtime-and-build-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0012-runtime-ownership-and-studio-boundary-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0013-metadata-convergence-and-runtime-sink-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0014-pack-wizard-summary-validation-and-pack-execution-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0015-tile-bank-packing-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0017-packer-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]}
|
||||
{"type":"discussion","id":"DSC-0004","status":"open","ticket":"tilemap-and-metatile-runtime-binary-layout","title":"Tilemap and Metatile Runtime Binary Layout","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","legacy-import","tilemap","metatile","runtime-layout"],"agendas":[{"id":"AGD-0004","file":"AGD-0004-tilemap-and-metatile-runtime-binary-layout.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Tile Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","legacy-import","tile-bank","palette-serialization","versioning"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0006","status":"open","ticket":"pbs-game-facing-asset-refs-and-call-result-discard","title":"PBS Game-Facing Asset References and Ignored Call Result Lowering","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","ergonomics","lowering","runtime","asset-identity","expression-statements"],"agendas":[{"id":"AGD-0006","file":"AGD-0006-pbs-game-facing-asset-refs-and-call-result-discard.md","status":"accepted","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[{"id":"DEC-0005","file":"DEC-0005-pbs-asset-address-surface-and-be-lowering.md","status":"accepted","created_at":"2026-03-27","updated_at":"2026-03-27","ref_agenda":"AGD-0006"},{"id":"DEC-0006","file":"DEC-0006-pbs-ignored-values-lowering-and-warning.md","status":"accepted","created_at":"2026-03-27","updated_at":"2026-03-27","ref_agenda":"AGD-0006"}],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0007","status":"done","ticket":"pbs-learn-to-discussion-lessons-migration","title":"Migrate PBS Learn Documents into Discussion Lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","migration","discussion-framework","lessons","learn-prune"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0018","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0018-pbs-ast-and-parser-contract-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0019","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0019-pbs-name-resolution-and-linking-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0020","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0020-pbs-runtime-values-identity-memory-boundaries-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0021","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0021-pbs-diagnostics-and-conformance-governance-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0022","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0022-pbs-globals-lifecycle-and-published-entrypoint-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
|
||||
{"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
|
||||
@ -1,4 +1,4 @@
|
||||
{"type":"meta","next_id":{"DSC":12,"AGD":12,"DEC":8,"PLN":12,"LSN":25,"CLSN":1}}
|
||||
{"type":"meta","next_id":{"DSC":19,"AGD":20,"DEC":17,"PLN":38,"LSN":31,"CLSN":1}}
|
||||
{"type":"discussion","id":"DSC-0001","status":"done","ticket":"studio-docs-import","title":"Import docs/studio into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["studio","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0001","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0001-assets-workspace-execution-wave-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0002","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0002-bank-composition-editor-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0003","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0003-mental-model-asset-mutations-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0004","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0004-mental-model-assets-workspace-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0005","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0005-mental-model-studio-events-and-components-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0006","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0006-mental-model-studio-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0007","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0007-pack-wizard-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0008","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0008-project-scoped-state-and-activity-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0016","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0016-studio-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]}
|
||||
{"type":"discussion","id":"DSC-0002","status":"open","ticket":"palette-management-in-studio","title":"Palette Management in Studio","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["studio","legacy-import","palette-management","tile-bank","packer-boundary"],"agendas":[{"id":"AGD-0002","file":"AGD-0002-palette-management-in-studio.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0003","status":"done","ticket":"packer-docs-import","title":"Import docs/packer into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0009","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0009-mental-model-packer-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0010-asset-identity-and-runtime-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0011-foundations-workspace-runtime-and-build-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0012-runtime-ownership-and-studio-boundary-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0013-metadata-convergence-and-runtime-sink-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0014-pack-wizard-summary-validation-and-pack-execution-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0015-tile-bank-packing-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0017-packer-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]}
|
||||
@ -8,5 +8,12 @@
|
||||
{"type":"discussion","id":"DSC-0007","status":"done","ticket":"pbs-learn-to-discussion-lessons-migration","title":"Migrate PBS Learn Documents into Discussion Lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","migration","discussion-framework","lessons","learn-prune"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0018","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0018-pbs-ast-and-parser-contract-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0019","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0019-pbs-name-resolution-and-linking-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0020","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0020-pbs-runtime-values-identity-memory-boundaries-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0021","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0021-pbs-diagnostics-and-conformance-governance-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0022","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0022-pbs-globals-lifecycle-and-published-entrypoint-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
|
||||
{"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
|
||||
{"type":"discussion","id":"DSC-0009","status":"open","ticket":"studio-debugger-workspace-integration","title":"Integrate ../debugger into Studio as a dedicated workspace","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["studio","debugger","workspace","integration","shell"],"agendas":[{"id":"AGD-0009","file":"AGD-0009-studio-debugger-workspace-integration.md","status":"open","created_at":"2026-03-30","updated_at":"2026-03-30"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0010","status":"open","ticket":"studio-code-editor-workspace-foundations","title":"Establish Code Editor workspace foundations in Studio without LSP","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["studio","editor","workspace","multi-frontend","lsp-deferred"],"agendas":[{"id":"AGD-0010","file":"AGD-0010-studio-code-editor-workspace-foundations.md","status":"open","created_at":"2026-03-30","updated_at":"2026-03-30"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0011","status":"open","ticket":"compiler-analyze-compile-build-pipeline-split","title":"Split compiler pipeline into analyze, compile, and build entrypoints","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["compiler","pipeline","artifacts","build","analysis"],"agendas":[{"id":"AGD-0011","file":"AGD-0011-compiler-analyze-compile-build-pipeline-split.md","status":"accepted","created_at":"2026-03-30","updated_at":"2026-03-30"}],"decisions":[{"id":"DEC-0007","file":"DEC-0007-compiler-analyze-compile-build-pipeline-split.md","status":"in_progress","created_at":"2026-03-30","updated_at":"2026-03-30","ref_agenda":"AGD-0011"}],"plans":[{"id":"PLN-0009","file":"PLN-0009-compiler-pipeline-spec-and-contract-propagation.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0007"]},{"id":"PLN-0010","file":"PLN-0010-refactor-builder-pipeline-service-into-entrypoints.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0007"]},{"id":"PLN-0011","file":"PLN-0011-migrate-callsites-and-tests-to-build-compile-analyze.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0007"]}],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0010","status":"done","ticket":"studio-code-editor-workspace-foundations","title":"Establish Code Editor workspace foundations in Studio without LSP","created_at":"2026-03-30","updated_at":"2026-03-31","tags":["studio","editor","workspace","multi-frontend","lsp-deferred"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0026","file":"discussion/lessons/DSC-0010-studio-code-editor-workspace-foundations/LSN-0026-read-only-editor-foundations-and-semantic-deferral.md","status":"done","created_at":"2026-03-31","updated_at":"2026-03-31"}]}
|
||||
{"type":"discussion","id":"DSC-0011","status":"done","ticket":"compiler-analyze-compile-build-pipeline-split","title":"Split compiler pipeline into analyze, compile, and build entrypoints","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["compiler","pipeline","artifacts","build","analysis"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0025","file":"discussion/lessons/DSC-0011-compiler-analyze-compile-build-pipeline-split/LSN-0025-compiler-pipeline-entrypoints-and-result-boundaries.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]}
|
||||
{"type":"discussion","id":"DSC-0012","status":"done","ticket":"studio-editor-document-vfs-boundary","title":"Definir um boundary de VFS documental para tree/view/open files no Code Editor do Studio","created_at":"2026-03-31","updated_at":"2026-03-31","tags":["studio","editor","workspace","vfs","filesystem","boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0027","file":"discussion/lessons/DSC-0012-studio-editor-document-vfs-boundary/LSN-0027-project-document-vfs-and-session-owned-editor-boundary.md","status":"done","created_at":"2026-03-31","updated_at":"2026-03-31"}]}
|
||||
{"type":"discussion","id":"DSC-0013","status":"done","ticket":"studio-editor-write-wave-supported-non-frontend-files","title":"Definir a wave inicial de edicao no Code Editor apenas para arquivos aceitos e nao relacionados ao FE","created_at":"2026-03-31","updated_at":"2026-04-02","tags":["studio","editor","workspace","write","read-only","vfs","frontend-boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0028","file":"discussion/lessons/DSC-0013-studio-editor-write-wave-supported-non-frontend-files/LSN-0028-controlled-editor-write-wave-and-read-only-frontend-semantic-phase.md","status":"done","created_at":"2026-04-02","updated_at":"2026-04-02"}]}
|
||||
{"type":"discussion","id":"DSC-0014","status":"done","ticket":"studio-frontend-owned-semantic-editor-presentation","title":"Definir ownership do schema visual semantico do editor por frontend","created_at":"2026-04-02","updated_at":"2026-04-02","tags":["studio","editor","frontend","presentation","semantic-highlighting","compiler","pbs"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0029","file":"discussion/lessons/DSC-0014-studio-frontend-owned-semantic-editor-presentation/LSN-0029-frontend-owned-semantic-presentation-descriptor-and-host-consumption.md","status":"done","created_at":"2026-04-02","updated_at":"2026-04-02"}]}
|
||||
{"type":"discussion","id":"DSC-0015","status":"done","ticket":"pbs-service-facade-reserved-metadata","title":"SDK Service Bodies Calling Builtin/Intrinsic Proxies as Ordinary PBS Code","created_at":"2026-04-03","updated_at":"2026-04-03","tags":["compiler","pbs","sdk","stdlib","lowering","service","intrinsic","sdk-interface"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0030","file":"discussion/lessons/DSC-0015-pbs-service-facade-reserved-metadata/LSN-0030-sdk-service-bodies-over-private-reserved-proxies.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03"}]}
|
||||
{"type":"discussion","id":"DSC-0016","status":"open","ticket":"studio-editor-scope-guides-and-brace-anchoring","title":"Scope Guides do Code Editor com ancoragem exata em braces e destaque do escopo ativo","created_at":"2026-04-03","updated_at":"2026-04-03","tags":["studio","editor","scope-guides","braces","semantic-read","frontend-contract"],"agendas":[{"id":"AGD-0017","file":"AGD-0017-studio-editor-scope-guides-and-brace-anchoring.md","status":"accepted","created_at":"2026-04-03","updated_at":"2026-04-03"}],"decisions":[{"id":"DEC-0014","file":"DEC-0014-studio-editor-active-scope-and-structural-anchors.md","status":"accepted","created_at":"2026-04-03","updated_at":"2026-04-03"}],"plans":[{"id":"PLN-0030","file":"PLN-0030-studio-active-container-and-active-scope-gutter-wave-1.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03"},{"id":"PLN-0031","file":"PLN-0031-studio-structural-anchor-semantic-surface-specification.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03"},{"id":"PLN-0032","file":"PLN-0032-frontend-structural-anchor-payloads-and-anchor-aware-tests.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03"}],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0017","status":"open","ticket":"studio-editor-inline-type-hints-for-let-bindings","title":"Inline Type Hints for Let Bindings in the Studio Editor","created_at":"2026-04-03","updated_at":"2026-04-03","tags":["studio","editor","inline-hints","inlay-hints","lsp","pbs","type-inference"],"agendas":[{"id":"AGD-0018","file":"AGD-0018-studio-editor-inline-type-hints-for-let-bindings.md","status":"accepted","created_at":"2026-04-03","updated_at":"2026-04-03"}],"decisions":[{"id":"DEC-0015","file":"DEC-0015-studio-editor-inline-type-hints-contract-and-rendering-model.md","status":"accepted","created_at":"2026-04-03","updated_at":"2026-04-03","ref_agenda":"AGD-0018"}],"plans":[{"id":"PLN-0033","file":"PLN-0033-inline-hint-spec-and-contract-propagation.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03","ref_decisions":["DEC-0015"]},{"id":"PLN-0034","file":"PLN-0034-lsp-inline-hint-transport-contract.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03","ref_decisions":["DEC-0015"]},{"id":"PLN-0035","file":"PLN-0035-pbs-inline-type-hint-payload-production.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03","ref_decisions":["DEC-0015"]},{"id":"PLN-0036","file":"PLN-0036-studio-inline-hint-rendering-and-rollout.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03","ref_decisions":["DEC-0015"]}],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0018","status":"open","ticket":"studio-project-local-studio-state-under-dot-studio","title":"Persist project-local Studio state under .studio","created_at":"2026-04-04","updated_at":"2026-04-04","tags":["studio","project-session","project-state","persistence","dot-studio","shell","layout","setup"],"agendas":[{"id":"AGD-0019","file":"AGD-0019-studio-project-open-state-under-dot-studio.md","status":"accepted","created_at":"2026-04-04","updated_at":"2026-04-04"}],"decisions":[{"id":"DEC-0016","file":"DEC-0016-project-local-studio-state-under-dot-studio.md","status":"accepted","created_at":"2026-04-04","updated_at":"2026-04-04","ref_agenda":"AGD-0019"}],"plans":[{"id":"PLN-0037","file":"PLN-0037-project-local-studio-state-store-and-restoration.md","status":"done","created_at":"2026-04-04","updated_at":"2026-04-04","ref_decisions":["DEC-0016"]}],"lessons":[]}
|
||||
20
discussion/.backups/index.ndjson.20260404-073314.bak
Normal file
20
discussion/.backups/index.ndjson.20260404-073314.bak
Normal file
@ -0,0 +1,20 @@
|
||||
{"type":"meta","next_id":{"DSC":20,"AGD":21,"DEC":18,"PLN":39,"LSN":32,"CLSN":1}}
|
||||
{"type":"discussion","id":"DSC-0001","status":"done","ticket":"studio-docs-import","title":"Import docs/studio into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["studio","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0001","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0001-assets-workspace-execution-wave-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0002","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0002-bank-composition-editor-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0003","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0003-mental-model-asset-mutations-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0004","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0004-mental-model-assets-workspace-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0005","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0005-mental-model-studio-events-and-components-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0006","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0006-mental-model-studio-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0007","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0007-pack-wizard-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0008","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0008-project-scoped-state-and-activity-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0016","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0016-studio-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]}
|
||||
{"type":"discussion","id":"DSC-0002","status":"open","ticket":"palette-management-in-studio","title":"Palette Management in Studio","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["studio","legacy-import","palette-management","tile-bank","packer-boundary"],"agendas":[{"id":"AGD-0002","file":"AGD-0002-palette-management-in-studio.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0003","status":"done","ticket":"packer-docs-import","title":"Import docs/packer into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0009","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0009-mental-model-packer-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0010-asset-identity-and-runtime-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0011-foundations-workspace-runtime-and-build-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0012-runtime-ownership-and-studio-boundary-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0013-metadata-convergence-and-runtime-sink-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0014-pack-wizard-summary-validation-and-pack-execution-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0015-tile-bank-packing-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0017-packer-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]}
|
||||
{"type":"discussion","id":"DSC-0004","status":"open","ticket":"tilemap-and-metatile-runtime-binary-layout","title":"Tilemap and Metatile Runtime Binary Layout","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","legacy-import","tilemap","metatile","runtime-layout"],"agendas":[{"id":"AGD-0004","file":"AGD-0004-tilemap-and-metatile-runtime-binary-layout.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Tile Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","legacy-import","tile-bank","palette-serialization","versioning"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0006","status":"done","ticket":"pbs-game-facing-asset-refs-and-call-result-discard","title":"PBS Game-Facing Asset References and Ignored Call Result Lowering","created_at":"2026-03-27","updated_at":"2026-03-30","tags":["compiler","pbs","ergonomics","lowering","runtime","asset-identity","expression-statements"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"discussion/lessons/DSC-0006-pbs-game-facing-asset-refs-and-call-result-discard/LSN-0024-addressable-surface-host-metadata-and-ignored-value-discipline.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]}
|
||||
{"type":"discussion","id":"DSC-0007","status":"done","ticket":"pbs-learn-to-discussion-lessons-migration","title":"Migrate PBS Learn Documents into Discussion Lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","migration","discussion-framework","lessons","learn-prune"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0018","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0018-pbs-ast-and-parser-contract-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0019","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0019-pbs-name-resolution-and-linking-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0020","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0020-pbs-runtime-values-identity-memory-boundaries-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0021","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0021-pbs-diagnostics-and-conformance-governance-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0022","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0022-pbs-globals-lifecycle-and-published-entrypoint-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
|
||||
{"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
|
||||
{"type":"discussion","id":"DSC-0009","status":"open","ticket":"studio-debugger-workspace-integration","title":"Integrate ../debugger into Studio as a dedicated workspace","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["studio","debugger","workspace","integration","shell"],"agendas":[{"id":"AGD-0009","file":"AGD-0009-studio-debugger-workspace-integration.md","status":"open","created_at":"2026-03-30","updated_at":"2026-03-30"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0010","status":"done","ticket":"studio-code-editor-workspace-foundations","title":"Establish Code Editor workspace foundations in Studio without LSP","created_at":"2026-03-30","updated_at":"2026-03-31","tags":["studio","editor","workspace","multi-frontend","lsp-deferred"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0026","file":"discussion/lessons/DSC-0010-studio-code-editor-workspace-foundations/LSN-0026-read-only-editor-foundations-and-semantic-deferral.md","status":"done","created_at":"2026-03-31","updated_at":"2026-03-31"}]}
|
||||
{"type":"discussion","id":"DSC-0011","status":"done","ticket":"compiler-analyze-compile-build-pipeline-split","title":"Split compiler pipeline into analyze, compile, and build entrypoints","created_at":"2026-03-30","updated_at":"2026-03-30","tags":["compiler","pipeline","artifacts","build","analysis"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0025","file":"discussion/lessons/DSC-0011-compiler-analyze-compile-build-pipeline-split/LSN-0025-compiler-pipeline-entrypoints-and-result-boundaries.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]}
|
||||
{"type":"discussion","id":"DSC-0012","status":"done","ticket":"studio-editor-document-vfs-boundary","title":"Definir um boundary de VFS documental para tree/view/open files no Code Editor do Studio","created_at":"2026-03-31","updated_at":"2026-03-31","tags":["studio","editor","workspace","vfs","filesystem","boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0027","file":"discussion/lessons/DSC-0012-studio-editor-document-vfs-boundary/LSN-0027-project-document-vfs-and-session-owned-editor-boundary.md","status":"done","created_at":"2026-03-31","updated_at":"2026-03-31"}]}
|
||||
{"type":"discussion","id":"DSC-0013","status":"done","ticket":"studio-editor-write-wave-supported-non-frontend-files","title":"Definir a wave inicial de edicao no Code Editor apenas para arquivos aceitos e nao relacionados ao FE","created_at":"2026-03-31","updated_at":"2026-04-02","tags":["studio","editor","workspace","write","read-only","vfs","frontend-boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0028","file":"discussion/lessons/DSC-0013-studio-editor-write-wave-supported-non-frontend-files/LSN-0028-controlled-editor-write-wave-and-read-only-frontend-semantic-phase.md","status":"done","created_at":"2026-04-02","updated_at":"2026-04-02"}]}
|
||||
{"type":"discussion","id":"DSC-0014","status":"done","ticket":"studio-frontend-owned-semantic-editor-presentation","title":"Definir ownership do schema visual semantico do editor por frontend","created_at":"2026-04-02","updated_at":"2026-04-02","tags":["studio","editor","frontend","presentation","semantic-highlighting","compiler","pbs"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0029","file":"discussion/lessons/DSC-0014-studio-frontend-owned-semantic-editor-presentation/LSN-0029-frontend-owned-semantic-presentation-descriptor-and-host-consumption.md","status":"done","created_at":"2026-04-02","updated_at":"2026-04-02"}]}
|
||||
{"type":"discussion","id":"DSC-0015","status":"done","ticket":"pbs-service-facade-reserved-metadata","title":"SDK Service Bodies Calling Builtin/Intrinsic Proxies as Ordinary PBS Code","created_at":"2026-04-03","updated_at":"2026-04-03","tags":["compiler","pbs","sdk","stdlib","lowering","service","intrinsic","sdk-interface"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0030","file":"discussion/lessons/DSC-0015-pbs-service-facade-reserved-metadata/LSN-0030-sdk-service-bodies-over-private-reserved-proxies.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03"}]}
|
||||
{"type":"discussion","id":"DSC-0016","status":"open","ticket":"studio-editor-scope-guides-and-brace-anchoring","title":"Scope Guides do Code Editor com ancoragem exata em braces e destaque do escopo ativo","created_at":"2026-04-03","updated_at":"2026-04-03","tags":["studio","editor","scope-guides","braces","semantic-read","frontend-contract"],"agendas":[{"id":"AGD-0017","file":"AGD-0017-studio-editor-scope-guides-and-brace-anchoring.md","status":"accepted","created_at":"2026-04-03","updated_at":"2026-04-03"}],"decisions":[{"id":"DEC-0014","file":"DEC-0014-studio-editor-active-scope-and-structural-anchors.md","status":"accepted","created_at":"2026-04-03","updated_at":"2026-04-03"}],"plans":[{"id":"PLN-0030","file":"PLN-0030-studio-active-container-and-active-scope-gutter-wave-1.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03"},{"id":"PLN-0031","file":"PLN-0031-studio-structural-anchor-semantic-surface-specification.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03"},{"id":"PLN-0032","file":"PLN-0032-frontend-structural-anchor-payloads-and-anchor-aware-tests.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03"}],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0017","status":"open","ticket":"studio-editor-inline-type-hints-for-let-bindings","title":"Inline Type Hints for Let Bindings in the Studio Editor","created_at":"2026-04-03","updated_at":"2026-04-03","tags":["studio","editor","inline-hints","inlay-hints","lsp","pbs","type-inference"],"agendas":[{"id":"AGD-0018","file":"AGD-0018-studio-editor-inline-type-hints-for-let-bindings.md","status":"accepted","created_at":"2026-04-03","updated_at":"2026-04-03"}],"decisions":[{"id":"DEC-0015","file":"DEC-0015-studio-editor-inline-type-hints-contract-and-rendering-model.md","status":"accepted","created_at":"2026-04-03","updated_at":"2026-04-03","ref_agenda":"AGD-0018"}],"plans":[{"id":"PLN-0033","file":"PLN-0033-inline-hint-spec-and-contract-propagation.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03","ref_decisions":["DEC-0015"]},{"id":"PLN-0034","file":"PLN-0034-lsp-inline-hint-transport-contract.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03","ref_decisions":["DEC-0015"]},{"id":"PLN-0035","file":"PLN-0035-pbs-inline-type-hint-payload-production.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03","ref_decisions":["DEC-0015"]},{"id":"PLN-0036","file":"PLN-0036-studio-inline-hint-rendering-and-rollout.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03","ref_decisions":["DEC-0015"]}],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0018","status":"done","ticket":"studio-project-local-studio-state-under-dot-studio","title":"Persist project-local Studio state under .studio","created_at":"2026-04-04","updated_at":"2026-04-04","tags":["studio","project-session","project-state","persistence","dot-studio","shell","layout","setup"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0031","file":"discussion/lessons/DSC-0018-studio-project-local-studio-state-under-dot-studio/LSN-0031-project-local-studio-state-and-lifecycle-safe-layout-restoration.md","status":"done","created_at":"2026-04-04","updated_at":"2026-04-04"}]}
|
||||
{"type":"discussion","id":"DSC-0019","status":"open","ticket":"studio-project-local-setup-separate-from-main-studio-state","title":"Separate project-local setup from the main Studio state under .studio","created_at":"2026-04-04","updated_at":"2026-04-04","tags":["studio","project-session","project-state","persistence","dot-studio","setup","boundary"],"agendas":[{"id":"AGD-0020","file":"AGD-0020-project-local-setup-separate-from-main-studio-state.md","status":"accepted","created_at":"2026-04-04","updated_at":"2026-04-04"}],"decisions":[{"id":"DEC-0017","file":"DEC-0017-project-local-setup-separate-from-session-state.md","status":"accepted","created_at":"2026-04-04","updated_at":"2026-04-04","ref_agenda":"AGD-0020"}],"plans":[{"id":"PLN-0038","file":"PLN-0038-separate-project-local-setup-from-session-state.md","status":"done","created_at":"2026-04-04","updated_at":"2026-04-04","ref_decisions":["DEC-0017"]}],"lessons":[]}
|
||||
@ -1,4 +1,4 @@
|
||||
{"type":"meta","next_id":{"DSC":19,"AGD":20,"DEC":17,"PLN":38,"LSN":31,"CLSN":1}}
|
||||
{"type":"meta","next_id":{"DSC":20,"AGD":21,"DEC":18,"PLN":39,"LSN":33,"CLSN":1}}
|
||||
{"type":"discussion","id":"DSC-0001","status":"done","ticket":"studio-docs-import","title":"Import docs/studio into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["studio","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0001","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0001-assets-workspace-execution-wave-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0002","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0002-bank-composition-editor-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0003","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0003-mental-model-asset-mutations-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0004","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0004-mental-model-assets-workspace-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0005","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0005-mental-model-studio-events-and-components-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0006","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0006-mental-model-studio-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0007","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0007-pack-wizard-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0008","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0008-project-scoped-state-and-activity-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0016","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0016-studio-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]}
|
||||
{"type":"discussion","id":"DSC-0002","status":"open","ticket":"palette-management-in-studio","title":"Palette Management in Studio","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["studio","legacy-import","palette-management","tile-bank","packer-boundary"],"agendas":[{"id":"AGD-0002","file":"AGD-0002-palette-management-in-studio.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0003","status":"done","ticket":"packer-docs-import","title":"Import docs/packer into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0009","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0009-mental-model-packer-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0010-asset-identity-and-runtime-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0011-foundations-workspace-runtime-and-build-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0012-runtime-ownership-and-studio-boundary-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0013-metadata-convergence-and-runtime-sink-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0014-pack-wizard-summary-validation-and-pack-execution-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0015-tile-bank-packing-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0017-packer-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]}
|
||||
@ -16,4 +16,5 @@
|
||||
{"type":"discussion","id":"DSC-0015","status":"done","ticket":"pbs-service-facade-reserved-metadata","title":"SDK Service Bodies Calling Builtin/Intrinsic Proxies as Ordinary PBS Code","created_at":"2026-04-03","updated_at":"2026-04-03","tags":["compiler","pbs","sdk","stdlib","lowering","service","intrinsic","sdk-interface"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0030","file":"discussion/lessons/DSC-0015-pbs-service-facade-reserved-metadata/LSN-0030-sdk-service-bodies-over-private-reserved-proxies.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03"}]}
|
||||
{"type":"discussion","id":"DSC-0016","status":"open","ticket":"studio-editor-scope-guides-and-brace-anchoring","title":"Scope Guides do Code Editor com ancoragem exata em braces e destaque do escopo ativo","created_at":"2026-04-03","updated_at":"2026-04-03","tags":["studio","editor","scope-guides","braces","semantic-read","frontend-contract"],"agendas":[{"id":"AGD-0017","file":"AGD-0017-studio-editor-scope-guides-and-brace-anchoring.md","status":"accepted","created_at":"2026-04-03","updated_at":"2026-04-03"}],"decisions":[{"id":"DEC-0014","file":"DEC-0014-studio-editor-active-scope-and-structural-anchors.md","status":"accepted","created_at":"2026-04-03","updated_at":"2026-04-03"}],"plans":[{"id":"PLN-0030","file":"PLN-0030-studio-active-container-and-active-scope-gutter-wave-1.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03"},{"id":"PLN-0031","file":"PLN-0031-studio-structural-anchor-semantic-surface-specification.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03"},{"id":"PLN-0032","file":"PLN-0032-frontend-structural-anchor-payloads-and-anchor-aware-tests.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03"}],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0017","status":"open","ticket":"studio-editor-inline-type-hints-for-let-bindings","title":"Inline Type Hints for Let Bindings in the Studio Editor","created_at":"2026-04-03","updated_at":"2026-04-03","tags":["studio","editor","inline-hints","inlay-hints","lsp","pbs","type-inference"],"agendas":[{"id":"AGD-0018","file":"AGD-0018-studio-editor-inline-type-hints-for-let-bindings.md","status":"accepted","created_at":"2026-04-03","updated_at":"2026-04-03"}],"decisions":[{"id":"DEC-0015","file":"DEC-0015-studio-editor-inline-type-hints-contract-and-rendering-model.md","status":"accepted","created_at":"2026-04-03","updated_at":"2026-04-03","ref_agenda":"AGD-0018"}],"plans":[{"id":"PLN-0033","file":"PLN-0033-inline-hint-spec-and-contract-propagation.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03","ref_decisions":["DEC-0015"]},{"id":"PLN-0034","file":"PLN-0034-lsp-inline-hint-transport-contract.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03","ref_decisions":["DEC-0015"]},{"id":"PLN-0035","file":"PLN-0035-pbs-inline-type-hint-payload-production.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03","ref_decisions":["DEC-0015"]},{"id":"PLN-0036","file":"PLN-0036-studio-inline-hint-rendering-and-rollout.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03","ref_decisions":["DEC-0015"]}],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0018","status":"open","ticket":"studio-project-local-studio-state-under-dot-studio","title":"Persist project-local Studio state under .studio","created_at":"2026-04-04","updated_at":"2026-04-04","tags":["studio","project-session","project-state","persistence","dot-studio","shell","layout","setup"],"agendas":[{"id":"AGD-0019","file":"AGD-0019-studio-project-open-state-under-dot-studio.md","status":"accepted","created_at":"2026-04-04","updated_at":"2026-04-04"}],"decisions":[{"id":"DEC-0016","file":"DEC-0016-project-local-studio-state-under-dot-studio.md","status":"accepted","created_at":"2026-04-04","updated_at":"2026-04-04","ref_agenda":"AGD-0019"}],"plans":[{"id":"PLN-0037","file":"PLN-0037-project-local-studio-state-store-and-restoration.md","status":"done","created_at":"2026-04-04","updated_at":"2026-04-04","ref_decisions":["DEC-0016"]}],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0018","status":"done","ticket":"studio-project-local-studio-state-under-dot-studio","title":"Persist project-local Studio state under .studio","created_at":"2026-04-04","updated_at":"2026-04-04","tags":["studio","project-session","project-state","persistence","dot-studio","shell","layout","setup"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0031","file":"discussion/lessons/DSC-0018-studio-project-local-studio-state-under-dot-studio/LSN-0031-project-local-studio-state-and-lifecycle-safe-layout-restoration.md","status":"done","created_at":"2026-04-04","updated_at":"2026-04-04"}]}
|
||||
{"type":"discussion","id":"DSC-0019","status":"done","ticket":"studio-project-local-setup-separate-from-main-studio-state","title":"Separate project-local setup from the main Studio state under .studio","created_at":"2026-04-04","updated_at":"2026-04-04","tags":["studio","project-session","project-state","persistence","dot-studio","setup","boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0032","file":"discussion/lessons/DSC-0019-studio-project-local-setup-separate-from-main-studio-state/LSN-0032-separate-project-config-from-session-restoration-state.md","status":"done","created_at":"2026-04-04","updated_at":"2026-04-04"}]}
|
||||
|
||||
@ -0,0 +1,147 @@
|
||||
---
|
||||
id: LSN-0031
|
||||
ticket: studio-project-local-studio-state-under-dot-studio
|
||||
title: Project-Local Studio State and Lifecycle-Safe Layout Restoration
|
||||
created: 2026-04-04
|
||||
tags: [studio, project-session, project-state, persistence, dot-studio, shell, layout, setup, javafx]
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
Studio needed a real project-local persistence boundary for user organization and setup.
|
||||
The team wanted the opened project itself to carry Studio-local state under `.studio/`, including:
|
||||
|
||||
- project-local setup such as the Prometeu runtime path,
|
||||
- shell and workspace organization,
|
||||
- open editor tabs and the active tab,
|
||||
- and restorable workspace layout such as split pane positions and mini-panel visibility.
|
||||
|
||||
The discussion explicitly rejected mixing that concern with global launcher preferences or with project-local activity history.
|
||||
It also rejected treating every UI surface as an independent persistence owner.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
### Make `.studio/` the Canonical Project-Local Studio Root
|
||||
|
||||
**What:**
|
||||
The durable Studio state for one opened project now lives under `.studio/` in the project root, with a single-file main store at `.studio/state.json`.
|
||||
|
||||
**Why:**
|
||||
That makes project-local setup and organization travel with the project instead of leaking into application-global storage.
|
||||
It also gives Studio one canonical place to evolve project-local state over time.
|
||||
|
||||
**Trade-offs:**
|
||||
The single-file approach is simpler to maintain and migrate in the first wave, but it concentrates multiple categories into one schema that must stay disciplined.
|
||||
|
||||
### Keep `StudioProjectSession` as the Persistence Owner
|
||||
|
||||
**What:**
|
||||
`StudioProjectSession` owns loading and saving of the main project-local Studio store.
|
||||
Workspaces and shell surfaces may consume and update in-memory snapshots, but they do not redefine the persistence lifecycle.
|
||||
|
||||
**Why:**
|
||||
The opened project session is the real lifetime of per-project Studio state.
|
||||
That state must survive workspace switching while still remaining scoped to one opened project window.
|
||||
|
||||
**Trade-offs:**
|
||||
This adds an explicit project-session boundary, but that is better than letting shell views or workspaces become accidental persistence roots.
|
||||
|
||||
### Split Main Session State from Project-Local Activity
|
||||
|
||||
**What:**
|
||||
The main store covers `projectLocalSetup`, `shellLayout`, `openShellState`, and `editorRestoration`.
|
||||
Project-local activity remains under `.studio/`, but outside the main session store and with its own persistence policy.
|
||||
|
||||
**Why:**
|
||||
Layout and setup are snapshot-like session restoration concerns.
|
||||
Activity is more naturally log-like and should not distort the main contract.
|
||||
|
||||
**Trade-offs:**
|
||||
This introduces two project-local persistence shapes under `.studio/`, but it keeps the session store narrow and predictable.
|
||||
|
||||
### Treat JavaFX Layout Restore as a Lifecycle Problem, Not Just a Codec Problem
|
||||
|
||||
**What:**
|
||||
The final implementation had to restore split pane state only when the relevant JavaFX surfaces were actually ready, suppress state capture while applying the restore, and reapply pending layout after the project stage was shown.
|
||||
|
||||
**Why:**
|
||||
The persisted values were being loaded correctly, but JavaFX initialization and default layout passes could still overwrite them with default divider positions such as `0.35`.
|
||||
The real bug was lifecycle ordering, not file persistence.
|
||||
|
||||
**Trade-offs:**
|
||||
The implementation became slightly more explicit about initialization phases, but it avoided unreliable "save more often" workarounds and kept the persistence lifecycle simple.
|
||||
|
||||
## Final Implementation
|
||||
|
||||
The final implementation established a project-local Studio state contract across specs, code, and tests:
|
||||
|
||||
- `docs/specs/studio/1. Studio Shell and Workspace Layout Specification.md` now defines shell restore/save behavior around the project session.
|
||||
- `docs/specs/studio/5. Code Editor Workspace Specification.md` now treats cross-session editor restoration as part of the accepted contract.
|
||||
- `docs/specs/studio/8. Project-Local Studio State Specification.md` defines the `.studio` root, the single-file main store, wave-1 categories, exclusions, and fallback behavior.
|
||||
- `ProjectLocalStudioState` and `ProjectLocalStudioStateService` define the versioned single-file state model at `.studio/state.json`.
|
||||
- `StudioProjectSession` and `StudioProjectSessionFactory` own load/save lifecycle for the state store.
|
||||
- `MainView`, `EditorWorkspace`, and `AssetWorkspace` restore layout from the session-owned snapshot and keep the in-memory snapshot synchronized during the session.
|
||||
- layout save remains lifecycle-driven: update memory on change, save on workspace switch, save on project close, load on project open, and apply on workspace open.
|
||||
- fallback to safe defaults keeps project open resilient when `.studio/state.json` is absent, invalid, or incompatible.
|
||||
|
||||
## Patterns and Algorithms
|
||||
|
||||
### Pattern: Put Project-Scoped UI Persistence Under the Project Session
|
||||
|
||||
When Studio state belongs to one opened project but must survive workspace focus changes, the owner should be a project session object.
|
||||
That is the right boundary for:
|
||||
|
||||
- project-local setup,
|
||||
- restorable shell/workspace layout,
|
||||
- open workspace selection,
|
||||
- and editor restoration state.
|
||||
|
||||
### Pattern: Keep Persistence Lifecycle Simple and Explicit
|
||||
|
||||
The durable lifecycle is:
|
||||
|
||||
1. load on project-session open,
|
||||
2. apply on workspace mount,
|
||||
3. keep the latest state in memory during the session,
|
||||
4. save on workspace switch,
|
||||
5. save on project or Studio close.
|
||||
|
||||
This is better than broad autosave logic when the accepted contract only needs stable session restoration.
|
||||
|
||||
### Pattern: Reapply Layout Only After the UI Surface Is Real
|
||||
|
||||
For JavaFX `SplitPane` and docked layout surfaces, correct restoration requires more than reading the saved divider values.
|
||||
The implementation must:
|
||||
|
||||
- defer application until the control has real dimensions,
|
||||
- suppress state-capture callbacks while restore is in progress,
|
||||
- and reapply pending layout after stage show if the initial layout pass can still override the restored values.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- Do not push project-local Studio state into launcher-global preferences just because there is no UI for editing all categories yet.
|
||||
- Do not let individual workspaces or panels become persistence owners; they should only expose capture and restore snapshots.
|
||||
- Do not mix project-local activity history into the main session restoration file.
|
||||
- Do not "fix" layout restore bugs by adding generic debounce-based save behavior when the real issue is UI lifecycle ordering.
|
||||
- Do not capture layout again during teardown if the session already has the correct in-memory snapshot; late teardown capture can overwrite valid persisted values with defaults.
|
||||
|
||||
## References
|
||||
|
||||
- `DEC-0016` Project-local Studio state under `.studio`
|
||||
- `PLN-0037` Project-local Studio state store and restoration
|
||||
- `docs/specs/studio/1. Studio Shell and Workspace Layout Specification.md`
|
||||
- `docs/specs/studio/5. Code Editor Workspace Specification.md`
|
||||
- `docs/specs/studio/8. Project-Local Studio State Specification.md`
|
||||
- `prometeu-studio/src/main/java/p/studio/projectstate/ProjectLocalStudioState.java`
|
||||
- `prometeu-studio/src/main/java/p/studio/projectstate/ProjectLocalStudioStateService.java`
|
||||
- `prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java`
|
||||
- `prometeu-studio/src/main/java/p/studio/window/MainView.java`
|
||||
- `prometeu-studio/src/main/java/p/studio/window/StudioWindowCoordinator.java`
|
||||
- `prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWorkspace.java`
|
||||
- `prometeu-studio/src/main/java/p/studio/workspaces/assets/AssetWorkspace.java`
|
||||
|
||||
## Takeaways
|
||||
|
||||
- Project-local Studio organization belongs under `.studio/`, not in global app state.
|
||||
- `StudioProjectSession` is the correct owner for per-project Studio persistence.
|
||||
- JavaFX layout restoration succeeds only when persistence and UI lifecycle are aligned, not when persistence is merely present.
|
||||
@ -0,0 +1,136 @@
|
||||
---
|
||||
id: LSN-0032
|
||||
ticket: studio-project-local-setup-separate-from-main-studio-state
|
||||
title: Separate Project Config from Session Restoration State
|
||||
created: 2026-04-04
|
||||
tags: [studio, project-session, project-state, persistence, dot-studio, setup, configuration, boundary]
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
Studio had already introduced project-local persistence under `.studio/`, with a main single-file store at `.studio/state.json`.
|
||||
That first wave correctly established project-local session restoration, but it also embedded `projectLocalSetup` in the same file.
|
||||
|
||||
After implementation and real lifecycle testing, the boundary problem became clearer:
|
||||
|
||||
- `shellLayout`, `openShellState`, and `editorRestoration` are session-restoration state;
|
||||
- runtime path and similar project-local settings are configuration of the project itself;
|
||||
- those two categories do not share the same lifecycle, mutation model, or troubleshooting surface.
|
||||
|
||||
The revision work closed that mismatch by splitting project configuration from session restoration while keeping both under `.studio/`.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
### Separate Project-Local Setup from `.studio/state.json`
|
||||
|
||||
**What:**
|
||||
`projectLocalSetup` was removed from the main session-restoration state contract.
|
||||
The main store now remains focused on:
|
||||
|
||||
- `shellLayout`
|
||||
- `openShellState`
|
||||
- `editorRestoration`
|
||||
|
||||
Project-local setup now lives in its own file at `.studio/setup.json`.
|
||||
|
||||
**Why:**
|
||||
Session restoration is about reopening the Studio shell in the last accepted project-local shape.
|
||||
Project setup is about durable configuration that consumers such as `Play` may need independently from shell/session restore behavior.
|
||||
|
||||
Those concerns belong to the same project-local root, but not to the same file or lifecycle contract.
|
||||
|
||||
**Trade-offs:**
|
||||
This adds another persisted file under `.studio/`.
|
||||
That extra file is worth it because it prevents `state.json` from becoming an accidental catch-all store and gives project configuration a clearer operational identity.
|
||||
|
||||
### Keep Setup Out of the Session Snapshot Lifecycle
|
||||
|
||||
**What:**
|
||||
The setup file is read through a dedicated DTO/service boundary and is intended for on-demand consumption.
|
||||
It does not participate in the in-memory snapshot lifecycle used by `.studio/state.json`.
|
||||
|
||||
**Why:**
|
||||
Project configuration is not session state.
|
||||
Treating it as another session snapshot would blur the boundary again and recreate the same design problem in a different shape.
|
||||
|
||||
**Trade-offs:**
|
||||
Consumers must explicitly read the setup file instead of receiving it “for free” from session-state snapshots.
|
||||
That is an intentional cost because it preserves the correct mental model and ownership.
|
||||
|
||||
### Use a Dry Format Change for Early Boundary Repair
|
||||
|
||||
**What:**
|
||||
The revision intentionally did not add compatibility for the obsolete shape where `projectLocalSetup` was embedded in `.studio/state.json`.
|
||||
|
||||
**Why:**
|
||||
The goal of this wave was to repair the boundary cleanly, not to carry transitional compatibility machinery for a very recent format that had not yet earned long-term support cost.
|
||||
|
||||
**Trade-offs:**
|
||||
Existing local fixtures and test projects had to be updated directly.
|
||||
That is acceptable for a controlled early-stage format revision.
|
||||
|
||||
## Final Implementation
|
||||
|
||||
The Studio domain now uses two different project-local persistence files under `.studio/`:
|
||||
|
||||
- `.studio/state.json` for session-restoration state only;
|
||||
- `.studio/setup.json` for project-local configuration.
|
||||
|
||||
The implementation changes established that split across code, tests, and specs:
|
||||
|
||||
- `ProjectLocalStudioState` and `ProjectLocalStudioStateService` no longer include `projectLocalSetup`.
|
||||
- `ProjectLocalStudioSetup` and `ProjectLocalStudioSetupService` define the dedicated setup DTO and reader.
|
||||
- `ProjectStudioPaths` now exposes the dedicated `.studio/setup.json` path.
|
||||
- the Studio specs now describe setup as project configuration rather than session state.
|
||||
- test projects under `test-projects/` now include the dedicated `setup.json` file.
|
||||
|
||||
## Patterns and Algorithms
|
||||
|
||||
### Pattern: One Project-Local Root, Multiple Persistence Contracts
|
||||
|
||||
It is valid for several project-local persistence files to live under the same `.studio/` root when they represent different categories:
|
||||
|
||||
- session-restoration snapshots;
|
||||
- project configuration;
|
||||
- activity history;
|
||||
- or other future categories.
|
||||
|
||||
The important rule is not “one root means one file”.
|
||||
The important rule is that each file must have a clear semantic contract.
|
||||
|
||||
### Pattern: Separate Snapshot State from Durable Config
|
||||
|
||||
If data is restored through open/mount/close lifecycle behavior, it is snapshot state.
|
||||
If data configures how the project should behave when some consumer needs it, it is durable config.
|
||||
|
||||
Those categories should not share the same file by convenience.
|
||||
|
||||
### Pattern: Read Config on Demand
|
||||
|
||||
When configuration does not belong to the session snapshot lifecycle, use a narrow reader boundary and let consumers fetch it when needed.
|
||||
That keeps configuration from being accidentally reclassified as runtime session state.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- Do not let `state.json` become a generic “everything under `.studio/`” store.
|
||||
- Do not move project-local setup into global application preferences just to avoid another file.
|
||||
- Do not turn the dedicated setup file back into a session snapshot by caching it in the same lifecycle as layout restoration.
|
||||
- Do not add compatibility machinery reflexively when the real need is to fix a still-young boundary cleanly.
|
||||
- Do not leave the setup file name ambiguous across code and specs; the implementation should choose one explicit canonical name and use it consistently.
|
||||
|
||||
## References
|
||||
|
||||
- `DEC-0017` Separate project-local setup from session restoration state under `.studio/`
|
||||
- `PLN-0038` Separate project-local setup from session restoration state
|
||||
- `docs/specs/studio/1. Studio Shell and Workspace Layout Specification.md`
|
||||
- `docs/specs/studio/8. Project-Local Studio State Specification.md`
|
||||
- `prometeu-studio/src/main/java/p/studio/projects/ProjectStudioPaths.java`
|
||||
- `prometeu-studio/src/main/java/p/studio/projectstate/ProjectLocalStudioState.java`
|
||||
- `prometeu-studio/src/main/java/p/studio/projectstate/ProjectLocalStudioSetup.java`
|
||||
- `prometeu-studio/src/main/java/p/studio/projectstate/ProjectLocalStudioSetupService.java`
|
||||
|
||||
## Takeaways
|
||||
|
||||
- Project-local persistence under `.studio/` does not imply a single-file design.
|
||||
- Session restoration state and project configuration are different persistence categories and should stay separate.
|
||||
- A small, explicit config reader is often better than folding durable configuration into a session snapshot contract.
|
||||
@ -1,213 +0,0 @@
|
||||
---
|
||||
id: AGD-0019
|
||||
ticket: studio-project-local-studio-state-under-dot-studio
|
||||
title: Persist project-local Studio state under .studio
|
||||
status: accepted
|
||||
created: 2026-04-04
|
||||
resolved: 2026-04-04
|
||||
decision: DEC-0016
|
||||
tags: [studio, project-session, project-state, persistence, dot-studio, shell, layout, setup]
|
||||
---
|
||||
|
||||
## Pain
|
||||
|
||||
O Studio ja tem um modelo de `project session` para runtime do projeto aberto, mas ainda nao tem um contrato explicito para estado persistente do proprio Studio por projeto.
|
||||
|
||||
Sem esse contrato, a organizacao e o setup do Studio por projeto correm tres riscos:
|
||||
|
||||
- virar estado apenas em memoria e se perder toda vez que o Studio fecha;
|
||||
- ser espalhado em arquivos ad hoc, sem uma raiz reservada e sem schema claro;
|
||||
- misturar configuracao local do projeto com estado global do launcher, quebrando o boundary entre "este projeto no Studio" e "preferencias gerais da aplicacao".
|
||||
|
||||
## Context
|
||||
|
||||
Domain owner: `studio`
|
||||
Owner surfaces: `docs/specs/studio/1. Studio Shell and Workspace Layout Specification.md`
|
||||
Related context: `discussion/lessons/DSC-0001-studio-docs-import/LSN-0008-project-scoped-state-and-activity-legacy.md`, `discussion/lessons/DSC-0012-studio-editor-document-vfs-boundary/LSN-0027-project-document-vfs-and-session-owned-editor-boundary.md`
|
||||
Relevant code: `prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java`
|
||||
|
||||
Ja existe precedente documental para duas direcoes importantes:
|
||||
|
||||
- `.studio/` e a raiz reservada para estado local ao projeto;
|
||||
- estado que precisa sobreviver a troca de workspace, mas continuar pertencendo ao projeto aberto, deve ser owned por `project session`.
|
||||
|
||||
O que ainda nao esta fechado e o contrato desta nova camada de estado persistente do Studio por projeto:
|
||||
|
||||
- quais dados entram nela;
|
||||
- quais dados devem continuar apenas em memoria;
|
||||
- o que e projeto-local versus launcher-global;
|
||||
- como versionar, carregar, gravar e tolerar corrupcao parcial;
|
||||
- se o modelo deve ser um store unico do projeto ou varios arquivos especializados sob `.studio/`.
|
||||
|
||||
Exemplos concretos do escopo pretendido agora:
|
||||
|
||||
- posicoes de divisorias e proporcoes de layout;
|
||||
- quais janelas, paineis ou workspaces estavam abertos;
|
||||
- quais tabs do editor estavam abertas e qual estava ativa;
|
||||
- caminhos de setup local do Studio para o projeto, como runtime do Prometeu;
|
||||
- futuras configuracoes locais do Studio que pertencam a este projeto e nao ao launcher global.
|
||||
|
||||
Categoria relacionada, mas separada deste contrato principal:
|
||||
|
||||
- `project-local activity` pode continuar vivendo sob `.studio/`, mas nao precisa pertencer ao mesmo store canonico de `project session` usado para layout, tabs, janelas e setup.
|
||||
|
||||
Observacao importante:
|
||||
|
||||
- `project-local setup` ja e requisito relevante agora, mesmo antes de existir uma UI dedicada para edita-lo, porque o Studio pode precisar consumir configuracoes locais do projeto antes da superficie visual de configuracao ficar pronta.
|
||||
|
||||
## Open Questions
|
||||
|
||||
### What to store
|
||||
|
||||
- [ ] Qual deve ser o escopo minimo obrigatorio do estado persistido do Studio por projeto na primeira wave?
|
||||
- [ ] O owner normativo do runtime deve ser `StudioProjectSession` com persistencia sob `.studio/`, ou cada workspace pode persistir diretamente seu proprio estado?
|
||||
- [x] O contrato deve usar um arquivo consolidado de estado do projeto ou uma arvore de arquivos especializados dentro de `.studio/`?
|
||||
Fechado: `single file`. O store principal da `project session` deve usar um arquivo consolidado, por ser mais simples de manter e governar.
|
||||
- [ ] Quais categorias entram desde a wave 1: layout do shell, divisorias, paineis e janelas abertas, tabs abertas, documento ativo, caminhos de setup local, configuracoes por workspace?
|
||||
- [ ] `Project-local setup` deve ser tratado como categoria de primeira classe desde o inicio, mesmo antes de haver UI propria?
|
||||
- [x] A `project-local activity` deve pertencer ao mesmo store de `project session` desta agenda?
|
||||
Fechado: nao. `Project-local activity` pode viver dentro de `.studio/`, mas deve permanecer dissociada do store principal de `project session` tratado nesta agenda.
|
||||
- [ ] Quais categorias devem ser explicitamente proibidas por agora: cache derivado, estado efemero de hover, resultados recomputaveis, output operacional pesado, artefatos operacionais transient?
|
||||
|
||||
### When to save and restore
|
||||
|
||||
- [x] Quando o Studio grava esse estado: sob eventos incrementais, no fechamento da sessao, em pontos de checkpoint, ou combinacao controlada?
|
||||
Fechado: a politica base deve ser gravacao no fechamento; checkpoints sao aceitaveis apenas para categorias que realmente precisarem disso; gravacao incremental como regra geral nao e a direcao.
|
||||
- [x] Quais categorias devem ser restauradas imediatamente ao abrir o projeto e quais devem ser carregadas sob demanda?
|
||||
Fechado: o estado restauravel de shell deve ser reaplicado quando o projeto sobe; no mesmo boundary, quando o shell do projeto desce, o estado correspondente deve ser salvo.
|
||||
- [x] O setup local do projeto deve ser lido logo na abertura da `project session`, antes mesmo de o usuario abrir workspaces especificos?
|
||||
Fechado: sim. O setup local do projeto deve ser lido na abertura da `project session`.
|
||||
- [x] Como o Studio deve reagir a `.studio/` ausente, estado em schema antigo, arquivo invalido ou dados parcialmente corrompidos?
|
||||
Fechado: fallback para valores default. A ausencia de `.studio/`, schema nao reconhecido ou conteudo invalido/corrompido nao deve impedir a abertura do projeto; o Studio deve cair para defaults seguros.
|
||||
|
||||
## Options
|
||||
|
||||
### Option A - Persistencia ad hoc por area do Studio sob `.studio/`
|
||||
- **Approach:** cada area do Studio grava diretamente os arquivos de que precisa sob `.studio/`, por exemplo shell/layout, editor tabs, setup local e outros modulos futuros, sem um owner central de sessao nem um schema compartilhado forte.
|
||||
- **Pro:** destrava persistencia rapido para features isoladas e exige pouco desenho inicial.
|
||||
- **Con:** tende a fragmentar naming, lifecycle, migration e recovery; piora consistencia entre workspaces e dificulta distinguir estado normativo de lixo historico.
|
||||
- **Maintainability:** baixa a media. Facil de iniciar, dificil de governar quando mais workspaces passarem a persistir.
|
||||
- **Trade-offs detalhados:**
|
||||
- reduz custo de entrada para a primeira feature consumidora, mas troca esse ganho por uma futura consolidacao mais cara;
|
||||
- favorece autonomia local de shell e workspaces, mas quebra o boundary de `project session` que o repositorio vem fortalecendo;
|
||||
- simplifica a escrita inicial, mas complica leitura, migracao de schema e tolerancia a falhas, porque cada workspace pode passar a degradar de um jeito diferente;
|
||||
- permite fatiar rollout por workspace, mas aumenta o risco de formatos incompatíveis coexistirem dentro de `.studio/`.
|
||||
|
||||
### Option B - Project-session state store canonico sob `.studio/`
|
||||
- **Approach:** definir um contrato explicito de estado persistente do Studio por projeto, owned pela `StudioProjectSession`, com raiz canonica em `.studio/` e schema/versionamento governados pelo Studio.
|
||||
- **Pro:** preserva o boundary correto entre runtime de sessao, persistencia local do projeto e concerns globais do launcher; facilita recovery, migration e extensao futura.
|
||||
- **Con:** exige desenhar ownership, schema e politica de gravacao antes de implementar a primeira feature consumidora.
|
||||
- **Maintainability:** forte. O Studio ganha uma surface clara para persistencia de layout, tabs, setup local e futuras configuracoes por projeto sem espalhar responsabilidade por cada modulo.
|
||||
- **Trade-offs detalhados:**
|
||||
- aumenta custo de desenho agora, mas reduz custo estrutural das proximas features que precisarem persistir estado por projeto;
|
||||
- centraliza ownership e recovery, o que melhora consistencia, mas exige uma API suficientemente clara para nao virar gargalo ou objeto “god state”;
|
||||
- facilita schema versioning, migration e corrupcao parcial, mas pede disciplina para separar configuracao local canonica de cache derivado;
|
||||
- protege a diferenca entre projeto-local e launcher-global, mas exige que o recorte inicial seja pequeno o bastante para nao bloquear implementacao por excesso de ambicao;
|
||||
- acomoda bem layout, setup e estado restauravel de UI, mas precisa de limites claros para nao começar a absorver qualquer detalhe efemero de sessao.
|
||||
|
||||
### Option C - Manter apenas estado global do launcher e evitar persistencia por projeto nesta fase
|
||||
- **Approach:** limitar a memoria persistente a recent projects e preferencias globais; cada projeto reconstroi layout, setup local e tabs do zero a cada abertura.
|
||||
- **Pro:** menor custo imediato e nenhum contrato novo dentro do projeto.
|
||||
- **Con:** conflita com o objetivo de tornar o projeto aberto uma unidade com estado proprio; degrada continuidade de uso e ignora o precedente ja registrado para `.studio/`.
|
||||
- **Maintainability:** simples no curtissimo prazo, mas funcionalmente insuficiente se o Studio quer evoluir como ambiente de trabalho persistente por projeto.
|
||||
- **Trade-offs detalhados:**
|
||||
- preserva simplicidade operacional agora, mas empurra o problema para depois sem melhorar a arquitetura do projeto aberto;
|
||||
- evita erro de modelagem prematuro, mas tambem impede validar cedo a disciplina de `.studio/` e `project session`;
|
||||
- mantem o launcher como unico ponto persistente, mas mistura setup local do projeto com concerns globais que deveriam permanecer fora do projeto;
|
||||
- reduz risco de schema local mal desenhado, mas aumenta risco de cada nova feature tentar contornar a ausencia de persistencia por atalhos locais.
|
||||
|
||||
## Discussion
|
||||
|
||||
O ponto principal aqui nao e apenas "onde salvar um JSON". O que precisa ser fechado e o boundary arquitetural:
|
||||
|
||||
1. ownership de runtime:
|
||||
quem monta o estado em memoria enquanto o projeto esta aberto;
|
||||
|
||||
2. ownership de persistencia:
|
||||
quem serializa e restaura esse estado sem deixar cada workspace inventar sua propria disciplina;
|
||||
|
||||
3. shape do dado:
|
||||
o que conta como organizacao e setup do Studio por projeto, o que e apenas view state efemero e o que pertence ao launcher global;
|
||||
|
||||
4. resiliencia:
|
||||
como o Studio lida com schema evolution, arquivos ausentes e degradacao parcial sem falhar ao abrir um projeto.
|
||||
|
||||
O precedente atual aponta para uma direcao relativamente forte:
|
||||
|
||||
- `.studio/` deve continuar sendo a raiz reservada do projeto para concerns do Studio;
|
||||
- `StudioProjectSession` ja e o owner natural do estado que vive acima do foco de um workspace;
|
||||
- workspaces devem consumir servicos de sessao, nao redefinir ownership de persistencia por conta propria.
|
||||
- nem todo dado sob `.studio/` precisa cair dentro do mesmo store de `project session`; `activity` e o exemplo claro de uma categoria projeto-local, mas com semantica e politica de persistencia diferentes.
|
||||
- para o store principal desta agenda, `single file` e a direcao preferida, porque simplifica manutencao, leitura, escrita e governanca inicial.
|
||||
|
||||
O risco de ir por um caminho ad hoc e que shell, editor e setup local comecem a salvar layout, tabs e caminhos em formatos independentes e acidentalmente normativos.
|
||||
Depois disso, consolidar ownership, migration e cleanup fica mais caro do que desenhar a superficie certa agora.
|
||||
|
||||
Ao mesmo tempo, uma primeira wave disciplinada nao precisa resolver toda a persistencia futura do Studio.
|
||||
Ela pode fechar:
|
||||
|
||||
- a raiz canonicamente reservada;
|
||||
- o owner do runtime e da serializacao;
|
||||
- as categorias de estado permitidas e proibidas na wave inicial;
|
||||
- o formato geral de schema e versionamento;
|
||||
- a politica de recovery minima para nao travar abertura de projeto.
|
||||
|
||||
Trade-off central da agenda:
|
||||
|
||||
- se priorizarmos velocidade local da primeira feature, Option A parece atraente, mas ela compra essa velocidade quebrando o owner correto;
|
||||
- se priorizarmos architecture hygiene, Option B e a direcao mais consistente, mas ela precisa de um recorte rigoroso para nao tentar resolver persistencia total do Studio numa tacada so;
|
||||
- Option C so faz sentido se o objetivo real nao for ainda ter projeto aberto como unidade persistente, o que conflita com a premissa desta agenda.
|
||||
|
||||
Os trade-offs tambem se separam naturalmente em dois eixos:
|
||||
|
||||
1. `what to store`
|
||||
quanto mais categorias entram na wave 1, maior o valor imediato de restauracao do Studio por projeto;
|
||||
por outro lado, maior o risco de misturar setup canonico com estado efemero ou cache derivado.
|
||||
|
||||
A convergencia atual deste eixo ja sugere uma separacao interna:
|
||||
|
||||
- um store principal de `project session` para layout, setup, janelas e restauracao de tabs;
|
||||
- stores ou artefatos adjacentes sob `.studio/` para categorias com semantica diferente, como `project-local activity`.
|
||||
|
||||
2. `when to save/restore`
|
||||
quanto mais automatico e frequente for o save, menor a perda de estado;
|
||||
por outro lado, maior o risco de churn de escrita, snapshots inconsistentes e acoplamento excessivo a eventos de UI.
|
||||
|
||||
Leituras ja convergidas neste eixo:
|
||||
|
||||
- `project-local setup` deve ser restaurado logo na abertura da `project session`;
|
||||
- o estado restauravel do shell deve subir com o projeto e ser salvo quando esse shell descer;
|
||||
- `save on close` deve ser a politica padrao;
|
||||
- checkpoints podem existir, mas apenas quando alguma categoria realmente exigir persistencia intermediaria.
|
||||
|
||||
Leitura atual dos trade-offs:
|
||||
|
||||
1. o maior risco de produto e nao ter continuidade de organizacao e setup do Studio entre aberturas do projeto;
|
||||
2. `project-local setup` tem prioridade alta porque pode ser consumido mesmo antes da UI de configuracao existir;
|
||||
3. o maior risco arquitetural e permitir que shell e workspaces inventem persistencia independente para layout, tabs e configuracao local;
|
||||
4. o maior risco de execucao em Option B e superdimensionar a primeira wave ou salvar estado demais cedo demais;
|
||||
5. portanto, a melhor convergencia parece ser um store canonico de sessao/projeto com escopo inicial deliberadamente estreito, `single file` no inicio, mas explicitamente capaz de crescer para layout, setup e configuracoes futuras.
|
||||
|
||||
## Resolution
|
||||
|
||||
Recommended direction: seguir com **Option B**.
|
||||
|
||||
A agenda deve convergir para uma decision com os seguintes fechamentos:
|
||||
|
||||
1. `.studio/` permanece a raiz canonica de estado local ao projeto para o Studio;
|
||||
2. `StudioProjectSession` ou um servico explicitamente owned por ela deve ser o owner do runtime e da persistencia do estado local do Studio por projeto;
|
||||
3. shell e workspaces devem consumir esse estado por contrato, em vez de cada um persistir arbitrariamente por conta propria;
|
||||
4. a primeira wave deve definir claramente quais categorias entram, com forte prioridade para `project-local setup`, layout restauravel e tabs/janelas abertas;
|
||||
5. o contrato deve prever schema/versionamento e recovery de dados ausentes ou invalidos;
|
||||
6. o boundary entre estado projeto-local e estado launcher-global deve ficar explicito;
|
||||
7. o desenho inicial deve suportar extensao futura para novas categorias de configuracao local sem exigir reorganizacao ad hoc de `.studio/`;
|
||||
8. a decision deve separar explicitamente `what to store` de `when to save/restore`, em vez de misturar conteudo e politica operacional;
|
||||
9. a politica base de persistencia deve ser `read on project-session open`, `restore on shell mount`, `save on shell/project close`, com checkpoints apenas quando justificadamente necessarios;
|
||||
10. `project-local activity` deve ser explicitamente tratada como concern separado: continua sob `.studio/`, mas fora do store principal de `project session`;
|
||||
11. o store principal deve comecar como `single file`;
|
||||
12. ausencia, schema antigo ou conteudo invalido/corrompido devem degradar para valores default seguros, sem bloquear abertura do projeto.
|
||||
|
||||
Next step suggestion: fechar nesta agenda, em separado, `what to store` e `when to save/restore`:
|
||||
|
||||
- `what to store`: pelo menos `project-local setup`, `shell layout`, `open panels/workspaces`, `editor open tabs + active tab`;
|
||||
- `when to save/restore`: leitura do setup ja na abertura da `project session`, restauracao do layout/tabs na entrada do shell, save no fechamento, e checkpoints apenas para categorias que realmente precisarem.
|
||||
@ -1,169 +0,0 @@
|
||||
---
|
||||
id: DEC-0016
|
||||
ticket: studio-project-local-studio-state-under-dot-studio
|
||||
title: Project-Local Studio State under .studio
|
||||
status: accepted
|
||||
created: 2026-04-04
|
||||
accepted: 2026-04-04
|
||||
agenda: AGD-0019
|
||||
plans: []
|
||||
tags: [studio, project-session, project-state, persistence, dot-studio, shell, layout, setup]
|
||||
---
|
||||
|
||||
## Decision
|
||||
|
||||
The Studio MUST persist project-local Studio state under `.studio/` in the project root.
|
||||
|
||||
This decision normatively separates three concerns:
|
||||
|
||||
1. project-local Studio state owned by the project and restored with that project;
|
||||
2. launcher-global state that is not owned by any specific project;
|
||||
3. project-local activity artifacts that may live under `.studio/` but are not part of the main project-session state store defined here.
|
||||
|
||||
The main project-local Studio state store MUST be owned by `StudioProjectSession`, or by a persistence service explicitly owned by `StudioProjectSession`.
|
||||
|
||||
Shells and workspaces MUST consume that state through the project-session boundary.
|
||||
They MUST NOT define ad hoc independent persistence contracts for layout, tabs, windows, or project-local setup.
|
||||
|
||||
The main project-session store MUST start as a `single file` under `.studio/`.
|
||||
|
||||
The first accepted scope of that store MUST include:
|
||||
|
||||
- project-local setup required by Studio to operate on the project, including paths such as the Prometeu runtime path;
|
||||
- shell layout state such as splitter positions and layout proportions;
|
||||
- open shell/workspace state such as which panels, windows, or workspaces were open;
|
||||
- editor restoration state including open tabs and the active tab.
|
||||
|
||||
`Project-local setup` is a first-class category from the start, even before a dedicated UI exists to edit it.
|
||||
The Studio MAY consume such setup programmatically before a UI surface exists.
|
||||
|
||||
`Project-local activity` MUST remain outside the main project-session store defined by this decision.
|
||||
It MAY continue to live under `.studio/`, but it SHALL be treated as a separate concern with its own storage contract and persistence policy.
|
||||
|
||||
The main project-session store MUST NOT be used for:
|
||||
|
||||
- derived cache;
|
||||
- ephemeral hover or transient interaction state;
|
||||
- recomputable operational results;
|
||||
- heavy operational output;
|
||||
- activity history.
|
||||
|
||||
## Rationale
|
||||
|
||||
The repository already converged on two architectural directions:
|
||||
|
||||
- `.studio/` is the reserved root for project-local Studio concerns;
|
||||
- `StudioProjectSession` is the correct owner for state that must survive workspace focus changes while remaining scoped to one opened project.
|
||||
|
||||
This decision extends those directions into a normative persistence contract.
|
||||
|
||||
The chosen model prevents three failure modes:
|
||||
|
||||
1. launcher-global persistence swallowing project-local setup and organization;
|
||||
2. each shell or workspace inventing its own persistence format under `.studio/`;
|
||||
3. the main session state store absorbing unrelated concerns such as activity history or cache data.
|
||||
|
||||
Starting with a `single file` is intentionally conservative.
|
||||
It reduces governance and maintenance cost for the first wave while preserving the option to evolve the schema later if needed.
|
||||
|
||||
Treating project-local setup as first-class from the start is necessary because Studio runtime behavior may depend on local project configuration before any settings UI is available.
|
||||
|
||||
## Technical Specification
|
||||
|
||||
### 1. Storage Root
|
||||
|
||||
The canonical root for project-local Studio persistence MUST be `.studio/` in the project root.
|
||||
|
||||
The main project-session state store MUST be created under that root.
|
||||
|
||||
### 2. Ownership Boundary
|
||||
|
||||
`StudioProjectSession` MUST own the lifecycle of the main project-session state store.
|
||||
|
||||
That ownership includes:
|
||||
|
||||
- loading project-local setup when the project session opens;
|
||||
- exposing the loaded state to shell and workspace consumers through project-session-owned contracts;
|
||||
- coordinating restoration when the project shell mounts;
|
||||
- coordinating persistence when the project shell or project session closes.
|
||||
|
||||
No workspace MAY bypass this boundary by defining an unrelated primary store for project-local Studio organization or setup.
|
||||
|
||||
### 3. Store Shape
|
||||
|
||||
The main store MUST begin as a `single file`.
|
||||
|
||||
This file MUST act as the canonical snapshot for the categories accepted by this decision.
|
||||
|
||||
The schema MUST be explicitly versioned so future revisions can detect compatibility and migration boundaries.
|
||||
|
||||
### 4. Accepted Wave-1 Categories
|
||||
|
||||
Wave 1 of the main project-session store MUST cover:
|
||||
|
||||
- `projectLocalSetup`
|
||||
Project-local configuration required by Studio to operate on the project, including Prometeu runtime path and equivalent future setup fields.
|
||||
|
||||
- `shellLayout`
|
||||
Restorable shell organization such as divider positions, layout proportions, and equivalent shell-level geometry state.
|
||||
|
||||
- `openShellState`
|
||||
Which panels, windows, or workspaces were open when the project shell last persisted.
|
||||
|
||||
- `editorRestoration`
|
||||
Open editor tabs and the active tab.
|
||||
|
||||
These names are conceptual categories.
|
||||
Plans MAY refine the concrete field names, but they MUST preserve the exact normative scope above.
|
||||
|
||||
### 5. Explicit Exclusions
|
||||
|
||||
The main project-session store MUST NOT include:
|
||||
|
||||
- activity history;
|
||||
- derived cache data;
|
||||
- ephemeral UI interaction state such as hover-only data;
|
||||
- heavy operational logs or output buffers;
|
||||
- recomputable results that do not represent project-local Studio setup or restoration state.
|
||||
|
||||
If a future category is proposed, it MUST be classified explicitly as either:
|
||||
|
||||
- main project-session state;
|
||||
- separate `.studio/` concern;
|
||||
- launcher-global concern;
|
||||
- or non-persisted transient state.
|
||||
|
||||
### 6. Read / Restore / Save Policy
|
||||
|
||||
The main policy is normatively locked as follows:
|
||||
|
||||
- project-local setup MUST be read when `StudioProjectSession` opens;
|
||||
- restorable shell and editor state MUST be restored when the project shell mounts;
|
||||
- the main project-session store MUST be saved when the project shell or project session closes.
|
||||
|
||||
The repository default for this store is `save on close`.
|
||||
|
||||
General incremental persistence MUST NOT be the default policy for the main store.
|
||||
|
||||
Checkpoints MAY be introduced only for categories that explicitly require intermediate persistence.
|
||||
Any such checkpoint behavior MUST be justified in a later plan or revision and MUST remain category-scoped rather than becoming an uncontrolled global autosave rule.
|
||||
|
||||
### 7. Failure Handling
|
||||
|
||||
If `.studio/` is absent, the main store is missing, the schema is unknown, or the content is invalid or partially corrupted, the Studio MUST fall back to safe default values.
|
||||
|
||||
Such conditions MUST NOT block opening the project.
|
||||
|
||||
The fallback behavior MUST preserve the ability to open the project and operate the Studio with default shell, workspace, and setup assumptions as far as possible.
|
||||
|
||||
## Constraints
|
||||
|
||||
- No plan may reinterpret launcher-global state as project-local state without an explicit revision to this decision.
|
||||
- No plan may move `project-local activity` into the main project-session store without an explicit revision to this decision.
|
||||
- No plan may replace the `single file` starting point with a multi-file tree by inference.
|
||||
- No plan may treat ephemeral UI noise or derived cache as accepted wave-1 project-session state.
|
||||
- If a later implementation needs checkpoint persistence for a specific category, that need MUST be justified explicitly instead of silently broadening the save policy.
|
||||
|
||||
## Revision Log
|
||||
|
||||
- 2026-04-04: Initial accepted decision from AGD-0019.
|
||||
@ -1,217 +0,0 @@
|
||||
---
|
||||
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.
|
||||
@ -80,7 +80,8 @@ Rules:
|
||||
- workspaces may consume those project-session services without inheriting their ownership;
|
||||
- introducing a project-session service must not collapse shell and workspace responsibilities into one monolithic root.
|
||||
- project-local Studio state under `.studio/` must be loaded through the project-session boundary rather than through shell-local ad hoc persistence;
|
||||
- project-local setup required before workspace use must be available when the project session opens;
|
||||
- session-restoration state under `.studio/state.json` must be loaded through the project-session lifecycle;
|
||||
- project-local setup under `.studio/setup.json` is configuration rather than session snapshot state and may be read on demand by the consumer that needs it;
|
||||
- shell-restorable state accepted by Studio must be restored when the project shell mounts and persisted when the project shell closes.
|
||||
|
||||
## Right Utility Panel
|
||||
|
||||
@ -8,11 +8,12 @@ Active
|
||||
|
||||
- `prometeu-studio`
|
||||
- Studio project-session persistence under `.studio/`
|
||||
- project-local Studio setup and restoration state
|
||||
- project-local Studio session restoration state
|
||||
- project-local Studio setup configuration
|
||||
|
||||
## Purpose
|
||||
|
||||
Define the normative contract for the main project-local Studio state store.
|
||||
Define the normative contract for Studio project-local persistence under `.studio/`, including the boundary between the main session-restoration store and the dedicated setup configuration file.
|
||||
|
||||
## Authority and Precedence
|
||||
|
||||
@ -26,47 +27,63 @@ It extends:
|
||||
## Core Rules
|
||||
|
||||
1. The canonical root for project-local Studio persistence MUST be `.studio/` in the project root.
|
||||
2. The main project-local Studio state store MUST be owned by `StudioProjectSession`, or by a service explicitly owned by `StudioProjectSession`.
|
||||
3. The main store MUST start as a single file.
|
||||
4. The main store MUST be versioned.
|
||||
5. The main store MUST load when the project session opens.
|
||||
2. The main project-local Studio session-restoration store MUST be owned by `StudioProjectSession`, or by a service explicitly owned by `StudioProjectSession`.
|
||||
3. The main session-restoration store MUST remain a single file at `.studio/state.json`.
|
||||
4. The main session-restoration store MUST be versioned.
|
||||
5. The main session-restoration store MUST load when the project session opens.
|
||||
6. Restorable shell and editor state accepted by this wave MUST restore when the project shell mounts.
|
||||
7. The main store MUST save when the project shell or project session closes.
|
||||
8. Missing, invalid, or schema-incompatible state MUST fall back to safe default values and MUST NOT block project open.
|
||||
7. The main session-restoration store MUST save when the project shell or project session closes.
|
||||
8. Missing, invalid, or schema-incompatible session-restoration state MUST fall back to safe default values and MUST NOT block project open.
|
||||
9. Project-local setup configuration MUST live in a separate file at `.studio/setup.json`.
|
||||
10. Project-local setup MUST NOT participate in the `.studio/state.json` snapshot lifecycle.
|
||||
11. Project-local setup MUST be read through a dedicated DTO/file boundary when a consumer needs it.
|
||||
|
||||
## Accepted Wave-1 Categories
|
||||
|
||||
The main store MUST include:
|
||||
The main session-restoration store MUST include:
|
||||
|
||||
- `projectLocalSetup`
|
||||
- `shellLayout`
|
||||
- `openShellState`
|
||||
- `editorRestoration`
|
||||
|
||||
Wave-1 accepted meaning is:
|
||||
|
||||
- `projectLocalSetup`: project-local Studio setup required to operate on the project, including runtime paths such as the Prometeu runtime path;
|
||||
- `shellLayout`: restorable layout state already accepted by implementation, including divider positions and equivalent layout proportions for accepted workspaces such as `Assets` and `Code Editor`, `Project Navigator` expansion state, and editor dock-panel open/closed plus restored-size configuration;
|
||||
- `openShellState`: which workspace or equivalent shell-owned project view was open;
|
||||
- `editorRestoration`: open editor tabs and active tab.
|
||||
|
||||
## Project-Local Setup Configuration
|
||||
|
||||
Project-local setup is a separate persistence concern under `.studio/`.
|
||||
|
||||
Rules:
|
||||
|
||||
- project-local setup MUST live in `.studio/setup.json`;
|
||||
- project-local setup MUST be treated as project configuration rather than session state;
|
||||
- project-local setup MAY contain runtime-oriented values such as the Prometeu runtime path;
|
||||
- project-local setup MAY grow with additional manual or automatic configuration keys over time;
|
||||
- consumers such as `Play` MUST read project-local setup from the dedicated setup file rather than from `.studio/state.json`;
|
||||
- this revision uses a dry format change and MUST NOT preserve compatibility with the obsolete shape where `projectLocalSetup` was embedded in `.studio/state.json`.
|
||||
|
||||
## Explicit Exclusions
|
||||
|
||||
The main store MUST NOT include:
|
||||
The main session-restoration store MUST NOT include:
|
||||
|
||||
- project-local setup configuration;
|
||||
- project-local activity history;
|
||||
- derived cache;
|
||||
- transient hover-only or equivalent ephemeral UI state;
|
||||
- heavy operational output;
|
||||
- recomputable results that do not represent project-local setup or restoration state.
|
||||
- recomputable results that do not represent session restoration state.
|
||||
|
||||
`Project-local activity` may still live under `.studio/`, but it is a separate persistence concern and not part of the main store defined here.
|
||||
`Project-local activity` and project-local setup may still live under `.studio/`, but they are separate persistence concerns and not part of the main session-restoration store defined here.
|
||||
|
||||
## Ownership Rules
|
||||
|
||||
- shell and workspace UI may consume the main store through project-session-owned contracts;
|
||||
- shell and workspace UI may consume the main session-restoration store through project-session-owned contracts;
|
||||
- shell and workspace UI must not define competing primary persistence files for accepted wave-1 categories;
|
||||
- project-local setup may be consumed before a dedicated settings UI exists.
|
||||
- project-local setup may be consumed before a dedicated settings UI exists;
|
||||
- project-local setup readers must not turn the setup file into another session snapshot by convenience.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ import java.util.Objects;
|
||||
public final class ProjectStudioPaths {
|
||||
private static final String STUDIO_DIR = ".studio";
|
||||
private static final String ACTIVITIES_FILE = "activities.json";
|
||||
private static final String SETUP_FILE = "setup.json";
|
||||
private static final String STATE_FILE = "state.json";
|
||||
|
||||
private ProjectStudioPaths() {
|
||||
@ -32,4 +33,11 @@ public final class ProjectStudioPaths {
|
||||
.toAbsolutePath()
|
||||
.normalize();
|
||||
}
|
||||
|
||||
public static Path setupPath(ProjectReference projectReference) {
|
||||
return studioRoot(projectReference)
|
||||
.resolve(SETUP_FILE)
|
||||
.toAbsolutePath()
|
||||
.normalize();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
package p.studio.projectstate;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public record ProjectLocalStudioSetup(String prometeuRuntimePath) {
|
||||
public ProjectLocalStudioSetup {
|
||||
prometeuRuntimePath = normalizeText(prometeuRuntimePath);
|
||||
}
|
||||
|
||||
public static ProjectLocalStudioSetup defaults() {
|
||||
return new ProjectLocalStudioSetup(null);
|
||||
}
|
||||
|
||||
private static String normalizeText(final String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
final String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package p.studio.projectstate;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import p.studio.projects.ProjectReference;
|
||||
import p.studio.projects.ProjectStudioPaths;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public final class ProjectLocalStudioSetupService {
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
|
||||
public ProjectLocalStudioSetup load(final ProjectReference projectReference) {
|
||||
final Path setupPath = ProjectStudioPaths.setupPath(projectReference);
|
||||
if (!Files.isRegularFile(setupPath)) {
|
||||
return ProjectLocalStudioSetup.defaults();
|
||||
}
|
||||
|
||||
try {
|
||||
final ProjectLocalStudioSetup loaded = MAPPER.readValue(setupPath.toFile(), ProjectLocalStudioSetup.class);
|
||||
return loaded == null ? ProjectLocalStudioSetup.defaults() : loaded;
|
||||
} catch (IOException | RuntimeException ignored) {
|
||||
return ProjectLocalStudioSetup.defaults();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,6 @@ import java.util.List;
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public record ProjectLocalStudioState(
|
||||
int version,
|
||||
ProjectLocalSetup projectLocalSetup,
|
||||
ShellLayout shellLayout,
|
||||
OpenShellState openShellState,
|
||||
EditorRestorationState editorRestoration) {
|
||||
@ -17,7 +16,6 @@ public record ProjectLocalStudioState(
|
||||
|
||||
public ProjectLocalStudioState {
|
||||
version = version <= 0 ? CURRENT_VERSION : version;
|
||||
projectLocalSetup = projectLocalSetup == null ? ProjectLocalSetup.defaults() : projectLocalSetup.normalize();
|
||||
shellLayout = shellLayout == null ? ShellLayout.defaults() : shellLayout.normalize();
|
||||
openShellState = openShellState == null ? OpenShellState.defaults() : openShellState.normalize();
|
||||
editorRestoration = editorRestoration == null ? EditorRestorationState.defaults() : editorRestoration.normalize();
|
||||
@ -26,41 +24,21 @@ public record ProjectLocalStudioState(
|
||||
public static ProjectLocalStudioState defaults() {
|
||||
return new ProjectLocalStudioState(
|
||||
CURRENT_VERSION,
|
||||
ProjectLocalSetup.defaults(),
|
||||
ShellLayout.defaults(),
|
||||
OpenShellState.defaults(),
|
||||
EditorRestorationState.defaults());
|
||||
}
|
||||
|
||||
public ProjectLocalStudioState withShellLayout(final ShellLayout nextShellLayout) {
|
||||
return new ProjectLocalStudioState(version, projectLocalSetup, nextShellLayout, openShellState, editorRestoration);
|
||||
return new ProjectLocalStudioState(version, nextShellLayout, openShellState, editorRestoration);
|
||||
}
|
||||
|
||||
public ProjectLocalStudioState withOpenShellState(final OpenShellState nextOpenShellState) {
|
||||
return new ProjectLocalStudioState(version, projectLocalSetup, shellLayout, nextOpenShellState, editorRestoration);
|
||||
return new ProjectLocalStudioState(version, shellLayout, nextOpenShellState, editorRestoration);
|
||||
}
|
||||
|
||||
public ProjectLocalStudioState withEditorRestoration(final EditorRestorationState nextEditorRestoration) {
|
||||
return new ProjectLocalStudioState(version, projectLocalSetup, shellLayout, openShellState, nextEditorRestoration);
|
||||
}
|
||||
|
||||
public ProjectLocalStudioState withProjectLocalSetup(final ProjectLocalSetup nextProjectLocalSetup) {
|
||||
return new ProjectLocalStudioState(version, nextProjectLocalSetup, shellLayout, openShellState, editorRestoration);
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public record ProjectLocalSetup(String prometeuRuntimePath) {
|
||||
public ProjectLocalSetup {
|
||||
prometeuRuntimePath = normalizeText(prometeuRuntimePath);
|
||||
}
|
||||
|
||||
public static ProjectLocalSetup defaults() {
|
||||
return new ProjectLocalSetup(null);
|
||||
}
|
||||
|
||||
private ProjectLocalSetup normalize() {
|
||||
return new ProjectLocalSetup(prometeuRuntimePath);
|
||||
}
|
||||
return new ProjectLocalStudioState(version, shellLayout, openShellState, nextEditorRestoration);
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
|
||||
@ -98,6 +98,11 @@ public final class MainView extends BorderPane {
|
||||
editorWorkspace.reapplyPendingLayoutState();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
persistProjectLocalState();
|
||||
host.deactivateCurrentWorkspace();
|
||||
}
|
||||
|
||||
private void loadWorkspace(WorkspaceId workspaceId) {
|
||||
host.change(workspaceId);
|
||||
if (workspaceLifecycleInitialized) {
|
||||
|
||||
@ -154,6 +154,7 @@ public final class StudioWindowCoordinator {
|
||||
projectStage.setScene(scene);
|
||||
windowStateService.installProjectShellState(projectStage, projectReference, PROJECT_WIDTH, PROJECT_HEIGHT);
|
||||
projectStage.setOnHidden(ignored -> {
|
||||
mainView.close();
|
||||
projectSession.close();
|
||||
launcherView.reloadProjects();
|
||||
launcherStage.show();
|
||||
|
||||
@ -24,13 +24,7 @@ public final class WorkspaceHost extends StackPane {
|
||||
public void change(final WorkspaceId id) {
|
||||
if (currentWorkspaceId == id) return;
|
||||
|
||||
if (currentWorkspaceId != null) {
|
||||
final var oldWorkspace = workspaces.get(currentWorkspaceId);
|
||||
StudioWorkspaceLifecycleSupport.deactivate(oldWorkspace);
|
||||
final var n = oldWorkspace.rootNode();
|
||||
n.setVisible(false);
|
||||
n.setManaged(false);
|
||||
}
|
||||
deactivateCurrentWorkspace();
|
||||
|
||||
final var nextWorkspace = workspaces.get(id);
|
||||
if (nextWorkspace == null) {
|
||||
@ -44,4 +38,19 @@ public final class WorkspaceHost extends StackPane {
|
||||
currentWorkspaceId = id;
|
||||
StudioWorkspaceLifecycleSupport.activate(nextWorkspace);
|
||||
}
|
||||
|
||||
public void deactivateCurrentWorkspace() {
|
||||
if (currentWorkspaceId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final var oldWorkspace = workspaces.get(currentWorkspaceId);
|
||||
if (oldWorkspace != null) {
|
||||
StudioWorkspaceLifecycleSupport.deactivate(oldWorkspace);
|
||||
final var n = oldWorkspace.rootNode();
|
||||
n.setVisible(false);
|
||||
n.setManaged(false);
|
||||
}
|
||||
currentWorkspaceId = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,7 +57,6 @@ final class StudioProjectSessionFactoryTest {
|
||||
private ProjectReference loadedProjectReference;
|
||||
private final ProjectLocalStudioState loadedState = new ProjectLocalStudioState(
|
||||
ProjectLocalStudioState.CURRENT_VERSION,
|
||||
new ProjectLocalStudioState.ProjectLocalSetup("/opt/prometeu"),
|
||||
ProjectLocalStudioState.ShellLayout.defaults(),
|
||||
new ProjectLocalStudioState.OpenShellState("EDITOR"),
|
||||
ProjectLocalStudioState.EditorRestorationState.defaults());
|
||||
|
||||
@ -20,6 +20,7 @@ import p.studio.vfs.messages.VfsRefreshRequest;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
|
||||
final class StudioProjectSessionTest {
|
||||
@Test
|
||||
@ -55,12 +56,12 @@ final class StudioProjectSessionTest {
|
||||
stateService,
|
||||
ProjectLocalStudioState.defaults());
|
||||
final ProjectLocalStudioState nextState = ProjectLocalStudioState.defaults()
|
||||
.withProjectLocalSetup(new ProjectLocalStudioState.ProjectLocalSetup("/opt/prometeu/runtime"));
|
||||
.withOpenShellState(new ProjectLocalStudioState.OpenShellState("EDITOR"));
|
||||
|
||||
session.replaceProjectLocalStudioState(nextState);
|
||||
session.close();
|
||||
|
||||
assertEquals("/opt/prometeu/runtime", stateService.savedState.projectLocalSetup().prometeuRuntimePath());
|
||||
assertSame(nextState, stateService.savedState);
|
||||
}
|
||||
|
||||
private ProjectReference projectReference() {
|
||||
|
||||
@ -0,0 +1,54 @@
|
||||
package p.studio.projectstate;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import p.studio.projects.ProjectReference;
|
||||
import p.studio.projects.ProjectStudioPaths;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
final class ProjectLocalStudioSetupServiceTest {
|
||||
@TempDir
|
||||
Path tempDir;
|
||||
|
||||
@Test
|
||||
void loadsDedicatedProjectSetupFile() throws Exception {
|
||||
final ProjectLocalStudioSetupService service = new ProjectLocalStudioSetupService();
|
||||
final ProjectReference project = project("main");
|
||||
Files.createDirectories(ProjectStudioPaths.studioRoot(project));
|
||||
Files.writeString(
|
||||
ProjectStudioPaths.setupPath(project),
|
||||
"""
|
||||
{
|
||||
"prometeuRuntimePath": "/opt/prometeu/runtime"
|
||||
}
|
||||
""");
|
||||
|
||||
assertEquals(new ProjectLocalStudioSetup("/opt/prometeu/runtime"), service.load(project));
|
||||
}
|
||||
|
||||
@Test
|
||||
void missingDedicatedProjectSetupFileFallsBackToDefaults() {
|
||||
final ProjectLocalStudioSetupService service = new ProjectLocalStudioSetupService();
|
||||
|
||||
assertEquals(ProjectLocalStudioSetup.defaults(), service.load(project("main")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void malformedDedicatedProjectSetupFileFallsBackToDefaults() throws Exception {
|
||||
final ProjectLocalStudioSetupService service = new ProjectLocalStudioSetupService();
|
||||
final ProjectReference project = project("main");
|
||||
Files.createDirectories(ProjectStudioPaths.studioRoot(project));
|
||||
Files.writeString(ProjectStudioPaths.setupPath(project), "{ not valid json");
|
||||
|
||||
assertEquals(ProjectLocalStudioSetup.defaults(), service.load(project));
|
||||
}
|
||||
|
||||
private ProjectReference project(final String name) {
|
||||
final Path projectRoot = tempDir.resolve(name);
|
||||
return new ProjectReference("Main", "1.0.0", "pbs", 1, projectRoot);
|
||||
}
|
||||
}
|
||||
@ -22,7 +22,6 @@ final class ProjectLocalStudioStateServiceTest {
|
||||
final ProjectReference project = project("main");
|
||||
final ProjectLocalStudioState state = new ProjectLocalStudioState(
|
||||
ProjectLocalStudioState.CURRENT_VERSION,
|
||||
new ProjectLocalStudioState.ProjectLocalSetup("/opt/prometeu/runtime"),
|
||||
new ProjectLocalStudioState.ShellLayout(
|
||||
new ProjectLocalStudioState.EditorLayoutState(
|
||||
List.of(0.25d),
|
||||
@ -66,10 +65,7 @@ final class ProjectLocalStudioStateServiceTest {
|
||||
ProjectStudioPaths.statePath(project),
|
||||
"""
|
||||
{
|
||||
"version": 99,
|
||||
"projectLocalSetup": {
|
||||
"prometeuRuntimePath": "/opt/legacy/runtime"
|
||||
}
|
||||
"version": 99
|
||||
}
|
||||
""");
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user