Fixes for broken master, trust-based source selection, module split, feed discovery & caching, sectioned config, and release tooling#26
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR aims to restore a working “master” by reintroducing missing version-handling functionality, fixing several regressions in module loading and update/feed handling, and adding initial unit-test and line-ending consistency infrastructure.
Changes:
- Added
SemanticVersioningand migrated version parsing/formatting to use it across updater/feed paths. - Fixed/adjusted updater + module-loader behaviors related to initialization and update flows, and added a minimal DepCtrl unit test.
- Updated the project update feed metadata, bumped versions, and enforced LF + final newline consistency.
Reviewed changes
Copilot reviewed 12 out of 15 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| modules/DependencyControl/Updater.moon | Migrates updater version handling to SemanticVersioning and adjusts update logging/changelog display. |
| modules/DependencyControl/UpdateFeed.moon | Adds legacy scriptType compatibility + new invalid scriptType messaging; moves DownloadManager init earlier. |
| modules/DependencyControl/UnitTestSuite.moon | No functional change (newline normalization). |
| modules/DependencyControl/Tests.moon | Adds a first unit test for Common.terms.capitalize. |
| modules/DependencyControl/SemanticVersioning.moon | Introduces semantic version parsing/formatting/comparison utilities. |
| modules/DependencyControl/Record.moon | Switches record version parsing to SemanticVersioning and adds compatibility helpers. |
| modules/DependencyControl/ModuleLoader.moon | Updates init-hook guard logic and switches version formatting/parsing to SemanticVersioning. |
| modules/DependencyControl/FileOps.moon | No functional change (newline normalization). |
| modules/DependencyControl/ConfigHandler.moon | No functional change (newline normalization). |
| modules/DependencyControl/Common.moon | Fixes capitalize() implementation to avoid unsupported string indexing. |
| modules/DependencyControl.moon | Bumps DepCtrl version, exposes SemanticVersioning, and adds a Moonscript minimum-version guard. |
| macros/l0.DependencyControl.Toolbox.moon | Bumps toolbox version; updates version formatting and script-type handling; registers DepCtrl test suite. |
| DependencyControl.json | Updates feed versions/hashes and adds new files (including tests) to the module feed. |
| .vscode/settings.json | Enforces final newline on save in VS Code. |
| .gitattributes | Enforces LF line endings in git. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
line0
force-pushed
the
add-missing-semver-module
branch
2 times, most recently
from
May 23, 2026 22:10
7f7ad69 to
9fee44a
Compare
line0
force-pushed
the
add-missing-semver-module
branch
from
May 23, 2026 22:46
9fee44a to
ad4a5ec
Compare
number segments over 255 and non-dot separate values
…r string is passed
line0
force-pushed
the
add-missing-semver-module
branch
from
May 23, 2026 23:14
ad4a5ec to
5bc3f45
Compare
nothing inside DepCtrl is supplying this parameter, so the only effect this bug would have had, is removing the default guard against modules trying to load themselves
- assert now passes through all varargs on success (allows chaining) - new assertNotNil method - fails only on nil, unlike assert which also fails on false - dump/dumpToString methods accept a maxDepth to cap recursive table output - new static Logger.describeType method - returns Lua type name but renders MoonScript class instances as "ClassName object" - fix: guard log/format calls against non-string message templates
Encode and decode the config through l0.dkjson directly instead of a generic `json` (one json lib per file), and write it with dkjson's Prettier-flavored indentMode plus a trailing newline, so a hand-edited config file stays readable. Decoding via dkjson's nil+error return also makes corrupt-file handling consistent (a parse failure now always backs the file up), rather than depending on the json lib's error convention. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a "Global Configuration" macro that edits DependencyControl's global settings (updates/feeds/logging/paths) in one sectioned dialog, leaving the three feed lists to Manage Feeds. A declarative field table drives the form and sources every effective default from its owning class or the central config-schema; integers use native intedit widgets, enums dropdowns, booleans checkboxes, and paths edits. Values left at their default are unset so the config file stays minimal, and crawlLimits is reassigned as a fresh object. Adds a GlobalConfig test class and a Toolbox changelog entry. Also refreshes the feed's file hashes to match the current sources. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…records triggering downstream bugs
Triggered by a bad required module spec (`{"ffi", "json"}`) in the ILL.ILL module
The prettier `indentMode` encoder had three issues, all reachable now that dkjson is exported (`json`/`dkjson`) to the whole ecosystem: - Non-deterministic key order: the default case-insensitive sort left keys that fold to the same lowercase string (e.g. name/Name) ordered by table iteration, so identical objects could serialize to different bytes and churn config/feed files on every rewrite. Ties are now broken by the raw key, giving a total order. - Reference cycles overflowed the stack instead of failing cleanly. The encoder now raises "reference cycle" — the same error upstream dkjson raises in every other mode — via a pre-flight ancestor walk. - Output now ends with a single trailing newline, matching Prettier. The callers that appended "\n" by hand (ConfigHandler, UpdateFeed) drop it; those that omitted it (dumpExpanded, FileCache) gain it, so every file DepCtrl writes ends consistently. Grow the prettier encoder tests from 4 round-trips to 31 mostly exact-output cases: layout, key ordering, width-based array breaking, cycles, and the trailing newline. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ent config hive
After waiting on the updater lock, refreshRecord reloads each pending module
via loadConfig. ConfigView\load returns true even for a hive missing from the
file, so an uninstalled module was mistaken for an installed one and its
identity fields (moduleName/namespace) were blanked while scriptType stayed
Module — the follow-up loadModule then indexed package.loaded with a nil key
("table index is nil").
Treat a hive as a real install only when it carries a version, so a still-
virtual module with no hive stays virtual and installs normally. Import stays a
full overwrite (so a field an update dropped, e.g. a removed provides, clears)
except moduleName/namespace, which a corrupt hive must never blank.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…of its DepCtrl record no longer demotes it to unmanaged hello ILL
line0
force-pushed
the
add-missing-semver-module
branch
3 times, most recently
from
July 22, 2026 22:32
ade6961 to
ff0fa9a
Compare
default branch changed
open(2) and sem_open(3) are variadic but were cdef'd with fixed prototypes and passed bare-number args. Harmless on x86-64, but the arm64 Apple ABI passes varargs on the stack, so the mode/value arrived as garbage — file locks failed to exclude and the first sem_wait blocked forever. Declare them variadic and pass the integer args as typed cdata.
line0
force-pushed
the
add-missing-semver-module
branch
2 times, most recently
from
July 23, 2026 00:32
d020a1e to
2056bfe
Compare
line0
force-pushed
the
add-missing-semver-module
branch
from
July 23, 2026 00:47
2056bfe to
0e9bb28
Compare
- switch to maintained luarocks action which supports windows - switch windows build toolchain to msvc - run windows tests in pwsh - install zlib via vcpkg on windows test runner - adjust zlib name for lzlib - caching for slower windows workflow
line0
force-pushed
the
add-missing-semver-module
branch
from
July 23, 2026 01:08
0e9bb28 to
be2852d
Compare
Contributor
Test results — macos-latest ✅1032 · ubuntu-latest ✅1032 · windows-latest ✅1028Summary
🎉 No failed tests in this run. Github Test Reporter by CTRF 💚 🔄 This comment has been updated |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR description
Summary
This branch started as a set of fixes to unbreak
masterafter the incomplete 0.7.0 refactor, but it has grown to carry the bulk of the 0.7.0 work itself. It is being merged as a single unit. The list below describes the delta againstmaster, grouped by area rather than by commit (history was rebased/reworked as we iterated, so individual commits are not a reliable map of the end state).At a high level, relative to
masterthis branch:SemanticVersiontype, a computed-property primitive (Accessors), and a feed trust/security model (FeedTrust,Host, SSRF guard, fetch policy).aegisub.re/aegisub.utildependencies.It also introduces a few one-time, persisted config migrations.
Reviewability note
This is intentionally a large single PR. The genuine "unbreak master" fixes (SemanticVersion presence, script-type handling, the double-init regression,
capitalize, lateDownloadManagerinit, the multi-assignment corruption) are the smallest slice; everything else is new 0.7.0 surface. Reviewers short on time should concentrate on the Security and Migrations sections, which change what gets fetched/executed and mutate users' config files.Changelog — 0.7.0
Added
Version handling
SemanticVersionmodule: parsing, formatting and comparison utilities (absent onmaster), plus an instantiable version value object — construct from a string, from numeric components, orfromPacked; instances compare with</<=/==, stringify, bump immutably, and test range satisfaction. Static helpers accept an instance anywhere they take a version.providesmodule aliases.Core primitives
Accessors: metatable-backed computed properties.Accessors.property{get, set}in the class body plusAccessors.install(class)after it; setter-less properties are read-only, subclasses inherit parent properties, every property is recorded onclass.__accessors, and readable properties appear inpairs(instance)via__pairs.Trust & networking
FeedTrustclass: centralized trust/block logic. Trusted / blocked / extra-feed lists with add + remove; block entries are objects carrying a match mode (prefix or exact) and a block reason; trust/block data can be sourced from the official feed.Hostclass: DNS resolver binding and private/loopback host detection (isPrivate, memoized).FeedInventory: breadth-first feed crawler, with every root and child gated through the fetch policy.Self-contained runtime
NamedSemaphore/FileLocklocking primitive that uses only OS APIs, as a replacement for the BadMutex dependency.DownloadManageralternative built on OS APIs or an installed libcurl, with stall detection and a concurrent-connection limit.dkjson, provided asjsonwhenluajsonis not installed; module import aliases.?userdirectory to the Lua/Moon search path.FileOps / Common
FileOps.writeFile().Commonhelper to detect running headless / in CLI.Toolbox
Tooling
Changed
l0/directory to match their require paths. (Confirm downstream require paths before tagging.)SemanticVersioninstance (@semanticVersion);record.versionis now a packed-integer accessor over it, so existing packed-int reads/writes/comparisons are unchanged. The version is persisted to config as amajor.minor.patchstring.Downloader:getProgress→progress,Lock:getState→state,UnitTestSuite:getFailures→failures, andHostisPrivate. (getVersionNumber/getVersionStringremain instance methods.)UpdateStatusenum;scriptTypeis aScriptTypeenum end-to-end.aegisub.reoraegisub.util.?dataautomation directory.assertpasses all varargs through on success (chainable); newassertNotNil(fails only on nil);dump/dumpToStringaccept amaxDepth; newdescribeType; log/format calls guard against non-string templates; incremental progress-bar fill; RNG warmed up after seeding._orderno longer required; tests can be skipped; per-test durations measured with a monotonic wall clock instead of CPU time.Security
Host+ DNS resolver).FileOps.remove()no longer recurses into directories by default, removing a silent whole-tree deletion path.Fixed
Updater / loader
__depCtrlInithooks were re-run on already-initialized modules, breaking modules that mutate exported state on first init (e.g. BadMutex).true/falsescript-type arguments were rejected after theScriptTypeenum migration.DownloadManagerwas instantiated too late, failing the update process.performUpdategated unmanaged-record handling on a nonexistentupdateRecordTypefield, so unmanaged modules never registered a dummy ref/version and the dummy ref was never cleaned up on failure.loadModule, crashing on a string index.Record.checkVersionignored its precision argument.SemanticVersion
toStringroundtrip raised on an invalid version string.getChangelogafter a successful install; such keys are now skipped.FileOps
joinPathdropped every segment after an empty/separator-only one (joinPath("a", "", "b")→"a").movedid not create destination directories recursively and emitted wrong error messages.mkdirreported success on failure;createTempDir/rmdirerrors lacked detail.Config
ConfigHandlercache was scanned by raw path instead of validated path, building duplicate handlers with divergent in-memory config for the same file.ConfigViewdid not register/unregister itself with its handler onsetFile/unsetFile, so whole-file refreshes skipped it and its writes were lost after another view replaced the backing tables.unmanagedflag instead ofrecordType, round-tripping unmanaged records back to managed.writeConfigwas not actually called when persisting a new record.Feed / trust / deployment
deleteflag on files.Concurrency / logging
NamedSemaphorecalledsem_unlinkon per-instance GC, letting an ephemeral handle remove a name still held by another owner and producing split-brain locks on POSIX; unlink is now deferred to Lua-state teardown. (Windows unaffected; verified on WSL with a regression test.)Common
itemsEqualtracked items as a boolean set, so duplicates matched incorrectly ({1,1}vs{1,1}→ false); now count-matched as a multiset.Platform / misc
package.pathcorruption when the existing path did not end in a semicolon.capitalize()used unsupported string indexing and had never actually worked; the depctrl CLI used the wrong config filename; assorted wrong file names and log tags.Removed
aegisub.re,aegisub.util, PreciseTimer, external BadMutex and external DownloadManager (replaced by internal equivalents — see Changed).Migrations (one-time, persisted on first load)
unmanagedflag →recordType; the obsolete flag is dropped from the config file.major.minor.patchstring.Both run once and persist. Note the implication for users who roll back to 0.6.x after a migrated load.
Dev / docs
AGENTS.mdcontribution conventions (annotation/comment style, file naming, MoonScript gotchas, public-API and test-exposure patterns, computed properties, changelog rules).validateFullPath/validateNamespace, FileLock / NamedSemaphore, downloader integration, Toolbox plumbing, wider Updater coverage; tests split into per-file suites; record-registry cleanup after runs; mock-server readiness fix.