Commit Graph

1351 Commits

Author SHA1 Message Date
morluto d5df7fd944 fix(reference): preserve source scope and loader authority
Share parser-owned package and runtime facts across dependency consumers.
Preserve uncertain loader requests and explicit wrapper bindings without
inventing unbound require authority in known modules. Cover selected source
grammar through the public MCP boundary and retain ambient/type dependencies.

Open each selected directory before loading its scoped policy, retaining
partial directory failures and cleanup ownership. Preserve explicit caller
negation precedence and source diagnostics across inventory projections.

Clarify how version comparison retains container provenance without claiming
semantic drift. Use independent unknown source inputs to keep candidate-limit
fixtures meaningful as conditional branch evaluation becomes more precise.

Fixes #6891
Fixes #6882
Fixes #6883
Fixes #6859
2026-10-24 06:24:55 +08:00
morluto 30db499db3 fix(javascript): preserve graph facts across omissions and versions
Omit absent inventory facts without erasing explicit unknowns. Compare canonical file occurrences by source path and digest while preserving complete container provenance in observations and Evidence.

Consolidate candidate-capacity fixtures around unresolved alternatives and update inventory coverage and source-occurrence oracles. Preserve resource, identity, relationship uncertainty, cancellation, and transfer regressions.
2026-10-24 06:20:36 +08:00
morluto a5de93a214 fix(reconstruction): qualify original process evidence at its owner 2026-10-24 06:13:53 +08:00
morluto 3914e72f1b fix(setup): admit client policy from the current snapshot 2026-10-24 06:13:53 +08:00
morluto 1252f17f0e fix(ci): model bundled runtime entries and dispatcher fixtures 2026-10-24 06:01:35 +08:00
morluto 097b604039 merge: consolidate upstream projection cleanup 2026-10-24 05:34:43 +08:00
morluto 15edc71914 refactor(javascript): remove obsolete in-process projection runner 2026-10-24 05:32:43 +08:00
morluto 0adcd83b1a test(ida): place capability composition at provider boundary 2026-10-24 05:13:41 +08:00
morluto c25ee582c5 test(wasm): place parsed interface comparison at provider boundary 2026-10-24 05:13:41 +08:00
morluto 53601d0bdf merge: consolidate upstream identity and representation owners 2026-10-24 05:13:41 +08:00
morluto 651afa4455 fix(elf): validate declared file extents before provider admission 2026-10-24 05:02:22 +08:00
gensokyo-dev 57b1f82367 perf(native): query retained export table facts (#6907)
* perf(native): query retained export table facts

* docs(perf): record native export task comparisons

* fix(native): preserve omitted export projection fields

* docs(perf): refresh final export view qualification

* test(native): verify sparse export view digests
2026-10-24 05:00:05 +08:00
morluto 171f56a5ed refactor(setup): own parsed registration command facts 2026-10-24 04:49:21 +08:00
morluto 7356434202 merge: consolidate upstream ownership and coverage fixes 2026-10-24 04:43:33 +08:00
morluto 87a5be3000 fix(environment): normalize values from owned response facts
Require a real clock-field context for numeric time normalization and actual rendered write rules for generated strings. Preserve literal read, replay and missing-response values, and retain generated aliases and distinctness within each response.

Keep clock context separate from entity identity while traversing arrays. Add domain and public CLI controls for measurements, business strings, confirmed writes, missing responses and generated-value relationships, with documented inference limits.

Fixes #6878
Fixes #6837
2026-10-24 04:42:09 +08:00
Muhammad Hamza 9e6c6241d7 fix(environment): match served items whose route repeats a separator (#6876)
* fix(environment): match served items whose route repeats a separator

callSegments split the tool path template itself and dropped empty literal
segments, while the held collection is split by segmentsOf, which keeps an
internal empty segment. A captured item route such as /api//books/{id} was
stored under collection /api//books but searched with ["api","books"], so
collectionMatch rejected it and a served item read reported the extracted
entity as missing.

Split the call template through segmentsOf, the same owner used for the held
collection path, so a repeated separator is preserved on both sides and the
item answers from its extracted collection. Single-separator routes stay
distinct and param positions are unchanged.

Fixes #6847

* fix(environment): keep repeated-separator collections writable

Preserving empty literal segments in callSegments made createdCollection's
missing-argument guard reject a create whose route repeats a separator, such
as POST /api//books: the empty literal segment tripped the
segments.some(text.length === 0) check and answerCreate refused the valid
route. Restrict the guard to empty supplied parameter segments, so a missing
path argument is still refused while a repeated-separator collection stays
writable as well as readable.

---------

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-24 04:33:51 +08:00
Aaron K. Clark a91412aaf9 feat(native): export function pseudocode to resumable directories (#6170)
* feat(decompile): write function pseudocode to a directory and return a manifest

Add decompile_all and `rea decompile-all` so a caller can write one
provider pseudocode file per function, or a filtered set, and receive
only a small manifest. The result stays bounded when the program is
larger than a local model's tool-result cap.

Resume continues an export for the same target digest, provider,
analysis profile, and layout. Matching files are skipped, conflicting
files stay unchanged, and one function's failure does not stop the
rest. Cancellation leaves files already written. Requesting dwarf
layout reports that compilation-unit paths are unavailable.

Simulated-provider tests cover the manifest, resume, filters, limits,
cancellation, and the failure cap. MCP registration, CLI coverage,
schema validity, the product catalog, check:fast, and docs:check
passed. Real Ghidra was not exercised.

Refs #6090

* fix(decompile): keep unknown export identity unresumable and recover torn journals

Resume treated two missing target or profile digests as a match, so an
export of one binary could continue into another. Resume now requires both
digests, and a decompiler observation without the export's profile, or with
a different target, is recorded as profile_changed.

A crash during a journal append left a torn final line that made the export
unresumable. Text after the last newline is now treated as uncommitted and
truncated before the next append, and stale temporary files are removed.

An inventory row with an empty address aborted the whole export because its
failure record failed the journal schema. Such rows are now excluded and
counted in the limitations.

A limited resume retried the same recorded failures first and never reached
new functions. Functions not yet attempted now run before retries. File path
reservations come from every journal line, so an output_io record no longer
releases a path. The index is rebuilt from the journal in numeric address
order, and journal close and cleanup failures return a Result.

The cancellation test now cancels after a file is committed and checks that
file survives and is skipped on resume. Redundant snapshot-replay checks are
removed, the CLI limit uses the contract constant, and --snapshot no longer
claims decompile-all updates it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb

* fix(decompile): refuse resume of a missing export and repair journals by byte offset

A second review round found that resume against a directory that does not
exist silently started a full new export and reported it as resumed. Resume
now requires an existing export directory.

The torn-line repair measured the committed journal from decoded text, so
damaged UTF-8 could move the truncation point past the end of the file. The
journal is now read as bytes and cut at the last newline byte, and an intact
journal is not truncated, so a concurrent append is kept.

A per-function observation for a different target is now recorded as
target_changed instead of profile_changed. A failure to remove a partly
created output directory is reported instead of hidden. The journal handle is
closed on every path again, including an unexpected throw. The path allocator
no longer gives up after 1,000 collisions and reuses a taken name.

Tests now use createTestTempDirectory, assert journal lines against the
journal schema, and cover resume of a missing directory, resume with an
unknown analysis profile, and a target-mismatched observation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb

* fix(decompile): keep a function's first file name across failed retries

Reserving every journal path stopped other addresses from taking a path, but
an address looked up only its latest record. After its file went missing and
a retry failed without a path, the next resume moved the function to a
hash-suffixed name and orphaned the original. Each address now keeps the
first path the journal gave it.

A matched commit still ran the decompiler but did not count toward limit.
The limit now counts every function taken on after skipping verified files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb

* fix(decompile): never follow a journal symlink and check procedure_info identity

Torn-line repair truncates the journal, and the journal was opened through
any symlink in the export directory, so repair could truncate a file outside
it. The journal must now be a regular file and is opened without following
symlinks where the platform supports it.

Body ranges from procedure_info were written without checking that the
observation belonged to this export or described the requested function. An
observation with a different provider, profile or target, or another entry
point, now leaves the body unavailable with that reason.

File, journal and index writes now use FileHandle.writeFile, which writes the
whole buffer instead of trusting one write call. The stale temporary sweep is
removed: a matching file name does not prove this export created the file.
The inverted-range test now uses one address space so it reaches the
inversion check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb

* fix(decompile): bound returned caveats and keep verified checksums

Ghidra names each terminal call's address in its per-function caveats,
so decompile_all copied one new caveat per function into the returned
Evidence and the answer grew with the program. The returned Evidence
now keeps the eight most often observed distinct per-function caveats,
grouped by provider and text as they are rendered, plus a count of the
rest. Inventory caveats are unchanged, and other workflows are not
bounded. Each function keeps the caveats of the observations it used:
a written file in its header, now including procedure_info caveats,
and a failed attempt in its journal and index record. A procedure_info
observation for another target or profile is foreign and contributes
none.

A failure record for a function that was already written replaced the
record holding its checksum, so after a transient read error a resume
decompiled that function again. The journal now keeps the last
successful write separately from the latest attempt. Resume verifies
against that write and records it again once the file verifies.

A caller abort that arrives while the export finishes now returns
cancellation with the caller's reason instead of a success manifest,
as #6143 does for other late finalization. A publish, index or close
failure stays the primary error.

Also make the missing-journal resume error say what to do, and add
boundary tests: one runs decompile-all through the real CLI against a
fake Kuna to check flag mapping, the relative output directory,
filters and limit; one runs decompile_all through production MCP
registration to check that the caveat bound is applied.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb

* fix(decompile): keep each function's complete caveats in the index

The returned Evidence keeps eight distinct per-function caveats and
counts the rest, pointing readers at the export. A written function's
file header truncates its caveats after 4,000 characters, and its
journal record kept none, so a large function with many terminal calls
could lose caveats from both the answer and the export.

Every journal record, written or failed, now keeps the complete caveats
of the observations its attempt used, and decompile-index.json carries
them. The header stays a readable summary and, when truncated, says
that the index keeps the complete list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb

* fix(decompile): report external functions instead of failing them

Ghidra classifies imports as external functions with an empty body and
returns null pseudocode for them, as its limitations state. decompile_all
recorded each one as an invalid_pseudocode failure ("not text"), so a
dynamically linked program reported every import as a decompiler failure:
34 of 116 functions in /usr/bin/xxd.

procedure_info owns the external classification. When it classifies a
function as external, the export now records status "external", counts it
in counts.external, writes no file and requests no pseudocode. The record
keeps the body fact as observed. The journal header pins the target,
provider and profile, so a resume skips a recorded external function
without asking the provider again; a limit below the external count still
leaves nothing remaining. A null pseudocode result for a function whose
classification is not external is reported as no_pseudocode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb

* fix(decompile): report finalization failures after a cancelled export

When the caller's abort stopped the publish loop, decompile_all returned
that cancellation before checking the index write and the journal close,
which had already run. A failure to finalize the export was hidden, so
the caller could not tell the saved index or journal was incomplete.

Publish failures stay primary, then index and close failures. A
cancellation counts as the caller's only when the caller's signal is
aborted, and is then reported after a successful finalization with the
caller's own reason. A provider's own cancellation, without a caller
abort, stays a publish failure like any other. Tests cover an index
failure and a close failure after the caller stops the loop, a stopped
loop with a successful finalization keeping the caller's reason, and a
provider cancellation staying primary over an index failure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb

* fix(decompile): remove a created output directory that cannot be secured

createPrivateDirectory ran mkdir and chmod as one step. When mkdir
succeeded and chmod failed, it returned an error before #create reached
its cleanup, leaving an empty directory behind. A fresh export then
refused the existing directory, and a resume refused it for having no
journal, so the caller had to remove it by hand.

mkdir and chmod are now separate. A mkdir failure created nothing, so
nothing is removed. A chmod failure after this call created the
directory removes it with a non-recursive rmdir: it is still empty, so a
path another process filled or replaced meanwhile is refused rather than
deleted, and that refusal is reported.

A filesystem boundary test fails chmod for the new root and checks the
directory is gone and a retry succeeds. A module test confirms that a
function written earlier and now classified as external still reports a
changed file at its path as output_exists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb

* refactor(process): share the socket lease with owners other than Hopper

The socket lease that keeps two REA processes from opening the same Hopper
document lived only in HopperLease, with Hopper error messages built in.
A decompile export needs the same guarantee for its output directory.

OwnedLease now holds the lease mechanism unchanged: a listening local
socket that the operating system ends with its process, owner identity
answered by the live holder, and recovery of a stale socket serialized
through a recovery directory. Callers map a tagged LeaseFailure to their
own error. HopperLease keeps its exports and maps each failure to the
same HopperStartError message as before. On Windows the lease is a named
pipe, which needs no stale recovery.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb

* fix(decompile): hold the output directory per run and stop on repeated write failures

Two runs could resume the same output directory at once. Each read the
journal once, and the index each wrote reflected only its own view, so
the last writer could drop the other run's records. A run's torn-line
repair could also truncate the other run's append.

DecompileExport now holds a lease on the output directory, named by its
device and inode, from before the journal is read (or, for a new export,
from just after the directory is created and before its journal exists)
until the journal is closed. A second run is refused as a retryable
capacity constraint that reports the holder's process ID. The lease ends
with its process, so a crashed run leaves no lock to clear. The lease is
released on every open failure, and a failed release is reported.

An export also kept decompiling every remaining function when its files
had stopped being writable mid-run, for example on a full disk, failing
each one with output_io. After five consecutive functions whose files
could not be written or read, the export now stops with an output error
that carries the counts and the last failures. A verified file or any
other outcome ends a run of failures. Committed files and records stay,
the index is still written, and a later resume continues.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb

* docs(native): record directory export verification

Record matched real Ghidra outputs, bounded caveat and cleanup regressions,
actual catalog-inclusive context estimates, runtime measurements and coverage
limits for the pinned integration.

* fix(native): bound export summaries and reserve portable paths

Use one case-folded reservation owner for allocation and resumed journals.
Budget inline failures and provider caveats by encoded JSON bytes while
retaining complete records in the output index. Align the tool contract
with the collector order and verify SDK result-window behavior.

* docs(native): refresh final export measurements

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-24 04:32:11 +08:00
morluto bfa60d596e docs: clarify batch decompilation retention limits 2026-10-24 04:23:56 +08:00
morluto 9877ab7d1d test: group boundary registration by observed behavior 2026-10-24 04:23:56 +08:00
morluto a3eae6e236 test: give oversized registration groups semantic owners 2026-10-24 04:23:56 +08:00
morluto b7ebccf8d3 fix(navigation): reject malformed containing-procedure results
Move the unchanged resolution contract into its domain owner and use it when
building navigation context. Preserve provider failures instead of guessing
absence from error text or malformed result shapes. Return null only for an
explicit valid negative resolution.

Remove the obsolete error-message matcher and partial name parser. Cover four
malformed result shapes, original error identity, valid positive/negative facts
and the typed MCP unreadable-output response. Original source failed six cases.

Validation: navigation source/MCP and advertised schema checks passed. Compact
and full generated catalogs are byte-identical to the parent. Static, docs,
discovery and duplication checks passed.
2026-10-24 04:18:07 +08:00
morluto d69752fd52 refactor(filesystem): share stable read state comparisons
Reuse sameRegularFileState for artifact, native plist and entropy readback.
Remove private copies of identity/size/timestamp checks and consistently include
mode in the existing stable-state contract.

Keep initial identity-only artifact admission, byte-count checks, capacity and
error precedence, symlink choices, cancellation and descriptor cleanup intact.

Validation: stable-file, plist, artifact outcome, entropy and public CLI/MCP
lifecycle regressions passed; static and documentation checks passed.
2026-10-24 04:18:07 +08:00
morluto 5796220f23 fix(native): validate Mach-O command framing before admission 2026-10-24 04:16:47 +08:00
morluto d9d77726ff fix(pe): distinguish unsupported overlapping header layouts 2026-10-24 04:14:17 +08:00
morluto 6f8dc9c139 fix(session): preserve binding commitments during restoration 2026-10-24 04:14:17 +08:00
morluto 1cc16128ea fix(javascript): retain unavailable source processing scopes 2026-10-24 04:14:17 +08:00
morluto 62f7b5e4cd fix(native): require observed symbol origin for named identity 2026-10-24 04:14:17 +08:00
morluto 18acae9188 fix(setup): require HTTPS throughout Hopper download redirects 2026-10-24 04:08:59 +08:00
morluto 76381b29d4 fix(objdump): preserve input issues and provider launch failures 2026-10-24 04:06:57 +08:00
morluto e909a927c4 fix(metadata): preserve canonical PowerPC subject identity 2026-10-24 04:06:57 +08:00
morluto 22d3236c31 fix(mips): retain unexamined RELR declaration coverage 2026-10-24 04:06:57 +08:00
morluto f8248417d7 fix(capabilities): report missing navigation targets 2026-10-24 04:05:23 +08:00
morluto ef00b2115a fix(javascript): retain primary interruption through worker cleanup 2026-10-24 04:05:23 +08:00
morluto e1d9ebd3cf fix(native): preserve seed analysis failures in value traces 2026-10-24 03:59:44 +08:00
morluto f01f56156e fix(browser): retain truthful cleanup facts and document request ownership 2026-10-24 03:59:44 +08:00
morluto 77ed32fabc fix(javascript): retain selected-root access and filesystem failure facts 2026-10-24 03:59:44 +08:00
morluto 8b7de17833 merge: reconcile upstream boundary and format fixes 2026-10-24 03:59:44 +08:00
morluto 9b7ba06661 style(lifecycle): format traversal and fallback edits 2026-10-24 03:16:30 +08:00
morluto 2fe5d972cc fix(hopper): retain failed private-display probe cleanup authority 2026-10-24 03:16:30 +08:00
morluto a954e9f488 fix(evidence): omit absent format recovery metadata 2026-10-24 03:16:30 +08:00
morluto 6103fddd45 fix(javascript): scope Next package admission by container identity 2026-10-24 03:16:29 +08:00
morluto f36893a1a2 fix(javascript): retain unavailable HTML reference scopes 2026-10-24 03:11:07 +08:00
morluto e94d5a5c74 fix: retain Electron file admission facts across adapters 2026-10-24 03:11:07 +08:00
morluto 25b28ffe8b fix(hopper): drain retained publishers after current close failure 2026-10-24 03:11:07 +08:00
morluto 27e927f70f fix(inventory): require released cleanup before capability fallback 2026-10-24 03:11:07 +08:00
morluto 48af28bf71 fix(tracing): retain caller reasons at traversal checkpoints 2026-10-24 03:11:07 +08:00
morluto 271fecf53a fix(evidence): preserve format-owned JSON recovery diagnostics 2026-10-24 03:11:07 +08:00
morluto 9becdfe8f4 fix(session): retain cleanup blockers and snapshot request identity 2026-10-24 03:11:07 +08:00
morluto e00b2eda0b fix(javascript): preserve recovery acquisition and cancellation failures 2026-10-24 03:11:07 +08:00
morluto 0326ad95f6 fix(setup): retain proven PATH aliases in installed registrations 2026-10-24 03:11:07 +08:00