Preserve typed failed attempts through root admission, hashing, inventory,
nested JavaScript readers and extraction rollback. Remove the intermediate
cause/resource records that discarded canonical cleanup capabilities.
Resolve original provider errors after confirmed release while preserving
primary failures, partial observations and invalidated-handle uncertainty.
Fixes#4928
Return the canonical owner and lease from failed releases. Compose initial
cleanup failures from explicit operation outcomes and failed attempts, and
carry their authority through the shared artifact failure contract.
Keep independent unknown cleanup unresolved. Distinguish operation failures
from completed work whose close rejected. Let the scope own current child
resource labels without replacing its canonical retry lease.
Cover mixed owners, partial release, cancellation provenance, typed close
rejections and independent unknown cleanup through the producing boundaries.
Recognize complete CFPropertyList literals at the XML owner and retain
canonical NaN and signed infinity identity as typed scalars. Keep scalar
wrappers distinct from lookalike dictionaries, share limitation text and
document alias normalization. Incomplete markup retains its existing
compatibility fallback and limitation. Bound token matching before case
normalization using the accepted grammar.
Adapted from PR #4908. Fixes#4906.
Validation: public CLI/MCP regression baseline 2 failed, 4 passed.
Final focused validation 430 passed across 25 files, including controlled
entitlement response coverage in the following commit. Real macOS plutil
CLI, check:fast, docs:check and discovery passed. Binary value identity
remains tracked in #4919; malformed literal policy remains #4852.
Co-authored-by: Mert Kaya <47145541+mertkayacs@users.noreply.github.com>
Plist inspection reported a serialized -0.0 real as the JSON number 0.
- The shared plist projection reports it as a typed real scalar whose value is the string -0, counted in a limitation for keyed archives and inspect_plist.
- The plutil JSON path applies the same value when it decodes -0.
- The XML decoder no longer returns -0 for a mixed-content integer.
Fixes#4834
Share the in-flight release for one exact owner, preserve failed attempts for retry, and notify dependent errors only after confirmed completion.
Validation: concurrency control fails on3fcba0796 with two cleanup attempts; isolated foundation passes38 selected lease/scope/resource tests. Authored lifecycle controls, no native provider qualification.
Pair each retry owner with its exact lease and reuse that lease for release and recovery. Remove variant-based lease inference.
Validation: isolated scope foundation passed 23 selected tests; final candidate passed the broader focused suite and static checks. Real-provider behavior was not qualified.
Use the canonical artifact cancellation checkpoint for enumeration, open and extraction instead of dropping the caller reason in a ZIP-specific helper.
Validation: both new ZIP reason controls fail on the unchanged baseline and pass on the candidate; the focused seven-file run passes 65 tests. Native Windows/Linux were not run.
Share exact command/helper cleanup adoption across Java probes. Preserve complete live resource labels and explicit unknowns through inspection leases, and retain unresolved ownership when a cleanup capability is unavailable.
Validation: focused cleanup, provider/doctor and Kuna consumer checks; shared Ghidra lifecycle and public doctor regressions. Native Windows/Linux provider behavior remains unverified.
Replace raw descriptor and workspace bookkeeping with artifact file ownership, canonical chunk reads, private roots and cleanup leases. Retain failed owners, fence replacement acquisition, release successful peers once, and preserve completed Evidence and physical failures through final cleanup and cancellation.
Use the shared directory reader and enforce the examined-entry budget before special-file omission. Keep command and artifact retry ownership separate by exact lease identity; remove superseded reads, implicit traversal and suppressing closes.
Validation: 163 focused tests in 20 files, build, typecheck/lint, docs and discovery passed. Six public controls fail on clean baseline 11bcf4425. Tiny FIFO, descriptor denial/retry, late allocation and mixed outcomes are controlled fixtures. Twenty-four completed CLI/stdio MCP comparisons return byte-identical replies; no speedup claim. Actual Apktool/JVM, natural OS denial and native Windows remain unverified; heavy stress/profiling stayed stopped.
Closes#4812
Interpret the validated, depth-bounded DOM directly. Collect source number
facts during the same traversal and share them with keyed archives, Interface
Builder and native plist projections. Remove the second XML parse, key aliases,
source-location rewriting and both duplicate XML numeric scanners. Preserve
character references, container/null behavior, safe own-property construction
and prototype omission accounting.
Decode signed hexadecimal integers and combine real text/CDATA. Retain exact
integer identity when a finite integer exceeds even Number's finite range,
using the shared scalar projector. Keep unsupported mixed integer syntax
conservative and report incomplete metadata.
Adapt @apitoagents's hexadecimal regression and literal-parsing proposal from
PR #3475. Native plutil controls establish the supported hex/real cases and
confirm that the synthetic 401-digit overflow case exceeds native bounds;
retaining accepted input does not claim native-format support.
Validation: 274 focused checks in 30 files pass, one skipped; build,
check:fast and docs:check pass. Built CLI/actual stdio MCP, native plist and
Interface Builder controls cover kinds, references, exact digits and digests.
Eight baseline checks fail; native binary conversion independently verifies
updated CDATA real expectations. 48 tiny completed CLI cost comparisons
preserve ordinary XML/binary and all three native replies byte for byte.
Two read-only reviews clear. No statistical speed claim, heavy profiler,
investigated-target execution or real deep-provider verification.
Fixes#3373Fixes#4042Fixes#4789
Move plist projection into the graph owner and identify generated scalar
wrappers by producer identity through every dictionary/UID consumer. Remove
the intermediate JSON clone that erased those facts. Literal wrapper-shaped
dictionaries remain dictionaries; scalar $top values fail as malformed.
Keep numeric projection after graph interpretation, preserve unknown counts,
and retain binary prototype-key partial facts with an explicit limitation.
Adapt @Jax367's relevant scalar proposal and public regression from PR #4317.
Add scalar-root, literal-root and binary prototype controls. Correct only
the captured Foundation data node expectation and its manifest digest;
original producer bytes and source are unchanged. Unrelated PR changes excluded.
Validation: 175 focused checks across 23 files pass, one skipped; build,
check:fast and docs:check pass. Public CLI and stdio MCP cover both encodings.
Baseline scalar controls fail; 24 tiny completed CLI cost comparisons retain
ordinary full replies and Evidence IDs byte for byte. No statistical speed
claim, heavy profiling, target execution or real deep-provider verification.
Fixes#4295Fixes#4785
Use the shared artifact resource scope for snapshot reads. Preserve completed facts, exact cancellation reasons and descriptor cleanup leases through session and public error projection; keep parent cleanup pending until all retained resources release.
Validation: 22 selected snapshot lifecycle checks and 85 contract, projection and bounded-reader checks; typecheck, lint and runtime builds. Uses small authored Node/socket fixtures, not real Ghidra or investigated target execution.
Refs #4752, #3977
Reject special files without blocking, cap the properties payload at 1 MiB before allocation, and verify descriptor extent and the selected name. Preserve Latin-1 data, selected symlinks, physical filesystem facts, completed observations and exact failed-close ownership.
Reuse the stable bounded reader for profile artifacts and consolidate Ghidra file failure projection. Distinguish missing-at-open from disappearance or read failure, and attribute typed prerequisite failures at the consuming operation.
Validation: 384 focused tests across 14 files, 42 seed/extension controls, 32 final metadata/profile/CLI controls, check:fast and docs:check. Controlled macOS file/process fixtures; no real Ghidra/JVM or Windows/Linux lifecycle verification.
Bounded FIFO reproduction: baseline direct and public doctor required external cleanup around 2.2s; candidate returned independently around 0.4/0.57s, all fixture groups verified empty. Warm normal doctor baseline/candidate: elapsed 1.211/1.230s, CPU 1.239/1.247s, sampled family RSS 524/524MB, reply tokens 3116/3116. No performance improvement claimed; true cold and whole-agent costs unmeasured.
Refs #4672
Return a closeable owner before prerequisite work begins. Share creation across independent callers, join the final departure and late handoffs, retain exact failed resource owners, and gate operation dispatch again after acquisition.
Keep reuse admission separate from native health. Move shared provider ownership below application workflows and consolidate failure attribution; remove the superseded lazy client.
Validation: 34 focused owner, lazy, composite and session controls; check:fast. Compiled baseline/candidate recording-provider workflow reproduces then fences dispatch after close. No native provider claim.
Refs #4561, #4667
Record cancellation at file checkpoints and before owner handoff. Keep physical hash failures, exact reasons, completed facts and failed-close owners distinct through artifact and provider projections and cleanup retries.
Refs #4598. Validated with 566 passing affected tests and 22 platform skips; final Kuna cleanup reason rerun passed 43 tests. No Android device or real JADX/Kuna execution claimed.
Refs #4495.
Normalize dylib file access once at the admitted descriptor boundary. Preserve full file identity, physical read outcomes, cancellation provenance and cleanup retry through artifact analysis.
Refs #4458, #4483.
Own admitted descriptors through final close, retain exact failed owners, and preserve physical read failures and cancellation reasons. Track stream coverage independently from delivered bytes and share the boundary across archive, Mach-O, hashing, and output readback consumers.
* fix(native): report PE input byte budgets as file-size limits
PeResourcesProvider translated every ArtifactReaderFailure with reason
"limit" into a memory resource constraint, so an image above the
caller's max_file_bytes was reported as a memory problem with memory
remediation advice. The bound that was exceeded is the input file's
byte length, which the caller raises with a flag.
Record the constrained bound on the failure the way ElectronFuseReader
already does, declare it at the reader's two input-byte refusals and at
the parser's metadata and entry budgets, and report that bound instead
of assuming memory. Readers that do not declare a boundary are
unchanged.
Fixes#4192
* fix(native): keep caller-selected PE budget refusals actionable
Address review findings on the budget classification:
- withCleanup now forwards the constrained bound, so a file that grows past
its byte limit while its handle also fails to close is still reported as
a file-size refusal rather than a memory one.
- Both caller-selected bounds carry their own remediation, pointing at
max_file_bytes and max_entries instead of the file-size fallback's worker
write-limit advice.
- AnalysisResourceConstraintError can declare that retrying cannot succeed.
The entry budget is deterministic for the same file and limit, so it no
longer inherits admission capacity's retryable behaviour.
The projection falls back to the previous resource-kind rule when a caller
does not declare retryability, so other capacity refusals are unchanged.
* fix(native): preserve budget retryability and name the schema ceiling
Address the remaining review findings on the budget classification:
- Failure redaction and the caller-copy path rebuilt resource constraint
errors without forwarding retryable, so a deterministic capacity refusal
projected as retryable again and automated callers could loop on it.
Both constructors now forward the declared boolean.
- Both remediations recommended raising a bound the caller had already
set to the schema maximum. The maxima are now named constants shared
with the schema, and the remediation names the operation's hard ceiling
when the caller is already at it.
* fix(application): retain completed evidence through cancellation
Validate completed provider reports before classifying cancellation and preserve Evidence and captured diagnostics. Share MCP recording and delivery across custom observation handlers. Add source-owned completion and public SDK recording controls. Refs #3923, #3927, #4261.
* fix(wasm): retain final observations through cancellation
Keep completed Evidence after finalization and through CLI/MCP delivery. Preserve output and cleanup failure precedence. Refs #4254.
* fix(browser): retain final observations and forward cancellation
Classify final CDP detach and completed scenario cleanup at the provider boundary. Translate completed partials into canonical Evidence for MCP recording, and forward CLI cancellation to passive Electron tools. Refs #4255, #4256, #4257.
* fix(ghidra): isolate cancellation of shared startup waiters
Keep startup group-owned while each caller has an independent abortable wait. Await final-owner cleanup and preserve cleanup facts before retrying. Reuse the shared abortable promise helper. Refs #3983.
* fix(mcp): keep shutdown registrations until cleanup succeeds
Retain repeated event requests while unresolved owners need cleanup, and unregister only after success. Verify coalescing and failed-owner retry. Refs #4253.
* fix(adb): own transfer snapshots and stage screen publication
Bind transfer digests to the exact private input bytes and preserve caller APK names. Retain failed descriptors and private-root owners with typed cleanup evidence; publish captures exclusively after the cancellation cutoff. Refs #4251, #4252.
* fix(verification): report ADB cleanup failures
Always close after attempted verification and keep unexpected primary failures and cleanup details visible. Exercise the production script with controlled imports, including null and undefined throws. Refs #4260.
* fix(runner): stop owned Windows commands on cancellation
Use the retained ChildProcess handle for IPC cancellation and parent disconnection. Keep the SQLite lock until observed child close, and include native Windows regressions in the curated CI lane. Native Windows results remain pending. Refs #4258.
* fix(website): canonicalize link containment boundaries
Compare resolved targets with resolved repository and site roots. Accept directory aliases while preserving escape checks and keep fixtures within their temporary owner. Refs #4264.
* docs(testing): cover completion races and cleanup retry
Clarify validation-before-cancellation, independent startup waiter controls, producer and adapter coverage, and repeated shutdown events.
* fix(filesystem): retain file owners and completed reads after close failure
* fix(session): report retained snapshot staging in cleanup status
Fixes#4277. Include both snapshot and profile file-resource scopes in the owning status fact, preserving publication receipts and cleanup retry.
* docs(mcp): clarify recovery of raw partial observations
Document the observed SDK cancellation boundary and the open design decision in #4276 without promoting raw errors to Evidence.
* fix(kuna): own the complete installation inspection lifetime
* test(kuna): cover session cleanup of shared cache resources
* fix(hopper): isolate publisher operation resource admission
* fix(hopper): preserve launcher cleanup failure classification
* fix(adb): retain ordered cleanup and screen publication outcomes
* fix(runner): retain Windows job ownership through cleanup retries
* docs: clarify inspection admission and ordered cleanup regressions
* fix(ghidra): preserve startup cleanup and request deadlines
* fix(runner): supervise stdin errors and bootstrap native controls
* docs: require queued lifecycle controls to survive admission
* fix(cli): leave cleanup resolution with resource owners
* test(adb): verify owned install snapshots through CLI
* fix(errors): exclude resolved primary cleanup resources
* fix(adb): resolve publication cleanup after its handle closes
* fix(android): resolve JADX hash cleanup after owned close
* refactor(android): share hash failure cause options
* fix(kuna): gate commands on retained descriptor cleanup
* docs: cover cleanup admission and owner-confirmed recovery
* refactor(artifacts): bind cleanup errors to confirmed release
* fix(adb): resolve recovered cleanup at retained owners
* fix(kuna): resolve installation cleanup after owned close
* fix(kuna): gate cache reads on retained hash cleanup
* fix(setup): preserve publisher cleanup admission failures
* fix(android): resolve the reported retirement cleanup error
* test(runner): scope post-spawn fault control to POSIX
* test(adb): cover persistent snapshot owner retirement
* fix(kuna): preserve file outcomes with explicit cleanup ownership
* fix(artifacts): resolve errors through retained cleanup owners
* docs(lifecycle): carry cleanup ownership in typed outcomes
* fix(adb): bind staged screen errors to their cleanup lease
* fix(kuna): bind profile cleanup through a close capability
* fix(artifacts): retain descriptor resources in cleanup errors
* fix(pcap): bind existing errors to snapshot retirement
* fix(windows): load source owner through its file URL
* test(build): copy the command runner helper into fixtures
* fix(mcp): own shared observation providers in the transport
* fix(jadx): resolve every retained cleanup retry error
* fix(kuna): bind retry errors to every retained cleanup owner
* fix(adb): bind admission and shutdown errors to exact cleanup leases
* fix(windows): resolve command paths before native ownership
* test(publisher): assert exact descriptor recovery without release metadata
* docs(lifecycle): require every retry error to follow its owners
* fix(kuna): keep hash cleanup state stable across concurrent retries
* test(windows): exercise surviving descendants with scoped shutdown deadlines
* fix(uninstall): preserve primary read errors through cleanup failure
* test(publisher): assert cleanup Result and exact owner recovery
* test(windows): observe supervisor resources through IPC disconnect
* fix(browser): retain typed cancellation after interrupted actions
* test(publisher): assert ownership phases without retry-count coupling
* fix(lifecycle): preserve abort reasons through shared provider execution
* fix(jadx): preserve execution and late hash cancellation causes
* fix(adb): compose late cancellation with exact cleanup failures
* test(mcp): use the shared budget for session workflows
Preserve duplicate archive occurrences in inventory and reject an ambiguous materialization before acquiring readers or output resources. Keep path collisions distinct from integrity failures.
Refs #4271, #4273
Co-authored-by: Liu Jie <maxazure@gmail.com>
Reuse byte-derived numeric metadata after graph classification so emitted
attributes preserve exact integers without changing UID links or identities.
Reserve metadata and attribute projection within the shared decode budget.
Validated six CLI cases covering XML, binary, collisions, real values and
incomplete metadata, plus decode-budget regressions. A small cold/warm CLI
comparison showed similar costs; it does not establish a speed improvement.
Refs #3876, #3972.
Co-authored-by: hhang <169027046+xu91102@users.noreply.github.com>
Use untranslated checksum status and nonblocking file admission for localized verification failures. Keep ambiguous readable targets unknown and bounded retries intact; retain failed descriptor ownership and cancellation.
Refs: #4146
Co-authored-by: Tomas Galmarini <tomigalmarini@gmail.com>
Reject negative bounded reads before allocation while retaining short-read and exact-EOF behavior. Exercise the corrupted central-directory offset through the public CLI.
Refs #4006, #3953
Co-authored-by: jackie_cqz <88996311+jackie-cqz@users.noreply.github.com>
Preserve original member spellings and central-directory identities while omitting actual root directory markers. Derive entry kind once so Unix symlink facts and size metadata agree; retain traversal and non-directory root rejection.
Verify public inspect/extract workflows for prefixed and root-only archives, distinct duplicate occurrences, and malformed/symlink controls.
Refs #4124
Co-authored-by: Adkid-Zephyr <laufs0310@163.com>
Artifact inventory decided source-map edges from the `.map` path suffix,
so an archive directory such as `main.js.map/` received a maps-source
edge whose parent was the sibling `main.js`, although the same
occurrence was classified as a directory container. Edge construction
now uses the occurrence's own artifact_kind, and the duplicate suffix
rule in relationFor is removed; such directories are contained by their
parent, and real source-map files keep maps-source.
Fixes#3909
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(apple): bound Interface Builder XML plists by shared value depth
The Interface Builder preflight rejected XML archives whose raw element
depth exceeded 128, but the shared plist parser bounds zero-based value
depth at 128; the plist envelope and dictionary keys add elements, not
value depth. Archives whose deepest value sat at depth 127 or 128 were
therefore omitted as over budget although keyed-archive inspection
decodes them. The preflight's duplicate depth rule is removed; the
shared parser's depth limit is mapped to the existing budget omission,
so deeper archives stay explicitly omitted.
Fixes#3949
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(apple): return the decode reservation of a depth-rejected archive
Review follow-up. The removed element-depth preflight rejected an archive
before its plist representation was reserved; the shared depth limit now
rejects it during decoding, after the reservation. A large over-depth
archive therefore kept its share of the aggregate budget and could
starve later valid archives. A document omitted by the budget after
reserving now releases that reservation.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
inspect-asset-catalog selected every bundle entry whose relative path
ended in Assets.car, so an unrelated NotAssets.car directory was listed
as a skipped catalog and, with no real catalog present, failed the
inspection instead of returning the empty inventory; a regular file such
as OldAssets.car would have been sent to assetutil. The selector now
compares the final path component exactly.
Fixes#3914
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix: select caller paths through symlinks and .. as the filesystem does
CLI adapters, binary target resolution, the reverse-engineering service
and the objdump and Rizin command builders made caller-selected paths
absolute with path.resolve, which collapses `link/..` lexically. On
POSIX the filesystem follows `link` first, so these commands inspected,
hashed or launched a different file and returned internally consistent
Evidence for it.
absoluteCallerPath now owns that step: on POSIX it prefixes a relative
path with the working directory and keeps an absolute path as spelled;
on Windows, where `..` resolves lexically, it keeps win32.resolve.
Fixes#3864Fixes#3911Fixes#3912
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: keep firmware, WASM list and output-root paths on the selected file
Review follow-up. The CLI already passed firmware and WASM paths through
absoluteCallerPath, but snapshotFirmware and SafeOutputTree.create
re-resolved them lexically, and the WASM glue and candidate lists still
used resolve, so those inputs could still select a sibling file or
create output beside the intended directory.
absoluteCallerPath now also drops `.` segments and repeated or trailing
separators on POSIX, which never change the named file, so selected
paths such as `./module.wasm` keep matching their glue references
exactly. Every `..` is still left for the filesystem.
SafeOutputTree keeps host path syntax; its platform argument selects only
the Windows name policy.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: keep directory requirements and relative cwd in caller paths
Review follow-up. absoluteCallerPath stripped a trailing `/` or `/.`, so
`file/` selected the regular file instead of failing with ENOTDIR; it
now keeps one trailing separator. A relative cwd option was appended to
the root; it is now made absolute without collapsing `..`. WASM glue
matching resolved local literals lexically, so a module selected through
`link/..` matched only by basename; the adapter now compares both sides
through absoluteCallerPath and still reports each candidate as given.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Replace fixed Linux Hopper release pins with current vendor feed metadata,
complete detached-PGP package verification under the stable publisher primary
key, and authenticated package evidence for offline admission. Share parsed
publisher facts across approved setup, doctor and the pre-execution guard.
Preserve existing ownership, cancellation, private-display and cleanup rules.
Fixes#3577
Normalize empty XDG settings, preserve backups during approved cache repair,
and retain publisher cleanup through cancellation and shutdown. Exercise cold
offline verification without reusing process-local proof state. Serialize
approved cache publication across processes, restore old evidence on failure,
and share the existing lease owner from process without changing its identities.
Validation: 438 focused tests (six platform-related skips), full static/documentation checks, real Ubuntu
24.04 official Hopper 6.6.0 setup/CLI/MCP, offline ordinary-user admission,
launcher mutation rejection, and cold/warm verification measurements. Official
RPM metadata mismatch is tracked separately in #3578 and fails closed.
BREAKING CHANGE: Older Linux Hopper builds admitted by the fixed allowlist
now require retained publisher-signed package evidence or an approved update
to the current public demo. Update explicit HOPPER_LAUNCHER_PATH values when
migrating; the live feed exposes only its current release.
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
plutil writes years past 9999 and negative years in a form the pinned
XML decoder cannot parse, and binary plists can hold dates outside the
JavaScript Date range. The decoder returns an Invalid Date. Its
projection's toISOString() call then threw, so inspect_plist failed the
whole plist as "unreadable_output" with a `rea doctor` remediation.
Keyed archive inspection and Interface Builder decoding rejected the
archive in the same way.
projectPlistValue, the shared projection, now reports such a date as
{ "$plist_type": "date", "iso8601": null } and counts it. inspect_plist,
keyed archive inspection and Interface Builder decoding each add a
counted limitation, as they already do for non-finite reals.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Preserve missing ASAR companion occurrence identity, declared size and unknown content in graph nodes and resolution limitations. Apply URL text semantics once for ESM lookup while preserving literal CommonJS paths and original specifiers. Keep CJS wrapper var bindings and assignment history, recognizing only untouched wrapper redeclarations.
Validation: real ASAR producer workflow and CLI/MCP path/coverage cases; semantic reassignment controls. Context7 Node documentation and direct Node wrapper execution confirm wrapper behavior.
Fixes#3213Fixes#3214Fixes#3223
Related: #3278, #3254
Co-authored-by: Geronimo <varungore1@gmail.com>
Co-authored-by: Paolo Valletta <paovalletta@hotmail.it>
* fix(artifacts): inventory universal slices REA cannot structurally index
inspect_artifact and extract_artifact rejected a valid universal Mach-O
when one slice was outside the structural index, such as XLD's
big-endian PowerPC slice. The whole inventory failed with "Artifact is
invalid or has changed. Get a fresh copy and try again."
When lipo reports every slice's range, the slices are now inventoried
from those ranges with a limitation naming the unsupported structure,
as the reader already does for files without structural facts. When
lipo omits a range, the failure is reported as unavailable support
rather than a corrupt artifact.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(artifacts): validate every FAT slice past an unsupported one
readFatSlices returned at the first unsupported slice, so a later
malformed slice went unchecked: with lipo's ranges now inventoried for
unsupported structure, a malformed little-endian slice after a
big-endian one was accepted while the reverse order was rejected.
Unsupported slices are now remembered and the remaining slices are
still validated, so malformed structure wins in either order.
Adds portable fake-lipo coverage for complete ranges, missing ranges
(unavailable) and malformed slices on both sides of a big-endian slice.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* perf(artifacts): run the asset catalog and Interface Builder bundle walks together
inspect_asset_catalog walked the app bundle for Assets.car files and then
walked it again for the Interface Builder graph that supplies resource
keys. The analyses are independent, so start the Interface Builder one
first and let a catalog failure cancel it and win, as the sequential
order did. Keynote 4.20 s -> 2.89 s with identical output.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(artifacts): hold asset catalog and Interface Builder work open to pin overlap
Keep the Interface Builder stub pending until catalog inspection starts,
and keep catalog inspection pending while asserting an early Interface
Builder failure has not escaped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* perf(artifacts): overlap bundle magic reads while enumerating dylib roots
trace_dylib_resolution opened every file of an app bundle one at a time
to read its Mach-O magic (Keynote: 35,971 files, 23 Mach-O images).
Keep up to eight reads in flight while the directory walk continues,
settling them in walk order so classification and failure precedence
match the sequential scan. Keynote 4.20 s -> 2.78 s.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(artifacts): pin ordered-read failure precedence and cleanup
Extract the overlapped magic-read queue into consumeWithOrderedReads and
test its ordering, concurrency bound, failure precedence, enumeration
close and read settlement with controlled promises.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Include omitted roots, unresolved retained endpoints and serialized NIB omissions in the owning hierarchy status. Reuse that status for summaries and coverage; remove the adapter recomputation and preserve per-document isolation.
Validation: 18 graph and 12 real NIB filesystem/built CLI tests pass.
Based on #3156.
Co-authored-by: Aliciawque <166712943+Aliciawque@users.noreply.github.com>
Normalize path facts once at the owning filesystem boundary, preserve caller spelling and unavailable inventory members, and retain typed read failures. Record exclusion entry kinds so only proven directories can establish descendant symlink targets; omitted legacy kinds stay unknown.
Reviewed fixes include #1969, #2642, #2759, and #2994.
Validation: 26 reference graph source tests passed; prior artifact checks passed 275 tests with one Windows-only skip. Updated compiled import workflows are included in final validation after regeneration.
* fix(artifacts): preserve Mach-O load-command string identity
* fix(process): report no remaining time after a provider deadline fires
Node timers can fire while performance.now() is still a fraction of a
millisecond short of the monotonic deadline. ProviderStartupDeadline then
reported interruption "timeout" and an aborted signal while remainingMs()
returned ceil(0.x) = 1, so polling loops guarded by remainingMs() > 0
(Hopper and Ghidra startup) could run past an elapsed deadline, and the
real-timer test "aborts a bounded wait when its real monotonic deadline
expires" failed intermittently in CI (expected 1 to be 0).
Once the deadline's own timer has classified a timeout, report zero
remaining time. A deterministic regression test fires the timer with the
monotonic clock 0.4 ms short of the deadline.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit dfdaa0ca74)
* fix(ci): isolate Linux Hopper process fixture inventory
* fix(comparison): recheck historical calls-only changes (#2223)
* fix(comparison): preserve incomplete function call evidence
Keep missing, unknown, partial and unresolved call relationships unknown in function comparisons and reconstruction claims. Aggregate IDA caller and callee coverage without overwriting uncertainty.
Validate with 144 focused tests, typecheck/lint, docs checks and test discovery. Real providers were not verified; the full headless IDA session suite requires unavailable Windows native controls.
* fix(comparison): recheck historical calls-only changes
---------
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
* style: format identity comparison and IDA runner
---------
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Lucien <164857476+dakjdakd@users.noreply.github.com>
* fix(artifacts): describe ZIP non-entry coverage accurately
* fix(process): report no remaining time after a provider deadline fires
Node timers can fire while performance.now() is still a fraction of a
millisecond short of the monotonic deadline. ProviderStartupDeadline then
reported interruption "timeout" and an aborted signal while remainingMs()
returned ceil(0.x) = 1, so polling loops guarded by remainingMs() > 0
(Hopper and Ghidra startup) could run past an elapsed deadline, and the
real-timer test "aborts a bounded wait when its real monotonic deadline
expires" failed intermittently in CI (expected 1 to be 0).
Once the deadline's own timer has classified a timeout, report zero
remaining time. A deterministic regression test fires the timer with the
monotonic clock 0.4 ms short of the deadline.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* style: format comparison and IDA sources
---------
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(flutter): name a missing or non-file APK selection
identify_flutter_build and inspect_dart_aot reported a missing path or a
directory as "The APK could not be read as a package: <path>: ENOENT ...",
which blames the package bytes for a selection mistake. Report
"Selected APK does not exist" for ENOENT/ENOTDIR and "Selected APK is not
a regular file" for a non-regular selection, matching the SQLite
inspector's wording. The issue path and invalid_format reason are
unchanged; package format failures keep their existing message.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(filesystem): classify unopenable non-regular selections at admission
A Unix socket cannot be opened at all: open() fails with ENXIO on Linux
and EOPNOTSUPP on macOS (surfaced by libuv as "Unknown system error
-102") before openRegularFile can stat the descriptor, so such a
selection escaped NonRegularFileReadError and the Flutter provider still
blamed the package bytes.
When open fails, classify the path by its own metadata (lstat when
symlinks are rejected, stat otherwise): an existing non-regular file
becomes NonRegularFileReadError. Missing paths, permission failures,
regular files, and the O_NOFOLLOW ELOOP rejection keep their original
errors. The Flutter selection test now covers a real Unix socket.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(filesystem): reclassify only unopenable file-type errors at admission
Checking the path's metadata after any open failure turned EACCES on an
unreadable directory into NonRegularFileReadError, so callers reported
invalid input instead of access_denied. Reclassify only errors that mean
the file type cannot be opened (ENXIO, EOPNOTSUPP, ENOTSUP, matched by
errno because libuv has no name for macOS EOPNOTSUPP 102); permission,
symlink-rejection and resource failures keep their original errors.
Run the Unix socket selection check in its own test, skipped on Windows
where listen() takes named pipes, and keep the missing-path and
directory checks cross-platform.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(filesystem): keep cancellation that arrives during the non-regular probe
A caller abort while the post-open metadata probe ran was replaced by
NonRegularFileReadError, so callers such as parseBinaryTarget reported an
input-format error instead of cancellation. Recheck the signal before
substituting the non-regular classification.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Inventory expands an ASAR-named filesystem file only when its bytes are
an ASAR. JavaScript reconstruction expanded it on the suffix alone, so
a directory holding any other file named *.asar failed the whole
analysis with an invalid ASAR header.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
* fix(apple): report a connector that cannot name its owner as an omission
A connector is recognized by class name and then dropped by an early
`continue` when its owner cannot be resolved. Nothing recorded the drop, so
connection coverage derived `complete` with `examined: 0` and `omitted: 0`
for a connector that was present, recognized and discarded.
Both producers of that coverage contract are affected and are changed
together, because they share the facet and the reason value:
- the keyed-archive parser records the drop as `unresolvedConnections` and
reports it through the `connections:<path>` facet, the document
`connection_count` and the graph omission total;
- the NIBArchive projection in the artifact adapter recorded nothing at all,
and the projected dictionary carried no trace of the dropped connector for
a downstream consumer to find. Its count is taken where the connector is
discarded and plumbed through the same per-document omission channel that
already carries incomplete hierarchies, so the reason follows the cause.
An unresolved source cannot be represented as a connection at all, because
connection identity requires a non-empty source; that is unlike an unresolved
destination, which the graph already retains as an unresolved edge.
`connection_limit_reached` stays reserved for connections dropped by the hard
cap and `serialized_view_hierarchy_incomplete` for hierarchy omissions.
`connection_count` also includes the unresolved connectors. That field already
counts connectors the parser recognized but could not emit, because
connections dropped by the hard cap are counted there too, so unresolved
connectors follow the existing rule rather than a new one.
Verified with 98 focused Interface Builder and catalog tests, check:fast and
verify:test-discovery on macOS arm64, and through the public CLI: a rooted
archive holding one ownerless UIRuntimeOutletConnection reported complete with
examined 0 and omitted 0 before this change and reports partial with the reason
connection_unresolved and omitted 1 after it.
* fix(apple): count ownerless NIBArchive connectors and keep the limit reason
Greptile found two defects in the NIBArchive half of this change.
The document summary was left unchanged, so the same recognized connector
counted as one in a keyed archive and zero in a NIBArchive. The dictionary
parser only sees connectors that were projected, so the omission recorded
where the connector was dropped is added to the matching document here.
The facet reason was overwritten unconditionally, so a NIBArchive holding both
a connection dropped by the limit and an ownerless connector reported
connection_unresolved and lost the cause a higher limit could recover. The
existing reason is kept when the graph already named one, which is the
precedence the keyed-archive producer applies.
Verified with `npm run test:focused` over the bundle suite (42 passed, 1
skipped), `npm run lint` (0 errors) and `npm run check:fast` on macOS arm64.
Reverting the reason precedence alone fails only the limit case; reverting the
document count fails the count assertion in both cases.
The new case moved into its own describe block because the enclosing callback
crossed the repository's max-lines-per-function bound otherwise.
---------
Co-authored-by: 吴佳浩 <wujiahao@supremind.com>