editor scope guides
This commit is contained in:
parent
18b1967e6d
commit
e06be29f4b
@ -1,4 +1,4 @@
|
||||
{"type":"meta","next_id":{"DSC":16,"AGD":17,"DEC":14,"PLN":30,"LSN":30,"CLSN":1}}
|
||||
{"type":"meta","next_id":{"DSC":17,"AGD":18,"DEC":15,"PLN":33,"LSN":31,"CLSN":1}}
|
||||
{"type":"discussion","id":"DSC-0001","status":"done","ticket":"studio-docs-import","title":"Import docs/studio into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["studio","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0001","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0001-assets-workspace-execution-wave-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0002","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0002-bank-composition-editor-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0003","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0003-mental-model-asset-mutations-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0004","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0004-mental-model-assets-workspace-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0005","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0005-mental-model-studio-events-and-components-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0006","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0006-mental-model-studio-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0007","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0007-pack-wizard-shell-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0008","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0008-project-scoped-state-and-activity-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0016","file":"discussion/lessons/DSC-0001-studio-docs-import/LSN-0016-studio-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]}
|
||||
{"type":"discussion","id":"DSC-0002","status":"open","ticket":"palette-management-in-studio","title":"Palette Management in Studio","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["studio","legacy-import","palette-management","tile-bank","packer-boundary"],"agendas":[{"id":"AGD-0002","file":"AGD-0002-palette-management-in-studio.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0003","status":"done","ticket":"packer-docs-import","title":"Import docs/packer into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0009","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0009-mental-model-packer-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0010-asset-identity-and-runtime-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0011-foundations-workspace-runtime-and-build-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0012-runtime-ownership-and-studio-boundary-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0013-metadata-convergence-and-runtime-sink-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0014-pack-wizard-summary-validation-and-pack-execution-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0015-tile-bank-packing-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0017-packer-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]}
|
||||
@ -13,4 +13,5 @@
|
||||
{"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":"open","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":[{"id":"AGD-0016","file":"AGD-0016-pbs-service-facade-reserved-metadata.md","status":"accepted","created_at":"2026-04-03","updated_at":"2026-04-03"}],"decisions":[{"id":"DEC-0013","file":"DEC-0013-pbs-sdk-executable-service-bodies.md","status":"accepted","created_at":"2026-04-03","updated_at":"2026-04-03","ref_agenda":"AGD-0016"}],"plans":[{"id":"PLN-0029","file":"PLN-0029-pbs-sdk-executable-service-bodies.md","status":"review","created_at":"2026-04-03","updated_at":"2026-04-03","ref_decisions":["DEC-0013"]}],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0015","status":"done","ticket":"pbs-service-facade-reserved-metadata","title":"SDK Service Bodies Calling Builtin/Intrinsic Proxies as Ordinary PBS Code","created_at":"2026-04-03","updated_at":"2026-04-03","tags":["compiler","pbs","sdk","stdlib","lowering","service","intrinsic","sdk-interface"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0030","file":"discussion/lessons/DSC-0015-pbs-service-facade-reserved-metadata/LSN-0030-sdk-service-bodies-over-private-reserved-proxies.md","status":"done","created_at":"2026-04-03","updated_at":"2026-04-03"}]}
|
||||
{"type":"discussion","id":"DSC-0016","status":"open","ticket":"studio-editor-scope-guides-and-brace-anchoring","title":"Scope Guides do Code Editor com ancoragem exata em braces e destaque do escopo ativo","created_at":"2026-04-03","updated_at":"2026-04-03","tags":["studio","editor","scope-guides","braces","semantic-read","frontend-contract"],"agendas":[{"id":"AGD-0017","file":"AGD-0017-studio-editor-scope-guides-and-brace-anchoring.md","status":"accepted","created_at":"2026-04-03","updated_at":"2026-04-03"}],"decisions":[{"id":"DEC-0014","file":"DEC-0014-studio-editor-active-scope-and-structural-anchors.md","status":"accepted","created_at":"2026-04-03","updated_at":"2026-04-03"}],"plans":[{"id":"PLN-0030","file":"PLN-0030-studio-active-container-and-active-scope-gutter-wave-1.md","status":"review","created_at":"2026-04-03","updated_at":"2026-04-03"},{"id":"PLN-0031","file":"PLN-0031-studio-structural-anchor-semantic-surface-specification.md","status":"review","created_at":"2026-04-03","updated_at":"2026-04-03"},{"id":"PLN-0032","file":"PLN-0032-frontend-structural-anchor-payloads-and-anchor-aware-tests.md","status":"review","created_at":"2026-04-03","updated_at":"2026-04-03"}],"lessons":[]}
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
---
|
||||
id: LSN-0030
|
||||
ticket: pbs-service-facade-reserved-metadata
|
||||
title: SDK Service Bodies Over Private Reserved Proxies
|
||||
created: 2026-04-03
|
||||
tags: [compiler, pbs, sdk, stdlib, lowering, service, intrinsic, sdk-interface]
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
PBS originally supported two clear execution shapes for SDK surfaces:
|
||||
|
||||
- public service wrappers over reserved hosts such as `Log`, `Gfx`, and `Assets`;
|
||||
- public builtin roots that lower directly to intrinsics.
|
||||
|
||||
The `@sdk:input` surface exposed a third requirement: keep the public API as a normal `service`, keep the builtin proxy private, and still allow user code like `Input.touch().x()` and `Input.pad().a().pressed()` to compile and lower correctly.
|
||||
|
||||
The core pitfall was assuming the public callsite itself still had to lower directly to `CALL_INTRINSIC`. That assumption forced the public API shape back toward builtin roots and broke the intended service abstraction.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
### Executable SDK Service Bodies for Builtin/Intrinsic-Backed Public Services
|
||||
|
||||
**What:**
|
||||
The accepted model keeps `SDK_INTERFACE` non-executable by default, but allows a restricted executable subset for SDK service methods. Public callsites such as `Input.touch()` lower as ordinary callable invocations of imported SDK service methods, while intrinsic lowering happens inside those imported method bodies when they call private reserved proxies such as `LowInput`.
|
||||
|
||||
**Why:**
|
||||
This preserves the intended product-facing API shape. SDK authors can write ordinary service bodies with locals and intermediate processing instead of exposing private builtin roots or inventing a second-class metadata-only facade system.
|
||||
|
||||
**Trade-offs:**
|
||||
The compiler must preserve owner/chaining semantics across callable returns, not only across direct intrinsic callsites. It also needs an explicit subset boundary and dedicated diagnostics so the executable exception for `SDK_INTERFACE` does not silently widen into arbitrary interface execution.
|
||||
|
||||
## Patterns and Algorithms
|
||||
|
||||
- Model the public SDK API as a normal service surface and keep the private reserved proxy internal.
|
||||
- Let the public user callsite lower as `CALL_FUNC` when the service method is the correct public abstraction.
|
||||
- Preserve reserved owner metadata on callable returns so chained expressions continue to resolve after the service call boundary.
|
||||
- Validate executable SDK service bodies against an explicit initial subset instead of inferring support from whatever lowering happens to tolerate.
|
||||
- Emit dedicated diagnostics for unsupported SDK executable constructs rather than collapsing to a generic unresolved-callee error.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- Do not assume every intrinsic-backed public SDK surface should lower directly from the public callsite to `CALL_INTRINSIC`.
|
||||
- Do not leak private builtin roots into the public API merely because the existing lowering path already understands them.
|
||||
- Do not add a broad executable mode to all `SDK_INTERFACE` declarations when only a narrow service-method subset is intended.
|
||||
- Do not rely on old tests that assert direct intrinsic callsites once the accepted model changes to callable public entrypoints plus intrinsic lowering inside imported SDK bodies.
|
||||
|
||||
## Takeaways
|
||||
|
||||
- Preserve the public API shape first, then adapt lowering to it when the abstraction is intentional.
|
||||
- Owner propagation across callable returns is the critical mechanism that makes service-over-intrinsic wrappers behave like ordinary PBS code.
|
||||
- A restricted executable subset plus dedicated diagnostics is safer than implicit support for arbitrary interface code.
|
||||
@ -1,113 +0,0 @@
|
||||
---
|
||||
id: AGD-0016
|
||||
ticket: pbs-service-facade-reserved-metadata
|
||||
title: SDK Service Bodies Calling Builtin/Intrinsic Proxies as Ordinary PBS Code
|
||||
status: accepted
|
||||
created: 2026-04-03
|
||||
resolved: 2026-04-03
|
||||
decision: DEC-0013
|
||||
tags: [compiler, pbs, sdk, stdlib, lowering, service, intrinsic, sdk-interface]
|
||||
---
|
||||
|
||||
## Pain
|
||||
|
||||
Domain owner: `compiler/pbs`
|
||||
|
||||
The PBS SDK currently supports two stable execution models:
|
||||
|
||||
1. public service wrappers over reserved host declarations such as `@sdk:log`, `@sdk:gfx`, and `@sdk:asset`;
|
||||
2. public builtin-const roots that lower directly to intrinsic owners.
|
||||
|
||||
The input surface now needs a service-oriented version of the intrinsic-backed case:
|
||||
|
||||
- a public `service Input`;
|
||||
- a private builtin type plus builtin const proxy used only inside the SDK;
|
||||
- ordinary PBS service bodies that call the private builtin proxy and return values normally.
|
||||
|
||||
Today this shape parses and passes frontend semantics, but executable lowering does not treat imported SDK service methods as ordinary executable call targets with real bodies. As a result, user code like `Input.touch()` and `Input.pad().a().pressed()` fails with `E_SEM_EXEC_LOWERING_UNRESOLVED_CALLEE` even though the service body itself is valid PBS code.
|
||||
|
||||
## Context
|
||||
|
||||
- `@sdk:input` currently wants to hide the builtin root and expose only the public service.
|
||||
- The lowering path already knows how to:
|
||||
- resolve host-backed service wrappers;
|
||||
- resolve builtin-const-rooted intrinsics.
|
||||
- The intended rule is that SDK service methods should behave as ordinary PBS methods even when their bodies call builtin/intrinsic proxies such as `LowInput`.
|
||||
- Existing tests in the PBS frontend assume `Input` chains resolve to intrinsic callsites and to builtin-owned chained receivers.
|
||||
- The user clarified the desired behavior:
|
||||
- `declare service Input { fn touch() -> InputTouch { let touch = LowInput.touch(); return touch; } }` must compile as normal PBS service code;
|
||||
- the body may include locals and additional processing before returning;
|
||||
- the public callsite does not need to lower directly to the intrinsic as long as the overall executable model works correctly.
|
||||
- Repository workflow requires decision before plan/implementation. This agenda exists to converge on the normative model first.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- [x] What executable artifact model should represent SDK service methods so imported user callsites can lower them as ordinary callable bodies rather than as metadata-only surfaces?
|
||||
Answer: eligible SDK service methods should be represented as ordinary executable callables with lowered bodies available to imported callsites.
|
||||
|
||||
- [x] Should `SDK_INTERFACE` continue forbidding emitted executable bodies globally, or should it gain a selective path for executable service methods that are safe to import and call?
|
||||
Answer: keep the global prohibition by default, but add a narrow selective path for eligible executable SDK service methods.
|
||||
|
||||
- [x] How should chained owner propagation work for values returned from SDK service methods whose bodies call builtin intrinsics, such as `Input.touch()` returning `InputTouch` and `Input.pad()` returning `InputPad`?
|
||||
Answer: owner propagation should follow the value actually returned by the lowered intrinsic call inside the SDK service body, so callers preserve the same chained builtin semantics as direct intrinsic use.
|
||||
|
||||
- [x] What constraints must apply so the compiler can support ordinary SDK service bodies without accidentally turning all interface code into full executable implementation code?
|
||||
Answer: restrict the feature to reserved SDK service methods that stay within a supported executable subset and are explicitly validated as importable/lowerable.
|
||||
|
||||
- [x] Which existing frontend tests must be reoriented from "public callsite resolves directly as intrinsic" to "public service callsite compiles normally and intrinsic resolution succeeds inside the imported method body"?
|
||||
Answer: the `@sdk:input` frontend and lowering tests should be reoriented to validate ordinary service calls, intrinsic lowering inside imported SDK method bodies, and chained owner preservation on returned values.
|
||||
|
||||
- [x] What diagnostics should the compiler emit when an SDK service body calls reserved proxies in ways that cannot be imported or lowered safely?
|
||||
Answer: add dedicated diagnostics for non-importable or non-lowerable executable SDK service bodies instead of collapsing to generic unresolved-callee failures.
|
||||
|
||||
## Options
|
||||
|
||||
### Option A - Treat SDK Service Bodies as Ordinary Executable Callables
|
||||
- **Approach:** Preserve executable bodies for eligible SDK service methods and import them as ordinary callable targets. Lowering of user code emits `CALL_FUNC` to the service method, and the service body itself lowers calls like `LowInput.touch()` to intrinsics.
|
||||
- **Pro:** Matches the intended product model exactly. Keeps service semantics ordinary and avoids facade-specific lowering rules.
|
||||
- **Con:** Requires widening the current `SDK_INTERFACE` lowering model, which today suppresses emitted function bodies.
|
||||
- **Maintainability:** Strong if the eligibility rules stay explicit and narrow.
|
||||
|
||||
### Option B - Explicit Reserved Facade Metadata on Service Methods
|
||||
- **Approach:** Add explicit reserved metadata on service methods declaring which intrinsic owner and method they represent. Lowering may continue to skip executable imported service bodies and instead lower the public callsite through the reserved metadata bridge.
|
||||
- **Pro:** Smaller execution-model change than importing executable service bodies.
|
||||
- **Con:** It does not deliver the user-requested semantics of "ordinary PBS service code with arbitrary local processing". It also creates a special case distinct from normal service behavior.
|
||||
- **Maintainability:** Medium. More explicit than inference, but still introduces a second-class meaning for service methods.
|
||||
|
||||
### Option C - Keep Builtin Root Public for Intrinsic-Backed SDK Modules
|
||||
- **Approach:** Continue exposing builtin const roots publicly and avoid service wrappers for intrinsic-backed modules such as `@sdk:input`.
|
||||
- **Pro:** Reuses the current lowering path with minimal compiler work.
|
||||
- **Con:** Conflicts directly with the intended SDK API shape and the user requirement that `Input` remain a normal public service.
|
||||
- **Maintainability:** Medium for the compiler, weak for the SDK/API design because it leaks implementation-facing reserved roots into public user code.
|
||||
|
||||
## Discussion
|
||||
|
||||
The user clarified that the target model is not a special "facade intrinsic" abstraction. The target model is ordinary service execution:
|
||||
|
||||
- SDK service methods should behave like normal PBS service methods;
|
||||
- they may call private reserved proxies such as `LowInput`;
|
||||
- they may allocate locals, perform intermediate work, and then return;
|
||||
- callers should not need direct access to the reserved proxy.
|
||||
|
||||
The core mismatch is therefore different from the original framing. `Log`, `Gfx`, and `Assets` work because the compiler already supports the relevant host-backed wrappers under the current SDK model. `Input` fails because intrinsic-backed SDK service bodies are not currently imported and lowered as ordinary executable code paths.
|
||||
|
||||
The compiler therefore likely needs first-class support for executable SDK service bodies, or an explicitly accepted alternative that is intentionally less general than normal service semantics.
|
||||
|
||||
## Resolution
|
||||
|
||||
Recommended direction: pursue **Option A - Treat SDK Service Bodies as Ordinary Executable Callables**.
|
||||
|
||||
Why:
|
||||
|
||||
- it matches the clarified requirement exactly: the public `service Input` should work as ordinary PBS code;
|
||||
- it allows locals and additional processing inside the method body without requiring special facade inference;
|
||||
- it keeps the private builtin proxy as an implementation detail rather than a user-facing surface;
|
||||
- it avoids introducing a second semantic class of service methods that only pretend to be ordinary services.
|
||||
|
||||
Suggested next step:
|
||||
|
||||
1. write a decision that defines the SDK executable model for service methods that call reserved proxies;
|
||||
2. specify how imported SDK service bodies are represented, lowered, and validated;
|
||||
3. derive an implementation plan from that accepted decision.
|
||||
|
||||
The discussion is now converged enough to move to the decision stage.
|
||||
@ -0,0 +1,123 @@
|
||||
---
|
||||
id: AGD-0017
|
||||
ticket: studio-editor-scope-guides-and-brace-anchoring
|
||||
title: Scope guides do Code Editor com active container, active scope e ancoragem estrutural
|
||||
status: accepted
|
||||
created: 2026-04-03
|
||||
resolved: 2026-04-03
|
||||
decision:
|
||||
tags:
|
||||
- studio
|
||||
- editor
|
||||
- scope-guides
|
||||
- braces
|
||||
- semantic-read
|
||||
- frontend-contract
|
||||
---
|
||||
|
||||
## Pain
|
||||
|
||||
Os scope guides do Code Editor hoje comunicam hierarquia de escopo, mas ainda falham em dois pontos visuais importantes:
|
||||
|
||||
- o guide nao comeca no `{` real do bloco; ele nasce aproximadamente no meio da linha inicial do simbolo;
|
||||
- o editor nao destaca o escopo em que o cursor esta, entao o usuario nao recebe feedback imediato de qual bloco esta ativo.
|
||||
|
||||
Isso deixa a feature util, mas incompleta. Em blocos aninhados, a leitura espacial do editor perde precisao justamente no momento em que o guide deveria ajudar mais.
|
||||
|
||||
## Context
|
||||
|
||||
Domain owner: `studio`
|
||||
Owner surfaces: `docs/specs/studio/5. Code Editor Workspace Specification.md`, `docs/specs/studio/7. Integrated LSP Semantic Read Phase Specification.md`
|
||||
Cross-domain input: frontends que produzem `documentSymbols()` para o Studio
|
||||
|
||||
Superficies relevantes hoje:
|
||||
|
||||
- `EditorWorkspace` monta os guides a partir de `analysis.documentSymbols()` e repassa o modelo para a paragraph graphic factory em `prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWorkspace.java`;
|
||||
- `EditorDocumentScopeGuideModel` projeta guias por linha com `depth` e `GuideSegmentKind`, mas nao carrega coluna nem offset estrutural do brace em `prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentScopeGuideModel.java`;
|
||||
- `EditorDocumentScopeGuideGraphicFactory` desenha `START` e `END` a partir do centro vertical da linha, nao de um token estrutural real, em `prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentScopeGuideGraphicFactory.java`;
|
||||
- os testes atuais do modelo validam apenas shape por linha, nao ancoragem precisa de brace nem estado ativo por cursor, em `prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorDocumentScopeGuideModelTest.java`.
|
||||
|
||||
Hoje o schema semantico exposto ao Studio entrega `documentSymbols` com `LspRangeDTO(startOffset, endOffset)`, o que e suficiente para inferir linhas de escopo, mas nao suficiente para afirmar onde o `{` de abertura e o `}` de fechamento realmente estao quando:
|
||||
|
||||
- o brace esta em outra coluna da mesma linha;
|
||||
- o header do simbolo se estende por mais de uma linha;
|
||||
- a linguagem tem formas de bloco em que o range do simbolo nao coincide com o token estrutural que queremos destacar.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- [x] O escopo ativo deve ser definido sempre como o menor range estrutural que contem o caret, ou existem casos em que o Studio deve promover o parent em vez do bloco mais interno?
|
||||
Fechado: `active scope` deve ser sempre o menor range estrutural que contem o caret.
|
||||
- [x] Como o Studio escolhe o `active container` quando o caret esta em blocos aninhados: funcao owner, tipo owner, ou simplesmente o menor ancestor acima do `active scope`?
|
||||
Fechado: `active container` deve ser o ancestor estrutural imediato acima do `active scope`, sem excecoes semanticas especiais para funcao, tipo ou outro owner.
|
||||
- [x] O guide deve ancorar no token estrutural real (`{`/`}`), ou basta uma heuristica local no editor que encontre o primeiro brace plausivel dentro do range do simbolo?
|
||||
Fechado: a ancoragem exata nao deve depender de heuristica textual local como contrato final; o objetivo correto e um anchor estrutural real.
|
||||
- [x] O contrato correto para essa precisao estrutural pertence ao frontend/LSP semantic read, ou o Studio deve derivar isso localmente a partir do texto do documento?
|
||||
Fechado: a precisao estrutural pertence ao frontend e deve ser exposta ao Studio como metadata semanticamente owned pelo produtor da linguagem.
|
||||
- [x] Como tratar linguagens que nao usam braces ou usam formas mistas de delimitacao, sem acoplar o Studio a PBS?
|
||||
Fechado: o contrato deve falar em `structural anchors` genericos, nao em braces como primitivo normativo.
|
||||
- [x] O schema atual de `documentSymbols` deve ser enriquecido, ou devemos introduzir uma surface estrutural paralela dedicada a guides/brackets?
|
||||
Fechado: devemos introduzir uma surface semantica propria para guides/anchors em vez de inflar `documentSymbols`.
|
||||
|
||||
## Options
|
||||
|
||||
### Option A - Heuristica local no Studio sobre os ranges atuais
|
||||
- **Approach:** Manter o contrato atual de `documentSymbols` e fazer o Studio procurar braces plausiveis dentro do texto/range de cada simbolo, alem de calcular o escopo ativo localmente pelo caret.
|
||||
- **Pro:** Menor custo inicial e pouca mudanca de contrato entre frontend e Studio.
|
||||
- **Con:** A heuristica tende a ser fragil para headers multiline, linguagens sem braces, ranges amplos demais e futuras linguagens com sintaxe diferente de PBS.
|
||||
- **Maintainability:** Media para baixa. Resolve rapido, mas cristaliza logica estrutural no host visual em vez de no owner da linguagem.
|
||||
|
||||
### Option B - Metadata estrutural explicita fornecida pelo frontend
|
||||
- **Approach:** Enriquecer o payload semantico consumido pelo Studio com posicoes estruturais explicitas para abertura/fechamento de blocos, ou com uma surface propria para scope/bracket guides; o editor usa esse contrato para ancoragem exata e para determinar o escopo ativo.
|
||||
- **Pro:** Fecha ownership correto no frontend, preserva neutralidade do Studio em relacao a sintaxe e permite ancoragem precisa sem heuristica textual fraca.
|
||||
- **Con:** Exige mudar o contrato entre semantic read e Studio, propagar implementacao para o frontend e decidir um schema que nao fique PBS-especifico.
|
||||
- **Maintainability:** Forte. A precisao estrutural fica no produtor semantico, onde o parse e o conhecimento de linguagem ja existem.
|
||||
|
||||
### Option C - Abordagem hibrida em duas waves
|
||||
- **Approach:** Implementar primeiro um gutter minimalista com no maximo duas linhas visiveis: `active container` e `active scope`, ambos calculados localmente a partir dos ranges atuais; tratar a ancoragem exata no `{` como uma extensao posterior baseada em metadata estrutural explicita.
|
||||
- **Pro:** Entrega contexto e foco ao mesmo tempo, com pouco ruido, sem bloquear na extensao de contrato e sem puxar o Studio para heuristica sintatica como solucao final.
|
||||
- **Con:** Exige definir semanticamente o que conta como `active container` e pode exigir retrabalho pequeno no modelo do editor quando a metadata estrutural chegar.
|
||||
- **Maintainability:** Boa, se a primeira wave permanecer estritamente limitada a duas linhas sem ancestry aberta.
|
||||
|
||||
## Discussion
|
||||
|
||||
Os dois sintomas nao tem o mesmo peso arquitetural.
|
||||
|
||||
Destacar o escopo ativo parece um problema majoritariamente local do editor, especialmente se a primeira wave for minimalista e restrita ao gutter:
|
||||
|
||||
- o `CodeArea` ja conhece caret/paragrafo atual;
|
||||
- o modelo atual ja conhece os ranges de escopo por linha;
|
||||
- em primeira aproximacao, o editor consegue descobrir qual range contem o cursor sem precisar saber a coluna exata do `{`;
|
||||
- renderizar no maximo duas linhas (`active container` e `active scope`) preserva contexto sem voltar ao mapa completo de ancestry.
|
||||
|
||||
Ja a ancoragem precisa do guide no brace parece um problema de contrato estrutural:
|
||||
|
||||
- o modelo atual nao sabe onde o brace real esta;
|
||||
- usar apenas `startOffset/endOffset` do simbolo empurra heuristica sintatica para dentro do Studio;
|
||||
- isso fica especialmente fraco num editor que ja foi desenhado para ser multi-frontend.
|
||||
|
||||
Por isso, vale separar claramente:
|
||||
|
||||
1. `active container` e `active scope` como comportamento visual local, minimalista, restrito ao gutter e derivado dos ranges atuais;
|
||||
2. `brace anchoring` como capacidade estrutural que talvez exija metadata adicional do frontend.
|
||||
|
||||
O risco de tentar resolver tudo localmente no Studio e transformar o host visual em pseudo-parser por linguagem.
|
||||
O risco oposto e bloquear uma melhoria visual simples do cursor enquanto esperamos um contrato estrutural maior ficar pronto.
|
||||
|
||||
## Resolution
|
||||
|
||||
Recommended direction: seguir com **Option C**.
|
||||
|
||||
A agenda deve convergir para uma decisao com os seguintes fechamentos:
|
||||
|
||||
1. a primeira wave deve manter o scope indicator no gutter, de forma minimalista e sem poluicao visual;
|
||||
2. a primeira wave pode renderizar no maximo duas linhas no gutter: `active container` e `active scope`, sem ancestry arbitraria e sem mapa completo de guides;
|
||||
3. `active scope` deve ser o menor range estrutural que contem o caret;
|
||||
4. `active container` deve ser o ancestor estrutural imediato acima do `active scope`;
|
||||
5. o destaque desses estados pelo cursor deve ser tratado como capacidade local do editor, usando os ranges semanticos ja disponiveis, desde que a regra fique language-agnostic;
|
||||
6. a apresentacao visual concreta desses indicadores deve continuar frontend-owned; o contrato do Studio nao deve fixar cores, tracos ou estilos especificos como regra normativa;
|
||||
7. a ancoragem exata do guide nao deve ser resolvida por heuristica textual como contrato final;
|
||||
8. a precisao estrutural deve ser exposta por metadata frontend-owned;
|
||||
9. essa metadata deve falar em `structural anchors` genericos, nao em braces como primitivo normativo;
|
||||
10. guides/anchors devem viver em uma surface semantica propria, em vez de estender `documentSymbols`.
|
||||
|
||||
Next step suggestion: converter esta agenda em uma `decision` que feche o boundary entre Studio e frontend para structural scope metadata, diferencie formalmente `active scope` de `brace anchor`, e declare a wave inicial aceitavel para o Code Editor.
|
||||
@ -1,159 +0,0 @@
|
||||
---
|
||||
id: DEC-0013
|
||||
ticket: pbs-service-facade-reserved-metadata
|
||||
title: Executable SDK Service Bodies for Builtin/Intrinsic-Backed Public Services
|
||||
status: accepted
|
||||
created: 2026-04-03
|
||||
accepted: 2026-04-03
|
||||
agenda: AGD-0016
|
||||
plans: [PLN-0029]
|
||||
tags: [compiler, pbs, sdk, stdlib, lowering, service, intrinsic, sdk-interface]
|
||||
---
|
||||
|
||||
## Decision
|
||||
|
||||
Domain owner: `compiler/pbs`
|
||||
|
||||
The PBS compiler SHALL support a restricted executable-service model inside `SDK_INTERFACE` sources.
|
||||
|
||||
Under this model:
|
||||
|
||||
1. public SDK `service` methods MAY contain ordinary PBS executable bodies;
|
||||
2. those bodies MAY call reserved hosts, reserved builtin const proxies, and reserved intrinsic-backed values;
|
||||
3. imported user callsites to eligible SDK service methods SHALL lower as ordinary callable invocations of the SDK service method body;
|
||||
4. intrinsic lowering SHALL occur inside the lowered SDK service body when the body calls the private reserved proxy;
|
||||
5. public user code MUST NOT be required to import or reference the private reserved proxy directly.
|
||||
|
||||
This decision explicitly rejects the requirement that intrinsic-backed public SDK services MUST lower directly from the user callsite to `CALL_INTRINSIC`.
|
||||
|
||||
For eligible SDK service methods, the normative lowering model is:
|
||||
|
||||
- public user callsite lowers as callable/service method invocation;
|
||||
- imported SDK service body lowers as executable PBS code;
|
||||
- reserved proxy calls inside that body lower through the existing intrinsic or host machinery;
|
||||
- returned values preserve the owner and chaining semantics established by the lowered reserved operation.
|
||||
|
||||
`@sdk:input` SHALL be supported by this model. A service body such as:
|
||||
|
||||
```pbs
|
||||
declare service Input {
|
||||
fn touch() -> InputTouch {
|
||||
let touch = LowInput.touch();
|
||||
return touch;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
MUST be valid as ordinary SDK service code, provided it remains within the supported restricted subset defined below.
|
||||
|
||||
## Rationale
|
||||
|
||||
This decision matches the intended SDK API shape:
|
||||
|
||||
- public SDK surfaces such as `Input` should be expressed as services when that is the product-facing abstraction;
|
||||
- private reserved builtins and builtin const proxies should remain implementation details;
|
||||
- SDK authors must be allowed to write normal service bodies with locals and intermediate processing rather than being forced into synthetic facade metadata or direct public builtin roots.
|
||||
|
||||
The alternative of explicit facade metadata on public service methods was rejected because it creates a second semantic class of services that only imitate ordinary PBS code. The alternative of keeping intrinsic roots public was rejected because it leaks reserved implementation surfaces into the user API.
|
||||
|
||||
## Technical Specification
|
||||
|
||||
### 1. Eligible Surface
|
||||
|
||||
The compiler SHALL define an explicit category of eligible executable SDK service methods.
|
||||
|
||||
An eligible executable SDK service method:
|
||||
|
||||
1. MUST be declared in a `SourceKind.SDK_INTERFACE` module;
|
||||
2. MUST belong to a `service` declaration;
|
||||
3. MUST remain within the restricted executable subset defined by compiler validation;
|
||||
4. MUST be importable as a callable body by user modules.
|
||||
|
||||
Non-eligible declarations in `SDK_INTERFACE` MUST continue to follow the existing non-executable interface rules.
|
||||
|
||||
### 2. SDK Interface Execution Boundary
|
||||
|
||||
`SDK_INTERFACE` SHALL remain non-executable by default.
|
||||
|
||||
The compiler SHALL introduce a narrow exception for eligible SDK service methods only. This exception MUST NOT implicitly generalize to arbitrary interface-level functions, globals, or unrestricted executable declarations.
|
||||
|
||||
### 3. Import Model
|
||||
|
||||
When a user module imports a public SDK service:
|
||||
|
||||
1. the imported semantic surface MUST continue to expose the service method signatures;
|
||||
2. the lowering pipeline MUST also have access to the executable body of each eligible imported SDK service method;
|
||||
3. a user callsite such as `Input.touch()` MUST be lowerable as an ordinary callable invocation of the imported SDK service method.
|
||||
|
||||
The compiler MUST NOT require special public facade metadata to connect the user callsite to the reserved intrinsic owner when the service body already expresses the call explicitly.
|
||||
|
||||
### 4. Lowering Model
|
||||
|
||||
For an eligible imported SDK service method:
|
||||
|
||||
1. the public callsite SHALL lower as a callable invocation;
|
||||
2. the imported SDK service body SHALL be lowered with the same executable-body discipline applied to ordinary PBS executable code, subject to the restricted subset;
|
||||
3. calls inside that body to reserved hosts SHALL continue to use host lowering;
|
||||
4. calls inside that body to reserved builtin const proxies SHALL continue to use intrinsic lowering;
|
||||
5. any returned reserved value SHALL preserve the return owner and chaining semantics inferred from the lowered reserved call.
|
||||
|
||||
As a result:
|
||||
|
||||
- `Input.touch()` MAY lower to a callable invocation of the imported SDK method;
|
||||
- `LowInput.touch()` inside the SDK body SHALL lower to the intrinsic owner `input.touch`;
|
||||
- chained user code such as `Input.touch().x()` and `Input.pad().a().pressed()` MUST remain valid when the returned owner chain is supported by the reserved metadata.
|
||||
|
||||
### 5. Restricted Executable Subset
|
||||
|
||||
The compiler SHALL validate eligible executable SDK service methods against an explicit restricted subset.
|
||||
|
||||
At minimum, the first supported subset MUST permit:
|
||||
|
||||
- local bindings;
|
||||
- ordinary return statements;
|
||||
- calls to reserved hosts;
|
||||
- calls to reserved builtin const proxies and their intrinsic-return values;
|
||||
- straightforward expression composition needed for wrapper-style service methods.
|
||||
|
||||
The first supported subset MUST NOT silently permit unsupported executable constructs. If a construct is outside the supported subset, the compiler MUST emit a dedicated diagnostic.
|
||||
|
||||
Whether control flow beyond straightforward wrapper composition is included in the first wave SHALL be decided in planning and implementation, but the compiler MUST validate the boundary explicitly rather than relying on accidental behavior.
|
||||
|
||||
### 6. Diagnostics
|
||||
|
||||
The compiler SHALL add dedicated diagnostics for executable SDK service bodies that cannot be imported or lowered safely.
|
||||
|
||||
These diagnostics MUST distinguish this failure mode from generic unresolved callee failures.
|
||||
|
||||
At minimum, diagnostics SHALL cover:
|
||||
|
||||
- SDK service bodies that use unsupported executable constructs;
|
||||
- imported SDK service methods that are not eligible for executable lowering;
|
||||
- inconsistencies between an imported SDK service signature and the lowered executable body shape;
|
||||
- reserved proxy use that cannot preserve required return-owner or chaining behavior.
|
||||
|
||||
### 7. Tests and Conformance
|
||||
|
||||
The compiler test suite SHALL be updated to reflect the new normative model.
|
||||
|
||||
Tests MUST cover:
|
||||
|
||||
1. public SDK service callsites lowering successfully as callable invocations;
|
||||
2. intrinsic lowering occurring inside the imported SDK service body;
|
||||
3. returned reserved owners preserving chained method access for values such as `InputTouch` and `InputPad`;
|
||||
4. use of locals and intermediate processing inside SDK service bodies;
|
||||
5. dedicated diagnostics for unsupported executable SDK service bodies.
|
||||
|
||||
Existing tests that assume the public `Input` callsite itself MUST resolve directly to an intrinsic SHALL be revised to match this decision.
|
||||
|
||||
## Constraints
|
||||
|
||||
- This decision applies to `compiler/pbs` and to SDK surfaces loaded through `SDK_INTERFACE`.
|
||||
- This decision does not authorize arbitrary executable code throughout interface modules.
|
||||
- This decision does not require public exposure of private reserved builtin roots.
|
||||
- This decision does not replace the existing host-backed SDK service model; it extends the compiler so intrinsic-backed SDK services can use ordinary service bodies.
|
||||
- Any future extension of the restricted executable subset MUST be treated as a follow-up decision or explicit revision if it changes the initial boundary materially.
|
||||
|
||||
## Revision Log
|
||||
|
||||
- 2026-04-03: Initial draft from AGD-0016.
|
||||
@ -0,0 +1,147 @@
|
||||
---
|
||||
id: DEC-0014
|
||||
ticket: studio-editor-scope-guides-and-brace-anchoring
|
||||
title: Code Editor active container, active scope, and frontend-owned structural anchors
|
||||
status: accepted
|
||||
created: 2026-04-03
|
||||
accepted: 2026-04-03
|
||||
agenda: AGD-0017
|
||||
plans:
|
||||
- PLN-0030
|
||||
- PLN-0031
|
||||
- PLN-0032
|
||||
tags:
|
||||
- studio
|
||||
- editor
|
||||
- scope-guides
|
||||
- semantic-read
|
||||
- frontend-contract
|
||||
- structural-anchors
|
||||
---
|
||||
|
||||
## Decision
|
||||
|
||||
The Studio Code Editor SHALL keep scope indicators in the gutter.
|
||||
|
||||
The initial wave SHALL render at most two simultaneous structural indicators:
|
||||
|
||||
1. `active container`
|
||||
2. `active scope`
|
||||
|
||||
The Studio MUST NOT render the full ancestry map or the current multi-guide stack as the default active-scope presentation.
|
||||
|
||||
`active scope` SHALL be defined as the smallest structural range that contains the caret.
|
||||
|
||||
`active container` SHALL be defined as the immediate structural ancestor of `active scope`.
|
||||
|
||||
The Studio SHALL determine `active container` and `active scope` locally from semantic ranges already available to the editor, provided that the rule remains language-agnostic.
|
||||
|
||||
The concrete visual presentation of these two indicators SHALL remain frontend-owned. The Studio contract MUST NOT normatively fix colors, stroke style, dashed versus solid rendering, or equivalent stylistic choices.
|
||||
|
||||
Exact guide anchoring MUST NOT rely on local textual heuristics as the final contract. Exact anchoring SHALL be backed by frontend-owned structural metadata.
|
||||
|
||||
That structural metadata SHALL be expressed as generic `structural anchors`, not as PBS-specific brace semantics. The contract MUST remain language-agnostic and applicable to languages that do not use `{` / `}` as primary delimiters.
|
||||
|
||||
Structural anchors and guide-specific structural data SHALL live in a dedicated semantic surface. They MUST NOT be folded into `documentSymbols` as an overloaded extension of the outline/navigation payload.
|
||||
|
||||
## Rationale
|
||||
|
||||
The current gutter guides already prove that structural ranges are useful, but the existing presentation is too noisy and not precise enough:
|
||||
|
||||
- multiple simultaneous guide columns create visual pollution;
|
||||
- the current guide start/end positions are derived from symbol line ranges, not from exact structural anchors;
|
||||
- the current model is good enough to identify containing ranges, but not good enough to express precise opening/closing structure.
|
||||
|
||||
The accepted direction separates two concerns that have different architectural weights:
|
||||
|
||||
- `active container` and `active scope` are local editor-state projections and can be derived from existing semantic ranges;
|
||||
- exact structural anchoring is a language-owned concern and belongs in frontend metadata rather than Studio-local syntax heuristics.
|
||||
|
||||
Restricting the default visualization to at most two indicators preserves context without reviving the clutter of a full ancestry map.
|
||||
|
||||
Keeping visual styling frontend-owned preserves the existing design direction in which semantic presentation belongs to the frontend rather than to Studio-global hardcoded rendering rules.
|
||||
|
||||
## Technical Specification
|
||||
|
||||
### 1. Gutter Indicator Model
|
||||
|
||||
The editor gutter SHALL support exactly two semantic slots for active structural indication:
|
||||
|
||||
- `activeContainer`
|
||||
- `activeScope`
|
||||
|
||||
The first implementation wave MAY omit `activeContainer` when no valid ancestor exists. It MUST NOT synthesize a non-existent container.
|
||||
|
||||
The editor MUST compute `activeScope` by selecting the smallest structural range that contains the caret offset.
|
||||
|
||||
The editor MUST compute `activeContainer` by selecting the immediate parent structural range of `activeScope`.
|
||||
|
||||
The editor MUST NOT promote a higher semantic owner such as function, type, or module when a nearer structural ancestor exists.
|
||||
|
||||
### 2. Presentation Ownership
|
||||
|
||||
The editor SHALL expose enough state for the presentation layer to distinguish:
|
||||
|
||||
- container indicator
|
||||
- scope indicator
|
||||
|
||||
The decision intentionally leaves the following presentation properties non-normative:
|
||||
|
||||
- color
|
||||
- opacity
|
||||
- stroke thickness
|
||||
- dashed versus solid treatment
|
||||
- cap styling
|
||||
- equivalent visual emphasis rules
|
||||
|
||||
Those choices SHALL remain frontend-owned or presentation-owned.
|
||||
|
||||
### 3. Structural Anchoring
|
||||
|
||||
Exact anchor positions for guide start/end SHALL come from semantic structural metadata produced by the language/frontend side.
|
||||
|
||||
Studio MUST treat those anchors as generic structural positions rather than brace-specific tokens.
|
||||
|
||||
The metadata model MUST support languages where structural delimiters are:
|
||||
|
||||
- braces
|
||||
- keywords
|
||||
- indentation-derived constructs
|
||||
- mixed delimiter schemes
|
||||
|
||||
### 4. Semantic Surface Boundary
|
||||
|
||||
`documentSymbols` SHALL remain the outline/navigation surface.
|
||||
|
||||
Structural guide metadata SHALL be introduced as a distinct semantic surface dedicated to:
|
||||
|
||||
- structural ranges
|
||||
- structural parent/child relationships when needed
|
||||
- structural anchors used by guide rendering
|
||||
|
||||
Studio MUST NOT infer the final structural contract by scanning source text for likely braces inside symbol ranges.
|
||||
|
||||
Local heuristics MAY exist only as temporary debugging aids during development. They MUST NOT become the canonical production contract.
|
||||
|
||||
### 5. Propagation Targets
|
||||
|
||||
This decision SHALL propagate to:
|
||||
|
||||
- Studio editor implementation in `prometeu-studio`
|
||||
- Studio-facing semantic read contracts in `docs/specs/studio/7. Integrated LSP Semantic Read Phase Specification.md`
|
||||
- Code Editor presentation and interaction behavior in `docs/specs/studio/5. Code Editor Workspace Specification.md`
|
||||
- frontend-produced semantic payloads that eventually expose structural anchors
|
||||
- tests covering active scope selection, active container selection, and anchor-aware rendering
|
||||
|
||||
## Constraints
|
||||
|
||||
- The decision does not authorize inline indentation-column guides inside the main code text area as the primary first-wave solution.
|
||||
- The decision does not authorize restoring the existing full stacked guide rendering as the default active-scope UX.
|
||||
- The decision does not fix a specific visual palette or theme mapping.
|
||||
- The decision does not yet define the exact serialized schema of the future structural-anchor surface; that belongs in plan/spec work derived from this decision.
|
||||
- The decision does not require immediate availability of structural anchors to ship the first-wave `active container` and `active scope` gutter behavior.
|
||||
|
||||
## Revision Log
|
||||
|
||||
- 2026-04-03: Initial draft from AGD-0017.
|
||||
- 2026-04-03: Accepted and split into execution plans PLN-0030, PLN-0031, and PLN-0032.
|
||||
@ -1,181 +0,0 @@
|
||||
---
|
||||
id: PLN-0029
|
||||
ticket: pbs-service-facade-reserved-metadata
|
||||
title: Implement Restricted Executable SDK Service Bodies for Intrinsic-Backed Public Services
|
||||
status: review
|
||||
created: 2026-04-03
|
||||
completed:
|
||||
tags: [compiler, pbs, sdk, stdlib, lowering, service, intrinsic, sdk-interface]
|
||||
---
|
||||
|
||||
## Objective
|
||||
|
||||
Implement the `DEC-0013` model for restricted executable SDK service bodies so public SDK services such as `@sdk:input` compile as ordinary PBS service code while preserving host and intrinsic lowering inside imported SDK service bodies.
|
||||
|
||||
## Background
|
||||
|
||||
`DEC-0013` accepts the model where:
|
||||
|
||||
- `SDK_INTERFACE` remains non-executable by default;
|
||||
- eligible SDK `service` methods gain a narrow executable path;
|
||||
- user callsites lower as ordinary callable invocations of imported SDK service methods;
|
||||
- host and intrinsic lowering continue to happen inside the imported SDK service body;
|
||||
- returned reserved values preserve owner and chaining behavior;
|
||||
- dedicated diagnostics replace generic unresolved-callee failures for unsupported cases.
|
||||
|
||||
The current compiler exposes imported SDK service signatures but does not provide an executable-body path for intrinsic-backed service wrappers such as `Input.touch()` and `Input.pad()`. The plan below closes that gap without generalizing arbitrary executable code across all interface declarations.
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
- Defining and validating eligibility rules for executable SDK service methods.
|
||||
- Representing eligible SDK service method bodies so imported user callsites can lower them as ordinary callable invocations.
|
||||
- Lowering imported SDK service bodies under a restricted executable subset.
|
||||
- Preserving owner propagation and chained reserved behavior for returned intrinsic-backed values.
|
||||
- Adding dedicated diagnostics for unsupported executable SDK service bodies.
|
||||
- Updating frontend and integration tests to reflect the accepted model.
|
||||
|
||||
### Excluded
|
||||
- General executable support for arbitrary `SDK_INTERFACE` functions, globals, or unrestricted declarations.
|
||||
- Public exposure of private reserved builtin roots.
|
||||
- Expansion of the restricted executable subset beyond the first explicitly supported wave unless needed to satisfy `DEC-0013`.
|
||||
- Editorial changes to unrelated SDK modules.
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Step 1 - Define the Executable SDK Service Eligibility Boundary
|
||||
|
||||
**What:** Introduce the compiler-side concept of an eligible executable SDK service method and enforce the first restricted subset accepted by `DEC-0013`.
|
||||
|
||||
**How:** Add validation logic that runs on `SourceKind.SDK_INTERFACE` service methods and classifies each method as either executable/importable or rejected with a dedicated diagnostic. The first supported subset must explicitly allow local bindings, ordinary returns, calls to reserved hosts, calls to reserved builtin const proxies, intrinsic-return chaining, and straightforward wrapper-style expression composition. Any construct outside that subset must fail deterministically with a dedicated diagnostic instead of reaching generic lowering failure.
|
||||
|
||||
**File(s):**
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsDeclarationSemanticsValidator.java`
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/...` as needed for executable-subset validation
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/PbsSemanticsErrors.java`
|
||||
|
||||
### Step 2 - Expose Imported SDK Service Bodies to the Lowering Pipeline
|
||||
|
||||
**What:** Extend imported SDK context assembly so eligible SDK service methods are available not only as callable signatures but also as executable bodies that user modules can target.
|
||||
|
||||
**How:** Enrich the imported semantic/lowering context with per-method executable metadata for eligible SDK service methods, including module identity, owning service, signature shape, AST/body reference, and any lowering metadata required to compile the imported method body exactly once in a controlled way. Preserve the existing lightweight path for non-executable interface declarations.
|
||||
|
||||
**File(s):**
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/services/PbsImportedSemanticContextService.java`
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/services/PbsImportedSemanticContext.java`
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/PbsFrontendCompiler.java`
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/messages/FESurfaceContext.java`
|
||||
|
||||
### Step 3 - Lower Public SDK Service Calls as Callable Invocations of Imported Bodies
|
||||
|
||||
**What:** Make user callsites such as `Input.touch()` and `Input.pad()` resolve as callable invocations of imported executable SDK service methods.
|
||||
|
||||
**How:** Update callable resolution and lowering metadata so eligible imported SDK service methods participate as ordinary callable targets with executable bodies rather than metadata-only surfaces. Ensure public service callsites resolve to `CALL_FUNC`-style lowering when appropriate and do not require public facade metadata or direct builtin-root identity at the callsite itself.
|
||||
|
||||
**File(s):**
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/lowering/PbsExecutableCallsiteEmitter.java`
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/lowering/PbsExecutableLoweringService.java`
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/lowering/PbsExecutableLoweringContext.java`
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/lowering/PbsExecutableLoweringModels.java`
|
||||
|
||||
### Step 4 - Lower Imported SDK Service Method Bodies Under the Restricted Subset
|
||||
|
||||
**What:** Add the executable-body lowering path for eligible imported SDK service methods so reserved host and intrinsic calls continue to lower inside the SDK method body itself.
|
||||
|
||||
**How:** Reuse as much of the existing executable lowering pipeline as possible, but constrain it to imported eligible SDK service methods. Ensure the lowering path supports locals, returns, reserved host calls, reserved builtin const proxy calls, and direct wrapper-style logic. Prevent accidental lowering of unsupported or non-eligible interface code.
|
||||
|
||||
**File(s):**
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/lowering/PbsExecutableBodyLowerer.java`
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/lowering/PbsExecutableMetadataIndexFactory.java`
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/lowering/PbsExecutableCallsiteEmitter.java`
|
||||
|
||||
### Step 5 - Preserve Return Owner and Chaining Semantics Across SDK Service Returns
|
||||
|
||||
**What:** Ensure values returned by imported SDK service methods keep the same reserved owner identity and chaining behavior as the intrinsic/host-backed values produced inside the method body.
|
||||
|
||||
**How:** Propagate owner metadata from the lowered reserved call through the return path of the imported SDK service method so downstream user expressions such as `Input.touch().x()` and `Input.pad().a().pressed()` retain resolvable chained semantics. Add targeted validation when the compiler cannot preserve this owner chain safely.
|
||||
|
||||
**File(s):**
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/lowering/PbsExecutableMetadataIndexFactory.java`
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/lowering/PbsExecutableCallsiteEmitter.java`
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/lowering/PbsExecutableLoweringContext.java`
|
||||
|
||||
### Step 6 - Introduce Dedicated Diagnostics for Non-Lowerable SDK Service Bodies
|
||||
|
||||
**What:** Replace generic unresolved-callee failures with dedicated diagnostics for unsupported executable SDK service bodies.
|
||||
|
||||
**How:** Add explicit error codes and reporting paths for:
|
||||
- non-eligible executable SDK service methods;
|
||||
- unsupported constructs inside executable SDK service bodies;
|
||||
- signature/body inconsistencies for imported executable SDK service methods;
|
||||
- unpreservable reserved owner/chaining cases.
|
||||
|
||||
Wire these diagnostics so failures are emitted at validation/lowering time with stable code identity and source spans.
|
||||
|
||||
**File(s):**
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/PbsSemanticsErrors.java`
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/lowering/...`
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/...` diagnostic contract tests
|
||||
|
||||
### Step 7 - Update and Expand Tests to Match DEC-0013
|
||||
|
||||
**What:** Align the PBS frontend and pipeline test suite with the accepted executable SDK service body model.
|
||||
|
||||
**How:** Update existing `@sdk:input` tests that currently assume public callsites lower directly to intrinsics. Add coverage for:
|
||||
- public `Input.touch()` and `Input.pad()` callsites lowering successfully through imported SDK service bodies;
|
||||
- intrinsic lowering occurring inside those imported bodies;
|
||||
- locals and intermediate processing inside SDK service bodies;
|
||||
- returned owner and chained calls such as `touch.x()` and `Input.pad().a().pressed()`;
|
||||
- dedicated diagnostics when an executable SDK service body violates the restricted subset.
|
||||
|
||||
**File(s):**
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/services/PBSFrontendPhaseServiceTest.java`
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsFrontendCompilerTest.java`
|
||||
- `prometeu-compiler/frontends/prometeu-frontend-pbs/src/test/java/p/studio/compiler/pbs/PbsGateUSdkInterfaceConformanceTest.java`
|
||||
- `prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/integration/MainProjectPipelineIntegrationTest.java`
|
||||
- related diagnostic/lowering tests as needed
|
||||
|
||||
## Test Requirements
|
||||
|
||||
### Unit Tests
|
||||
|
||||
- Validation tests for executable SDK service method eligibility and restricted-subset rejection.
|
||||
- Lowering tests for imported SDK service callsites resolving as callable invocations.
|
||||
- Lowering tests for intrinsic and host operations inside imported SDK service bodies.
|
||||
- Owner-propagation tests for returned reserved values and chained member calls.
|
||||
- Diagnostic identity tests for each new SDK executable-service failure mode.
|
||||
|
||||
### Integration Tests
|
||||
|
||||
- Pipeline test proving `test-projects/main` compiles successfully when `@sdk:input` is expressed as a public service over a private builtin proxy.
|
||||
- Integration coverage for mixed SDK modules so existing host-backed wrappers (`Log`, `Gfx`, `Assets`) continue to work unchanged alongside the new intrinsic-backed service model.
|
||||
|
||||
### Manual Verification
|
||||
|
||||
- Run the compile pipeline against the main test project with the service-based `@sdk:input` shape.
|
||||
- Verify the resulting IR contains callable lowering for the public SDK service entrypoint and intrinsic lowering inside the imported SDK service body.
|
||||
- Confirm unsupported SDK executable constructs emit the new dedicated diagnostics rather than `E_SEM_EXEC_LOWERING_UNRESOLVED_CALLEE`.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Eligible SDK service methods in `SDK_INTERFACE` can be imported with executable bodies while the rest of the interface surface remains non-executable by default.
|
||||
- [ ] Public callsites such as `Input.touch()` and `Input.pad()` lower as callable invocations of imported SDK service methods.
|
||||
- [ ] Reserved host and intrinsic calls inside imported SDK service bodies lower correctly through the existing reserved machinery.
|
||||
- [ ] Returned reserved values preserve owner/chaining semantics for expressions such as `Input.touch().x()` and `Input.pad().a().pressed()`.
|
||||
- [ ] Unsupported executable SDK service bodies fail with dedicated diagnostics instead of generic unresolved-callee errors.
|
||||
- [ ] Existing host-backed SDK services continue to compile without regression.
|
||||
- [ ] Frontend and integration tests reflect and enforce the accepted model from `DEC-0013`.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Accepted decision: `DEC-0013`.
|
||||
- Existing reserved metadata and intrinsic lowering infrastructure in the PBS frontend.
|
||||
- Existing imported semantic-context assembly for SDK modules.
|
||||
- Existing host-backed SDK service behavior must remain as the regression baseline.
|
||||
|
||||
## Risks
|
||||
|
||||
- The executable-service exception for `SDK_INTERFACE` could accidentally broaden into support for arbitrary interface code if the eligibility boundary is not enforced centrally.
|
||||
- Owner propagation across imported SDK service returns may require careful threading of metadata through call/return paths and could regress chained intrinsic resolution if partially implemented.
|
||||
- Reusing ordinary executable lowering for imported SDK bodies may expose assumptions that currently only hold for project-local executable functions.
|
||||
- Test expectations that currently assert direct intrinsic callsites may need careful revision to avoid preserving obsolete invariants.
|
||||
@ -0,0 +1,137 @@
|
||||
---
|
||||
id: PLN-0030
|
||||
ticket: studio-editor-scope-guides-and-brace-anchoring
|
||||
title: Wave 1 editor implementation for active container and active scope gutter indicators
|
||||
status: review
|
||||
created: 2026-04-03
|
||||
completed:
|
||||
tags:
|
||||
- studio
|
||||
- editor
|
||||
- scope-guides
|
||||
- gutter
|
||||
- active-scope
|
||||
---
|
||||
|
||||
## Objective
|
||||
|
||||
Implement the first Studio editor wave mandated by DEC-0014: a gutter-based active-structure indicator that renders at most two simultaneous states, `activeContainer` and `activeScope`, computed locally from existing structural ranges.
|
||||
|
||||
## Background
|
||||
|
||||
The current editor renders a stacked multi-guide gutter model derived from document symbols. DEC-0014 replaces that default with a constrained active-state presentation:
|
||||
|
||||
- keep scope indicators in the gutter;
|
||||
- compute `activeScope` as the smallest structural range containing the caret;
|
||||
- compute `activeContainer` as the immediate ancestor of `activeScope`;
|
||||
- render at most two indicators;
|
||||
- keep concrete styling frontend-owned.
|
||||
|
||||
This plan intentionally covers only the editor-local behavior that can ship without structural-anchor metadata.
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
- Replace the default stacked guide presentation with an active-state model in `prometeu-studio`.
|
||||
- Extend the editor scope guide model so it can resolve `activeScope` and `activeContainer` from the caret offset.
|
||||
- Update gutter rendering to draw no more than two structural indicators.
|
||||
- Expose semantic slots or equivalent rendering states that allow presentation to distinguish container versus scope.
|
||||
- Add tests for active-scope selection and active-container selection.
|
||||
|
||||
### Excluded
|
||||
- Exact anchor positioning from structural metadata.
|
||||
- Changes to frontend payload schemas.
|
||||
- Changes to semantic read transport contracts outside what the editor already consumes.
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Step 1 - Refactor the local scope-guide model around structural containment
|
||||
|
||||
**What:** Introduce a model capable of resolving structural containment from caret position and expressing the two active semantic states.
|
||||
|
||||
**How:** Update `EditorDocumentScopeGuideModel` so it retains enough structural information to:
|
||||
- map paragraph and caret offsets back to containing structural ranges;
|
||||
- select the smallest containing range as `activeScope`;
|
||||
- select the immediate parent as `activeContainer`;
|
||||
- expose a paragraph-level view suitable for rendering only the relevant two indicators.
|
||||
|
||||
Avoid any logic that promotes higher semantic owners such as function or type when a nearer ancestor exists.
|
||||
|
||||
**File(s):**
|
||||
- `prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentScopeGuideModel.java`
|
||||
- supporting editor model classes if extraction improves clarity
|
||||
|
||||
### Step 2 - Bind caret movement to active-state recomputation
|
||||
|
||||
**What:** Recompute active structural state as the caret moves.
|
||||
|
||||
**How:** Update `EditorWorkspace` to observe caret position changes from the `CodeArea`, resolve the current active structural state through the model, and refresh paragraph graphics when the active state changes.
|
||||
|
||||
The implementation must remain language-agnostic and rely only on structural ranges already available through the semantic read result.
|
||||
|
||||
**File(s):**
|
||||
- `prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorWorkspace.java`
|
||||
|
||||
### Step 3 - Replace stacked guide rendering with a two-slot gutter renderer
|
||||
|
||||
**What:** Redesign the gutter renderer so the default active-state UX shows at most `activeContainer` and `activeScope`.
|
||||
|
||||
**How:** Update `EditorDocumentScopeGuideGraphicFactory` to consume the active-state data and render:
|
||||
- no indicator when no structural range contains the caret;
|
||||
- one indicator when only `activeScope` exists;
|
||||
- two distinguishable indicators when both `activeContainer` and `activeScope` exist.
|
||||
|
||||
Do not hardcode semantic color contracts into decision logic. The renderer may expose separate style classes, paint roles, or equivalent slots so that presentation styling remains decoupled from the semantic model.
|
||||
|
||||
**File(s):**
|
||||
- `prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentScopeGuideGraphicFactory.java`
|
||||
- related editor presentation stylesheet hooks if necessary
|
||||
|
||||
### Step 4 - Update editor tests for the new active-state behavior
|
||||
|
||||
**What:** Replace tests that validate the old stacked guide model as the default expectation.
|
||||
|
||||
**How:** Add or update tests that cover:
|
||||
- smallest-containing-range selection for `activeScope`;
|
||||
- immediate-parent selection for `activeContainer`;
|
||||
- omission of `activeContainer` when no parent exists;
|
||||
- rendering behavior constrained to at most two semantic indicators.
|
||||
|
||||
**File(s):**
|
||||
- `prometeu-studio/src/test/java/p/studio/workspaces/editor/EditorDocumentScopeGuideModelTest.java`
|
||||
- renderer tests or workspace tests if such coverage exists or needs to be introduced
|
||||
|
||||
## Test Requirements
|
||||
|
||||
### Unit Tests
|
||||
- Model tests for nested ranges and caret placement transitions.
|
||||
- Tests that prove immediate-parent selection rather than semantic-owner promotion.
|
||||
- Tests that prove no more than two semantic gutter indicators are active at once.
|
||||
|
||||
### Integration Tests
|
||||
- Editor workspace tests that move the caret through nested structures and validate gutter state transitions if an existing JavaFX/editor harness is available.
|
||||
|
||||
### Manual Verification
|
||||
- Open a frontend-backed document with nested scopes.
|
||||
- Move the caret across siblings, parent blocks, and root-level declarations.
|
||||
- Confirm that the gutter shows only `activeScope` and optional `activeContainer`.
|
||||
- Confirm that no full ancestry stack is shown by default.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] The default editor gutter no longer renders the old full stacked active-scope presentation.
|
||||
- [ ] `activeScope` is selected as the smallest structural range containing the caret.
|
||||
- [ ] `activeContainer` is selected as the immediate structural ancestor of `activeScope`.
|
||||
- [ ] The editor renders at most two active semantic indicators in the gutter.
|
||||
- [ ] The implementation remains language-agnostic and uses only existing structural ranges.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Accepted decision `DEC-0014-studio-editor-active-scope-and-structural-anchors.md`
|
||||
- Existing semantic range payloads already consumed by `EditorWorkspace`
|
||||
|
||||
## Risks
|
||||
|
||||
- Paragraph-graphic refreshes may become visually noisy or too expensive if caret updates are not throttled or diffed.
|
||||
- Existing tests may encode the previous stacked-gutter behavior and need coordinated updates.
|
||||
- The current model may need deeper refactoring than expected if it stores only per-line segments and not enough structural identity information.
|
||||
@ -0,0 +1,112 @@
|
||||
---
|
||||
id: PLN-0031
|
||||
ticket: studio-editor-scope-guides-and-brace-anchoring
|
||||
title: Structural anchor semantic surface specification for Studio semantic read
|
||||
status: review
|
||||
created: 2026-04-03
|
||||
completed:
|
||||
tags:
|
||||
- studio
|
||||
- specs
|
||||
- semantic-read
|
||||
- structural-anchors
|
||||
- frontend-contract
|
||||
---
|
||||
|
||||
## Objective
|
||||
|
||||
Specify the dedicated semantic surface required by DEC-0014 for structural anchors and guide-specific structural metadata, without overloading `documentSymbols`.
|
||||
|
||||
## Background
|
||||
|
||||
DEC-0014 requires exact guide anchoring to come from frontend-owned structural metadata expressed as generic structural anchors. The decision explicitly forbids treating local text scanning as the final contract and explicitly keeps `documentSymbols` as the outline/navigation surface.
|
||||
|
||||
This plan covers the normative documentation and contract-shaping work needed before frontend payloads and Studio consumers can converge on a stable schema.
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
- Define the semantic-read contract boundary for structural anchors in Studio specs.
|
||||
- Specify a dedicated surface for structural guide metadata separate from `documentSymbols`.
|
||||
- Define the normative semantics of structural ranges, parentage, and anchors in language-agnostic terms.
|
||||
- Define how the Studio editor consumes that surface for exact guide start/end anchoring.
|
||||
|
||||
### Excluded
|
||||
- Frontend implementation of the new payload.
|
||||
- Studio code changes that consume the new payload.
|
||||
- Theme or visual styling decisions.
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Step 1 - Update the semantic-read specification with a dedicated structural-anchor surface
|
||||
|
||||
**What:** Add a normative section to the Studio semantic-read specification defining a new dedicated semantic surface for guide-oriented structural metadata.
|
||||
|
||||
**How:** Update the semantic-read spec to state that:
|
||||
- `documentSymbols` remains the outline/navigation surface;
|
||||
- structural guide metadata is delivered through a separate payload or surface;
|
||||
- the surface must support structural ranges, parent/child relations when required, and exact anchors for guide rendering;
|
||||
- the contract is language-agnostic and must not encode brace-only assumptions.
|
||||
|
||||
**File(s):**
|
||||
- `docs/specs/studio/7. Integrated LSP Semantic Read Phase Specification.md`
|
||||
|
||||
### Step 2 - Update the Code Editor workspace specification for active indicators and anchor consumption
|
||||
|
||||
**What:** Propagate DEC-0014 into the Code Editor workspace specification.
|
||||
|
||||
**How:** Update the editor spec so it normatively states:
|
||||
- the gutter remains the primary scope-indicator surface for the initial wave;
|
||||
- the editor renders at most two active indicators: `activeContainer` and `activeScope`;
|
||||
- exact start/end anchoring depends on the structural-anchor semantic surface;
|
||||
- concrete visual treatment remains frontend-owned.
|
||||
|
||||
**File(s):**
|
||||
- `docs/specs/studio/5. Code Editor Workspace Specification.md`
|
||||
|
||||
### Step 3 - Define the schema and semantic invariants of structural anchors
|
||||
|
||||
**What:** Describe the minimum schema and invariants needed for frontend and Studio implementations to interoperate safely.
|
||||
|
||||
**How:** Specify, at minimum:
|
||||
- what a structural range represents;
|
||||
- how parentage is expressed or inferred;
|
||||
- what anchor positions represent;
|
||||
- how the model behaves for languages with braces, keywords, indentation, or mixed delimiters;
|
||||
- which invariants tests and future implementations must honor.
|
||||
|
||||
If a separate schema subsection or appendix is needed, add it within the relevant spec surface rather than inventing an ad hoc note.
|
||||
|
||||
**File(s):**
|
||||
- `docs/specs/studio/7. Integrated LSP Semantic Read Phase Specification.md`
|
||||
- `docs/specs/studio/5. Code Editor Workspace Specification.md` if editor-facing invariants need reiteration
|
||||
|
||||
## Test Requirements
|
||||
|
||||
### Unit Tests
|
||||
- Not applicable at this spec-only stage.
|
||||
|
||||
### Integration Tests
|
||||
- Not applicable at this spec-only stage.
|
||||
|
||||
### Manual Verification
|
||||
- Review the spec text against DEC-0014 and confirm every normative requirement is represented.
|
||||
- Confirm the spec does not overload `documentSymbols`.
|
||||
- Confirm the spec speaks in generic structural anchors rather than brace-specific terms.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] The semantic-read spec defines a dedicated structural-anchor surface separate from `documentSymbols`.
|
||||
- [ ] The Code Editor spec reflects the two-indicator gutter model and frontend-owned presentation.
|
||||
- [ ] The contract is language-agnostic and does not assume braces as the only structural delimiter.
|
||||
- [ ] The spec text is sufficient for a frontend and Studio implementation plan without reopening DEC-0014.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Accepted decision `DEC-0014-studio-editor-active-scope-and-structural-anchors.md`
|
||||
- Existing Studio specs in `docs/specs/studio`
|
||||
|
||||
## Risks
|
||||
|
||||
- Over-specifying serialization too early may constrain future frontends unnecessarily.
|
||||
- Under-specifying parentage and anchor semantics may leave ambiguous implementation choices and force a decision revisit.
|
||||
@ -0,0 +1,126 @@
|
||||
---
|
||||
id: PLN-0032
|
||||
ticket: studio-editor-scope-guides-and-brace-anchoring
|
||||
title: Frontend structural-anchor payload propagation and anchor-aware test coverage
|
||||
status: review
|
||||
created: 2026-04-03
|
||||
completed:
|
||||
tags:
|
||||
- studio
|
||||
- frontend
|
||||
- semantic-read
|
||||
- structural-anchors
|
||||
- tests
|
||||
---
|
||||
|
||||
## Objective
|
||||
|
||||
Implement and validate frontend-produced structural-anchor payloads and the Studio-side test coverage required to support exact anchor-aware gutter rendering after the contract defined in DEC-0014 and its derived specs is in place.
|
||||
|
||||
## Background
|
||||
|
||||
DEC-0014 splits execution into two tracks:
|
||||
|
||||
- a first local editor wave based on existing structural ranges;
|
||||
- a later exact-anchoring wave backed by frontend-owned structural metadata delivered through a dedicated semantic surface.
|
||||
|
||||
This plan covers the propagation work after the semantic surface is specified.
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
- Extend the relevant frontend semantic-read payloads to emit structural-anchor metadata.
|
||||
- Extend Studio-side DTOs or semantic-read consumption models to accept the new payload.
|
||||
- Add tests proving that exact anchor positions survive transport and can drive guide rendering.
|
||||
- Validate language-agnostic behavior through contract-level fixtures or tests.
|
||||
|
||||
### Excluded
|
||||
- The first-wave active-container/active-scope editor behavior based only on current ranges.
|
||||
- Broader presentation redesign beyond what is required to consume exact anchors.
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Step 1 - Extend frontend semantic-read producers with structural-anchor payloads
|
||||
|
||||
**What:** Add production of the dedicated structural-anchor surface in the relevant frontend(s).
|
||||
|
||||
**How:** For each participating frontend, emit:
|
||||
- structural ranges;
|
||||
- parentage or equivalent ancestry data as required by the final spec;
|
||||
- anchor positions for exact guide start/end rendering.
|
||||
|
||||
Implementations must honor the language-agnostic contract while mapping language-specific structure into the generic anchor model.
|
||||
|
||||
**File(s):**
|
||||
- frontend semantic-read producers and payload mappers, to be identified from the accepted spec work
|
||||
|
||||
### Step 2 - Extend Studio semantic-read consumption models
|
||||
|
||||
**What:** Teach Studio DTOs and semantic-read consumption code to accept the structural-anchor surface.
|
||||
|
||||
**How:** Update DTOs, transport mapping, and editor-side analysis models so the new structural metadata can flow from semantic read results into the gutter renderer without polluting `documentSymbols`.
|
||||
|
||||
**File(s):**
|
||||
- Studio DTO and semantic-read integration modules, to be identified after schema finalization
|
||||
- `prometeu-studio` editor integration points that consume semantic analysis results
|
||||
|
||||
### Step 3 - Make gutter rendering anchor-aware
|
||||
|
||||
**What:** Upgrade the gutter renderer to use exact structural anchors when available.
|
||||
|
||||
**How:** Adapt the active indicator renderer so guide start/end/cap placement uses structural-anchor metadata rather than symbol-line midpoint approximations.
|
||||
|
||||
The implementation must preserve the DEC-0014 rule that structural anchors are the canonical source of exact positioning.
|
||||
|
||||
**File(s):**
|
||||
- `prometeu-studio/src/main/java/p/studio/workspaces/editor/EditorDocumentScopeGuideGraphicFactory.java`
|
||||
- associated editor model or adapter layers introduced to consume structural anchors
|
||||
|
||||
### Step 4 - Add anchor-aware contract and rendering tests
|
||||
|
||||
**What:** Add tests covering transport, interpretation, and rendering of structural anchors.
|
||||
|
||||
**How:** Introduce tests that prove:
|
||||
- structural-anchor payloads are emitted by frontend semantic read;
|
||||
- Studio receives and stores them separately from `documentSymbols`;
|
||||
- exact opening/closing anchor positions drive rendering behavior;
|
||||
- languages with non-brace structure can still map into the generic contract.
|
||||
|
||||
**File(s):**
|
||||
- frontend semantic-read tests
|
||||
- Studio DTO/transport tests
|
||||
- editor model and renderer tests
|
||||
|
||||
## Test Requirements
|
||||
|
||||
### Unit Tests
|
||||
- Payload schema mapping tests.
|
||||
- Editor adapter/model tests for anchor interpretation.
|
||||
- Renderer tests for exact start/end placement using anchor positions.
|
||||
|
||||
### Integration Tests
|
||||
- End-to-end semantic-read tests from frontend producer to Studio consumer when an existing harness supports that boundary.
|
||||
|
||||
### Manual Verification
|
||||
- Open representative nested documents after structural anchors are available.
|
||||
- Confirm that guide start/end visually align with structural anchor positions rather than line midpoints.
|
||||
- Confirm that the active indicator model remains limited to `activeContainer` and `activeScope`.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Frontend semantic-read payloads expose structural anchors through a dedicated semantic surface.
|
||||
- [ ] Studio consumes structural anchors without overloading `documentSymbols`.
|
||||
- [ ] Exact guide positioning uses structural-anchor metadata when available.
|
||||
- [ ] Tests cover payload transport, anchor interpretation, and anchor-aware rendering.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Accepted decision `DEC-0014-studio-editor-active-scope-and-structural-anchors.md`
|
||||
- Accepted spec work derived from `PLN-0031`
|
||||
- Studio editor wave-1 implementation from `PLN-0030` if shared gutter machinery is reused
|
||||
|
||||
## Risks
|
||||
|
||||
- Frontend payload evolution may require coordinated versioning or backwards-compatibility handling.
|
||||
- Test fixtures may become brittle if the structural-anchor schema is not stabilized before implementation starts.
|
||||
- Exact rendering behavior may vary with font metrics and paragraph layout, requiring robust assertions that test semantic placement rather than pixel-perfect incidental details.
|
||||
Loading…
x
Reference in New Issue
Block a user