diff --git a/docs/studio/agendas/Agenda-01-Asset-Bank-Composition-Snapshot-Transfer-to-Details-DTOs.md b/docs/studio/agendas/Agenda-01-Asset-Bank-Composition-Snapshot-Transfer-to-Details-DTOs.md new file mode 100644 index 00000000..0a5b7860 --- /dev/null +++ b/docs/studio/agendas/Agenda-01-Asset-Bank-Composition-Snapshot-Transfer-to-Details-DTOs.md @@ -0,0 +1,80 @@ +# Asset Bank Composition Snapshot Transfer to Details DTOs Agenda + +Status: Open +Domain Owner: `docs/studio` +Cross-Domain Impact: `docs/packer` + +## Problem + +The `Bank Composition` section needs a stable details-facing data shape before any component or middleware work can proceed. + +Today the underlying information comes from two different sources: + +- snapshot state derived from `walkResult`, which should feed `available` files; +- `asset.json`, which should feed the currently `selected` files for build composition. + +This agenda exists to close how those sources should be transferred into Studio-facing DTOs for `Asset Details`. + +## Context + +Recent packer/runtime work already gives the Studio enough source information to populate a first-wave `Bank Composition` section: + +- registered assets have stable identity; +- the snapshot already contains file inventory derived from `walkResult`; +- blocking diagnostics already exclude files from being generally available; +- selection state is persisted in `asset.json` and is expected to move through the newer `artifacts` shape. + +The Studio should not bind raw UI code directly to packer internals. +The section needs a dedicated Studio DTO layer. + +## Options + +1. Bind the UI directly to snapshot and manifest shapes. +2. Build one dedicated Studio bank-file DTO for both `available` and `selected` rows. +3. Build separate DTOs for `available` rows and `selected` rows. + +## Tradeoffs + +1. Direct binding is fast initially but couples Studio too tightly to packer/runtime structures. +2. One shared DTO keeps the section simpler and is easier to use across transfer list, meter, and staged draft state. +3. Separate DTOs may model source differences more explicitly, but they add mapping and coordination overhead early. + +## Recommendation + +Adopt one dedicated Studio DTO family for bank composition rows and section state. + +Baseline direction: + +- `walkResult`-derived snapshot rows become `available`; +- `asset.json` composition state becomes `selected`; +- both are projected into Studio-owned DTOs before reaching the section UI; +- the DTO should be generic enough to work for any bank type, even if family-specific fields arrive later. +- the DTO field set should stay intentionally small and grow only when a concrete UI need appears. + +### First-Wave DTO Baseline + +The first-wave DTO direction is intentionally pragmatic: + +- define one Studio-owned bank-file DTO family for both `available` and `selected` rows; +- add fields incrementally as real section behavior requires them; +- do not project blocking files into the UI DTO layer at all; +- keep selected-file order visual in the UI, but persist it in `asset.json` through an explicit index shape such as `{ file, index }`. +- start with this minimum first-wave field set: + `fileId/path`, `displayName`, `size`, `lastModified`, `fingerprint`, and `metadata`. + +## Open Questions + +No open questions remain in this agenda wave. + +### Resolved In This Agenda Wave + +The following points are now closed: + +1. The DTO field set should start small and grow only as concrete UI needs appear. +2. Only non-blocking files become `available` DTOs; blocking files should not be projected into the section DTO layer. +3. UI ordering is visual, while persisted ordering in `asset.json` should use an explicit index representation such as `{ file, index }`. +4. The first DTO revision should start with `fileId/path`, `displayName`, `size`, `lastModified`, `fingerprint`, and `metadata`. + +## Next Suggested Step + +Turn this into a `decision` that closes the first-wave Studio DTO shape for `Bank Composition` details data. diff --git a/docs/studio/agendas/Agenda-02-Asset-Bank-Composition-Base-Components.md b/docs/studio/agendas/Agenda-02-Asset-Bank-Composition-Base-Components.md new file mode 100644 index 00000000..24be7c30 --- /dev/null +++ b/docs/studio/agendas/Agenda-02-Asset-Bank-Composition-Base-Components.md @@ -0,0 +1,87 @@ +# Asset Bank Composition Base Components Agenda + +Status: Open +Domain Owner: `docs/studio` +Cross-Domain Impact: `docs/packer` + +## Problem + +The `Bank Composition` section depends on two new Studio components: + +- `StudioDualListView` +- `StudioAssetCapacityMeter` + +Those components need a first-wave contract and scope before the section shell or middleware can be implemented safely. + +## Context + +The current direction is already partially fixed: + +- `StudioDualListView` should be abstract; +- the first concrete subclass should be asset-details-specific; +- right-list ordering must support `move up`, `move down`, and visible indices; +- `StudioAssetCapacityMeter` should be a vertical, game-like progress bar with color bands and percentage text; +- both components should stay intentionally dumb and leave family-specific rules to middleware/controller logic. + +## Options + +1. Build highly generic reusable components from the start. +2. Build bank-composition-scoped Studio components with narrow first-wave APIs. +3. Skip dedicated components and build the section directly inside `AssetDetails`. + +## Tradeoffs + +1. Highly generic components risk overengineering before the first section is proven. +2. Narrow first-wave components keep momentum and preserve room to generalize later from real usage. +3. Inline section code would move faster once, but it would bury behavior that already deserves named UI building blocks. + +## Recommendation + +Build dedicated first-wave components with narrow APIs: + +- abstract `StudioDualListView` as the transfer-list base; +- one asset-details concrete subclass first; +- `StudioAssetCapacityMeter` as a dumb vertical meter component with color thresholds and percentage display. + +Do not force broad reuse rules yet. + +### First-Wave Component Baseline + +The first-wave component contract should stay intentionally small. + +`StudioDualListView` should expose only the hooks needed for the initial bank-composition section: + +- row text and/or row graphic projection; +- current left and right collections; +- current selection state; +- move left-to-right; +- move right-to-left; +- `moveUp`; +- `moveDown`; +- visible index refresh for the right-side list. + +The first concrete asset-details subclass should render rows directly. +Do not introduce a separate row renderer abstraction yet. + +`StudioAssetCapacityMeter` should start as a dumb visual component with these baseline inputs: + +- `progress` in the `0..1` range; +- a label, including percentage text when needed; +- a severity band state; +- optional hint text. + +## Open Questions + +No open questions remain in this agenda wave. + +### Resolved In This Agenda Wave + +The following points are now closed: + +1. `StudioDualListView` should expose only a narrow first-wave hook set for row projection, selection, transfers, reordering, and right-list index refresh. +2. The first concrete asset-details subclass should own row rendering directly. +3. `StudioAssetCapacityMeter` should start with `progress`, label, severity band state, and optional hint text. + +## Next Suggested Step + +Turn this into a `decision` that fixes the first-wave component contracts for `StudioDualListView` and `StudioAssetCapacityMeter`. diff --git a/docs/studio/agendas/Agenda-03-Asset-Bank-Composition-Section-Shell.md b/docs/studio/agendas/Agenda-03-Asset-Bank-Composition-Section-Shell.md new file mode 100644 index 00000000..5a18291f --- /dev/null +++ b/docs/studio/agendas/Agenda-03-Asset-Bank-Composition-Section-Shell.md @@ -0,0 +1,77 @@ +# Asset Bank Composition Section Shell Agenda + +Status: Open +Domain Owner: `docs/studio` +Cross-Domain Impact: `docs/packer` + +## Problem + +`Bank Composition` needs a section shell inside `Asset Details` before behavior is added. + +That shell must align visually and operationally with existing sections, especially `Runtime Contract`, instead of inventing a separate layout and editing model. + +## Context + +The current baseline is already known: + +- `Bank Composition` is a `VBox` section like the others; +- it is always visible for the current bank-based families; +- it should follow the same staged-editing model as `Runtime Contract`; +- the section body should place the dual list on the left and the capacity meter on the right. + +This agenda focuses on the static shell and section composition, not the internal behavior. + +## Options + +1. Add the section only when behavior is ready. +2. Build the section shell first, with placeholder or disabled behavior. +3. Hide the section behind an experimental flag. + +## Tradeoffs + +1. Waiting for full behavior keeps the surface hidden longer and delays visual integration feedback. +2. A shell-first approach lets the Studio validate section rhythm, spacing, controls, and staged-edit affordances early. +3. A flag adds operational complexity without much value if the section is already part of the near-term plan. + +## Recommendation + +Create the `Bank Composition` section shell early, with no real behavior yet. + +Baseline expectations: + +- section header and actions align with `Runtime Contract`; +- `change`, `apply`, `reset`, and `cancel` are part of the shell contract; +- body layout already reserves the dual-list and meter regions; +- the shell may render with placeholder or disabled internals until middleware arrives. + +### First-Wave Shell Baseline + +The first-wave shell should mirror `Runtime Contract` as closely as practical at the JavaFX composition level. + +That includes: + +- the same section rhythm and action placement model; +- the same staged-edit shell expectations; +- alignment with the existing `FormSession` pattern instead of inventing a separate section lifecycle. + +Before middleware wiring is ready, the body should render in a disabled or read-only state rather than as an empty placeholder. + +Outside `change` mode, the section should show the current persisted state as read-only. +It should not stay visually neutral or look absent when data already exists. + +## Open Questions + +No open questions remain in this agenda wave. + +### Resolved In This Agenda Wave + +The following points are now closed: + +1. The section shell should mirror `Runtime Contract` as closely as practical at the JavaFX composition level. +2. The shell should align with the existing `FormSession` model for staged editing. +3. Before middleware is ready, the body should render disabled or read-only internals instead of an empty placeholder. +4. Outside `change` mode, the section should render the current persisted state as read-only. + +## Next Suggested Step + +Turn this into a `decision` that fixes the shell contract and static layout of the `Bank Composition` section. diff --git a/docs/studio/agendas/Agenda-04-Asset-Bank-Composition-Middleware-and-Staged-Editing.md b/docs/studio/agendas/Agenda-04-Asset-Bank-Composition-Middleware-and-Staged-Editing.md new file mode 100644 index 00000000..8a3689ab --- /dev/null +++ b/docs/studio/agendas/Agenda-04-Asset-Bank-Composition-Middleware-and-Staged-Editing.md @@ -0,0 +1,92 @@ +# Asset Bank Composition Middleware and Staged Editing Agenda + +Status: Open +Domain Owner: `docs/studio` +Cross-Domain Impact: `docs/packer` + +## Problem + +`StudioDualListView` and `StudioAssetCapacityMeter` are intentionally dumb. +That means `Bank Composition` needs a middleware/controller layer that owns: + +- family-specific capacity rules; +- staged draft state; +- `change` / `apply` / `reset` / `cancel` orchestration; +- hard-limit decisions about whether a candidate file can enter the selected list. + +Without that layer, component responsibilities will blur quickly. + +## Context + +The current direction already rejects two extremes: + +- no component should hide bank-family rules internally; +- the first wave should not overgeneralize into a universal bank manager abstraction. + +The middleware/controller therefore needs to be explicit, scoped to `Asset Details`, and designed to evolve incrementally. + +## Options + +1. Put orchestration inside the section control itself. +2. Create a dedicated bank-composition middleware/controller for the section. +3. Push family-specific logic down into the transfer list and meter components. + +## Tradeoffs + +1. Section-local orchestration reduces file count initially, but risks turning `AssetDetails` into a heavy behavior host. +2. A dedicated middleware/controller keeps the section and components simpler while preserving room for bank-family policies. +3. Embedding rules into components breaks the current design goal of keeping them dumb and composable. + +## Recommendation + +Create a dedicated bank-composition middleware/controller for the section. + +Baseline expectations: + +- own the draft state while editing is active; +- translate persisted state into editable state on `change`; +- support `reset` back to the persisted state; +- support `cancel` by discarding draft changes; +- keep `apply` stubbed or disabled until persistence is wired; +- delegate family-specific capacity logic through narrowly scoped policies instead of premature platform-wide abstractions. + +### First-Wave Middleware Baseline + +The first wave should not introduce a second session model parallel to the one already used by Studio. + +The middleware/controller should be built around `StudioFormSession` as the common staged-edit core. + +Family-specific variation should not come from subclassing `StudioFormSession`. +It should come from family-specific draft factories and policies that operate on a shared session model. + +Baseline direction: + +- `StudioFormSession` owns `source`, `draft`, `mode`, `isDirty`, `beginEdit`, `reset`, `cancel`, and `apply`; +- the bank-composition middleware/controller coordinates that form session for the section; +- each asset family can offer its own draft-construction and bank-composition policy implementation; +- those policies should decide transfer eligibility, reorder effects, capacity usage, and hard-limit blockers; +- `apply` may remain stubbed or disabled until persistence is wired, but the session contract should already be complete. + +The minimal state published by the middleware/controller should be one section-facing view model carrying: + +- shell state such as `isEditing`, `isDirty`, and action availability; +- left and right list state; +- capacity-meter state; +- active blockers and hint messages when relevant. + +## Open Questions + +No open questions remain in this agenda wave. + +### Resolved In This Agenda Wave + +The following points are now closed: + +1. The middleware/controller should be built around `StudioFormSession`, not a parallel staged-edit model. +2. Family-specific behavior should come from draft factories and policies, not from subclassing `StudioFormSession`. +3. Family-specific rules should be represented first as small policies offered per asset family. +4. The middleware/controller should publish one section-facing view model with shell state, list state, meter state, blockers, and hints. + +## Next Suggested Step + +Turn this into a `decision` that fixes the middleware/controller contract and staged-edit lifecycle for the first wave. diff --git a/docs/studio/agendas/Agenda-05-Asset-Bank-Composition-WorkspaceBus-Interaction.md b/docs/studio/agendas/Agenda-05-Asset-Bank-Composition-WorkspaceBus-Interaction.md new file mode 100644 index 00000000..19170571 --- /dev/null +++ b/docs/studio/agendas/Agenda-05-Asset-Bank-Composition-WorkspaceBus-Interaction.md @@ -0,0 +1,94 @@ +# Asset Bank Composition WorkspaceBus Interaction Agenda + +Status: Open +Domain Owner: `docs/studio` +Cross-Domain Impact: `docs/packer` + +## Problem + +The `Bank Composition` section should use `workspaceBus` for coordination, but the first-wave event contract should stay small and be designed together with the middleware/controller. + +This agenda exists to close the first minimal event surface without inventing an oversized bus protocol too early. + +## Context + +The current baseline is already known: + +- events and middleware should evolve together; +- the first event baseline can stay very small; +- capacity changes are naturally expressed as percentage deltas or level changes in the `0..1` range; +- the transfer list and meter should be consumers of orchestrated state, not independent sources of product rules. + +## Options + +1. Define a broad event taxonomy upfront. +2. Define only the minimum events needed for the first staged-edit interaction loop. +3. Avoid `workspaceBus` and wire components directly. + +## Tradeoffs + +1. A broad taxonomy is easy to regret and hard to prune once code lands. +2. A minimal contract matches the current incremental direction and keeps future changes cheap. +3. Direct wiring would fight the current workspace architecture and reduce observability of section state changes. + +## Recommendation + +Define a minimal first-wave `workspaceBus` contract together with the middleware/controller. + +Baseline direction: + +- begin with the smallest useful set of section-local events; +- include capacity increase/decrease semantics in the `0..1` range only as needed; +- avoid encoding family-specific product rules directly into bus event types. + +### First-Wave Event Baseline + +The first wave should keep user actions local to the middleware/controller whenever possible. + +That means the following actions do not need to become public `workspaceBus` commands in the first implementation: + +- `beginEdit` +- `moveToSelected` +- `moveToAvailable` +- `moveUp` +- `moveDown` +- `reset` +- `cancel` +- `apply` + +The middleware/controller should receive those actions locally, recalculate section state, and publish only the state transitions or lifecycle notifications that matter outside the section. + +The first public `workspaceBus` notifications should stay minimal: + +- `BankCompositionDraftChanged` +- `BankCompositionCapacityChanged` +- `BankCompositionApplyRequested` +- `BankCompositionApplied` +- `BankCompositionApplyFailed` + +Capacity notifications should use absolute progress in the `0..1` range rather than deltas. + +A practical first-wave shape for capacity notifications is: + +- `progress` +- `severity` +- `blocked` + +If internal increase/decrease semantics are useful later, they can remain local implementation detail rather than part of the initial public bus contract. + +## Open Questions + +No open questions remain in this agenda wave. + +### Resolved In This Agenda Wave + +The following points are now closed: + +1. First-wave user actions should stay local to the middleware/controller rather than becoming public bus commands. +2. The first public `workspaceBus` contract should be notification-oriented. +3. Capacity notifications should use absolute `0..1` progress rather than deltas. +4. A minimal first-wave bus surface is enough: draft change, capacity change, apply requested, apply success, and apply failure. + +## Next Suggested Step + +Turn this into a `decision` that fixes the minimal first-wave `workspaceBus` contract for `Bank Composition`. diff --git a/docs/studio/agendas/Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md b/docs/studio/agendas/Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md new file mode 100644 index 00000000..d195555c --- /dev/null +++ b/docs/studio/agendas/Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md @@ -0,0 +1,98 @@ +# Asset Bank Composition Persistence and Snapshot Propagation Agenda + +Status: Open +Domain Owner: `docs/studio` +Cross-Domain Impact: `docs/packer` + +## Problem + +When the developer clicks `apply`, the selected files for bank composition must be persisted and reflected back into runtime state. + +That write path spans Studio and packer concerns: + +- staged selected files must be serialized into `asset.json`; +- the older `inputsByRole` shape should give way to the newer `artifacts` shape; +- the minimal runtime snapshot must reflect the persisted result after apply. + +## Context + +The earlier agendas in this sequence assume `apply` may remain disabled or stubbed until persistence is ready. +This agenda isolates the write-path discussion so the rest of the UI can progress first. + +The current direction is already mostly known: + +- persistence should happen through packer, not by having Studio write manifest files directly; +- selected composition should be stored in `asset.json`; +- runtime state should be refreshed after persistence so `Asset Details` stays coherent. + +## Options + +1. Let Studio write `asset.json` directly. +2. Route `apply` through packer services and let packer own manifest persistence plus snapshot refresh. +3. Persist only to runtime state first and defer manifest persistence. + +## Tradeoffs + +1. Direct manifest writes from Studio would bypass packer ownership and create duplicate write rules. +2. A packer-owned write path is cleaner and aligns with existing asset mutation flows. +3. Runtime-only persistence would create an unstable editing model and almost certainly drift from disk state. + +## Recommendation + +Route `apply` through packer and persist selected files into `asset.json` using the newer `artifacts` representation. + +Baseline expectations: + +- `apply` submits the selected ordered files to packer; +- packer updates `asset.json`; +- packer propagates the resulting minimal state back into the runtime snapshot; +- Studio refreshes the section from the updated details/snapshot state instead of trusting stale draft data. + +### Persistence Baseline + +The first-wave persistence direction is: + +- `artifacts` replaces the older `inputsByRole` representation in `asset.json`; +- the bank-composition selection should therefore persist through `artifacts`, not through a parallel legacy shape; +- selected file order should remain explicit in persisted data rather than relying on array position alone. + +### Apply Refresh and Failure Baseline + +After `apply`, the Studio should not trust stale draft state. + +The first-wave refresh baseline is: + +- packer persists the selected ordered files into `asset.json`; +- packer refreshes the minimal runtime snapshot state needed by `Asset Details`; +- the Studio rebinds the section from the refreshed persisted state and returns the section to consistent read-only mode. + +The minimum refreshed state should include: + +- persisted `selected` rows; +- the current `available` projection for details; +- recalculated capacity state; +- recalculated blockers or eligibility state relevant to the section. + +If `apply` fails: + +- the draft must not be discarded; +- the section must remain in editing mode; +- the middleware/controller should publish `BankCompositionApplyFailed`; +- the UI should show a local error or hint surface; +- the user should still be able to retry, reset, or cancel. + +## Open Questions + +No open questions remain in this agenda wave. + +### Resolved In This Agenda Wave + +The following points are now closed: + +1. `artifacts` should replace the older `inputsByRole` shape rather than coexist with it for bank-composition persistence. +2. After `apply`, packer should refresh the minimal snapshot state required by `Asset Details` and Studio should rebind from that refreshed persisted state. +3. If `apply` fails, the draft remains intact, the section stays in editing mode, and the UI surfaces a local failure state while preserving retry, reset, and cancel. + +## Next Suggested Step + +Turn this into a cross-domain `decision` or a paired `docs/studio` + `docs/packer` decision set that closes the apply write path. diff --git a/docs/studio/agendas/Asset Bank Composition Area - Dual List and Capacity Meter Agenda.md b/docs/studio/agendas/Asset Bank Composition Area - Dual List and Capacity Meter Agenda.md new file mode 100644 index 00000000..57ba1f24 --- /dev/null +++ b/docs/studio/agendas/Asset Bank Composition Area - Dual List and Capacity Meter Agenda.md @@ -0,0 +1,234 @@ +# Asset Bank Composition Area - Dual List and Capacity Meter Agenda + +Status: Open (Umbrella, split into follow-up agendas) +Domain Owner: `docs/studio` +Cross-Domain Impact: `docs/packer` + +## Problem + +The Studio `Assets` details area does not yet expose an explicit authoring surface for bank composition based on internal asset files. + +The next planned area is not a simple form row. +It combines: + +- a left-side transfer area with `available files` and `files included in build`; +- a right-side vertical capacity meter for fixed bank size usage; +- rule-driven gating where files can no longer be moved into the build set once the bank reaches its fixed size limit. + +This looks small in layout terms, but it hides many interaction details: + +- which files are shown at all; +- which files are build-eligible; +- how diagnostics affect transfer availability; +- whether order matters; +- how the meter behaves near or above the limit; +- and how Studio should explain hard capacity blockers without becoming noisy. + +This topic needs a Studio agenda before it becomes a decision or implementation PR. + +## Context + +Recent packer work now gives the runtime snapshot enough information to support this UI discussion more concretely: + +- available files per registered asset; +- build-candidate files derived from the current walk; +- file-scoped diagnostics kept segregated for future UI use; +- measured bank size usage for the current build-candidate set; +- stable asset identity through `asset_id` for registered assets only. + +That means the Studio can now discuss this area against a real backend shape instead of inventing a purely visual placeholder. + +Important constraints already known: + +1. only registered assets should participate in this internal bank-composition flow; +2. the snapshot should retain file inventory and build-candidate information, but not raw file bytes; +3. bank size is fixed on the hardware/runtime side; +4. when the bank reaches its maximum size, the UI must block adding more files into the build set. + +## Current Code Context + +The current Studio selected-asset details composition is still centered on: + +- summary and actions; +- runtime contract; +- diagnostics and preview-related surfaces already present in the details flow. + +Relevant code anchors today: + +- `prometeu-studio/src/main/java/p/studio/workspaces/assets/details/AssetDetailsControl.java` +- `prometeu-studio/src/main/java/p/studio/workspaces/assets/details/contract/AssetDetailsContractControl.java` +- `docs/studio/specs/4. Assets Workspace Specification.md` + +There is no existing `DualListView` or dedicated bank-composition control in `prometeu-studio` yet. + +That matters because this agenda is not only about layout. +It is about how a new section inside `Asset Details` should behave and how its internal components should coordinate. + +## Recommendation + +Create a dedicated `Bank Composition` section inside `Asset Details`, implemented as a `VBox` section just like the other asset-details sections, and explicitly backed by packer runtime data. + +Operationally, this section should follow the same staged-editing pattern already used by `Runtime Contract`, including `change`, `apply`, `reset`, and `cancel` actions. + +Recommended baseline shape: + +1. left side of the section body: a dedicated `StudioDualListView` component with: + - left list = available files + - right list = files included in build +2. right side of the section body: a dedicated vertical `StudioAssetCapacityMeter` component showing current measured usage versus fixed bank capacity +3. hard gating rule: + if adding a file would exceed the fixed bank size, the move must be blocked before the item enters the build list +4. coordination rule: + the transfer list and the capacity meter must be built as components for this asset-workspace use case and must be able to exchange typed events through the `workspaceBus` + +Why this direction: + +- it gives bank composition its own didactic and operational area inside `Asset Details`; +- it leaves room to discuss many smaller details without destabilizing the rest of selected-asset details; +- it keeps authoring behavior aligned with the existing `Runtime Contract` section instead of inventing a second editing model inside `Asset Details`; +- it aligns with the Studio event-driven workspace model already used by the `Assets` workspace. + +### Component Direction + +The first implementation should not treat these controls as isolated local widgets. + +Rules: + +- `StudioDualListView` is the component name for the transfer-list surface of this section; +- `StudioDualListView` should be introduced as an abstract Studio component created for this bank-composition section; +- `StudioDualListView` should leave concrete behavior to subclasses, with capabilities added incrementally as real bank-composition needs appear; +- `StudioAssetCapacityMeter` is the component name for the vertical capacity meter of this section; +- `StudioAssetCapacityMeter` should also be introduced as a Studio component created for this bank-composition section; +- both components must be able to publish and consume typed events through the `workspaceBus`; +- the event model must allow coordination not only between the transfer list and the capacity meter, but also with surrounding details/workspace components when selection, eligibility, diagnostics, or staged apply behavior evolves; +- the first event baseline should stay intentionally small: + increase and decrease capacity updates expressed as percentage in the `0..1` range are enough to start; +- the initial component scope is still bank-composition-specific, even if later refactoring makes them reusable elsewhere. + +### Current Baseline Assumptions + +The following points are now assumed for the current discussion wave: + +1. `StudioDualListView` is abstract, with concrete subclasses supplying bank-specific behavior over time. +2. `Bank Composition` is always visible for the current asset families, because the currently active bank-based families are `Tile` and `Sound`. +3. `available files` come directly from the snapshot projection derived from `walkResult`. +4. only files without blocking diagnostics may appear in `available files`. +5. file order in the right list affects build output and must be developer-controlled. +6. the right list therefore needs ordering support and should surface indices as part of the UI. +7. capacity computation is family-specific and must not be normalized prematurely into one fake universal formula. +8. the bank-composition section should receive its data as part of the normal asset-details fetch. +9. `StudioDualListView` and `StudioAssetCapacityMeter` should both remain intentionally dumb; a bank-composition middleware/controller should own family-specific UI rules and hard-limit orchestration. +10. if the Studio later needs non-bank-based asset handling, that should be introduced via another bank manager/composition manager rather than by overengineering this first wave. +11. the section should use the same staged interaction model as `Runtime Contract`, with `change`, `apply`, `reset`, and `cancel`. + +### Family-Specific Capacity Notes + +The current bank-capacity semantics already differ by family: + +- `Tile` banks are matrix-based. + Example: + a `256x256` indexed matrix with tiles configured as `32x32` yields `8x8 = 64` tile slots. + If each selected build file contributes one `32x32` tile, the bank can contain at most `64` selected files. +- `Sound` banks are byte-budget-based. + The relevant measure is sample size in bytes, with a fixed bank capacity such as `1 MB`. + +That means `StudioAssetCapacityMeter` must be driven by bank-family semantics rather than by one simplistic shared percentage algorithm hidden from the user. + +### Meter Behavior Baseline + +The current direction for the meter is explicitly game-like: + +- a vertical progress-bar style meter that rises as the bank fills; +- green, orange, and red severity bands instead of one neutral fill; +- a percentage label below the bar; +- supporting text or hint copy explaining that banks have fixed capacity and must not be exceeded; +- hint text should also nudge the developer toward splitting or reorganizing the asset when the bank is too full. + +Initial thresholds: + +- green below `65%` +- orange at `>= 65%` or `> 9/16` +- red at `>= 95%` or `> 14/16` + +Hard-limit interaction baseline: + +- the UI should disable only moves from left to right when capacity is exhausted or the candidate item would overflow the bank; +- moving items from right to left must remain possible; +- ordering actions on the right list must remain possible; +- the surface should still explain why add is blocked, instead of silently failing. + +### Section Workflow Baseline + +`Bank Composition` should not auto-persist edits while the developer is moving files around. + +The first-wave workflow should mirror `Runtime Contract`: + +- `change` enters editable mode; +- list transfers, ordering, and capacity feedback happen inside the staged draft state; +- `apply` persists the new composition; +- `reset` returns the draft to the last persisted state while staying in the editing flow; +- `cancel` exits editing and discards uncommitted draft changes. + +This keeps the mental model of `Asset Details` consistent across sections and avoids mixing immediate-write behavior with staged authoring behavior in the same surface. + +### Ordering Baseline + +The current first-wave baseline for right-list ordering is: + +- `move up` +- `move down` +- visible indices on the right/build list + +Drag-and-drop may still be attractive later, but it is not yet required to validate the first wave. + +## Open Questions + +1. What exact first-wave event and controller contract should be defined together for the bank-composition flow, since the `workspaceBus` events and the bank-composition middleware/controller should evolve as one design surface? +2. What exact explanatory text should the section show for tile-bank exhaustion versus sound-bank exhaustion so the user understands the capacity rule, not just the percentage? + +### Resolved In This Agenda Wave + +The following points are now closed for the first wave: + +1. The UI-facing file-row structure should be a dedicated Studio DTO for any bank type. +2. The first concrete `StudioDualListView` subclass should be asset-details-specific. +3. The event contract and middleware/controller shape should be designed together incrementally, without premature generalization. +4. Detailed wording for family-specific explanatory copy can be deferred until the section contract is otherwise ready. + +## Suggested Next Step + +Do not implement the area yet. + +This umbrella agenda is now intentionally split into focused follow-up agendas aligned to the proposed execution order: + +1. snapshot transfer into details DTOs: + [`Agenda-01-Asset-Bank-Composition-Snapshot-Transfer-to-Details-DTOs.md`](./Agenda-01-Asset-Bank-Composition-Snapshot-Transfer-to-Details-DTOs.md) +2. base component construction: + [`Agenda-02-Asset-Bank-Composition-Base-Components.md`](./Agenda-02-Asset-Bank-Composition-Base-Components.md) +3. `Bank Composition` section shell: + [`Agenda-03-Asset-Bank-Composition-Section-Shell.md`](./Agenda-03-Asset-Bank-Composition-Section-Shell.md) +4. bank-composition middleware/controller: + [`Agenda-04-Asset-Bank-Composition-Middleware-and-Staged-Editing.md`](./Agenda-04-Asset-Bank-Composition-Middleware-and-Staged-Editing.md) +5. middleware-driven interaction: + [`Agenda-05-Asset-Bank-Composition-WorkspaceBus-Interaction.md`](./Agenda-05-Asset-Bank-Composition-WorkspaceBus-Interaction.md) +6. persistence: + [`Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md`](./Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md) + +### Proposed Execution Order + +The current proposed implementation order is: + +1. transfer snapshot state into asset-details DTOs +2. build the base and concrete UI components +3. create the `Bank Composition` UI shell with no behavior +4. introduce the bank-composition middleware/controller and staged DTO flow +5. wire developer actions through middleware and `workspaceBus` +6. persist the selected composition back through packer into `asset.json` and the minimal snapshot + +This sequence is useful not only for implementation, but also for decision slicing: + +- early decisions can close DTO and section-shape questions first; +- middle decisions can close middleware and event-orchestration questions; +- the final decision can close persistence into `asset.json` and minimal snapshot propagation. + +The next correct step is to work these follow-up agendas in order and derive smaller `decision` records from them instead of trying to close the whole bank-composition architecture in one pass. diff --git a/docs/studio/agendas/README.md b/docs/studio/agendas/README.md index 6207b736..99158187 100644 --- a/docs/studio/agendas/README.md +++ b/docs/studio/agendas/README.md @@ -2,7 +2,15 @@ This directory contains active Studio discussion agendas. -There are currently no active Studio agendas. +Active agendas: + +- [`Asset Bank Composition Area - Dual List and Capacity Meter Agenda.md`](./Asset%20Bank%20Composition%20Area%20-%20Dual%20List%20and%20Capacity%20Meter%20Agenda.md) +- [`Agenda-01-Asset-Bank-Composition-Snapshot-Transfer-to-Details-DTOs.md`](./Agenda-01-Asset-Bank-Composition-Snapshot-Transfer-to-Details-DTOs.md) +- [`Agenda-02-Asset-Bank-Composition-Base-Components.md`](./Agenda-02-Asset-Bank-Composition-Base-Components.md) +- [`Agenda-03-Asset-Bank-Composition-Section-Shell.md`](./Agenda-03-Asset-Bank-Composition-Section-Shell.md) +- [`Agenda-04-Asset-Bank-Composition-Middleware-and-Staged-Editing.md`](./Agenda-04-Asset-Bank-Composition-Middleware-and-Staged-Editing.md) +- [`Agenda-05-Asset-Bank-Composition-WorkspaceBus-Interaction.md`](./Agenda-05-Asset-Bank-Composition-WorkspaceBus-Interaction.md) +- [`Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md`](./Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md) The shell, UI foundations, components admission baselines, and the first asset workspace wave were already consolidated into [`../specs/`](../specs/) and [`../learn/`](../learn/). diff --git a/docs/studio/decisions/Bank Composition Base Components Decision.md b/docs/studio/decisions/Bank Composition Base Components Decision.md new file mode 100644 index 00000000..1791f4ae --- /dev/null +++ b/docs/studio/decisions/Bank Composition Base Components Decision.md @@ -0,0 +1,110 @@ +# Bank Composition Base Components Decision + +Status: Decided +Cycle: 2026-03 +Domain Owner: `docs/studio` +Cross-Domain Impact: `docs/packer` + +## Context + +The `Bank Composition` section inside `Asset Details` depends on two new Studio components: + +- `StudioDualListView` +- `StudioAssetCapacityMeter` + +These components need a first-wave contract before the section shell, middleware, and persistence work can proceed safely. + +The DTO projection boundary was already closed in: + +- [`Bank Composition Details DTO Projection Decision.md`](./Bank%20Composition%20Details%20DTO%20Projection%20Decision.md) + +This decision closes the first-wave component direction discussed in: + +- [`Agenda-02-Asset-Bank-Composition-Base-Components.md`](../agendas/Agenda-02-Asset-Bank-Composition-Base-Components.md) + +## Decision + +Adopt narrow, bank-composition-scoped first-wave components. + +The component choices are: + +1. `StudioDualListView` remains an abstract Studio component; +2. the first concrete implementation is asset-details-specific; +3. `StudioAssetCapacityMeter` is a dumb visual component for vertical capacity display; +4. neither component should own bank-family product rules. + +`StudioDualListView` should expose only the hooks needed by the first `Bank Composition` wave: + +- row text and/or row graphic projection; +- current left and right collections; +- current selection state; +- move left-to-right; +- move right-to-left; +- `moveUp`; +- `moveDown`; +- visible right-list index refresh. + +The first asset-details concrete subclass should render rows directly. +Do not introduce a separate row-renderer abstraction in this first wave. + +`StudioAssetCapacityMeter` starts with these baseline inputs: + +- `progress` in the `0..1` range; +- a label, including percentage text when needed; +- a severity-band state; +- optional hint text. + +## Justification + +This keeps component scope small and aligned with the current implementation plan. + +The decision avoids two common mistakes: + +- overengineering highly generic components before the first section exists; +- burying section behavior directly inside `Asset Details` with no named component boundary. + +Direct row rendering in the first concrete dual-list implementation is the pragmatic choice. +There is no current evidence that a standalone row-renderer abstraction is needed. + +Keeping `StudioAssetCapacityMeter` dumb also protects the future middleware/controller boundary. +Family-specific rules should not leak into the visual component. + +## Invariants and Constraints + +The following constraints now apply: + +1. `StudioDualListView` must remain abstract in the first wave; +2. the first concrete `StudioDualListView` implementation belongs to the asset-details flow; +3. right-list ordering support must include `moveUp`, `moveDown`, and visible indices; +4. `StudioAssetCapacityMeter` must remain visual and state-driven, not rule-driven; +5. bank-family capacity logic remains outside both components. + +## Explicit Non-Decisions + +This decision does not yet define: + +- the Java package layout or exact class names for the first concrete asset-details subclass; +- the `Bank Composition` section shell layout details; +- the middleware/controller contract; +- the `workspaceBus` event contract; +- persistence or apply behavior. + +## Propagation Targets + +- Studio agendas: + [`Agenda-03-Asset-Bank-Composition-Section-Shell.md`](../agendas/Agenda-03-Asset-Bank-Composition-Section-Shell.md) + [`Agenda-04-Asset-Bank-Composition-Middleware-and-Staged-Editing.md`](../agendas/Agenda-04-Asset-Bank-Composition-Middleware-and-Staged-Editing.md) + [`Agenda-05-Asset-Bank-Composition-WorkspaceBus-Interaction.md`](../agendas/Agenda-05-Asset-Bank-Composition-WorkspaceBus-Interaction.md) + [`Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md`](../agendas/Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md) +- Studio specs: + [`4. Assets Workspace Specification.md`](../specs/4.%20Assets%20Workspace%20Specification.md) +- Studio code: + future component classes for `StudioDualListView`, the first asset-details concrete implementation, and `StudioAssetCapacityMeter` + +## Validation Notes + +Examples implied by this decision: + +- the right/build list can be reordered through `moveUp` and `moveDown`; +- the right/build list can display visible indices without requiring middleware-specific rendering logic; +- the capacity meter can show green, orange, or red state based on inputs from higher-level orchestration without knowing tile or sound rules. diff --git a/docs/studio/decisions/Bank Composition Details DTO Projection Decision.md b/docs/studio/decisions/Bank Composition Details DTO Projection Decision.md new file mode 100644 index 00000000..f922db7d --- /dev/null +++ b/docs/studio/decisions/Bank Composition Details DTO Projection Decision.md @@ -0,0 +1,109 @@ +# Bank Composition Details DTO Projection Decision + +Status: Decided +Cycle: 2026-03 +Domain Owner: `docs/studio` +Cross-Domain Impact: `docs/packer` + +## Context + +The `Bank Composition` section inside `Asset Details` needs a stable UI-facing data shape before component, middleware, and persistence work can proceed. + +The source information comes from two distinct places: + +- runtime snapshot state derived from `walkResult`, which should feed `available` files; +- persisted `asset.json` composition state, which should feed `selected` files. + +The Studio should not bind section UI directly to snapshot internals or raw manifest structures. +This needs a Studio-owned DTO projection boundary. + +This decision closes the DTO direction discussed in: + +- [`Agenda-01-Asset-Bank-Composition-Snapshot-Transfer-to-Details-DTOs.md`](../agendas/Agenda-01-Asset-Bank-Composition-Snapshot-Transfer-to-Details-DTOs.md) + +## Decision + +Adopt one dedicated Studio-owned DTO family for `Bank Composition` details data. + +The first-wave projection rules are: + +1. snapshot rows derived from `walkResult` become `available` rows in the Studio DTO layer; +2. persisted composition rows from `asset.json` become `selected` rows in the Studio DTO layer; +3. both flows must be projected into Studio DTOs before reaching `Asset Details` UI code; +4. the DTO family must be generic enough to support any bank type, even if family-specific fields are added later; +5. the DTO field set must stay intentionally small and grow only when concrete UI behavior requires it. + +The first DTO revision starts with these fields: + +- `fileId/path` +- `displayName` +- `size` +- `lastModified` +- `fingerprint` +- `metadata` + +Availability and ordering rules are: + +1. only non-blocking files become `available` DTO rows; +2. blocking files must not be projected into the `Bank Composition` DTO layer; +3. UI ordering is visual in the selected list; +4. persisted ordering in `asset.json` should use an explicit index representation such as `{ file, index }`. + +## Justification + +This direction keeps the Studio UI decoupled from packer/runtime internal shapes while still using runtime data as the source of truth. + +One shared DTO family is the pragmatic middle ground: + +- lighter than separate `available` and `selected` row models; +- safer than direct binding to snapshot and manifest structures; +- easier to reuse across section shell, transfer list, meter, and staged editing middleware. + +Filtering blocking files before DTO projection also keeps the section contract simpler. +The UI should receive only rows that are actually eligible to appear as `available`. + +Persisted order needs an explicit index in `asset.json` because list order is not a robust persistence contract by itself. + +## Implications + +The Studio details layer now owns a DTO projection step for `Bank Composition`. + +This means: + +- component work should consume Studio DTOs, not packer snapshot rows directly; +- middleware work should operate on DTO-based staged state; +- persistence work must translate selected DTO order into indexed `asset.json` entries; +- packer-facing details fetches must expose enough source data to populate the DTO fields above. + +## Explicit Non-Decisions + +This decision does not yet define: + +- the exact Java classes or package layout for the DTOs; +- the section middleware/controller contract; +- the `workspaceBus` event contract; +- the concrete `asset.json` `artifacts` schema beyond the need for explicit indexed order; +- family-specific explanatory copy for tile versus sound exhaustion. + +## Propagation Targets + +- Studio agendas: + [`Agenda-02-Asset-Bank-Composition-Base-Components.md`](../agendas/Agenda-02-Asset-Bank-Composition-Base-Components.md) + [`Agenda-03-Asset-Bank-Composition-Section-Shell.md`](../agendas/Agenda-03-Asset-Bank-Composition-Section-Shell.md) + [`Agenda-04-Asset-Bank-Composition-Middleware-and-Staged-Editing.md`](../agendas/Agenda-04-Asset-Bank-Composition-Middleware-and-Staged-Editing.md) + [`Agenda-05-Asset-Bank-Composition-WorkspaceBus-Interaction.md`](../agendas/Agenda-05-Asset-Bank-Composition-WorkspaceBus-Interaction.md) + [`Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md`](../agendas/Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md) +- Studio specs: + [`4. Assets Workspace Specification.md`](../specs/4.%20Assets%20Workspace%20Specification.md) +- Studio code: + `Asset Details` details fetch, DTO projection layer, and `Bank Composition` section inputs +- Packer code and docs: + details payload shaping and future `asset.json` persistence under the `artifacts` composition path + +## Validation Notes + +Examples implied by this decision: + +- a file with blocking diagnostics does not produce an `available` DTO row at all; +- a selected file may appear in the UI with visual order `3`, while persistence writes something like `{ file: "...", index: 3 }`; +- adding new UI needs later should extend the DTO deliberately instead of pulling snapshot internals straight into the section. diff --git a/docs/studio/decisions/Bank Composition Middleware and Staged Editing Decision.md b/docs/studio/decisions/Bank Composition Middleware and Staged Editing Decision.md new file mode 100644 index 00000000..333269ef --- /dev/null +++ b/docs/studio/decisions/Bank Composition Middleware and Staged Editing Decision.md @@ -0,0 +1,114 @@ +# Bank Composition Middleware and Staged Editing Decision + +Status: Decided +Cycle: 2026-03 +Domain Owner: `docs/studio` +Cross-Domain Impact: `docs/packer` + +## Context + +`Bank Composition` needs a control layer above the new UI components because: + +- `StudioDualListView` is intentionally dumb; +- `StudioAssetCapacityMeter` is intentionally dumb; +- the section must follow the same staged-edit model already used elsewhere in `Asset Details`; +- capacity and blocker rules differ by asset family. + +The current codebase already has a staged-edit primitive in: + +- [`StudioFormSession.java`](../../../prometeu-studio/src/main/java/p/studio/controls/forms/StudioFormSession.java) + +The earlier `Bank Composition` decisions already fixed: + +- DTO projection: + [`Bank Composition Details DTO Projection Decision.md`](./Bank%20Composition%20Details%20DTO%20Projection%20Decision.md) +- base components: + [`Bank Composition Base Components Decision.md`](./Bank%20Composition%20Base%20Components%20Decision.md) +- section shell: + [`Bank Composition Section Shell Decision.md`](./Bank%20Composition%20Section%20Shell%20Decision.md) + +This decision closes the middleware direction discussed in: + +- [`Agenda-04-Asset-Bank-Composition-Middleware-and-Staged-Editing.md`](../agendas/Agenda-04-Asset-Bank-Composition-Middleware-and-Staged-Editing.md) + +## Decision + +Adopt a dedicated bank-composition middleware/controller built around `StudioFormSession`. + +The first-wave rules are: + +1. `StudioFormSession` is the shared staged-edit core for the section; +2. `Bank Composition` must not introduce a second session model parallel to `StudioFormSession`; +3. family-specific variation must not come from subclassing `StudioFormSession`; +4. family-specific variation must come from draft factories and bank-composition policies offered per asset family; +5. `apply` may remain stubbed or disabled until persistence is wired, but the session contract should already exist. + +The middleware/controller owns orchestration around the form session, including: + +- translating persisted section state into session source/draft state; +- beginning edit mode; +- resetting draft state; +- canceling edits; +- applying draft state when persistence is available; +- evaluating transfer eligibility; +- evaluating reorder effects; +- calculating capacity state; +- calculating hard-limit blockers and hints. + +The middleware/controller should publish one section-facing view model that includes: + +- shell state such as editing mode, dirty state, and action availability; +- left and right list state; +- capacity-meter state; +- blockers and hint text when relevant. + +## Justification + +This is the simplest design that matches the actual codebase. + +`StudioFormSession` already provides the staged-edit lifecycle the section needs. +Creating a second middleware-specific session model would duplicate behavior for no gain. + +At the same time, subclassing `StudioFormSession` is the wrong variation point. +The current class is final, and more importantly the lifecycle does not change by asset family. +What changes by family is bank-composition logic: draft shaping, eligibility, capacity, and blockers. + +That makes policies and factories the correct seam. + +## Invariants and Constraints + +The following constraints now apply: + +1. `StudioFormSession` is the only staged-edit core for the section in the first wave; +2. asset-family differences must be modeled outside `StudioFormSession`; +3. the middleware/controller remains section-specific and should not become a platform-wide bank manager abstraction; +4. dumb UI components consume derived state and do not own bank rules; +5. the section-facing output must be consolidated into one view model rather than scattered state channels. + +## Explicit Non-Decisions + +This decision does not yet define: + +- the exact Java class names or package layout for the middleware/controller, policies, or draft factories; +- the exact shape of `BankCompositionDraft`; +- the `workspaceBus` event contract; +- persistence/apply integration with packer; +- the exact text of family-specific hint and blocker messages. + +## Propagation Targets + +- Studio agendas: + [`Agenda-05-Asset-Bank-Composition-WorkspaceBus-Interaction.md`](../agendas/Agenda-05-Asset-Bank-Composition-WorkspaceBus-Interaction.md) + [`Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md`](../agendas/Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md) +- Studio specs: + [`4. Assets Workspace Specification.md`](../specs/4.%20Assets%20Workspace%20Specification.md) +- Studio code: + `StudioFormSession` integration, `Bank Composition` section controller/middleware, family-specific draft factories, and family-specific bank-composition policies + +## Validation Notes + +Examples implied by this decision: + +- a tile family and a sound family can share the same `StudioFormSession` lifecycle while using different capacity/blocker policies; +- the dual list and meter can stay dumb because the middleware/controller supplies already-derived state; +- when persistence is not wired yet, `beginEdit`, `reset`, and `cancel` still work through the shared form-session model. diff --git a/docs/studio/decisions/Bank Composition Persistence and Snapshot Propagation Decision.md b/docs/studio/decisions/Bank Composition Persistence and Snapshot Propagation Decision.md new file mode 100644 index 00000000..8cb605c0 --- /dev/null +++ b/docs/studio/decisions/Bank Composition Persistence and Snapshot Propagation Decision.md @@ -0,0 +1,117 @@ +# Bank Composition Persistence and Snapshot Propagation Decision + +Status: Decided +Cycle: 2026-03 +Domain Owner: `docs/studio` +Cross-Domain Impact: `docs/packer` + +## Context + +`Bank Composition` reaches across Studio and packer when the developer clicks `apply`. + +That write path must: + +- persist selected ordered files into `asset.json`; +- use the newer `artifacts` representation instead of the older `inputsByRole` shape; +- refresh enough runtime state for `Asset Details` to become consistent again after apply. + +The earlier `Bank Composition` decisions already fixed: + +- DTO projection: + [`Bank Composition Details DTO Projection Decision.md`](./Bank%20Composition%20Details%20DTO%20Projection%20Decision.md) +- base components: + [`Bank Composition Base Components Decision.md`](./Bank%20Composition%20Base%20Components%20Decision.md) +- section shell: + [`Bank Composition Section Shell Decision.md`](./Bank%20Composition%20Section%20Shell%20Decision.md) +- middleware and staged editing: + [`Bank Composition Middleware and Staged Editing Decision.md`](./Bank%20Composition%20Middleware%20and%20Staged%20Editing%20Decision.md) +- workspace bus interaction: + [`Bank Composition WorkspaceBus Interaction Decision.md`](./Bank%20Composition%20WorkspaceBus%20Interaction%20Decision.md) + +This decision closes the persistence direction discussed in: + +- [`Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md`](../agendas/Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md) + +## Decision + +Route `Bank Composition` apply through packer and persist selection under `asset.json` `artifacts`. + +The first-wave rules are: + +1. Studio must not write `asset.json` directly; +2. packer owns persistence of selected bank-composition files; +3. `artifacts` replaces the older `inputsByRole` representation for this flow; +4. selected file order must remain explicit in persisted data rather than relying on array position alone; +5. after a successful apply, Studio must refresh from persisted state rather than trusting stale draft state. + +The minimal successful apply flow is: + +1. Studio submits the selected ordered files to packer; +2. packer updates `asset.json` under the `artifacts` representation; +3. packer refreshes the minimal runtime snapshot state required by `Asset Details`; +4. Studio rebinds the section from that refreshed persisted state; +5. the section returns to consistent read-only mode. + +The minimum refreshed state after apply must include: + +- persisted `selected` rows; +- the current `available` projection used by `Asset Details`; +- recalculated capacity state; +- recalculated blockers or eligibility state relevant to the section. + +The failure rules are: + +1. if apply fails, the draft must not be discarded; +2. the section must remain in editing mode; +3. the middleware/controller should publish `BankCompositionApplyFailed`; +4. the UI should show a local failure surface; +5. the user must still be able to retry, reset, or cancel. + +## Justification + +This keeps write ownership in the correct domain boundary. + +Packer already owns asset mutation and runtime refresh logic. +Letting Studio write manifests directly would duplicate rules and create drift between UI and runtime behavior. + +Refreshing from persisted state after success is also necessary. +Otherwise the section would keep trusting stale draft state and could diverge from what packer actually accepted and wrote. + +Preserving the draft on failure is the correct staged-edit behavior. +The user should not lose work because persistence failed. + +## Invariants and Constraints + +The following constraints now apply: + +1. Studio is not the manifest writer for `Bank Composition`; +2. `artifacts` is the persistence path for selected bank-composition files; +3. `inputsByRole` is not the write target for this flow; +4. successful apply requires snapshot refresh before the section settles back to read-only mode; +5. failed apply must preserve draft state and editing mode. + +## Explicit Non-Decisions + +This decision does not yet define: + +- the exact final `asset.json` `artifacts` schema beyond explicit ordered file persistence; +- the concrete packer request/response message names; +- the exact Java event class payloads for apply success or failure; +- broader manifest migration strategy outside this `Bank Composition` flow. + +## Propagation Targets + +- Studio specs: + [`4. Assets Workspace Specification.md`](../specs/4.%20Assets%20Workspace%20Specification.md) +- Studio code: + bank-composition apply flow, failure handling, and section refresh behavior +- Packer docs and code: + `asset.json` `artifacts` persistence, write-path integration, and minimal runtime snapshot refresh after apply + +## Validation Notes + +Examples implied by this decision: + +- after a successful apply, the section should reload from the refreshed persisted state instead of keeping the old draft instance; +- if packer rejects an apply, the selected rows remain in the draft so the user can adjust and retry; +- selected bank-composition files must be written through `artifacts`, not through `inputsByRole`. diff --git a/docs/studio/decisions/Bank Composition Section Shell Decision.md b/docs/studio/decisions/Bank Composition Section Shell Decision.md new file mode 100644 index 00000000..f7205273 --- /dev/null +++ b/docs/studio/decisions/Bank Composition Section Shell Decision.md @@ -0,0 +1,85 @@ +# Bank Composition Section Shell Decision + +Status: Decided +Cycle: 2026-03 +Domain Owner: `docs/studio` +Cross-Domain Impact: `docs/packer` + +## Context + +The `Bank Composition` area needs a visible section shell inside `Asset Details` before behavior and persistence are wired. + +The section should not invent a parallel editing model. +It needs to align with the existing `Asset Details` section rhythm, especially `Runtime Contract`. + +The DTO projection boundary and the first-wave component direction were already closed in: + +- [`Bank Composition Details DTO Projection Decision.md`](./Bank%20Composition%20Details%20DTO%20Projection%20Decision.md) +- [`Bank Composition Base Components Decision.md`](./Bank%20Composition%20Base%20Components%20Decision.md) + +This decision closes the shell direction discussed in: + +- [`Agenda-03-Asset-Bank-Composition-Section-Shell.md`](../agendas/Agenda-03-Asset-Bank-Composition-Section-Shell.md) + +## Decision + +Create the `Bank Composition` section shell early, before full behavior is implemented. + +The shell contract is: + +1. `Bank Composition` is a `VBox` section inside `Asset Details`; +2. the section shell should mirror `Runtime Contract` as closely as practical at the JavaFX composition level; +3. the section should align with the existing `FormSession` staged-editing pattern; +4. the section header and action cluster must support `change`, `apply`, `reset`, and `cancel`; +5. the body layout must reserve the dual-list region on the left and the capacity-meter region on the right; +6. outside `change` mode, the section should render the current persisted state as read-only; +7. before middleware wiring exists, the section body should still render disabled or read-only internals rather than an empty placeholder. + +## Justification + +This keeps the editing model of `Asset Details` coherent. + +The developer should not need to learn one staged-edit contract for `Runtime Contract` and another for `Bank Composition`. +Using the same shell and `FormSession` rhythm lowers implementation risk and reduces UI inconsistency. + +Rendering the current persisted state in read-only mode is also the better default. +It teaches the surface, shows that data exists, and avoids making the section look unfinished or absent whenever editing is not active. + +## Invariants and Constraints + +The following constraints now apply: + +1. `Bank Composition` must exist as a real section shell before middleware behavior is complete; +2. the shell must follow the same staged-edit interaction model already used by `Runtime Contract`; +3. `FormSession` is part of the expected section lifecycle; +4. the section must not collapse into a blank placeholder when behavior is still incomplete; +5. the shell layout must already reflect the intended dual-list plus capacity-meter structure. + +## Explicit Non-Decisions + +This decision does not yet define: + +- the middleware/controller contract; +- the `workspaceBus` event contract; +- the exact disabled/read-only visuals of the early shell; +- apply persistence behavior; +- family-specific meter semantics beyond the already agreed general direction. + +## Propagation Targets + +- Studio agendas: + [`Agenda-04-Asset-Bank-Composition-Middleware-and-Staged-Editing.md`](../agendas/Agenda-04-Asset-Bank-Composition-Middleware-and-Staged-Editing.md) + [`Agenda-05-Asset-Bank-Composition-WorkspaceBus-Interaction.md`](../agendas/Agenda-05-Asset-Bank-Composition-WorkspaceBus-Interaction.md) + [`Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md`](../agendas/Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md) +- Studio specs: + [`4. Assets Workspace Specification.md`](../specs/4.%20Assets%20Workspace%20Specification.md) +- Studio code: + `AssetDetailsControl`, the future `Bank Composition` section control, and any `FormSession` integration needed for staged editing + +## Validation Notes + +Examples implied by this decision: + +- the section can appear in the details view even before middleware logic exists; +- the shell can show current selection state in read-only mode when the user has not entered `change`; +- the same section-level action rhythm used by `Runtime Contract` should apply to `Bank Composition`. diff --git a/docs/studio/decisions/Bank Composition WorkspaceBus Interaction Decision.md b/docs/studio/decisions/Bank Composition WorkspaceBus Interaction Decision.md new file mode 100644 index 00000000..a09667bd --- /dev/null +++ b/docs/studio/decisions/Bank Composition WorkspaceBus Interaction Decision.md @@ -0,0 +1,106 @@ +# Bank Composition WorkspaceBus Interaction Decision + +Status: Decided +Cycle: 2026-03 +Domain Owner: `docs/studio` +Cross-Domain Impact: `docs/packer` + +## Context + +The `Bank Composition` section should integrate with the Studio workspace event model, but the first-wave `workspaceBus` surface needs to stay intentionally small. + +The previous decisions already fixed: + +- DTO projection: + [`Bank Composition Details DTO Projection Decision.md`](./Bank%20Composition%20Details%20DTO%20Projection%20Decision.md) +- base components: + [`Bank Composition Base Components Decision.md`](./Bank%20Composition%20Base%20Components%20Decision.md) +- section shell: + [`Bank Composition Section Shell Decision.md`](./Bank%20Composition%20Section%20Shell%20Decision.md) +- middleware and staged editing: + [`Bank Composition Middleware and Staged Editing Decision.md`](./Bank%20Composition%20Middleware%20and%20Staged%20Editing%20Decision.md) + +This decision closes the first-wave event direction discussed in: + +- [`Agenda-05-Asset-Bank-Composition-WorkspaceBus-Interaction.md`](../agendas/Agenda-05-Asset-Bank-Composition-WorkspaceBus-Interaction.md) + +## Decision + +Adopt a minimal, notification-oriented first-wave `workspaceBus` contract for `Bank Composition`. + +The first-wave rules are: + +1. user actions should stay local to the bank-composition middleware/controller whenever possible; +2. the first public `workspaceBus` surface should publish only state transitions or lifecycle notifications that matter outside the section; +3. the event contract must not encode bank-family product rules directly into event types; +4. capacity notifications should use absolute progress in the `0..1` range, not deltas. + +The first-wave public notification set is: + +- `BankCompositionDraftChanged` +- `BankCompositionCapacityChanged` +- `BankCompositionApplyRequested` +- `BankCompositionApplied` +- `BankCompositionApplyFailed` + +The first-wave local-only action set remains inside the middleware/controller: + +- `beginEdit` +- `moveToSelected` +- `moveToAvailable` +- `moveUp` +- `moveDown` +- `reset` +- `cancel` +- `apply` + +The first-wave capacity notification should expose at least: + +- `progress` +- `severity` +- `blocked` + +## Justification + +This preserves the workspace event architecture without inflating the bus contract too early. + +If every section interaction became a public event, the bus would turn into a noisy command surface with little external value. +The middleware/controller is already the right local place for section commands and recalculation. + +Absolute capacity state is also the right public shape. +It is easier to consume, easier to reason about, and safer for late subscribers than delta-based updates. + +## Invariants and Constraints + +The following constraints now apply: + +1. the first-wave public bus contract is notification-oriented, not command-oriented; +2. section-local interactions should not become public events unless another subscriber truly needs them; +3. capacity state must be published as absolute progress; +4. the bus contract must stay bank-family-neutral at the event-type level. + +## Explicit Non-Decisions + +This decision does not yet define: + +- the exact Java class names or package layout for the new events; +- the full payload shape of each event beyond the minimum capacity fields already fixed; +- whether future cross-section coordination will require more bus events; +- apply persistence semantics with packer. + +## Propagation Targets + +- Studio agendas: + [`Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md`](../agendas/Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md) +- Studio specs: + [`4. Assets Workspace Specification.md`](../specs/4.%20Assets%20Workspace%20Specification.md) +- Studio code: + bank-composition middleware/controller, event definitions, and event subscribers in `Asset Details` + +## Validation Notes + +Examples implied by this decision: + +- dragging or reordering inside the dual list does not require a public bus command in the first wave; +- the capacity meter can react to a published absolute progress state such as `0.72` with `orange` severity and `blocked=false`; +- apply success or failure can be observed outside the section without exposing every internal section action as a bus event. diff --git a/docs/studio/decisions/README.md b/docs/studio/decisions/README.md index f215135b..f139d0dc 100644 --- a/docs/studio/decisions/README.md +++ b/docs/studio/decisions/README.md @@ -2,7 +2,14 @@ This directory contains Studio decision records. -There are currently no retained Studio decision records. +Current decision records: + +- [`Bank Composition Details DTO Projection Decision.md`](./Bank%20Composition%20Details%20DTO%20Projection%20Decision.md) +- [`Bank Composition Base Components Decision.md`](./Bank%20Composition%20Base%20Components%20Decision.md) +- [`Bank Composition Section Shell Decision.md`](./Bank%20Composition%20Section%20Shell%20Decision.md) +- [`Bank Composition Middleware and Staged Editing Decision.md`](./Bank%20Composition%20Middleware%20and%20Staged%20Editing%20Decision.md) +- [`Bank Composition WorkspaceBus Interaction Decision.md`](./Bank%20Composition%20WorkspaceBus%20Interaction%20Decision.md) +- [`Bank Composition Persistence and Snapshot Propagation Decision.md`](./Bank%20Composition%20Persistence%20and%20Snapshot%20Propagation%20Decision.md) The first Studio decision wave and the first asset workspace wave were already consolidated into: diff --git a/test-projects/main/.studio/activities.json b/test-projects/main/.studio/activities.json index ab1bb565..167fe9fb 100644 --- a/test-projects/main/.studio/activities.json +++ b/test-projects/main/.studio/activities.json @@ -3,6 +3,156 @@ "message" : "7 assets loaded", "severity" : "SUCCESS", "sticky" : false +}, { + "source" : "Assets", + "message" : "Asset scan diagnostics updated.", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: bla", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: one-more-atlas", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: ui_atlas", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: one-more-atlas", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: bbb2", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: ui_atlas", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: Bigode", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Asset scan started", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "7 assets loaded", + "severity" : "SUCCESS", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Asset scan diagnostics updated.", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: bla", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: one-more-atlas", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: ui_atlas", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: one-more-atlas", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: bbb2", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: ui_atlas", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: Bigode", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Asset scan started", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "7 assets loaded", + "severity" : "SUCCESS", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Asset scan diagnostics updated.", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: bla", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: one-more-atlas", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: ui_atlas", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: one-more-atlas", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: bbb2", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: ui_atlas", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Discovered asset: Bigode", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "Asset scan started", + "severity" : "INFO", + "sticky" : false +}, { + "source" : "Assets", + "message" : "7 assets loaded", + "severity" : "SUCCESS", + "sticky" : false }, { "source" : "Assets", "message" : "Discovered asset: bla", @@ -2348,154 +2498,4 @@ "message" : "Discovered asset: Bigode", "severity" : "INFO", "sticky" : false -}, { - "source" : "Assets", - "message" : "Asset scan started", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "7 assets loaded", - "severity" : "SUCCESS", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: test", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: one-more-atlas", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: ui_atlas", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: bla", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: one-more-atlas", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: ui_atlas", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: Bigode", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Asset scan started", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "7 assets loaded", - "severity" : "SUCCESS", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: test", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: one-more-atlas", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: ui_atlas", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: bla", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: one-more-atlas", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: ui_atlas", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: Bigode", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Asset scan started", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "7 assets loaded", - "severity" : "SUCCESS", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: test", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: one-more-atlas", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: ui_atlas", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: bla", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: one-more-atlas", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: ui_atlas", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: Bigode", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Asset scan started", - "severity" : "INFO", - "sticky" : false -}, { - "source" : "Assets", - "message" : "7 assets loaded", - "severity" : "SUCCESS", - "sticky" : false -}, { - "source" : "Assets", - "message" : "Discovered asset: test", - "severity" : "INFO", - "sticky" : false } ] \ No newline at end of file diff --git a/test-projects/main/assets/.prometeu/cache.json b/test-projects/main/assets/.prometeu/cache.json new file mode 100644 index 00000000..a2fecbdf --- /dev/null +++ b/test-projects/main/assets/.prometeu/cache.json @@ -0,0 +1,59 @@ +{ + "schema_version" : 1, + "assets" : [ { + "asset_id" : 3, + "files" : [ { + "relative_path" : "confirm.png", + "mime_type" : "image/png", + "size" : 137, + "last_modified" : 1773571367191, + "fingerprint" : "aa7d241deabcebe29a6096e14eaf16fdc06cf06380c11a507620b00fc7bff094", + "metadata" : { + "tile" : { + "width" : 16, + "height" : 16, + "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAEBAQEBAQEBAQEBAQAAAAABAQEBAQEBAQEBAQEAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAABAQEBAQEAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAAAAAAAAAAEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + } + } + } ] + }, { + "asset_id" : 7, + "files" : [ ] + }, { + "asset_id" : 8, + "files" : [ ] + }, { + "asset_id" : 11, + "files" : [ ] + }, { + "asset_id" : 12, + "files" : [ { + "relative_path" : "confirm.png", + "mime_type" : "image/png", + "size" : 137, + "last_modified" : 1773253076764, + "fingerprint" : "aa7d241deabcebe29a6096e14eaf16fdc06cf06380c11a507620b00fc7bff094", + "metadata" : { + "tile" : { + "width" : 16, + "height" : 16, + "paletteIndices" : "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAEBAQEBAQEBAQEBAQAAAAABAQEBAQEBAQEBAQEAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAABAQEBAQEAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAAAAAAAAAAEBAQEBAQ==" + }, + "palette" : { + "originalArgb8888" : [ -265674 ], + "convertedRgb565" : [ -122 ] + } + } + } ] + }, { + "asset_id" : 13, + "files" : [ ] + }, { + "asset_id" : 14, + "files" : [ ] + } ] +} \ No newline at end of file