Commit Graph
76 Commits
Author SHA1 Message Date
Abdessamad Derraz 0d3a2b87ed fix: name homonymous release assets by path 2026-10-05 02:51:13 +02:00
Abdessamad Derraz 243e95725b fix: print the released pack counts, not main's 2026-10-04 20:26:09 +02:00
Abdessamad Derraz 14975ce5da fix: keep an issue number from opening a heading 2026-10-04 20:02:34 +02:00
Abdessamad Derraz 52f682cdd6 feat: publish a large pack as zips, not byte ranges 2026-10-04 18:09:24 +02:00
Abdessamad Derraz 63af5167ed feat: state how many files each pack holds 2026-10-04 18:01:33 +02:00
Abdessamad Derraz 2efc37a738 feat: pack the files a directory entry names 2026-10-04 17:58:10 +02:00
Abdessamad Derraz 1be50e056f docs: state what separates two platform packs 2026-10-04 17:49:16 +02:00
Abdessamad Derraz 59ccb5b7d5 feat: scope a profile data directory to a build mode 2026-10-04 17:09:14 +02:00
Abdessamad Derraz b81199ff26 feat: keep cached platform originals in step 2026-10-04 16:36:35 +02:00
Abdessamad Derraz 08bce47668 fix: keep install manifests and release assets true 2026-09-14 01:17:49 +02:00
Abdessamad Derraz 691ccbfca7 feat: make the native export round-trip a platform file 2026-09-05 17:32:48 +02:00
Abdessamad Derraz a0b2263bae feat: let a profile say its pin is held on purpose
nethersx2-turnip-classic documents the shim rules of the revision it
pins, and says so in prose: the classic build is that revision. Compared
to HEAD it reported the same two changes every pass, and recaling would
have repointed its refs at rules this build never had.

pin_frozen says the freeze is deliberate, and the profile is then judged
against its own revision, exactly as one pinned to a superseded tag
already was. Recale and bump are refused for it, which is what makes the
declaration safe to trust.
2026-09-05 10:50:53 +02:00
Abdessamad Derraz 771c38ab09 fix: say nothing was run when the fingerprint differs 2026-09-05 07:50:18 +02:00
Abdessamad Derraz ab170f990d docs: add a first install walkthrough 2026-09-05 07:46:06 +02:00
Abdessamad Derraz 45e21fca51 docs: cover android in the installer pages 2026-09-05 07:02:57 +02:00
Abdessamad Derraz f864613f11 feat: detect android in the installer 2026-09-05 07:00:12 +02:00
Abdessamad Derraz c738073f66 fix: move the refs and the pin together or not at all
Recaling refs while the pin stays put produces exactly the state the
all-or-nothing rule exists to prevent: a profile whose refs describe one
revision and whose source_commit names another. The tool manufactured it
on mariani, where three prose runs it could not rewrite kept
bump_commit refusing while eleven refs had already moved.

Asking for both writes is now atomic. The work happens on a copy, which
is promoted only when the pin follows, and a rebase is refused outright
when something visible beforehand will hold the pin: an annotated ref,
one under a mode key, or a prose run whose tokens cannot be located well
enough to rewrite. Where the block only appears after the write, the
copy is discarded and the profile is named on stderr rather than left
half moved.

mariani is back on its pin and stays at four refs to read, which is
honest: three of them have to be rewritten by hand before anything can
advance.
2026-09-04 18:55:15 +02:00
Abdessamad Derraz d124f6c516 feat: watch the profiles that declare no files
An empty file list is the one assertion here that ages unwatched. Nothing
can go missing and no ref can drift, so nothing notices when a core that
embedded everything grows a path. virtualjaguar said "No external BIOS
files are required or loaded by this core" while its source had grown
eleven filenames read from the system directory, and only a reading
found it.

fileless_audit looks for the request itself, the system directory ask, in
the sources each profile already cites. Over the 151 fileless profiles it
named eleven, of which two were covered by data_directories, six carried
an exclusion_note, and three had nothing written down at all: craft
writes its world database in that directory, dice stores the answer in a
variable no other file in the tree names, lutro hands it to the Lua game.
Each now says so.

The check settles: declared files, a declared directory, or a written
answer all end it, so what it reports is the set nobody has read yet. A
test holds the corpus at zero.
2026-09-04 18:13:53 +02:00
Abdessamad Derraz 1a1f19be2d feat: check a MAME ref against the set it names
profile_sync follows content, so a ref that drifted still anchors where
the cited text went. That is drift detection working, and it cannot
answer the only question a MAME romset ref asks: does this line declare
this set. It flagged five refs in one driver file where nineteen were
stale, the fourteen others having been relocatable somewhere plausible.

mame_ref_audit asks the stronger question and found ninety-two across
the four profiles whose upstream still moves: mame 66, mamearcade 18,
mamemess 6, groovymame 2. Each had exactly one declaration to point at.
The frozen generations, mame2009 through mame2016, come out clean, which
is the check saying it finds drift only where drift can happen.

The set name is argument 1 of the machine macro. Matching it anywhere on
the line matches every clone naming it as parent, which is most of a
driver, and comments are stripped first because a declaration can sit
behind one. A set no machine declares is reported as not judgeable, not
wrong: device archives take their DEFINE_DEVICE_TYPE shortname.
2026-09-04 17:48:24 +02:00
Abdessamad Derraz 5ccdaa6bdf docs: the release key is registered, so name the cross-check 2026-09-04 17:32:14 +02:00
Abdessamad Derraz ece637d52d feat: let a profile state that its upstream is gone
Saying those profiles would stay open no matter what was wrong. A dead
forge is a verifiable fact, and a fact can be recorded: upstream_gone
carries why, and the profile stops being an open problem. The refs
describe the last revision anyone could reach, which is all any reader
can ask of them.

The declaration is guarded rather than trusted, because a forge can come
back and a profile that keeps asserting a death nobody rechecks is worse
than one that fails loudly. Declared and unreachable reports as a
recorded fact; declared and answering reports as the contradiction it
is, and the profile has to be read again.

yuzu and suyu carry GitHub's 451. citron carries the loss of
git.citron-emu.org and the squatter now sitting on the .com. Each names
what was probed and when, so the next reader retraces it rather than
repeating it.
2026-09-04 17:25:23 +02:00
Abdessamad Derraz f45050aa5c docs: say what a gone forge and a mirror do 2026-09-04 15:36:10 +02:00
Abdessamad Derraz 3891d897a6 fix: report the writes a dry run would make
--backfill-commits and --realign-prose have always printed what they
would write. --rebase-refs and --bump-commit took the flag and printed
nothing, so the only way to read a plan was to let it happen, and the
recale and the pin had to be done in two full network passes with
--force in between.

Both now plan. The plan runs the production write path over a throwaway
copy rather than a parallel branch, so it cannot drift from the write,
and the planned bump reads the text the recale would have left: a pin
held back by prose the same pass would move is no longer reported as
blocked. One pass does both, recale before bump on each profile.

bump_commit also stopped announcing a rewrite of the pin to the value it
already held. On the corpus that was 126 of 232 announcements, which
buried the 106 profiles that did move.
2026-09-04 14:41:37 +02:00
Abdessamad Derraz 1a96853aee feat: sign the release checksum list
SHA256SUMS.txt sat beside the artifacts it vouches for, so whoever could
rewrite a release rewrote the list with it. The packs were already
reproducible, which answers corruption and lets a third party rebuild an
archive byte for byte; nothing answered a rewritten release.

The list is now signed with an ed25519 key kept for this alone, and the
public half is allowed_signers at the repository root, so verification
does not go through the release page: ssh-keygen -Y verify against the
committed file, then sha256sum --check. Rehearsed on all three outcomes:
a good signature, a tampered pack caught by the sums, a rewritten list
caught by the signature.

The release steps sign and upload the signature, the README points a
downloader at the procedure, and the reproducibility section says what
each half proves. Rotation keeps retired lines so past releases stay
verifiable. Three tests hold the trust root, the signing step and the
documented principal in agreement.
2026-09-04 14:01:05 +02:00
Abdessamad Derraz 5587c25675 fix: run the suite on both roads into main
validate.yml triggered on pull_request alone, and it holds the only
unittest invocation in the repository: deploy-site.yml stops at
validate_schemas, generation and the freshness diff. Work lands on main
by direct push far more often than by pull request, so 1,318 cases were
guarding the road almost nothing takes.

The suite and the schema check now run on both events. validate-bios and
label-pr read pull request context and carry an event guard. The
concurrency group falls back to the ref, so a push series collapses to
the tip: what stays verified is the head of main.

The path lists are spelled out per event because the workflow parser
reads no YAML anchor, which PyYAML would have accepted in silence. Four
tests hold the wiring: the suite reachable from a push, the two path
lists equal, every job reading pull request context guarded, and no
anchor in any workflow.
2026-09-04 13:40:11 +02:00
Abdessamad Derraz 60c723a3bf docs: name the files adler32 belongs to
The field reference carried the same attribution the FAQ did:
known_hash_adler32 described as Dolphin's IPL files, when dolphin.yml
declares it on dsp_rom.bin and dsp_coef.bin. The guard now scans every
wiki page rather than the FAQ alone.
2026-09-04 11:43:38 +02:00
Abdessamad Derraz fe77535c3b fix: state one catalog ratio, correct the faq
The home page and the stats export counted every file carrying a
provenance record, the provenance page and the README only the system
files. The site published 553 and 566 for the same quantity, one click
apart, and the export paired the wider count with composition.systems as
its denominator. common.count_catalog_matched is now the single source,
scoped to the systems bucket.

The FAQ had drifted from the profiles it describes: MAME pinned at 0.287
against 0.289 in mame.yml, Adler-32 attributed to Dolphin's IPL rather
than the DSP ROMs that carry known_hash_adler32, and the per-emulator
verbose report named as the only content check on an existence platform,
which skips the DISCREPANCY line the platform report raises itself.

Tests read both sides: no generator may count matches inline, and each
FAQ claim is checked against the profile or the script that owns it.
2026-09-04 11:41:17 +02:00
Abdessamad Derraz 022888e9ea docs: name the two sizes a pack has 2026-09-04 10:19:04 +02:00
Abdessamad Derraz 626c012a6b docs: document split packs and region filtering 2026-09-04 10:18:14 +02:00
Abdessamad Derraz 361b958f41 feat: download packs published as split volumes 2026-09-04 10:18:14 +02:00
Abdessamad Derraz d368b37165 docs: surface region filtering in the readme 2026-09-04 08:31:05 +02:00
Abdessamad Derraz 11c4a6a945 docs: answer the installer questions on the page 2026-09-04 08:31:05 +02:00
Abdessamad Derraz b1d1eeab06 docs: give the installer a page of its own 2026-09-04 06:55:23 +02:00
Abdessamad Derraz f2346d6001 docs: keep only the latest release 2026-09-04 04:40:50 +02:00
Abdessamad Derraz 9669ae06d2 docs: publish a release only once its assets are up 2026-09-04 04:16:58 +02:00
Abdessamad Derraz 7ff6ea20d1 docs: one pack per platform, the complete one 2026-09-04 04:10:15 +02:00
Abdessamad Derraz 26df60db75 chore: build releases locally, retire the ci build 2026-09-04 03:37:01 +02:00
Abdessamad Derraz d66e891051 chore: retire the weekly platform sync 2026-09-03 17:34:22 +02:00
Abdessamad Derraz 8b404e500f fix: keep a packed file's executable bit
Pinning every member's metadata made packs reproducible and took the
executable bit with it. The RetroDECK pack ships the two Voxatron engine
binaries, and extracted at 644 they cannot be run.

Git records the bit, so reading it from the source file keeps a pack the
same from any clone. Nothing else about the source's mode reaches the
archive: 2569 members ship at 644 and 942 at 755, which is what the
builder produced before the pinning.

Nothing caught this. The comparison that proved the pinning inert
checked member names, CRCs and sizes, and mode is none of those. A test
now builds a runnable payload and asserts it survives extraction.

RetroDECK rebuilds to the same bytes twice and passes its integrity
check, 2008/2008 baseline and 1551/1551 cores.
2026-08-23 07:58:23 +02:00
Abdessamad Derraz 4b8d7baac5 feat: transcribe bios search orders into priority 2026-08-11 19:18:30 +02:00
Abdessamad Derraz 36a284b93b fix: name and announce every narrowed pack 2026-08-11 17:54:28 +02:00
Abdessamad Derraz 4bd277a7be feat: name every narrowing in the pack filename 2026-08-11 16:56:20 +02:00
Abdessamad Derraz d37caecc27 test: cover slot naming and per-system extras 2026-08-11 16:06:20 +02:00
Abdessamad Derraz 85f3f7c393 fix: read the bios preference order the code applies 2026-08-11 14:34:49 +02:00
Abdessamad Derraz a372f2abf3 feat: keep one bios per slot on declared order 2026-08-11 13:34:15 +02:00
Abdessamad Derraz 1f33148180 chore: make the release a manual dispatch
The job carried if: false, which blocks workflow_dispatch as well as
push, so there was no way to cut a release through CI at all and the
comment described a temporary state that had become permanent.

Releasing is deliberate: the push trigger is gone and the job runs when
someone dispatches it. The seven-day rate limit stays as the guard
against dispatching twice, and concurrency no longer cancels a run that
may be midway through uploading assets.
2026-08-11 05:08:40 +02:00
Abdessamad Derraz 367d4efaac feat: tag filtered packs by region and target
A region- or target-filtered build wrote to the same filename as the
full one. Both filters now appear in the pack and manifest names, and
verify.py accepts --region for emulator and system reports so the
coverage figures come from the same selection the builder used.
2026-08-11 00:56:14 +02:00
Abdessamad Derraz 958b988015 docs: scope the licence and temper the legal claims
LICENSE covered the whole repository, so the MIT grant read as
covering 9.9 GB of third-party firmware. It now states its scope and
NOTICE describes the files it does not cover, with a removal channel.

The FAQ cited Connectix and Accolade for redistribution when both
decided intermediate copying during reverse engineering, presented fair
use as settled, read section 1201(f) as a general permission, and
listed abandonware among legal doctrines. Each claim is now stated at
the strength it actually has, and the weakest ground is named.
2026-08-11 00:54:10 +02:00
Abdessamad Derraz 64ab248802 docs: state when a file carries a region 2026-08-10 18:08:57 +02:00
Abdessamad Derraz c00314d479 docs: align the wiki with what the code does
The pages described workflows, an installer pinning and a CI permission
model that are not the ones in the tree. Corrected: the release process,
the CI table, the resolution chain and its statuses, the hash-mismatch
policy per verification mode, the archive convention, and the romset
recipe store.

The FAQ keeps the project's own reading of the legal question rather
than a version that reaches no conclusion.
2026-08-10 13:37:20 +02:00