Compare commits

..

10 Commits

Author SHA1 Message Date
2f289b9425
update gitignore
All checks were successful
JaCoCo Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 61.88% (17291/27941) * Branch Coverage: 52.91% (6692/12647) * Lines of Code: 27941 * Cyclomatic Complexity: 11191 #### Quality Gates Summary Output truncated.
Test / Build skipped: 11, passed: 577
Intrepid/Prometeu/Studio/pipeline/head This commit looks good
Intrepid/Prometeu/Studio/pipeline/pr-master This commit looks good
2026-05-08 10:30:54 +01:00
54339a95b8
implements PLN-0077 2026-05-08 10:15:17 +01:00
7cbe61f5eb
implements PLN-0076 2026-05-08 10:13:38 +01:00
7f40541e96
implements PLN-0075 2026-05-08 10:04:39 +01:00
240525286b
Wave 1 de assistencia editorial via LSP para PBS no VS Code 2026-05-08 09:48:14 +01:00
ef814b2420
housekeeping 2026-05-08 09:17:43 +01:00
0e6a2cd5bc
housekeeping 2026-05-07 14:53:33 +01:00
905d92afe7
Highlight color adjustments 2026-05-07 14:21:31 +01:00
dfad621d05
Frontend Visual Theme Spec and Retirement of Host-Consumed Semantic CSS 2026-05-06 17:20:38 +01:00
e23367b022
Frontend Visual Theme Spec and Retirement of Host-Consumed Semantic CSS 2026-05-06 15:50:35 +01:00
77 changed files with 4470 additions and 2807 deletions

View File

@ -1,12 +0,0 @@
{"type":"meta","next_id":{"DSC":12,"AGD":12,"DEC":9,"PLN":15,"LSN":26,"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":"in_progress","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":"accepted","created_at":"2026-03-30","updated_at":"2026-03-30"}],"decisions":[{"id":"DEC-0008","file":"DEC-0008-studio-code-editor-read-only-workspace-foundations.md","status":"accepted","created_at":"2026-03-30","updated_at":"2026-03-30","ref_agenda":"AGD-0010"}],"plans":[{"id":"PLN-0012","file":"PLN-0012-studio-code-editor-spec-propagation.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0008"]},{"id":"PLN-0013","file":"PLN-0013-editor-workspace-layout-and-passive-surfaces.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0008"]},{"id":"PLN-0014","file":"PLN-0014-project-navigator-snapshot-and-read-only-file-opening.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30","ref_decisions":["DEC-0008"]}],"lessons":[]}
{"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"}]}

View File

@ -1,13 +0,0 @@
{"type":"meta","next_id":{"DSC":13,"AGD":13,"DEC":10,"PLN":19,"LSN":27,"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":"open","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":[{"id":"AGD-0012","file":"AGD-0012-studio-editor-document-vfs-boundary.md","status":"in_progress","created_at":"2026-03-31","updated_at":"2026-03-31"}],"decisions":[{"id":"DEC-0009","file":"DEC-0009-studio-prometeu-vfs-project-document-boundary.md","status":"in_progress","created_at":"2026-03-31","updated_at":"2026-03-31","ref_agenda":"AGD-0012"}],"plans":[{"id":"PLN-0015","file":"PLN-0015-propagate-dec-0009-into-studio-specs.md","status":"done","created_at":"2026-03-31","updated_at":"2026-03-31","ref_decisions":["DEC-0009"]},{"id":"PLN-0016","file":"PLN-0016-build-prometeu-vfs-filesystem-backed-core.md","status":"done","created_at":"2026-03-31","updated_at":"2026-03-31","ref_decisions":["DEC-0009"]},{"id":"PLN-0017","file":"PLN-0017-add-studio-project-session-ownership-for-prometeu-vfs.md","status":"done","created_at":"2026-03-31","updated_at":"2026-03-31","ref_decisions":["DEC-0009"]},{"id":"PLN-0018","file":"PLN-0018-migrate-code-editor-to-prometeu-vfs.md","status":"done","created_at":"2026-03-31","updated_at":"2026-03-31","ref_decisions":["DEC-0009"]}],"lessons":[]}

View File

@ -0,0 +1,35 @@
{"type":"meta","next_id":{"DSC":35,"AGD":38,"DEC":35,"PLN":75,"LSN":47,"CLSN":1}}
{"type":"discussion","id":"DSC-0034","status":"in_progress","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[{"id":"AGD-0037","file":"AGD-0037-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0034","file":"DEC-0034-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0037"}],"plans":[{"id":"PLN-0072","file":"PLN-0072-frontend-semantic-host-projection-contract.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0073","file":"PLN-0073-lsp-semantic-host-projection-transport.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0074","file":"PLN-0074-vscode-semantic-host-projection-adapter.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]}],"lessons":[]}
{"type":"discussion","id":"DSC-0033","status":"in_progress","ticket":"frontend-visual-theme-spec-and-css-retirement","title":"Frontend visual theme spec and retirement of host-consumed semantic CSS","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","presentation","theming","studio","vscode","lsp","pbs"],"agendas":[{"id":"AGD-0036","file":"AGD-0036-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0033","file":"DEC-0033-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0036"}],"plans":[{"id":"PLN-0068","file":"PLN-0068-frontend-visual-contract-and-pbs-migration.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0069","file":"PLN-0069-lsp-visual-theme-transport-and-selection.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0070","file":"PLN-0070-studio-visual-theme-adapter-and-css-retirement.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0071","file":"PLN-0071-vscode-dynamic-theme-translation-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]}],"lessons":[]}
{"type":"discussion","id":"DSC-0032","status":"in_progress","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[{"id":"AGD-0035","file":"AGD-0035-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0032","file":"DEC-0032-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0035"}],"plans":[{"id":"PLN-0065","file":"PLN-0065-lsp-boundary-and-module-scaffolding.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0066","file":"PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0067","file":"PLN-0067-compiler-backed-dumb-lsp-server-baseline.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]}],"lessons":[]}
{"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]}
{"type":"discussion","id":"DSC-0030","status":"done","ticket":"studio-scene-pack-runtime-binary-contract","title":"Studio scene pack contract for runtime SCENE binary payload","created_at":"2026-04-24","updated_at":"2026-05-01","tags":["studio","packer","runtime","scene","asset-pack","binary-format","tiled"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0030-studio-scene-pack-runtime-binary-contract/LSN-0046-canonical-scene-owns-editorial-truth-while-pack-stays-request-driven.md","status":"done","created_at":"2026-05-01","updated_at":"2026-05-01"}]}
{"type":"discussion","id":"DSC-0029","status":"done","ticket":"studio-frame-composer-syscall-and-sprite-alignment","title":"Studio Alignment with Runtime FrameComposer Syscalls and Sprite Composition","created_at":"2026-04-18","updated_at":"2026-04-18","tags":["studio","compiler","pbs","stdlib","runtime-alignment","abi","syscall","frame-composer","sprites"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0041","file":"discussion/lessons/DSC-0029-studio-frame-composer-syscall-and-sprite-alignment/LSN-0041-composer-must-own-public-sprite-composition.md","status":"done","created_at":"2026-04-18","updated_at":"2026-04-18"}]}
{"type":"discussion","id":"DSC-0028","status":"done","ticket":"studio-tiled-parser-assets-scene-asset-type","title":"Tiled Parser and Scene Asset-Type Ownership in Assets Workspace","created_at":"2026-04-15","updated_at":"2026-04-23","tags":["studio","assets","scene","tiled","parser","asset-type"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0045","file":"discussion/lessons/DSC-0028-studio-tiled-parser-assets-scene-asset-type/LSN-0045-asset-owned-scene-bank-and-tiled-xml-workflow.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]}
{"type":"discussion","id":"DSC-0027","status":"abandoned","ticket":"studio-scene-workspace","title":"Scene Workspace for SCENE Authoring","created_at":"2026-04-14","updated_at":"2026-04-15","tags":["studio","workspace","scene","tilemap","asset","runtime-alignment"],"agendas":[{"id":"AGD-0029","file":"AGD-0029-studio-scene-workspace.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","_override_reason":"Explicit user request on 2026-04-15 to abandon the accepted agenda and its downstream work."}],"decisions":[{"id":"DEC-0026","file":"DEC-0026-studio-scene-workspace.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_agenda":"AGD-0029","_override_reason":"Explicit user request on 2026-04-15 to abandon the accepted decision and stop using it as normative guidance."}],"plans":[{"id":"PLN-0049","file":"PLN-0049-scene-workspace-spec-and-boundary-propagation.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0026"],"_override_reason":"Explicit user request on 2026-04-15 to abandon all plans derived from DEC-0026."},{"id":"PLN-0050","file":"PLN-0050-scene-workspace-shell-and-project-state-foundations.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0026"],"_override_reason":"Explicit user request on 2026-04-15 to abandon all plans derived from DEC-0026."},{"id":"PLN-0051","file":"PLN-0051-scene-artifact-and-assets-handoff-contract.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0026"],"_override_reason":"Explicit user request on 2026-04-15 to abandon all plans derived from DEC-0026."},{"id":"PLN-0052","file":"PLN-0052-scene-workspace-wave-1-tilemap-editor.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0026"],"_override_reason":"Explicit user request on 2026-04-15 to abandon all plans derived from DEC-0026."}],"lessons":[]}
{"type":"discussion","id":"DSC-0026","status":"done","ticket":"glyph-bank-naming-alignment-with-runtime","title":"Glyph Bank Naming Alignment with Runtime DEC-0006","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["packer","studio","naming","asset-contract","runtime-alignment","glyph-bank"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0040","file":"discussion/lessons/DSC-0026-glyph-bank-naming-alignment-with-runtime/LSN-0040-glyph-bank-artifact-naming-alignment.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
{"type":"discussion","id":"DSC-0025","status":"done","ticket":"packer-pipeline-metadata-ownership","title":"Pipeline Metadata Ownership and Runtime Contract","created_at":"2026-04-09","updated_at":"2026-04-10","tags":["packer","metadata","runtime-contract","tooling","studio"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0039","file":"discussion/lessons/DSC-0025-packer-pipeline-metadata-ownership/LSN-0039-runtime-header-boundary-and-tooling-owned-pipeline-metadata.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
{"type":"discussion","id":"DSC-0024","status":"done","ticket":"jacoco-reports-consolidation","title":"JaCoCo Reports Consolidation in Gradle","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["infra","gradle","jacoco","coverage","jenkins"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0038","file":"discussion/lessons/DSC-0024-jacoco-reports-consolidation/LSN-0038-jacoco-reports-consolidation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"},{"id":"LSN-0044","file":"discussion/lessons/DSC-0024-jacoco-reports-consolidation/LSN-0044-jenkins-jacoco-alignment.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]}
{"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":"done","ticket":"palette-management-in-studio","title":"Palette Management in Studio","created_at":"2026-03-26","updated_at":"2026-04-23","tags":["studio","legacy-import","palette-management","tile-bank","packer-boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0042","file":"discussion/lessons/DSC-0002-palette-management-in-studio/LSN-0042-schema-driven-palette-authoring-and-local-metadata-events.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]}
{"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":"abandoned","ticket":"tilemap-and-metatile-runtime-binary-layout","title":"Tilemap and Metatile Runtime Binary Layout","created_at":"2026-03-26","updated_at":"2026-04-24","tags":["packer","legacy-import","tilemap","metatile","runtime-layout"],"agendas":[{"id":"AGD-0004","file":"AGD-0004-tilemap-and-metatile-runtime-binary-layout.md","status":"abandoned","created_at":"2026-03-26","updated_at":"2026-04-24","_override_reason":"Explicit user request on 2026-04-24 to abandon AGD-0004 because the agenda is no longer valid."}],"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":"done","ticket":"studio-debugger-workspace-integration","title":"Integrate ../debugger into Studio as a dedicated workspace","created_at":"2026-03-30","updated_at":"2026-04-07","tags":["studio","debugger","workspace","integration","shell"],"agendas":[],"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":"done","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-06","tags":["studio","editor","scope-guides","braces","semantic-read","frontend-contract"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0034","file":"discussion/lessons/DSC-0016-studio-editor-scope-guides-and-brace-anchoring/LSN-0034-active-scope-gutter-and-frontend-owned-structural-anchors.md","status":"done","created_at":"2026-04-06","updated_at":"2026-04-06"}]}
{"type":"discussion","id":"DSC-0017","status":"done","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-06","tags":["studio","editor","inline-hints","inlay-hints","lsp","pbs","type-inference"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0035","file":"discussion/lessons/DSC-0017-studio-editor-inline-type-hints-for-let-bindings/LSN-0035-frontend-owned-inline-hints-with-decorative-inline-rendering.md","status":"done","created_at":"2026-04-06","updated_at":"2026-04-06"}]}
{"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"}]}
{"type":"discussion","id":"DSC-0020","status":"done","ticket":"studio-editor-indentation-policy-and-project-setup","title":"Indentation Policy, Status-Bar Semantics, and Project-Local Editor Setup","created_at":"2026-04-04","updated_at":"2026-04-04","tags":["studio","editor","indentation","tabs","setup","dot-studio","configuration","ux"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0033","file":"discussion/lessons/DSC-0020-studio-editor-indentation-policy-and-project-setup/LSN-0033-setup-owned-indentation-policy-and-project-bootstrap-defaults.md","status":"done","created_at":"2026-04-04","updated_at":"2026-04-04"}]}
{"type":"discussion","id":"DSC-0021","status":"done","ticket":"studio-frontend-editor-write-and-save-wave","title":"Enable Frontend Editing and Save in the Studio Code Editor","created_at":"2026-04-04","updated_at":"2026-04-06","tags":["studio","editor","frontend","write","save","vfs","lsp","pbs","access-policy"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0036","file":"discussion/lessons/DSC-0021-studio-frontend-editor-write-and-save-wave/LSN-0036-vfs-owned-frontend-edit-and-save-wave.md","status":"done","created_at":"2026-04-06","updated_at":"2026-04-06"}]}
{"type":"discussion","id":"DSC-0022","status":"done","ticket":"studio-play-stop-cartridge-flow","title":"Wire the Studio Play/Stop button to shipper phase 1 cartridge preparation and runtime execution","created_at":"2026-04-06","updated_at":"2026-04-07","tags":["studio","play-stop","shipper","runtime","cartridge","shell"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0043","file":"discussion/lessons/DSC-0022-studio-play-stop-and-debugger-integration/LSN-0043-studio-play-stop-and-debugger-integration.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]}
{"type":"discussion","id":"DSC-0023","status":"done","ticket":"gradle-version-catalog-migration","title":"Move dependency version management to Version Catalog (TOML)","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["gradle","buildSrc","dependency-management","version-catalog"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0037","file":"discussion/lessons/DSC-0023-gradle-version-catalog-migration/LSN-0037-gradle-version-catalog-adoption.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]}

View File

@ -0,0 +1,35 @@
{"type":"meta","next_id":{"DSC":35,"AGD":38,"DEC":35,"PLN":75,"LSN":49,"CLSN":1}}
{"type":"discussion","id":"DSC-0034","status":"done","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-07","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0048","file":"discussion/lessons/DSC-0034-frontend-semantic-host-projection-flexibility/LSN-0048-frontend-owned-semantic-vocabularies-with-declarative-host-projection.md","status":"done","created_at":"2026-05-07","updated_at":"2026-05-07"}]}
{"type":"discussion","id":"DSC-0033","status":"in_progress","ticket":"frontend-visual-theme-spec-and-css-retirement","title":"Frontend visual theme spec and retirement of host-consumed semantic CSS","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","presentation","theming","studio","vscode","lsp","pbs"],"agendas":[{"id":"AGD-0036","file":"AGD-0036-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0033","file":"DEC-0033-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0036"}],"plans":[{"id":"PLN-0068","file":"PLN-0068-frontend-visual-contract-and-pbs-migration.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0069","file":"PLN-0069-lsp-visual-theme-transport-and-selection.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0070","file":"PLN-0070-studio-visual-theme-adapter-and-css-retirement.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0071","file":"PLN-0071-vscode-dynamic-theme-translation-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]}],"lessons":[]}
{"type":"discussion","id":"DSC-0032","status":"done","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-07","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0047","file":"discussion/lessons/DSC-0032-studio-new-lsp-api-and-v1-boundary/LSN-0047-project-scoped-lsp-boundary-and-protocol-containment.md","status":"done","created_at":"2026-05-07","updated_at":"2026-05-07"}]}
{"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]}
{"type":"discussion","id":"DSC-0030","status":"done","ticket":"studio-scene-pack-runtime-binary-contract","title":"Studio scene pack contract for runtime SCENE binary payload","created_at":"2026-04-24","updated_at":"2026-05-01","tags":["studio","packer","runtime","scene","asset-pack","binary-format","tiled"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0030-studio-scene-pack-runtime-binary-contract/LSN-0046-canonical-scene-owns-editorial-truth-while-pack-stays-request-driven.md","status":"done","created_at":"2026-05-01","updated_at":"2026-05-01"}]}
{"type":"discussion","id":"DSC-0029","status":"done","ticket":"studio-frame-composer-syscall-and-sprite-alignment","title":"Studio Alignment with Runtime FrameComposer Syscalls and Sprite Composition","created_at":"2026-04-18","updated_at":"2026-04-18","tags":["studio","compiler","pbs","stdlib","runtime-alignment","abi","syscall","frame-composer","sprites"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0041","file":"discussion/lessons/DSC-0029-studio-frame-composer-syscall-and-sprite-alignment/LSN-0041-composer-must-own-public-sprite-composition.md","status":"done","created_at":"2026-04-18","updated_at":"2026-04-18"}]}
{"type":"discussion","id":"DSC-0028","status":"done","ticket":"studio-tiled-parser-assets-scene-asset-type","title":"Tiled Parser and Scene Asset-Type Ownership in Assets Workspace","created_at":"2026-04-15","updated_at":"2026-04-23","tags":["studio","assets","scene","tiled","parser","asset-type"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0045","file":"discussion/lessons/DSC-0028-studio-tiled-parser-assets-scene-asset-type/LSN-0045-asset-owned-scene-bank-and-tiled-xml-workflow.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]}
{"type":"discussion","id":"DSC-0027","status":"abandoned","ticket":"studio-scene-workspace","title":"Scene Workspace for SCENE Authoring","created_at":"2026-04-14","updated_at":"2026-04-15","tags":["studio","workspace","scene","tilemap","asset","runtime-alignment"],"agendas":[{"id":"AGD-0029","file":"AGD-0029-studio-scene-workspace.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","_override_reason":"Explicit user request on 2026-04-15 to abandon the accepted agenda and its downstream work."}],"decisions":[{"id":"DEC-0026","file":"DEC-0026-studio-scene-workspace.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_agenda":"AGD-0029","_override_reason":"Explicit user request on 2026-04-15 to abandon the accepted decision and stop using it as normative guidance."}],"plans":[{"id":"PLN-0049","file":"PLN-0049-scene-workspace-spec-and-boundary-propagation.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0026"],"_override_reason":"Explicit user request on 2026-04-15 to abandon all plans derived from DEC-0026."},{"id":"PLN-0050","file":"PLN-0050-scene-workspace-shell-and-project-state-foundations.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0026"],"_override_reason":"Explicit user request on 2026-04-15 to abandon all plans derived from DEC-0026."},{"id":"PLN-0051","file":"PLN-0051-scene-artifact-and-assets-handoff-contract.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0026"],"_override_reason":"Explicit user request on 2026-04-15 to abandon all plans derived from DEC-0026."},{"id":"PLN-0052","file":"PLN-0052-scene-workspace-wave-1-tilemap-editor.md","status":"abandoned","created_at":"2026-04-14","updated_at":"2026-04-15","ref_decisions":["DEC-0026"],"_override_reason":"Explicit user request on 2026-04-15 to abandon all plans derived from DEC-0026."}],"lessons":[]}
{"type":"discussion","id":"DSC-0026","status":"done","ticket":"glyph-bank-naming-alignment-with-runtime","title":"Glyph Bank Naming Alignment with Runtime DEC-0006","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["packer","studio","naming","asset-contract","runtime-alignment","glyph-bank"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0040","file":"discussion/lessons/DSC-0026-glyph-bank-naming-alignment-with-runtime/LSN-0040-glyph-bank-artifact-naming-alignment.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
{"type":"discussion","id":"DSC-0025","status":"done","ticket":"packer-pipeline-metadata-ownership","title":"Pipeline Metadata Ownership and Runtime Contract","created_at":"2026-04-09","updated_at":"2026-04-10","tags":["packer","metadata","runtime-contract","tooling","studio"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0039","file":"discussion/lessons/DSC-0025-packer-pipeline-metadata-ownership/LSN-0039-runtime-header-boundary-and-tooling-owned-pipeline-metadata.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
{"type":"discussion","id":"DSC-0024","status":"done","ticket":"jacoco-reports-consolidation","title":"JaCoCo Reports Consolidation in Gradle","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["infra","gradle","jacoco","coverage","jenkins"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0038","file":"discussion/lessons/DSC-0024-jacoco-reports-consolidation/LSN-0038-jacoco-reports-consolidation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"},{"id":"LSN-0044","file":"discussion/lessons/DSC-0024-jacoco-reports-consolidation/LSN-0044-jenkins-jacoco-alignment.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]}
{"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":"done","ticket":"palette-management-in-studio","title":"Palette Management in Studio","created_at":"2026-03-26","updated_at":"2026-04-23","tags":["studio","legacy-import","palette-management","tile-bank","packer-boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0042","file":"discussion/lessons/DSC-0002-palette-management-in-studio/LSN-0042-schema-driven-palette-authoring-and-local-metadata-events.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]}
{"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":"abandoned","ticket":"tilemap-and-metatile-runtime-binary-layout","title":"Tilemap and Metatile Runtime Binary Layout","created_at":"2026-03-26","updated_at":"2026-04-24","tags":["packer","legacy-import","tilemap","metatile","runtime-layout"],"agendas":[{"id":"AGD-0004","file":"AGD-0004-tilemap-and-metatile-runtime-binary-layout.md","status":"abandoned","created_at":"2026-03-26","updated_at":"2026-04-24","_override_reason":"Explicit user request on 2026-04-24 to abandon AGD-0004 because the agenda is no longer valid."}],"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":"done","ticket":"studio-debugger-workspace-integration","title":"Integrate ../debugger into Studio as a dedicated workspace","created_at":"2026-03-30","updated_at":"2026-04-07","tags":["studio","debugger","workspace","integration","shell"],"agendas":[],"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":"done","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-06","tags":["studio","editor","scope-guides","braces","semantic-read","frontend-contract"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0034","file":"discussion/lessons/DSC-0016-studio-editor-scope-guides-and-brace-anchoring/LSN-0034-active-scope-gutter-and-frontend-owned-structural-anchors.md","status":"done","created_at":"2026-04-06","updated_at":"2026-04-06"}]}
{"type":"discussion","id":"DSC-0017","status":"done","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-06","tags":["studio","editor","inline-hints","inlay-hints","lsp","pbs","type-inference"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0035","file":"discussion/lessons/DSC-0017-studio-editor-inline-type-hints-for-let-bindings/LSN-0035-frontend-owned-inline-hints-with-decorative-inline-rendering.md","status":"done","created_at":"2026-04-06","updated_at":"2026-04-06"}]}
{"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"}]}
{"type":"discussion","id":"DSC-0020","status":"done","ticket":"studio-editor-indentation-policy-and-project-setup","title":"Indentation Policy, Status-Bar Semantics, and Project-Local Editor Setup","created_at":"2026-04-04","updated_at":"2026-04-04","tags":["studio","editor","indentation","tabs","setup","dot-studio","configuration","ux"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0033","file":"discussion/lessons/DSC-0020-studio-editor-indentation-policy-and-project-setup/LSN-0033-setup-owned-indentation-policy-and-project-bootstrap-defaults.md","status":"done","created_at":"2026-04-04","updated_at":"2026-04-04"}]}
{"type":"discussion","id":"DSC-0021","status":"done","ticket":"studio-frontend-editor-write-and-save-wave","title":"Enable Frontend Editing and Save in the Studio Code Editor","created_at":"2026-04-04","updated_at":"2026-04-06","tags":["studio","editor","frontend","write","save","vfs","lsp","pbs","access-policy"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0036","file":"discussion/lessons/DSC-0021-studio-frontend-editor-write-and-save-wave/LSN-0036-vfs-owned-frontend-edit-and-save-wave.md","status":"done","created_at":"2026-04-06","updated_at":"2026-04-06"}]}
{"type":"discussion","id":"DSC-0022","status":"done","ticket":"studio-play-stop-cartridge-flow","title":"Wire the Studio Play/Stop button to shipper phase 1 cartridge preparation and runtime execution","created_at":"2026-04-06","updated_at":"2026-04-07","tags":["studio","play-stop","shipper","runtime","cartridge","shell"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0043","file":"discussion/lessons/DSC-0022-studio-play-stop-and-debugger-integration/LSN-0043-studio-play-stop-and-debugger-integration.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]}
{"type":"discussion","id":"DSC-0023","status":"done","ticket":"gradle-version-catalog-migration","title":"Move dependency version management to Version Catalog (TOML)","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["gradle","buildSrc","dependency-management","version-catalog"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0037","file":"discussion/lessons/DSC-0023-gradle-version-catalog-migration/LSN-0037-gradle-version-catalog-adoption.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]}

View File

@ -1,8 +1,10 @@
{"type":"meta","next_id":{"DSC":35,"AGD":38,"DEC":35,"PLN":75,"LSN":47,"CLSN":1}}
{"type":"discussion","id":"DSC-0034","status":"in_progress","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[{"id":"AGD-0037","file":"AGD-0037-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0034","file":"DEC-0034-frontend-semantic-host-projection-flexibility.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0037"}],"plans":[{"id":"PLN-0072","file":"PLN-0072-frontend-semantic-host-projection-contract.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0073","file":"PLN-0073-lsp-semantic-host-projection-transport.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]},{"id":"PLN-0074","file":"PLN-0074-vscode-semantic-host-projection-adapter.md","status":"done","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0034"]}],"lessons":[]}
{"type":"discussion","id":"DSC-0033","status":"in_progress","ticket":"frontend-visual-theme-spec-and-css-retirement","title":"Frontend visual theme spec and retirement of host-consumed semantic CSS","created_at":"2026-05-06","updated_at":"2026-05-06","tags":["compiler","compiler-general","frontend","presentation","theming","studio","vscode","lsp","pbs"],"agendas":[{"id":"AGD-0036","file":"AGD-0036-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06"}],"decisions":[{"id":"DEC-0033","file":"DEC-0033-frontend-visual-theme-spec-and-css-retirement.md","status":"accepted","created_at":"2026-05-06","updated_at":"2026-05-06","ref_agenda":"AGD-0036"}],"plans":[{"id":"PLN-0068","file":"PLN-0068-frontend-visual-contract-and-pbs-migration.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0069","file":"PLN-0069-lsp-visual-theme-transport-and-selection.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0070","file":"PLN-0070-studio-visual-theme-adapter-and-css-retirement.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]},{"id":"PLN-0071","file":"PLN-0071-vscode-dynamic-theme-translation-adapter.md","status":"open","created_at":"2026-05-06","updated_at":"2026-05-06","ref_decisions":["DEC-0033"]}],"lessons":[]}
{"type":"discussion","id":"DSC-0032","status":"in_progress","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[{"id":"AGD-0035","file":"AGD-0035-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0032","file":"DEC-0032-studio-new-lsp-api-and-v1-boundary.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0035"}],"plans":[{"id":"PLN-0065","file":"PLN-0065-lsp-boundary-and-module-scaffolding.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0066","file":"PLN-0066-project-scoped-lsp-server-lifecycle-in-studio.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]},{"id":"PLN-0067","file":"PLN-0067-compiler-backed-dumb-lsp-server-baseline.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0032"]}],"lessons":[]}
{"type":"discussion","id":"DSC-0031","status":"in_progress","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-05","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[{"id":"AGD-0034","file":"AGD-0034-vscode-editor-migration-feasibility.md","status":"accepted","created_at":"2026-05-05","updated_at":"2026-05-05"}],"decisions":[{"id":"DEC-0031","file":"DEC-0031-studio-editor-workspace-cleanup.md","status":"in_progress","created_at":"2026-05-05","updated_at":"2026-05-05","ref_agenda":"AGD-0034"}],"plans":[{"id":"PLN-0062","file":"PLN-0062-shell-session-and-state-cleanup-after-editor-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0063","file":"PLN-0063-legacy-lsp-and-vfs-module-removal-with-runtime-preservation.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]},{"id":"PLN-0064","file":"PLN-0064-normative-test-and-lesson-cleanup-for-editor-stack-removal.md","status":"done","created_at":"2026-05-05","updated_at":"2026-05-05","ref_decisions":["DEC-0031"]}],"lessons":[]}
{"type":"meta","next_id":{"DSC":37,"AGD":40,"DEC":36,"PLN":78,"LSN":51,"CLSN":1}}
{"type":"discussion","id":"DSC-0036","status":"open","ticket":"pbs-symbol-documentation-and-hover-markdown","title":"Modelo de documentacao de simbolos em PBS e consumo markdown no hover","created_at":"2026-05-08","updated_at":"2026-05-08","tags":["compiler","compiler-pbs","studio","lsp","vscode","editor","hover","documentation","markdown"],"agendas":[{"id":"AGD-0039","file":"AGD-0039-pbs-symbol-documentation-and-hover-markdown.md","status":"open","created_at":"2026-05-08","updated_at":"2026-05-08"}],"decisions":[],"plans":[],"lessons":[]}
{"type":"discussion","id":"DSC-0035","status":"in_progress","ticket":"pbs-lsp-editor-assistance-wave-1","title":"Wave 1 de assistencia editorial via LSP para PBS no VS Code","created_at":"2026-05-08","updated_at":"2026-05-08","tags":["studio","lsp","vscode","compiler","compiler-pbs","editor","completion","hover","signature-help"],"agendas":[{"id":"AGD-0038","file":"AGD-0038-pbs-lsp-editor-assistance-wave-1.md","status":"accepted","created_at":"2026-05-08","updated_at":"2026-05-08"}],"decisions":[{"id":"DEC-0035","file":"DEC-0035-pbs-lsp-editor-assistance-wave-1.md","status":"accepted","created_at":"2026-05-08","updated_at":"2026-05-08","ref_agenda":"AGD-0038"}],"plans":[{"id":"PLN-0075","file":"PLN-0075-pbs-editorial-resolution-surface-for-symbols-members-and-signatures.md","status":"open","created_at":"2026-05-08","updated_at":"2026-05-08","ref_decisions":["DEC-0035"]},{"id":"PLN-0076","file":"PLN-0076-lsp-completion-hover-and-signature-help-over-editorial-resolution.md","status":"open","created_at":"2026-05-08","updated_at":"2026-05-08","ref_decisions":["DEC-0035"]},{"id":"PLN-0077","file":"PLN-0077-vscode-consumption-and-wave-1-editor-assistance-validation.md","status":"open","created_at":"2026-05-08","updated_at":"2026-05-08","ref_decisions":["DEC-0035"]}],"lessons":[]}
{"type":"discussion","id":"DSC-0034","status":"done","ticket":"frontend-semantic-host-projection-flexibility","title":"Frontend semantic vocabulary flexibility and declarative host projection","created_at":"2026-05-06","updated_at":"2026-05-07","tags":["compiler","compiler-general","frontend","semantics","vscode","host-projection","lsp"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0048","file":"discussion/lessons/DSC-0034-frontend-semantic-host-projection-flexibility/LSN-0048-frontend-owned-semantic-vocabularies-with-declarative-host-projection.md","status":"done","created_at":"2026-05-07","updated_at":"2026-05-07"}]}
{"type":"discussion","id":"DSC-0033","status":"done","ticket":"frontend-visual-theme-spec-and-css-retirement","title":"Frontend visual theme spec and retirement of host-consumed semantic CSS","created_at":"2026-05-06","updated_at":"2026-05-08","tags":["compiler","compiler-general","frontend","presentation","theming","studio","vscode","lsp","pbs"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0050","file":"discussion/lessons/DSC-0033-frontend-visual-theme-spec-and-css-retirement/LSN-0050-frontend-owned-visual-themes-with-structured-contract-and-host-adapters.md","status":"done","created_at":"2026-05-08","updated_at":"2026-05-08"}]}
{"type":"discussion","id":"DSC-0032","status":"done","ticket":"studio-new-lsp-api-and-v1-boundary","title":"Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code","created_at":"2026-05-05","updated_at":"2026-05-07","tags":["studio","lsp","vscode","protocol","api","boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0047","file":"discussion/lessons/DSC-0032-studio-new-lsp-api-and-v1-boundary/LSN-0047-project-scoped-lsp-boundary-and-protocol-containment.md","status":"done","created_at":"2026-05-07","updated_at":"2026-05-07"}]}
{"type":"discussion","id":"DSC-0031","status":"done","ticket":"studio-editor-workspace-cleanup","title":"Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados","created_at":"2026-05-05","updated_at":"2026-05-08","tags":["studio","editor","cleanup","vfs","lsp","migration"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0049","file":"discussion/lessons/DSC-0031-studio-editor-workspace-cleanup/LSN-0049-remove-the-embedded-editor-stack-before-rebuilding-code-workflows.md","status":"done","created_at":"2026-05-08","updated_at":"2026-05-08"}]}
{"type":"discussion","id":"DSC-0030","status":"done","ticket":"studio-scene-pack-runtime-binary-contract","title":"Studio scene pack contract for runtime SCENE binary payload","created_at":"2026-04-24","updated_at":"2026-05-01","tags":["studio","packer","runtime","scene","asset-pack","binary-format","tiled"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0030-studio-scene-pack-runtime-binary-contract/LSN-0046-canonical-scene-owns-editorial-truth-while-pack-stays-request-driven.md","status":"done","created_at":"2026-05-01","updated_at":"2026-05-01"}]}
{"type":"discussion","id":"DSC-0029","status":"done","ticket":"studio-frame-composer-syscall-and-sprite-alignment","title":"Studio Alignment with Runtime FrameComposer Syscalls and Sprite Composition","created_at":"2026-04-18","updated_at":"2026-04-18","tags":["studio","compiler","pbs","stdlib","runtime-alignment","abi","syscall","frame-composer","sprites"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0041","file":"discussion/lessons/DSC-0029-studio-frame-composer-syscall-and-sprite-alignment/LSN-0041-composer-must-own-public-sprite-composition.md","status":"done","created_at":"2026-04-18","updated_at":"2026-04-18"}]}
{"type":"discussion","id":"DSC-0028","status":"done","ticket":"studio-tiled-parser-assets-scene-asset-type","title":"Tiled Parser and Scene Asset-Type Ownership in Assets Workspace","created_at":"2026-04-15","updated_at":"2026-04-23","tags":["studio","assets","scene","tiled","parser","asset-type"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0045","file":"discussion/lessons/DSC-0028-studio-tiled-parser-assets-scene-asset-type/LSN-0045-asset-owned-scene-bank-and-tiled-xml-workflow.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]}

View File

@ -0,0 +1,84 @@
---
id: LSN-0049
discussion: DSC-0031
title: Remove the embedded editor stack before rebuilding code workflows
status: done
created: 2026-05-08
updated: 2026-05-08
tags: [studio, editor, cleanup, lsp, vfs, shell, migration]
---
## Original Problem
Studio still carried an embedded `Code Editor` workspace together with a `prometeu-vfs` boundary and a legacy `prometeu-lsp` path that existed only to support that editor.
That stack had become architectural drag:
- the JavaFX editor was no longer a product direction;
- the legacy `VFS` and `LSP` contracts were shaped around that editor model;
- shell state and project session still persisted editor-specific assumptions;
- and keeping those surfaces alive made any future code-backend redesign harder.
## Consolidated Decision
`DEC-0031` locked a full cleanup of the embedded editor stack.
The repository removed:
- the `Code Editor` workspace as an active Studio surface;
- the legacy editor-owned `VFS` boundary;
- the legacy editor-era `LSP` assumptions;
- shell/session/state dependencies that expected the editor to exist;
- and normative references that treated that stack as current architecture.
The decision also locked an equally important limit:
- this cleanup was not allowed to define the future code backend;
- a replacement LSP or automation boundary had to come later, in separate discussion.
## Final Result
The Studio shell now opens with surviving workspaces only: `Assets`, `Debug`, and `Shipper`.
Project-local state no longer persists editor restoration or editor layout fields, while still loading old state safely and falling back to surviving shell behavior.
The cleanup also succeeded without freezing the repository in a "no LSP ever again" state.
Later work in `DSC-0032` introduced a new project-scoped LSP boundary as separate architecture, which is exactly what `DEC-0031` required: remove the old stack first, then rebuild cleanly under a new decision.
## Implementation Notes
The cleanup landed in three coordinated waves:
1. shell/session/state cleanup removed `WorkspaceId.EDITOR`, editor restoration state, and editor-owned session composition;
2. the old editor-era `VFS` and `LSP` stack stopped being the active Studio foundation;
3. specs, tests, and historical references were revised so the removed editor stack no longer appears as current product guidance.
This produced an important boundary reset:
- Studio remains responsible for launcher, assets, shipper, debug, build, and run orchestration;
- code-editing architecture is no longer smuggled in through dead UI or legacy session seams.
## Example
Before the cleanup, an old `.studio/state.json` could still restore editor-centric state.
After the cleanup, the same persisted payload is treated defensively:
- old editor fields are ignored;
- the selected workspace falls back safely when `EDITOR` is present;
- the project reopens into a surviving workspace instead of reviving a dead surface.
## Pitfalls and Anti-Patterns
- Do not preserve dead editor-era boundaries "for compatibility" when the product direction has already moved.
- Do not treat naming continuity as architectural continuity. A later `prometeu-lsp` module can be valid if it comes from a new discussion and a new boundary.
- Do not leave project-local state as an accidental migration trap; persisted legacy fields must degrade safely.
## References
- `AGD-0034` Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados
- `DEC-0031` Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados
- `PLN-0062` Shell Session and State Cleanup After Editor Removal
- `PLN-0063` Legacy LSP and VFS Module Removal with Runtime Preservation
- `PLN-0064` Normative Test and Lesson Cleanup for Editor Stack Removal
- `LSN-0047` Project-scoped LSP boundary and protocol containment

View File

@ -0,0 +1,106 @@
---
id: LSN-0047
ticket: studio-new-lsp-api-and-v1-boundary
title: Project-Scoped LSP Boundary and Protocol Containment
created: 2026-05-07
tags: [studio, lsp, vscode, protocol, api, boundary, compiler]
---
## Context
After the legacy embedded editor stack was removed, Prometeu needed a new LSP baseline without repeating the old mistake of collapsing protocol, session lifecycle, host UI, and semantic ownership into one module.
The main architectural pressure came from two facts:
- the VS Code extension already existed as a real LSP client over TCP,
- and the compiler already existed as the canonical owner of semantic behavior.
That meant the missing piece was not "add editor features first". The missing piece was a strict boundary that let the Studio host, the protocol adapter, and the compiler evolve without contaminating each other.
## Key Decisions
### Keep `lsp-api` Minimal and Internal
**What:**
`lsp-api` became a narrow internal Studio boundary, starting with project-scoped lifecycle operations such as boot and shutdown instead of mirroring the LSP protocol.
**Why:**
The Studio needed a reusable internal service boundary, not a second copy of the external wire protocol.
**Trade-offs:**
The API starts intentionally small and may need explicit growth later, but that is safer than locking protocol-shaped DTOs into the internal architecture too early.
### Contain `LSP4J` and Protocol DTOs Inside `lsp-v1`
**What:**
`lsp-v1` became the only concrete protocol adapter and the only module allowed to depend on `LSP4J`.
**Why:**
Protocol libraries are integration details. If they leak outward, the host architecture starts depending on the current transport and implementation framework instead of on stable domain boundaries.
**Trade-offs:**
This forces explicit mapping layers and a little more ceremony, but it keeps protocol churn from infecting the rest of the codebase.
### Make the Server Lifecycle Project-Scoped
**What:**
The LSP server now belongs to project open/close lifecycle instead of global Studio process startup.
**Why:**
Project scope is the real ownership boundary for source roots, compiler context, and editor-facing behavior.
**Trade-offs:**
Lifecycle wiring is slightly more involved, but resource ownership becomes predictable and multi-project behavior stays sane.
### Keep `compiler` as Semantic Owner Even in a Dumb First Wave
**What:**
The baseline server remained intentionally simple in behavior, but its request handling already routes through compiler-facing bridge seams.
**Why:**
A "temporary mock" becomes dangerous when it also becomes the architecture. The repository needed a structurally correct baseline before adding semantic depth.
**Trade-offs:**
Wave 1 delivered less feature richness, but it created a safe foundation for later layering.
## Patterns and Algorithms
### Pattern: Internal Boundary, External Adapter
The stable split is:
1. `lsp-api` exposes internal lifecycle operations,
2. `lsp-v1` speaks protocol and transport,
3. `compiler` owns semantic and analysis behavior,
4. the VS Code extension remains an ordinary external LSP client.
### Pattern: Build the Seams Before the Features
The server can begin "dumb" in capability coverage if:
- the lifecycle boundary is already correct,
- compiler access already flows through explicit bridge services,
- and protocol containment is already enforced.
That sequence is safer than shipping richer features on top of a blurred module boundary.
## Pitfalls
- Do not let `lsp-api` grow into a shadow copy of the LSP protocol.
- Do not import `LSP4J` outside `lsp-v1`, even for convenience.
- Do not move semantic ownership into the protocol adapter just because the adapter is the caller-facing layer.
- Do not boot a global server for the entire Studio process when the actual ownership boundary is the project session.
- Do not treat a connectivity mock as an acceptable long-term module shape.
## References
- `DEC-0032` Boundary normativo entre lsp-api, lsp-v1 e a extensao VS Code
- `PLN-0065` LSP Boundary and Module Scaffolding
- `PLN-0066` Project-Scoped LSP Server Lifecycle in Studio
- `PLN-0067` Compiler-Backed Dumb LSP Server Baseline
## Takeaways
- Protocol adapters should stay narrow and concrete; internal Studio boundaries should stay protocol-agnostic.
- Project-scoped lifecycle is the correct owner for the LSP server.
- A dumb first wave is acceptable only when the architecture is already correct.

View File

@ -0,0 +1,93 @@
---
id: LSN-0050
discussion: DSC-0033
title: Frontend-owned visual themes with structured contract and host adapters
status: done
created: 2026-05-08
updated: 2026-05-08
tags: [compiler, compiler-general, frontend, presentation, theming, lsp, vscode, pbs]
---
## Original Problem
Frontend semantic presentation was frontend-owned in principle, but not in a form that could survive multiple hosts.
PBS still depended on authored semantic CSS as the practical visual source of truth, which created three problems:
- CSS was a host-facing artifact rather than a compiler-general contract;
- VS Code could only approximate frontend intent through manual translation;
- every host risked drifting away from the frontend's real visual identity.
## Consolidated Decision
`DEC-0033` replaced authored host-consumed semantic CSS with a structured frontend-owned visual contract.
That contract now owns:
- the frontend theme list;
- the default active theme;
- token-scoped styles;
- editor-surface palette data;
- and host projections used to translate frontend semantic keys into host-native semantic selectors.
Hosts are adapters over this data.
They do not own frontend visual truth.
## Final Result
The canonical visual source now lives in `FrontendSemanticPresentationSpec`, with concrete PBS theme data and host projections authored in structured Java models instead of CSS resources.
The new LSP path transports:
- frontend semantic keys;
- visual themes;
- active theme identity;
- and host projection metadata.
The VS Code extension consumes that payload and writes semantic token and workbench color customizations dynamically, which means routine frontend color changes no longer require hand-edited extension theme tables.
The old PBS semantic CSS still exists only as migration residue and derivative compatibility material.
It is no longer the authored canonical contract.
## Implementation Notes
The decision was realized across four layers:
1. compiler/frontend metadata grew a structured presentation contract;
2. PBS migrated its theme definition into that contract;
3. the LSP description path started exporting visual themes and host projections;
4. the VS Code extension became a mechanical translator of the contract at runtime.
This also clarified the relationship between `DSC-0033` and `DSC-0034`:
- `DSC-0033` established the structured theme contract and CSS retirement;
- `DSC-0034` established that host projections belong in the frontend contract rather than in the host.
Together they define the current highlight pipeline.
## Example
For PBS today:
- the frontend publishes semantic keys such as `pbs-keyword` and `pbs-service`;
- the same frontend publishes the canonical theme colors and emphasis flags for those keys;
- the LSP sends the theme plus a `vscode` host projection;
- the VS Code extension applies both the canonical semantic selectors and the projected host selectors.
This is why a color change in PBS theme data can flow to VS Code without a new curated palette in `package.json`.
## Pitfalls and Anti-Patterns
- Do not reintroduce CSS as a silent second source of truth.
- Do not move frontend theme authorship into host adapters just because one host has capability gaps.
- Do not collapse frontend semantic identity into generic host categories during transport; host categories are projections, not the canonical vocabulary.
## References
- `AGD-0036` Frontend Visual Theme Spec and Retirement of Host-Consumed Semantic CSS
- `DEC-0033` Frontend-owned visual theme spec as canonical presentation contract
- `PLN-0068` Frontend Visual Contract and PBS Migration
- `PLN-0069` LSP Visual Theme Transport and Theme Selection Propagation
- `PLN-0070` Studio Visual Theme Adapter and CSS Retirement
- `PLN-0071` VS Code Dynamic Theme Translation Adapter
- `LSN-0048` Frontend-owned semantic vocabularies with declarative host projection

View File

@ -0,0 +1,90 @@
---
id: LSN-0048
ticket: frontend-semantic-host-projection-flexibility
title: Frontend-Owned Semantic Vocabularies with Declarative Host Projection
created: 2026-05-07
tags: [compiler, compiler-general, frontend, semantics, vscode, host-projection, lsp]
---
## Context
Prometeu had already established that frontend-owned visual themes should remain canonical.
The remaining semantic risk was subtler: VS Code prefers host-shaped token categories, and that pressure could easily turn the host taxonomy into the real source of semantic truth.
This discussion closed that gap by making semantic ownership explicit:
- the frontend keeps the canonical semantic vocabulary,
- host adaptation is additional metadata,
- and the adapter translates mechanically instead of inventing semantic policy.
## Key Decisions
### Keep Frontend Semantic Keys Canonical
**What:**
Each frontend remains free to define and evolve its own semantic keys, and those keys stay canonical across the stack.
**Why:**
Semantic meaning belongs to the language frontend, not to a single host's preferred category system.
**Trade-offs:**
Adapters must handle more varied vocabularies, but that is the correct cost of preserving frontend ownership.
### Add Declarative Host Projection Instead of Global Normalization
**What:**
The frontend now authors host projection metadata describing how canonical semantic keys should map into VS Code token types, modifiers, and fallbacks.
**Why:**
Hosts still need a practical adaptation path, but that adaptation should be explicit projection data rather than a hidden normalization rule.
**Trade-offs:**
The contract grows an extra layer, but it stays declarative and prevents semantic meaning from being reauthored inside the adapter.
### Keep LSP and the Extension Mechanical
**What:**
LSP transports canonical keys plus projection metadata, and the VS Code extension consumes both mechanically.
**Why:**
If either layer starts hand-mapping semantic meaning, the host stack becomes the de facto author of language semantics.
**Trade-offs:**
The transport and adapter need clearer model shapes, but their responsibilities stay cleaner and more reusable.
## Patterns and Algorithms
### Pattern: Canonical Vocabulary Plus Per-Host Projection
The stable flow is:
1. frontend defines semantic keys,
2. frontend defines host projections for those keys,
3. LSP transports canonical keys and projection data together,
4. the host adapter applies the projection without reinterpretation.
### Pattern: Mechanical Translation with Explicit Fallbacks
Projection metadata should say not only the preferred host token type, but also the fallback when the host cannot represent the frontend key exactly.
That keeps fallback behavior visible and reviewable instead of implicit in adapter code.
## Pitfalls
- Do not collapse frontend semantic keys into a repository-wide host taxonomy.
- Do not hide semantic policy inside the VS Code extension just because the platform has its own token vocabulary.
- Do not transport only host-shaped token types and discard canonical frontend identity.
- Do not confuse projection metadata with the canonical semantic contract itself.
## References
- `DEC-0034` Frontend semantic vocabularies remain canonical and hosts consume declarative projections
- `PLN-0072` Frontend Semantic Host Projection Contract
- `PLN-0073` LSP Semantic Host Projection Transport
- `PLN-0074` VS Code Semantic Host Projection Adapter
- `DEC-0033` Frontend-owned visual theme spec as canonical presentation contract
## Takeaways
- Semantic ownership stays with the frontend even when the host prefers a different taxonomy.
- Host projection is the right adaptation mechanism; global normalization is not.
- LSP and host adapters stay healthier when they translate declaratively instead of authoring semantic meaning.

View File

@ -1,106 +0,0 @@
---
id: AGD-0034
ticket: studio-editor-workspace-cleanup
title: Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados
status: accepted
created: 2026-05-05
resolved: 2026-05-05
decision: DEC-0031
tags: [studio, editor, cleanup, vfs, lsp, migration]
---
## Pain
O repositório ainda carrega um `Workspace Editor` no `prometeu-studio` junto com camadas de `VFS` e `LSP` desenhadas especificamente para esse editor embutido.
Esse conjunto virou um legado arquitetural:
- o editor JavaFX não é mais a direção do produto;
- o `prometeu-vfs` atual está acoplado ao modelo editorial do editor embutido;
- o `prometeu-lsp` atual está acoplado ao `VFS` e ao host local do Studio;
- e manter essa base viva só aumenta o custo da futura reconstrução correta do backend de código.
## Context
- O monorepo já separa `prometeu-compiler`, `prometeu-packer` e `prometeu-studio`, mas o `prometeu-lsp` e o `prometeu-vfs` atuais nasceram como suporte ao editor embutido.
- A capacidade de compilação dos projetos deve continuar existindo no Studio.
- O alvo imediato não é discutir o novo LSP nem o novo contrato de automação.
- O alvo imediato é remover:
- o `Workspace Editor`;
- o `prometeu-lsp` legado usado por ele;
- e o `prometeu-vfs` acoplado a esse modelo editorial.
- O Studio continua existindo como produto fora do editor:
- shell e launcher de projeto;
- assets workspace;
- shipper/build surfaces;
- play/stop e integração com runtime/debug.
- Uma agenda futura poderá discutir a reconstrução do backend de código e do novo servidor LSP, mas isso fica fora deste artefato.
## Open Questions
- Quais partes do `prometeu-vfs` atual pertencem exclusivamente ao `Workspace Editor` e podem ser removidas integralmente?
- Existe algum consumer ainda válido do `prometeu-lsp` legado fora do editor embutido?
- O fluxo `play` ou qualquer outro fluxo do Studio depende hoje, mesmo indiretamente, de APIs do editor legado, do `VFS` legado ou do `LSP` legado?
- A limpeza deve remover apenas código de produção ou também specs, testes, lessons e referências que tratam o editor embutido como superfície ativa?
- Quais contratos de compilação precisam ser preservados explicitamente enquanto a camada de edição é removida?
## Options
### Option A - Manter o editor legado até a reconstrução completa do backend de código
- **Approach:** adiar a limpeza e preservar temporariamente `Workspace Editor`, `prometeu-vfs` legado e `prometeu-lsp` legado até o novo backend existir.
- **Pro:** menor ruptura imediata.
- **Con:** prolonga a vida do legado, aumenta custo de manutenção e deixa a futura reconstrução mais confusa.
- **Maintainability:** fraca.
### Option B - Limpeza completa agora, preservando apenas a compilação do Studio
- **Approach:** remover `Workspace Editor`, `prometeu-lsp` legado e o `prometeu-vfs` acoplado a esse modelo, mantendo apenas as superfícies de compilação e execução que não dependem desse stack.
- **Pro:** reduz o legado antes da reconstrução, clarifica boundaries e impede que o futuro LSP nasça comprometido por compatibilidade acidental.
- **Con:** cria um período sem editor embutido e sem backend de código novo dentro do Studio.
- **Maintainability:** forte.
Vamos de Option B.
## Discussion
O trabalho desta agenda não é desenhar o novo backend de código.
O trabalho desta agenda é remover o legado que impediria esse redesenho.
Isso implica alguns cortes diretos:
- o `Workspace Editor` deixa de ser superfície ativa do Studio;
- o `prometeu-lsp` atual deixa de ser tratado como base evolutiva;
- o `prometeu-vfs` atual, por ser acoplado ao modelo editorial do editor embutido, sai junto com esse stack;
- as capacidades de compilação, build e execução que não dependem desse stack devem ser preservadas.
O princípio aqui é de limpeza arquitetural antes de reconstrução:
- não carregar compatibilidade acidental com o editor antigo;
- não manter um `VFS` ou `LSP` cujo contrato nasce de um modelo que já foi abandonado;
- e não misturar, nesta discussão, a limpeza do legado com o desenho do futuro servidor LSP.
Isso também reduz o risco de falsa migração:
- em vez de adaptar o editor atual, o repositório assume explicitamente que ele vai morrer;
- em vez de reaproveitar um `LSP` embrionário acoplado ao host local, o repositório aceita que um novo backend de código será desenhado depois;
- e em vez de preservar o `VFS` por inércia, o repositório valida se ele ainda possui valor fora do modelo que o originou.
## Resolution
Recomendação preliminar:
- seguir com a Option B;
- tratar esta agenda exclusivamente como limpeza completa do `Workspace Editor` do Studio;
- remover junto o `prometeu-lsp` legado e o `prometeu-vfs` acoplado a esse modelo;
- preservar explicitamente a capacidade de compilação e os fluxos do Studio que não dependem desse stack;
- e abrir uma discussão futura separada para o backend de código novo, o novo LSP e o contrato de automação.
## Next Step
Se a direção fizer sentido, o próximo passo disciplinado é fechar uma `decision` com:
1. o escopo exato da remoção do `Workspace Editor`;
2. o escopo exato da remoção do `prometeu-lsp` legado;
3. o escopo exato da remoção do `prometeu-vfs` acoplado a esse modelo;
4. as capacidades de compilação e execução que devem sobreviver intactas;
5. e os artefatos normativos, testes e código que precisam ser limpos ou preservados.

View File

@ -1,128 +0,0 @@
---
id: AGD-0035
ticket: studio-new-lsp-api-and-v1-boundary
title: Novo boundary entre lsp-api, lsp-v1 e a extensao VS Code
status: accepted
created: 2026-05-05
resolved: 2026-05-05
decision: DEC-0032
tags: [studio, lsp, vscode, protocol, api, boundary]
---
## Pain
O stack legado de editor, `prometeu-lsp` e `prometeu-vfs` acabou de ser removido. O próximo passo natural é reconstruir o backend de linguagem, mas sem repetir o erro anterior de misturar engine semântica, transporte LSP, sessão editorial e host UI em um único desenho.
Ao mesmo tempo, já existe uma extensão em `tools/vscode-extension` que hoje sabe conectar via TCP em `127.0.0.1:7777` e falar LSP como cliente real. Isso reduz incerteza no lado do FE, mas aumenta a exigência arquitetural do backend: o servidor novo precisa nascer com boundary correto.
O risco central é reintroduzir acoplamento acidental entre:
- contratos internos de linguagem;
- transporte externo LSP;
- implementação concreta baseada em `LSP4J`;
- e necessidades específicas do VS Code.
## Context
- O cleanup do stack legado foi fechado por `DEC-0031`.
- A extensão VS Code já existe em `tools/vscode-extension`.
- A extensão usa `vscode-languageclient` e conecta por socket TCP configurável.
- O usuário quer explicitamente que `LSP4J` **não vaze** de `lsp-v1`.
- A intenção geral do produto é que o Studio fale a própria língua internamente e exponha adapters externos para FEs, no mesmo espírito já discutido para integrações como Tiled.
Hoje, a pergunta não é "como implementar o LSP inteiro", mas sim:
- que módulos recriar;
- qual boundary o `lsp-api` realmente deve carregar;
- e qual responsabilidade cabe a `lsp-v1` como adapter concreto.
Também já existe um direcionamento adicional do produto:
- `lsp-v1` deve consumir serviços existentes de `compiler`;
- `lsp-api` deve expor funcionalidades reutilizáveis por outras partes do sistema;
- o bootstrap do servidor deve acontecer quando um projeto é aberto, e o shutdown quando o projeto é fechado;
- a API pode começar mínima, por exemplo com `boot server` e `shutdown server`, e crescer só quando houver necessidade real.
## Open Questions
- [x] O `lsp-api` deve expor contratos próprios de domínio/serviço ou DTOs alinhados diretamente ao protocolo LSP?
R: o lsp-api deve expor somente servicos que serao usados por outras partes do sistema, e nao ser um espelho do protocolo.
- [x] O `lsp-v1` deve ser somente um adapter `LSP4J` sobre serviços internos de `compiler`, ou também pode carregar parte da orquestração de sessão?
R: O lsp-v1 deve conter o servidor e todo o necessario para falar LSP, incluindo DTOs e dependencias de LSP4J (e fazer uso de compiler quando necessario). o start e o stop do servidor podem ser chamados via lsp-api, mas a logica de orquestracao de sessao deve ficar dentro do lsp-v1.
- [x] O lifecycle de bootstrap/shutdown do servidor por projeto pertence ao `lsp-api`, ao `lsp-v1`, ou a outro serviço do Studio?
R: o contrato fica no lsp-api, mas a logica de orquestracao fica no lsp-v1. o lsp-api pode expor um contrato como `bootServer(project)` e `shutdownServer(project)`, mas a implementacao concreta e a logica de associar o servidor ao projeto fica no lsp-v1.
- [x] O canal de automação (`compile/build/run/debug`) deve viver fora do novo `lsp-api` desde o início?
R: o canal de automacao deve viver fora do lsp-api. nesse primeiro momento o foco principal deve ser o LSP e o comportamento editorial/semantico. o canal de automacao pode ser discutido e implementado separadamente, sem misturar responsabilidades.
- [x] O `tools/vscode-extension` deve continuar falando LSP puro em socket TCP, ou o produto precisa reservar outra estratégia de transporte já nesta fase?
R: o vscode-extension deve continuar falando LSP puro em socket TCP. o lsp-api deve ser agnóstico ao transporte, mas ainda aceito recomendacoes q sejam mais faceis ou performaticas.
## Options
### Option A - `lsp-api` como API diretamente moldada pelo protocolo LSP
- **Approach:** recriar `lsp-api` com tipos e serviços muito próximos da superfície do protocolo, deixando `lsp-v1` apenas como bootstrap `LSP4J` e roteamento para `compiler`.
- **Pro:** acelera integração com o cliente existente e reduz tradução entre camadas.
- **Con:** tende a tornar o protocolo externo dono do desenho interno; muda mal quando surgir outro FE ou outro adapter.
- **Maintainability:** fraca. O risco de vazamento conceitual do protocolo para dentro do domínio é alto, mesmo sem importar classes `LSP4J` fora de `lsp-v1`.
### Option B - `lsp-api` mínima e operacional; `lsp-v1` como adapter LSP4J que consome `compiler`
- **Approach:** `lsp-api` expõe uma surface mínima e reutilizável para o sistema, começando com operações como `boot server(project)` e `shutdown server(project)` e, no máximo, contratos estáveis que outras partes do Studio precisem enxergar. `lsp-v1` concentra a implementação concreta do servidor, depende exclusivamente de `LSP4J`, e consome os serviços do `compiler` para responder às capacidades LSP.
- **Pro:** respeita a regra de não vazamento de `LSP4J`, evita inflar a API cedo demais e alinha o lifecycle do servidor ao projeto aberto, não ao processo global do Studio.
- **Con:** exige disciplina para não transformar `lsp-api` em um espelho parcial do protocolo nem `lsp-v1` em um segundo backend semântico solto do `compiler`.
- **Maintainability:** forte. O backend nasce hexagonal e o custo de evolução fica mais previsível.
### Option C - Sem `lsp-api`; expor apenas um servidor LSP concreto em `lsp-v1`
- **Approach:** pular a separação e concentrar tudo em um único módulo novo de servidor, com contratos locais apenas package-private ou internos.
- **Pro:** menor custo inicial de scaffolding.
- **Con:** repete exatamente o tipo de colapso arquitetural que gerou o legado descartado; dificulta teste, substituição de transporte e integração com outros FEs.
- **Maintainability:** ruim. A velocidade inicial é comprada com dívida estrutural imediata.
## Discussion
O dado novo mais importante é que o cliente VS Code já está funcional como cliente LSP puro. Isso elimina a necessidade de desenhar o protocolo "pensando no editor". O editor já sabe falar LSP; quem precisa de disciplina agora é o Studio.
Isso empurra a arquitetura para uma separação bem objetiva:
- `lsp-api` não deve ser "API pública do protocolo";
- `lsp-api` deve ser uma API interna e mínima do backend de linguagem do Studio;
- `lsp-v1` deve ser o adapter LSP concreto e consumidor dos serviços de `compiler`;
- `LSP4J` deve existir exclusivamente em `lsp-v1`.
O ponto sensível é não confundir "API interna" com "engine concreta". Se `lsp-api` virar um lugar para pôr qualquer detalhe de sessão, thread, socket, `CompletableFuture` de transporte, ou estruturas do `LSP4J`, ele já nasce errado. Pelo direcionamento atual, a API deve começar deliberadamente estreita:
- boot do servidor por projeto;
- shutdown do servidor por projeto;
- e só depois crescer quando outro consumidor real do sistema exigir isso.
Também vale separar desde já o que não pertence ao LSP:
- `compile/build/run/debug` não devem entrar no `lsp-api` por conveniência;
- esses fluxos pertencem a um contrato de automação paralelo;
- o LSP deve se limitar ao que é comportamento editorial/semântico.
Outro ponto: o usuário já fixou que o Studio é o backend autoritativo e o cliente externo é só cliente. Isso reforça que o lifecycle do servidor precisa acompanhar o projeto aberto. Em outras palavras:
- abrir Studio não implica subir servidor LSP global;
- abrir projeto pode implicar subir o servidor LSP daquele projeto;
- fechar projeto deve encerrar o servidor correspondente.
As respostas atuais também fecharam um boundary operacional importante:
- quem "fala LSP" de verdade é o `lsp-v1`;
- `lsp-api` não é adapter nem espelho do protocolo;
- `lsp-api` existe para expor um boundary interno consumível pelo Studio;
- o contrato mínimo inicial pode ser pequeno, desde que suficiente para boot/shutdown por projeto;
- DTOs, tipos e dependências do protocolo podem existir em `lsp-v1` sem contaminar a API interna.
## Resolution
Direção recomendada para convergir:
1. recriar `lsp-api` como surface interna mínima e reutilizável do sistema, começando com bootstrap e shutdown por projeto;
2. recriar `lsp-v1` como adapter LSP/JSON-RPC concreto, com dependência exclusiva de `LSP4J`;
3. fazer `lsp-v1` consumir serviços existentes de `compiler`, em vez de reconstruir pipeline semântico próprio;
4. deixar a lógica concreta de orquestração de sessão e associação `projeto -> servidor` dentro de `lsp-v1`, mesmo quando o bootstrap/shutdown for disparado através de `lsp-api`;
5. tratar qualquer tipo `LSP4J` fora de `lsp-v1` como violação arquitetural;
6. manter `tools/vscode-extension` como cliente LSP puro em socket TCP;
7. discutir separadamente o contrato de automação para `compile/build/run/debug`, em vez de empurrá-lo para dentro do LSP.
Neste ponto, a agenda já tem direção clara o bastante para virar `decision`. O que ainda resta fechar depois disso é implementação, não escolha arquitetural principal.

View File

@ -1,147 +0,0 @@
---
id: AGD-0036
ticket: frontend-visual-theme-spec-and-css-retirement
title: Frontend Visual Theme Spec and Retirement of Host-Consumed Semantic CSS
status: accepted
created: 2026-05-06
resolved: 2026-05-06
decision: DEC-0033
tags: [compiler, compiler-general, frontend, presentation, theming, studio, vscode, lsp, pbs]
---
## Pain
The current semantic highlighting path is no longer strong enough now that Prometeu must project frontend-owned presentation into more than one host.
Today the frontend still effectively ships a host-facing CSS file as the practical source of truth for visual presentation.
That works tolerably for the legacy Studio editor path, but it collapses once the same frontend presentation must be exported to VS Code through LSP semantic tokens.
The result is a weak cross-host contract:
- the frontend publishes semantic keys, but not a complete visual spec,
- `semantic-highlighting.css` still acts as the real authored presentation artifact,
- VS Code only receives a partial hand-translated approximation,
- and each host risks drifting away from the frontend's intended visual identity.
The CSS file should be treated as migration input only and must die by the end of this refactor.
## Context
Domain owner: `compiler/general`
Propagation targets are expected in at least three places:
- compiler frontend metadata and contracts,
- Studio host consumption,
- VS Code extension host consumption.
Relevant historical context already exists in `LSN-0029`, which established frontend ownership of semantic presentation metadata through `FrontendSpec`.
That lesson is still useful for ownership boundaries, but it is not sufficient for the next wave because the current contract is too weak and too resource-oriented.
Current state:
- `FrontendSemanticPresentationSpec` exposes only `semanticKeys` and opaque `resources`,
- PBS publishes `/themes/pbs/semantic-highlighting.css` as a semantic presentation resource,
- Studio can consume that resource directly,
- VS Code cannot consume that CSS directly and must approximate it via `package.json` and semantic token theming,
- recent LSP work now transports PBS semantic token types, but the host-side rendering still falls short of the original PBS editor look.
What is missing is a frontend-owned visual spec that is structured enough to be exported to multiple hosts without making CSS the canonical source.
## Open Questions
- [x] What is the canonical replacement for `semantic-highlighting.css` inside `FrontendSpec`?
R: a structured visual presentation spec (a JSON) that includes semantic token styles and editor-level colors.
- [x] Which parts of frontend presentation are normative and cross-host, and which are host-specific adapters only?
R: a ideia eh que o FE presentation possa ser completamente expostado para os clientes como o VSCode.
- [x] Should the visual contract be semantic-token-centric only, or should it also include editor-level colors such as base foreground, selection, gutter, and accent surfaces?
R: o contrato visual pode ofertar toda essa gama de atributos para cada token, o cliente (VSCode) pode usa-los para compor o tema, mas o contrato deve ser token-centric para garantir que a intenção visual seja sempre atrelada a chaves semânticas.
- [x] How should Studio consume the new visual spec without keeping CSS as a hidden canonical source?
R: o FE Presentation na medida que o servidor eh described oferece um contrato visual estruturado, o cliente (VSCode extension) deve consumir esse contrato e gerar o que tiver que gerar para compor o tema. Se o cliente usar CSS que gere isso.
- [x] How should VS Code consume the new visual spec: static generated contribution, runtime translation, or both?
R: A ideia eh que o cliente seja bem burro, ele deve ser uma maquina que traduz o contrato visual para um formato que o VSCode entenda, seja isso um contribution estatico ou uma tradução dinamica, o importante eh que o contrato visual seja o unico input e a fonte de verdade para a intencao visual do frontend.
- [x] How do we phase out existing frontend-owned CSS resources without breaking current Studio rendering during migration?
R: nada no studio depende desse CSS, ele eh um artefato de migração para o PBS. O contrato visual deve ser definido e implementado no PBS primeiro, usando o CSS como input para derivar o formato estruturado. Depois disso, o CSS pode ser descontinuado.
- [x] How do we version and validate the visual contract so new frontends can implement it consistently?
R: o contrato deve viver dentro de `FrontendSpec` e ser versionado junto com ele.
## Options
### Option A - Keep CSS as the canonical frontend artifact and add exporters around it
- **Approach:** Preserve `semantic-highlighting.css` as the frontend-owned source and build tooling that parses or translates it into Studio and VS Code outputs.
- **Pro:** Smallest migration cost in the short term, because PBS already has authored CSS.
- **Con:** Keeps host-facing CSS as the source of truth, which is the wrong abstraction for multi-host consumption and weak for validation.
- **Maintainability:** Poor. Every new host would need a CSS interpretation path or a CSS-to-host adapter with lossy translation rules.
### Option B - Introduce a structured frontend visual spec and treat CSS as a temporary migration input
- **Approach:** Replace the current resource-centric semantic presentation contract with a structured visual spec published by the frontend. Use the existing CSS only as bootstrap input while migrating PBS, then retire it as canonical data.
- **Pro:** Creates a real multi-host contract that can be exported mechanically to Studio and VS Code while preserving frontend ownership.
- **Con:** Requires contract design, adapter work in both hosts, and a migration story for current frontend resources.
- **Maintainability:** Strong. New frontends would author one canonical visual contract and hosts would implement stable adapters.
### Option C - Split the contract into semantic vocabulary plus host-owned themes
- **Approach:** Keep frontend ownership only over semantic keys and let each host define its own visual theme for those keys.
- **Pro:** Simplifies frontend metadata and gives each host more freedom.
- **Con:** Reintroduces host ownership over frontend meaning in practice and guarantees visual drift between Studio and VS Code.
- **Maintainability:** Medium at best. It reduces frontend burden but loses the core requirement of frontend-owned identity.
## Tradeoffs
Option A looks attractive because it reuses existing assets, but it cements the wrong boundary.
If CSS remains canonical, the compiler/frontend layer still cannot describe its own presentation in a host-neutral way.
Option C is cleaner than the current situation from a tooling perspective, but it fails the product goal.
The user experience would vary per host because visual meaning would no longer be frontend-owned.
Option B is the only direction that preserves the previous ownership decision while extending it into a credible cross-host architecture.
Its cost is real, but that cost is exactly the work we need to make the contract durable.
## Recommendation
Adopt Option B.
The frontend should publish a structured visual presentation spec as canonical data.
That spec should become the only normative source for frontend semantic/editor appearance that is intended to survive across hosts.
`semantic-highlighting.css` should be used only as migration input for PBS while we derive the first structured visual spec.
After migration, CSS may remain as a generated Studio adapter artifact for a while, but it must no longer be treated as authored truth.
The new contract likely needs at least these conceptual layers:
- semantic token styles,
- editor surface colors,
- optional UI accent colors tied to the editing surface,
- explicit host adapter boundaries.
The LSP path should transport structured visual data or enough structured metadata for the VS Code extension to render the same frontend-owned intent without reverse-engineering CSS.
## Discussion
This agenda is intentionally narrower than “general editor theming”.
The problem is not to invent a universal Prometeu theme engine first.
The problem is to stop using frontend-authored CSS as the canonical semantic/editor presentation contract and replace it with a frontend-owned visual spec that survives host translation.
The most important discipline point is ownership:
- compiler/frontend owns semantic and visual intent,
- LSP transports frontend-owned intent,
- Studio and VS Code are rendering adapters,
- host adapters may have capability gaps, but they must not become canonical.
There is also an important migration constraint:
- PBS is the first frontend and will define the initial shape,
- but the contract must not become “PBS-specific metadata with generic naming later”,
- instead it must be valid as a compiler-general surface that PBS implements first.
## Resolution
Accepted on 2026-05-06.
The discussion resolves in favor of a structured frontend-owned visual theme specification with support for multiple themes per frontend.
Themes remain tied to the frontend's own semantic vocabulary.
Studio and the VS Code extension act as adapters over that contract.
`semantic-highlighting.css` remains migration input only and must be retired as canonical authored truth.

View File

@ -1,85 +0,0 @@
---
id: AGD-0037
ticket: frontend-semantic-host-projection-flexibility
title: Frontend Semantic Vocabulary Flexibility and Host Projection
status: accepted
created: 2026-05-06
resolved: 2026-05-06
decision: DEC-0034
tags: [compiler, compiler-general, frontend, semantics, vscode, host-projection, lsp]
---
## Pain
The current discussion exposed an architectural tension:
- frontend semantic keys must remain frontend-owned and flexible,
- but VS Code prefers host-shaped semantic token categories and modifiers,
- and forcing frontend vocabularies into a rigid global taxonomy would collapse frontend ownership into host constraints.
If Prometeu treats VS Code semantic categories as the canonical semantic contract, the frontend loses semantic freedom and the wrong layer starts owning language meaning.
## Context
Domain owner: `compiler/general`
This discussion extends `DEC-0033` rather than replacing it.
`DEC-0033` already locked that visual themes are frontend-owned and hosts are adapters.
What remained implicit was how a frontend-owned semantic vocabulary should adapt to host capabilities when the host prefers a different semantic model.
The key clarification is:
- the frontend semantic vocabulary remains canonical,
- host adaptation is declarative projection,
- host projection does not become the canonical semantic contract.
## Open Questions
- [x] Should Prometeu define a rigid global semantic token taxonomy shared by every frontend?
R: no. Each frontend keeps its own vocabulary.
- [x] How should VS Code consume flexible frontend vocabularies without becoming the owner of semantic meaning?
R: through a frontend-authored host projection for VS Code.
- [x] Does this revise `DEC-0033`?
R: it complements `DEC-0033` by clarifying semantic vocabulary and host projection responsibilities.
## Options
### Option A - Canonicalize around VS Code token types
- **Approach:** Force frontends to express semantic meaning in a shared VS Code-shaped taxonomy.
- **Pro:** Simplifies host adaptation.
- **Con:** Makes the host model canonical and removes frontend semantic freedom.
- **Maintainability:** Poor. It solves adapter simplicity by weakening frontend ownership.
### Option B - Keep frontend vocabularies canonical and add declarative host projection
- **Approach:** Let each frontend define its own semantic keys and publish host projection metadata that explains how a host such as VS Code should adapt those keys.
- **Pro:** Preserves frontend semantic ownership while keeping host adaptation mechanical.
- **Con:** Requires an additional contract layer.
- **Maintainability:** Strong. Ownership stays correct and adapters remain declarative.
## Tradeoffs
Option A would make the current VS Code situation easier, but only by moving semantic authorship to the wrong layer.
Option B adds contract surface, but that surface is the correct one because it keeps the frontend canonical and makes host projection explicit rather than implicit.
## Recommendation
Adopt Option B.
Frontend semantic keys remain canonical and flexible.
Hosts such as VS Code consume a declarative projection authored by the frontend for that host.
## Discussion
This discussion is intentionally narrow.
It does not reopen the frontend-owned visual theme decision.
It only clarifies that semantic vocabulary itself must also remain frontend-owned, and that host adaptation must be expressed as projection rather than normalization into a rigid shared taxonomy.
## Resolution
Accepted on 2026-05-06.
Prometeu keeps frontend-owned semantic vocabularies flexible and introduces declarative host projection as the adaptation mechanism for hosts such as VS Code.

View File

@ -0,0 +1,207 @@
---
id: AGD-0038
ticket: pbs-lsp-editor-assistance-wave-1
title: Wave 1 de assistencia editorial via LSP para PBS no VS Code
status: accepted
created: 2026-05-08
resolved: 2026-05-08
decision: DEC-0035
tags: [studio, lsp, vscode, compiler, compiler-pbs, editor, completion, hover, signature-help]
---
## Pain
O stack atual de PBS no VS Code ja entrega duas capacidades relevantes:
- diagnostics basicos;
- semantic highlighting com tema frontend-owned.
Mas ele ainda nao entrega o minimo de assistencia editorial para um fluxo real de escrita de codigo:
- nao existe `completion`;
- `hover` ainda eh placeholder;
- nao existe `signature help`.
Sem isso, o editor continua servindo mais como viewer colorido com erros do que como ambiente minimamente utilizavel para escrever PBS com conforto.
## Context
Domain owner: `studio`
Subdomains touched:
- `studio/lsp`
- `compiler/pbs`
- `compiler/general`
Estado atual observado no codigo:
- o servidor anuncia `hover` e `semanticTokens`, mas nao anuncia `completionProvider`, `signatureHelpProvider` ou `documentFormattingProvider`;
- o bridge interno do LSP so expõe `describeServer`, `analyzeDocument`, `hover`, `semanticTokens` e `onSave`;
- `hover` hoje retorna texto fixo, sem usar simbolo, assinatura, tipo ou docs;
- o pipeline do compiler ja consegue analisar overlay do documento e possui superficies semanticas e de linking relevantes no PBS;
- o highlighting recente ja resolve bastante informacao lexical e parte da superficie stdlib/imports.
Esta agenda trata apenas da wave 1 de assistencia editorial.
Ela nao tenta fechar todo o problema de IDE features.
## Open Questions
- Qual deve ser o escopo minimo de `completion` para chamarmos essa wave de utilizavel?
- [x] Qual deve ser o escopo minimo de `completion` para chamarmos essa wave de utilizavel?
R: keywords, nomes locais em escopo, simbolos importados/publicos, e members apos `.` para superfícies reconhecidas (`service`, `host`, `builtin type`, `struct` e constructors/funcoes relacionados). Sem isso, a feature ainda nao ajuda na descoberta real da API.
- `completion` deve nascer apenas com heuristicas lexicais/sintaticas, ou ja deve usar semantica e linking do compiler onde isso for viavel?
- [x] `completion` deve nascer apenas com heuristicas lexicais/sintaticas, ou ja deve usar semantica e linking do compiler onde isso for viavel?
R: deve nascer compiler-backed sempre que a informacao ja existir de forma confiavel no pipeline semantico/linking. Heuristica local pode existir apenas como complemento estritamente limitado para casos ainda nao resolvidos, nunca como segunda semantica canônica.
- Em `hover`, quais informacoes sao obrigatorias na primeira entrega:
assinatura, kind, modulo de origem, tipo inferido, documentacao?
- [x] Em `hover`, quais informacoes sao obrigatorias na primeira entrega:
assinatura, kind, modulo de origem, tipo inferido, documentacao?
R: obrigatorios: `kind`, assinatura quando aplicavel, modulo/origem quando relevante, e tipo/shape basico quando houver. Documentacao textual eh desejavel para stdlib e builtins, mas nao deve bloquear a wave 1 se a infraestrutura de docstring ainda nao existir. Se a linguagem vier a adotar algo como `Document(...)` com markdown pronto para hover, isso deve nascer em discussao propria; nesta wave atual, basta preparar o local de consumo para documentacao opcional quando ela existir.
- `signature help` deve usar a mesma fonte semantica de `hover/completion`, ou pode nascer numa implementacao mais local para chamadas conhecidas?
- [x] `signature help` deve usar a mesma fonte semantica de `hover/completion`, ou pode nascer numa implementacao mais local para chamadas conhecidas?
R: deve usar a mesma base semantica. O objetivo da wave eh justamente evitar tres caminhos tecnicos diferentes para responder "qual assinatura esta sendo chamada?".
- Como tratar membros de stdlib, aliases importados, services, hosts, builtin types e metodos de struct sem criar uma segunda semantica paralela no LSP?
- [x] Como tratar membros de stdlib, aliases importados, services, hosts, builtin types e metodos de struct sem criar uma segunda semantica paralela no LSP?
R: o LSP deve perguntar ao compiler por uma superficie editorial/resolutiva unica, derivada das mesmas fontes usadas para analise, linking, stdlib e metadata do frontend. O LSP nao deve reconstruir manualmente tabelas paralelas de membros.
- Esta wave deve incluir `go to definition`, ou isso deve ficar explicitamente fora do escopo para nao diluir a entrega?
- [x] Esta wave deve incluir `go to definition`, ou isso deve ficar explicitamente fora do escopo para nao diluir a entrega?
R: deve ficar fora do escopo desta wave. Ele eh um proximo passo natural, mas nao eh requisito para chamar `completion + hover + signature help` de minimamente utilizaveis.
- Formatacao e identacao automatica devem ficar fora desta agenda como non-goal explicito?
- [x] Formatacao e identacao automatica devem ficar fora desta agenda como non-goal explicito?
R: sim. Podem virar discussao/plan posterior. Nesta wave, elas seriam custo adicional sem impacto proporcional comparado a completion/hover/signature help.
## Options
### Option A - Completion e hover por heuristica leve, com signature help posterior
- **Approach:** implementar `completion` usando contexto local, imports, keywords e alguns casos de member access, implementar `hover` com informacao minima, e deixar `signature help` para uma wave seguinte.
- **Pro:** menor custo inicial e menor risco de travar na arquitetura semantica.
- **Con:** pode criar uma primeira entrega inconsistente, especialmente em chamadas de stdlib e tipos importados, e pode forcar refactor cedo demais depois.
- **Maintainability:** media.
### Option B - Wave 1 coerente com completion, hover e signature help sobre uma mesma base semantica
- **Approach:** desenhar uma pequena superficie de assistencia editorial no LSP que use uma base comum para resolver simbolos, membros e assinaturas. Entregar juntos:
- completion minimo utilizavel;
- hover real;
- signature help em chamadas.
- **Pro:** evita duplicacao conceitual e produz uma experiencia de editor mais consistente desde a primeira wave.
- **Con:** custo maior de desenho e implementacao agora.
- **Maintainability:** forte.
### Option C - Adiar assistencia semantica e depender do VS Code + snippets
- **Approach:** manter diagnostics e colors como estao, adicionar no maximo snippets ou pequenas ajudas na extensao.
- **Pro:** quase nenhum custo de backend.
- **Con:** nao resolve o problema real; o editor continua insuficiente para escrita cotidiana de PBS.
- **Maintainability:** fraca.
## Tradeoffs
Option C nao fecha a dor real e deve ser descartada.
Option A parece atraente para ganhar velocidade, mas carrega um risco ruim:
- introduzir `completion`, `hover` e depois `signature help` por caminhos tecnicos diferentes;
- duplicar logica entre parser local, heuristicas e linking;
- e transformar a wave 2 num retrabalho de consolidacao.
Option B custa mais, mas o custo eh justificavel porque estas tres features se apoiam nas mesmas perguntas:
- o que este simbolo representa?
- quais membros ele expõe?
- qual eh a assinatura desta chamada?
- qual o modulo/origem deste item?
Se essas perguntas forem respondidas por uma base comum, a wave 1 fica mais coerente e abre caminho natural para futuras features como `definition`, `references` e `inlay hints` via LSP.
## Recommendation
Seguir com **Option B**.
A recomendacao eh abrir uma wave 1 coerente de assistencia editorial com:
- `completion` minimo utilizavel;
- `hover` funcional;
- `signature help` funcional.
Escopo minimo recomendado para `completion`:
- keywords;
- simbolos locais em escopo;
- nomes importados/publicos relevantes;
- members apos `.` para stdlib, builtin types, structs e services/hosts reconhecidos.
Escopo minimo recomendado para `hover`:
- kind do simbolo;
- assinatura quando aplicavel;
- modulo/origem quando relevante;
- tipo ou shape basico quando isso existir de forma confiavel.
Escopo minimo recomendado para `signature help`:
- chamadas de funcao/metodo/construtor;
- parametro ativo;
- labels consistentes com a mesma representacao de assinatura usada no hover.
## Discussion
O ponto principal desta agenda nao eh “adicionar IDE features” genericamente.
O ponto principal eh definir a primeira wave de superfícies de assistencia que tiram o PBS no VS Code do estado de:
- diagnostics + coloracao
para um estado de:
- escrita assistida minima, com descoberta de API e leitura de assinatura.
Isso exige disciplina de boundary.
O VS Code extension nao deve inventar semantica local.
O servidor LSP deve continuar sendo o owner da assistencia editorial.
Da mesma forma, o LSP nao deve criar uma semantica paralela desconectada do compiler se ja existe informacao aproveitavel em parser, linking, stdlib e superficies semanticas do PBS.
Tambem vale explicitar o que fica fora desta agenda:
- formatter completo;
- identacao automatica robusta de documento;
- quick fixes;
- definition/references;
- rename;
- code actions mais amplas.
Esses itens podem virar agenda posterior.
Tambem fica registrado um criterio importante de arquitetura:
- o primeiro passo nao eh encher o protocolo de features;
- o primeiro passo eh criar uma base editorial coerente no lado `compiler/pbs` + `studio/lsp` que consiga responder simbolo, members e assinatura;
- `completion`, `hover` e `signature help` sao projeções diferentes sobre a mesma base.
E um criterio adicional de preparacao editorial:
- a wave 1 deve prever um campo/superficie opcional de documentacao no modelo editorial resolvido por simbolo;
- mas a autoria dessa documentacao na linguagem PBS, inclusive eventual anotacao `Document(...)` com markdown, fica fora desta agenda e pode seguir para discussao separada.
## Resolution
Resolucao preliminar:
- a wave 1 deve ser considerada valida quando o VS Code conseguir oferecer descoberta minima de API, leitura de assinatura e ajuda em chamadas sem depender de conhecimento local na extensao;
- `completion`, `hover` e `signature help` devem nascer sobre uma mesma base compiler-backed;
- `go to definition`, formatter e outras features de IDE ficam explicitamente fora do escopo.
Se esta leitura fizer sentido, o proximo passo eh aceitar a agenda e fechar uma `decision` que:
1. defina o escopo normativo exato de `completion`, `hover` e `signature help`;
2. fixe o boundary entre `compiler/pbs`, `studio/lsp` e `tools/vscode-extension`;
3. declare explicitamente os non-goals desta wave;
4. determine se a base deve nascer compiler-backed desde o inicio ou com alguma heuristica local estritamente limitada.
## Next Step
Se voce concordar com o enquadramento, eu converto esta agenda em `accepted` e escrevo a `decision` normativa da wave 1 de assistencia editorial para PBS no VS Code.

View File

@ -0,0 +1,137 @@
---
id: AGD-0039
ticket: pbs-symbol-documentation-and-hover-markdown
title: Modelo de documentacao de simbolos em PBS e consumo markdown no hover
status: open
created: 2026-05-08
tags: [compiler, compiler-pbs, studio, lsp, vscode, editor, hover, documentation, markdown]
---
## Pain
A wave atual de assistencia editorial quer `hover` util, mas ainda nao existe um modelo claro para documentacao authored dentro de PBS.
Sem esse modelo, o hover pode até mostrar:
- kind;
- assinatura;
- origem;
- tipo/shape.
Mas continua sem uma superficie limpa para explicar intencao de uso, contrato semantico, detalhes de parametros ou observacoes de API.
Hoje a ideia proposta eh algo como:
- `Document(qualquer markdown aqui dentro...)`
como anotacao consumida diretamente pelo hover.
Isso parece simples no uso, mas toca em decisoes de linguagem e contrato editorial que merecem discussao propria.
## Context
Domain owner: `compiler/pbs`
Subdomains touched:
- `compiler/general`
- `studio/lsp`
- `tools/vscode-extension`
Esta agenda eh deliberadamente separada de `AGD-0038`.
Razao:
- `AGD-0038` trata da wave 1 de `completion`, `hover` e `signature help`;
- esta nova agenda trata da autoria, armazenamento, propagacao e consumo de documentacao de simbolos.
O objetivo eh evitar que a primeira wave de assistencia editorial fique bloqueada por uma decisao de linguagem ainda nao fechada.
## Open Questions
- A autoria da documentacao deve acontecer por anotacao explicita como `Document(...)`, por comentario estruturado, ou por outro mecanismo?
- O payload authored deve aceitar markdown arbitrario como fonte canonica, ou deve haver alguma normalizacao/restricao?
- Quais simbolos podem carregar documentacao na wave inicial:
funcoes, methods, services, hosts, builtin types, structs, enums, fields, constructors?
- A documentacao deve viver no AST/semantics como superficie compiler-backed explicita?
- Como a documentacao authored em PBS se relaciona com documentacao de stdlib gerada ou importada de outras fontes?
- O hover deve consumir markdown pronto sem transformacao, ou deve haver um pipeline intermediario de sanitizacao/normalizacao?
- Como tratar multilinhas, escaping e ergonomia de escrita se a surface for `Document(...)`?
- A agenda deve definir apenas o modelo de autoria, ou tambem o transporte LSP e a composicao final do hover?
## Options
### Option A - Anotacao `Document(...)` com markdown como payload canonico
- **Approach:** introduzir uma anotacao explicita na linguagem PBS cujo conteudo ja eh markdown pronto para o hover.
- **Pro:** autoria direta, intencao clara, pipeline simples de consumo no LSP e no hover.
- **Con:** precisa desenhar sintaxe, escaping, multiline e regras de onde a anotacao eh permitida.
- **Maintainability:** forte se a surface de linguagem ficar limpa.
### Option B - Comentarios estruturados como fonte de documentacao
- **Approach:** usar comentarios especiais ou doc-comments, com parser especifico para gerar documentacao de simbolo.
- **Pro:** mais familiar para quem vem de outras linguagens e menos intrusivo no corpo semantico da linguagem.
- **Con:** exige novo contrato de binding entre comentarios e simbolos, e pode aumentar ambiguidade editorial.
- **Maintainability:** media.
### Option C - Nao definir autoria em PBS agora e suportar apenas docs de stdlib por metadata externa
- **Approach:** deixar a linguagem sem surface authored por enquanto e alimentar hover apenas com docs externas/geradas.
- **Pro:** menor custo imediato de linguagem.
- **Con:** resolve mal a autoria de codigo de usuario e deixa o modelo incompleto.
- **Maintainability:** fraca.
## Tradeoffs
Option C nao parece suficiente como direcao de produto se a intencao eh ter hover realmente util para APIs authored em PBS.
Option B eh plausivel, mas move o problema para um binding entre comentario e simbolo que tambem precisa ser projetado com cuidado. Isso costuma parecer mais barato do que realmente eh.
Option A tem um custo claro de sintaxe e modelo, mas pelo menos deixa explicito que documentacao eh metadado semantico e nao apenas texto solto ao redor do codigo.
Se a equipe realmente quer markdown authored pronto para consumo no hover, Option A parece a discussao mais direta e honesta.
## Recommendation
Discutir esta agenda com viés inicial para **Option A**, mas sem fechar ainda a sintaxe final.
A recomendacao preliminar eh separar o problema em duas perguntas:
1. qual eh a surface canonical de autoria da documentacao em PBS?
2. como essa documentacao vira um payload editorial resolvido para hover e futuros consumers?
Mesmo que `Document(...)` seja a direcao vencedora, a decisao deve deixar claro:
- onde ela pode ser usada;
- qual formato textual aceita;
- como ela eh preservada no compiler;
- como chega ao LSP;
- e como o hover deve compor isso com assinatura e metadados do simbolo.
## Discussion
Esta agenda nao deve ser reduzida a "mostrar markdown no hover".
O problema real eh definir ownership e boundary da documentacao:
- o author escreve onde?
- o compiler preserva como?
- o LSP transporta em qual shape?
- o hover monta o resultado com qual ordem e responsabilidade?
Tambem vale observar que a escolha aqui pode influenciar mais do que hover:
- completions futuras podem querer `detail` e `documentation`;
- signature help pode querer descricoes de parametros;
- docs de stdlib podem querer surface unificada com docs authored.
Por isso, mesmo sendo uma agenda separada, ela conversa diretamente com a futura qualidade do editor.
## Resolution
Ainda em aberto.
## Next Step
Se o enquadramento fizer sentido, o proximo passo eh discutir as open questions e fechar uma `decision` propria para o modelo de documentacao de simbolos em PBS.

View File

@ -1,148 +0,0 @@
---
id: DEC-0031
ticket: studio-editor-workspace-cleanup
title: Limpeza completa do Workspace Editor do Studio e remoção dos acoplamentos legados
status: in_progress
created: 2026-05-05
accepted: 2026-05-05
agenda: AGD-0034
plans: [PLN-0062, PLN-0063, PLN-0064]
tags: [studio, editor, cleanup, vfs, lsp, migration]
---
## Decision
O repositório SHALL remover integralmente o `Workspace Editor` do Studio como superfície ativa do produto.
Essa remoção SHALL incluir:
1. o workspace de código embutido em `prometeu-studio`;
2. o `prometeu-lsp` legado usado por esse workspace;
3. o `prometeu-vfs` legado acoplado ao modelo editorial desse workspace;
4. os pontos de integração do shell, da sessão de projeto e do bootstrap que assumem a existência desse stack;
5. e os artefatos normativos, testes e referências documentais que tratam esse stack como superfície vigente.
Ao mesmo tempo, esta decisão ALSO locks que:
1. a capacidade de compilação dos projetos MUST permanecer disponível no Studio;
2. os fluxos atuais de `build`, `play`, `run` e `debug` MUST permanecer funcionais desde que não dependam do editor legado, do `prometeu-lsp` legado ou do `prometeu-vfs` legado;
3. esta decisão MUST NOT introduzir o novo backend de código, o novo servidor LSP ou o futuro contrato de automação;
4. qualquer reconstrução dessas superfícies MUST acontecer em discussão posterior e separada.
## Rationale
O `Workspace Editor`, o `prometeu-lsp` atual e o `prometeu-vfs` atual formam um stack único, criado especificamente para o editor embutido do Studio.
Esse stack não é mais alinhado à direção do produto:
1. o editor JavaFX deixou de ser a direção principal;
2. o `prometeu-lsp` atual não deve ser tratado como base séria para um futuro servidor LSP;
3. o `prometeu-vfs` atual carrega um contrato editorial pensado para o editor embutido;
4. manter esse legado vivo aumenta o custo de reconstrução e preserva boundaries errados por inércia.
Portanto, a limpeza precisa acontecer antes da reconstrução.
## Technical Specification
### 1. Editor Workspace Removal
O Studio MUST remover a superfície `Code Editor` do shell.
Isso inclui:
1. remover `WorkspaceId.EDITOR`;
2. remover o `EditorWorkspace` e todos os controles, painéis, modelos e helpers sob `prometeu-studio/.../workspaces/editor`;
3. remover a presença do editor na workspace rail, no layout principal e no fluxo de restauração de shell;
4. remover strings, ícones e estado visual exclusivos dessa superfície.
### 2. Legacy LSP Removal
O repositório MUST remover o `prometeu-lsp` legado como módulo ativo.
Isso inclui:
1. remover os módulos `prometeu-lsp-api` e `prometeu-lsp-v1`;
2. remover `LspService`, `LspServiceFactory` e todos os DTOs/messages específicos desse stack legado;
3. remover a criação e injeção dessas dependências no `AppContainer`, no `Container`, na sessão de projeto e nos testes associados;
4. remover a hipótese de que esse `LSP` será evoluído para o futuro backend de código.
Os conceitos úteis descobertos nesse stack MAY ser reaproveitados mais tarde, mas esta decisão não preserva compatibilidade de código, pacote ou contrato com ele.
### 3. Legacy VFS Removal
O repositório MUST remover o `prometeu-vfs` legado como módulo ativo.
Isso inclui:
1. remover os módulos `prometeu-vfs-api` e `prometeu-vfs-v1`;
2. remover `VfsProjectDocument`, `ProjectDocumentVfsFactory` e implementações filesystem-backed associadas;
3. remover a criação e posse desse `VFS` na sessão de projeto;
4. remover qualquer regra que trate esse `VFS` como boundary documental vigente do Studio.
Esta decisão assume que o `prometeu-vfs` atual pertence ao modelo do editor legado e, portanto, não deve sobreviver por compatibilidade acidental.
### 4. Session and Shell Cleanup
O Studio MUST reconfigurar a sessão de projeto e o shell principal para não depender do stack removido.
Isso inclui:
1. remover `LSP` e `VFS` legados da estrutura de `StudioProjectSession`;
2. remover sua criação em `StudioProjectSessionFactory`;
3. remover dependências globais correspondentes do bootstrap e do container;
4. remover persistência de layout e restauração editorial específicas do editor.
### 5. State Cleanup
O estado local do projeto MUST deixar de persistir dados exclusivos do editor legado.
Isso inclui:
1. remover `editorRestoration`;
2. remover `shellLayout.editorLayout`;
3. garantir fallback seguro para estados antigos já persistidos em `.studio/state.json`;
4. preservar apenas os campos ainda pertencentes a workspaces vivos e ao shell remanescente.
### 6. Documentation and Test Cleanup
O repositório MUST limpar artefatos normativos e testes que descrevem o stack legado como vigente.
Isso inclui:
1. revisar ou remover as specs do `Code Editor`, do `Project Document VFS` e do `Integrated LSP Semantic Read Phase`;
2. revisar `docs/specs/studio/README.md`;
3. remover ou arquivar testes exclusivos do editor, do `prometeu-lsp` legado e do `prometeu-vfs` legado;
4. revisar lessons e referências históricas para deixar explícito que se tratam de legado, quando forem mantidas.
### 7. Capabilities That MUST Survive
As seguintes capacidades MUST sobreviver a esta limpeza:
1. compilação de projetos pelo pipeline canônico existente;
2. build de artefatos via `BuilderPipelineService`;
3. preparação do fluxo de shipper;
4. `play`, `run` e `debug` do Studio, desde que apoiados nas superfícies remanescentes e não no stack removido;
5. workspaces `Assets`, `Shipper` e `Debug`, além do launcher e do shell geral.
### 8. Explicit Non-Goals
Esta decisão MUST NOT:
1. definir o novo servidor LSP;
2. definir o novo contrato de automação;
3. definir o novo modelo de sessão de código;
4. definir integração com VS Code;
5. reter compatibilidade com o `LSP` ou `VFS` legados por conveniência.
## Constraints
1. A limpeza MUST preservar o pipeline canônico `analyze`, `compile` e `build` já existente no compiler.
2. A limpeza MUST evitar remover ou degradar fluxos de `build/run/debug` que hoje dependem apenas de `compiler`, `shipper`, runtime e shell.
3. A limpeza MUST deixar o shell do Studio em estado coerente, sem workspace fantasma, sem layout órfão e sem dependências mortas.
4. A limpeza MUST tratar specs e estado persistido como parte do trabalho, não como detalhe pós-código.
5. A futura reconstrução do backend de código SHALL nascer em discussão separada, sem herdar obrigação de compatibilidade com o stack removido.
## Revision Log
- 2026-05-05: Initial draft from AGD-0034.
- 2026-05-05: Accepted and decomposed into PLN-0062, PLN-0063, and PLN-0064.

View File

@ -1,196 +0,0 @@
---
id: DEC-0032
ticket: studio-new-lsp-api-and-v1-boundary
title: Boundary normativo entre lsp-api, lsp-v1 e a extensao VS Code
status: accepted
created: 2026-05-05
accepted: 2026-05-05
agenda: AGD-0035
plans: [PLN-0065, PLN-0066, PLN-0067]
tags: [studio, lsp, vscode, protocol, api, boundary, compiler]
---
## Decision
O repositório SHALL reconstruir o stack de linguagem do Studio com separação explícita entre:
1. `lsp-api` como boundary interno do Studio;
2. `lsp-v1` como adapter LSP/JSON-RPC concreto;
3. `compiler` como owner dos serviços semânticos e de análise consumidos por esse adapter;
4. `tools/vscode-extension` como cliente externo que continua falando LSP puro via socket TCP.
Esta decisão ALSO locks os seguintes pontos:
1. `lsp-api` MUST NOT ser espelho do protocolo LSP;
2. `lsp-api` MUST expor apenas funcionalidades internas realmente consumíveis por outras partes do Studio;
3. `lsp-api` MAY começar mínima, por exemplo com contratos como `bootServer(project)` e `shutdownServer(project)`;
4. `lsp-v1` MUST concentrar o servidor LSP concreto, os DTOs de protocolo, o transporte e qualquer dependência de `LSP4J`;
5. `LSP4J` MUST NOT vazar para fora de `lsp-v1`;
6. `lsp-v1` MUST consumir serviços existentes de `compiler` em vez de reconstruir pipeline semântico próprio;
7. o lifecycle do servidor LSP MUST ser associado à abertura e ao fechamento de projeto, não à abertura global do processo Studio;
8. o atual `lsp-v1` presente hoje no repositório serve apenas como mock de conectividade VS Code ↔ Studio e MUST NOT ser tratado como padrão arquitetural, base estrutural ou referência de implementação do backend definitivo.
9. a primeira onda de implementação desta decisão SHALL priorizar arquitetura, lifecycle e separação de responsabilidades, mesmo que o comportamento LSP permaneça deliberadamente simples ou "dumb" por um período controlado.
## Rationale
O stack legado anterior foi removido justamente porque misturava responsabilidades erradas e criou boundaries frágeis entre UI, sessão, semântica e transporte.
Ao mesmo tempo, o projeto já tem dois fatos importantes:
1. a extensão VS Code já existe e já sabe atuar como cliente LSP puro;
2. o Studio já possui serviços de `compiler` que devem continuar sendo a fonte real de comportamento semântico.
Logo, o problema não é "inventar um cliente" nem "reescrever a semântica". O problema é definir corretamente:
1. o que é boundary interno reutilizável do Studio;
2. o que é adapter concreto de protocolo;
3. e onde termina a influência do protocolo externo.
Essa separação reduz acoplamento, melhora teste e evita que detalhes de `LSP4J` ou do transporte contaminem o restante da base.
Também existe uma prioridade explícita de rollout:
1. primeiro consolidar a arquitetura;
2. depois adicionar capacidade semântica por camadas;
3. sem obrigar a primeira implementação a já ser semanticamente rica.
Isso evita repetir o padrão anterior de crescer funcionalidade em cima de uma base estrutural errada.
## Technical Specification
### 1. Module Roles
`lsp-api` MUST ser tratado como módulo de boundary interno do Studio.
Ele SHALL:
1. expor somente contratos que façam sentido para outros consumidores internos do sistema;
2. permanecer agnóstico ao protocolo LSP concreto;
3. permanecer agnóstico a `LSP4J`;
4. permanecer agnóstico ao transporte TCP ou a qualquer detalhe de socket;
5. começar com surface mínima suficiente para o lifecycle do servidor por projeto.
`lsp-v1` MUST ser tratado como o primeiro adapter concreto do boundary acima.
Ele SHALL:
1. implementar o servidor LSP;
2. carregar os DTOs e tipos de protocolo que forem necessários para falar LSP;
3. carregar a dependência de `LSP4J`;
4. realizar a tradução entre o mundo do protocolo e os serviços internos consumidos;
5. concentrar a lógica concreta de sessão e associação `projeto -> servidor`.
### 2. LSP4J Containment
O repositório MUST tratar `LSP4J` como dependência exclusiva de `lsp-v1`.
Portanto:
1. nenhum tipo de `LSP4J` MAY aparecer em `lsp-api`;
2. nenhum tipo de `LSP4J` MAY aparecer em outros módulos do Studio;
3. nenhum contrato de `lsp-api` MAY depender semanticamente de tipos, nomes ou formas obrigadas pelo `LSP4J`;
4. qualquer vazamento de `LSP4J` para fora de `lsp-v1` SHALL ser tratado como violação arquitetural.
### 3. Compiler Ownership
`lsp-v1` MUST consumir serviços existentes de `compiler` quando precisar responder capacidades editoriais e semânticas.
Isso implica:
1. `lsp-v1` MUST NOT reconstruir uma engine semântica paralela por conveniência;
2. `lsp-v1` MUST preferir compor sobre entrypoints e serviços canônicos do `compiler`;
3. qualquer lacuna percebida no `compiler` para servir o novo backend SHALL ser tratada como evolução explícita do `compiler`, e não como autorização para duplicação semântica dentro de `lsp-v1`.
### 4. Server Lifecycle
O lifecycle do servidor MUST ser project-scoped.
Regras:
1. abrir o processo Studio MUST NOT implicitamente significar "subir um servidor LSP global";
2. abrir um projeto MAY disparar `bootServer(project)` através do boundary exposto por `lsp-api`;
3. fechar um projeto MUST disparar `shutdownServer(project)` para o servidor correspondente;
4. a implementação concreta desse bootstrap/shutdown e o vínculo entre projeto e instância do servidor MUST residir em `lsp-v1`.
### 5. Internal API Minimalism
`lsp-api` MUST nascer pequeno.
Ele SHALL:
1. expor apenas o que outro consumidor interno realmente precise enxergar;
2. evitar DTOs de protocolo sem necessidade;
3. evitar antecipar capacidades futuras sem consumidor real;
4. crescer somente quando houver pressão concreta de uso interno.
O contrato inicial mínimo aceito por esta decisão é:
1. `bootServer(project)`
2. `shutdownServer(project)`
Contratos adicionais MAY ser adicionados depois, mas não fazem parte do lock inicial desta decisão.
### 6. VS Code Transport
`tools/vscode-extension` SHALL permanecer cliente LSP puro via socket TCP nesta fase.
Isso implica:
1. a extensão atual pode continuar evoluindo nesse modelo;
2. `lsp-api` MUST permanecer agnóstico a esse transporte;
3. mudanças futuras de transporte MAY ser discutidas depois, mas não fazem parte do boundary normativo inicial.
### 7. Current Mock Status
O `lsp-v1` que existe hoje para testes de conectividade entre VS Code e Studio MUST ser tratado como mock transitório.
Ele MUST NOT:
1. servir de blueprint estrutural do novo servidor;
2. servir de contrato implícito do sistema;
3. servir de justificativa para manter responsabilidades colapsadas;
4. contaminar o padrão de código alvo do backend definitivo.
O backend definitivo SHALL priorizar:
1. separação clara de responsabilidades;
2. boundaries pequenos e explícitos;
3. código fácil de manter;
4. composição sobre serviços canônicos do `compiler`;
5. isolamento rígido do adapter de protocolo.
### 8. Implementation Wave 1
A primeira onda de implementação derivada desta decisão MUST focar em transformar o mock atual em uma estrutura sólida de trabalho.
Essa onda SHALL incluir:
1. `lsp-api` mínimo com bootstrap e shutdown por projeto;
2. `lsp-v1` organizado como adapter concreto limpo, mesmo que ainda responda um conjunto reduzido ou simplificado de capacidades;
3. boot do servidor quando o projeto abrir;
4. shutdown do servidor quando o projeto fechar;
5. isolamento explícito entre boundary interno, adapter de protocolo e consumo de `compiler`.
Essa onda MUST NOT ser bloqueada pela ausência de "carne semântica" completa.
Em outras palavras:
1. é aceitável manter um comportamento LSP inicial deliberadamente simples;
2. não é aceitável manter um padrão arquitetural improvisado só porque o comportamento ainda é simples;
3. a evolução semântica futura SHALL acontecer por camadas sobre a estrutura consolidada.
## Constraints
1. Esta decisão MUST preservar a separação entre boundary interno e adapter externo.
2. Esta decisão MUST preservar `compiler` como owner semântico do sistema.
3. Esta decisão MUST impedir vazamento de `LSP4J` para fora de `lsp-v1`.
4. Esta decisão MUST impedir que o mock atual de conectividade seja usado como padrão do produto.
5. Esta decisão MUST manter `compile/build/run/debug` fora do escopo do `lsp-api` nesta fase.
6. Qualquer plano derivado desta decisão MUST refletir explicitamente o lifecycle por projeto e a contenção de protocolo em `lsp-v1`.
7. O primeiro plano derivado desta decisão MUST priorizar a consolidação estrutural do servidor antes do enriquecimento semântico.
## Revision Log
- 2026-05-05: Initial draft from AGD-0035.
- 2026-05-05: Added explicit phase-1 rollout guidance to solidify architecture before semantic depth.
- 2026-05-05: Accepted and decomposed into PLN-0065, PLN-0066, and PLN-0067.

View File

@ -1,152 +0,0 @@
---
id: DEC-0033
ticket: frontend-visual-theme-spec-and-css-retirement
title: Frontend-owned visual theme spec as canonical presentation contract
status: accepted
created: 2026-05-06
accepted: 2026-05-06
agenda: AGD-0036
plans: [PLN-0068, PLN-0069, PLN-0070, PLN-0071]
tags: [compiler, compiler-general, frontend, presentation, theming, studio, vscode, lsp, pbs]
---
## Decision
Prometeu SHALL replace frontend-authored host-consumed semantic CSS with a structured frontend-owned visual theme specification as the canonical presentation contract.
This decision locks the following normative points:
1. Each `FrontendSpec` MUST publish its own semantic vocabulary and MAY publish multiple visual themes for that vocabulary.
2. Visual themes MUST be frontend-owned and MUST remain associated with the semantic tokens defined by that same frontend.
3. `semantic-highlighting.css` MUST be treated as migration input only and MUST cease to be an authored canonical contract by the end of this refactor.
4. Studio and the VS Code extension MUST act as rendering adapters over the frontend-owned visual contract and MUST NOT become owners of frontend theme data.
5. The VS Code extension MUST translate the frontend visual contract dynamically or mechanically from the contract itself, so frontend visual adjustments do not require extension maintenance for each theme change.
## Rationale
The current model is structurally weak for multi-host consumption.
PBS still carries a CSS resource that works as the practical source of visual truth, while VS Code can only consume a partial manual approximation through semantic token configuration.
That creates the wrong ownership boundary:
1. the frontend owns semantic meaning but does not fully own its exported visual contract;
2. hosts are forced to reinterpret or approximate visual intent;
3. every frontend visual adjustment risks requiring host edits;
4. visual drift becomes likely across Studio and VS Code.
The repository already established that semantic presentation belongs to the frontend.
This decision extends that ownership model into a stronger cross-host contract:
1. the frontend authors semantic and visual intent once;
2. LSP transports that intent;
3. hosts adapt it without redefining it.
## Technical Specification
### 1. Canonical Visual Contract
`FrontendSpec` MUST evolve to expose a structured visual presentation contract as canonical data.
That contract MUST:
1. live with the frontend definition;
2. be versioned together with `FrontendSpec`;
3. be sufficient for multiple hosts to render the frontend's intended appearance without interpreting CSS as the source of truth;
4. remain compiler-general even if PBS is the first frontend to implement it.
The canonical contract MAY be encoded as JSON-backed structured data or as an equivalent strongly-typed model, but the authored source of truth MUST be the structured visual contract, not CSS.
### 2. Frontend-Owned Themes
Each frontend MAY publish multiple visual themes.
Rules:
1. themes MUST belong to the frontend that defines the semantic vocabulary they style;
2. themes MUST be expressed in terms of that frontend's own semantic token keys and related editor presentation surfaces;
3. hosts MAY select which frontend theme is active;
4. hosts MUST NOT redefine the theme contract as host-owned authored data.
This means theme ownership is:
1. frontend authors themes,
2. host selects and applies themes,
3. host does not author the frontend visual semantics.
### 3. Token-Centric Contract with Editor Surfaces
The visual contract MUST be token-centric, but it SHALL also support editor-level presentation data where needed to preserve frontend visual intent.
Therefore the contract MUST be able to express:
1. token-scoped presentation such as foreground, emphasis, and related token styling attributes;
2. editor surface colors such as base foreground, selection, gutter, and other editing-surface colors when they are part of frontend visual intent;
3. optional frontend-specific accents tied to the editing experience.
Token-centricity remains mandatory because semantic meaning MUST stay anchored to semantic keys.
Editor-surface data is allowed because semantic fidelity alone is insufficient to reproduce frontend identity across hosts.
### 4. Host Adapter Responsibilities
Studio and the VS Code extension MUST consume the frontend visual contract as adapters.
Studio:
1. MUST consume the structured frontend visual contract;
2. MAY render through generated CSS or another host mechanism;
3. MUST NOT treat generated CSS as the canonical frontend artifact.
VS Code extension:
1. MUST consume the frontend visual contract through the server description path or an equivalent frontend-owned transport surface;
2. MUST translate that contract into whatever VS Code requires, whether through runtime translation, generated contributions, or another adapter mechanism;
3. MUST behave as a mechanical translator of the frontend contract;
4. MUST NOT require hand-maintained extension theme edits whenever a frontend changes a color, emphasis rule, or theme variant.
### 5. LSP Transport Responsibilities
The LSP path MUST transport enough structured frontend-owned visual information for hosts to render the active frontend theme.
It MUST preserve:
1. frontend identity,
2. semantic token identity,
3. theme identity where multiple themes exist,
4. visual attributes needed by the host adapter.
LSP MUST NOT collapse frontend themes into host-authored generic theme categories.
### 6. Migration and CSS Retirement
`semantic-highlighting.css` is allowed only as migration input for the first structured contract derivation.
Migration rules:
1. PBS SHALL be the first frontend migrated;
2. the existing PBS CSS MAY be parsed or manually transcribed into the first canonical structured visual contract;
3. once the structured contract becomes authoritative, the CSS MUST no longer be treated as authored truth;
4. any remaining CSS after migration MAY exist only as generated adapter output or as temporary compatibility residue scheduled for removal;
5. the refactor is not complete while host-consumed semantic CSS remains the canonical frontend presentation source.
### 7. Extension Stability Requirement
This decision explicitly locks an operational requirement for `tools/vscode-extension`:
1. frontend visual changes MUST be expressible by changing frontend-owned contract data;
2. such frontend changes MUST NOT force routine extension source edits;
3. the extension SHALL be stable as a contract adapter rather than a repository of manually curated frontend theme rules.
## Constraints
1. The canonical source of frontend visual intent MUST move out of authored CSS.
2. Theme ownership MUST remain with the frontend.
3. The contract MUST support multiple themes per frontend.
4. The contract MUST remain compiler-general and MUST NOT hardcode PBS as the universal model.
5. Hosts MUST remain adapters and MUST NOT become fallback authors of frontend visual identity.
6. Any derived plan MUST include an explicit migration path for PBS and explicit retirement of `semantic-highlighting.css` as canonical data.
7. Any derived plan MUST cover compiler contract changes, transport propagation, Studio consumption, and VS Code consumption.
## Revision Log
- 2026-05-06: Initial accepted decision from AGD-0036.
- 2026-05-06: Decomposed into PLN-0068, PLN-0069, PLN-0070, and PLN-0071.

View File

@ -1,112 +0,0 @@
---
id: DEC-0034
ticket: frontend-semantic-host-projection-flexibility
title: Frontend semantic vocabularies remain canonical and hosts consume declarative projections
status: accepted
created: 2026-05-06
accepted: 2026-05-06
agenda: AGD-0037
plans: [PLN-0072, PLN-0073, PLN-0074]
tags: [compiler, compiler-general, frontend, semantics, vscode, host-projection, lsp]
---
## Decision
Prometeu SHALL keep semantic vocabularies frontend-owned and canonical.
Hosts such as VS Code SHALL consume declarative host projection data authored by the frontend instead of forcing frontend semantic keys into a rigid shared host taxonomy.
This decision locks the following normative points:
1. Each frontend MUST remain free to define its own semantic keys.
2. Prometeu MUST NOT introduce a rigid global semantic token taxonomy as the canonical contract for all frontends.
3. Host-facing semantic adaptation MUST happen through frontend-authored host projection metadata.
4. Host projection metadata MUST be declarative and MUST NOT become the canonical semantic vocabulary.
5. VS Code adaptation MUST consume the frontend semantic vocabulary plus its VS Code projection, not reinterpret semantic meaning ad hoc inside the extension.
## Rationale
The current stack already establishes frontend ownership over visual themes.
Without this complementary rule, semantic vocabulary itself could still drift toward host ownership because VS Code prefers a different semantic model than a frontend may naturally publish.
If the repository made VS Code token categories canonical, it would:
1. collapse frontend semantic freedom,
2. move semantic authorship into the host layer,
3. and make frontend evolution hostage to one specific adapter model.
Declarative host projection preserves the correct ownership boundary:
1. frontend defines semantic meaning,
2. frontend also defines how a given host should project that meaning,
3. host adapters translate mechanically.
## Technical Specification
### 1. Canonical Semantic Vocabulary
The canonical semantic vocabulary for a document language MUST live in that frontend's contract surface.
This implies:
1. semantic keys remain frontend-owned,
2. semantic keys MAY vary significantly between frontends,
3. semantic keys MUST NOT be rewritten into a mandatory repository-wide host-shaped taxonomy.
### 2. Host Projection Contract
Frontend metadata MUST evolve to support host projection descriptors.
At minimum, a host projection descriptor for VS Code MUST be capable of expressing:
1. which canonical semantic key is being projected,
2. which VS Code semantic token type should receive that key,
3. which VS Code semantic token modifiers, if any, should accompany that projection,
4. any fallback behavior needed when the host cannot represent the frontend key exactly.
The host projection descriptor MAY support other hosts later, but the first required host projection is VS Code.
### 3. Ownership Rules
Ownership SHALL be:
1. frontend owns semantic keys,
2. frontend owns host projection metadata,
3. LSP transports both,
4. the host adapter translates both.
The extension MUST NOT become the place where semantic meaning is hand-mapped or reauthored as code-driven policy.
### 4. Relationship to DEC-0033
This decision complements `DEC-0033`.
`DEC-0033` remains normative for:
1. frontend-owned visual theme contracts,
2. frontend-owned theme variants,
3. host adapter responsibilities for visual rendering.
This decision adds the semantic vocabulary clarification that `DEC-0033` left implicit:
1. semantic vocabularies remain frontend-owned and flexible,
2. host adaptation is projection, not normalization.
### 5. VS Code Adapter Rule
For VS Code specifically:
1. the extension MUST consume frontend-owned semantic keys,
2. the extension MUST consume frontend-authored VS Code projection metadata,
3. the extension MUST apply that projection mechanically,
4. the extension MUST NOT force every frontend into a single rigid shared semantic taxonomy to satisfy VS Code.
## Constraints
1. No plan derived from this decision may replace frontend semantic keys with a mandatory global host taxonomy.
2. Any plan touching VS Code semantic adaptation MUST include declarative host projection support.
3. Any plan touching LSP transport for semantic vocabularies MUST preserve frontend canonical keys.
4. This decision MUST be treated as complementary to `DEC-0033`, not as a rollback of frontend-owned theming.
## Revision Log
- 2026-05-06: Initial accepted decision from AGD-0037.

View File

@ -0,0 +1,192 @@
---
id: DEC-0035
ticket: pbs-lsp-editor-assistance-wave-1
title: Wave 1 de assistencia editorial via LSP para PBS no VS Code
status: accepted
created: 2026-05-08
accepted: 2026-05-08
agenda: AGD-0038
plans: [PLN-0075, PLN-0076, PLN-0077]
tags: [studio, lsp, vscode, compiler, compiler-pbs, editor, completion, hover, signature-help]
---
## Context
O stack atual de PBS no VS Code ja entrega diagnostics basicos e semantic highlighting frontend-owned, mas ainda nao oferece assistencia editorial minima para escrita cotidiana de codigo.
Hoje:
1. nao existe `completion`;
2. `hover` existe apenas como placeholder;
3. nao existe `signature help`;
4. o servidor ainda nao anuncia capabilities correspondentes para essas superficies;
5. o compiler e o frontend PBS ja possuem informacao semantica, de linking, stdlib e metadata suficiente para nao precisarmos inventar uma segunda semantica local na extensao.
Esta decisao trata apenas da primeira wave de assistencia editorial para PBS no VS Code.
Ela nao cobre formatter, identacao automatica robusta, quick fixes, `go to definition`, `references`, `rename` nem code actions gerais.
## Decision
O repositório SHALL entregar uma wave 1 de assistencia editorial via LSP para PBS no VS Code com tres superfícies funcionais:
1. `completion`;
2. `hover`;
3. `signature help`.
Esta wave SHALL ser considerada valida quando essas tres superfícies permitirem:
1. descoberta minima de API;
2. leitura de assinatura em simbolos e chamadas;
3. ajuda de chamada sem dependencia de conhecimento semantico local na extensao VS Code.
Esta decisao ALSO locks que:
1. `completion`, `hover` e `signature help` MUST nascer sobre uma mesma base editorial compiler-backed;
2. o LSP MUST ser o owner operacional da assistencia editorial;
3. a extensao VS Code MUST atuar apenas como cliente/adaptador do protocolo, e MUST NOT reconstruir semantica propria para simbolos, members ou assinaturas;
4. heuristicas locais no LSP MAY existir apenas como complemento temporario e estritamente limitado para lacunas nao resolvidas, mas MUST NOT virar uma segunda semantica canônica;
5. `go to definition`, formatter, identacao automatica robusta, quick fixes, `references`, `rename` e code actions amplas MUST ficar fora desta wave.
## Rationale
As tres features desta wave respondem essencialmente ao mesmo conjunto de perguntas:
1. que simbolo eh este?
2. quais members ele expõe?
3. qual assinatura ele tem?
4. de onde ele vem?
Implementa-las por caminhos tecnicos diferentes introduziria:
1. duplicacao entre parser local, heuristicas e linking;
2. incoerencia entre o que aparece em `completion`, `hover` e `signature help`;
3. retrabalho na wave seguinte.
Portanto, a primeira entrega precisa nascer sobre uma base editorial unificada, reaproveitando o que o compiler e o frontend PBS ja sabem sobre:
1. escopo local;
2. imports e aliases;
3. stdlib;
4. builtin types;
5. services, hosts, structs, enums, constructors, functions e methods.
## Technical Specification
### 1. Shared Editorial Resolution Surface
`compiler/pbs` e `studio/lsp` MUST introduzir uma superficie editorial resolvida comum para uso de `completion`, `hover` e `signature help`.
Essa superficie MUST ser capaz de responder, de forma compiler-backed:
1. identidade do simbolo;
2. `kind` do simbolo;
3. modulo/origem quando relevante;
4. assinatura ou shape quando aplicavel;
5. members disponíveis para receivers reconhecidos;
6. documentacao opcional quando existir, sem bloquear esta wave.
Essa superficie MAY ser exposta por novos modelos internos do compiler, novos adapters no bridge do LSP, ou ambos.
Mas ela MUST permanecer derivada do compiler e MUST NOT ser reautoriada na extensao.
### 2. Completion Scope
`completion` MUST ser entregue como superfície minima utilizavel.
Na wave 1, isso MUST cobrir pelo menos:
1. keywords da linguagem;
2. nomes locais em escopo;
3. simbolos importados/publicos relevantes;
4. members apos `.` para superfícies reconhecidas, incluindo `service`, `host`, `builtin type`, `struct`, e call surfaces relacionadas.
`completion` SHOULD expor labels, kinds e detalhes coerentes com a mesma base usada por `hover`.
`completion` MUST NOT depender de tabela hardcoded na extensao para stdlib ou members de PBS.
### 3. Hover Scope
`hover` MUST deixar de ser placeholder e passar a ser simbolo-resolved.
Na wave 1, o hover MUST incluir quando disponivel:
1. `kind` do simbolo;
2. assinatura quando aplicavel;
3. modulo/origem quando relevante;
4. tipo ou shape basico quando isso existir de forma confiavel.
`hover` MAY incluir documentacao textual opcional.
Mas a autoria de documentacao em PBS, incluindo eventual anotacao como `Document(...)`, MUST seguir discussao separada e MUST NOT bloquear esta wave.
### 4. Signature Help Scope
`signature help` MUST ser implementado para chamadas de:
1. funcao;
2. metodo;
3. construtor.
Na wave 1, ele MUST informar:
1. a assinatura ativa;
2. o parametro ativo;
3. labels coerentes com a mesma representacao de assinatura usada no hover.
`signature help` MUST usar a mesma base editorial de resolucao usada por `completion` e `hover`.
### 5. Boundary Responsibilities
`compiler/pbs`:
1. MUST continuar sendo a fonte de verdade de semantica, linking e metadata relevante para simbolos e call surfaces;
2. MUST fornecer a base necessaria para resolucao editorial de simbolos, members e assinaturas.
`studio/lsp`:
1. MUST projetar essa base editorial em endpoints/protocol features adequados;
2. MUST anunciar as capabilities LSP necessarias para `completion`, `hover` e `signature help`;
3. MUST manter o transporte fiel ao modelo compiler-backed.
`tools/vscode-extension`:
1. MUST consumir o protocolo como cliente;
2. MUST NOT carregar tabelas paralelas de membros, stdlib ou assinaturas como fonte principal;
3. MAY conter apenas a logica estrutural normal de integração exigida pelo VS Code.
### 6. Documentation Preparation Rule
Esta wave MUST preparar um campo ou superfície opcional para documentacao editorial resolvida por simbolo.
Mas esta decisao ALSO locks que:
1. a surface de autoria dessa documentacao em PBS nao faz parte desta wave;
2. a sintaxe ou contrato de linguagem para documentacao authored deve ser discutido separadamente;
3. a ausencia dessa autoria nao bloqueia `completion`, `hover` nem `signature help` da wave 1.
### 7. Explicit Non-Goals
Esta decisao MUST NOT:
1. incluir formatter completo;
2. incluir identacao automatica robusta de documento;
3. incluir `go to definition`;
4. incluir `references`;
5. incluir `rename`;
6. incluir quick fixes;
7. incluir code actions mais amplas;
8. definir o modelo de autoria de documentacao em PBS.
## Constraints
1. A wave 1 MUST priorizar coerencia entre `completion`, `hover` e `signature help` sobre cobertura enciclopedica de todos os casos.
2. A extensao VS Code MUST permanecer thin; a inteligencia editorial MUST ficar no compiler/LSP.
3. A implementacao MUST favorecer evolucao futura para `definition`, `references`, `documentation`, e outras editor features sem exigir reescrita conceitual da base editorial.
4. A implementacao MUST evitar surfaces duplicadas para stdlib, aliases, members e signatures.
5. Qualquer plan derivado desta decisao MUST separar claramente:
- base editorial compiler-backed;
- projeção LSP/protocolo;
- integração VS Code.
## Revision Log
- 2026-05-08: Initial draft from AGD-0038.
- 2026-05-08: Accepted and decomposed into PLN-0075, PLN-0076, and PLN-0077.

View File

@ -1,91 +0,0 @@
---
id: PLN-0062
ticket: studio-editor-workspace-cleanup
title: Shell Session and State Cleanup After Editor Removal
status: done
created: 2026-05-05
completed: 2026-05-05
tags: [studio, editor, cleanup, shell, session, state]
---
## Objective
Remove the `Code Editor` workspace from the Studio shell and reconfigure project session and persisted state so the application remains coherent without any editor-owned concepts.
## Background
`DEC-0031` locks the complete removal of the embedded editor stack. The shell, project session, workspace registry, and `.studio/state.json` currently still assume the existence of `WorkspaceId.EDITOR`, `EditorWorkspace`, editor restoration state, and editor-specific layout state.
## Scope
### Included
- Remove `WorkspaceId.EDITOR` from the Studio shell.
- Remove `EditorWorkspace` registration and shell integration.
- Remove editor-specific state persistence and restoration paths.
- Remove `LSP`/`VFS` legacy ownership from `StudioProjectSession` and `StudioProjectSessionFactory`.
- Keep `Assets`, `Shipper`, `Debug`, launcher, and shell flows functional.
### Excluded
- Removal of the `prometeu-lsp` and `prometeu-vfs` module source trees themselves.
- Documentation and lesson cleanup.
- New code backend or replacement LSP architecture.
## Execution Steps
### Step 1 - Remove editor workspace registration from the shell
**What:** Remove all shell-level references to the `Code Editor` workspace.
**How:** Update the main window composition to stop creating `EditorWorkspace`, remove the editor rail item, stop selecting or restoring `WorkspaceId.EDITOR`, and ensure shell fallback remains stable when old persisted state still references the editor.
**File(s):** `prometeu-studio/src/main/java/p/studio/window/MainView.java`, `prometeu-studio/src/main/java/p/studio/workspaces/WorkspaceId.java`, any directly related shell controls or selectors.
### Step 2 - Remove editor-owned state and restoration from project-local state
**What:** Remove editor layout and restoration data from persisted project-local Studio state.
**How:** Simplify `ProjectLocalStudioState` to remove `editorRestoration` and `shellLayout.editorLayout`, update normalization/defaults, and make loading old `.studio/state.json` degrade safely without crashes or stale editor assumptions.
**File(s):** `prometeu-studio/src/main/java/p/studio/projectstate/ProjectLocalStudioState.java`, `prometeu-studio/src/main/java/p/studio/projectstate/ProjectLocalStudioStateService.java`, any callers that write or restore editor state.
### Step 3 - Reconfigure project session to stop owning editor legacy dependencies
**What:** Remove legacy editor-driven `LSP` and `VFS` ownership from project session composition.
**How:** Refactor `StudioProjectSession` and `StudioProjectSessionFactory` so opening a project no longer constructs `VfsProjectDocument` or `LspService`, and so close semantics remain valid without those resources.
**File(s):** `prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java`, `prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java`, dependent tests.
### Step 4 - Remove bootstrap/container dependencies that only existed for the editor stack
**What:** Remove application bootstrap and container seams that exist only to inject legacy editor stack services.
**How:** Delete `LspServiceFactory` and `ProjectDocumentVfsFactory` accessors from the container surfaces once shell/session no longer depend on them, and update `AppContainer` accordingly.
**File(s):** `prometeu-studio/src/main/java/p/studio/Container.java`, `prometeu-app/src/main/java/p/studio/AppContainer.java`, directly affected tests.
## Test Requirements
### Unit Tests
- Update session and state tests to reflect the absence of editor state.
- Add coverage for loading old persisted project-local state without editor restoration fields being required.
### Integration Tests
- Verify the main Studio shell opens a project and activates a surviving workspace without editor registration.
- Verify session close still saves valid project-local state and shuts down surviving services cleanly.
### Manual Verification
- Open the Studio shell and confirm only surviving workspaces appear.
- Reopen a project with stale `.studio/state.json` containing editor data and confirm safe fallback.
- Confirm project switching and shell startup remain stable.
## Acceptance Criteria
- [x] `WorkspaceId.EDITOR` no longer exists in production code.
- [x] `MainView` no longer instantiates or restores `EditorWorkspace`.
- [x] Project-local state no longer persists editor restoration or editor layout fields.
- [x] `StudioProjectSession` no longer owns legacy editor `LSP`/`VFS` resources.
- [x] The Studio shell remains functional with surviving workspaces.
## Dependencies
- `DEC-0031` accepted and normatively locked.
- Knowledge of all shell/session/state call sites that currently assume the editor exists.
## Risks
- Shell restoration may break if old persisted state is not normalized defensively.
- Session teardown may regress if hidden resource ownership remains after field removal.
- Removing editor assumptions too early may temporarily orphan callers still using editor-specific state APIs.

View File

@ -1,91 +0,0 @@
---
id: PLN-0063
ticket: studio-editor-workspace-cleanup
title: Legacy LSP and VFS Module Removal with Runtime Preservation
status: done
created: 2026-05-05
completed: 2026-05-05
tags: [studio, editor, cleanup, lsp, vfs, runtime]
---
## Objective
Remove the legacy `prometeu-lsp` and `prometeu-vfs` modules and all remaining code references to them while preserving compiler, shipper, play, run, and debug flows that do not depend on the editor stack.
## Background
`DEC-0031` treats the current `prometeu-lsp` and `prometeu-vfs` modules as part of the embedded editor legacy stack. The Studio execution path must continue to compile, build, package, and run projects through the existing compiler and runtime orchestration layers.
## Scope
### Included
- Remove `prometeu-lsp` modules from Gradle settings and codebase references.
- Remove `prometeu-vfs` modules from Gradle settings and codebase references.
- Remove tests dedicated to these legacy modules.
- Verify `StudioShipperService`, `StudioPlayStopCoordinator`, and runtime/debug flows remain intact.
### Excluded
- Shell/editor state cleanup handled by a separate plan.
- Documentation/spec/lesson cleanup handled by a separate plan.
- New replacement backend services.
## Execution Steps
### Step 1 - Remove Gradle module registration for legacy editor stack modules
**What:** Stop building the legacy `prometeu-lsp` and `prometeu-vfs` modules.
**How:** Remove the module includes and any direct module dependencies that point to `prometeu-lsp:*` and `prometeu-vfs:*`, then fix resulting build graph fallout in Studio modules.
**File(s):** `settings.gradle.kts`, affected `build.gradle.kts` files in `prometeu-app`, `prometeu-studio`, and module directories.
### Step 2 - Remove legacy module source trees and direct test coverage
**What:** Delete the legacy `prometeu-lsp` and `prometeu-vfs` code once all consumers are detached.
**How:** Remove module source files and their dedicated tests only after production call sites no longer compile against them.
**File(s):** `prometeu-lsp/**`, `prometeu-vfs/**`, related test sources in `prometeu-studio`.
### Step 3 - Preserve compiler and shipper build flow
**What:** Ensure build preparation still uses the canonical compiler pipeline without editor legacy dependencies.
**How:** Validate and adjust `StudioShipperService` and any shipper/build callers so they continue using `BuilderPipelineService`, `BuilderPipelineConfig`, and `BuilderPipelineContext` directly without reintroducing removed editor-layer seams.
**File(s):** `prometeu-studio/src/main/java/p/studio/shipper/StudioShipperService.java`, affected compiler/shipper integration tests.
### Step 4 - Preserve play, run, and debug execution flow
**What:** Ensure runtime orchestration continues to function after legacy module removal.
**How:** Re-test and patch `StudioPlayStopCoordinator`, runtime handshake services, execution session handling, and debug workspace projections if any hidden import or event dependency pointed at removed editor-stack modules.
**File(s):** `prometeu-studio/src/main/java/p/studio/execution/StudioPlayStopCoordinator.java`, `prometeu-studio/src/main/java/p/studio/debug/runtime/**`, `prometeu-studio/src/main/java/p/studio/workspaces/debug/**`, related tests.
## Test Requirements
### Unit Tests
- Update or remove module-specific tests for `prometeu-lsp` and `prometeu-vfs`.
- Preserve unit coverage for execution session, play/stop coordination, and runtime handshake behavior.
### Integration Tests
- Run compiler pipeline integration tests that cover `analyze`, `compile`, and `build`.
- Run shipper/build integration tests that exercise `StudioShipperService`.
- Run runtime/debug integration or coordinator tests that validate play/stop behavior.
### Manual Verification
- Trigger Studio build flow and confirm artifact generation still works.
- Trigger Studio play flow and confirm runtime launch/stop still works.
- Open Debug and Shipper workspaces and confirm they remain operational.
## Acceptance Criteria
- [x] `prometeu-lsp` is no longer part of the build graph.
- [x] `prometeu-vfs` is no longer part of the build graph.
- [x] No production Studio class imports legacy `LSP` or `VFS` module types.
- [x] Compiler and shipper build flows still work.
- [x] Play/run/debug flows still work without the removed modules.
## Dependencies
- `DEC-0031` accepted and normatively locked.
- Shell/session cleanup completed enough that no surviving production code still requires legacy `LSP`/`VFS` types.
## Risks
- Hidden transitive dependencies may keep the build graph coupled to removed modules longer than expected.
- Runtime or debug flows may have indirect event or session assumptions not obvious from imports alone.
- Deleting modules too early may obscure compile errors that should instead be fixed in surviving Studio code first.

View File

@ -1,90 +0,0 @@
---
id: PLN-0064
ticket: studio-editor-workspace-cleanup
title: Normative Test and Lesson Cleanup for Editor Stack Removal
status: done
created: 2026-05-05
completed: 2026-05-05
tags: [studio, editor, cleanup, docs, tests, lessons]
---
## Objective
Remove or revise the normative documentation, tests, lessons, and user-facing resources that describe the embedded editor stack as a current Studio surface.
## Background
`DEC-0031` treats the editor stack removal as both code cleanup and normative cleanup. The repository currently contains active specs, README entries, i18n resources, and lessons that define `Code Editor`, `prometeu-vfs`, and the integrated semantic-read phase as active architecture.
## Scope
### Included
- Remove or rewrite Studio specs dedicated to the embedded editor stack.
- Update the Studio specs index and README.
- Remove or archive editor/LSP/VFS-specific tests that are no longer valid.
- Reclassify legacy lessons and references so they are not presented as active guidance.
- Remove user-facing i18n strings that only existed for the editor stack.
### Excluded
- Implementation of shell/session/module cleanup itself.
- Future specs for the replacement backend or replacement external-editor strategy.
## Execution Steps
### Step 1 - Clean normative Studio specs
**What:** Remove or replace specs that define the embedded editor stack as active architecture.
**How:** Delete or explicitly retire the `Code Editor`, `Project Document VFS`, and `Integrated LSP Semantic Read Phase` specs, then rewrite any remaining Studio README/index material so it no longer points to dead architecture.
**File(s):** `docs/specs/studio/5. Code Editor Workspace Specification.md`, `docs/specs/studio/6. Project Document VFS Specification.md`, `docs/specs/studio/7. Integrated LSP Semantic Read Phase Specification.md`, `docs/specs/studio/README.md`.
### Step 2 - Clean user-facing resources and shell references
**What:** Remove editor-specific strings, labels, and messages that no longer correspond to product surfaces.
**How:** Delete `workspace.code` and `codeEditor.*` message keys and any equivalent theme or resource references still tied to removed editor UI.
**File(s):** `prometeu-studio/src/main/resources/i18n/messages.properties`, any directly related theme or resource files.
### Step 3 - Clean tests and update surviving expectations
**What:** Remove tests whose sole purpose was validating the editor stack and update remaining tests to stop expecting that stack.
**How:** Delete or rewrite tests for editor workspace behavior, legacy `LSP`, legacy `VFS`, session expectations, and any shell assertions that still require the editor workspace.
**File(s):** `prometeu-studio/src/test/java/p/studio/projectsessions/**`, editor-related tests, `prometeu-lsp/**/test/**`, `prometeu-vfs/**/test/**`, any shell-level tests affected by workspace removal.
### Step 4 - Reclassify lessons and historical references
**What:** Ensure discussion lessons remain historically useful without being mistaken for current architecture.
**How:** Review the lessons and references tied to editor/VFS/LSP waves and either archive them, mark them as legacy, or update index/readme material so they are not treated as active operational guidance.
**File(s):** affected files under `discussion/lessons/DSC-0010*`, `DSC-0012*`, `DSC-0013*`, `DSC-0014*`, `DSC-0016*`, `DSC-0017*`, `DSC-0020*`, `DSC-0021*`, plus any summary/index surfaces that present them.
## Test Requirements
### Unit Tests
- Ensure no surviving test suite still references removed editor stack types or message keys.
- Add assertions where needed that remaining shell/resource state is internally consistent.
### Integration Tests
- Validate the Studio docs/spec tree remains internally linked after removal or retirement of the editor specs.
- Validate the build/test graph no longer includes editor-stack-only suites.
### Manual Verification
- Read the Studio spec README and confirm it no longer advertises the removed stack as active.
- Inspect project lessons/readme surfaces and confirm editor-stack lessons are clearly historical or retired.
- Launch the application and confirm no missing i18n keys or dead UI labels remain.
## Acceptance Criteria
- [x] Studio specs no longer define the embedded editor stack as an active surface.
- [x] Studio README/index material no longer points to removed editor/VFS/LSP architecture as current.
- [x] Editor-specific i18n keys are removed or no longer consumed.
- [x] Obsolete tests are removed or rewritten.
- [x] Historical lessons are clearly demoted from active operational guidance.
## Dependencies
- `DEC-0031` accepted and normatively locked.
- Sufficient implementation progress that the codebase no longer depends on the removed specs/resources/tests.
## Risks
- Removing normative docs too early may temporarily leave the repo without clear current guidance.
- Historical lessons may still be valuable; deleting them outright could lose context that should instead be reclassified.
- Partial cleanup can leave broken links or missing i18n keys that only appear at runtime.

View File

@ -1,118 +0,0 @@
---
id: PLN-0065
ticket: studio-new-lsp-api-and-v1-boundary
title: LSP Boundary and Module Scaffolding
status: done
created: 2026-05-05
completed: 2026-05-05
tags: [studio, lsp, api, boundary, modules, architecture]
---
## Objective
Recreate `prometeu-lsp:prometeu-lsp-api` and `prometeu-lsp:prometeu-lsp-v1` with a structurally correct boundary that is ready for long-term maintenance, while intentionally keeping the initial server behavior minimal.
## Background
`DEC-0032` locks that:
- `lsp-api` is an internal Studio boundary, not a mirror of the LSP protocol;
- `lsp-v1` is the concrete LSP adapter and the only module allowed to depend on `LSP4J`;
- the current mock server shape MUST NOT be treated as the product pattern;
- wave 1 prioritizes architecture and lifecycle over semantic depth.
The repository already reserves `prometeu-lsp:*` in `settings.gradle.kts`, but the modules are currently empty shells after the cleanup.
## Scope
### Included
- Recreate Gradle/module structure for `prometeu-lsp-api` and `prometeu-lsp-v1`.
- Define the minimal internal API contract for server lifecycle by project.
- Establish package boundaries that keep protocol DTOs and `LSP4J` types out of `lsp-api`.
- Add boundary-oriented tests or build checks where feasible.
### Excluded
- Wiring the server into Studio project open/close.
- Rich semantic behavior, diagnostics, definition, symbols, or incremental analysis.
- Automation channel work for `compile/build/run/debug`.
## Non-Goals
- Full language feature implementation.
- Any attempt to preserve compatibility with the legacy removed `prometeu-lsp`.
- Transport changes in the VS Code extension.
## Execution Steps
### Step 1 - Recreate the Gradle modules with explicit dependency ownership
**What:** Reintroduce the `prometeu-lsp-api` and `prometeu-lsp-v1` modules as clean boundaries.
**How:** Restore the module directories and `build.gradle.kts` files, wire them in `settings.gradle.kts`, and keep dependencies explicit:
- `prometeu-lsp-api` depends only on stable internal modules it truly needs;
- `prometeu-lsp-v1` depends on `prometeu-lsp-api`, `compiler` services it consumes, and `LSP4J`;
- no other Studio module depends on `LSP4J`.
**File(s):** `settings.gradle.kts`, `prometeu-lsp/prometeu-lsp-api/build.gradle.kts`, `prometeu-lsp/prometeu-lsp-v1/build.gradle.kts`, affected root/module build files.
### Step 2 - Define the minimal internal lifecycle contract in `lsp-api`
**What:** Create the smallest stable API needed by the Studio host.
**How:** Add internal contracts such as a project-scoped `bootServer(project)` and `shutdownServer(project)` surface plus the minimal supporting DTO/entity types required by that lifecycle. Keep the API transport-agnostic and free of protocol DTOs.
**File(s):** `prometeu-lsp/prometeu-lsp-api/src/main/java/**`.
### Step 3 - Define the adapter shape in `lsp-v1`
**What:** Establish the internal code organization of the concrete adapter.
**How:** Create clear package slices inside `lsp-v1`, such as:
- lifecycle/bootstrap,
- server host/transport,
- protocol DTO mapping,
- compiler-facing service bridge.
The implementation may stay behaviorally dumb, but the structure MUST already reflect the final responsibility split.
**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/**`.
### Step 4 - Add boundary conformance tests
**What:** Prevent architectural drift from day 1.
**How:** Add tests or static checks that fail if:
- `lsp-api` imports `LSP4J`;
- protocol DTOs leak into `lsp-api`;
- non-`lsp-v1` Studio modules start importing `LSP4J`.
**File(s):** `prometeu-lsp/prometeu-lsp-api/src/test/java/**`, `prometeu-lsp/prometeu-lsp-v1/src/test/java/**`, or build-level checks if that is cleaner.
## Test Requirements
### Unit Tests
- Verify the lifecycle contracts in `lsp-api` have deterministic defaults and null-safety.
- Verify `lsp-v1` module-local bootstrap pieces can be instantiated without a running Studio shell.
- Verify boundary checks catch `LSP4J` leakage.
### Integration Tests
- Run a root or targeted Gradle build proving the new modules compile and coexist with `prometeu-studio` and `prometeu-app`.
### Manual Verification
- Inspect the recreated module tree and confirm `lsp-api` contains no protocol or `LSP4J` types.
## Acceptance Criteria
- [x] `prometeu-lsp-api` and `prometeu-lsp-v1` exist again as active modules.
- [x] `lsp-api` exposes only internal lifecycle-oriented contracts.
- [x] `lsp-v1` is the only module allowed to depend on `LSP4J`.
- [x] The new module structure expresses clear responsibility boundaries even with dumb behavior.
- [x] Boundary conformance is covered by tests or equivalent build checks.
## Dependencies
- `DEC-0032` accepted and normatively locked.
- Current Gradle graph and module includes available for reactivation.
## Risks
- Reintroducing the modules too loosely can recreate the same ambiguity that killed the legacy stack.
- An underspecified API can force churn later; an oversized API can lock the wrong shape too early.
- Build-only enforcement may miss architectural drift unless the checks are explicit.

View File

@ -1,103 +0,0 @@
---
id: PLN-0066
ticket: studio-new-lsp-api-and-v1-boundary
title: Project-Scoped LSP Server Lifecycle in Studio
status: done
created: 2026-05-05
completed: 2026-05-05
tags: [studio, lsp, lifecycle, projects, boot, shutdown]
---
## Objective
Wire the new LSP server lifecycle into the Studio project lifecycle so a server starts when a project opens and stops when that project closes, without introducing a process-global LSP service.
## Background
`DEC-0032` requires a project-scoped server lifecycle and explicitly rejects a global Studio-wide server. The current natural integration points are:
- `StudioProjectSession`
- `StudioProjectSessionFactory`
- `StudioWindowCoordinator`
These surfaces already own project startup and teardown flow and therefore are the correct place to consume `lsp-api`.
## Scope
### Included
- Add project-scoped LSP server ownership to the Studio project session lifecycle.
- Boot the server during project open.
- Shutdown the server during project close.
- Preserve existing shell, packer, play/stop, and debug flows.
### Excluded
- Rich semantic responses.
- Automation channel work.
- VS Code extension transport changes.
## Non-Goals
- Cross-project shared server process management.
- Multi-project pooling or server reuse.
- Changing the overall launcher/window model.
## Execution Steps
### Step 1 - Extend project session ownership to include the LSP lifecycle boundary
**What:** Make `StudioProjectSession` own the new project-scoped LSP service reference.
**How:** Add the minimal `lsp-api` contract to `StudioProjectSession`, ensure it is initialized by `StudioProjectSessionFactory`, and guarantee shutdown on `close()`, including failure-safe teardown ordering.
**File(s):** `prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java`, `prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSessionFactory.java`, related tests.
### Step 2 - Trigger boot during project open flow
**What:** Start the LSP server as part of project initialization.
**How:** Update the project-open sequence so the server boots after the project context is ready and before the project window is considered fully opened. Ensure failures surface as project-open failures instead of becoming silent background errors.
**File(s):** `prometeu-studio/src/main/java/p/studio/window/StudioWindowCoordinator.java`, possibly `prometeu-app/src/main/java/p/studio/AppContainer.java` and `prometeu-studio/src/main/java/p/studio/Container.java` if dependency injection changes are needed.
### Step 3 - Trigger shutdown during project close flow
**What:** Cleanly stop the project-bound server when the project closes.
**How:** Ensure the existing project close path tears down the LSP service through the session close path, with no leaked socket listener or hanging background resources.
**File(s):** `prometeu-studio/src/main/java/p/studio/window/StudioWindowCoordinator.java`, `prometeu-studio/src/main/java/p/studio/projectsessions/StudioProjectSession.java`.
### Step 4 - Preserve current dumb connectivity semantics
**What:** Keep the initial server behavior intentionally simple while validating lifecycle.
**How:** Wire the server so the VS Code extension can still connect over TCP, even if the server behavior remains a minimal handshake or stubbed capability set for now.
**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/**`, `tools/vscode-extension/src/extension.ts` only if configuration or expectations need adjustment.
## Test Requirements
### Unit Tests
- Verify project session close calls LSP shutdown exactly once.
- Verify boot failures are surfaced deterministically during project open.
- Verify repeated close remains idempotent.
### Integration Tests
- Run `prometeu-studio` tests covering project open/close lifecycle.
- Add a focused integration test proving a project-scoped server is booted and then shut down.
### Manual Verification
- Open a Studio project, confirm the server starts.
- Close the project, confirm the server port is released and the process/resources terminate.
- Connect via the existing VS Code extension and confirm the dumb server remains reachable.
## Acceptance Criteria
- [x] Opening a Studio project boots an LSP server for that project.
- [x] Closing the project shuts down that server.
- [x] The lifecycle is owned by project session boundaries, not global app startup.
- [x] Existing non-LSP project flows remain operational.
- [x] The current dumb connectivity workflow remains usable as a temporary implementation phase.
## Dependencies
- `DEC-0032` accepted and normatively locked.
- `PLN-0065` providing the new module and API boundary.
## Risks
- Startup ordering mistakes can make project open flaky or hide boot errors.
- Shutdown ordering mistakes can leak ports or threads.
- Lifecycle wiring can accidentally reintroduce global process ownership if the session boundary is not kept strict.

View File

@ -1,100 +0,0 @@
---
id: PLN-0067
ticket: studio-new-lsp-api-and-v1-boundary
title: Compiler-Backed Dumb LSP Server Baseline
status: done
created: 2026-05-05
completed: 2026-05-05
tags: [studio, lsp, compiler, baseline, protocol, vscode]
---
## Objective
Establish a maintainable, compiler-backed baseline inside `lsp-v1` that keeps the server behavior deliberately simple while creating the seams required for later semantic layering.
## Background
`DEC-0032` explicitly allows wave 1 to remain semantically thin, but it forbids keeping an ad hoc mock structure as the long-term coding pattern. The backend therefore needs a baseline that is:
- dumb in behavior when necessary,
- but already correctly composed over `compiler` services,
- and already structured for layered enrichment later.
## Scope
### Included
- Create compiler-facing service seams used by `lsp-v1`.
- Provide a small, explicit set of LSP capabilities or responses that prove the adapter shape.
- Keep the VS Code extension compatible with the current TCP model.
- Document the temporary behavioral limits in code and tests.
### Excluded
- Full diagnostics, definition, symbols, inlay hints, or multi-file semantic completeness.
- Automation channel work.
- Non-TCP transport experiments.
## Non-Goals
- Matching the full final language feature set.
- Recreating the deleted legacy `prometeu-lsp` behavior.
- Optimizing for performance before the baseline structure is validated.
## Execution Steps
### Step 1 - Define compiler-facing bridge services inside `lsp-v1`
**What:** Introduce explicit bridge classes or adapters between protocol handlers and `compiler`.
**How:** Create narrow services inside `lsp-v1` that own calls into `compiler` entrypoints. Even if the first concrete responses are stubbed or partial, the protocol handlers must already call through these seams instead of embedding compiler knowledge everywhere.
**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/**`, relevant `prometeu-compiler` integration points when discoverable.
### Step 2 - Implement a minimal but structured capability slice
**What:** Keep the server intentionally dumb, but no longer structurally improvised.
**How:** Choose a small capability surface such as `initialize`, `shutdown`, and one lightweight language feature or health response. The exact feature set may stay narrow, but the code must already follow the final layering:
- protocol request handling,
- bridge service invocation,
- result mapping.
**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/**`, potentially `tools/vscode-extension/src/extension.ts` if initialization expectations need tightening.
### Step 3 - Codify temporary behavior limits
**What:** Make the current limitations explicit instead of implicit.
**How:** Add tests and lightweight documentation/comments that define the intentionally supported baseline behavior so future work can add capability in layers without guessing what the "mock" currently means.
**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/test/java/**`, targeted source comments where they reduce ambiguity.
## Test Requirements
### Unit Tests
- Verify protocol handlers call the correct bridge services.
- Verify compiler bridge services can be instantiated and return stable baseline results.
- Verify no handler bypasses the bridge layer to embed semantic logic ad hoc.
### Integration Tests
- Run a targeted Studio/LSP integration proving the VS Code client can initialize against the dumb server.
- Run compiler-related tests needed to validate the consumed service seams.
### Manual Verification
- Connect from VS Code and confirm the server initializes and remains stable.
- Confirm the limited capability set behaves predictably and does not masquerade as richer support than actually implemented.
## Acceptance Criteria
- [x] `lsp-v1` talks to `compiler` through explicit bridge services.
- [x] The baseline server behavior remains intentionally simple but structurally clean.
- [x] At least one minimal end-to-end capability slice proves the final layering.
- [x] The extension can still connect over TCP without protocol regressions.
- [x] Temporary semantic limits are explicit in tests and code structure.
## Dependencies
- `DEC-0032` accepted and normatively locked.
- `PLN-0065` for module/boundary setup.
- `PLN-0066` for project-scoped lifecycle integration.
## Risks
- A "temporary" dumb server can calcify unless the seams are truly explicit and tested.
- Over-stubbing can hide compiler integration issues that should be surfaced early.
- Picking too many baseline features in this wave can dilute the architectural focus.

View File

@ -1,118 +0,0 @@
---
id: PLN-0068
ticket: frontend-visual-theme-spec-and-css-retirement
title: Frontend Visual Contract and PBS Migration
status: open
created: 2026-05-06
completed:
tags: [compiler, compiler-general, frontend, pbs, presentation, theming, contract]
---
## Objective
Introduce the canonical structured frontend visual contract in `FrontendSpec`, migrate PBS to that contract, and demote `semantic-highlighting.css` from authored truth to migration-only input.
## Background
`DEC-0033` locks that frontend visual intent must become structured canonical data, support multiple themes per frontend, remain token-centric, and retire authored host-consumed semantic CSS as the canonical source.
PBS is the first frontend and therefore defines the first concrete migration path, but the contract MUST remain compiler-general rather than PBS-shaped by accident.
## Scope
### Included
- Evolve compiler/frontend metadata to publish a structured visual contract.
- Define the contract shape for semantic-token styling, editor surfaces, and theme identity.
- Migrate PBS to the new contract.
- Preserve any temporary migration utility needed to derive the first contract from the existing PBS CSS.
- Add validation tests that make the new contract normative and stable.
### Excluded
- LSP transport changes.
- Studio rendering changes.
- VS Code runtime translation changes.
## Non-Goals
- Designing a generic host-owned theme engine.
- Supporting every possible frontend visual attribute in wave 1.
- Keeping authored CSS as a parallel canonical source.
## Execution Steps
### Step 1 - Define the structured visual contract in compiler-general surfaces
**What:** Replace the resource-centric semantic presentation shape with a canonical structured visual contract in `FrontendSpec`.
**How:** Add or evolve frontend metadata models so each frontend can publish:
1. semantic token vocabulary ownership,
2. one or more named visual themes,
3. token-centric visual rules,
4. editor-surface colors needed to preserve frontend identity.
The model MUST be compiler-general and MUST NOT encode PBS-specific assumptions into the shared type system.
**File(s):** `prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/**`, affected frontend registry/definition surfaces.
### Step 2 - Define the theme and token rule semantics explicitly
**What:** Make the contract operational rather than descriptive.
**How:** Specify exact fields, invariants, and null/empty behavior for:
1. theme identity,
2. theme selection metadata if needed at the contract layer,
3. token style rules,
4. editor surface colors,
5. versioning semantics inside or alongside `FrontendSpec`.
The implementation MUST make it possible for hosts to translate the contract mechanically without inferring missing meaning.
**File(s):** `prometeu-compiler/prometeu-compiler-core/src/main/java/**`, associated tests in compiler modules.
### Step 3 - Migrate PBS from authored CSS truth to structured contract truth
**What:** Make PBS the first frontend to author the new contract.
**How:** Update `PBSDefinitions` and related PBS presentation metadata to publish one or more frontend-owned themes through the new contract. The existing `semantic-highlighting.css` MAY be parsed or manually transcribed to bootstrap the migration, but once the structured contract is in place, CSS MUST no longer be treated as authored truth.
**File(s):** `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/**`, `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/resources/themes/pbs/**`, related PBS tests.
### Step 4 - Lock contract validity with tests
**What:** Prevent future drift back to opaque resource ownership.
**How:** Add tests that assert:
1. frontends publish structured visual themes,
2. PBS token vocabulary and theme definitions are coherent,
3. required token styles and editor-surface data resolve correctly,
4. authored CSS is no longer the canonical contract source.
**File(s):** compiler-general and PBS test suites.
## Test Requirements
### Unit Tests
- Validate model invariants for theme IDs, token rules, and editor-surface fields.
- Validate `FrontendSpec` copies and exposes structured theme data safely.
- Validate PBS publishes at least one coherent theme using the new contract.
### Integration Tests
- Run targeted compiler and PBS tests proving the contract compiles, resolves, and remains discoverable through frontend definitions.
### Manual Verification
- Inspect the PBS frontend definition and confirm the structured contract is the readable authored source of truth.
- Confirm any remaining CSS is clearly migration-only or generated-output-only.
## Acceptance Criteria
- [ ] `FrontendSpec` publishes a structured canonical visual contract.
- [ ] The contract supports multiple themes per frontend.
- [ ] The contract is token-centric and can also express editor-surface colors.
- [ ] PBS is migrated to the new contract.
- [ ] `semantic-highlighting.css` is no longer treated as authored canonical frontend presentation data.
## Dependencies
- `DEC-0033` accepted and normatively locked.
## Risks
- Overfitting the first contract to PBS would weaken future frontend adoption.
- An underspecified token-style model would force host inference and violate the decision.
- Keeping CSS alive as a silent parallel truth source would nullify the migration.

View File

@ -1,114 +0,0 @@
---
id: PLN-0069
ticket: frontend-visual-theme-spec-and-css-retirement
title: LSP Visual Theme Transport and Theme Selection Propagation
status: open
created: 2026-05-06
completed:
tags: [studio, lsp, protocol, transport, presentation, theming, compiler]
---
## Objective
Extend the LSP boundary and transport surfaces so hosts receive frontend-owned visual theme data, theme identity, and active-theme information without collapsing that contract into host-authored categories.
## Background
`DEC-0033` requires LSP to transport enough structured frontend-owned visual information for hosts to render the active frontend theme, preserve frontend and token identity, and avoid forcing the extension to keep hand-maintained theme rules.
The compiler contract itself is handled by `PLN-0068`. This plan covers the transport boundary that carries that contract into host adapters.
## Scope
### Included
- Extend internal LSP-facing description or capability surfaces to expose structured frontend visual contract data.
- Transport theme identity and active-theme information where needed.
- Preserve semantic token identity and frontend ownership through mapping layers.
- Add transport-level tests for the new visual contract payloads.
### Excluded
- Defining the compiler-general contract itself.
- Studio-side rendering implementation.
- VS Code-side rendering implementation.
## Non-Goals
- Inventing host-owned fallback theme categories.
- Expanding LSP beyond what is required to carry the visual contract.
- Building transport that requires hand-curated per-frontend extension updates.
## Execution Steps
### Step 1 - Extend internal LSP descriptions to carry visual contract data
**What:** Evolve the LSP-side server/bridge description surfaces to expose frontend-owned visual contract data instead of ad hoc token metadata only.
**How:** Update `lsp-api` and `lsp-v1` internal description models so they can carry:
1. frontend identity,
2. semantic token legend identity,
3. available theme definitions or references,
4. active theme selection.
The payload shape MUST remain faithful to the frontend contract and MUST NOT normalize it into host-owned abstractions.
**File(s):** `prometeu-lsp/prometeu-lsp-api/src/main/java/**`, `prometeu-lsp/prometeu-lsp-v1/src/main/java/**`.
### Step 2 - Thread the visual contract through bridge and mapper layers
**What:** Ensure the compiler-backed bridge and protocol mappers preserve visual theme data end to end.
**How:** Update bridge services, protocol mappers, server description responses, and any capability/bootstrap path that currently exposes token data so they now expose the structured visual contract and active theme metadata.
**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/**`, `.../messages/**`, `.../mapping/**`.
### Step 3 - Define theme selection behavior for host consumption
**What:** Make active-theme semantics operational.
**How:** Define and implement the transport rule for which theme a host should apply:
1. single-theme frontend behavior,
2. multi-theme frontend behavior,
3. default theme behavior when no host override is in play,
4. how active-theme selection is surfaced to adapters.
The transport MUST make host behavior deterministic without host-owned guessing.
**File(s):** `prometeu-lsp/prometeu-lsp-api/**`, `prometeu-lsp/prometeu-lsp-v1/**`, tests.
### Step 4 - Add transport conformance tests
**What:** Prevent regression back to token-only or host-shaped payloads.
**How:** Add tests that verify:
1. theme payloads are present,
2. token identities survive transport unchanged,
3. active-theme information is deterministic,
4. no mapper collapses frontend-owned visual data into host-authored categories.
**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/test/java/**`, `prometeu-lsp/prometeu-lsp-api/src/test/java/**` if needed.
## Test Requirements
### Unit Tests
- Validate DTO/model invariants for theme payloads and active-theme fields.
- Validate mapper behavior for full visual contract transport.
### Integration Tests
- Run targeted LSP tests proving a compiler-backed frontend description reaches the host adapter layer with visual theme data intact.
### Manual Verification
- Inspect initialize/description pathways and confirm theme metadata is present and frontend-shaped.
## Acceptance Criteria
- [ ] LSP description/transport surfaces carry structured frontend visual theme data.
- [ ] Theme identity and active-theme semantics are deterministic.
- [ ] Semantic token identity remains frontend-owned end to end.
- [ ] No LSP layer introduces host-owned theme abstractions as canonical transport data.
## Dependencies
- `DEC-0033` accepted and normatively locked.
- `PLN-0068` for the compiler-side contract shape and PBS migration.
## Risks
- Transporting too little theme data would force host inference and violate the decision.
- Transporting host-shaped payloads would silently recreate the wrong ownership boundary.
- Theme selection semantics can become ambiguous unless explicitly defined in this plan.

View File

@ -1,101 +0,0 @@
---
id: PLN-0070
ticket: frontend-visual-theme-spec-and-css-retirement
title: Studio Visual Theme Adapter and CSS Retirement
status: open
created: 2026-05-06
completed:
tags: [studio, editor, presentation, theming, adapter, css-retirement]
---
## Objective
Make Studio consume the structured frontend visual contract as an adapter, remove any remaining dependency on authored frontend semantic CSS as the canonical source, and keep any host rendering mechanism clearly derivative.
## Background
`DEC-0033` locks that Studio is a rendering adapter over frontend-owned visual themes and that generated CSS is acceptable only as an adapter mechanism, not as the canonical frontend artifact.
This plan applies that rule to the Studio side of the stack.
## Scope
### Included
- Update Studio-side presentation registries or rendering services to consume structured frontend visual contract data.
- Generate or map host rendering artifacts from the structured contract if Studio still needs CSS or equivalent host render descriptors.
- Remove reliance on authored frontend semantic CSS as a direct semantic presentation contract.
- Add Studio tests proving the adapter path is derivative and deterministic.
### Excluded
- Compiler-side contract design.
- LSP transport contract design.
- VS Code adapter behavior.
## Non-Goals
- Rebuilding the deleted legacy Studio editor stack.
- Introducing Studio-owned frontend themes.
- Preserving authored semantic CSS as a parallel truth source.
## Execution Steps
### Step 1 - Update Studio presentation consumption to use the structured contract
**What:** Make Studio consume frontend-owned visual theme data instead of resource-only semantic presentation.
**How:** Update presentation registries, semantic highlighting services, or other editor-related rendering seams so they resolve structured visual theme data from the frontend description path.
**File(s):** `prometeu-studio/src/main/java/**`, any remaining editor/presentation adapter surfaces still active after cleanup.
### Step 2 - Derive host rendering artifacts from the contract
**What:** Keep Studio rendering mechanical.
**How:** If Studio still requires CSS or CSS-like structures, generate or map them from the structured frontend visual contract. The host-generated artifact MUST be clearly derivative and MUST NOT be treated as authored frontend truth.
**File(s):** `prometeu-studio/src/main/java/**`, possible theme/presentation helper modules, generated resource paths if adopted.
### Step 3 - Remove direct canonical dependence on frontend semantic CSS
**What:** Retire the old consumption model.
**How:** Remove or rewrite any code path that treats frontend semantic CSS resources as the canonical semantic presentation input. Leave only temporary compatibility or generated-output behavior if strictly needed during rollout.
**File(s):** `prometeu-studio/**`, related frontend resource loading code.
### Step 4 - Add Studio adapter conformance tests
**What:** Lock the adapter boundary.
**How:** Add tests that verify:
1. Studio consumes structured frontend visual themes,
2. token style rendering inputs are contract-derived,
3. any generated CSS is derivative,
4. Studio does not silently fall back to host-authored frontend theme logic.
**File(s):** `prometeu-studio/src/test/java/**` and any relevant integration test modules.
## Test Requirements
### Unit Tests
- Validate contract-to-rendering translation logic.
- Validate theme selection consumption on the Studio side.
### Integration Tests
- Run targeted Studio-side tests proving frontend presentation resolves from structured contract data and not from authored semantic CSS.
### Manual Verification
- Inspect the Studio path and confirm remaining CSS, if any, is generated or compatibility-only.
## Acceptance Criteria
- [ ] Studio consumes structured frontend visual contract data.
- [ ] Any Studio-side CSS or equivalent rendering descriptor is derivative, not canonical.
- [ ] Direct canonical dependence on authored frontend semantic CSS is removed.
- [ ] Studio does not reauthor frontend visual identity locally.
## Dependencies
- `DEC-0033` accepted and normatively locked.
- `PLN-0068` for the canonical compiler/frontend contract.
- `PLN-0069` for transport of visual contract data into the host boundary.
## Risks
- Studio may still hide old CSS assumptions in helper layers unless the migration is exhaustive.
- Generated CSS can accidentally become the new silent truth source if ownership boundaries are not explicit in code and tests.
- Residual editor cleanup from earlier refactors may obscure the remaining active consumption path.

View File

@ -1,100 +0,0 @@
---
id: PLN-0071
ticket: frontend-visual-theme-spec-and-css-retirement
title: VS Code Dynamic Theme Translation Adapter
status: open
created: 2026-05-06
completed:
tags: [vscode, extension, lsp, presentation, theming, adapter]
---
## Objective
Turn the VS Code extension into a stable adapter that translates frontend-owned visual theme contracts into VS Code-compatible rendering behavior without requiring source edits for routine frontend theme changes.
## Background
`DEC-0033` explicitly locks that the extension must not become a repository of manually curated frontend theme rules. The extension must translate the contract it receives rather than being edited whenever a frontend changes colors, emphasis, or theme variants.
This plan covers the client-side adapter behavior that satisfies that requirement.
## Scope
### Included
- Replace hardcoded per-frontend visual theme rules with dynamic or generated translation based on the transported frontend contract.
- Define the minimum static VS Code contribution surface still required by the platform.
- Support multi-theme frontend data consumption and active-theme application.
- Add extension tests or verification coverage around theme translation.
### Excluded
- Compiler-side contract definition.
- LSP transport definition.
- Studio rendering behavior.
## Non-Goals
- Building a general-purpose VS Code theme marketplace artifact.
- Allowing the extension to become a second authored source of frontend theme truth.
- Solving unrelated reconnect or transport lifecycle issues beyond what this adapter needs.
## Execution Steps
### Step 1 - Identify the minimal static VS Code contribution surface
**What:** Separate what the extension must declare statically from what it can translate dynamically.
**How:** Keep only the minimal `package.json` contribution data required for VS Code to recognize semantic token kinds or activate the extension. Remove hardcoded frontend-specific color rules from static configuration where dynamic translation can take over.
**File(s):** `tools/vscode-extension/package.json`, related extension bootstrap files.
### Step 2 - Implement contract-to-VS Code theme translation
**What:** Translate frontend-owned visual contract data into VS Code-understandable configuration.
**How:** Update extension runtime code to receive the transported visual theme contract, map token and editor-surface data into the VS Code APIs/configuration model, and apply the active frontend theme deterministically.
**File(s):** `tools/vscode-extension/src/**`, mirrored build outputs only if local toolchain constraints require temporary manual sync.
### Step 3 - Support multi-theme frontends without extension source edits
**What:** Make frontend theme growth operationally cheap.
**How:** Ensure that adding or changing frontend-owned themes does not require new extension source logic unless the VS Code platform itself introduces a new capability boundary. Theme identity, token rules, and active selection must be data-driven.
**File(s):** `tools/vscode-extension/src/**`, possible supporting protocol model surfaces if consumed directly.
### Step 4 - Add adapter verification coverage
**What:** Protect the no-manual-theme-maintenance rule.
**How:** Add tests or deterministic verification around:
1. translation of token rules,
2. translation of editor-surface colors where supported,
3. handling of multiple frontend themes,
4. absence of hardcoded PBS-only theme logic in the adapter path.
**File(s):** `tools/vscode-extension/src/test/**` if present, or equivalent test harness/verification approach adopted by the extension module.
## Test Requirements
### Unit Tests
- Validate translation of structured token rules into VS Code-compatible theme rules.
- Validate active-theme switching behavior for data-driven frontend themes.
### Integration Tests
- Run extension-targeted validation proving the frontend contract can change without source-level theme edits.
### Manual Verification
- Open PBS content through the extension and confirm the active theme is applied from transported contract data rather than hardcoded `package.json` color tables.
## Acceptance Criteria
- [ ] The extension no longer depends on hardcoded frontend-specific theme rules as the primary rendering source.
- [ ] Frontend theme changes are driven by contract data rather than extension source edits.
- [ ] Multi-theme frontend payloads can be translated and applied deterministically.
- [ ] The remaining static VS Code contribution surface is minimal and structural only.
## Dependencies
- `DEC-0033` accepted and normatively locked.
- `PLN-0069` for transport of visual theme data to the extension.
## Risks
- VS Code platform constraints may force a hybrid static/runtime model that must stay carefully bounded.
- The current local Node/TypeScript environment issues can slow validation.
- Leaving too much theme data in `package.json` would preserve the current maintenance problem under a new name.

View File

@ -1,119 +0,0 @@
---
id: PLN-0072
ticket: frontend-semantic-host-projection-flexibility
title: Frontend Semantic Host Projection Contract
status: done
created: 2026-05-06
completed: 2026-05-06
tags: [compiler, compiler-general, frontend, semantics, host-projection, vscode, pbs]
---
## Objective
Introduce the canonical frontend-authored semantic host projection contract in compiler-general frontend metadata and migrate PBS to publish its first VS Code projection without weakening frontend-owned semantic vocabulary.
## Background
`DEC-0034` locks that semantic vocabularies remain frontend-owned and canonical, while hosts such as VS Code consume declarative projection metadata authored by the frontend. The current semantic presentation work already establishes frontend-owned themes through `DEC-0033`, but semantic adaptation still lacks a structured host projection contract.
PBS is the first concrete frontend and therefore the first migration target, but the contract MUST remain compiler-general rather than PBS-shaped.
## Scope
### Included
- Evolve compiler/frontend metadata to publish declarative semantic host projection descriptors.
- Define the contract shape for VS Code semantic token projection.
- Migrate PBS to author VS Code projection metadata for its canonical semantic keys.
- Add tests that lock the contract and prevent host-owned remapping logic from becoming the source of truth.
### Excluded
- LSP transport changes.
- VS Code extension runtime consumption changes.
- Redesigning PBS canonical semantic keys to mimic VS Code categories.
## Non-Goals
- Introducing a global rigid semantic taxonomy across frontends.
- Making VS Code semantic token types the canonical frontend semantic contract.
- Solving projection for every future host in the first wave.
## Execution Steps
### Step 1 - Define compiler-general host projection metadata
**What:** Extend the frontend semantic metadata surfaces to carry host projection descriptors alongside canonical semantic keys.
**How:** Add or evolve compiler-general model types so a frontend can declare, for each host projection entry:
1. the canonical frontend semantic key being projected,
2. the target host identity,
3. the host token type or equivalent target category,
4. any host modifiers,
5. fallback projection semantics when the host cannot represent the key exactly.
The contract MUST preserve the frontend semantic key as canonical and MUST treat projection as derivative metadata.
**File(s):** `prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/models/**`, related frontend definition surfaces.
### Step 2 - Make projection rules operational and mechanically consumable
**What:** Turn the projection contract into an exact operational surface rather than an informal note.
**How:** Define invariants, null/empty behavior, and lookup rules for projection descriptors, including:
1. host identifier semantics,
2. duplicate or conflicting projection handling,
3. missing projection behavior,
4. fallback behavior representation,
5. safe access patterns from `FrontendSpec`.
The result MUST allow host adapters to translate frontend-authored projection data mechanically without semantic reinterpretation.
**File(s):** `prometeu-compiler/prometeu-compiler-core/src/main/java/**`, associated compiler-general tests.
### Step 3 - Migrate PBS to author its first VS Code projection
**What:** Make PBS publish its VS Code semantic projection through the new contract.
**How:** Update PBS frontend metadata so its canonical semantic keys remain unchanged while the frontend also declares how each key projects into VS Code semantic token types and modifiers. The authored projection MUST live in PBS frontend metadata and MUST NOT be reauthored inside the extension.
**File(s):** `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/**`, related PBS semantic presentation tests.
### Step 4 - Lock the contract with tests
**What:** Prevent future drift toward host-owned semantic policy.
**How:** Add tests that assert:
1. frontends publish projection descriptors through compiler-general metadata,
2. PBS canonical keys remain frontend-owned,
3. PBS VS Code projection resolves mechanically from frontend metadata,
4. no global repository-wide rigid semantic taxonomy is introduced as the canonical contract.
**File(s):** compiler-general and PBS test suites.
## Test Requirements
### Unit Tests
- Validate projection model invariants, including required frontend key linkage and host target fields.
- Validate `FrontendSpec` safely exposes host projection metadata.
- Validate missing and duplicate projection handling.
### Integration Tests
- Run targeted compiler and PBS tests proving host projection metadata compiles, resolves, and remains discoverable through frontend definitions.
### Manual Verification
- Inspect PBS frontend metadata and confirm the VS Code projection is authored there rather than in host adapter code.
- Confirm canonical PBS semantic keys remain readable and unchanged in ownership terms.
## Acceptance Criteria
- [ ] Compiler-general frontend metadata publishes declarative host projection descriptors.
- [ ] The contract preserves canonical frontend semantic keys as the source of truth.
- [ ] The contract supports a VS Code projection without forcing a global rigid taxonomy.
- [ ] PBS authors its VS Code semantic projection through the new contract.
- [ ] Tests lock the contract against host-owned semantic remapping drift.
## Dependencies
- `DEC-0034` accepted and normatively locked.
- `DEC-0033` accepted where semantic presentation metadata already exists and may need coordinated evolution.
## Risks
- Overfitting projection fields to PBS or to VS Code would weaken future frontend flexibility.
- Allowing ambiguous projection semantics would push semantic authorship back into adapters.
- Collapsing canonical keys into host-shaped aliases would violate `DEC-0034`.

View File

@ -1,107 +0,0 @@
---
id: PLN-0073
ticket: frontend-semantic-host-projection-flexibility
title: LSP Semantic Host Projection Transport
status: done
created: 2026-05-06
completed: 2026-05-06
tags: [lsp, compiler, frontend, semantics, host-projection, vscode, protocol]
---
## Objective
Transport canonical frontend semantic vocabulary and frontend-authored VS Code host projection metadata through the Prometeu LSP boundary without normalizing semantic meaning inside the transport layer.
## Background
`DEC-0034` requires LSP to carry both canonical frontend semantic keys and frontend-authored host projection metadata, while preserving the ownership boundary between frontend semantics and host adaptation. `DEC-0033` already introduced frontend-authored visual themes through the LSP handshake; semantic host projection must now follow the same ownership model.
## Scope
### Included
- Extend LSP-facing baseline message models to carry semantic host projection metadata.
- Update the compiler-backed language service bridge to resolve and expose that metadata from frontend definitions.
- Update the LSP protocol mapper to publish the transported metadata to the VS Code extension.
- Add tests that prove canonical keys and projection metadata are both preserved across transport.
### Excluded
- Defining the compiler-general projection contract itself.
- Applying the projection inside the VS Code extension.
- Redesigning semantic token classification logic beyond what is needed to expose projection metadata.
## Non-Goals
- Performing semantic normalization inside the LSP layer.
- Collapsing frontend semantic keys into host token types in baseline message models.
- Introducing host-specific semantic rules into `lsp-api` that belong to frontend metadata.
## Execution Steps
### Step 1 - Extend baseline transport models for semantic projection
**What:** Add baseline message shapes that can carry semantic host projection metadata.
**How:** Evolve LSP-facing DTOs so the server description or related handshake payload can transport:
1. frontend language identity,
2. canonical frontend semantic keys,
3. one or more host projection entries for VS Code,
4. any fallback metadata required by the projection contract.
The transport model MUST preserve canonical frontend keys explicitly rather than flattening everything into host token types.
**File(s):** `prometeu-lsp/prometeu-lsp-api/src/main/java/**`, `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/**`.
### Step 2 - Resolve transport payload from compiler frontend metadata
**What:** Make the language service bridge expose semantic host projection metadata from the frontend contract.
**How:** Update compiler-backed bridge code to read canonical semantic keys plus VS Code projection descriptors from the frontend definition and map them into the baseline transport payload without reinterpreting semantic meaning.
**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/**`.
### Step 3 - Publish the projection payload through the handshake
**What:** Make the VS Code client able to receive semantic projection metadata at initialization time.
**How:** Update the protocol mapping layer so the initialize result transports canonical semantic keys and VS Code projection metadata through the agreed experimental surface or another current handshake surface, while keeping semantic theming transport from `DEC-0033` intact and coherent.
**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/mapping/**`, related server description surfaces.
### Step 4 - Lock transport behavior with tests
**What:** Prevent future drift toward semantic normalization inside LSP.
**How:** Add tests that assert:
1. canonical frontend semantic keys survive transport,
2. VS Code projection entries survive transport,
3. payload structure remains mechanically consumable by the extension,
4. the transport layer does not replace frontend keys with host token categories.
**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/test/java/**`, `prometeu-lsp/prometeu-lsp-api` tests if present.
## Test Requirements
### Unit Tests
- Validate mapping from frontend projection metadata into baseline transport DTOs.
- Validate transport serialization of canonical keys plus projection entries.
### Integration Tests
- Run targeted `lsp-v1` tests proving the server handshake exposes both semantic themes and semantic host projection coherently.
### Manual Verification
- Inspect the initialize payload and confirm that frontend semantic keys and VS Code projection metadata are both visible.
- Confirm no layer in LSP rewrites canonical semantic keys into a mandatory host taxonomy.
## Acceptance Criteria
- [ ] LSP transport models carry canonical frontend semantic keys and VS Code projection metadata together.
- [ ] The compiler-backed bridge resolves that metadata directly from frontend definitions.
- [ ] The initialize payload exposes the metadata mechanically to the extension.
- [ ] Tests lock the transport layer against semantic normalization drift.
## Dependencies
- `DEC-0034` accepted and normatively locked.
- `PLN-0072` completes the compiler/frontend projection contract.
- `DEC-0033` transport conventions remain in force for visual theme payloads.
## Risks
- Reusing visual theme payload structures carelessly could blur the boundary between visual and semantic contracts.
- Flattening transport too aggressively could erase canonical frontend key identity.
- Excessive protocol specialization could make future hosts harder to add.

View File

@ -1,109 +0,0 @@
---
id: PLN-0074
ticket: frontend-semantic-host-projection-flexibility
title: VS Code Semantic Host Projection Adapter
status: done
created: 2026-05-06
completed: 2026-05-06
tags: [vscode, extension, frontend, semantics, host-projection, adapter]
---
## Objective
Make the VS Code extension consume frontend-authored semantic host projection metadata mechanically so semantic highlighting behavior no longer depends on extension-owned assumptions about frontend semantic key names.
## Background
`DEC-0034` makes the frontend semantic vocabulary canonical and requires VS Code adaptation to follow frontend-authored projection metadata rather than an extension-owned taxonomy. `DEC-0033` already moved visual theme ownership into frontend-authored runtime payloads; the semantic adapter must now follow the same model.
The current extension still contains assumptions about semantic token naming and package-level declarations that do not fully reflect frontend-authored projection data.
## Scope
### Included
- Consume semantic host projection payload from the LSP handshake.
- Translate frontend-authored VS Code projection descriptors into the extension's semantic token registration and runtime theme application flow.
- Reduce extension-owned semantic assumptions to the minimum static structure the VS Code platform requires.
- Add tests or verification hooks that prove the adapter follows frontend-authored projection data mechanically.
### Excluded
- Inventing or redefining canonical semantic meaning inside the extension.
- Reworking compiler semantic classification beyond consuming the delivered keys and projections.
- Solving projection for non-VS Code hosts.
## Non-Goals
- Making the extension the owner of semantic taxonomy policy.
- Hardcoding PBS-specific semantic mapping logic as the authoritative source.
- Guaranteeing a perfect one-to-one rendering match with Studio for every frontend key.
## Execution Steps
### Step 1 - Update extension-side semantic projection models
**What:** Add extension-side runtime shapes for the transported semantic projection payload.
**How:** Extend the VS Code extension client code so it can read and store:
1. canonical frontend semantic keys,
2. VS Code projection entries per key,
3. fallback metadata if present,
4. any language-scoped identity needed to apply the projection safely.
These runtime shapes MUST reflect transported frontend-authored metadata rather than a hand-maintained extension mapping table.
**File(s):** `tools/vscode-extension/src/**`, generated `out/**` mirror as needed.
### Step 2 - Apply projection mechanically in the semantic adapter path
**What:** Make the extension derive VS Code-facing semantic behavior from the transported projection.
**How:** Update extension logic so semantic token registration, selectors, and any runtime semantic color rule generation consume the frontend-authored projection entries. The adapter MUST treat missing projection data as a fallback condition, not as permission to reauthor semantic meaning broadly in extension code.
**File(s):** `tools/vscode-extension/src/extension.ts`, related extension helper modules if introduced, generated `out/**` mirror as needed.
### Step 3 - Minimize static package-level semantic assumptions
**What:** Reduce static `package.json` semantic declarations to the minimum platform-required scaffolding.
**How:** Audit the extension manifest and runtime so static declarations remain only where VS Code requires them structurally. Any semantic mapping policy that can be expressed by frontend-authored projection data MUST move out of the manifest and into runtime translation logic.
**File(s):** `tools/vscode-extension/package.json`, `tools/vscode-extension/src/**`.
### Step 4 - Lock adapter behavior with tests and verification
**What:** Prevent regression toward extension-owned semantic policy.
**How:** Add tests or targeted verification code that assert:
1. the adapter reads frontend-authored projection payloads,
2. semantic rules derive from projection data rather than hardcoded PBS assumptions,
3. fallback paths stay bounded and explicit,
4. frontend projection updates do not require extension semantic remapping edits for ordinary token adjustments.
**File(s):** extension test surfaces if present, otherwise targeted runtime assertions and documented manual verification paths.
## Test Requirements
### Unit Tests
- Validate parsing of semantic projection payloads from the initialize response.
- Validate transformation from projection entries into VS Code semantic token rule inputs.
### Integration Tests
- If extension test infrastructure exists, verify that a mock initialize payload drives semantic adapter behavior without code-level remapping tables.
### Manual Verification
- Reload the extension and inspect runtime behavior with a PBS project to confirm semantic highlighting is driven by transported projection data.
- Confirm that a frontend-authored projection change would only require frontend/LSP updates, not new semantic mapping logic in the extension.
## Acceptance Criteria
- [ ] The extension consumes canonical semantic keys and VS Code projection metadata from the LSP handshake.
- [ ] Semantic adapter behavior derives mechanically from transported projection data.
- [ ] Static extension manifest assumptions are reduced to platform-required scaffolding.
- [ ] The extension no longer acts as the authoritative source of frontend semantic mapping policy.
## Dependencies
- `DEC-0034` accepted and normatively locked.
- `PLN-0073` completes LSP transport of semantic host projection metadata.
- `DEC-0033` dynamic visual theme translation remains in place and coherent with semantic adaptation.
## Risks
- VS Code manifest constraints may still require some static declarations, and those boundaries must stay explicit.
- Weak fallback rules could accidentally recreate extension-owned semantic policy.
- Failure to update generated extension output alongside source would leave the runtime out of sync in the current local environment.

View File

@ -0,0 +1,135 @@
---
id: PLN-0075
ticket: pbs-lsp-editor-assistance-wave-1
title: PBS Editorial Resolution Surface for Symbols, Members, and Signatures
status: open
created: 2026-05-08
completed:
tags: [compiler, compiler-pbs, editor, completion, hover, signature-help, semantics]
---
## Objective
Introduce a compiler-backed editorial resolution surface in `compiler/pbs` that can answer symbol identity, kind, origin, signature/shape, callable details, and receiver members for use by LSP `completion`, `hover`, and `signature help`.
## Background
`DEC-0035` requires all three editor-assistance features to be built over one shared compiler-backed base. The current repository already has useful pieces:
- parser and AST for PBS;
- semantic validation and flow analysis;
- stdlib and import visibility rules;
- semantic token classification;
- builder-pipeline overlay analysis.
What is still missing is an explicit editorial surface designed for interactive symbol resolution instead of only diagnostics or coloring.
## Scope
### Included
- Define internal compiler-side models for editorial symbol resolution.
- Resolve local names, imported/public symbols, and recognized member surfaces.
- Resolve callable signatures for functions, methods, and constructors.
- Provide optional documentation slot(s) in the model without defining authored PBS documentation syntax.
- Add PBS-focused tests for symbol/member/signature resolution.
### Excluded
- LSP protocol capability changes.
- VS Code client behavior.
- Authored documentation syntax such as `Document(...)`.
- `go to definition`, `references`, `rename`, formatter, or code actions.
## Non-Goals
- Rebuilding the full compiler around IDE concerns.
- Solving every ambiguous or partial parse state in wave 1.
- Designing a generic multi-language IDE framework before PBS proves the model.
## Execution Steps
### Step 1 - Define editorial resolution models in compiler-owned surfaces
**What:** Introduce explicit models for resolved symbols, member candidates, callable signatures, and optional documentation payload.
**How:** Add compiler-owned DTO/model types that can express:
1. symbol identity and kind;
2. declared/imported origin;
3. callable label/signature shape;
4. receiver member entries;
5. optional documentation text field.
The model must be expressive enough for `completion`, `hover`, and `signature help` without forcing each consumer to reinterpret raw AST nodes.
**File(s):** `prometeu-compiler/prometeu-compiler-core/src/main/java/**` and/or `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/**` depending on final ownership split.
### Step 2 - Build PBS symbol resolution for local and imported surfaces
**What:** Resolve names in editorial contexts.
**How:** Reuse parser, name/linking, stdlib import knowledge, and any existing semantic tables to resolve:
1. local bindings in scope;
2. declared top-level PBS symbols;
3. imported/public symbols and aliases;
4. stdlib-owned surfaces currently recognized by the frontend.
The implementation must avoid duplicating semantic truth already present in compiler/linking logic.
**File(s):** `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/**`.
### Step 3 - Build member and callable resolution
**What:** Resolve members and callable signatures for recognized receiver and call surfaces.
**How:** Support at minimum:
1. member lookup after `.` for services, hosts, builtin types, and structs;
2. direct callable lookup for functions and constructors;
3. active-call signature resolution for later `signature help` use.
This step must produce stable labels/details that can be reused unchanged by LSP features.
**File(s):** `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/**`.
### Step 4 - Add editorial conformance tests
**What:** Lock the compiler-backed editorial contract before LSP integration.
**How:** Add tests for:
1. local variable and parameter resolution;
2. imported service/host/builtin-type resolution;
3. member lookup after `.` on recognized surfaces;
4. callable signature extraction for function/method/constructor cases;
5. optional documentation field stability when absent.
**File(s):** PBS/compiler test suites under `prometeu-compiler/**/src/test/java/**`.
## Test Requirements
### Unit Tests
- Model invariants for symbol/member/signature payloads.
- Resolver tests covering locals, imports, aliases, members, and constructors.
### Integration Tests
- Compiler-backed overlay/editorial tests using representative PBS snippets and stdlib imports.
### Manual Verification
- Inspect resolved payloads in tests or debug output and confirm they are sufficient to drive all three editor features without ad hoc reinterpretation.
## Acceptance Criteria
- [ ] Compiler-side editorial models exist for symbols, members, signatures, and optional documentation.
- [ ] PBS can resolve local names, imported/public symbols, and recognized member surfaces.
- [ ] Function, method, and constructor signatures are available through the shared editorial surface.
- [ ] No consumer is required to reconstruct signature/member meaning from raw AST-only data.
## Dependencies
- `DEC-0035` accepted and normatively locked.
- Existing PBS semantic and import/linking infrastructure remains the truth source.
## Risks
- Overfitting the first resolver to the current stdlib shape may hurt future fronts or future PBS growth.
- Mixing diagnostics-only semantics with editorial semantics carelessly may produce partial or contradictory answers.
- Incomplete member resolution can make `completion` appear flaky even if `hover` works.

View File

@ -0,0 +1,121 @@
---
id: PLN-0076
ticket: pbs-lsp-editor-assistance-wave-1
title: LSP Completion, Hover, and Signature Help over Editorial Resolution
status: open
created: 2026-05-08
completed:
tags: [studio, lsp, protocol, completion, hover, signature-help, editor]
---
## Objective
Expose `completion`, real `hover`, and `signature help` through the project-scoped LSP stack by projecting the compiler-backed editorial resolution surface into explicit protocol capabilities and request handlers.
## Background
`DEC-0035` requires `studio/lsp` to be the operational owner of these editor features while remaining faithful to compiler-backed symbol, member, and signature resolution. The current LSP path only handles diagnostics, semantic tokens, and a placeholder hover.
## Scope
### Included
- Extend the internal bridge/API with completion and signature-help operations.
- Replace placeholder hover with symbol-resolved hover.
- Announce LSP capabilities for completion and signature help.
- Add message models/mappers/tests for the new request/response paths.
### Excluded
- Creation of the underlying compiler editorial model itself.
- Authored documentation syntax.
- VS Code-specific UI behavior beyond normal LSP consumption.
## Non-Goals
- `go to definition`, `references`, `rename`, formatter, code actions, or quick fixes.
- Rich workspace-wide indexing beyond what the shared editorial surface already provides.
## Execution Steps
### Step 1 - Extend the LSP bridge contract
**What:** Add compiler-backed editor-assistance operations to the bridge.
**How:** Evolve `LanguageServiceBridge` and related internal messages to support at minimum:
1. completion requests;
2. symbol-resolved hover payloads;
3. signature-help requests.
The bridge contract must align structurally with the shared editorial resolution surface rather than inventing a second feature-specific abstraction.
**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/**`, `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/messages/**`.
### Step 2 - Implement compiler-backed request handling
**What:** Wire LSP requests to compiler-backed editorial resolution.
**How:** Update `CompilerLanguageServiceBridge` so it:
1. resolves completion candidates from local/import/member contexts;
2. resolves hover payloads from symbol identity, origin, and signatures;
3. resolves active call signatures for `signature help`.
This step must remove the current fixed hover placeholder.
**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/compiler/**`.
### Step 3 - Announce and map protocol capabilities
**What:** Make the server advertise the new feature set and map payloads into lsp4j types.
**How:** Update protocol mappers and text-document service so the server announces:
1. `completionProvider`;
2. `signatureHelpProvider`;
3. improved `hoverProvider` backed by real payloads.
Map completion items, hover markdown, and signature-help structures into concrete LSP responses.
**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/main/java/p/studio/lsp/services/protocol/**`, `.../mapping/**`.
### Step 4 - Add transport and conformance tests
**What:** Prevent regression to placeholder/editor-local behavior.
**How:** Add tests that verify:
1. capabilities are announced correctly;
2. completion returns compiler-backed candidates;
3. hover no longer returns the baseline placeholder;
4. signature-help returns deterministic active-signature information.
**File(s):** `prometeu-lsp/prometeu-lsp-v1/src/test/java/**`.
## Test Requirements
### Unit Tests
- DTO/model invariants for completion, hover, and signature-help payloads.
- Mapper tests for lsp4j conversion.
### Integration Tests
- LSP request/response tests using realistic PBS snippets with locals, imports, and member access.
### Manual Verification
- Connect the VS Code extension and confirm server capabilities include completion and signature help.
- Confirm hover content changes with the hovered symbol rather than returning static baseline text.
## Acceptance Criteria
- [ ] The LSP bridge exposes completion and signature-help operations in addition to diagnostics, hover, and semantic tokens.
- [ ] Hover is symbol-resolved and no longer hardcoded placeholder text.
- [ ] The server advertises completion and signature-help capabilities.
- [ ] Completion, hover, and signature help all derive from the same compiler-backed editorial surface.
## Dependencies
- `DEC-0035` accepted and normatively locked.
- `PLN-0075` for the shared compiler-backed editorial resolution surface.
## Risks
- Protocol mapping can drift from compiler payload shape if feature-specific shortcuts are added.
- Active parameter/signature calculation may be brittle around incomplete syntax unless request handling is conservative.
- Completion can feel noisy if candidate ranking or filtering is too weak in wave 1.

View File

@ -0,0 +1,103 @@
---
id: PLN-0077
ticket: pbs-lsp-editor-assistance-wave-1
title: VS Code Consumption and Wave 1 Editor Assistance Validation
status: open
created: 2026-05-08
completed:
tags: [vscode, extension, editor, completion, hover, signature-help, validation]
---
## Objective
Keep the VS Code extension thin while validating that the new LSP-delivered `completion`, `hover`, and `signature help` features actually produce a minimally usable PBS editing experience end to end.
## Background
`DEC-0035` explicitly requires the extension to remain a client/adaptor rather than a second semantic engine. Because VS Code already knows how to consume LSP completion, hover, and signature-help responses, the extension work should be small and mostly about ensuring transport, configuration, and real validation are correct.
## Scope
### Included
- Confirm the extension does not need or gain local semantic tables for stdlib, members, or signatures.
- Adjust only the minimal extension/bootstrap behavior needed for the new LSP features to flow correctly.
- Add verification coverage and manual validation guidance for the full wave.
### Excluded
- Compiler-side editorial resolution logic.
- LSP-side protocol feature implementation.
- Formatter/indentation, code actions, or non-wave-1 IDE features.
## Non-Goals
- Turning the extension into a feature-rich semantic client.
- Adding hardcoded completion/signature content for PBS inside TypeScript runtime code.
## Execution Steps
### Step 1 - Verify thin-client integration boundaries
**What:** Confirm the extension remains a pure LSP consumer for the new features.
**How:** Review and adjust the extension only where necessary so completion, hover, and signature help are obtained from the LSP session without client-side semantic fallback tables.
**File(s):** `tools/vscode-extension/src/**`, `tools/vscode-extension/package.json`.
### Step 2 - Add any minimal structural configuration required by VS Code
**What:** Keep static contribution surfaces minimal and structural.
**How:** If VS Code requires additional structural contribution metadata for the new features, add only that metadata. Do not add curated PBS semantic or signature data into the extension package.
**File(s):** `tools/vscode-extension/package.json`.
### Step 3 - Add validation coverage for end-to-end editor assistance
**What:** Lock the no-local-semantics rule and the end-to-end feature expectations.
**How:** Add tests or deterministic verification steps that ensure:
1. the extension connects and receives the feature set from the server;
2. no local completion/signature tables were introduced;
3. the user-facing wave can be exercised end to end.
**File(s):** `tools/vscode-extension/**`, existing validation harnesses if present, and related docs/test notes.
### Step 4 - Define manual smoke scenarios for wave 1 usability
**What:** Make the wave verifiable as a product experience rather than only a protocol exercise.
**How:** Document and run manual checks for:
1. keyword and local-name completion;
2. imported stdlib/member completion after `.`;
3. hover on locals, imported services, builtin types, and methods;
4. signature help during function/method/constructor calls.
**File(s):** extension verification notes or adjacent implementation docs/tests as appropriate.
## Test Requirements
### Unit Tests
- Any extension-side helpers introduced for structural integration only.
### Integration Tests
- End-to-end or near-end-to-end validation that VS Code consumes the server feature set without local semantic duplication.
### Manual Verification
- Open representative PBS files in VS Code and verify `completion`, `hover`, and `signature help` behavior matches the expected wave-1 scope.
## Acceptance Criteria
- [ ] The extension remains thin and contains no new hardcoded PBS semantic tables for members or signatures.
- [ ] VS Code can consume the new LSP completion, hover, and signature-help responses without extension-side semantic authorship.
- [ ] Wave-1 smoke scenarios are documented and manually verifiable.
## Dependencies
- `DEC-0035` accepted and normatively locked.
- `PLN-0076` for the actual LSP feature delivery.
## Risks
- It is easy to accidentally patch around server gaps with client-local logic; this plan must resist that.
- Validation can become too protocol-centric and miss real usability failures if manual smoke scenarios are weak.

View File

@ -17,5 +17,6 @@ public class PBSDefinitions {
List.of(PBSFrontendThemes.DEFAULT_PBS),
"pbs-default",
List.of(PBSFrontendHostProjections.VSCODE)))
.semanticTokenProvider(new PBSSemanticTokenProvider())
.build();
}

View File

@ -39,6 +39,7 @@ public final class PBSFrontendHostProjections {
case HOST -> projection(HOST.semanticKey(), "class", "type", "defaultLibrary");
case BUILTIN_TYPE -> projection(BUILTIN_TYPE.semanticKey(), "type", "variable", "defaultLibrary");
case SERVICE -> projection(SERVICE.semanticKey(), "class", "type", "defaultLibrary");
case ASSET -> projection(ASSET.semanticKey(), "variable", "string", "readonly");
case ERROR -> projection(ERROR.semanticKey(), "enum", "type");
case ENUM -> projection(ENUM.semanticKey(), "enum", "type");
case CALLBACK -> projection(CALLBACK.semanticKey(), "interface", "type");

View File

@ -20,21 +20,22 @@ public class PBSFrontendThemes {
"#f5efff"),
List.of(
new FrontendTokenStyleSpec("pbs-comment", "#8b949e", true, false, false),
new FrontendTokenStyleSpec("pbs-string", "#7ee787", false, false, false),
new FrontendTokenStyleSpec("pbs-number", "#ffa657", false, false, false),
new FrontendTokenStyleSpec("pbs-literal", "#79c0ff", false, false, false),
new FrontendTokenStyleSpec("pbs-string", "#d8b86a", false, false, false),
new FrontendTokenStyleSpec("pbs-number", "#ff8cc6", false, false, false),
new FrontendTokenStyleSpec("pbs-literal", "#7fb8ff", false, false, false),
new FrontendTokenStyleSpec("pbs-lifecycle", "#ff7b72", false, true, false),
new FrontendTokenStyleSpec("pbs-keyword", "#d2a8ff", false, false, false),
new FrontendTokenStyleSpec("pbs-keyword", "#7fb8ff", false, false, false),
new FrontendTokenStyleSpec("pbs-operator", "#c9d1d9", false, false, false),
new FrontendTokenStyleSpec("pbs-punctuation", "#8b949e", false, false, false),
new FrontendTokenStyleSpec("pbs-function", "#ffa657", false, true, false),
new FrontendTokenStyleSpec("pbs-method", "#ffd580", false, false, false),
new FrontendTokenStyleSpec("pbs-constructor", "#e3b341", false, true, false),
new FrontendTokenStyleSpec("pbs-struct", "#56d4dd", false, false, false),
new FrontendTokenStyleSpec("pbs-function", "#7ee787", false, true, false),
new FrontendTokenStyleSpec("pbs-method", "#7ee787", false, false, false),
new FrontendTokenStyleSpec("pbs-constructor", "#7ee787", false, true, false),
new FrontendTokenStyleSpec("pbs-struct", "#56d4dd", true, false, false),
new FrontendTokenStyleSpec("pbs-contract", "#79c0ff", false, false, true),
new FrontendTokenStyleSpec("pbs-host", "#c297ff", false, false, false),
new FrontendTokenStyleSpec("pbs-builtin-type", "#7ee787", true, false, false),
new FrontendTokenStyleSpec("pbs-service", "#c297ff", false, true, false),
new FrontendTokenStyleSpec("pbs-builtin-type", "#56d4dd", false, false, false),
new FrontendTokenStyleSpec("pbs-service", "#ff8e7a", false, true, false),
new FrontendTokenStyleSpec("pbs-asset", "#c297ff", false, false, false),
new FrontendTokenStyleSpec("pbs-error", "#ff7b72", false, false, true),
new FrontendTokenStyleSpec("pbs-enum", "#56d4dd", false, true, false),
new FrontendTokenStyleSpec("pbs-callback", "#ffb3e6", false, false, false),

View File

@ -0,0 +1,365 @@
package p.studio.compiler;
import p.studio.compiler.models.FrontendSemanticToken;
import p.studio.compiler.models.FrontendSemanticTokenProvider;
import p.studio.compiler.pbs.ast.PbsAst;
import p.studio.compiler.pbs.PbsSemanticKind;
import p.studio.compiler.pbs.lexer.PbsLexer;
import p.studio.compiler.pbs.lexer.PbsToken;
import p.studio.compiler.pbs.lexer.PbsTokenKind;
import p.studio.compiler.pbs.parser.PbsBarrelParser;
import p.studio.compiler.pbs.parser.PbsParser;
import p.studio.compiler.pbs.stdlib.ResourceStdlibEnvironmentResolver;
import p.studio.compiler.pbs.stdlib.StdlibModuleSource;
import p.studio.compiler.source.diagnostics.DiagnosticSink;
import p.studio.compiler.source.identifiers.FileId;
import p.studio.utilities.structures.ReadOnlyList;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public final class PBSSemanticTokenProvider implements FrontendSemanticTokenProvider {
private static final Set<String> BUILTIN_TYPE_NAMES = Set.of("int", "float", "bool", "string", "i32", "i64", "f32", "f64");
private static final int DEFAULT_STDLIB_VERSION = 1;
private static final ResourceStdlibEnvironmentResolver STDLIB_RESOLVER = new ResourceStdlibEnvironmentResolver();
private static final Map<PbsTokenKind, PbsSemanticKind> DECLARATION_KINDS = declarationKinds();
@Override
public List<FrontendSemanticToken> tokenize(final String documentText) {
final String effectiveText = documentText == null ? "" : documentText;
final ReadOnlyList<PbsToken> tokens = PbsLexer.lex(effectiveText, FileId.none(), DiagnosticSink.empty());
final Map<String, PbsSemanticKind> declaredKindsByName = collectDeclaredKinds(tokens);
final Set<Integer> assetReferenceTokenIndexes = collectAssetReferenceTokenIndexes(tokens);
final ArrayList<FrontendSemanticToken> semanticTokens = new ArrayList<>();
for (int index = 0; index < tokens.size(); index += 1) {
final PbsToken token = tokens.get(index);
final PbsSemanticKind semanticKind = classifyToken(tokens, index, declaredKindsByName, assetReferenceTokenIndexes);
if (semanticKind == null) {
continue;
}
semanticTokens.add(new FrontendSemanticToken(token.start(), token.end(), semanticKind.semanticKey()));
}
return List.copyOf(semanticTokens);
}
private PbsSemanticKind classifyToken(
final ReadOnlyList<PbsToken> tokens,
final int index,
final Map<String, PbsSemanticKind> declaredKindsByName,
final Set<Integer> assetReferenceTokenIndexes) {
final PbsToken token = tokens.get(index);
final PbsSemanticKind lexicalKind = PbsSemanticKind.forToken(token);
if (lexicalKind != null) {
return lexicalKind;
}
if (token.kind() == PbsTokenKind.IDENTIFIER) {
if (assetReferenceTokenIndexes.contains(index)) {
return PbsSemanticKind.ASSET;
}
if (isLifecycleToken(tokens, index, token)) {
return PbsSemanticKind.LIFECYCLE;
}
return classifyIdentifierToken(tokens, index, token, declaredKindsByName);
}
return null;
}
private PbsSemanticKind classifyIdentifierToken(
final ReadOnlyList<PbsToken> tokens,
final int index,
final PbsToken token,
final Map<String, PbsSemanticKind> declaredKindsByName) {
final PbsTokenKind previousKind = previousSignificantKind(tokens, index);
final PbsTokenKind nextKind = nextSignificantKind(tokens, index);
final boolean typeReferenceContext = isTypeReferenceContext(previousKind);
if (previousKind == PbsTokenKind.STRUCT) {
return PbsSemanticKind.STRUCT;
}
if (previousKind == PbsTokenKind.CONTRACT) {
return PbsSemanticKind.CONTRACT;
}
if (previousKind == PbsTokenKind.HOST) {
return PbsSemanticKind.HOST;
}
if (previousKind == PbsTokenKind.SERVICE) {
return PbsSemanticKind.SERVICE;
}
if (previousKind == PbsTokenKind.ENUM || previousKind == PbsTokenKind.ERROR) {
return PbsSemanticKind.ENUM;
}
if (previousKind == PbsTokenKind.CALLBACK) {
return PbsSemanticKind.CALLBACK;
}
if (previousKind == PbsTokenKind.GLOBAL) {
return PbsSemanticKind.GLOBAL;
}
if (previousKind == PbsTokenKind.CONST) {
return PbsSemanticKind.CONST;
}
if (previousKind == PbsTokenKind.CTOR || previousKind == PbsTokenKind.NEW) {
return PbsSemanticKind.CONSTRUCTOR;
}
if (previousKind == PbsTokenKind.BUILTIN) {
return PbsSemanticKind.BUILTIN_TYPE;
}
final PbsSemanticKind declaredKind = declaredKindsByName.get(token.lexeme());
if (declaredKind != null) {
if (previousKind == PbsTokenKind.DOT && nextKind == PbsTokenKind.LEFT_PAREN) {
return PbsSemanticKind.METHOD;
}
if (nextKind == PbsTokenKind.DOT
|| previousKind == PbsTokenKind.NEW
|| typeReferenceContext) {
return declaredKind;
}
}
if (previousKind == PbsTokenKind.DOT && nextKind == PbsTokenKind.LEFT_PAREN) {
return PbsSemanticKind.METHOD;
}
if (nextKind == PbsTokenKind.LEFT_PAREN) {
return PbsSemanticKind.FUNCTION;
}
if (typeReferenceContext && BUILTIN_TYPE_NAMES.contains(token.lexeme())) {
return PbsSemanticKind.BUILTIN_TYPE;
}
return PbsSemanticKind.IDENTIFIER;
}
private Map<String, PbsSemanticKind> collectDeclaredKinds(final ReadOnlyList<PbsToken> tokens) {
final Map<String, PbsSemanticKind> declaredKindsByName = new HashMap<>();
for (int index = 0; index < tokens.size() - 1; index += 1) {
final PbsToken token = tokens.get(index);
final PbsToken nextToken = tokens.get(index + 1);
if (nextToken.kind() != PbsTokenKind.IDENTIFIER) {
continue;
}
final PbsSemanticKind declarationKind = declarationKind(token.kind());
if (declarationKind == null) {
continue;
}
declaredKindsByName.put(nextToken.lexeme(), declarationKind);
}
declaredKindsByName.putAll(collectStdlibImportedKinds(tokens));
return Map.copyOf(declaredKindsByName);
}
private Set<Integer> collectAssetReferenceTokenIndexes(final ReadOnlyList<PbsToken> tokens) {
final Set<Integer> indexes = new HashSet<>();
for (int index = 0; index < tokens.size(); index += 1) {
final PbsToken token = tokens.get(index);
if (token.kind() != PbsTokenKind.IDENTIFIER || !"assets".equals(token.lexeme())) {
continue;
}
final Integer firstDotIndex = nextSignificantIndex(tokens, index);
if (firstDotIndex == null || tokens.get(firstDotIndex).kind() != PbsTokenKind.DOT) {
continue;
}
indexes.add(index);
Integer cursor = firstDotIndex;
while (cursor != null && tokens.get(cursor).kind() == PbsTokenKind.DOT) {
final Integer memberIndex = nextSignificantIndex(tokens, cursor);
if (memberIndex == null || tokens.get(memberIndex).kind() != PbsTokenKind.IDENTIFIER) {
break;
}
indexes.add(memberIndex);
cursor = nextSignificantIndex(tokens, memberIndex);
}
}
return Set.copyOf(indexes);
}
private PbsSemanticKind declarationKind(final PbsTokenKind kind) {
return DECLARATION_KINDS.get(kind);
}
private Map<String, PbsSemanticKind> collectStdlibImportedKinds(final ReadOnlyList<PbsToken> tokens) {
final DiagnosticSink diagnostics = DiagnosticSink.empty();
final PbsAst.File file = PbsParser.parse(tokens, FileId.none(), diagnostics);
final Map<String, PbsSemanticKind> importedKindsByLocalName = new HashMap<>();
for (final PbsAst.ImportDecl importDecl : file.imports()) {
if (importDecl.items().isEmpty()) {
continue;
}
final Map<String, PbsSemanticKind> exportedKinds = resolveStdlibExportKinds(importDecl.moduleRef());
if (exportedKinds.isEmpty()) {
continue;
}
for (final Map.Entry<String, PbsSemanticKind> entry : exportedKinds.entrySet()) {
if (entry.getValue() == PbsSemanticKind.BUILTIN_TYPE) {
importedKindsByLocalName.put(entry.getKey(), entry.getValue());
}
}
for (final PbsAst.ImportItem item : importDecl.items()) {
final PbsSemanticKind semanticKind = exportedKinds.get(item.name());
if (semanticKind == null) {
continue;
}
importedKindsByLocalName.put(item.alias() == null ? item.name() : item.alias(), semanticKind);
}
}
return importedKindsByLocalName;
}
private Map<String, PbsSemanticKind> resolveStdlibExportKinds(final PbsAst.ModuleRef moduleRef) {
final var stdlibEnvironment = STDLIB_RESOLVER.resolve(DEFAULT_STDLIB_VERSION);
return stdlibEnvironment.resolveModule(moduleRef.project(), moduleRef.pathSegments())
.map(this::parseStdlibVisibleKinds)
.orElseGet(Map::of);
}
private Map<String, PbsSemanticKind> parseStdlibVisibleKinds(final StdlibModuleSource moduleSource) {
final Map<String, PbsSemanticKind> visibleKinds = new HashMap<>(parseBarrelExportKinds(moduleSource.barrelSource()));
for (final StdlibModuleSource.SourceFile sourceFile : moduleSource.sourceFiles()) {
visibleKinds.putAll(parseBuiltinTypeKinds(sourceFile.source()));
}
return visibleKinds;
}
private Map<String, PbsSemanticKind> parseBarrelExportKinds(final String barrelSource) {
final ReadOnlyList<PbsToken> barrelTokens = PbsLexer.lex(barrelSource, FileId.none(), DiagnosticSink.empty());
final PbsAst.BarrelFile barrelFile = PbsBarrelParser.parse(barrelTokens, FileId.none(), DiagnosticSink.empty());
final Map<String, PbsSemanticKind> exportedKinds = new HashMap<>();
for (final PbsAst.BarrelItem item : barrelFile.items()) {
final PbsSemanticKind semanticKind = semanticKindForBarrelItem(item);
if (semanticKind == null) {
continue;
}
if (item instanceof PbsAst.BarrelStructItem structItem && structItem.visibility() == PbsAst.Visibility.PUB) {
exportedKinds.put(structItem.name(), semanticKind);
} else if (item instanceof PbsAst.BarrelContractItem contractItem && contractItem.visibility() == PbsAst.Visibility.PUB) {
exportedKinds.put(contractItem.name(), semanticKind);
} else if (item instanceof PbsAst.BarrelHostItem hostItem && hostItem.visibility() == PbsAst.Visibility.PUB) {
exportedKinds.put(hostItem.name(), semanticKind);
} else if (item instanceof PbsAst.BarrelErrorItem errorItem && errorItem.visibility() == PbsAst.Visibility.PUB) {
exportedKinds.put(errorItem.name(), semanticKind);
} else if (item instanceof PbsAst.BarrelEnumItem enumItem && enumItem.visibility() == PbsAst.Visibility.PUB) {
exportedKinds.put(enumItem.name(), semanticKind);
} else if (item instanceof PbsAst.BarrelServiceItem serviceItem && serviceItem.visibility() == PbsAst.Visibility.PUB) {
exportedKinds.put(serviceItem.name(), semanticKind);
} else if (item instanceof PbsAst.BarrelGlobalItem globalItem && globalItem.visibility() == PbsAst.Visibility.PUB) {
exportedKinds.put(globalItem.name(), semanticKind);
} else if (item instanceof PbsAst.BarrelConstItem constItem && constItem.visibility() == PbsAst.Visibility.PUB) {
exportedKinds.put(constItem.name(), semanticKind);
} else if (item instanceof PbsAst.BarrelCallbackItem callbackItem && callbackItem.visibility() == PbsAst.Visibility.PUB) {
exportedKinds.put(callbackItem.name(), semanticKind);
}
}
return exportedKinds;
}
private Map<String, PbsSemanticKind> parseBuiltinTypeKinds(final String source) {
final ReadOnlyList<PbsToken> sourceTokens = PbsLexer.lex(source, FileId.none(), DiagnosticSink.empty());
final PbsAst.File file = PbsParser.parse(
sourceTokens,
FileId.none(),
DiagnosticSink.empty(),
PbsParser.ParseMode.INTERFACE_MODULE);
final Map<String, PbsSemanticKind> builtinKinds = new HashMap<>();
for (final PbsAst.TopDecl topDecl : file.topDecls()) {
if (topDecl instanceof PbsAst.BuiltinTypeDecl builtinTypeDecl) {
builtinKinds.put(builtinTypeDecl.name(), PbsSemanticKind.BUILTIN_TYPE);
}
}
return builtinKinds;
}
private PbsSemanticKind semanticKindForBarrelItem(final PbsAst.BarrelItem item) {
return switch (item) {
case PbsAst.BarrelStructItem ignored -> PbsSemanticKind.STRUCT;
case PbsAst.BarrelContractItem ignored -> PbsSemanticKind.CONTRACT;
case PbsAst.BarrelHostItem ignored -> PbsSemanticKind.HOST;
case PbsAst.BarrelErrorItem ignored -> PbsSemanticKind.ENUM;
case PbsAst.BarrelEnumItem ignored -> PbsSemanticKind.ENUM;
case PbsAst.BarrelServiceItem ignored -> PbsSemanticKind.SERVICE;
case PbsAst.BarrelGlobalItem ignored -> PbsSemanticKind.GLOBAL;
case PbsAst.BarrelConstItem ignored -> PbsSemanticKind.CONST;
case PbsAst.BarrelCallbackItem ignored -> PbsSemanticKind.CALLBACK;
case PbsAst.BarrelFunctionItem ignored -> null;
};
}
private static Map<PbsTokenKind, PbsSemanticKind> declarationKinds() {
final Map<PbsTokenKind, PbsSemanticKind> kinds = new EnumMap<>(PbsTokenKind.class);
kinds.put(PbsTokenKind.STRUCT, PbsSemanticKind.STRUCT);
kinds.put(PbsTokenKind.CONTRACT, PbsSemanticKind.CONTRACT);
kinds.put(PbsTokenKind.HOST, PbsSemanticKind.HOST);
kinds.put(PbsTokenKind.SERVICE, PbsSemanticKind.SERVICE);
kinds.put(PbsTokenKind.ENUM, PbsSemanticKind.ENUM);
kinds.put(PbsTokenKind.ERROR, PbsSemanticKind.ENUM);
kinds.put(PbsTokenKind.CALLBACK, PbsSemanticKind.CALLBACK);
kinds.put(PbsTokenKind.GLOBAL, PbsSemanticKind.GLOBAL);
kinds.put(PbsTokenKind.CONST, PbsSemanticKind.CONST);
kinds.put(PbsTokenKind.CTOR, PbsSemanticKind.CONSTRUCTOR);
kinds.put(PbsTokenKind.BUILTIN, PbsSemanticKind.BUILTIN_TYPE);
return Map.copyOf(kinds);
}
private boolean isTypeReferenceContext(final PbsTokenKind previousKind) {
if (previousKind == null) {
return false;
}
if (previousKind != PbsTokenKind.COLON
&& previousKind != PbsTokenKind.ARROW
&& previousKind != PbsTokenKind.AS
&& previousKind != PbsTokenKind.IMPLEMENTS) {
return false;
}
return true;
}
private PbsTokenKind previousSignificantKind(
final ReadOnlyList<PbsToken> tokens,
final int index) {
for (int cursor = index - 1; cursor >= 0; cursor -= 1) {
final PbsTokenKind kind = tokens.get(cursor).kind();
if (kind == PbsTokenKind.COMMENT || kind == PbsTokenKind.EOF) {
continue;
}
return kind;
}
return null;
}
private PbsTokenKind nextSignificantKind(
final ReadOnlyList<PbsToken> tokens,
final int index) {
final Integer cursor = nextSignificantIndex(tokens, index);
return cursor == null ? null : tokens.get(cursor).kind();
}
private Integer nextSignificantIndex(
final ReadOnlyList<PbsToken> tokens,
final int index) {
for (int cursor = index + 1; cursor < tokens.size(); cursor += 1) {
final PbsTokenKind kind = tokens.get(cursor).kind();
if (kind == PbsTokenKind.COMMENT || kind == PbsTokenKind.EOF) {
continue;
}
return cursor;
}
return null;
}
private boolean isLifecycleToken(
final ReadOnlyList<PbsToken> tokens,
final int index,
final PbsToken token) {
if (!"Init".equals(token.lexeme()) && !"Frame".equals(token.lexeme())) {
return false;
}
if (index == 0 || index + 1 >= tokens.size()) {
return false;
}
return tokens.get(index - 1).kind() == PbsTokenKind.LEFT_BRACKET
&& tokens.get(index + 1).kind() == PbsTokenKind.RIGHT_BRACKET;
}
}

View File

@ -22,6 +22,7 @@ public enum PbsSemanticKind {
HOST("pbs-host"),
BUILTIN_TYPE("pbs-builtin-type"),
SERVICE("pbs-service"),
ASSET("pbs-asset"),
ERROR("pbs-error"),
ENUM("pbs-enum"),
CALLBACK("pbs-callback"),

View File

@ -0,0 +1,30 @@
package p.studio.compiler.pbs.semantics;
import java.util.Objects;
public record PbsEditorialCompletionCandidate(
String label,
PbsEditorialSymbolKind kind,
String detail,
String origin) {
public PbsEditorialCompletionCandidate {
label = requireText(label, "label");
kind = Objects.requireNonNull(kind, "kind");
detail = normalize(detail);
origin = normalize(origin);
}
private static String requireText(
final String value,
final String field) {
final String candidate = normalize(value);
if (candidate.isEmpty()) {
throw new IllegalArgumentException(field + " must not be blank");
}
return candidate;
}
private static String normalize(final String value) {
return value == null ? "" : value.trim();
}
}

View File

@ -0,0 +1,35 @@
package p.studio.compiler.pbs.semantics;
import java.util.List;
import java.util.Objects;
public record PbsEditorialResolvedSymbol(
String displayName,
PbsEditorialSymbolKind kind,
String detail,
String origin,
List<PbsEditorialSignature> signatures,
String documentation) {
public PbsEditorialResolvedSymbol {
displayName = requireText(displayName, "displayName");
kind = Objects.requireNonNull(kind, "kind");
detail = normalize(detail);
origin = normalize(origin);
signatures = List.copyOf(Objects.requireNonNull(signatures, "signatures"));
documentation = normalize(documentation);
}
private static String requireText(
final String value,
final String field) {
final String candidate = normalize(value);
if (candidate.isEmpty()) {
throw new IllegalArgumentException(field + " must not be blank");
}
return candidate;
}
private static String normalize(final String value) {
return value == null ? "" : value.trim();
}
}

View File

@ -0,0 +1,27 @@
package p.studio.compiler.pbs.semantics;
import java.util.List;
import java.util.Objects;
public record PbsEditorialSignature(
String callableName,
String label,
List<String> parameterLabels,
String returnLabel) {
public PbsEditorialSignature {
callableName = requireText(callableName, "callableName");
label = requireText(label, "label");
parameterLabels = List.copyOf(Objects.requireNonNull(parameterLabels, "parameterLabels"));
returnLabel = requireText(returnLabel, "returnLabel");
}
private static String requireText(
final String value,
final String field) {
final String candidate = Objects.requireNonNull(value, field).trim();
if (candidate.isEmpty()) {
throw new IllegalArgumentException(field + " must not be blank");
}
return candidate;
}
}

View File

@ -0,0 +1,22 @@
package p.studio.compiler.pbs.semantics;
import java.util.List;
import java.util.Objects;
public record PbsEditorialSignatureHelp(
List<PbsEditorialSignature> signatures,
int activeSignature,
int activeParameter) {
public PbsEditorialSignatureHelp {
signatures = List.copyOf(Objects.requireNonNull(signatures, "signatures"));
if (signatures.isEmpty()) {
throw new IllegalArgumentException("signatures must not be empty");
}
if (activeSignature < 0 || activeSignature >= signatures.size()) {
throw new IllegalArgumentException("activeSignature must reference one of the provided signatures");
}
if (activeParameter < 0) {
throw new IllegalArgumentException("activeParameter must be >= 0");
}
}
}

View File

@ -0,0 +1,21 @@
package p.studio.compiler.pbs.semantics;
public enum PbsEditorialSymbolKind {
KEYWORD,
LOCAL,
PARAMETER,
FIELD,
FUNCTION,
METHOD,
CONSTRUCTOR,
STRUCT,
BUILTIN_TYPE,
SERVICE,
HOST,
CONTRACT,
CALLBACK,
ENUM,
ERROR,
GLOBAL,
CONST
}

View File

@ -584,5 +584,9 @@ final class PbsFlowSemanticSupport {
final var symbol = names.get(name);
return symbol != null && symbol.mutable();
}
Map<String, LocalSymbol> entries() {
return Map.copyOf(names);
}
}
}

View File

@ -133,12 +133,14 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
assembly.parsedSourceFiles(),
assembly.moduleTable());
final var flowSemanticsValidator = new PbsFlowSemanticsValidator();
final Map<FileId, p.studio.compiler.pbs.ast.PbsAst.File> astByFile = new LinkedHashMap<>();
final Map<FileId, ReadOnlyList<p.studio.compiler.pbs.ast.PbsAst.TopDecl>> supplementalTopDeclsByFile = new LinkedHashMap<>();
final Map<FileId, ReadOnlyList<PbsInlineHintSurface>> inlineHintsByFile = new LinkedHashMap<>();
for (final var entry : importedSemanticContexts.entrySet()) {
supplementalTopDeclsByFile.put(entry.getKey(), entry.getValue().supplementalTopDecls());
}
for (final var parsedSourceFile : assembly.parsedSourceFiles()) {
astByFile.put(parsedSourceFile.fileId(), parsedSourceFile.ast());
final var importedSemanticContext = importedSemanticContexts.getOrDefault(
parsedSourceFile.fileId(),
PbsImportedSemanticContext.empty());
@ -152,11 +154,13 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
}
}
return new PbsSemanticReadSurface(
Map.copyOf(astByFile),
Map.copyOf(supplementalTopDeclsByFile),
Map.copyOf(inlineHintsByFile));
}
public record PbsSemanticReadSurface(
Map<FileId, p.studio.compiler.pbs.ast.PbsAst.File> astByFile,
Map<FileId, ReadOnlyList<p.studio.compiler.pbs.ast.PbsAst.TopDecl>> supplementalTopDeclsByFile,
Map<FileId, ReadOnlyList<PbsInlineHintSurface>> inlineHintsByFile) {
}

View File

@ -1,111 +0,0 @@
.editor-workspace-code-area-type-pbs {
-fx-highlight-fill: #2d4f6b;
}
.editor-workspace-code-area-type-pbs .text {
-fx-fill: #d9e2ec;
}
.editor-workspace-code-area-type-pbs .lineno {
-fx-text-fill: #6f8193;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-keyword {
-fx-fill: #569cd6;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-lifecycle {
-fx-fill: #ef50c0;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-function {
-fx-fill: #f2c14e;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-method {
-fx-fill: #f2c14e;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-constructor {
-fx-fill: #ecdcaa;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-struct {
-fx-fill: #4ec9b0;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-contract {
-fx-fill: #78dce8;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-host {
-fx-fill: #b7a2fa;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-builtin-type {
-fx-fill: #8be9fd;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-service {
-fx-fill: #b7a2fa;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-error {
-fx-fill: #ff5b5b;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-enum {
-fx-fill: #56cfe1;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-callback {
-fx-fill: #b7a2fa;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-global {
-fx-fill: #f790fc;
-fx-font-style: italic;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-const {
-fx-fill: #f78c6c;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-implements {
-fx-fill: #a1c181;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-string {
-fx-fill: #00c088;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-number {
-fx-fill: #ff90b0;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-comment {
-fx-fill: #c090b0;
-fx-font-style: italic;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-literal {
-fx-fill: #4fc1ff;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-operator {
-fx-fill: #d4d4d4;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-punctuation {
-fx-fill: #d4d4d4;
}
.editor-workspace-code-area-type-pbs .text.editor-semantic-pbs-identifier {
-fx-fill: #d4d4d4;
}
.editor-workspace-status-chip-type-pbs {
-fx-background-color: #2c2140;
-fx-border-color: #a47dff;
-fx-text-fill: #efe6ff;
}

View File

@ -3,6 +3,9 @@ package p.studio.compiler.pbs;
import org.junit.jupiter.api.Test;
import p.studio.compiler.PBSFrontendHostProjections;
import p.studio.compiler.PBSDefinitions;
import p.studio.compiler.models.FrontendSemanticToken;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@ -20,8 +23,19 @@ final class PbsSemanticPresentationContractTest {
assertEquals(1, presentation.themes().size());
assertEquals("PBS Default", presentation.defaultTheme().displayName());
assertEquals("#d9e2ec", presentation.defaultTheme().editorPalette().baseForeground());
assertEquals("#d2a8ff", presentation.defaultTheme().requireTokenStyle("pbs-keyword").foreground());
assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-builtin-type").italic());
assertEquals("#7fb8ff", presentation.defaultTheme().requireTokenStyle("pbs-keyword").foreground());
assertEquals("#d8b86a", presentation.defaultTheme().requireTokenStyle("pbs-string").foreground());
assertEquals("#ff8cc6", presentation.defaultTheme().requireTokenStyle("pbs-number").foreground());
assertEquals("#7fb8ff", presentation.defaultTheme().requireTokenStyle("pbs-literal").foreground());
assertEquals("#7ee787", presentation.defaultTheme().requireTokenStyle("pbs-function").foreground());
assertEquals("#7ee787", presentation.defaultTheme().requireTokenStyle("pbs-method").foreground());
assertEquals("#7ee787", presentation.defaultTheme().requireTokenStyle("pbs-constructor").foreground());
assertEquals("#56d4dd", presentation.defaultTheme().requireTokenStyle("pbs-struct").foreground());
assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-struct").italic());
assertEquals("#56d4dd", presentation.defaultTheme().requireTokenStyle("pbs-builtin-type").foreground());
assertFalse(presentation.defaultTheme().requireTokenStyle("pbs-builtin-type").italic());
assertEquals("#ff8e7a", presentation.defaultTheme().requireTokenStyle("pbs-service").foreground());
assertEquals("#c297ff", presentation.defaultTheme().requireTokenStyle("pbs-asset").foreground());
assertTrue(presentation.defaultTheme().requireTokenStyle("pbs-comment").italic());
assertEquals(PBSFrontendHostProjections.VSCODE_HOST_ID, presentation.requireHostProjection("vscode").hostId());
}
@ -46,8 +60,87 @@ final class PbsSemanticPresentationContractTest {
vscodeProjection.tokenProjections().stream().map(tokenProjection -> tokenProjection.semanticKey()).toList());
assertEquals("keyword", vscodeProjection.requireProjection(PbsSemanticKind.KEYWORD.semanticKey()).hostTokenType());
assertEquals("type", vscodeProjection.requireProjection(PbsSemanticKind.STRUCT.semanticKey()).fallbackTokenType());
assertEquals("variable", vscodeProjection.requireProjection(PbsSemanticKind.ASSET.semanticKey()).hostTokenType());
assertEquals(
java.util.List.of("readonly"),
vscodeProjection.requireProjection(PbsSemanticKind.GLOBAL.semanticKey()).hostTokenModifiers());
}
@Test
void shouldPublishPbsOwnedSemanticTokenProvider() {
final List<FrontendSemanticToken> semanticTokens = PBSDefinitions.PBS.getSemanticTokenProvider().tokenize("""
struct Vec2 {}
service Log {}
host Input {}
enum ResultKind { Ok = 1; }
fn main() -> void {
const answer: int = 42;
let value = new Vec2();
value.length();
Log.info();
Input.read();
let kind: ResultKind;
}
""");
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.BUILTIN_TYPE.semanticKey())));
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.FUNCTION.semanticKey())));
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.CONST.semanticKey())));
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.BUILTIN_TYPE.semanticKey())));
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.CONSTRUCTOR.semanticKey())));
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.METHOD.semanticKey())));
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.SERVICE.semanticKey())));
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.HOST.semanticKey())));
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.ENUM.semanticKey())));
}
@Test
void shouldClassifyStdlibImportsUsingTheirPublishedBarrelKinds() {
final List<FrontendSemanticToken> semanticTokens = PBSDefinitions.PBS.getSemanticTokenProvider().tokenize("""
import { Log } from @sdk:log;
import { Composer } from @sdk:composer;
import { Color as Paint } from @core:color;
fn main() -> void {
Log.info("hello");
Composer.emit_sprite(0, 0, 0, 0, 0, 0, false, false, 0);
let paint: Paint;
}
""");
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.SERVICE.semanticKey())));
assertTrue(semanticTokens.stream().anyMatch(token -> token.semanticKey().equals(PbsSemanticKind.BUILTIN_TYPE.semanticKey())));
}
@Test
void shouldClassifyAssetRootedAliasesUsingDedicatedSemanticKind() {
final List<FrontendSemanticToken> semanticTokens = PBSDefinitions.PBS.getSemanticTokenProvider().tokenize("""
import { Assets } from @sdk:asset;
fn main() -> void {
Assets.load(assets.ui.atlas2, 3);
}
""");
final long assetTokenCount = semanticTokens.stream()
.filter(token -> token.semanticKey().equals(PbsSemanticKind.ASSET.semanticKey()))
.count();
assertEquals(3, assetTokenCount);
}
@Test
void shouldClassifyBuiltinTypesExposedByImportedStdlibModules() {
final List<FrontendSemanticToken> semanticTokens = PBSDefinitions.PBS.getSemanticTokenProvider().tokenize("""
import { Input } from @sdk:input;
fn main() -> void {
let touch : InputTouch = Input.touch();
let pad : InputPad = Input.pad();
}
""");
assertTrue(semanticTokens.stream().filter(token -> token.semanticKey().equals(PbsSemanticKind.BUILTIN_TYPE.semanticKey())).count() >= 2);
}
}

View File

@ -0,0 +1,215 @@
package p.studio.compiler.pbs.semantics;
import org.junit.jupiter.api.Test;
import p.studio.compiler.pbs.ast.PbsAst;
import p.studio.compiler.pbs.lexer.PbsLexer;
import p.studio.compiler.pbs.parser.PbsParser;
import p.studio.compiler.source.diagnostics.DiagnosticSink;
import p.studio.compiler.source.identifiers.FileId;
import p.studio.utilities.structures.ReadOnlyList;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
final class PbsEditorialSupportServiceTest {
private final PbsEditorialSupportService service = new PbsEditorialSupportService();
@Test
void shouldResolveGeneralCompletionAndHoverAcrossLocalAndImportedSymbols() {
final var source = """
import { Log } from @sdk:log;
fn helper(value: int) -> int {
let total = value;
Log.info("hello");
return total;
}
""";
final var ast = parseOrdinary(source);
final var supplementalTopDecls = supplementalTopDecls("""
declare service Log {
fn info(message: str) -> void {
return;
}
}
""");
final var completions = service.completion(
source,
ast,
supplementalTopDecls,
source.indexOf("return total"));
assertTrue(completions.stream().anyMatch(candidate ->
candidate.label().equals("fn") && candidate.kind() == PbsEditorialSymbolKind.KEYWORD));
assertTrue(completions.stream().anyMatch(candidate ->
candidate.label().equals("value") && candidate.kind() == PbsEditorialSymbolKind.PARAMETER));
assertTrue(completions.stream().anyMatch(candidate ->
candidate.label().equals("total") && candidate.kind() == PbsEditorialSymbolKind.LOCAL));
assertTrue(completions.stream().anyMatch(candidate ->
candidate.label().equals("Log") && candidate.kind() == PbsEditorialSymbolKind.SERVICE));
assertTrue(completions.stream().anyMatch(candidate ->
candidate.label().equals("helper") && candidate.kind() == PbsEditorialSymbolKind.FUNCTION));
final var parameterHover = requireHover(source, ast, supplementalTopDecls, "value;");
assertEquals(PbsEditorialSymbolKind.PARAMETER, parameterHover.kind());
assertEquals("int", parameterHover.detail());
final var importedHover = requireHover(source, ast, supplementalTopDecls, "Log.info");
assertEquals(PbsEditorialSymbolKind.SERVICE, importedHover.kind());
assertEquals("@sdk:log", importedHover.origin());
}
@Test
void shouldResolveMemberCompletionAndHoverForImportedHostAndBuiltinTypes() {
final var source = """
import { Input } from @sdk:input;
fn main() -> void {
let touch: InputTouch = Input.touch();
Input.touch();
touch.x_axis();
}
""";
final var ast = parseOrdinary(source);
final var supplementalTopDecls = supplementalTopDecls("""
declare builtin type InputTouch(
pub x: int
) {
fn x_axis() -> int;
}
declare host Input {
fn touch() -> InputTouch;
fn pad() -> InputPad;
}
declare builtin type InputPad(
pub id: int
) {
fn strength() -> int;
}
""");
final var hostMembers = service.completion(
source,
ast,
supplementalTopDecls,
source.indexOf("touch();"));
assertTrue(hostMembers.stream().anyMatch(candidate ->
candidate.label().equals("touch") && candidate.kind() == PbsEditorialSymbolKind.METHOD));
assertTrue(hostMembers.stream().anyMatch(candidate ->
candidate.label().equals("pad") && candidate.kind() == PbsEditorialSymbolKind.METHOD));
final var builtinMembers = service.completion(
source,
ast,
supplementalTopDecls,
source.indexOf("x_axis();"));
assertTrue(builtinMembers.stream().anyMatch(candidate ->
candidate.label().equals("x") && candidate.kind() == PbsEditorialSymbolKind.FIELD));
assertTrue(builtinMembers.stream().anyMatch(candidate ->
candidate.label().equals("x_axis") && candidate.kind() == PbsEditorialSymbolKind.METHOD));
final var builtinTypeHover = requireHover(source, ast, supplementalTopDecls, "InputTouch");
assertEquals(PbsEditorialSymbolKind.BUILTIN_TYPE, builtinTypeHover.kind());
final var hostMethodHover = requireHover(source, ast, supplementalTopDecls, "touch();");
assertEquals(PbsEditorialSymbolKind.METHOD, hostMethodHover.kind());
assertEquals("Input", hostMethodHover.origin());
}
@Test
void shouldResolveSignatureHelpForFunctionMethodAndConstructorCalls() {
final var source = """
declare struct Vec() {
fn blend(dx: int, dy: int) -> int { return dx; }
}
fn mix(left: int, right: int) -> int { return left; }
fn main(vec: Vec) -> void {
mix(1, 2);
vec.blend(1, 2);
new Vec();
}
""";
final var ast = parseOrdinary(source);
final var functionHelp = service.signatureHelp(
source,
ast,
ReadOnlyList.empty(),
source.indexOf("2);"));
assertTrue(functionHelp.isPresent());
assertEquals("mix(left: int, right: int) -> int", functionHelp.orElseThrow().signatures().getFirst().label());
assertEquals(1, functionHelp.orElseThrow().activeParameter());
final var methodHelp = service.signatureHelp(
source,
ast,
ReadOnlyList.empty(),
source.lastIndexOf("2);"));
assertTrue(methodHelp.isPresent());
assertEquals("blend(arg0: int, arg1: int) -> int", methodHelp.orElseThrow().signatures().getFirst().label());
assertEquals(1, methodHelp.orElseThrow().activeParameter());
final var constructorHelp = service.signatureHelp(
source,
ast,
ReadOnlyList.empty(),
source.indexOf("Vec();") + 4);
assertTrue(constructorHelp.isPresent());
assertEquals("Vec()", constructorHelp.orElseThrow().signatures().getFirst().label());
final var constructorHover = requireHover(source, ast, ReadOnlyList.empty(), "Vec();");
assertEquals(PbsEditorialSymbolKind.CONSTRUCTOR, constructorHover.kind());
assertEquals("Vec()", constructorHover.signatures().getFirst().label());
}
private PbsEditorialResolvedSymbol requireHover(
final String source,
final PbsAst.File ast,
final ReadOnlyList<PbsAst.TopDecl> supplementalTopDecls,
final String needle) {
final int offset = source.indexOf(needle);
assertTrue(offset >= 0, "Expected to find needle: " + needle);
return service.hover(source, ast, supplementalTopDecls, offset)
.orElseThrow();
}
private ReadOnlyList<PbsAst.TopDecl> supplementalTopDecls(final String... interfaceModuleSources) {
final ArrayList<PbsAst.TopDecl> topDecls = new ArrayList<>();
int fileNumber = 100;
for (final var source : interfaceModuleSources) {
topDecls.addAll(parseInterface(source, new FileId(fileNumber)).topDecls().asList());
fileNumber += 1;
}
return ReadOnlyList.wrap(topDecls);
}
private PbsAst.File parseOrdinary(final String source) {
return parse(source, new FileId(0), PbsParser.ParseMode.ORDINARY);
}
private PbsAst.File parseInterface(
final String source,
final FileId fileId) {
return parse(source, fileId, PbsParser.ParseMode.INTERFACE_MODULE);
}
private PbsAst.File parse(
final String source,
final FileId fileId,
final PbsParser.ParseMode parseMode) {
final var diagnostics = DiagnosticSink.empty();
final var tokens = PbsLexer.lex(source, fileId, diagnostics);
final var ast = PbsParser.parse(tokens, fileId, diagnostics, parseMode);
assertFalse(diagnostics.hasErrors(), () -> "Unexpected parse errors: " + diagnostics.stream().toList());
return ast;
}
}

View File

@ -0,0 +1,29 @@
package p.studio.compiler.models;
import java.util.Objects;
public record FrontendSemanticToken(
int startOffset,
int endOffset,
String semanticKey) {
public FrontendSemanticToken {
if (startOffset < 0) {
throw new IllegalArgumentException("startOffset must be >= 0");
}
if (endOffset < startOffset) {
throw new IllegalArgumentException("endOffset must be >= startOffset");
}
semanticKey = requireText(semanticKey, "semanticKey");
}
private static String requireText(
final String value,
final String field) {
final String candidate = Objects.requireNonNull(value, field).trim();
if (candidate.isEmpty()) {
throw new IllegalArgumentException(field + " must not be blank");
}
return candidate;
}
}

View File

@ -0,0 +1,14 @@
package p.studio.compiler.models;
import java.util.List;
@FunctionalInterface
public interface FrontendSemanticTokenProvider {
FrontendSemanticTokenProvider NOOP = documentText -> List.of();
List<FrontendSemanticToken> tokenize(String documentText);
static FrontendSemanticTokenProvider noop() {
return NOOP;
}
}

View File

@ -17,6 +17,8 @@ public class FrontendSpec {
private final List<Stdlib> stdlibVersions = List.of();
@Builder.Default
private final FrontendSemanticPresentationSpec semanticPresentation = FrontendSemanticPresentationSpec.empty();
@Builder.Default
private final FrontendSemanticTokenProvider semanticTokenProvider = FrontendSemanticTokenProvider.noop();
public String toString() {
return String.format("FrontendSpec(language=%s)", languageId);

View File

@ -5,7 +5,10 @@ plugins {
dependencies {
implementation(project(":prometeu-lsp:prometeu-lsp-api"))
implementation(project(":prometeu-compiler:prometeu-compiler-core"))
implementation(project(":prometeu-compiler:prometeu-frontend-api"))
implementation(project(":prometeu-compiler:prometeu-build-pipeline"))
implementation(project(":prometeu-compiler:frontends:prometeu-frontend-pbs"))
implementation(project(":prometeu-compiler:prometeu-frontend-registry"))
implementation(project(":prometeu-compiler:prometeu-deps"))
implementation(libs.lsp4j)
}

View File

@ -0,0 +1,12 @@
package p.studio.lsp.messages;
import java.util.List;
import java.util.Objects;
public record BaselineCompletion(
boolean incomplete,
List<BaselineCompletionItem> items) {
public BaselineCompletion {
items = List.copyOf(Objects.requireNonNull(items, "items"));
}
}

View File

@ -0,0 +1,30 @@
package p.studio.lsp.messages;
import java.util.Objects;
public record BaselineCompletionItem(
String label,
BaselineCompletionItemKind kind,
String detail,
String documentation) {
public BaselineCompletionItem {
label = requireText(label, "label");
kind = Objects.requireNonNull(kind, "kind");
detail = normalize(detail);
documentation = normalize(documentation);
}
private static String requireText(
final String value,
final String field) {
final String candidate = normalize(value);
if (candidate.isEmpty()) {
throw new IllegalArgumentException(field + " must not be blank");
}
return candidate;
}
private static String normalize(final String value) {
return value == null ? "" : value.trim();
}
}

View File

@ -0,0 +1,20 @@
package p.studio.lsp.messages;
public enum BaselineCompletionItemKind {
KEYWORD,
VARIABLE,
FIELD,
FUNCTION,
METHOD,
CONSTRUCTOR,
STRUCT,
BUILTIN_TYPE,
SERVICE,
HOST,
CONTRACT,
CALLBACK,
ENUM,
ERROR,
GLOBAL,
CONST
}

View File

@ -8,6 +8,8 @@ public record BaselineServerDescription(
String version,
String frontendLanguageId,
boolean hoverSupported,
boolean completionSupported,
boolean signatureHelpSupported,
List<String> semanticTokenTypes,
List<BaselineSemanticHostProjection> semanticHostProjections,
List<BaselineVisualTheme> visualThemes,

View File

@ -0,0 +1,29 @@
package p.studio.lsp.messages;
import java.util.List;
import java.util.Objects;
public record BaselineSignature(
String label,
List<String> parameters,
String documentation) {
public BaselineSignature {
label = requireText(label, "label");
parameters = List.copyOf(Objects.requireNonNull(parameters, "parameters"));
documentation = normalize(documentation);
}
private static String requireText(
final String value,
final String field) {
final String candidate = normalize(value);
if (candidate.isEmpty()) {
throw new IllegalArgumentException(field + " must not be blank");
}
return candidate;
}
private static String normalize(final String value) {
return value == null ? "" : value.trim();
}
}

View File

@ -0,0 +1,19 @@
package p.studio.lsp.messages;
import java.util.List;
import java.util.Objects;
public record BaselineSignatureHelp(
List<BaselineSignature> signatures,
int activeSignature,
int activeParameter) {
public BaselineSignatureHelp {
signatures = List.copyOf(Objects.requireNonNull(signatures, "signatures"));
if (!signatures.isEmpty() && (activeSignature < 0 || activeSignature >= signatures.size())) {
throw new IllegalArgumentException("activeSignature must reference one of the provided signatures");
}
if (activeParameter < 0) {
throw new IllegalArgumentException("activeParameter must be >= 0");
}
}
}

View File

@ -1,8 +1,10 @@
package p.studio.lsp.services;
import p.studio.lsp.messages.BaselineDocumentAnalysis;
import p.studio.lsp.messages.BaselineCompletion;
import p.studio.lsp.messages.BaselineHover;
import p.studio.lsp.messages.BaselineSemanticTokens;
import p.studio.lsp.messages.BaselineSignatureHelp;
import p.studio.lsp.messages.BaselineServerDescription;
import p.studio.lsp.messages.LspProjectContext;
@ -11,7 +13,11 @@ public interface LanguageServiceBridge {
BaselineDocumentAnalysis analyzeDocument(LspProjectContext context, String documentUri, String text);
BaselineHover hover(LspProjectContext context, String documentUri, int line, int character);
BaselineCompletion completion(LspProjectContext context, String documentUri, String text, int line, int character);
BaselineHover hover(LspProjectContext context, String documentUri, String text, int line, int character);
BaselineSignatureHelp signatureHelp(LspProjectContext context, String documentUri, String text, int line, int character);
BaselineSemanticTokens semanticTokens(LspProjectContext context, String documentUri, String text);

View File

@ -1,24 +1,31 @@
package p.studio.lsp.services.compiler;
import org.apache.commons.lang3.StringUtils;
import p.studio.compiler.FrontendRegistryService;
import p.studio.compiler.messages.BuilderPipelineConfig;
import p.studio.compiler.messages.BuildingIssueSink;
import p.studio.compiler.messages.FrontendPhaseContext;
import p.studio.compiler.messages.BuildingIssue;
import p.studio.compiler.messages.HostAdmissionContext;
import p.studio.compiler.models.AnalysisSnapshot;
import p.studio.compiler.models.BuilderPipelineContext;
import p.studio.compiler.models.FrontendEditorPaletteSpec;
import p.studio.compiler.models.FrontendHostProjectionEntrySpec;
import p.studio.compiler.models.FrontendHostProjectionSpec;
import p.studio.compiler.PBSDefinitions;
import p.studio.compiler.models.FrontendSemanticPresentationSpec;
import p.studio.compiler.models.FrontendSemanticToken;
import p.studio.compiler.models.FrontendTokenStyleSpec;
import p.studio.compiler.models.FrontendVisualThemeSpec;
import p.studio.compiler.pbs.PbsSemanticKind;
import p.studio.compiler.pbs.lexer.PbsLexer;
import p.studio.compiler.pbs.lexer.PbsToken;
import p.studio.compiler.pbs.lexer.PbsTokenKind;
import p.studio.compiler.source.identifiers.FileId;
import p.studio.compiler.source.diagnostics.DiagnosticSink;
import p.studio.compiler.services.PBSFrontendPhaseService;
import p.studio.compiler.workspaces.AssetSurfaceContextLoader;
import p.studio.compiler.utilities.SourceProviderFactory;
import p.studio.compiler.workspaces.BuilderPipelineService;
import p.studio.compiler.pbs.semantics.PbsEditorialCompletionCandidate;
import p.studio.compiler.pbs.semantics.PbsEditorialResolvedSymbol;
import p.studio.compiler.pbs.semantics.PbsEditorialSignature;
import p.studio.compiler.pbs.semantics.PbsEditorialSymbolKind;
import p.studio.compiler.pbs.semantics.PbsEditorialSupportService;
import p.studio.lsp.messages.*;
import p.studio.lsp.services.LanguageServiceBridge;
import p.studio.utilities.logs.LogAggregator;
@ -28,23 +35,27 @@ import java.net.URI;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
public record CompilerLanguageServiceBridge() implements LanguageServiceBridge {
private static final Set<String> BUILTIN_TYPE_NAMES = Set.of("int", "float", "bool", "string", "i32", "i64", "f32", "f64");
import java.util.Optional;
public final class CompilerLanguageServiceBridge implements LanguageServiceBridge {
private final AssetSurfaceContextLoader assetSurfaceContextLoader = new AssetSurfaceContextLoader();
private final PbsEditorialSupportService editorialSupportService = new PbsEditorialSupportService();
@Override
public BaselineServerDescription describeServer(final LspProjectContext context) {
Objects.requireNonNull(context, "context");
final var presentation = PBSDefinitions.PBS.getSemanticPresentation();
final var frontend = frontendSpec(context);
final var presentation = frontend.getSemanticPresentation();
return new BaselineServerDescription(
"Prometeu Studio LSP",
"0.1.0",
context.languageId(),
true,
true,
true,
presentation.semanticKeys(),
presentation.hostProjections().stream().map(this::mapSemanticHostProjection).toList(),
presentation.themes().stream().map(this::mapVisualTheme).toList(),
@ -64,19 +75,76 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge {
}
@Override
public BaselineHover hover(
public BaselineCompletion completion(
final LspProjectContext context,
final String documentUri,
final String text,
final int line,
final int character) {
Objects.requireNonNull(context, "context");
return new BaselineHover("""
**Prometeu Studio LSP**
Compiler-backed baseline.
Semantic enrichment will be layered later.
""");
return editorialDocument(context, documentUri, text)
.map(document -> {
final int offset = new DocumentPositionMapper(document.text()).byteOffsetOf(line, character);
final List<PbsEditorialCompletionCandidate> candidates = editorialSupportService.completion(
document.text(),
document.ast(),
document.supplementalTopDecls(),
document.feSurfaceContext(),
offset);
return new BaselineCompletion(
false,
candidates.stream().map(this::mapCompletionItem).toList());
})
.orElseGet(() -> new BaselineCompletion(false, List.of()));
}
@Override
public BaselineHover hover(
final LspProjectContext context,
final String documentUri,
final String text,
final int line,
final int character) {
Objects.requireNonNull(context, "context");
return editorialDocument(context, documentUri, text)
.flatMap(document -> {
final int offset = new DocumentPositionMapper(document.text()).byteOffsetOf(line, character);
return editorialSupportService.hover(
document.text(),
document.ast(),
document.supplementalTopDecls(),
document.feSurfaceContext(),
offset);
})
.map(symbol -> new BaselineHover(formatHoverMarkdown(symbol)))
.orElseGet(() -> new BaselineHover("No symbol information."));
}
@Override
public BaselineSignatureHelp signatureHelp(
final LspProjectContext context,
final String documentUri,
final String text,
final int line,
final int character) {
Objects.requireNonNull(context, "context");
return editorialDocument(context, documentUri, text)
.flatMap(document -> {
final int offset = new DocumentPositionMapper(document.text()).byteOffsetOf(line, character);
return editorialSupportService.signatureHelp(
document.text(),
document.ast(),
document.supplementalTopDecls(),
document.feSurfaceContext(),
offset);
})
.map(signatureHelp -> new BaselineSignatureHelp(
signatureHelp.signatures().stream()
.map(signature -> new BaselineSignature(signature.label(), signature.parameterLabels(), ""))
.toList(),
signatureHelp.activeSignature(),
signatureHelp.activeParameter()))
.orElseGet(() -> new BaselineSignatureHelp(List.of(), 0, 0));
}
@Override
@ -86,28 +154,24 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge {
final String text) {
Objects.requireNonNull(context, "context");
final String effectiveText = text == null ? "" : text;
final var legend = PBSDefinitions.PBS.getSemanticPresentation().semanticKeys();
final var tokens = PbsLexer.lex(effectiveText, FileId.none(), DiagnosticSink.empty());
final var frontend = frontendSpec(context);
final FrontendSemanticPresentationSpec presentation = frontend.getSemanticPresentation();
final List<FrontendSemanticToken> tokens = frontend.getSemanticTokenProvider().tokenize(effectiveText);
final var positionMapper = new DocumentPositionMapper(effectiveText);
final var semanticTokens = new ArrayList<BaselineSemanticToken>();
for (int index = 0; index < tokens.size(); index += 1) {
final PbsToken token = tokens.get(index);
final PbsSemanticKind semanticKind = classifyToken(tokens, index);
if (semanticKind == null) {
continue;
}
final DocumentPosition start = positionMapper.positionOf(token.start());
final DocumentPosition end = positionMapper.positionOf(token.end());
for (final FrontendSemanticToken token : tokens) {
final DocumentPosition start = positionMapper.positionOf(token.startOffset());
final DocumentPosition end = positionMapper.positionOf(token.endOffset());
final int length = Math.max(1, end.character() - start.character());
semanticTokens.add(new BaselineSemanticToken(
start.line(),
start.character(),
length,
semanticKind.semanticKey()));
token.semanticKey()));
}
return new BaselineSemanticTokens(legend, semanticTokens);
return new BaselineSemanticTokens(presentation.semanticKeys(), semanticTokens);
}
@Override
@ -130,6 +194,71 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge {
return BuilderPipelineService.INSTANCE.analyze(pipelineContext, LogAggregator.empty());
}
private Optional<EditorialDocument> editorialDocument(
final LspProjectContext context,
final String documentUri,
final String text) {
if (!"pbs".equals(context.languageId())) {
return Optional.empty();
}
final Path documentPath = normalizeDocumentPath(documentUri);
final BuilderPipelineContext pipelineContext = BuilderPipelineContext.fromConfig(
new BuilderPipelineConfig(
false,
context.projectRoot().toString(),
"core-v1",
SourceProviderFactory.overlayUtf8(text == null ? Map.of() : Map.of(documentPath, text))));
BuilderPipelineService.INSTANCE.analyze(pipelineContext, LogAggregator.empty());
final FileId fileId = findFileId(pipelineContext, documentPath);
if (fileId == null) {
return Optional.empty();
}
final FrontendPhaseContext frontendPhaseContext = new FrontendPhaseContext(
pipelineContext.resolvedWorkspace.graph().projectTable(),
pipelineContext.fileTable,
pipelineContext.resolvedWorkspace.stack(),
pipelineContext.resolvedWorkspace.stdlib(),
HostAdmissionContext.permissiveDefault(),
assetSurfaceContextLoader.load(pipelineContext.resolvedWorkspace.mainProject().getRootPath()));
final var semanticReadSurface = PBSFrontendPhaseService.semanticReadSurface(
frontendPhaseContext,
p.studio.compiler.source.diagnostics.DiagnosticSink.empty(),
BuildingIssueSink.empty());
final var ast = semanticReadSurface.astByFile().get(fileId);
if (ast == null) {
return Optional.empty();
}
return Optional.of(new EditorialDocument(
text == null ? readCurrentText(pipelineContext, fileId) : text,
ast,
semanticReadSurface.supplementalTopDeclsByFile().getOrDefault(fileId, ReadOnlyList.empty()),
frontendPhaseContext.feSurfaceContext()));
}
private FileId findFileId(
final BuilderPipelineContext pipelineContext,
final Path documentPath) {
for (int fileIndex = 0; fileIndex < pipelineContext.fileTable.size(); fileIndex += 1) {
final FileId candidate = new FileId(fileIndex);
final var sourceHandle = pipelineContext.fileTable.get(candidate);
if (sourceHandle != null
&& sourceHandle.getCanonPath().toAbsolutePath().normalize().equals(documentPath)) {
return candidate;
}
}
return null;
}
private String readCurrentText(
final BuilderPipelineContext pipelineContext,
final FileId fileId) {
final var sourceHandle = pipelineContext.fileTable.get(fileId);
if (sourceHandle == null) {
return "";
}
return sourceHandle.readUtf8().orElse("");
}
private List<BaselineDocumentIssue> mapDiagnostics(
final AnalysisSnapshot snapshot,
final Path documentPath,
@ -174,125 +303,12 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge {
return Path.of(URI.create(Objects.requireNonNull(documentUri, "documentUri"))).toAbsolutePath().normalize();
}
private PbsSemanticKind classifyToken(
final ReadOnlyList<PbsToken> tokens,
final int index) {
final PbsToken token = tokens.get(index);
final PbsSemanticKind lexicalKind = PbsSemanticKind.forToken(token);
if (lexicalKind != null) {
return lexicalKind;
}
if (token.kind() == p.studio.compiler.pbs.lexer.PbsTokenKind.IDENTIFIER) {
if (isLifecycleToken(tokens, index, token)) {
return PbsSemanticKind.LIFECYCLE;
}
return classifyIdentifierToken(tokens, index, token);
}
return null;
}
private PbsSemanticKind classifyIdentifierToken(
final ReadOnlyList<PbsToken> tokens,
final int index,
final PbsToken token) {
final PbsTokenKind previousKind = previousSignificantKind(tokens, index);
final PbsTokenKind nextKind = nextSignificantKind(tokens, index);
if (previousKind == PbsTokenKind.STRUCT) {
return PbsSemanticKind.STRUCT;
}
if (previousKind == PbsTokenKind.CONTRACT) {
return PbsSemanticKind.CONTRACT;
}
if (previousKind == PbsTokenKind.HOST) {
return PbsSemanticKind.HOST;
}
if (previousKind == PbsTokenKind.SERVICE) {
return PbsSemanticKind.SERVICE;
}
if (previousKind == PbsTokenKind.ENUM || previousKind == PbsTokenKind.ERROR) {
return PbsSemanticKind.ENUM;
}
if (previousKind == PbsTokenKind.CALLBACK) {
return PbsSemanticKind.CALLBACK;
}
if (previousKind == PbsTokenKind.GLOBAL) {
return PbsSemanticKind.GLOBAL;
}
if (previousKind == PbsTokenKind.CONST) {
return PbsSemanticKind.CONST;
}
if (previousKind == PbsTokenKind.CTOR || previousKind == PbsTokenKind.NEW) {
return PbsSemanticKind.CONSTRUCTOR;
}
if (previousKind == PbsTokenKind.BUILTIN) {
return PbsSemanticKind.BUILTIN_TYPE;
}
if (previousKind == PbsTokenKind.DOT && nextKind == PbsTokenKind.LEFT_PAREN) {
return PbsSemanticKind.METHOD;
}
if (nextKind == PbsTokenKind.LEFT_PAREN) {
return PbsSemanticKind.FUNCTION;
}
if (isTypeReferenceContext(previousKind, token.lexeme())) {
return PbsSemanticKind.BUILTIN_TYPE;
}
return PbsSemanticKind.IDENTIFIER;
}
private boolean isTypeReferenceContext(
final PbsTokenKind previousKind,
final String lexeme) {
if (previousKind == null) {
return false;
}
if (previousKind != PbsTokenKind.COLON
&& previousKind != PbsTokenKind.ARROW
&& previousKind != PbsTokenKind.AS
&& previousKind != PbsTokenKind.IMPLEMENTS) {
return false;
}
return BUILTIN_TYPE_NAMES.contains(lexeme);
}
private PbsTokenKind previousSignificantKind(
final ReadOnlyList<PbsToken> tokens,
final int index) {
for (int cursor = index - 1; cursor >= 0; cursor -= 1) {
final PbsTokenKind kind = tokens.get(cursor).kind();
if (kind == PbsTokenKind.COMMENT || kind == PbsTokenKind.EOF) {
continue;
}
return kind;
}
return null;
}
private PbsTokenKind nextSignificantKind(
final ReadOnlyList<PbsToken> tokens,
final int index) {
for (int cursor = index + 1; cursor < tokens.size(); cursor += 1) {
final PbsTokenKind kind = tokens.get(cursor).kind();
if (kind == PbsTokenKind.COMMENT || kind == PbsTokenKind.EOF) {
continue;
}
return kind;
}
return null;
}
private boolean isLifecycleToken(
final ReadOnlyList<PbsToken> tokens,
final int index,
final PbsToken token) {
if (!"Init".equals(token.lexeme()) && !"Frame".equals(token.lexeme())) {
return false;
}
if (index == 0 || index + 1 >= tokens.size()) {
return false;
}
return tokens.get(index - 1).kind() == p.studio.compiler.pbs.lexer.PbsTokenKind.LEFT_BRACKET
&& tokens.get(index + 1).kind() == p.studio.compiler.pbs.lexer.PbsTokenKind.RIGHT_BRACKET;
private BaselineCompletionItem mapCompletionItem(final PbsEditorialCompletionCandidate candidate) {
return new BaselineCompletionItem(
candidate.label(),
mapCompletionKind(candidate.kind()),
candidate.detail(),
candidate.origin());
}
private BaselineVisualTheme mapVisualTheme(final FrontendVisualThemeSpec theme) {
@ -337,4 +353,70 @@ public record CompilerLanguageServiceBridge() implements LanguageServiceBridge {
tokenStyle.bold(),
tokenStyle.underline());
}
private p.studio.compiler.models.FrontendSpec frontendSpec(final LspProjectContext context) {
return FrontendRegistryService.getFrontendSpec(context.languageId())
.orElseThrow(() -> new IllegalArgumentException("no frontend registered for languageId: " + context.languageId()));
}
private BaselineCompletionItemKind mapCompletionKind(final PbsEditorialSymbolKind kind) {
return switch (kind) {
case KEYWORD -> BaselineCompletionItemKind.KEYWORD;
case LOCAL, PARAMETER -> BaselineCompletionItemKind.VARIABLE;
case FIELD -> BaselineCompletionItemKind.FIELD;
case FUNCTION -> BaselineCompletionItemKind.FUNCTION;
case METHOD -> BaselineCompletionItemKind.METHOD;
case CONSTRUCTOR -> BaselineCompletionItemKind.CONSTRUCTOR;
case STRUCT -> BaselineCompletionItemKind.STRUCT;
case BUILTIN_TYPE -> BaselineCompletionItemKind.BUILTIN_TYPE;
case SERVICE -> BaselineCompletionItemKind.SERVICE;
case HOST -> BaselineCompletionItemKind.HOST;
case CONTRACT -> BaselineCompletionItemKind.CONTRACT;
case CALLBACK -> BaselineCompletionItemKind.CALLBACK;
case ENUM -> BaselineCompletionItemKind.ENUM;
case ERROR -> BaselineCompletionItemKind.ERROR;
case GLOBAL -> BaselineCompletionItemKind.GLOBAL;
case CONST -> BaselineCompletionItemKind.CONST;
};
}
private String formatHoverMarkdown(final PbsEditorialResolvedSymbol symbol) {
final StringBuilder markdown = new StringBuilder();
final List<PbsEditorialSignature> signatures = symbol.signatures();
if (!signatures.isEmpty()) {
markdown.append("```pbs\n");
for (int index = 0; index < signatures.size(); index += 1) {
if (index > 0) {
markdown.append('\n');
}
markdown.append(signatures.get(index).label());
}
markdown.append("\n```");
} else if (!symbol.detail().isBlank()) {
markdown.append("```pbs\n").append(symbol.displayName());
if (!symbol.detail().isBlank()) {
markdown.append(" : ").append(symbol.detail());
}
markdown.append("\n```");
}
final String kindLabel = symbol.kind().name().toLowerCase(Locale.ROOT).replace('_', ' ');
if (markdown.length() > 0) {
markdown.append("\n\n");
}
markdown.append("**").append(kindLabel).append("**");
if (!symbol.origin().isBlank()) {
markdown.append(" from `").append(symbol.origin()).append('`');
}
if (!symbol.documentation().isBlank()) {
markdown.append("\n\n").append(symbol.documentation());
}
return markdown.toString();
}
private record EditorialDocument(
String text,
p.studio.compiler.pbs.ast.PbsAst.File ast,
ReadOnlyList<p.studio.compiler.pbs.ast.PbsAst.TopDecl> supplementalTopDecls,
p.studio.compiler.messages.FESurfaceContext feSurfaceContext) {
}
}

View File

@ -42,6 +42,40 @@ final class DocumentPositionMapper {
return new DocumentPosition(line, character);
}
int byteOffsetOf(
final int line,
final int character) {
if (line <= 0 && character <= 0) {
return 0;
}
int currentLine = 0;
int currentCharacter = 0;
int utf8Offset = 0;
for (int index = 0; index < text.length(); ) {
if (currentLine == line && currentCharacter >= character) {
return utf8Offset;
}
final int codePoint = text.codePointAt(index);
final int utf16Width = Character.charCount(codePoint);
final int utf8Width = utf8Length(codePoint);
if (currentLine == line && currentCharacter + utf16Width > character) {
return utf8Offset;
}
utf8Offset += utf8Width;
if (codePoint == '\n') {
if (currentLine == line) {
return utf8Offset - utf8Width;
}
currentLine += 1;
currentCharacter = 0;
} else {
currentCharacter += utf16Width;
}
index += utf16Width;
}
return utf8Offset;
}
private int utf8Length(final int codePoint) {
if (codePoint <= 0x7F) {
return 1;
@ -54,4 +88,4 @@ final class DocumentPositionMapper {
}
return 4;
}
}
}

View File

@ -1,6 +1,7 @@
package p.studio.lsp.services.protocol;
import org.eclipse.lsp4j.*;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.services.LanguageClient;
import org.eclipse.lsp4j.services.TextDocumentService;
import p.studio.lsp.messages.LspProjectContext;
@ -11,6 +12,7 @@ import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentMap;
import java.util.List;
public final class PrometeuTextDocumentService implements TextDocumentService {
private final LspProjectContext project;
@ -70,15 +72,44 @@ public final class PrometeuTextDocumentService implements TextDocumentService {
languageServiceBridge.onSave(project, params.getTextDocument().getUri())));
}
@Override
public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completion(final CompletionParams params) {
final String uri = params.getTextDocument().getUri();
final String text = documentTextByUri.get(uri);
return CompletableFuture.completedFuture(Either.forRight(protocolMessageMapper.mapCompletion(
languageServiceBridge.completion(
project,
uri,
text,
params.getPosition().getLine(),
params.getPosition().getCharacter()))));
}
@Override
public CompletableFuture<Hover> hover(final HoverParams params) {
final String uri = params.getTextDocument().getUri();
final String text = documentTextByUri.get(uri);
return CompletableFuture.completedFuture(protocolMessageMapper.mapHover(languageServiceBridge.hover(
project,
params.getTextDocument().getUri(),
uri,
text,
params.getPosition().getLine(),
params.getPosition().getCharacter())));
}
@Override
public CompletableFuture<SignatureHelp> signatureHelp(final SignatureHelpParams params) {
final String uri = params.getTextDocument().getUri();
final String text = documentTextByUri.get(uri);
return CompletableFuture.completedFuture(protocolMessageMapper.mapSignatureHelp(
languageServiceBridge.signatureHelp(
project,
uri,
text,
params.getPosition().getLine(),
params.getPosition().getCharacter())));
}
@Override
public CompletableFuture<SemanticTokens> semanticTokensFull(final SemanticTokensParams params) {
final String uri = params.getTextDocument().getUri();

View File

@ -24,6 +24,18 @@ public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper {
capabilities.setTextDocumentSync(syncOptions);
capabilities.setHoverProvider(description.hoverSupported());
if (description.completionSupported()) {
final CompletionOptions completionOptions = new CompletionOptions();
completionOptions.setResolveProvider(false);
completionOptions.setTriggerCharacters(List.of("."));
capabilities.setCompletionProvider(completionOptions);
}
if (description.signatureHelpSupported()) {
final SignatureHelpOptions signatureHelpOptions = new SignatureHelpOptions();
signatureHelpOptions.setTriggerCharacters(List.of("(", ","));
signatureHelpOptions.setRetriggerCharacters(List.of(","));
capabilities.setSignatureHelpProvider(signatureHelpOptions);
}
final SemanticTokensWithRegistrationOptions semanticTokens = new SemanticTokensWithRegistrationOptions();
semanticTokens.setLegend(new SemanticTokensLegend(description.semanticTokenTypes(), List.of()));
semanticTokens.setFull(true);
@ -71,6 +83,38 @@ public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper {
return result;
}
@Override
public CompletionList mapCompletion(final BaselineCompletion completion) {
final CompletionList list = new CompletionList();
list.setIsIncomplete(completion.incomplete());
list.setItems(completion.items().stream().map(this::mapCompletionItem).toList());
return list;
}
@Override
public SignatureHelp mapSignatureHelp(final BaselineSignatureHelp signatureHelp) {
final SignatureHelp result = new SignatureHelp();
result.setActiveSignature(signatureHelp.activeSignature());
result.setActiveParameter(signatureHelp.activeParameter());
result.setSignatures(signatureHelp.signatures().stream().map(signature -> {
final SignatureInformation information = new SignatureInformation();
information.setLabel(signature.label());
if (!signature.documentation().isBlank()) {
final MarkupContent content = new MarkupContent();
content.setKind(MarkupKind.MARKDOWN);
content.setValue(signature.documentation());
information.setDocumentation(content);
}
information.setParameters(signature.parameters().stream().map(parameter -> {
final ParameterInformation parameterInformation = new ParameterInformation();
parameterInformation.setLabel(parameter);
return parameterInformation;
}).toList());
return information;
}).toList());
return result;
}
@Override
public SemanticTokens mapSemanticTokens(final BaselineSemanticTokens semanticTokens) {
final List<BaselineSemanticToken> orderedTokens = new ArrayList<>(semanticTokens.tokens());
@ -127,6 +171,39 @@ public final class Lsp4jProtocolMessageMapper implements ProtocolMessageMapper {
return diagnostic;
}
private CompletionItem mapCompletionItem(final BaselineCompletionItem item) {
final CompletionItem completionItem = new CompletionItem();
completionItem.setLabel(item.label());
completionItem.setKind(mapCompletionItemKind(item.kind()));
if (!item.detail().isBlank()) {
completionItem.setDetail(item.detail());
}
if (!item.documentation().isBlank()) {
final MarkupContent content = new MarkupContent();
content.setKind(MarkupKind.MARKDOWN);
content.setValue(item.documentation());
completionItem.setDocumentation(content);
}
return completionItem;
}
private CompletionItemKind mapCompletionItemKind(final BaselineCompletionItemKind kind) {
return switch (kind) {
case KEYWORD -> CompletionItemKind.Keyword;
case VARIABLE -> CompletionItemKind.Variable;
case FIELD -> CompletionItemKind.Field;
case FUNCTION -> CompletionItemKind.Function;
case METHOD -> CompletionItemKind.Method;
case CONSTRUCTOR -> CompletionItemKind.Constructor;
case STRUCT, BUILTIN_TYPE -> CompletionItemKind.Struct;
case SERVICE, HOST, CONTRACT -> CompletionItemKind.Interface;
case CALLBACK -> CompletionItemKind.Function;
case ENUM -> CompletionItemKind.Enum;
case ERROR -> CompletionItemKind.EnumMember;
case GLOBAL, CONST -> CompletionItemKind.Constant;
};
}
private DiagnosticSeverity mapSeverity(final BaselineIssueSeverity severity) {
return switch (severity) {

View File

@ -4,11 +4,15 @@ import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.InitializeResult;
import org.eclipse.lsp4j.MessageParams;
import org.eclipse.lsp4j.PublishDiagnosticsParams;
import org.eclipse.lsp4j.SignatureHelp;
import org.eclipse.lsp4j.SemanticTokens;
import p.studio.lsp.messages.BaselineDocumentAnalysis;
import p.studio.lsp.messages.BaselineCompletion;
import p.studio.lsp.messages.BaselineHover;
import p.studio.lsp.messages.BaselineSemanticTokens;
import p.studio.lsp.messages.BaselineSignatureHelp;
import p.studio.lsp.messages.BaselineServerDescription;
import org.eclipse.lsp4j.CompletionList;
public interface ProtocolMessageMapper {
InitializeResult mapInitializeResult(BaselineServerDescription description);
@ -19,6 +23,10 @@ public interface ProtocolMessageMapper {
Hover mapHover(BaselineHover hover);
CompletionList mapCompletion(BaselineCompletion completion);
SignatureHelp mapSignatureHelp(BaselineSignatureHelp signatureHelp);
SemanticTokens mapSemanticTokens(BaselineSemanticTokens semanticTokens);
MessageParams mapInfoMessage(String message);

View File

@ -52,10 +52,17 @@ class CompilerLanguageServiceBridgeTest {
}
}
service Log {}
host Input {}
enum ResultKind { Ok = 1; }
fn main() -> void {
const answer: int = 42;
let value = new Vec2();
value.length();
Log.info();
Input.read();
let kind: ResultKind;
}
""");
@ -68,6 +75,92 @@ class CompilerLanguageServiceBridgeTest {
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-const")));
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-builtin-type")));
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-constructor")));
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-service")));
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-host")));
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-enum")));
}
@Test
void semanticTokensClassifyBuiltinTypesExposedByImportedStdlibModules() {
final CompilerLanguageServiceBridge bridge = new CompilerLanguageServiceBridge();
final var semanticTokens = bridge.semanticTokens(
new LspProjectContext("main", "pbs", Path.of(".")),
Path.of("demo.pbs").toUri().toString(),
"""
import { Input } from @sdk:input;
fn main() -> void {
let touch : InputTouch = Input.touch();
}
""");
assertTrue(semanticTokens.tokens().stream().anyMatch(token -> token.semanticKey().equals("pbs-builtin-type")));
}
@Test
void completionHoverAndSignatureHelpUseCompilerBackedEditorialResolution() {
final Path projectRoot = findRepoRoot(Path.of("").toAbsolutePath().normalize())
.resolve("test-projects")
.resolve("main")
.toAbsolutePath()
.normalize();
final Path documentPath = projectRoot.resolve("src").resolve("main.pbs");
final String overlay = """
declare struct Vec() {
fn blend(dx: int, dy: int) -> int { return dx; }
}
fn mix(left: int, right: int) -> int { return left; }
fn frame(vec: Vec) -> void {
mix(1, 2);
vec.blend(1, 2);
new Vec();
}
""";
final CompilerLanguageServiceBridge bridge = new CompilerLanguageServiceBridge();
final LspProjectContext context = new LspProjectContext("main", "pbs", projectRoot);
final DocumentPositionMapper mapper = new DocumentPositionMapper(overlay);
final var completionPosition = mapper.positionOf(overlay.indexOf("mix(1, 2);"));
final var hoverPosition = mapper.positionOf(overlay.indexOf("blend(1, 2);"));
final var functionSignaturePosition = mapper.positionOf(overlay.indexOf("2);"));
final var constructorSignaturePosition = mapper.positionOf(overlay.indexOf("Vec();") + 4);
final var completion = bridge.completion(
context,
documentPath.toUri().toString(),
overlay,
completionPosition.line(),
completionPosition.character());
assertTrue(completion.items().stream().anyMatch(item -> item.label().equals("mix")));
assertTrue(completion.items().stream().anyMatch(item -> item.label().equals("vec")));
final var hover = bridge.hover(
context,
documentPath.toUri().toString(),
overlay,
hoverPosition.line(),
hoverPosition.character());
assertTrue(hover.markdown().contains("blend(arg0: int, arg1: int) -> int"));
assertTrue(hover.markdown().contains("**method**"));
final var functionSignatureHelp = bridge.signatureHelp(
context,
documentPath.toUri().toString(),
overlay,
functionSignaturePosition.line(),
functionSignaturePosition.character());
assertEquals(1, functionSignatureHelp.activeParameter());
assertEquals("mix(left: int, right: int) -> int", functionSignatureHelp.signatures().getFirst().label());
final var constructorSignatureHelp = bridge.signatureHelp(
context,
documentPath.toUri().toString(),
overlay,
constructorSignaturePosition.line(),
constructorSignaturePosition.character());
assertEquals("Vec()", constructorSignatureHelp.signatures().getFirst().label());
}
@Test
@ -78,6 +171,8 @@ class CompilerLanguageServiceBridgeTest {
assertEquals("pbs", description.frontendLanguageId());
assertEquals("pbs-default", description.activeVisualThemeId());
assertTrue(description.completionSupported());
assertTrue(description.signatureHelpSupported());
assertEquals(1, description.semanticHostProjections().size());
assertEquals("vscode", description.semanticHostProjections().getFirst().hostId());
assertTrue(description.semanticHostProjections().getFirst().tokenProjections().stream()
@ -88,7 +183,7 @@ class CompilerLanguageServiceBridgeTest {
assertEquals("#d9e2ec", description.visualThemes().getFirst().editorPalette().baseForeground());
assertTrue(description.visualThemes().getFirst().tokenStyles().stream()
.anyMatch(tokenStyle -> tokenStyle.semanticKey().equals("pbs-keyword")
&& tokenStyle.foreground().equals("#d2a8ff")));
&& tokenStyle.foreground().equals("#7fb8ff")));
}
private Path findRepoRoot(final Path start) {

View File

@ -6,16 +6,22 @@ import org.eclipse.lsp4j.InitializeResult;
import org.eclipse.lsp4j.InitializedParams;
import org.eclipse.lsp4j.MessageParams;
import org.eclipse.lsp4j.PublishDiagnosticsParams;
import org.eclipse.lsp4j.SignatureHelp;
import org.eclipse.lsp4j.SemanticTokens;
import org.eclipse.lsp4j.jsonrpc.ResponseErrorException;
import org.eclipse.lsp4j.services.LanguageClient;
import org.eclipse.lsp4j.services.TextDocumentService;
import org.junit.jupiter.api.Test;
import p.studio.lsp.messages.BaselineCompletion;
import p.studio.lsp.messages.BaselineCompletionItem;
import p.studio.lsp.messages.BaselineCompletionItemKind;
import p.studio.lsp.messages.BaselineDocumentAnalysis;
import p.studio.lsp.messages.BaselineEditorPalette;
import p.studio.lsp.messages.BaselineHover;
import p.studio.lsp.messages.BaselineSemanticHostProjection;
import p.studio.lsp.messages.BaselineSemanticHostProjectionEntry;
import p.studio.lsp.messages.BaselineSignature;
import p.studio.lsp.messages.BaselineSignatureHelp;
import p.studio.lsp.messages.BaselineSemanticTokens;
import p.studio.lsp.messages.BaselineServerDescription;
import p.studio.lsp.messages.BaselineTokenStyle;
@ -90,6 +96,8 @@ class PrometeuLanguageServerTest {
"1",
"pbs",
true,
true,
true,
List.of(),
List.of(new BaselineSemanticHostProjection(
"vscode",
@ -118,10 +126,35 @@ class PrometeuLanguageServerTest {
}
@Override
public BaselineHover hover(final LspProjectContext project, final String documentUri, final int line, final int character) {
public BaselineCompletion completion(
final LspProjectContext project,
final String documentUri,
final String text,
final int line,
final int character) {
return new BaselineCompletion(false, List.of(new BaselineCompletionItem("demo", BaselineCompletionItemKind.FUNCTION, "", "")));
}
@Override
public BaselineHover hover(
final LspProjectContext project,
final String documentUri,
final String text,
final int line,
final int character) {
return new BaselineHover("hover");
}
@Override
public BaselineSignatureHelp signatureHelp(
final LspProjectContext project,
final String documentUri,
final String text,
final int line,
final int character) {
return new BaselineSignatureHelp(List.of(new BaselineSignature("demo()", List.of(), "")), 0, 0);
}
@Override
public BaselineSemanticTokens semanticTokens(final LspProjectContext context, final String documentUri, final String text) {
return new BaselineSemanticTokens(List.of(), List.of());
@ -158,6 +191,16 @@ class PrometeuLanguageServerTest {
throw new UnsupportedOperationException();
}
@Override
public org.eclipse.lsp4j.CompletionList mapCompletion(final BaselineCompletion completion) {
throw new UnsupportedOperationException();
}
@Override
public SignatureHelp mapSignatureHelp(final BaselineSignatureHelp signatureHelp) {
throw new UnsupportedOperationException();
}
@Override
public SemanticTokens mapSemanticTokens(final BaselineSemanticTokens semanticTokens) {
throw new UnsupportedOperationException();

View File

@ -0,0 +1,212 @@
package p.studio.lsp.services.protocol;
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.CompletionList;
import org.eclipse.lsp4j.CompletionParams;
import org.eclipse.lsp4j.DidOpenTextDocumentParams;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.HoverParams;
import org.eclipse.lsp4j.MarkupContent;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.SignatureHelp;
import org.eclipse.lsp4j.SignatureHelpParams;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.lsp4j.TextDocumentItem;
import org.junit.jupiter.api.Test;
import p.studio.lsp.messages.BaselineCompletion;
import p.studio.lsp.messages.BaselineCompletionItem;
import p.studio.lsp.messages.BaselineCompletionItemKind;
import p.studio.lsp.messages.BaselineDocumentAnalysis;
import p.studio.lsp.messages.BaselineHover;
import p.studio.lsp.messages.BaselineSemanticTokens;
import p.studio.lsp.messages.BaselineServerDescription;
import p.studio.lsp.messages.BaselineSignature;
import p.studio.lsp.messages.BaselineSignatureHelp;
import p.studio.lsp.messages.LspProjectContext;
import p.studio.lsp.services.LanguageServiceBridge;
import p.studio.lsp.services.protocol.mapping.ProtocolMessageMapper;
import java.nio.file.Path;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
final class PrometeuTextDocumentServiceTest {
@Test
void shouldPassOpenDocumentOverlayToCompletionHoverAndSignatureHelp() {
final var bridge = new RecordingBridge();
final var mapper = new RecordingMapper();
final var service = new PrometeuTextDocumentService(
new LspProjectContext("main", "pbs", Path.of(".")),
bridge,
mapper);
final String uri = Path.of("demo.pbs").toUri().toString();
final String text = """
fn frame() -> void {
demo();
}
""";
final var openParams = new DidOpenTextDocumentParams(new TextDocumentItem(uri, "pbs", 1, text));
service.didOpen(openParams);
final var completion = service.completion(new CompletionParams(
new TextDocumentIdentifier(uri),
new Position(1, 2))).join();
final var completionList = completion.getRight();
assertSame(mapper.completionList, completionList);
assertEquals(text, bridge.lastCompletionText);
assertEquals(1, bridge.lastCompletionLine);
assertEquals(2, bridge.lastCompletionCharacter);
final Hover hover = service.hover(new HoverParams(
new TextDocumentIdentifier(uri),
new Position(1, 4))).join();
final var hoverContent = (MarkupContent) hover.getContents().getRight();
assertEquals("hover", hoverContent.getValue());
assertEquals(text, bridge.lastHoverText);
final SignatureHelp signatureHelp = service.signatureHelp(new SignatureHelpParams(
new TextDocumentIdentifier(uri),
new Position(1, 6))).join();
assertSame(mapper.signatureHelp, signatureHelp);
assertEquals(text, bridge.lastSignatureHelpText);
assertEquals(1, bridge.lastSignatureHelpLine);
assertEquals(6, bridge.lastSignatureHelpCharacter);
assertTrue(mapper.mappedSignatureHelp.signatures().getFirst().label().contains("demo"));
}
private static final class RecordingBridge implements LanguageServiceBridge {
private String lastCompletionText;
private int lastCompletionLine;
private int lastCompletionCharacter;
private String lastHoverText;
private String lastSignatureHelpText;
private int lastSignatureHelpLine;
private int lastSignatureHelpCharacter;
@Override
public BaselineServerDescription describeServer(final LspProjectContext context) {
throw new UnsupportedOperationException();
}
@Override
public BaselineDocumentAnalysis analyzeDocument(final LspProjectContext context, final String documentUri, final String text) {
return new BaselineDocumentAnalysis(List.of());
}
@Override
public BaselineCompletion completion(
final LspProjectContext context,
final String documentUri,
final String text,
final int line,
final int character) {
lastCompletionText = text;
lastCompletionLine = line;
lastCompletionCharacter = character;
return new BaselineCompletion(false, List.of(
new BaselineCompletionItem("demo", BaselineCompletionItemKind.FUNCTION, "", "")));
}
@Override
public BaselineHover hover(
final LspProjectContext context,
final String documentUri,
final String text,
final int line,
final int character) {
lastHoverText = text;
return new BaselineHover("hover");
}
@Override
public BaselineSignatureHelp signatureHelp(
final LspProjectContext context,
final String documentUri,
final String text,
final int line,
final int character) {
lastSignatureHelpText = text;
lastSignatureHelpLine = line;
lastSignatureHelpCharacter = character;
return new BaselineSignatureHelp(List.of(
new BaselineSignature("demo()", List.of(), "")), 0, 0);
}
@Override
public BaselineSemanticTokens semanticTokens(final LspProjectContext context, final String documentUri, final String text) {
return new BaselineSemanticTokens(List.of(), List.of());
}
@Override
public String onSave(final LspProjectContext context, final String documentUri) {
return "saved";
}
}
private static final class RecordingMapper implements ProtocolMessageMapper {
private final CompletionList completionList = new CompletionList(false, List.of(new CompletionItem("demo")));
private final SignatureHelp signatureHelp = new SignatureHelp();
private BaselineSignatureHelp mappedSignatureHelp;
@Override
public org.eclipse.lsp4j.InitializeResult mapInitializeResult(final BaselineServerDescription description) {
throw new UnsupportedOperationException();
}
@Override
public org.eclipse.lsp4j.PublishDiagnosticsParams mapDiagnostics(
final String uri,
final BaselineDocumentAnalysis analysis) {
throw new UnsupportedOperationException();
}
@Override
public org.eclipse.lsp4j.PublishDiagnosticsParams emptyDiagnostics(final String uri) {
throw new UnsupportedOperationException();
}
@Override
public Hover mapHover(final BaselineHover hover) {
final var content = new MarkupContent();
content.setKind("markdown");
content.setValue(hover.markdown());
return new Hover(content);
}
@Override
public CompletionList mapCompletion(final BaselineCompletion completion) {
return completionList;
}
@Override
public SignatureHelp mapSignatureHelp(final BaselineSignatureHelp signatureHelp) {
this.mappedSignatureHelp = signatureHelp;
return this.signatureHelp;
}
@Override
public org.eclipse.lsp4j.SemanticTokens mapSemanticTokens(final BaselineSemanticTokens semanticTokens) {
throw new UnsupportedOperationException();
}
@Override
public org.eclipse.lsp4j.MessageParams mapInfoMessage(final String message) {
throw new UnsupportedOperationException();
}
@Override
public org.eclipse.lsp4j.MessageParams mapErrorMessage(final String message) {
throw new UnsupportedOperationException();
}
@Override
public org.eclipse.lsp4j.MessageParams mapWarningMessage(final String message) {
throw new UnsupportedOperationException();
}
}
}

View File

@ -1,10 +1,16 @@
package p.studio.lsp.services.protocol.mapping;
import org.eclipse.lsp4j.InitializeResult;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.junit.jupiter.api.Test;
import p.studio.lsp.messages.BaselineCompletion;
import p.studio.lsp.messages.BaselineCompletionItem;
import p.studio.lsp.messages.BaselineCompletionItemKind;
import p.studio.lsp.messages.BaselineEditorPalette;
import p.studio.lsp.messages.BaselineSemanticHostProjection;
import p.studio.lsp.messages.BaselineSemanticHostProjectionEntry;
import p.studio.lsp.messages.BaselineSignature;
import p.studio.lsp.messages.BaselineSignatureHelp;
import p.studio.lsp.messages.BaselineServerDescription;
import p.studio.lsp.messages.BaselineTokenStyle;
import p.studio.lsp.messages.BaselineVisualTheme;
@ -14,6 +20,7 @@ import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertTrue;
final class Lsp4jProtocolMessageMapperTest {
@ -25,6 +32,8 @@ final class Lsp4jProtocolMessageMapperTest {
"1",
"pbs",
true,
true,
true,
List.of("demo-keyword"),
List.of(new BaselineSemanticHostProjection(
"vscode",
@ -43,6 +52,9 @@ final class Lsp4jProtocolMessageMapperTest {
final InitializeResult result = mapper.mapInitializeResult(description);
assertEquals(List.of("."), result.getCapabilities().getCompletionProvider().getTriggerCharacters());
assertEquals(List.of("(", ","), result.getCapabilities().getSignatureHelpProvider().getTriggerCharacters());
final var experimental = assertInstanceOf(Map.class, result.getCapabilities().getExperimental());
final var semanticPayload = assertInstanceOf(Map.class, experimental.get("prometeuSemanticHostProjections"));
assertEquals("pbs", semanticPayload.get("frontendLanguageId"));
@ -59,4 +71,33 @@ final class Lsp4jProtocolMessageMapperTest {
assertEquals(List.of("declaration"), firstTokenProjection.get("hostTokenModifiers"));
assertEquals("variable", firstTokenProjection.get("fallbackTokenType"));
}
@Test
void completionAndSignatureHelpMapToLspPayloads() {
final var mapper = new Lsp4jProtocolMessageMapper();
final var completion = mapper.mapCompletion(new BaselineCompletion(
false,
List.of(new BaselineCompletionItem(
"blend",
BaselineCompletionItemKind.METHOD,
"blend(dx: int, dy: int) -> int",
"method docs"))));
assertEquals(1, completion.getItems().size());
assertEquals("blend", completion.getItems().getFirst().getLabel());
assertEquals("blend(dx: int, dy: int) -> int", completion.getItems().getFirst().getDetail());
final var documentation = assertInstanceOf(Either.class, completion.getItems().getFirst().getDocumentation());
assertTrue(documentation.isRight());
final var signatureHelp = mapper.mapSignatureHelp(new BaselineSignatureHelp(
List.of(new BaselineSignature(
"mix(left: int, right: int) -> int",
List.of("left: int", "right: int"),
"")),
0,
1));
assertEquals(1, signatureHelp.getSignatures().size());
assertEquals("mix(left: int, right: int) -> int", signatureHelp.getSignatures().getFirst().getLabel());
assertEquals(1, signatureHelp.getActiveParameter());
}
}

View File

@ -1,25 +0,0 @@
package p.studio.utilities;
import org.junit.jupiter.api.Test;
import p.studio.compiler.PBSDefinitions;
import static org.junit.jupiter.api.Assertions.assertTrue;
class FrontendVisualThemeCssRendererTest {
@Test
void rendersLegacyCompatibleCssFromStructuredFrontendTheme() {
final FrontendVisualThemeCssRenderer renderer = new FrontendVisualThemeCssRenderer();
final String css = renderer.renderDefaultTheme(
PBSDefinitions.PBS.getLanguageId(),
PBSDefinitions.PBS.getSemanticPresentation());
assertTrue(css.contains(".editor-workspace-code-area-type-pbs"));
assertTrue(css.contains(".text.editor-semantic-pbs-keyword"));
assertTrue(css.contains("-fx-fill: #569cd6;"));
assertTrue(css.contains("-fx-font-style: italic;"));
assertTrue(css.contains(".editor-workspace-status-chip-type-pbs"));
assertTrue(css.contains("-fx-border-color: #a47dff;"));
}
}

View File

@ -6,37 +6,37 @@
"foreground": "#8b949e",
"italic": true
},
"pbs-string:pbs": "#7ee787",
"pbs-number:pbs": "#ffa657",
"pbs-literal:pbs": "#79c0ff",
"pbs-string:pbs": "#d8b86a",
"pbs-number:pbs": "#ff8cc6",
"pbs-literal:pbs": "#7fb8ff",
"pbs-lifecycle:pbs": {
"foreground": "#ff7b72",
"bold": true
},
"pbs-keyword:pbs": "#d2a8ff",
"pbs-keyword:pbs": "#7fb8ff",
"pbs-operator:pbs": "#c9d1d9",
"pbs-punctuation:pbs": "#8b949e",
"pbs-function:pbs": {
"foreground": "#ffa657",
"foreground": "#7ee787",
"bold": true
},
"pbs-method:pbs": "#ffd580",
"pbs-method:pbs": "#7ee787",
"pbs-constructor:pbs": {
"foreground": "#e3b341",
"foreground": "#7ee787",
"bold": true
},
"pbs-struct:pbs": "#56d4dd",
"pbs-struct:pbs": {
"foreground": "#56d4dd",
"italic": true
},
"pbs-contract:pbs": {
"foreground": "#79c0ff",
"underline": true
},
"pbs-host:pbs": "#c297ff",
"pbs-builtin-type:pbs": {
"foreground": "#7ee787",
"italic": true
},
"pbs-builtin-type:pbs": "#56d4dd",
"pbs-service:pbs": {
"foreground": "#c297ff",
"foreground": "#ff8e7a",
"bold": true
},
"pbs-error:pbs": {
@ -62,10 +62,10 @@
"foreground": "#8b949e",
"italic": true
},
"string:pbs": "#7ee787",
"number:pbs": "#ffa657",
"enumMember:pbs": "#79c0ff",
"variable:pbs": "#79c0ff",
"string:pbs": "#d8b86a",
"number:pbs": "#ff8cc6",
"enumMember:pbs": "#7fb8ff",
"variable:pbs": "#7fb8ff",
"function.async:pbs": {
"foreground": "#ff7b72",
"bold": true
@ -74,41 +74,43 @@
"foreground": "#ff7b72",
"bold": true
},
"keyword:pbs": "#d2a8ff",
"keyword:pbs": "#7fb8ff",
"operator:pbs": "#c9d1d9",
"function:pbs": {
"foreground": "#ffa657",
"foreground": "#7ee787",
"bold": true
},
"method:pbs": "#ffd580",
"method:pbs": "#7ee787",
"class.declaration:pbs": {
"foreground": "#e3b341",
"foreground": "#7ee787",
"bold": true
},
"type.declaration:pbs": {
"foreground": "#e3b341",
"foreground": "#7ee787",
"bold": true
},
"struct:pbs": "#56d4dd",
"type:pbs": "#56d4dd",
"struct:pbs": {
"foreground": "#56d4dd",
"italic": true
},
"type:pbs": {
"foreground": "#56d4dd",
"italic": true
},
"interface:pbs": {
"foreground": "#79c0ff",
"underline": true
},
"class.defaultLibrary:pbs": "#c297ff",
"type.defaultLibrary:pbs": "#c297ff",
"variable.defaultLibrary:pbs": {
"foreground": "#7ee787",
"italic": true
},
"variable.defaultLibrary:pbs": "#56d4dd",
"enum:pbs": {
"foreground": "#ff7b72",
"underline": true
},
"variable.readonly:pbs": {
"foreground": "#f778ba",
"italic": true
}
"variable.readonly:pbs": "#c297ff",
"pbs-asset:pbs": "#c297ff",
"string.readonly:pbs": "#c297ff"
}
},
"workbench.colorCustomizations": {

View File

@ -1909,7 +1909,7 @@
"relative_path" : "scene-bank.pack-request.json",
"mime_type" : "application/json",
"size" : 1313159,
"last_modified" : 1777631167251,
"last_modified" : 1778159580103,
"fingerprint" : "31b7a0019dc08d84af95893b349839ba2975e0f8094d8eafdc1b4c48841709f8",
"metadata" : {
"scenePackRequest" : {

View File

@ -15,6 +15,8 @@ declare global camera_mult: int = 1;
declare const MAX_FRAMES: int = 4;
declare const CAMERA_SPEED: int = 1;
declare struct Bla (a: int) {}
[Init]
fn init() -> void
{
@ -25,6 +27,7 @@ fn init() -> void
camera_x = 0;
camera_mult = 1;
Composer.bind_scene(0);
let bla: Bla = new Bla(1);
}
[Frame]
@ -55,9 +58,8 @@ fn frame() -> void
}
}
let touch : InputTouch = Input.touch();
let pad : InputPad = Input.pad();
if (touch.button().released())
{
@ -93,15 +95,15 @@ fn frame() -> void
let b : int = 15;
let total : int = a + b;
if (Input.pad().a().pressed())
if (pad.a().pressed())
{
total += 25;
}
else if (Input.pad().b().pressed())
else if (pad.b().pressed())
{
total += 5;
}
else if (Input.pad().x().pressed())
else if (pad.x().pressed())
{
total -= 10;
}

View File

@ -32,4 +32,7 @@ Thumbs.db
# Editor local state
.vscode/settings.json
.vscode/*.log
.vscode/*.log
# AI
debug