Expose a per-call SQLite worker deadline with exact CLI/MCP recovery controls,
parent-owned execution metadata and historical unknown preservation. Keep fixed
resource limits and cleanup admission intact. Share typed cleanup composition
with one captured-output owner and preserve the timeout after cleanup resolves.
Fixes#5812. Follow-up tracking: #5808. Existing CLI test-oracle failure: #5845.
Verified 155 SQLite tests (3 skipped), static/docs/discovery checks, six real
CLI/MCP pairs and 13 actual Codex sessions including four corrected deadline
recoveries. Three pre-dispatch discovery failures remain explicit, not passes.
Review findings include real retained-cleanup and fixture ownership regressions.
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
Expose the existing WABT command deadline as an optional validated per-call CLI/MCP budget, preserving its 30000 ms default and fixed safety allowances.
Retain selected execution profiles in success and rejected-module Evidence. Keep typed timeout recovery through cleanup failures without duplicating command output or making incomplete cleanup retryable.
Verified focused tests, real WABT CLI/MCP workflows and actual Codex recovery/blocked controls; detailed measurements and qualification limits are recorded in issue #5797. Merge uses the explicitly authorized maintainer override with pending CI and unchecked human-review attestations disclosed on PR #5798.
Closes#5797
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
Decode direct Objective-C class names separately from nominal descriptors, retain indirect class bindings as partial facts, and preserve readable protocol and witness evidence when related bytes are unavailable.
Validated with 98 focused tests, check:ci, docs:check, and named-schema CLI/MCP replays of compiler-produced imported-class and struct fixtures plus an inert kind-3 control. The fixtures were inspected statically, never executed.
Fixes#5738
Distinguish CDP session detachment, observed crashes, and transport loss. Preserve the observed window alongside the original typed coverage-stop failure and unconfirmed cleanup.
Validated with 40 focused boundary tests, check:ci, docs:check, and the real Chrome public CLI/MCP verifier on macOS. Browser timing comparison remains incomplete because unchanged-main fixture readiness was intermittent.
Fixes#5756
Decode native binary plists from bounded owned source bytes before conversion can erase scalar values. Share scalar preflight and isolate overlapping decoder records while retaining exact integers, date uncertainty, and original bytes. Refuse numeric payloads that read structural table bytes, and avoid retaining projection metadata when callers only need structural validation.
Closes#5701Closes#5703Closes#5705Closes#5782Closes#5783Closes#5792
Preserve unsupported GGUF version bytes and both UINT32 interpretations without inventing byte order at the shared parser. Keep existing layout support, typed errors, evidence identity, scoped reads and resource limits.
Validation: 78 focused tests, full static/architecture and documentation checks, real CLI/MCP version controls and an independently checked public model. Latest-head Codex found no issues; Greptile is 5/5 and all review threads are resolved.
Some CI remained pending at merge qualification. Merge under the human owner's explicit standing bypass authorization does not claim the full CI suite passed.
Fixes#5749.
* fix(environment): report later bundle write failures as host failures
Only destination admission now refuses the selected directory as invalid
input. A path failure on a nested bundle file after admission, such as a
host pathname-length limit, is reported as an output failure that names the
host cause and the absolute failed path, with recovery guidance for the
partial folder it leaves in place.
Fixes#5522
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(environment): name the host-refused path in export permission failures
A permission failure after earlier bundle files were written was reported
as access denied for the bundle root, so the documented failed path was
lost. The refusal now names the absolute path the host reported, falling
back to the root, and keeps the root as `output_directory`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(environment): attribute pathless bundle write failures to their file
Descriptor operations such as `write` and `fsync` fail without a path, so
a disk-full failure after earlier files named only the bundle root. The
bundle writer now attributes such failures to the file it was writing.
Host-write recovery is applied only to actual host failures; an integrity
refusal keeps its own message without disk-space advice.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(environment): attribute package tarball read failures to the tarball
The destination-write attribution also caught failures from reading the
admitted package tarball during the copy, so a source `EIO` named the
destination file and advised freeing disk space. Host failures are now
attributed by direction: tarball reads name the tarball with read
recovery, bundle writes name the file being written.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(environment): state which export failures name a path
The export documentation and host-write message promised a failed path
for every later write failure, but a directory sync at commit time fails
without one. They now promise the failed bundle file or package tarball
when the failure is on one, and only the cause for a folder sync.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
inspect-desktop-application reported a regular-file, missing or read-denied
root as artifact_operation_failed/execution_failure, leaving the ENOTDIR,
ENOENT or EACCES cause only in message text.
DirectoryArtifactReader now marks root admission and root-open failures with
DirectoryArtifactRootFailure. DesktopApplicationReader, which owns the caller's
selection, maps a non-directory root to unsupported_target and host failures to
the shared BinaryTargetError (target_unavailable, or access_denied with
read-access recovery), keeping any partial observation. Child-entry failures
and other DirectoryArtifactReader consumers are unchanged.
Fixes#5513
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
ELOOP raised while resolving the caller-selected path (access/realpath)
is a symbolic link loop or over-deep chain in that path, not evidence of
a change. Classify filesystem failures by resolution stage so only ELOOP
from opening the canonical path with symbolic links rejected keeps the
"target changed while being opened" reason. The structured code,
category and retryability are unchanged.
Fixes#5521
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(hopper): preserve caller abort reasons on cancellation
Hopper cancellation dropped the caller's abort reason, and the typed
error treated an explicit undefined cause as omission. Retain the exact
reason at the request queue, startup, socket, and launcher boundaries.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* style(hopper): format launcher cancellation return
oxfmt rejects the wrapped abort return in HopperApplicationLauncher.
Co-authored-by: morluto <morluto@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
sigrok-cli refusals of a caller-supplied decoder ID or annotation class
were reported as execution_failure with "Run `rea doctor`" advice, which
has no sigrok check. Recognize the observed sigrok-cli 0.7.2 refusals at
the provider boundary only when the rejected name matches a caller
selector, and report invalid_request naming the decoders or annotations
argument, retaining the captured output and pointing to
inspect_signal_decoders. Other non-zero exits stay provider failures.
Fixes#5515
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The owned worker inspects only a private snapshot, so its format reason
cannot name the caller's selection. Project path-scoped worker rejections
with the selected database path so distinct malformed inputs report their
own source, matching the documented failure contract.
Fixes#5520
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(apple): refuse invalid binary dates and unknown sub-millisecond instants
Reachable binary plist dates must use marker 0x33. Other type-3 markers are
malformed and are no longer projected as observed timestamps. A valid float64
date stays known only when it is exactly the canonical millisecond instant;
other finite instants remain typed unknown dates with a counted limitation.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(apple): share one decoder copy and bound binary date payloads
Wide-integer rewrites and unrepresentable date payloads now share the
single parser-input copy already reserved by the decode budget. Reachable
date markers and payloads must end at the offset table even when other
decoder-bounds checks read trailing bytes.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test(apple): refuse out-of-region dates through the keyed reader
Decoder-bounds date truncation is now asserted on decodeKeyedArchiveBytes,
the path that selects those bounds.
Co-authored-by: morluto <morluto@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
Validate omitted GGUF strings without materializing discarded text while preserving full UTF-8 checks and retained Evidence. Record real-model costs and workflow coverage; preserve failed experiment receipts through cleanup.
Fixes#5774.
* fix(windows): retain native handles whose close is unconfirmed
CloseHandle failure no longer drops the numeric value. A still-open handle
stays owned and can be closed again; a value missing from the handle table
is dropped and never closed again; unreadable liveness blocks another close
until a probe says the value is open.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test(process): keep scratch until inherited pipes close
Lock the execFileOutput settlement contract: an inherited-pipe descendant
holds the caller's scratch root until it exits, and destroying the readers
is not process-family completion.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(windows): retry admitted file closes before runtime removal
A failed private-file close stays on the runtime that opened it. Runtime
removal closes that same wrapper before the tree walk, including when the
read that opened the file has already returned.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(windows): resume a close after part of the owner is released
A runtime whose directory handle is already released continues with its
parent handles instead of walking that invalid root. A process whose
settlement was already observed retries process close alone, without kill
or poll against the released job.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test(process): signal only an owned inherited-pipe descendant
Skip the descendant SIGKILL after pipe settlement. On an earlier failure,
signal only when the process command line still contains that test's path.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(windows): do not close a handle again after a failed close
An open liveness probe can observe a reused numeric value. After CloseHandle
fails, drop the value only when the handle table no longer contains it, and
do not call CloseHandle on that number again.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(windows): stop using a close-blocked pipe for I/O
A broken pipe whose CloseHandle fails stays owned, but its numeric value
may have been reused. Later polls and stdin writes treat that pipe as
ended instead of reading or writing the number.
Co-authored-by: morluto <morluto@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
Validate the fixed 16-byte version-39 records before using their count to select the serialized index width. Reject contradictory count and byte extents while preserving valid zero, one and 300-record controls.
Validation: 89 focused reader/provider/compiled CLI and stdio MCP tests; check:ci; seven reproduced CLI and SDK-validated MCP cases with unchanged fixture hashes. Version-specific source and independent parser evidence distinguish fixed records from compressed indices. Synthetic metadata only; no real-game or target-execution qualification.
Fixes#5751
Remove unsupported DWORD alignment refusals from resource data entries and adjacent directory tables. Preserve original record locations, UTF-16 name alignment, bounds, mapping, overlap checks and payload hashes.
Validation: 49 focused parser/provider/filesystem/lifecycle and compiled CLI/stdio MCP tests; check:ci; independent pefile agreement for the reported layout, padded control and PE32/PE32+ word-aligned directories. Public CLI and SDK-validated MCP retain truncated-input refusals and unchanged source hashes. Synthetic static inspection only; Windows loading was not tested.
Fixes#5750
Fixes#5771.
Preserve the configuration owner's parsed registration settings and remediation in IDA readiness, retain caller-selected paths, and distinguish configuration selection from validity and live connection. Verified with 84 relevant tests, CLI/MCP negative-case parity, static/docs gates, independent source review and repeated actual Codex recovery tasks. No real IDA engine/GUI analysis qualification.
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
Fixes#5767.
Retain exact WABT version-probe output and tool identity, including nonzero command failures, and provide condition-specific configuration recovery. Verified with 54 focused tests, the final 51-case real WABT CLI/MCP lane, actual Codex recovery trials, and independent source reviews. No provider installation, target execution or admission relaxation.
Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
Preserve the upstream WAT framing optimization alongside the qualified dylib fix. The combined tree passes 14 compiled dylib CLI tests and the full check:ci gate.
Apply dyld’s implicit macOS compatibility rule only for a root executable with observed macOS platform and a supported candidate CPU type. Retain the absent platform fields as raw facts and expose the derivation on the candidate. Traverse the selected dylib and report missing required children; preserve unknown platform coverage and the later known fallback graph in other contexts.
Validation: 144 source/reader tests, 14 compiled CLI tests, 18 schema tests, full check:ci and docs:check passed. Four source-built app variants passed CLI and SDK-validated stdio MCP checks with unchanged fixture digests. No fixture executable or Apple dyld comparison was run. Independent review resolved a library-root authority gap before integration.
Sixteen cold/warm task-cost observations are retained locally with sampling limits; the catalog adds 66 bytes. Actual model tokens and maximum-sized inputs were not measured; no speedup is claimed.
Closes#5696
Preserve valid empty TShark protocol stacks at the shared parser, retain frame and other fact inventories, and cover malformed producer output and mixed-frame ordering.
Validated with focused source/boundary tests, full static checks, docs checks, real Linux CLI/MCP and a mixed-interface public HTTP pcapng. Latest-head Codex found no issues; Greptile is 5/5 and its test-coverage thread is addressed. Remaining queued CI was bypassed under the human owner's explicit authorization; this does not claim that the full CI suite passed.
Fixes#5734.
Move ELF, PE and Mach-O container parsing into a shared native owner. Go alone selects and validates Go build-info sections, so unrelated malformed Go metadata no longer blocks Rust dependency or IL2CPP inspection. Remove the superseded Go-specific container representation and migrate all consumers. Adapted from draft PR #5510 without asserting human PR readiness.
Validation: 51 compiled CLI/MCP acceptance tests across Rust, Go and IL2CPP; 186 shared-reader tests; full check:ci passed. Three public synthetic-file probes reproduce the baseline Rust refusal and validate the fixed SDK-advertised MCP output, artifact digests and unchanged bytes. The exact zero-address nonallocated ELF case now succeeds for Rust while Go still reports invalid_format. No target execution or real compiler-artifact qualification was performed; no performance improvement is claimed.
Closes#3398
Extract repeated process rows, environment transitions and exact lineage expectations while retaining all identity, replacement-read and cancellation cases. Clean main exceeded the configured 3.5% duplication limit at 3.521867%; this refactor passes at 3.499188% without changing the limit.
Validation: 72 focused process-ownership tests and the full check:ci gate passed. Independent source review found no assertion or coverage loss. No runtime behavior changes.
* fix(process): token-check identityless exit-refresh replacements
A launcher-exit refresh could drop a reparented grandchild that was absent
from the prior snapshot and report cleanup complete, or publish a verified
empty lineage, without reading its run token.
Fixes#5206
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): re-read identityless refresh rows when relations change
Lineage refresh classified every pre-existing process as a newcomer, and it
skipped a row after caching its first parent and group. Seed the exclusion
set from the initial snapshot and read a row again when that relation changes.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* style: format files oxfmt rejects on main
Repo-wide format:check fails on these two files at current main. Align them
so the process-ownership fix can pass the required static check.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): keep owned groups found while confirming exit
An unreadable exit-refresh row used to hide the confirmation table, and
revalidation dropped groups discovered after the plan was built. Both now
stay in the same cleanup, and confirmation reads are bounded.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): reclassify lineage rows when tree membership changes
Initial outsiders and cached refresh rows are read again when a parent,
group, or ancestor move changes launcher-tree membership. Unchanged
initial rows stay unread.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): re-read cached identityless lineage tokens
Parent and group do not identify a process generation. A row whose token
was read is read again on the next refresh, so a reused PID cannot keep
a verified descendant.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): revalidate an owned group that reappears
A group discovered after it was already processed is queued once more.
Another appearance stays unresolved instead of reporting cleanup complete.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): recheck a helper that changes groups during confirmation
The confirmation table can move a token-matched member into a new group.
That row is read again, and cleanup signals the group it belongs to now.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): publish one lineage row when a descendant returns
A refreshed descendant replaces the initial row for the same PID, including
when its group moves away and then returns to the original relation.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): re-read foreign PIDs on the exit confirmation table
A readable foreign token does not identify a process that later reuses
that PID. The confirmation table reads those newcomers again.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): recheck a pre-exit PID whose relation changes
An unchanged pre-existing row stays unread. A prior PID whose parent or
group changed is token-checked, so a reused owned process is not skipped.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): recheck an initial descendant after its token matches
A successful read in the first lineage pass marks that PID token-checked.
A later refresh reads it again, so a reused PID cannot stay verified.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): recheck the launcher on each lineage refresh
A later refresh reads the launcher PID again. A missing or unowned
launcher is unavailable instead of rooting a verified lineage.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): publish lineage from the latest refresh table
A descendant missing from the latest refresh is omitted. A refreshed
launcher whose group or command no longer matches stays unavailable.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test(process): cover a refreshed launcher parent mismatch
A same-token launcher whose parent no longer matches the committed
expected parent is unavailable, same as a group or command change.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): recheck a token-read helper that returns to its group
A confirmation table dropped a previously matched PID once its parent and
group matched the pre-exit row, so cleanup could signal only the group it
had joined and report success while that helper survived.
Co-authored-by: morluto <morluto@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
Use one XML 1.0 line-ending rule in the shared XML boundary and plist source-span owner. Normalize literal CRLF and CR while retaining NEL, line separator and paragraph separator as observed characters. Keep character references, raw scalar locations and prototype-key omission intact.
Validation: 229 XML/plist source tests, 60 adjacent Ghidra/Apktool/SAZ source tests, and 33 compiled CLI/provider tests passed. Full check:ci passed. Real plutil XML and binary fixtures reproduced the baseline loss and passed CLI plus SDK-validated stdio MCP checks with unchanged input digests. Independent source review found no blocker. Binary conversion losses tracked by #5701, #5703 and #5705 remain separate work.
Closes#5702
Resolve relative pointers using field-owned ABI encodings. Keep null, raw, rebased, imported and unknown targets distinct, and retain imported conformance rows with exact Mach-O binding provenance. Decode legacy rebase membership with source-derived memory and work bounds, preserving validated prefix facts when streams are incomplete.
Validation: check:ci, docs:check and build passed; 158 source tests and 20 schema/acceptance tests passed. Ten source-built Apple dispatch variants and four issue-specific CLI/MCP workflows passed without executing targets. Paired cold/warm CLI/MCP cost observations retained locally; model tokens and maximum-sized input runtime were not measured.
Closes#5683Closes#5685
BREAKING CHANGE: Swift conformance type_name and protocol_name can be null when names cannot be resolved; consumers must use typed type_binding and protocol_binding evidence. MachoImportBinding replaces the former Objective-C-specific binding type and schema.
Preserve load-command paths as evidence while passing a separate root-relative lookup path to the bounded tree resolver. Apply the same containment rule to absolute install names and rpath bases, including caller-selected root symlink spellings.
Validation: 140 source tests, full check:ci, docs and runtime build passed. Compiler-built literal, rpath and relative fixtures passed CLI/stdio MCP parity, preserved both dependency edges and left all bytes unchanged. External system paths stayed outside-target; relative control was unchanged. Fixtures were not executed, and actual dyld execution was not qualified.
Closes#5637
Own CDP frame applicability and identity at the parsed event boundary. Preserve malformed or incomplete main-frame facts, recognize replacement roots, and carry the same document identity through captures, screenshots, timelines, and execution windows.
Validation: full check:ci and docs:check; 763 browser and dispatch tests passed, 6 skipped. Independent source and fixture-lifecycle review passed. Local real-Chrome behavior was not exercised.
Closes#5665
Count each admitted unique class or metaclass object at its parsing owner. Preserve emitted metadata, independent class-list scan bounds, partial failures, and truncation.
Closes#5706
Count examined and decoded vtable slots in the same population, preserving all returned slots and partial descriptor failures. Document the coverage unit and retain malformed-sibling and unresolved-slot checks.
Closes#5681
Keep raw physical read diagnostics alongside explicit operation provenance on the same cleanup owner. Preserve provenance after successful close retry for opted-in readers, restore legacy error projections, and prevent borrowed cleanup-shaped failures from authorizing foreign resource retries.
Refs #5686
Parse only documented compound otool field labels so valid segment and section names are retained at the owning boundary. Verified real Apple clang fixtures through compiled CLI and stdio MCP without executing the targets.
Closes#5680
Tag physical read outcomes at the owning boundary and preserve opaque caller cancellation reasons through JSON pipelines and reference imports. Share named bounded-read options across consumers and retain failed cleanup ownership for retry.
Closes#5686
Join provider class observations only when selected-image identity and exact import bindings establish equivalence. Preserve distinct observations and unsupported coverage.
Refs #5607
Preserve exact selected-image identity and descriptor ownership across preparation, final cleanup, and retries. Keep physical failures and failed cleanup leases observable through provider and launcher boundaries.
Closes#5688
Keep malformed or missing CDP opcodes and payload facts unknown, retain observed zero and empty payloads, and avoid false capture differences while preserving independently known facts.
Validation: 59 source tests; compiled public CLI and stdio MCP fake-CDP acceptance; check:fast; docs:check; changed-file formatting. Real Chromium malformed-event behavior was not tested.
BREAKING CHANGE: WebSocket event opcode is nullable and numeric values are restricted to the four-bit protocol range.
Fixes#5666
Add a read-only app resource session shared by CLI and MCP. Preserve resource-root provenance without inventing executable identity, reject binary-only snapshots and operations, and retain failed cleanup owners across switches and retries.
Keep filesystem admission failures typed and preserve cancellation ordering from observed cleanup facts. Document resource routing in the packaged investigation skill.
BREAKING CHANGE: resource-only observations may have a null Evidence subject and null executable target digests. Clients must use resource_root and reported per-resource provenance instead.
Refs #5589
* fix(observation): keep incomplete cancellation observations
Service projection treated a retained observation that failed the completed
schema as a malformed completed result. Cancellation became unreadable_output
and the partial was dropped. Incomplete observations now stay on the owner
error, including the exact abort reason.
* fix(observation): drop non-JSON incomplete observations
Keep a retained partial only when projectAnalysisError can serialize it.
Clear a non-JSON partial and record an AnalysisOutputError as a secondary
failure so cancellation and timeout stay the owner error.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(observation): validate incomplete partials without copying
jsonValueSchema.safeParse cloned a JSON-safe partial that projection
copies again. Use jsonValueValidationIssue so the gate only checks.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test(ida): expect non-retryable unresolved procedure lookups
Main stops treating invalid_request as retryable. An unchanged missing
procedure stays invalid_request and is not marked retryable.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test(observation): share incomplete-observation assertions
The new non-JSON cases repeated the same owner-error checks and pushed
duplication over the 3.5% limit. One expectation helper keeps those
checks without a second copy.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test(observation): keep the assertion helper out of the package
The helper imports Vitest. Rename it to a fixture so the production
build excludes it and dist does not import a dev dependency.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(observation): clear non-JSON partials on cleanup primaries
Projection can return the cleanup primary after retry. Clearing only
the wrapper left that primary's partial in place, so projectAnalysisError
threw. The gate now clears every non-JSON partial in the chain.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(observation): freeze retained incomplete observations
A JSON partial stayed a live provider object, so a later mutation could
make projection throw. The gate now keeps one frozen snapshot and still
drops a non-JSON partial without copying it.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* refactor(observation): share web runtime partial retention
Observe and inspect used the same promote-or-keep path. One helper
owns that sequence so the two operations cannot drift.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(observation): snapshot a shared partial once
A cleanup wrapper and its primary can hold the same partial object.
The gate now reuses the first frozen snapshot for that object.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(observation): parse a kept partial once
jsonValueSchema.safeParse validates and copies only a JSON partial.
The gate freezes that copy and no longer walks the same value first.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test(observation): share repeated observation fixtures
The incomplete-observation tests repeated the same provider setup and
an empty Electron coverage tail, which pushed duplication over 3.5%.
One coverage fixture and shared assertions bring the tree back under
the threshold.
Co-authored-by: morluto <morluto@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>