[GH-ISSUE #7478] [Design] One owner each for target-format and architecture vocabularies #4461

Open
opened 2026-10-31 00:50:01 +00:00 by bsakaguchi · 3 comments
Owner

Originally created by @Entrpi on GitHub (Oct 27, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/7478

Before submitting

  • I searched the open and closed issues and pull requests for a related discussion.
  • I understand the contribution scope must be reviewed before integration; open questions are welcome here.
  • This discussion does not include credentials, private samples, or sensitive target data.

Decision needed

Would you accept two behaviour-preserving refactors, with the format half first?

  1. One owner (a single table) for target formats, from which the format enums and declaration lists are derived.
  2. One owner for architecture families, with typed per-provider lane tables. These make IDA, Hopper and Kuna list every family explicitly.

Context and evidence

Each new target format is added by hand to about eight vocabularies:

  • executableFormatHintSchema;
  • the BinaryTarget union;
  • the Evidence subject formats and declarations;
  • the snapshot format and target schemas;
  • the live summary variants;
  • the artifact-graph formats;
  • the load-image union and view.

Missing one caused #7290. 50822e1ef unified only the subject declarations.

For architectures, among 16 architecture change sets:

  • 15 touched src/domain/binaryTargetTypes.ts;
  • 12 touched src/ghidra/GhidraProvider.ts;
  • 5 of the 7 open architecture PRs conflict.

The same facts drift across copies:

  • The Ghidra refusal text omits PowerPC and Hexagon.
  • Hopper advises a "verified Ghidra Hexagon profile" that does not exist.
  • Hexagon needed a follow-up (ef05713d8) for a second machine map.
  • IDA admits by denylist, so an unlisted family reports "supported".

Expected interaction with targets

No target interaction (documentation or usability only)

Boundary details

No behaviour change. The advertised schema digests must be identical before and after each step. Provider language ids stay in provider adapters, never in the domain.

Options and tradeoffs

  1. Proposed: land the format table first, since it touches no architecture hot spot. Then the domain family table, then one provider table per PR. Open PRs need only mechanical, append-only rebases.
  2. Keep the current structure, adding a conformance test that every format appears in every vocabulary. That test is a guard, not a fix.

Verification available so far

I have a prototype or observed results

The conformance test from option 2 exists on a local branch. The counts above come from git log over the cited change sets.

Success criteria and open questions

  • Identical advertised schemas.
  • The per-family test copies are replaced by one table-driven test.
  • A new format or header-only architecture becomes a table row, plus its lane and docs.
  • Open question: should the IDA allowlist land separately first? It is a small fail-open fix.

References

#7290, 50822e1ef, #4819 (Hexagon), and the open architecture PRs #4843, #4678, #4911, #4811, #2362, #4532 and #1922.

Originally created by @Entrpi on GitHub (Oct 27, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/7478 ### Before submitting - [x] I searched the open and closed issues and pull requests for a related discussion. - [x] I understand the contribution scope must be reviewed before integration; open questions are welcome here. - [x] This discussion does not include credentials, private samples, or sensitive target data. ### Decision needed Would you accept two behaviour-preserving refactors, with the format half first? 1. One owner (a single table) for target formats, from which the format enums and declaration lists are derived. 2. One owner for architecture families, with typed per-provider lane tables. These make IDA, Hopper and Kuna list every family explicitly. ### Context and evidence Each new target format is added by hand to about eight vocabularies: - `executableFormatHintSchema`; - the `BinaryTarget` union; - the Evidence subject formats and declarations; - the snapshot format and target schemas; - the live summary variants; - the artifact-graph formats; - the load-image union and view. Missing one caused #7290. `50822e1ef` unified only the subject declarations. For architectures, among 16 architecture change sets: - 15 touched `src/domain/binaryTargetTypes.ts`; - 12 touched `src/ghidra/GhidraProvider.ts`; - 5 of the 7 open architecture PRs conflict. The same facts drift across copies: - The Ghidra refusal text omits PowerPC and Hexagon. - Hopper advises a "verified Ghidra Hexagon profile" that does not exist. - Hexagon needed a follow-up (`ef05713d8`) for a second machine map. - IDA admits by denylist, so an unlisted family reports "supported". ### Expected interaction with targets No target interaction (documentation or usability only) ### Boundary details No behaviour change. The advertised schema digests must be identical before and after each step. Provider language ids stay in provider adapters, never in the domain. ### Options and tradeoffs 1. *Proposed:* land the format table first, since it touches no architecture hot spot. Then the domain family table, then one provider table per PR. Open PRs need only mechanical, append-only rebases. 2. Keep the current structure, adding a conformance test that every format appears in every vocabulary. That test is a guard, not a fix. ### Verification available so far I have a prototype or observed results The conformance test from option 2 exists on a local branch. The counts above come from `git log` over the cited change sets. ### Success criteria and open questions - Identical advertised schemas. - The per-family test copies are replaced by one table-driven test. - A new format or header-only architecture becomes a table row, plus its lane and docs. - Open question: should the IDA allowlist land separately first? It is a small fail-open fix. ### References #7290, `50822e1ef`, #4819 (Hexagon), and the open architecture PRs #4843, #4678, #4911, #4811, #2362, #4532 and #1922.
Author
Owner

@Entrpi commented on GitHub (Oct 28, 2026):

A prototype of the format half (option 1) is ready for design review on my fork: compare with main. It's a demonstration for your decision, not a PR. I'm at the open-PR limit, and nothing will build on it until you decide.

What it does. src/domain/targetFormats.ts has one row per format: target kind, architecture rule, entry point, explicit selection, load-image lane, artifact-graph role and ZIP family. The eight vocabularies listed above derive from the rows, and so do ZIP_PACKAGE_FORMATS, the resolver's archive check and the Ghidra load-image lane check. Per-format members are satisfies Record<…> maps, and expectTypeOf ties BinaryTarget to the rows, so a missing branch fails compilation.

No contract change. I digested every MCP tools/list listing in all six schema profiles, the server's catalog identity, and the CLI --schema output of all 178 commands plus --llms and --help, on main at dfa068989 (with #7498's esp-image) and with the change. All are byte-identical. The only difference is in the snapshot file parser, which isn't advertised: a corrupt snapshot's error lists the expected formats in table order.

Adding a format (vocabulary edits only; the detection code is the same on both sides):

Dummy format main Prototype
Archive identified from bytes, like uImage or the ESP image 7 edits in 6 files; 2 compile if forgotten 1 row; forgetting it fails to compile
Caller-selected executable with a header entry, like DOL 16 edits in 9 files; 6 compile if forgotten the row, its BinaryTarget member and Hopper's loader decision; forgetting any fails to compile

#7498 made exactly the first row's seven edits for esp-image. The tests had copies too: the live
summary test's archive list misses unityfs, uimage, intel-hex, srec and esp-image. The prototype derives those fixtures from the rows.

Two questions:

  1. Byte-identity needs three frozen order pins, because three advertised enums used other orders than the Evidence subject list (the artifact occurrence and node formats, and the live header executables). New formats append, so the pins never change. Would you rather accept a one-time reorder of those three enums and drop the pins? JSON Schema enum order has no meaning, but the catalog digests would change once.
  2. The reader dispatch lists in src/artifacts/ still name formats (8 places for an archive reader). Should they become reader capabilities on the rows in a later step, or stay as they are?

If you accept the direction, I'll open it as a PR when a slot frees up.

<!-- gh-comment-id:6483229764 --> @Entrpi commented on GitHub (Oct 28, 2026): A prototype of the format half (option 1) is ready for design review on my fork: [compare with `main`](https://github.com/morluto/rea/compare/main...Entrpi:rea:refactor-target-format-owner). It's a demonstration for your decision, not a PR. I'm at the open-PR limit, and nothing will build on it until you decide. **What it does.** `src/domain/targetFormats.ts` has one row per format: target kind, architecture rule, entry point, explicit selection, load-image lane, artifact-graph role and ZIP family. The eight vocabularies listed above derive from the rows, and so do `ZIP_PACKAGE_FORMATS`, the resolver's archive check and the Ghidra load-image lane check. Per-format members are `satisfies Record<…>` maps, and `expectTypeOf` ties `BinaryTarget` to the rows, so a missing branch fails compilation. **No contract change.** I digested every MCP `tools/list` listing in all six schema profiles, the server's catalog identity, and the CLI `--schema` output of all 178 commands plus `--llms` and `--help`, on `main` at `dfa068989` (with #7498's `esp-image`) and with the change. All are byte-identical. The only difference is in the snapshot file parser, which isn't advertised: a corrupt snapshot's error lists the expected formats in table order. **Adding a format** (vocabulary edits only; the detection code is the same on both sides): | Dummy format | `main` | Prototype | | --- | --- | --- | | Archive identified from bytes, like uImage or the ESP image | 7 edits in 6 files; 2 compile if forgotten | 1 row; forgetting it fails to compile | | Caller-selected executable with a header entry, like DOL | 16 edits in 9 files; 6 compile if forgotten | the row, its `BinaryTarget` member and Hopper's loader decision; forgetting any fails to compile | #7498 made exactly the first row's seven edits for `esp-image`. The tests had copies too: the live summary test's archive list misses `unityfs`, `uimage`, `intel-hex`, `srec` and `esp-image`. The prototype derives those fixtures from the rows. **Two questions:** 1. Byte-identity needs three frozen order pins, because three advertised enums used other orders than the Evidence subject list (the artifact occurrence and node formats, and the live header executables). New formats append, so the pins never change. Would you rather accept a one-time reorder of those three enums and drop the pins? JSON Schema `enum` order has no meaning, but the catalog digests would change once. 2. The reader dispatch lists in `src/artifacts/` still name formats (8 places for an archive reader). Should they become reader capabilities on the rows in a later step, or stay as they are? If you accept the direction, I'll open it as a PR when a slot frees up.
Author
Owner

@Entrpi commented on GitHub (Oct 28, 2026):

Proposed answers to the two questions above, so each has a concrete default to accept or redirect:

  1. Order pins: drop them with a one-time reorder, as a separate final commit in the same PR. The refactor commit stays byte-identical, so its proof still holds, and the three advertised enums then follow the table's order with no permanent pin lists. JSON Schema enum order carries no meaning; the catalog digests change once, and the PR's compatibility section will say so.
  2. Reader dispatch lists: yes, in a later step, but not on the domain rows, since src/domain must not depend on artifact readers. One reader registry in src/artifacts, keyed by the domain's archive-format type with satisfies Record<…>, would replace the eight lists, so a missing reader fails to compile and each layer keeps one owner.

The IDA allowlist question in the issue is answered by #7485, which went out separately.

<!-- gh-comment-id:6483783640 --> @Entrpi commented on GitHub (Oct 28, 2026): Proposed answers to the two questions above, so each has a concrete default to accept or redirect: 1. **Order pins:** drop them with a one-time reorder, as a separate final commit in the same PR. The refactor commit stays byte-identical, so its proof still holds, and the three advertised enums then follow the table's order with no permanent pin lists. JSON Schema `enum` order carries no meaning; the catalog digests change once, and the PR's compatibility section will say so. 2. **Reader dispatch lists:** yes, in a later step, but not on the domain rows, since `src/domain` must not depend on artifact readers. One reader registry in `src/artifacts`, keyed by the domain's archive-format type with `satisfies Record<…>`, would replace the eight lists, so a missing reader fails to compile and each layer keeps one owner. The IDA allowlist question in the issue is answered by #7485, which went out separately.
Author
Owner

@Entrpi commented on GitHub (Oct 30, 2026):

#8054 landed the reader-registry step from my second answer above, for artifact formats: one FormatDescriptor per ArtifactFormatId, and a missing id fails typecheck.

Option 1 is the same step on the domain side: one row per target format in src/domain/targetFormats.ts, and the eight target vocabularies derive from it. Would you like that next? If so, I will rebuild the prototype on current main in #8054's pattern (Record<TargetFormat, Descriptor>, where a missing format fails typecheck) and open it as a PR when you are ready for it. Option 2, architecture families, would follow the same shape.

<!-- gh-comment-id:6513426427 --> @Entrpi commented on GitHub (Oct 30, 2026): #8054 landed the reader-registry step from my second answer above, for artifact formats: one `FormatDescriptor` per `ArtifactFormatId`, and a missing id fails typecheck. Option 1 is the same step on the domain side: one row per target format in `src/domain/targetFormats.ts`, and the eight target vocabularies derive from it. Would you like that next? If so, I will rebuild the prototype on current `main` in #8054's pattern (`Record<TargetFormat, Descriptor>`, where a missing format fails typecheck) and open it as a PR when you are ready for it. Option 2, architecture families, would follow the same shape.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#4461
No description provided.