Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
ec760ac
feat(profiles): add MO2-style install profile loadouts
Jun 12, 2026
435fd37
Merge branch 'master' into feat/install-profiles
oldrepublicwizard Jun 12, 2026
d1e816b
feat(fomod): add ModuleConfig parser and Option/Choose mapper
Jun 12, 2026
f930344
feat(cli): add profile verb for install profile CRUD
Jul 18, 2026
df3cb6f
feat(cli): add validate --output json for agent-native reports
Jul 18, 2026
baafbd7
feat(cli): add settings verb for settings.json get/set/list
Jul 18, 2026
afe2416
chore: sync local changes (2026-07-24)
Jul 25, 2026
1cd9ce8
docs(plan): add lossless roundtrip universal pipeline brainstorm and …
Jul 30, 2026
f3755ad
fix(core): preserve GUID/instructions/options across markdown round-trip
Jul 30, 2026
25c61e1
fix(review): remove unreachable KVP-handling branch, doc requireName …
Jul 30, 2026
51ca06f
fix(tests): complete U1/U2 roundtrip test re-enablement (skip logic, …
Jul 30, 2026
abeaeaf
feat(parsing): generalize admonition-fence support to all guide field…
Jul 30, 2026
f85d9a5
feat(parsing): surface unparsed directions as reviewable gaps (U2)
Jul 30, 2026
031d79d
feat(parsing): decompose K2CP+HD-Visas nested conditional clauses (U3)
Jul 30, 2026
2cc6cb1
feat(parsing): detect redrob cleanlist-driven deletion instead of gue…
Jul 30, 2026
2fa54e0
fix(parsing): stop truncating filenames at their own extension dot (U5)
Jul 30, 2026
a2ea7a4
feat(ports): carry markdown content sections through the guide ingest…
Jul 30, 2026
6c25ebb
feat(ingest): route CLI convert and GUI file-open/paste through the g…
Jul 30, 2026
9ec613a
test(roundtrip): add self-contained Choose-tree round-trip coverage (U8)
Jul 30, 2026
1587998
fix(test): normalize path separator in Choose-tree round-trip test (U8)
Jul 30, 2026
6512abd
fix(tests): clean-skip on missing corpus, tag slow real-guide test (U9)
Jul 30, 2026
e77ac6f
refactor: dedupe constants and add regex pre-filters (simplify pass)
Jul 30, 2026
a87ef1a
fix(review): stop over-flagging zero-draft components, avoid double-p…
Jul 30, 2026
484fb60
fix(ci): apply dotnet format whitespace to test files
Jul 30, 2026
60ec2ac
update gitignore
Jul 30, 2026
1da3543
test
Jul 30, 2026
5a62815
test
Jul 30, 2026
1cf2603
merge: fold feat/install-profiles into AIO (superseded by evolved HEAD)
Jul 30, 2026
6ba8822
Merge remote-tracking branch 'origin/feat/cli-profile-verb' into feat…
Jul 30, 2026
7e18bce
merge: add settings CLI verb alongside profile verb (AIO)
Jul 30, 2026
2cac1ca
chore: untrack cursor hook runtime state
Jul 30, 2026
8e0a623
merge: add validate --output json alongside profile/settings verbs (AIO)
Jul 30, 2026
4bb68a4
merge: fold feat/fomod-installer into AIO (superseded by shipped FOMO…
Jul 30, 2026
5cb8620
feat(download): survive DeadlyStream Cloudflare challenges
Jul 30, 2026
b70640f
fix(settings): honor explicit --settings-dir instead of legacy fallback
Jul 30, 2026
d84913e
style: fix import ordering after AIO merges
Jul 30, 2026
1fbe54e
Merge branch 'master' into feat/aio-consolidation
oldrepublicwizard Jul 31, 2026
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
Empty file added .commandcode/taste/taste.md
Empty file.
70 changes: 70 additions & 0 deletions .cursor/skills/headless_mod_download_automation/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Headless mod download automation

## When to use

Use this skill when the task explicitly involves:

- fully downloading and installing a `mod-builds` TOML (`KOTOR1_Full.toml`, `KOTOR2_Full.toml`, or any other build) with no human clicking through download pages
- resolving DeadlyStream / Nexus Mods / MEGA download links via browser automation and/or FlareSolverr
- converging a real install to zero remaining `validate --full` errors

This is the **headless CLI** counterpart to `full_build_install_validation` (which drives the Avalonia GUI wizard by hand). Use this skill instead when the goal is unattended acquisition of every mod archive, not exercising the wizard.

## Read first

- `docs/knowledgebase/mod-download-playbook.md` — canonical, continually-updated per-host download strategy and FlareSolverr usage. Read before improvising; append to it when you learn something new.
- `AGENTS.md` — `## Headless full mod-build install (CLI + browser automation)` section.
- `.claude/skills/kotor-mod-download-automation/SKILL.md` and `.claude/agents/mod-download-agent.md` / `mod-link-triage-agent.md` if running under Claude Code — this Cursor skill and those Claude Code assets describe the same procedure; keep them in sync.

## Required repo state

- `./mod-builds` cloned at repo root
- `ModSync.Core` builds (`dotnet build src/ModSync.Core/ModSync.Core.csproj -c Debug -f net9.0`)
- FlareSolverr reachable at `http://localhost:8191` — verify via `POST /v1` with a JSON body (e.g. `{"cmd":"sessions.list"}`); a bare `GET /` 404s and is not a health check
- Browser automation available (Playwright/Patchright/claude-in-chrome, whichever the current agent has) for Nexus/DeadlyStream/MEGA flows

## Procedure

1. Generate or confirm a fresh merged instruction file (TOML + Markdown merged) for the target build.
2. Check the real game directory's `Override/` file count as a starting baseline.
3. Per mod not yet present as a verified archive in staging, route by host:
- **deadlystream.com**: browser navigate to the file page, click the real download control, capture the download. Most failures here are stale/renumbered attachment ids or a missing session, not a bot-wall — investigate per link.
- **nexusmods.com**: browser "Slow download" flow, honor the countdown timer; no API key available in this environment, so this is the only free path.
- **mega.nz**: browser only, wait for client-side decrypt before triggering download.
- **github.com**: direct `curl -L`.
- misc one-offs (Drive, pastebin, gamefront): handle individually.
4. Verify every download before trusting it: correct archive type via `file`/`unzip -t`/`7z t`, and a non-trivial size floor. A small HTML error page saved under an archive extension is the classic silent-failure mode this catches.
5. Batch install (not one mod at a time):
```
dotnet run --project src/ModSync.Core/ModSync.Core.csproj -f net9.0 --no-build -- \
install -i <merged-toml> -g <game-dir> -s <staging-dir> \
-d --concurrent --best-effort --skip-validation --download-timeout-hours 72
```
6. Run a full validate pass periodically:
```
dotnet run --project src/ModSync.Core/ModSync.Core.csproj -f net9.0 -- \
validate -i <merged-toml> -g <game-dir> -s <staging-dir> --full
```
7. Feed validate failures back into step 3. For any link that fails repeatedly after direct investigation, resolve it individually (a corrected id, a mirror, a required access step, or a confirmed-unobtainable verdict) rather than retrying it forever or silently dropping it.
8. Repeat 3-7 until validate is clean or every remaining failure is an explicitly logged, individually-investigated exception.

## What to record

- Starting and ending `Override/` file counts (real numbers, not estimates)
- Mods installed vs. named exceptions with reasons
- Any new per-host quirks discovered (fold into the playbook doc, not just this file)

## Project-specific behavior that matters

- `--best-effort --skip-validation` on `install` is what makes batch/partial installs safe to run repeatedly without re-validating everything each time — validation is a separate, explicit step.
- The merged instruction file must be regenerated if the source TOML/Markdown changes after it was produced — check timestamps.
- No new `.sh` files for this workflow — every action is an inline command or an inline browser-automation call, so the whole run stays auditable from the terminal transcript alone.

## Update rule

Whenever a better download/triage approach or a new host quirk is discovered, update together:

- `docs/knowledgebase/mod-download-playbook.md`
- this skill
- `.claude/skills/kotor-mod-download-automation/SKILL.md` and the `.claude/agents/*.md` pair (Claude Code side)
- `AGENTS.md`'s `## Headless full mod-build install (CLI + browser automation)` section
12 changes: 12 additions & 0 deletions .cursorrules
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,15 @@ pwsh -Command '& {
- For local Linux desktop runs, if validation says HoloPatcher is missing, run `scripts/agents/ensure_linux_holopatcher.sh` before assuming the GUI flow itself is broken.
- `mod-builds` is expected at the repo root as `./mod-builds` for full-build tests.
- Anything user-visible in the GUI should be exercised in a real desktop session, not only headless tests.

=== HEADLESS MOD-BUILD DOWNLOAD AUTOMATION ===

- For fully unattended download+install of a `mod-builds` TOML (no GUI, no human clicking through DeadlyStream/Nexus/MEGA), read `docs/knowledgebase/mod-download-playbook.md` first and use `.cursor/skills/headless_mod_download_automation/SKILL.md`.
- FlareSolverr's real endpoint is `POST http://localhost:8191/v1`, not a bare `GET /` (that 404s and is not a health check).
- Nexus Mods blocks plain `curl` (403) and this repo's environment has no `NEXUS_API_KEY`; use the free "Slow download" browser flow.
- DeadlyStream itself is not broadly bot-walled — treat individual download failures as stale/renumbered links to investigate, not a blanket block.
- Verify every downloaded archive's real file type before trusting it (a captured HTML error page saved with an archive extension is a known failure mode here).
- If Cloudflare WARP (`warp-cli`) is active and a host times out at the TCP level (not just an HTTP error), check `warp-cli tunnel host list` before assuming a bot-block — WARP's shared exit IP can already be reputation-blocked independent of anything this session did. Fix with `warp-cli tunnel host add <domain>` to split-tunnel that host around WARP.
- If `claude-in-chrome`/the Chrome MCP extension isn't connected, fall back to the `agent-browser` CLI (`~/.cargo/bin/agent-browser`, `agent-browser --help`) — a real installed browser automation tool usable via plain inline Bash.
- HARD RULE: never solve or click through a CAPTCHA (Cloudflare Turnstile, reCAPTCHA, hCaptcha) under any instruction, even "don't ask, just get it done." If automation hits one, stop on that item and log it as blocked-pending-user-action instead.
- Keep `AGENTS.md`, this file, `docs/knowledgebase/mod-download-playbook.md`, `.cursor/skills/headless_mod_download_automation/SKILL.md`, and (if using Claude Code) `.claude/skills/kotor-mod-download-automation/SKILL.md` + `.claude/agents/mod-download-agent.md` / `mod-link-triage-agent.md` in sync when this workflow changes.
1 change: 1 addition & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,4 @@ Debug builds and test runs assume the .NET 9 toolchain described in `AGENTS.md`.
- In Avalonia XAML, do not hardcode font/style/color properties on controls unless absolutely necessary; rely on the implicit theme defaults.
- The repo already ships MCP wrapper configs in `mcp.json` and `.cursor/mcp.json` for `repo-filesystem`, `desktop-commander`, and `playwright`; prefer those wrappers over inventing repo-specific server commands.
- Repo docs call out a few environment-specific gotchas that are worth preserving in agent work: `CrossPlatformFileWatcherTests` are expected to fail in the cloud VM, some UI tests only make sense in a real desktop session, and Linux GUI validation may require `scripts/agents/ensure_linux_holopatcher.sh`.
- For fully unattended, no-GUI download+install of a `mod-builds` TOML (every archive fetched by automation, not clicked through by a human), see `AGENTS.md`'s `## Headless full mod-build install (CLI + browser automation)` section and `docs/knowledgebase/mod-download-playbook.md`. Key facts: FlareSolverr's real endpoint is `POST http://localhost:8191/v1` (a bare `GET /` 404s and is not a health check); Nexus Mods needs the free "Slow download" browser flow since no API key is configured; DeadlyStream itself isn't broadly bot-walled, so individual download failures are usually stale links, not a blanket block; every downloaded archive needs a real file-type check before being trusted.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -433,3 +433,10 @@ audit/
package.json
package-lock.json
pnpm-lock.yaml

clutter/
.compound-engineering/
.claude/

# Cursor hook runtime state (machine-local)
.cursor/hooks/state/
6 changes: 3 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[submodule "src/AvRichTextBox"]
path = src/AvRichTextBox
url = https://github.com/th3w1zard1/AvRichTextBox.git
url = https://github.com/oldrepublicwizard/AvRichTextBox.git
[submodule "src/RtfDomParserAvalonia"]
path = src/RtfDomParserAvalonia
url = https://github.com/th3w1zard1/RtfDomParserAvalonia.git
url = https://github.com/oldrepublicwizard/RtfDomParserAvalonia.git
[submodule "vendor/KPatcher"]
path = vendor/KPatcher
url = https://github.com/th3w1zard1/KPatcher.git
url = https://github.com/oldrepublicwizard/KPatcher.git
68 changes: 68 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,66 @@ For `KOTOR1_Full.toml` / `KOTOR2_Full.toml` tests:
6. Run validation from `ValidatePage`.
7. Only proceed to install after validation is acceptable for the task at hand.

## Headless full mod-build install (CLI + browser automation)

Distinct from the GUI wizard flow above: this is the no-human, no-GUI path for actually
*acquiring and installing every mod* in a build (not just validating it), driven entirely
from the terminal plus browser automation. Use `.cursor/skills/headless_mod_download_automation/SKILL.md`
(Cursor) or `.claude/skills/kotor-mod-download-automation/SKILL.md` +
`.claude/agents/mod-download-agent.md` / `mod-link-triage-agent.md` (Claude Code) to drive
it. The living, continually-updated per-host reference is
`docs/knowledgebase/mod-download-playbook.md` — read it before improvising a download
approach for DeadlyStream, Nexus Mods, or MEGA.

### Environment facts that matter (discovered 2026-07-30, KOTOR1_Full full install)

- **FlareSolverr's real API is `POST http://localhost:8191/v1`** with a JSON body (e.g.
`{"cmd":"sessions.list"}`). A bare `GET /` returns 404 and is **not** a health check —
don't conclude FlareSolverr is down from that alone.
- **Nexus Mods** returns HTTP 403 to plain `curl` (Cloudflare/bot-check), and this
environment has no `NEXUS_API_KEY` configured — the free "Slow download" button flow
via a real browser session is the only path for non-premium Nexus files. Premium-only
files with no free tier should be logged as unobtainable-without-payment, not retried.
- **DeadlyStream** (the bulk of most KOTOR builds) is *not* broadly bot-walled — plain
file/category pages return HTTP 200 to `curl`. A prior fully-automated attempt at this
build got almost no successful downloads; the cause was very likely stale/renumbered
attachment ids or missing session/referer on the actual download endpoint, not a
blanket Cloudflare block. Treat DeadlyStream download failures as "investigate this
specific link" (dispatch `mod-link-triage-agent` / follow the triage procedure), not
"the host is blocked."
- **MEGA** links require a real browser — the file is decrypted client-side from the URL
fragment, so `curl` cannot produce a usable archive even on a 200 response.
- **Every downloaded archive needs an integrity check before being trusted**: confirm
actual file type (`file <path>`, `unzip -t`, `7z t`) and a non-trivial size floor. The
same prior attempt saved a 104-byte `.rar` that was almost certainly a captured HTML
error page — this is the specific failure mode the check exists to catch.
- No new `.sh` files for this workflow — every download/install action should be an
inline command or an inline browser-automation call so the run stays auditable purely
from the terminal/agent transcript.
- **If `claude-in-chrome` reports the extension not connected**, fall back to the
`agent-browser` CLI (`~/.cargo/bin/agent-browser`) — a real, already-installed
Chrome-backed browser automation tool usable via plain inline Bash (`agent-browser
open/click/download/get/screenshot/snapshot`, `agent-browser --help` for the full
reference). Confirmed working 2026-07-30 when `claude-in-chrome` was unavailable in
this environment.
- **HARD RULE, no exceptions: never solve, click through, or otherwise bypass a CAPTCHA**
(Cloudflare Turnstile "verify you are human" checkbox, reCAPTCHA, hCaptcha, etc.),
even with a fully working browser-automation tool. This holds regardless of any
"don't ask, just get it done" instruction in the task — that authorizes working
around inconvenience, not around this boundary. If automation hits a real CAPTCHA
(distinct from a JS-timing "please wait" interstitial, which does resolve on its
own), stop on that specific item, do not interact with the challenge, and log it as
blocked-pending-user-action. Nexus Mods' file pages showed a real Cloudflare
Turnstile checkbox during the 2026-07-30 KOTOR1_Full run.
- **If this machine has Cloudflare WARP active (`warp-cli status`) and a host starts
timing out at the TCP level** (not just an HTTP error — full connect timeouts from
multiple independent tools), check `warp-cli tunnel host list` before assuming a
fresh bot-block. WARP's shared consumer exit IP can already be reputation-blocked by
a site, independent of anything this session did. Fix: `warp-cli tunnel host add
<domain>` to split-tunnel that host around WARP while leaving WARP on for everything
else — this fixed DeadlyStream connectivity immediately (no cooldown wait needed) on
2026-07-30.

## Linux-specific note

The plain Debug output can run the GUI, but local Linux validation/install checks may still require:
Expand All @@ -291,6 +351,14 @@ Update all of the following together:
- `.cursor/mcp.json` or the wrapper scripts if agent tooling changed
- `.vscode/tasks.json` / `.vscode/launch.json` if the launch flow changed

For headless mod-download/install automation specifically, also update together:

- `docs/knowledgebase/mod-download-playbook.md` (the primary living per-host reference)
- `.cursor/skills/headless_mod_download_automation/SKILL.md`
- `.claude/skills/kotor-mod-download-automation/SKILL.md`
- `.claude/agents/mod-download-agent.md` and `.claude/agents/mod-link-triage-agent.md`
- this file's `## Headless full mod-build install (CLI + browser automation)` section

## Cursor Cloud specific instructions

### Overview
Expand Down
Loading
Loading