Skip to content

fix(version): read DR autostarts from UserVars instead of dependency#2277

Merged
mrhoribu merged 3 commits intoelanthia-online:masterfrom
MahtraDR:fix-version-dr-autostarts
Mar 20, 2026
Merged

fix(version): read DR autostarts from UserVars instead of dependency#2277
mrhoribu merged 3 commits intoelanthia-online:masterfrom
MahtraDR:fix-version-dr-autostarts

Conversation

@MahtraDR
Copy link
Copy Markdown
Contributor

Summary

  • Read DR autostarts from UserVars.autostart_scripts instead of calling list_autostarts gated behind Script.running?('dependency')
  • list_autostarts no longer exists and dependency.lic is now run-once

Depends on

Test plan

  • Run ;version on a DR character — verify "DR autostarts" shows the correct list
  • Run ;version on a GS character — verify no errors (line is DR-gated)

🤖 Generated with Claude Code

dependency.lic is now run-once (elanthia-online/dr-scripts#7334) and
no longer exposes list_autostarts. Autostarts have been migrated from
script-scoped Settings to globally-accessible UserVars.autostart_scripts.

Read directly from UserVars instead of gating on Script.running?.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 18, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bb309626-3553-4cbb-a8f1-c30338351e20

📥 Commits

Reviewing files that changed from the base of the PR and between 193c15f and b49e8c0.

📒 Files selected for processing (1)
  • scripts/version.lic
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/version.lic

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Updated autostart reporting for DR games to provide consistent data.
  • Chores
    • Version bumped to 1.2.3.

Walkthrough

A single-line modification to scripts/version.lic that changes the DR autostart value source from a runtime Script.running?('dependency') check to a direct read from UserVars.autostart_scripts.to_a.join(', '), removing the dependency-state conditional.

Changes

Cohort / File(s) Summary
DR Autostart Value Source
scripts/version.lic
Replaced conditional that used list_autostarts.join(', ') when Script.running?('dependency') is true (or returned "Dependency not running") with always using UserVars.autostart_scripts.to_a.join(', '). Bumped version to 1.2.3 and added changelog entry.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and concisely summarizes the main change: reading DR autostarts from UserVars instead of dependency, which matches the core modification in the changeset.
Description check ✅ Passed The description is directly related to the changeset, explaining the rationale for the change (list_autostarts no longer exists, dependency is run-once) and providing clear test steps.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@mrhoribu mrhoribu merged commit 82ea7c4 into elanthia-online:master Mar 20, 2026
4 checks passed
MahtraDR added a commit to elanthia-online/lich-5 that referenced this pull request Mar 28, 2026
## Summary

This PR migrates game-agnostic classes from `dependency.lic` into core
lich-5 and introduces **ScriptSync** -- a SHA-based script repository
synchronization system that replaces blind bulk downloads with
incremental, checksum-verified updates. Script repos now auto-sync on
login for both DR and GS.

---

## Part 1: Core Class Migration

Moves four classes from `dependency.lic` into `lib/` so they load at
boot before any script runs:

### ArgParser (`lib/common/arg_parser.rb`)
Script argument parsing with pattern matching and help display. Parses
`--flag`, `--key=value`, and positional arguments into a normalized
hash.

### SetupFiles (`lib/common/setup_files.rb`)
YAML cascade settings engine. Loads per-character, per-class, and base
YAML files, resolves `include:` directives, merges them in priority
order, and caches results. Includes deep-clone protection so scripts
cannot mutate shared settings.

### SettingsTransformer (`lib/common/settings_transformer.rb`)
Data-driven settings enrichment engine with 7 transform phases:
1. Defaults injection
2. Spell enrichment (spell name/abbreviation lookups)
3. List composition (merge/append/prepend from named lists)
4. UserVars fallback (fill missing keys from UserVars)
5. Hometown lookups (resolve town-specific data)
6. Denylists (filter out blocked items)
7. Legacy migrations (rename deprecated keys)

The transformer is fully game-agnostic -- each game provides its own
config hash describing which keys to transform and how.

### DR SettingsConfig (`lib/dragonrealms/dependency/settings_config.rb`)
Frozen config hash with DR-specific transform rules. Loaded by
`gameloader.rb` for DR sessions only.

### Integration
- `lich.rbw` requires ArgParser, SetupFiles, and SettingsTransformer at
boot
- `lib/common/gameloader.rb` requires SettingsConfig for DR sessions
- All classes are namespaced under `Lich::Common` / `Lich::DragonRealms`
and made available at top level via `include Lich::Common` in `lich.rbw`
- `dependency.lic` continues to define these classes inline. The dual
definitions are harmless (Ruby reopens the same class). A follow-up
dr-scripts PR will add `defined?` guards to skip redundant definitions.

---

## Part 2: ScriptSync -- SHA-Based Repository Synchronization

Adds a complete script repository sync system to `Lich::Util::Update`
that replaces the old blind-download approach with SHA-based incremental
sync.

### SCRIPT_REPOS Registry
A frozen hash defining repositories to sync:
- **`dr-scripts`** (`elanthia-online/dr-scripts`): tracking_mode `:all`
-- syncs every `.lic` at root, plus `profiles/` and `data/`
subdirectories. Filtered to DR sessions only via `game_filter: /^DR/`.
- **`scripts`** (`elanthia-online/scripts`): tracking_mode `:explicit`
-- syncs only a default tracked list (alias.lic, go2.lic, map.lic, etc.)
plus user-added scripts. Available for both DR and GS.

### How Sync Works
1. Fetches the GitHub tree API for the repo (cached 60s)
2. Builds a local SHA map by computing git blob SHAs
(`Digest::SHA1.hexdigest("blob #{size}\0#{content}")`) for all local
files
3. Compares remote tree SHAs against local SHAs
4. Downloads only files whose SHA differs (or are missing locally)
5. Writes files atomically via `safe_write` (tmp + rename with rollback
on failure)

### New CLI Commands
```
;lich5-update --sync                              Sync all repos for current game
;lich5-update --sync=dr-scripts                   Sync only dr-scripts repo
;lich5-update --sync=scripts                      Sync only EO/scripts repo
;lich5-update --tracked                           List tracked scripts for all repos
;lich5-update --tracked=scripts                   List tracked scripts for one repo
;lich5-update --track=scripts:bigshot.lic         Add a script to tracked list
;lich5-update --untrack=scripts:bigshot.lic       Remove from tracked list
;lich5-update --script=dr-scripts:hunting-buddy.lic  Update script from specific repo
;lich5-update --data=dr-scripts:base-hunting.yaml    Update data file from specific repo
```

### Key Methods Added to `Lich::Util::Update`
- `sync_all_repos` / `sync_repo(key)` -- top-level sync entry points
- `sync_subdir(tree, config, name, subconfig)` -- sync subdirectories
(profiles, data)
- `filter_syncable_scripts(tree, config)` -- apply tracking_mode and
patterns
- `build_local_sha_map(dir, pattern)` -- compute local git blob SHAs
- `safe_write(path, content)` -- atomic file write with rollback
- `http_get(url, auth:)` -- Net::HTTP wrapper with optional GitHub token
auth
- `github_token` -- lazy-loads token from `DATA_DIR/githubtoken.txt`
- `update_file_from_repo(type, repo_key, filename)` -- download a
specific file from a named repo with SHA pre-check
- `track_script` / `untrack_script` / `show_tracked` -- manage per-repo
tracked script lists
- `render_sync_summary` -- Terminal::Table formatted sync results
- `respond_mono` -- monospace output for all frontends (Profanity,
Genie, etc.)

### GitHub Token Support
If `DATA_DIR/githubtoken.txt` exists, all GitHub API calls include a
Bearer token. This avoids rate limiting for users who sync frequently.
Unauthenticated access works fine for casual use.

---

## Part 3: Login Auto-Sync for Both DR and GS

### What Changed
- **`games.rb`**: Script repos now sync automatically on login for
**both DR and GS** (previously DR only). Runs in a background thread to
avoid blocking `process_xml_data` and the `XMLData.name` race condition.
Each repo's `game_filter` already scopes which repos sync for which
game.
- **`update.rb`**: Removed `sync_all_repos` call from
`update_core_data_and_scripts`. Since a relog is required after every
`--update` or `--branch` operation, the login auto-sync handles script
updates. This avoids redundant downloads and stops clobbering local
script edits during lich core updates.
- **Help text**: Updated to reflect both-game auto-sync. Removed the
GS-specific `autostart add --sync` suggestion since it is now automatic.

### Why
- The old `--update` path force-downloaded core scripts unconditionally,
overwriting any local edits.
- With auto-sync on login, scripts update via SHA comparison -- only
downloading what actually changed.
- Both games benefit equally: DR syncs dr-scripts + EO/scripts, GS syncs
EO/scripts.
- Users can still manually sync at any time via `;lich5-update --sync`.

---

## Part 4: Branch Tracking Enhancements

- `--branch=owner:branch_name` syntax to install from a fork (e.g.,
`;lich5-update --branch=MahtraDR:some-feature`)
- `--branch` always re-downloads from GitHub, even when already on the
same branch, so newer commits are picked up without manual intervention
- `--status` shows current branch, repository, and last-updated
timestamp
- Branch tracking persists via `LICH_BRANCH` / `LICH_BRANCH_REPO`
constants in `version.rb`

---

## Part 5: UX Polish

- **Display names**: Each repo has a `display_name` (e.g., "DR Scripts")
used in user-facing messages
- **Terminal::Table**: `--tracked` and sync summaries render as
formatted tables
- **Monospace output**: `respond_mono` wraps output in
`Lich::Messaging.mono()` when available, ensuring proper alignment in
Profanity, Genie, and other frontends
- **Vars.save**: Called immediately after `--track`/`--untrack` to
persist changes

---

## Part 6: Code Review Fixes

Fixes addressing CodeRabbit review feedback:

- **`arg_parser.rb`**: Replaced bare `exit` with `raise ArgumentError`
so invalid/help args don't kill the Lich process. Script threads catch
the exception naturally via Lich's thread management. Important since
ArgParser now loads at boot in core rather than inside a script context.
- **`settings_transformer.rb` (denylists)**: Replaced bare `exit` with
`raise ArgumentError`. The exception is caught by the existing `rescue`
block in `transform()`, which logs the error and returns an empty
`OpenStruct` -- strictly better than killing the process.
- **`settings_transformer.rb` (defaults/fallback)**: Replaced `||=` with
`settings.to_h.key?` presence checks in `apply_defaults` and
`apply_uservars_fallback` so explicit `false` values in YAML are
preserved rather than overwritten by defaults. Checks both string and
symbol keys since `OpenStruct.new` converts string keys to symbols.
- **`settings_transformer.rb` (spells)**: Added `is_a?(Hash)` guards in
`apply_tm_prep_defaults` and `apply_battle_cries` to handle malformed
entries gracefully.
- **`settings_transformer.rb` (denylists)**: Fixed `keys.first` bug to
report actual offending key.
- **`settings_transformer.rb` (eval)**: Replaced `eval()` in global
overrides with explicit allowlist of lambdas.
- **`arg_parser.rb`**: Added `Regexp.escape(checkname)` for safe profile
path matching.
- **`setup_files.rb`**: Added missing `require 'set'`.

### Intentionally Not Changed
- **`setup_files.rb` (`unsafe_load_file`)**: Intentionally using
`YAML.unsafe_load_file`. These are user-owned local YAML config files,
not untrusted input. Player YAMLs use features `safe_load` rejects
(anchors, aliases, complex structures). Switching would break existing
configurations across the community.
- **`setup_files.rb` (basename cache keys)**: Profile and data files
have distinct naming conventions and are loaded through separate code
paths. Basename-only keys match existing `dependency.lic` behavior. A
collision would require identical names across directories, which
doesn't happen in the DR/GS ecosystem.
- **`arg_parser.rb` (nil vars TypeError)**: `check_match` handles empty
`vars` safely -- `matches_def(definition, nil)` returns `false`, the
method returns `nil`, and `compact` strips it. This code has worked in
production for years.

---

## Part 7: GS Scripts URL Fix

Fixed two bugs in the `scripts` (EO/scripts) repository sync:

- **Double path prefix**: `raw_base_url` ended with `/scripts` but
GitHub tree API paths already include `scripts/` (e.g.,
`scripts/ewaggle.lic`). The download URL was constructed as
`.../master/scripts/scripts/ewaggle.lic`, producing HTTP 404s. Fixed by
removing the trailing `/scripts` from `raw_base_url`.
- **Single-file tree lookup**: `update_file_from_repo` used bare
filenames (e.g., `ewaggle.lic`) for tree SHA lookups, but tree entries
use full paths (`scripts/ewaggle.lic`). Added `script_prefix` config
field to build the correct lookup path.
- **Branch re-download guard**: `--branch` short-circuited with "Already
on branch" when the user was already tracking the same branch,
preventing them from picking up newer commits (including this fix
itself). Removed the guard so `--branch` always re-downloads the latest
tarball.

---

## Related PRs
- elanthia-online/dr-scripts#7334 (Phase 0: dependency run-once)
- elanthia-online/scripts#2277 (version.lic fix for UserVars autostarts)

## Files Changed
| File | Change |
|------|--------|
| `lich.rbw` | Require ArgParser, SetupFiles, SettingsTransformer at
boot |
| `lib/common/arg_parser.rb` | **New** -- ArgParser class |
| `lib/common/setup_files.rb` | **New** -- SetupFiles class |
| `lib/common/settings_transformer.rb` | **New** -- SettingsTransformer
class |
| `lib/common/gameloader.rb` | Require SettingsConfig for DR |
| `lib/dragonrealms/dependency/settings_config.rb` | **New** -- DR
transform config |
| `lib/update.rb` | ScriptSync system, CLI commands, Net::HTTP, GitHub
token, branch enhancements, URL fix, remove redundant sync from update
path |
| `lib/games.rb` | Auto-sync on login for both DR and GS (removed
DR-only guard) |
| `spec/lib/common/arg_parser_spec.rb` | **New** -- 9 examples |
| `spec/lib/common/setup_files_spec.rb` | **New** -- 18 examples |
| `spec/lib/common/settings_transformer_spec.rb` | **New** -- 22
examples |
| `spec/lib/dragonrealms/dependency/settings_config_spec.rb` | **New**
-- 7 examples |
| `spec/lib/util/update_sync_spec.rb` | **New** -- 13 examples |

## Test Plan
- [x] `rspec spec/lib/common/arg_parser_spec.rb` -- 9 examples
- [x] `rspec spec/lib/common/setup_files_spec.rb` -- 18 examples
- [x] `rspec spec/lib/common/settings_transformer_spec.rb` -- 22
examples
- [x] `rspec spec/lib/dragonrealms/dependency/settings_config_spec.rb`
-- 7 examples
- [x] `rspec spec/lib/util/update_sync_spec.rb` -- 13 examples
- [x] Full suite: `rspec` -- all 3550 examples pass (0 failures)
- [x] Manual: boot lich, verify DR login works, `get_settings` returns
valid data
- [x] Manual: `;lich5-update --sync` downloads only changed files
- [x] Manual: `;lich5-update --tracked` displays formatted table
- [x] Manual: `;lich5-update
--branch=MahtraDR:feat/core-argparser-setupfiles-transformer` installs
from fork
- [x] Manual: `;lich5-update --branch` re-downloads when already on same
branch (picks up newer commits)
- [x] Manual: verify GS login triggers auto-sync of EO/scripts
- [x] Manual: verify `--update` no longer force-downloads scripts

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants