[PR #4146] [CLOSED] fix(dmg): classify localized hdiutil verify failures #6086

Closed
opened 2026-10-31 01:11:45 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/4146
Author: @tomigalmarini3398
Created: 10/15/2026
Status: ❌ Closed

Base: main ← Head: fix/dmg-verify-locale


📝 Commits (3)

  • 5dc776c fix(dmg): classify localized hdiutil verify failures
  • 0d110ae fix(dmg): keep ambiguous localized verify refusals unknown
  • 126df8d fix(dmg): own the verify probe descriptor and honor its cancellation

📊 Changes

3 files changed (+400 additions, -37 deletions)

View changed files

📝 src/artifacts/NativeDmgArtifactReader.ts (+168 -28)
📝 tests/boundary/providers/native/nativeDmgArtifactReader.test.ts (+160 -9)
➕ tests/boundary/providers/native/nativeDmgProbeCleanup.test.ts (+72 -0)

📄 Description

Summary

On macOS systems whose preferred language is not English, every failed DMG
verification is reported as unavailable, so callers cannot tell an
unreadable target or a checksum mismatch from anything else. This change keeps
the existing English classification and adds a locale-independent fallback for
the causes that untranslated hdiutil output can establish, while keeping the
ambiguous cases unknown.

No issue is linked: the failure was found by running the test suite on a macOS
system set to Spanish (AppleLanguages = es-419).

Problem and expected behavior

hdiutil follows AppleLanguages and localizes the trailing failure reason.
NativeDmgArtifactReader classifies verify failures only by matching that
reason against English (and en-GB/en-AU) strings, so localized output always
falls through to unavailable.

Smallest trigger, on a system with AppleLanguages = es-419:

$ hdiutil verify missing.dmg
hdiutil: verify: unable to recognize "missing.dmg" as a disk image. (No existe este archivo o directorio)
hdiutil: verify failed - No existe este archivo o directorio

Expected io; observed unavailable. Likewise an unreadable target (expected
io) and a corrupted UDRO image (expected integrity, output ends in
verify failed - suma no válida) are reported as unavailable. The real-hdiutil tests also asserted English
diagnostics, so they fail on any non-English system.

Change and scope

hdiutil localizes the reason but not its own status lines. When the reason is
not a known English diagnostic, classification now falls back to them:

  • hdiutil: verify: checksum of "…" is INVALID → integrity.
  • hdiutil: verify: unable to recognize "…" as a disk image. → this line is
    emitted for malformed, unreadable and transiently busy targets alike, and only
    the localized reason distinguishes them. #verify probes the target with the
    existing nonblocking openRegularFile helper (following symlinks, as
    hdiutil does, and honoring cancellation): an open failure establishes io.
    Otherwise the cause stays unavailable, and the refusal is retried like the
    explicit transient diagnostic, so a briefly busy image on a non-English host
    still attaches. Directories and other non-regular files also stay unknown,
    since hdiutil can read some image formats from them.
  • Neither line → unavailable, as before.

Known English diagnostics, including the transient
Resource temporarily unavailable that drives the verify retry, are classified
exactly as before and never reach the fallback.

Not included: on a non-English system a readable non-image is still reported as
unavailable (after the bounded retry, about 750 ms), not format. Its
localized reason cannot be told apart from a transient refusal without matching
translated text.

Contribution scope: not applicable — an ordinary fix within the existing DMG
reader boundary.

Contract and boundary impact

  • Semantic owner and earliest changed stage: src/artifacts/NativeDmgArtifactReader.ts, hdiutil verify failure classification.
  • Contribution scope fit and linked maintainer decision: ordinary fix within existing boundaries; not applicable.
  • CLI and MCP/tool-catalog contract: none; only the reported ArtifactReaderFailure.reason changes, and only on non-English systems.
  • Provider, bridge, target-format, or platform compatibility: macOS DMG reading on non-English systems now reports io or integrity instead of unavailable where untranslated output establishes it, and retries ambiguous refusals of readable targets. English output is unchanged.
  • Evidence, artifact, provenance, or reconstruction contract: unchanged; failure messages still carry the full captured hdiutil stdout/stderr, and verify attempts remain in provenance.
  • Target selection, authority, upstream behavior, and cleanup details (if applicable): the new read-only, nonblocking open of the caller-selected target (openRegularFile) happens only after hdiutil verify has already failed with an ambiguous refusal, and the handle is closed immediately.
  • Generated metadata (docs/public/product-catalog.json), package, or installation impact: none.

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

Executed on macOS 26.3.1 (arm64), AppleLanguages = es-419, Node 24.18.0.

  • Tests added or updated:
    • New native DMG localized verification diagnostics suite (fake host) using hdiutil output captured under es-419: checksum mismatch → integrity; unrecognized readable target (malformed or transiently busy reason) → unavailable after three attempts; a localized transient refusal that clears → attaches; unrecognized missing target → io without retry; target replaced by a named pipe → unavailable without blocking; localized failure with no status line → unavailable.
    • The three real-hdiutil tests in native DMG real verification diagnostics asserted English diagnostics (No such file or directory, Permission denied, calculated CRC32, verify failed - invalid checksum), so they could not pass on a non-English system even with a correct classifier. They now assert the untranslated status lines, and the malformed-image test expects format only when hdiutil's output is English.
  • Base reproduction: on 1579b6865, the three real-hdiutil tests fail on this system with expected 'unavailable' to be 'format', … 'io', and … 'integrity'.
  • Review follow-up: against the first commit's source (5dc776cfe), the four new retry/named-pipe tests fail; the named-pipe test times out after 10 s because the previous blocking open(path, "r") waits for a writer.
  • User-visible CLI/MCP output (if applicable): the failure reason in DMG read errors on non-English systems.
  • Remaining proof gaps: not run on an English-language system after the change (English paths are covered by the existing fake-host tests, which pass); localized transient refusal not reproduced.

For evidence-bearing changes:

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

  • npx vitest run tests/boundary/providers/native/nativeDmgArtifactReader.test.ts — 46 passed.
  • npx vitest run tests/boundary/providers/native/ tests/boundary/artifacts — 32 files, 336 tests passed.
  • npm run verify:module-boundaries — passed.
  • npx tsc --noEmit — passed.
  • npx oxfmt --check on both changed files — passed.
  • npx oxlint on both changed files — one max-lines warning on NativeDmgArtifactReader.ts, which already exists on the base revision; no new warnings.
  • Pre-commit hook (lint-staged: oxfmt, oxlint --fix) — passed with no changes.
  • npm run check:fast (pre-push hook: repository-wide typecheck and lint) — passed.
  • Full npm run check and the full test suite were not run on the final commit.

Compatibility, safety, and release

  • Breaking changes or migration steps: none.
  • Real Hopper/Ghidra, browser, or OS coverage: real hdiutil on macOS 26.3.1 with Spanish (es-419); no Hopper/Ghidra involvement.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: adds one read-only, nonblocking open/close of the caller-selected DMG path after an ambiguous failed verify; no writes, no new processes.

Author readiness

Human owner: @tomigalmarini3398

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/4146 **Author:** [@tomigalmarini3398](https://github.com/tomigalmarini3398) **Created:** 10/15/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/dmg-verify-locale` --- ### 📝 Commits (3) - [`5dc776c`](https://github.com/morluto/rea/commit/5dc776cfe73bc3eda238810832932641adc1b1e6) fix(dmg): classify localized hdiutil verify failures - [`0d110ae`](https://github.com/morluto/rea/commit/0d110ae6f2d6d7d9a3630dec14b7ddc44d085675) fix(dmg): keep ambiguous localized verify refusals unknown - [`126df8d`](https://github.com/morluto/rea/commit/126df8d704ebe4a962c87bb67f2fa336f3d3b4f5) fix(dmg): own the verify probe descriptor and honor its cancellation ### 📊 Changes **3 files changed** (+400 additions, -37 deletions) <details> <summary>View changed files</summary> 📝 `src/artifacts/NativeDmgArtifactReader.ts` (+168 -28) 📝 `tests/boundary/providers/native/nativeDmgArtifactReader.test.ts` (+160 -9) ➕ `tests/boundary/providers/native/nativeDmgProbeCleanup.test.ts` (+72 -0) </details> ### 📄 Description ## Summary On macOS systems whose preferred language is not English, every failed DMG verification is reported as `unavailable`, so callers cannot tell an unreadable target or a checksum mismatch from anything else. This change keeps the existing English classification and adds a locale-independent fallback for the causes that untranslated `hdiutil` output can establish, while keeping the ambiguous cases unknown. No issue is linked: the failure was found by running the test suite on a macOS system set to Spanish (`AppleLanguages` = `es-419`). ## Problem and expected behavior `hdiutil` follows `AppleLanguages` and localizes the trailing failure reason. `NativeDmgArtifactReader` classifies `verify` failures only by matching that reason against English (and en-GB/en-AU) strings, so localized output always falls through to `unavailable`. Smallest trigger, on a system with `AppleLanguages` = `es-419`: ```text $ hdiutil verify missing.dmg hdiutil: verify: unable to recognize "missing.dmg" as a disk image. (No existe este archivo o directorio) hdiutil: verify failed - No existe este archivo o directorio ``` Expected `io`; observed `unavailable`. Likewise an unreadable target (expected `io`) and a corrupted UDRO image (expected `integrity`, output ends in `verify failed - suma no válida`) are reported as `unavailable`. The real-`hdiutil` tests also asserted English diagnostics, so they fail on any non-English system. ## Change and scope `hdiutil` localizes the reason but not its own status lines. When the reason is not a known English diagnostic, classification now falls back to them: - `hdiutil: verify: checksum of "…" is INVALID` → `integrity`. - `hdiutil: verify: unable to recognize "…" as a disk image.` → this line is emitted for malformed, unreadable and transiently busy targets alike, and only the localized reason distinguishes them. `#verify` probes the target with the existing nonblocking `openRegularFile` helper (following symlinks, as `hdiutil` does, and honoring cancellation): an open failure establishes `io`. Otherwise the cause stays `unavailable`, and the refusal is retried like the explicit transient diagnostic, so a briefly busy image on a non-English host still attaches. Directories and other non-regular files also stay unknown, since `hdiutil` can read some image formats from them. - Neither line → `unavailable`, as before. Known English diagnostics, including the transient `Resource temporarily unavailable` that drives the verify retry, are classified exactly as before and never reach the fallback. Not included: on a non-English system a readable non-image is still reported as `unavailable` (after the bounded retry, about 750 ms), not `format`. Its localized reason cannot be told apart from a transient refusal without matching translated text. Contribution scope: not applicable — an ordinary fix within the existing DMG reader boundary. ## Contract and boundary impact - Semantic owner and earliest changed stage: `src/artifacts/NativeDmgArtifactReader.ts`, `hdiutil verify` failure classification. - Contribution scope fit and linked maintainer decision: ordinary fix within existing boundaries; not applicable. - CLI and MCP/tool-catalog contract: none; only the reported `ArtifactReaderFailure.reason` changes, and only on non-English systems. - Provider, bridge, target-format, or platform compatibility: macOS DMG reading on non-English systems now reports `io` or `integrity` instead of `unavailable` where untranslated output establishes it, and retries ambiguous refusals of readable targets. English output is unchanged. - Evidence, artifact, provenance, or reconstruction contract: unchanged; failure messages still carry the full captured `hdiutil` stdout/stderr, and verify attempts remain in provenance. - Target selection, authority, upstream behavior, and cleanup details (if applicable): the new read-only, nonblocking open of the caller-selected target (`openRegularFile`) happens only after `hdiutil verify` has already failed with an ambiguous refusal, and the handle is closed immediately. - Generated metadata (`docs/public/product-catalog.json`), package, or installation impact: none. Expected effects: - [x] Read existing files or captured data. - [x] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage Executed on macOS 26.3.1 (arm64), `AppleLanguages` = `es-419`, Node 24.18.0. - Tests added or updated: - New `native DMG localized verification diagnostics` suite (fake host) using `hdiutil` output captured under `es-419`: checksum mismatch → `integrity`; unrecognized readable target (malformed or transiently busy reason) → `unavailable` after three attempts; a localized transient refusal that clears → attaches; unrecognized missing target → `io` without retry; target replaced by a named pipe → `unavailable` without blocking; localized failure with no status line → `unavailable`. - The three real-`hdiutil` tests in `native DMG real verification diagnostics` asserted English diagnostics (`No such file or directory`, `Permission denied`, `calculated CRC32`, `verify failed - invalid checksum`), so they could not pass on a non-English system even with a correct classifier. They now assert the untranslated status lines, and the malformed-image test expects `format` only when `hdiutil`'s output is English. - Base reproduction: on `1579b6865`, the three real-`hdiutil` tests fail on this system with `expected 'unavailable' to be 'format'`, `… 'io'`, and `… 'integrity'`. - Review follow-up: against the first commit's source (`5dc776cfe`), the four new retry/named-pipe tests fail; the named-pipe test times out after 10 s because the previous blocking `open(path, "r")` waits for a writer. - User-visible CLI/MCP output (if applicable): the failure reason in DMG read errors on non-English systems. - Remaining proof gaps: not run on an English-language system after the change (English paths are covered by the existing fake-host tests, which pass); localized transient refusal not reproduced. For evidence-bearing changes: - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed - `npx vitest run tests/boundary/providers/native/nativeDmgArtifactReader.test.ts` — 46 passed. - `npx vitest run tests/boundary/providers/native/ tests/boundary/artifacts` — 32 files, 336 tests passed. - `npm run verify:module-boundaries` — passed. - `npx tsc --noEmit` — passed. - `npx oxfmt --check` on both changed files — passed. - `npx oxlint` on both changed files — one `max-lines` warning on `NativeDmgArtifactReader.ts`, which already exists on the base revision; no new warnings. - Pre-commit hook (`lint-staged`: oxfmt, oxlint --fix) — passed with no changes. - `npm run check:fast` (pre-push hook: repository-wide typecheck and lint) — passed. - Full `npm run check` and the full test suite were not run on the final commit. ## Compatibility, safety, and release - Breaking changes or migration steps: none. - Real Hopper/Ghidra, browser, or OS coverage: real `hdiutil` on macOS 26.3.1 with Spanish (es-419); no Hopper/Ghidra involvement. - Package or release metadata impact: none. - Security, privacy, process, or containment review: adds one read-only, nonblocking `open`/`close` of the caller-selected DMG path after an ambiguous failed verify; no writes, no new processes. ## Author readiness Human owner: @tomigalmarini3398 - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:11:45 +00:00
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#6086
No description provided.