fix(deploy): label merged/raw mods and name the merged artifact in deploy output (#255) - #264
Conversation
…ame the merged artifact (#255) On a DeployCompile game, per-mod success lines counted mods that individually deployed nothing, and the one artifact that actually reached the game directory - the profile-level merged pak built after the loop - was never named. Issue #255's decided option (b): - core: classify each mod BEFORE the deploy loop (enabledMergeSources) as merged / raw / individual, carried on DeployDeployed via the new DeployProgress.ModClass (DeployModClass enum); after a successful syncMergedPak, emit one new DeployMergeSynced event (participant count, artifact name via source.MergeCompiler.MergedArtifactName - no format literals in core, #256) and mirror the readout on DeployResult (MergedArtifact/MergedMods/RawFallbacks) for progress-less callers. - CLI: compile-mode header drops the misleading "using <method>"; per-mod lines label "(merged)" / "(raw)"; a post-sync footer prints "Merged N mod(s) -> <artifact>" (plus "(N deployed raw)" on conversion fallbacks) directly above "Deployed: N", which still counts merge participants. The one optimistic case - a pak labeled (merged) whose conversion then fails - is corrected by the existing conversion-failure warning plus the footer, per the issue's decided design. - TUI parity: coreProvider.DeployProfile appends the merge readout to the one-row Message from the new DeployResult fields (progress is nil there; warnings channel deliberately avoided - #253's overlay auto-opens on 2+). Non-compile deploy output is byte-identical; all pre-existing deploy tests pass untouched. New coverage: all three mod classes at core and CLI level, the conversion-failure correction path at both levels, non-compile gating, and the TUI message. Fixes #255 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR implements issue #255’s “option (b)” deploy readout for compile-mode games by pre-classifying mods before the deploy loop, labeling per-mod output accordingly, and emitting a post-sync merged-artifact footer (plus result fields for progress-less callers like the TUI).
Changes:
- Add compile-mode deploy classification (
DeployModClass) and a one-shot post-sync phase (DeployMergeSynced), plusDeployResultfields to carry merged artifact/counts. - Update CLI deploy output to (a) drop the misleading
using <method>header on compile games, (b) label per-mod lines as(merged)/(raw), and (c) print a merged-artifact footer above the summary. - Update TUI deploy outcome message to include merged-artifact readout based on
DeployResult(since TUI deploy currently has no progress stream), and add targeted test coverage.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/tui/service_core.go | Extends the one-row deploy outcome message to include merged artifact + counts when present. |
| internal/tui/service_core_deploy_compile_test.go | Adds a TUI parity test asserting the merged artifact is named in the deploy message (and not routed through warnings). |
| internal/core/merged_pak.go | Adds pre-loop compile deploy classification and post-sync merge outcome recording onto DeployResult + progress. |
| internal/core/flows.go | Introduces DeployMergeSynced, DeployModClass, and new fields on DeployProgress/DeployResult; wires classification + merge outcome into DeployProfile. |
| internal/core/flows_deploy_compile_readout_test.go | Adds core-level tests for 3-way classification, merge event ordering, raw-fallback reporting, and non-compile gating. |
| cmd/lmm/deploy.go | Adjusts CLI output for compile mode (header, per-mod labels, merged footer placement) while preserving non-compile output. |
| cmd/lmm/deploy_compile_test.go | Adds CLI compile-mode tests for labels/footer and conversion-failure correction behavior. |
| CHANGELOG.md | Documents the corrected compile-mode deploy readout behavior for CLI + TUI (#255). |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| case core.DeployMergeSynced: | ||
| // #255: the post-sync footer naming the merged artifact. Fires | ||
| // only after the deploy loop (some per-mod event has already | ||
| // printed the header), and its Total is the merge-participant | ||
| // count, not the deploy total - so it must not fall through to | ||
| // printDeployHeaderOnce below. |
There was a problem hiding this comment.
Confirmed — the comment overstated it: core sets Total to the mods the merged artifact actually carries (raw fallbacks are excluded and ride RawFallbacks). Reworded in 98fe168.
| // MergeSource.ModRef carries. Returns nil for a non-compile game and on any | ||
| // resolution failure - classification is a readout, never a reason to fail | ||
| // the deploy, and the zero class is always a safe rendering default. |
There was a problem hiding this comment.
Confirmed mismatch. Kept the best-effort partial-map behavior deliberately (the readout must never fail or degrade the deploy; a partial map only loses labels for later mods in an already-degenerate corner: --all with a disabled retained mod and no compile source configured) and rewrote the doc comment to state that contract honestly in 98fe168.
…t best-effort classify contract (#255) Both round-1 findings were doc-comment accuracy gaps, no behavior change: the CLI footer comment called Total the "merge-participant count" when it counts only mods the artifact actually carries (fallbacks ride RawFallbacks), and classifyCompileDeployMods claimed nil on "any resolution failure" while a mid-walk compiler failure deliberately returns the partial, best-effort map. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fixes #255 — implements the issue's decided option (b) exactly: classify before the loop, correct in the footer.
What changed
Core (
internal/core):DeployProgress.ModClass(DeployModClass: individual / merged / raw), set onDeployDeployed. Classification runs before the deploy loop viaenabledMergeSources— the stored fingerprint is deliberately not consulted (wrong on first deploy).DeployMergeSyncedphase, emitted once after a successfulsyncMergedPakwhen a merged artifact exists:Total= participant count,Detail= artifact name viasource.MergeCompiler.MergedArtifactName()(no format literals in core, per Move Unreal/pak knowledge out of core and behind the MergeCompiler seam (before a second DeployCompile game exists) #256),RawFallbacks= participants that fell back to raw.DeployResultgainsMergedArtifact/MergedMods/RawFallbacksso progress-less callers (the TUI) get the same readout.CLI (
cmd/lmm/deploy.go):The optimistic case — a pak labeled
(merged)whose conversion then fails — is corrected by the existingpak conversion failed … deploying rawwarning plus the footer's(N deployed raw)count.Deployed: Nstill counts merge participants. The Warnings/Notes ↔ event invariant atcmd/lmm/deploy.gois untouched (the merge event is not a warning; nothing double-prints).TUI (
internal/tui/service_core.go):Deployed 1 mod(s) — merged 1 → zzz_LMM_Merged_P.pakin the one-row outcomeMessage, built from the newDeployResultfields. Deliberately not routed through Warnings (#253's overlay auto-opens on 2+ warnings).Guarantees held
grep -n '"[^"]*\.pak"'andgrep -in exmodzover non-testinternal/corematch comments only.Coverage added
Out of scope
DeployMergeSyncedas-is.Verification
go build ./... && go vet ./... && gofmt -l . && go test ./...— all clean;trunk checkon changed files: no new issues. Manual TUI smoke test pending (merge gate, coordinator's step).🤖 Generated with Claude Code