Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
title: "FOMOD archive discovery after download"
status: reviewed
date: 2026-06-14
origin: docs/plans/vortex-mo2-feature-parity-living-plan.md
---

# FOMOD archive discovery after download

## Summary

After GUI downloads finish, detect FOMOD installers inside downloaded archives and
optionally prompt the user to run the existing FOMOD configuration wizard. Skipping
is allowed and remembered per archive file.

## Problem Frame

FOMOD parser and installer dialog exist, but discovery still requires the user to
manually pick an extracted folder via **Configure FOMOD Mod**. Downloads already land
archives in the mod workspace without surfacing FOMOD packages automatically.

## Requirements

**Download detection and prompt**

- R1: After a GUI download session completes, scan selected components' downloaded
archive files in the mod directory using archive entry listing (no full extract for
detection).
- R2: When `fomod/ModuleConfig.xml` is found, show an optional post-download prompt to
configure installer options now.
- R3: Choosing **No** dismisses the prompt for that archive on that component; the user
can still use **Configure FOMOD Mod** manually later.
- R4: Choosing **Yes** extracts the archive to the mod workspace, runs the existing
FOMOD wizard, and merges generated options/instructions into the existing component.

**Archive enumeration**

- R5: When building the mod file tree, mark archive nodes that contain a FOMOD
installer so the UI can distinguish them later.

**Persistence**

- R6: Dismissed and configured outcomes are stored per archive file name on the
component's resource metadata so prompts do not repeat unnecessarily.

## Success Criteria

- A downloaded archive containing `fomod/ModuleConfig.xml` triggers the post-download
prompt once per archive until dismissed or configured.
- Accepting the prompt runs the existing FOMOD wizard without requiring a manual folder
picker first.
- Archive enumeration marks FOMOD archives without requiring extraction.

## Scope Boundaries

**In scope**

- GUI download orchestration path used by **Fetch Downloads** (wizard and Getting
Started).
- Reuse of `FomodDetector`, `FomodInstallerDialog`, and existing mapper/presenter stack.

**Deferred**

- CLI download/install parity.
- Validation blocking when FOMOD choices are unset.
- Plugin images and advanced conditional file-install runtime beyond current mapper.

## Key Decisions

- Detection uses archive entry listing; extraction happens only when the user accepts
the prompt.
- Prompt state is tracked per archive file name in resource handler metadata.
- Wizard output merges into the existing instruction-file component rather than
creating a separate standalone component.

## Outstanding Questions

- Whether all GUI download entry points beyond **Fetch Downloads** should share the
same prompt hook in a follow-up slice.
101 changes: 101 additions & 0 deletions docs/brainstorms/2026-06-14-fomod-cli-download-prompts-requirements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
---
title: "CLI FOMOD post-download prompts"
status: reviewed
date: 2026-06-14
origin: docs/brainstorms/2026-06-14-fomod-archive-discovery-requirements.md
supersedes_deferred: CLI download/install parity from GUI FOMOD discovery slice
---

# CLI FOMOD post-download prompts

## Summary

After CLI download phases on `install`, `convert`, and `merge`, detect FOMOD installers in downloaded archives and offer the same configuration outcomes as the GUI post-download hook. Interactive terminals run a full step wizard; non-interactive environments warn and continue by default, with global configuration via CLI flags, environment variables, and ModSync settings.

## Problem Frame

PR #169 added GUI post-download FOMOD detection and optional configuration, but headless `install -d` and `convert -d` workflows still download FOMOD archives without surfacing installer choices. Agents and power users running full-build CLI installs hit validation/install with mapper defaults only, diverging from GUI-configured `Choose` options and instructions.

## Requirements

**Post-download detection and scope**

- R1: After CLI download completes on `install -d`, `convert -d`, and `merge -d`, scan **selected** components' downloaded archive files in the mod/source directory using `FomodArchiveProbe` (entry listing, no full extract for detection).
- R2: When `fomod/ModuleConfig.xml` is found and `FomodDownloadPromptState.ShouldPrompt` is true, run the post-download FOMOD flow for that archive.
- R3: Component scope matches GUI: only components with `IsSelected == true` at the hook point (after selection filters are applied for each verb).

**Interactive TTY behavior**

- R4: When stdin is an interactive TTY, ask Yes/No to configure now; **No** calls `MarkDismissed` (GUI parity).
- R5: On **Yes**, extract the archive, run the **full** FOMOD wizard in the terminal (all install steps, groups, and plugin choices) using the same presenter rules as `FomodInstallerDialog`, then merge into the existing component via `FomodConfiguredComponentMerger` and `MarkConfigured`.

**Non-interactive behavior**

- R6: When stdin is not an interactive TTY (CI, agents, redirected I/O), default mode is **warn and continue**: emit a structured `WARN:` line per detected FOMOD archive and proceed without persisting dismiss state.
- R7: Global `--fomod-skip` (and equivalent env/settings) persists `MarkDismissed` for archives handled under that skip policy in the session.
- R8: Non-interactive mode is configurable globally via environment variable, CLI startup/global flags, and ModSync settings dialog; v1 ships the `warn-continue` mode but the resolution pipeline must accept future modes without redesign.

**Agent / automation path**

- R9: Non-interactive runs may supply a FOMOD choices sidecar file (CLI flag and `MODSYNC_FOMOD_CHOICES` env) so cloud agents can configure without TTY; when present, apply selections and `MarkConfigured` without prompting.

**Persistence by verb**

- R10: On `convert -d` (and `merge -d` when output is written), after FOMOD configuration, persist merged component state (options, instructions, `HandlerMetadata` including `fomodPromptStatus`) to the instruction output path.
- R11: On `install -d`, FOMOD changes apply in-memory for the current run only unless the user sets an explicit output/save flag documented in the plan.

**Shared orchestration**

- R12: Core owns post-download FOMOD orchestration; GUI and CLI are thin hosts over the same service (unified pipeline parity with validation).
- R13: Headless `FomodInstallerPresenter` lives in Core so CLI does not reference Avalonia.

**Correctness fixes bundled in this slice**

- R14: Applying wizard selections must not merge plugins from steps that are no longer visible after condition-flag changes (hidden-step parity with visible validation).
- R15: Re-configuring the same archive updates existing option selections and replaces superseded FOMOD-generated instructions instead of silently skipping duplicate option GUIDs.

## Success Criteria

- Headless `install -d` against a fixture with a FOMOD archive prompts on TTY, applies choices, and proceeds to validation with merged options.
- Non-TTY `convert -d` emits `WARN:` once per unprompted archive and does not hang on `ReadLine`.
- `--fomod-skip` on a non-TTY run persists dismissed state into serialized TOML on convert output.
- `--fomod-choices` configures a FOMOD mod without TTY and marks configured state.
- GUI **Fetch Downloads** behavior unchanged after GUI delegates to the Core orchestrator.
- `docs/knowledgebase/agent-action-parity.md` documents post-download FOMOD configure for CLI.

## Scope Boundaries

**In scope**

- Core orchestrator, CLI console host, GUI adapter refactor, settings/env/CLI config resolution, tests, KB updates.
- Hooks on `install -d`, `convert -d`, `merge -d`.
- Spectre.Console or equivalent injectable console prompt layer behind a host interface.

**Deferred for later**

- Validation blocking when FOMOD choices are unset.
- Plugin images in terminal wizard.
- Download scope alignment so CLI only downloads `IsSelected` components (separate download-system change).
- Additional non-TTY modes beyond `warn-continue` (fail-fast, auto-dismiss-all) once v1 config plumbing exists.

**Outside this product's identity**

- Headless API server or MCP tools inside the desktop app (scripts/CLI remain the agent path).

## Key Decisions

- Architecture: Core `FomodPostDownloadOrchestrator` + `IFomodPostDownloadHost` adapters (GUI dialog host, console TTY host, warn-continue host, choices-file host).
- TTY detection uses input redirect, output redirect, `Environment.UserInteractive`, and explicit `--non-interactive` / `--interactive` overrides.
- Config precedence: CLI flags > environment variables > `settings.json` > TTY-derived default.
- Selected-only FOMOD scan even when download fetched more components.
- Convert/merge output persistence uses existing `-o` / output path; no silent in-place overwrite of input without documented flag.

## Dependencies / Assumptions

- PR #169 Core pieces (`FomodArchiveProbe`, `FomodDownloadPromptState`, `FomodConfiguredComponentMerger`) remain the persistence and detection layer.
- Instruction paths continue to use `<<modDirectory>>` / `<<kotorDirectory>>` placeholders after FOMOD merge.
- `ModSync.Tests` remains the single test project.

## Outstanding Questions

- None blocking — user confirmed synthesis call-outs (2026-06-14 session).
5 changes: 3 additions & 2 deletions docs/knowledgebase/agent-action-parity.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Wizard order from `src/ModSync.GUI/Dialogs/InstallWizardDialog.axaml.cs` and `AG
| 5 | `GameDirectoryPage` | Pick game dir | `-g` / `--kotorPath=` | Full |
| 6 | `AspyrNoticePage` | Acknowledge (K2) | No CLI equivalent | UI |
| 7 | `ModSelectionPage` | Select mods, filters | `install` without `--select` = select all; `install --select category:X` / `tier:X` | Full (install); Partial (subset only with `--select`) |
| 8 | `DownloadsExplainPage` | Continue (downloads may run) | `install -d` or `convert -d` | Partial — see [download-system.md](download-system.md) |
| 8 | `DownloadsExplainPage` | Continue (downloads may run) | `install -d` or `convert -d` | Partial — see [download-system.md](download-system.md); FOMOD post-download configure is GUI-only until [Plan 123](../plans/2026-06-14-123-feat-fomod-cli-download-prompts-plan.md) |
| 9 | `ValidatePage` | Run validation | `validate --full --dry-run --use-file-selection` (same Core `InstallationValidationPipeline` as GUI) | Full |
| 10 | `InstallStartPage` | Confirm install | `install -y` (runs `InstallationValidationPipeline` / `WizardFull` pre-check unless `--skip-validation`) | Full |
| 11 | `InstallingPage` | Watch progress | `install` (console progress) | Full — see [install-lifecycle.md](install-lifecycle.md) |
Expand All @@ -30,7 +30,7 @@ Wizard order from `src/ModSync.GUI/Dialogs/InstallWizardDialog.axaml.cs` and `AG
| `Step1ModDirectoryPicker` | `--modDirectory=` / `-s` | Full |
| `Step1KotorDirectoryPicker` | `--kotorPath=` / `-g` | Full |
| `Step2Button` (load file) | `--instructionFile=` / `-i` | Full |
| `ScrapeDownloadsButton` | `install -d` or `convert -d` | Partial |
| `ScrapeDownloadsButton` | `install -d` or `convert -d` | Partial — FOMOD configure after download: GUI (PR #169); CLI planned Plan 123 |
| `ValidateButton` | `validate --full --dry-run --use-file-selection` (via `InstallationValidationPipeline`) | Full |
| `OpenModDirectoryButton` | `ls` / file tools on mod dir | Full |
| Download status / stop | No first-class CLI | UI |
Expand Down Expand Up @@ -72,5 +72,6 @@ Wizard order from `src/ModSync.GUI/Dialogs/InstallWizardDialog.axaml.cs` and `AG
6. **CI test coverage** — green CI runs subsets only; local `run_headless_tests.sh` is broader. See [ci-test-matrix.md](ci-test-matrix.md).
7. **Validation pipeline fail-fast** — `InstallationValidationPipeline` stops after environment failure (no conflict/order/archive/dry-run stages). GUI and CLI both use `ValidationPipelineResult.IsSuccess`; do not infer pass from an empty dry-run result.
8. **Install pre-check opt-out** — `install --skip-validation` and `install_best_effort.sh` skip the wizard-equivalent pipeline; default `install` does not.
9. **FOMOD post-download** — GUI prompts after Fetch Downloads (PR #169). CLI parity: TTY wizard, `--fomod-skip`, `--fomod-choices` / `MODSYNC_FOMOD_CHOICES` per [Plan 123](../plans/2026-06-14-123-feat-fomod-cli-download-prompts-plan.md).

See [agent-native-audit.md](agent-native-audit.md) for scored principles and [core-cli-reference.md](core-cli-reference.md) for flags.
10 changes: 6 additions & 4 deletions docs/knowledgebase/agent-native-audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ This product is a **desktop mod installer**, not a web agent host. Scores reflec
| Metric | Value |
|--------|-------|
| Principles scored | 8 / 8 |
| Weighted average | **62%** |
| Weighted average | **65%** |
| Headless agent readiness | Strong for Core CLI + tests |
| Desktop-only gap | GUI wizard, downloads UX, widescreen flow |

## Principle scores

| # | Principle | Score | Summary |
|---|-----------|-------|---------|
| 1 | **Parity** | 14/25 (56%) | Core paths (`validate`, `install`, convert) are CLI-accessible; many wizard-only flows lack headless equivalents. |
| 1 | **Parity** | 17/25 (68%) | Core paths plus CLI FOMOD post-download (Plan 123) close a major GUI-only gap; widescreen/Aspyr remain UI-only. |
| 2 | **Granularity** | 16/20 (80%) | CLI verbs are composable; scripts wrap common combos without hiding primitives. |
| 3 | **Composability** | 12/15 (80%) | New agent workflows combine `dotnet run` + scripts + tests without code changes. |
| 4 | **Emergent capability** | 10/15 (67%) | Agents can fix TOMLs and run installs; limited without Nexus keys, real game dirs, or desktop. |
Expand All @@ -38,6 +38,8 @@ This product is a **desktop mod installer**, not a web agent host. Scores reflec
| Set mod / game directories | GUI preload or CLI `-g` / `-s` | Yes |
| Run validation | `ValidatePage` or `validate --full` | Yes (full needs dirs) |
| Fetch downloads | Wizard / `ScrapeDownloadsButton` | Partial — CLI `install -d` / `convert -d` |
| Post-download FOMOD configure | GUI after Fetch Downloads (PR #169) | Partial — Plan 123: TTY wizard, `--fomod-choices`, `--fomod-skip` |
| FOMOD step wizard | `FomodInstallerDialog` | Partial — GUI today; Plan 123 terminal wizard |
| Install mods | Wizard or `install` | Yes |
| Mod selection / filters | `ModSelectionPage` UI | Partial — CLI `--select` |
| Widescreen-only install block | Dynamic wizard pages | No — desktop only |
Expand All @@ -46,9 +48,9 @@ This product is a **desktop mod installer**, not a web agent host. Scores reflec

**Strengths:** `[REPO]` `ModBuildConverter` covers validate/install/convert/merge; `install_best_effort.sh` documents a full-build-style headless path.

**Gaps:** `[OPEN]` No headless API for every wizard button; widescreen and Aspyr notice flows are `[UI]` only.
**Gaps:** `[OPEN]` No headless API for every wizard button; widescreen and Aspyr notice flows are `[UI]` only. FOMOD post-download configure is GUI-only until Plan 123 (`docs/plans/2026-06-14-123-feat-fomod-cli-download-prompts-plan.md`).

**Recommendations (Tier 1):** Keep `agent-action-parity.md` current when wizard pages change. Document `--select` examples for tier/category installs.
**Recommendations (Tier 1):** Keep `agent-action-parity.md` current when wizard pages change. Ship Plan 123 to close FOMOD action-parity gap; document `--fomod-choices` in `core-cli-reference.md`.

---

Expand Down
6 changes: 6 additions & 0 deletions docs/knowledgebase/core-cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ All verbs inherit from `BaseOptions`:
|------|-------------|
| `-v` / `--verbose` | Verbose logging |
| `--plaintext` | Plain-text log output (no ANSI) |
| `--fomod-skip` | Skip FOMOD post-download configuration; marks archives dismissed for this run |
| `--fomod-choices` | JSON sidecar with FOMOD plugin selections (see [fomod-support.md](fomod-support.md)) |
| `--interactive` | Force interactive FOMOD prompts when I/O is redirected |
| `--non-interactive` | Force warn-continue FOMOD behavior (no TTY wizard) |

Environment: `MODSYNC_FOMOD_CHOICES` (choices file path), `MODSYNC_FOMOD_POST_DOWNLOAD_MODE` (`warn-continue` or `skip`). Settings key: `fomodPostDownloadMode` in `%AppData%/ModSync/settings.json`.

## Verbs

Expand Down
11 changes: 11 additions & 0 deletions docs/knowledgebase/download-system.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ Helper: **`scripts/agents/cli_validate.sh`** does not download; use **`install -

**Parity gap**: CLI can download archives; it does not replicate the GUI download status panel or stop button. See [agent-action-parity.md](agent-action-parity.md).

## FOMOD post-download (CLI + GUI)

`[REPO]` After downloads complete, selected components with FOMOD archives may be configured before validation/install:

| Surface | Behavior |
|---------|----------|
| GUI | `DownloadOrchestrationService` → `FomodPostDownloadPromptService` → `FomodGuiPostDownloadHost` (installer dialog) |
| CLI `install -d` / `convert -d` / `merge -d` | `FomodPostDownloadOrchestrator` with TTY wizard, warn-continue, skip, or `--fomod-choices` / `MODSYNC_FOMOD_CHOICES` |

**Settings** (`settings.json` key `fomodPostDownloadMode`): `warn-continue` (default) or `skip` — affects headless CLI only; GUI always prompts. Also: `--fomod-skip`, `--interactive` / `--non-interactive`, env `MODSYNC_FOMOD_POST_DOWNLOAD_MODE`. See [fomod-support.md](fomod-support.md) and [core-cli-reference.md](core-cli-reference.md).

## Typical agent workflow

1. Clone **`./mod-builds`** at repo root if testing full builds — [mod-builds-sources.md](mod-builds-sources.md).
Expand Down
19 changes: 17 additions & 2 deletions docs/knowledgebase/fomod-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,23 @@ GUI (`src/ModSync.GUI/`):

## Deferred `[OPEN]`

- Detection hook in `DownloadCacheService`/`ArchiveEnumerationService` that offers
the guided flow when `FomodDetector` matches an archive.
- Plugin images from `image path`.

## Planned: CLI post-download parity `[REPO]`

Requirements: [docs/brainstorms/2026-06-14-fomod-cli-download-prompts-requirements.md](../brainstorms/2026-06-14-fomod-cli-download-prompts-requirements.md)

Plan: [docs/plans/2026-06-14-123-feat-fomod-cli-download-prompts-plan.md](../plans/2026-06-14-123-feat-fomod-cli-download-prompts-plan.md)

- Core `FomodPostDownloadOrchestrator` + CLI console host + `--fomod-skip` / `--fomod-choices`
- Full TTY wizard; non-TTY default warn-continue; convert output persists FOMOD state

## Post-download hook `[REPO]`

- `FomodArchiveProbe` detects `fomod/ModuleConfig.xml` inside downloaded archives via entry listing.
- `FomodPostDownloadPromptService` runs after GUI **Fetch Downloads** completes; optional prompt per archive.
- `FomodDownloadPromptState` stores dismissed/configured outcomes in resource handler metadata.
- `ArchiveEnumerationService` sets `FileTreeNode.IsFomodInstaller` when an archive contains FOMOD metadata.

## Verification

Expand Down
Loading
Loading