296 lines
14 KiB
Markdown
296 lines
14 KiB
Markdown
# Pack Wizard Studio Decision Propagation Agenda
|
|
|
|
Status: Open
|
|
Domain Owner: `docs/packer`
|
|
Cross-Domain Impact: `docs/studio`
|
|
|
|
## Purpose
|
|
|
|
Converge the packer-side discussion that still remains open after the first `Pack Wizard` propagation wave: the actual `packing` operation.
|
|
|
|
`summary` and `validation` are already closed enough to implement and consume.
|
|
What is still unresolved is how `pack execution` should behave as a packer-owned operation when Studio enters the `Packing` and `Result` phases.
|
|
|
|
This agenda is therefore about execution semantics, artifact emission, progress visibility, and failure boundaries for `packWorkspace(...)`.
|
|
|
|
## Problem
|
|
|
|
The repository already closed the Studio shell boundary and the packer-side preflight boundary, but the actual pack execution contract is still underspecified.
|
|
|
|
Today the gap is concrete:
|
|
|
|
1. Studio already depends on a four-phase wizard:
|
|
`Summary`, `Validation`, `Packing`, `Result`;
|
|
2. the public packer API already exposes `packWorkspace(...)`;
|
|
3. `prometeu-packer-v1` still throws `UnsupportedOperationException` for that operation;
|
|
4. the specs define `assets.pa` authority and deterministic ordering, but they do not yet define the operational semantics for emitting that artifact through the Studio-facing service boundary.
|
|
|
|
Without this agenda, implementation risks falling into one of these traps:
|
|
|
|
- a direct file-write implementation that leaks partial artifacts;
|
|
- a Studio-visible progress model that is too vague to support the wizard honestly;
|
|
- an execution path that does not clearly separate validation failure from emission failure;
|
|
- or a result contract that is too poor for the `Result` phase even if the pack technically succeeds.
|
|
|
|
## Context
|
|
|
|
The upstream state is now clear enough to isolate the remaining question.
|
|
|
|
Already closed:
|
|
|
|
- Studio is a shell over packer-owned semantics:
|
|
[`../../studio/decisions/Pack Wizard in Assets Workspace Decision.md`](../../studio/decisions/Pack%20Wizard%20in%20Assets%20Workspace%20Decision.md)
|
|
- packer-side `summary` and `validation` contracts are accepted:
|
|
[`../decisions/Pack Wizard Summary and Validation Contracts Decision.md`](../decisions/Pack%20Wizard%20Summary%20and%20Validation%20Contracts%20Decision.md)
|
|
- runtime artifact authority is already normative:
|
|
[`../specs/4. Build Artifacts and Deterministic Packing Specification.md`](../specs/4.%20Build%20Artifacts%20and%20Deterministic%20Packing%20Specification.md)
|
|
- event causality and serialized operation rules are already normative:
|
|
[`../specs/5. Diagnostics, Operations, and Studio Integration Specification.md`](../specs/5.%20Diagnostics,%20Operations,%20and%20Studio%20Integration%20Specification.md)
|
|
|
|
Current code context:
|
|
|
|
- `getPackWorkspaceSummary(...)` already exists in `FileSystemPackerWorkspaceService`;
|
|
- `validatePackWorkspace(...)` already exists in `FileSystemPackerWorkspaceService`;
|
|
- `packWorkspace(...)` exists in the public API but is not implemented in `prometeu-packer-v1`;
|
|
- the current `PackWorkspaceResult` shape is minimal, but the operational meaning of its fields is not fully closed.
|
|
|
|
That means the current decision gap is no longer about whether packing should exist.
|
|
It is about what guarantees `packWorkspace(...)` must provide when it starts emitting runtime-facing artifacts.
|
|
|
|
## Options
|
|
|
|
### Option A - Direct in-place pack with minimal lifecycle semantics
|
|
|
|
Implement `packWorkspace(...)` as one serialized write-lane operation that:
|
|
|
|
- optionally reruns the validation gate;
|
|
- emits `assets.pa` and companion artifacts directly into their final locations;
|
|
- publishes a small number of lifecycle events;
|
|
- returns one final result DTO with success or failure.
|
|
|
|
### Option B - Staged pack transaction with explicit lifecycle phases
|
|
|
|
Implement `packWorkspace(...)` as one serialized packer-owned execution flow with explicit internal phases:
|
|
|
|
1. gate
|
|
2. plan/materialize
|
|
3. stage emit
|
|
4. commit/promote
|
|
5. finalize result
|
|
|
|
The operation still appears to Studio as one `packWorkspace(...)` call, but the packer gives stronger semantics:
|
|
|
|
- validation is rechecked at execution start;
|
|
- emitted files are staged before final promotion;
|
|
- final artifact visibility changes only at commit;
|
|
- progress events map to meaningful lifecycle boundaries;
|
|
- the final result distinguishes validation, emission, and persistence failure classes.
|
|
|
|
### Option C - Detached build session abstraction
|
|
|
|
Introduce a larger `PackSession`-style model or resumable build-session protocol for packing.
|
|
|
|
Studio would create a session, observe step state, and then explicitly finalize or close it.
|
|
|
|
## Tradeoffs
|
|
|
|
- Option A is the smallest implementation step, but it leaves too many failure and visibility rules implicit.
|
|
- Option A also makes it easier to leak partially written artifacts into final paths if the process fails mid-pack.
|
|
- Option B fits the existing service boundary while still making artifact visibility and progress semantics explicit.
|
|
- Option B also aligns well with the current specs:
|
|
serialized writes, causal events, deterministic outputs, and packer-owned truth.
|
|
- Option B adds some implementation structure, but that structure corresponds to real operational risk and is not ceremonial.
|
|
- Option C could become attractive later if the build system needs cancellation, resume, remote workers, or richer host orchestration.
|
|
- Option C is too heavy for the current repository state and would introduce a second interaction model before the first one is stable.
|
|
|
|
## Recommendation
|
|
|
|
Adopt `Option B`.
|
|
|
|
The packer should keep `packWorkspace(...)` as a single public service operation, but internally define and honor explicit execution phases with staged emission and an atomic final visibility boundary.
|
|
|
|
### Execution Boundary Recommendation
|
|
|
|
`packWorkspace(...)` should be the only first-wave operation that emits build artifacts.
|
|
|
|
Rules:
|
|
|
|
- it runs through the packer-owned serialized write lane for the project;
|
|
- it evaluates the active pack set as `registered + included in build`;
|
|
- it must perform an internal gate check before emitting artifacts, even if Studio already ran `validation`;
|
|
- it must freeze the execution input set before materialization begins;
|
|
- a failing gate returns a terminal result without creating final artifacts.
|
|
|
|
This avoids trusting host orchestration timing as if it were a correctness guarantee.
|
|
|
|
### Frozen Snapshot Recommendation
|
|
|
|
`packWorkspace(...)` should not pack from live filesystem rereads after execution begins.
|
|
|
|
Recommended first-wave baseline:
|
|
|
|
- the packer creates a frozen pack-execution snapshot before materialization starts;
|
|
- that frozen snapshot is derived from the current runtime snapshot but enriches build-relevant walk files with in-memory content bytes;
|
|
- content bytes are needed only for:
|
|
- registered assets included in build;
|
|
- artifact files that actually participate in the current build output;
|
|
- non-build assets and non-selected artifact files do not need in-memory content in the pack-execution snapshot;
|
|
- the current runtime snapshot model should expose file bytes as optional rather than introducing a second snapshot model in the first wave;
|
|
- `PackerRuntimeWalkFile` should therefore carry optional content bytes so the packer can freeze build-relevant inputs without forcing all runtime-backed reads to retain content unnecessarily;
|
|
- the family walkers may continue to produce full file probes with bytes loaded during probe processing;
|
|
- the variation for runtime versus packing should happen when probe results are exported into the runtime walk projection;
|
|
- walker materialization must therefore gain clearer execution context/config so build-focused flows can request content bytes intentionally instead of coupling that behavior to every normal read path.
|
|
|
|
This preserves precision without turning the general runtime snapshot into a blanket in-memory mirror of the workspace.
|
|
|
|
### Walker Policy Recommendation
|
|
|
|
The current walker baseline should remain family-oriented and generalist.
|
|
|
|
Recommended first-wave baseline:
|
|
|
|
- family walkers continue to discover files relevant to the asset family;
|
|
- that family-oriented discovery remains the normal runtime-backed mode;
|
|
- packing adds one extra selection layer instead of redefining walker discovery itself;
|
|
- the extra selection layer filters the discovered probe results down to the files that actually participate in the current build output;
|
|
- the same export layer also decides whether optional content bytes are injected into `PackerRuntimeWalkFile`.
|
|
|
|
This means the first-wave split should be:
|
|
|
|
1. family-relevant probe discovery in the walkers;
|
|
2. export/materialization policy for runtime projection;
|
|
3. packing-specific projection filter over discovered probe results;
|
|
4. optional byte injection only when the export policy requests it.
|
|
|
|
This is intentionally conservative.
|
|
It keeps the walkers on known ground and moves the packing-specific behavior into one explicit projection/materialization policy layer.
|
|
|
|
Recommended config shape:
|
|
|
|
```java
|
|
public record PackerRuntimeMaterializationConfig(
|
|
PackerWalkMode mode,
|
|
Predicate<PackerProbeResult> projectionFilter) {
|
|
|
|
public static PackerRuntimeMaterializationConfig runtimeDefault() {
|
|
return new PackerRuntimeMaterializationConfig(PackerWalkMode.RUNTIME, probe -> true);
|
|
}
|
|
|
|
public static PackerRuntimeMaterializationConfig packingBuild() {
|
|
return new PackerRuntimeMaterializationConfig(
|
|
PackerWalkMode.PACKING,
|
|
PackerProbePolicies::isIncludedInCurrentBuild);
|
|
}
|
|
}
|
|
```
|
|
|
|
With this baseline:
|
|
|
|
- `PackerWalkMode.RUNTIME` means runtime-backed general projection and suppresses optional content bytes during export;
|
|
- `PackerWalkMode.PACKING` means packing-focused projection and injects optional content bytes during export;
|
|
- `projectionFilter` decides which discovered probe results actually survive into `PackerRuntimeWalkFile`;
|
|
- the first-wave packing filter should keep only current-build probe results;
|
|
- byte injection behavior is derived from `mode` rather than from a second explicit boolean in the first wave.
|
|
|
|
### Emission Recommendation
|
|
|
|
Artifact emission should be staged before promotion into final visible locations.
|
|
|
|
Recommended first-wave baseline:
|
|
|
|
- materialize `assets.pa` and companion artifacts in a staging location owned by the packer operation;
|
|
- use `build/.staging/<operation-id>/` as the first-wave staging location;
|
|
- `<operation-id>` should be one random 20-character alphanumeric identifier;
|
|
- if a staging directory collision happens for that identifier, the packer may overwrite that staging directory rather than adding a second collision-resolution protocol in the first wave;
|
|
- treat staging output as non-authoritative until commit;
|
|
- promote staged files into final `build/` locations only after the operation reaches a coherent success point;
|
|
- if emission fails before commit, final artifact locations must remain unchanged from the caller's point of view.
|
|
|
|
This is the safest baseline for a filesystem-first packer.
|
|
It keeps durable visibility aligned with a packer-owned commit boundary rather than with incidental file-write timing.
|
|
|
|
### Progress Recommendation
|
|
|
|
Progress should continue to flow through the existing packer event path rather than through a polling-specific result shape.
|
|
|
|
The first-wave lifecycle should be observable through summaries and progress updates equivalent to:
|
|
|
|
1. `packing_started`
|
|
2. `packing_validating`
|
|
3. `packing_materializing`
|
|
4. `packing_emitting`
|
|
5. `packing_finalizing`
|
|
6. terminal success or failure
|
|
|
|
The exact event kind names can still be finalized in the decision, but the meaning must be explicit enough for Studio to render the `Packing` phase honestly without fake timers or inferred state.
|
|
|
|
### Result Recommendation
|
|
|
|
The final `PackWorkspaceResult` should stay compact but semantically explicit.
|
|
|
|
The primary result summary should expose at least:
|
|
|
|
- final status;
|
|
- whether validation failed or execution actually began;
|
|
- canonical build-relative `assets.pa` artifact reference;
|
|
- build-relative companion artifact references when emitted;
|
|
- total packed asset count;
|
|
- elapsed time in milliseconds.
|
|
|
|
The first-wave `Result` phase in Studio does not need a full build report dump, but it does need enough structure to distinguish successful pack, blocked pack, and failed pack after execution started.
|
|
|
|
### Failure Recommendation
|
|
|
|
The packer should distinguish at least three terminal classes:
|
|
|
|
1. validation gate failure before emission;
|
|
2. execution or materialization failure during pack generation;
|
|
3. persistence or promotion failure while making artifacts final.
|
|
|
|
These classes matter because they map directly to the Studio `Result` phase already decided upstream.
|
|
|
|
### Build Output Recommendation
|
|
|
|
The packer publication boundary for this flow should remain `build/`.
|
|
|
|
Recommended first-wave baseline:
|
|
|
|
- `packWorkspace(...)` publishes final outputs to `build/`;
|
|
- the canonical runtime-facing artifact is `build/assets.pa`;
|
|
- the baseline companion artifacts are:
|
|
- `build/asset_table.json`
|
|
- `build/preload.json`
|
|
- `build/asset_table_metadata.json`
|
|
- a future shipper may consume those packer outputs together with `program.pbx`;
|
|
- the shipper is mentioned here only to keep the boundary explicit, not because it participates in `packWorkspace(...)`.
|
|
|
|
This keeps the current domain boundary intact:
|
|
the packer publishes build artifacts and the shipper assembles cartridges.
|
|
|
|
## Open Questions
|
|
|
|
None for the first-wave execution shape.
|
|
The remaining work is to convert this agenda into a decision and then propagate the agreed materialization policy into code and specs.
|
|
|
|
## Recommendation Summary
|
|
|
|
This agenda recommends closing the first-wave `packing` contract as:
|
|
|
|
1. one packer-owned `packWorkspace(...)` operation;
|
|
2. internally phased and serialized through the project write lane;
|
|
3. guarded by a packer-owned validation check at execution start;
|
|
4. based on one frozen in-memory execution snapshot for the build-relevant asset bytes;
|
|
5. staged under `build/.staging/<operation-id>/` before promotion to final artifact visibility in `build/`;
|
|
6. observable through causality-preserving progress events;
|
|
7. finished with a result that distinguishes blocked, failed, and successful pack outcomes.
|
|
|
|
## Next Suggested Step
|
|
|
|
Convert this agenda into a `docs/packer` decision focused on `pack execution` semantics and propagation targets.
|
|
|
|
That decision should then drive:
|
|
|
|
1. one PR for `prometeu-packer-api` result and event-contract adjustments, if needed;
|
|
2. one PR for `prometeu-packer-v1` execution, staging, and artifact-promotion behavior;
|
|
3. one Studio PR to bind the `Packing` and `Result` phases to the final packer-owned execution contract.
|