Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
f1cd97d
feat(tables): capture native write facts
swackhamer Sep 13, 2026
ec6214c
fix(tables): preserve write source indirection
swackhamer Sep 13, 2026
468a114
fix(tables): close native writer autoload grammar
swackhamer Sep 13, 2026
2c9519c
tools: add seeded version rehearsal planning
swackhamer Sep 13, 2026
6cb5d16
tools: bind rehearsal plans to matching native versions
swackhamer Sep 13, 2026
21eed54
tools: verify deterministic rehearsal plans
swackhamer Sep 13, 2026
c4e3bb5
docs: adopt newer native behavior on ExifTool upgrades
swackhamer Sep 13, 2026
cb18fb9
Record native dump identity after writer fact capture
swackhamer Sep 13, 2026
b6d364c
feat(tables): stage inactive write descriptors
swackhamer Sep 13, 2026
10c8956
fix(tables): bind inactive write candidate source facts
swackhamer Sep 13, 2026
059f56d
Add inactive scoped TIFF entry editing primitive
swackhamer Sep 13, 2026
abaae4b
tools: capture rehearsal release identities
swackhamer Sep 13, 2026
b5bef0b
tools: accept GitHub repository-id page links
swackhamer Sep 13, 2026
cd08dcf
tools: bind rehearsal archive resolution to capture
swackhamer Sep 13, 2026
8f31940
tools: constrain rehearsal catalog page origins
swackhamer Sep 13, 2026
3131ee7
tools: require contiguous rehearsal catalog pages
swackhamer Sep 13, 2026
4c584dd
tools: reject ambiguous catalog next links
swackhamer Sep 13, 2026
1643250
Record source candidates and version capture with execution gaps
swackhamer Sep 13, 2026
a80452d
docs: record validated foundation and first selected release sources
swackhamer Sep 13, 2026
66f2837
fix(tables): preserve writer bindings and source-distinct rehearsals
swackhamer Sep 13, 2026
149387d
docs: record foundation review fixes and remaining upgrade proof
swackhamer Sep 13, 2026
675a736
ci: allow complete native table verification within a bounded job
swackhamer Sep 14, 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
14 changes: 7 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -442,14 +442,14 @@ jobs:
# throwaway harness to execute the committed Start/Base forms.
verify-tables:
name: Verify Generated Tables
# 2x on purpose: this is a tarball fetch plus a perl/python pass over one
# file, ~30s and entirely I/O-bound. The sizing measurements above apply
# to compile-bound jobs and buy nothing here -- 2x is for the Warp queue
# (seconds, vs minutes on the GitHub-hosted pool), not for the cores.
# This job now verifies generated artifacts and runs the complete native
# mutation/replay suite. Keep the existing runner size; allow the serial
# Perl/Python work to finish instead of treating it as a short I/O check.
runs-on: warp-ubuntu-latest-x64-2x
# Native source replay adds a measured 399-second local suite to the
# previous six-minute verification job. Keep room for cold hosted runs.
timeout-minutes: 20
# PR #761 at 149387d2 used 5m47s for setup/tier verification, then hit the
# former 20m job cap during native inventory mutations (679 tests reached).
# No check is removed; retain a finite bound with room for the full suite.
timeout-minutes: 35
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# The release comes from .exiftool-version, the repo-wide pin. This job
Expand Down
18 changes: 14 additions & 4 deletions docs/AUTOGENERATION-PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ binaries against the newer oracle; add a separate non-promoting rehearsal that
regenerates both releases and checks each against its own native read/write
behavior. Selection or successful generation alone is not conformance.

The selected newer ExifTool is the authority after upgrading. Its parsing bug
fixes, added/removed/renamed tags, type changes, formatting and write semantics
must replace older behavior. Keep three comparisons: old OxiDex versus old
native, new OxiDex versus new native, and the native old-to-new delta. A change
in native output is an expected upstream change when the new generated build
matches it. Cross-version output equality is not required. A new unsupported
rule is a visible gap requiring shared compiler/runtime work; silently using
the old tag rule is not an acceptable upgrade.

Once that runner passes its own tests, exercise a randomly selected distinct
release pair after three relevant merged batches or one week, whichever comes
first. The existing hourly continuation records this cadence without launching
Expand All @@ -114,10 +123,11 @@ been established.
| --- | --- | --- |
| Shared table compiler and reader | Already exist; some families use them | We have a foundation to extend instead of building a new interpreter for every camera brand. |
| Sony focus-table pilot | Merged in PR #746 at `04eaf6e1`, including removal of 17 duplicate entries. Final CI is green at `a1626cb6`; the 4,238-file pair records ten raw-ID fixes and no other per-file changes. | The shared route now replaces the duplicate Sony producer. Remaining source-inventory work is broader than this pilot. |
| Shared binary strings | Merged in PR #747 at `8f0fdaf4`. It preserves raw bytes in saved state, distinguishes a one-byte default from a remainder string, and carries the bounded CameraInfo repair. | This is a shared capability, not a Canon migration. CameraInfo remains a legacy text-domain adapter, and no Canon manual reader has been removed. The prior full-pair supervisor-status limitation remains recorded. |
| Shared binary strings | Merged in PR #747 at `8f0fdaf4`. It preserves raw bytes in saved state, distinguishes a one-byte default from a remainder string, and carries the bounded CameraInfo repair. | This is a shared capability, not a Canon migration. CameraInfo remains a legacy text-domain adapter, and that batch removed no Canon manual reader. The subsequent AFInfo2/AFInfo3 retirement is listed separately. The prior full-pair supervisor-status limitation remains recorded. |
| Keyed-directory schema and compiler | Merged in PR #748 at `ebbe1ece`; all final hosted checks passed at `a422e8de`. | Native parent facts and expression declarations are checked. Shared reporting policy merged in #750; the inactive reader merged in #752 at `634e5616`. No production route is active. |
| Shared word-directory processor | Merged in PR #754 at `1138a880`; nine tables, 132 rows, 698 Python tests and all five hosted jobs pass. | Four of five unsupported child processors now have generated descriptors. Canon production routing and manual-reader retirement remain unfinished. |
| Shared serial processor | Foundation merged in #757; #759 at `8887e5d9` expands the eight-table total to 122 emitted alternatives and 10 omissions, with all five hosted checks passing. Canon AFInfo 14/14 and AFInfo2 16/16 are generated and natively replayed. | Real AudioV4 is a validated production caller. Canon's next delivery is complete parent routing and manual AFInfo2 reader retirement; definition readiness alone does not count as that migration. |
| Shared word-directory processor | Merged in PR #754 at `1138a880`; nine tables, 132 rows, 698 Python tests and all five hosted jobs pass. | Four of five unsupported child processors now have generated descriptors. The separate Canon AFInfo2/AFInfo3 serial migration merged in #760; other word-directory callers remain separate work. |
| Shared serial processor | Foundation merged in #757; #759 at `8887e5d9` expands the eight-table total to 122 emitted alternatives and 10 omissions, with all five hosted checks passing. Canon AFInfo 14/14 and AFInfo2 16/16 are generated and natively replayed. | Real AudioV4 is a validated production caller. Canon AFInfo2/AFInfo3 now uses the generated route after #760. Old AFInfo geometry and CanonRaw omissions remain unfinished. |
| Canon AFInfo2/AFInfo3 retirement | Merged in #760 at `4a3eb26c`; all five required hosted checks passed on `2630ded8`. One shared manual arm, eight offsets, two parent IDs and a 20-value enum removed. | Exact native and bounded/full corpus evidence passes. A supported native name change reaches output through regeneration. This does not activate generated writing or establish a new project-wide percentage. |
| Real AudioV4 retirement | Merged in #758 at `19cb7650`; one manual reader and its 31-slot sequence removed. Full corpus: one Copyright correction, 4,237 other files unchanged. All five hosted checks pass. | Supported source-name changes reach actual output after regeneration with no tag-specific Python/Rust edit. Native occurrence groups, warning output and V3/V5 remain explicit residuals. |
| Recorded source inventory | Merged in PR #749 at `18a8ef17`; all final hosted checks passed at `72e8e664`. The report accounts for 1,512 table identities and retains 119 tables with no named rows. | This establishes the captured source population. Classifying which rules are generated, manual, unsupported or unclassified remains open; source shape is not automation. |
| Sony plain generator recovery | PR #745 merged; six tables and 193 rows reproduced | These tables can be rebuilt. This alone does not prove that their behavior is fully automatic. |
Expand All @@ -139,7 +149,7 @@ order and independent native validation.
| **2. Prove one complete migration.** | Move Sony's 17-entry focus-point table, `Tag202a`, through the shared machinery. Reuse the existing ability to save a value and evaluate conditions on it; extend it for binary tables. Preserve native selection rules and list any remaining parent-routing work. | All 17 entries and their conditions are accounted for. Real-file and synthetic boundary comparisons agree with pinned ExifTool. Change a name, enum, offset and supported new row in a copied native source: regeneration must reflect each change without a new handwritten tag rule. Stale output must fail verification. |
| **3. Remove what the pilot replaces.** | Switch the validated family to the shared path, then remove its duplicate custom declarations and handling. Preserve shared file-reading/decryption mechanisms and explicitly list any remaining tag-specific routing or helper rules. | A merged change identifies the exact manual rules removed, shows the shared path actually executed, and has zero unexplained per-file regressions. Keeping the old path as the real producer does not pass this step. |
| **4. Expand by shared capability.** | Choose the next unsupported behavior that serves several families. Candidates include saved-value effects, suppression rules, lookup conversions and verified handling of encrypted blocks. Generate other families through the same machinery; use one difficult neighboring family to test that the design generalizes. | Each batch lists the native families unlocked, manual rules retired, remaining unsupported rules, actual output gain and validation scope. Add no new vendor-specific copy of an already supported expression. The first additional family must reuse the new capability without adding another interpreter. |
| **5. Prove an upgrade needs less intervention.** | Run the existing isolated upgrade tool against another pinned release. Record every manual edit and its cause. Turn repeated causes into shared capabilities, then rerun. | Supported native changes regenerate with zero tag-specific Python/Rust edits. Unknown semantics fail visibly and preserve working output. Report elapsed time, build time, manual interventions and corpus changes. A failed or unexercised change stays open. |
| **5. Prove an upgrade needs less intervention.** | Run the existing isolated upgrade tool against another pinned release. Record every manual edit and its cause. Turn repeated causes into shared capabilities, then rerun. | Supported native changes regenerate with zero tag-specific Python/Rust edits. Unknown new semantics refuse promotion and remain a visible gap; they must not silently retain old rules in a new-version build. Report elapsed time, build time, manual interventions and corpus changes. A failed or unexercised change stays open. |
| **6. Close the full remaining inventory.** | Repeat the capability/migration/retirement cycle until no native rule in scope depends on manual tag knowledge. Broaden fixtures for unexercised formats and keep testing later release changes. | Zero manually maintained tag-specific rules, zero unclassified rules, and zero required unsupported behaviors remain in scope. All required parity and upgrade checks pass. A corpus percentage alone cannot certify this finish line. |

Step 1 measurement and Step 2 implementation can proceed in parallel. We will
Expand Down
Loading
Loading