asset walker (WIP)

This commit is contained in:
bQUARKz 2026-03-19 00:28:36 +00:00
parent b4733a0e49
commit c4b7acab6f
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
17 changed files with 1629 additions and 152 deletions

View File

@ -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.

View File

@ -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<T>`
- `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<T>` 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<T>` 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<T>` 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<T>` 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<T>` and `StudioAssetCapacityMeter`.

View File

@ -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.

View File

@ -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<T>` 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<BankCompositionDraft>` 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<BankCompositionDraft>` 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<BankCompositionDraft>`, 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.

View File

@ -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`.

View File

@ -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.

View File

@ -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<T>` 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<T>` 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<T>` is the component name for the transfer-list surface of this section;
- `StudioDualListView<T>` should be introduced as an abstract Studio component created for this bank-composition section;
- `StudioDualListView<T>` 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<T>` 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<T>` 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<T>` 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.

View File

@ -2,7 +2,15 @@
This directory contains active Studio discussion agendas. 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/). The shell, UI foundations, components admission baselines, and the first asset workspace wave were already consolidated into [`../specs/`](../specs/) and [`../learn/`](../learn/).

View File

@ -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<T>`
- `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<T>` 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<T>` 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<T>` must remain abstract in the first wave;
2. the first concrete `StudioDualListView<T>` 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<T>`, 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.

View File

@ -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.

View File

@ -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<T>` 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<BankCompositionDraft>`.
The first-wave rules are:
1. `StudioFormSession<BankCompositionDraft>` 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<BankCompositionDraft>` 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.

View File

@ -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`.

View File

@ -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`.

View File

@ -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.

View File

@ -2,7 +2,14 @@
This directory contains Studio decision records. 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: The first Studio decision wave and the first asset workspace wave were already consolidated into:

View File

@ -3,6 +3,156 @@
"message" : "7 assets loaded", "message" : "7 assets loaded",
"severity" : "SUCCESS", "severity" : "SUCCESS",
"sticky" : false "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", "source" : "Assets",
"message" : "Discovered asset: bla", "message" : "Discovered asset: bla",
@ -2348,154 +2498,4 @@
"message" : "Discovered asset: Bigode", "message" : "Discovered asset: Bigode",
"severity" : "INFO", "severity" : "INFO",
"sticky" : false "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
} ] } ]

View File

@ -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" : [ ]
} ]
}