85 Commits

Author SHA1 Message Date
Rudy Mizrahi Celekli 98422997c0 fix(setup): report Kuna cache aliases consistently (#7207)
fix(setup): report Kuna cache aliases consistently (#7207)

Unify lexical default-cache reports without changing removal authority. Plan selections before deleting managed directories; resolve absolute POSIX paths independently of ambient cwd. Preserve parent traversal, literal backslashes, caller data, and result/removal order.

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-27 15:13:47 +08:00
morluto 01a725ecfa fix(setup): preserve configuration directory requirements 2026-10-27 13:14:50 +08:00
morluto d2da713859 fix(setup): recognize inherited owned launcher 2026-10-27 11:45:01 +08:00
morluto f2277454b8 fix(setup): preserve unowned client registrations 2026-10-27 11:39:32 +08:00
morluto 768b58c6db fix(setup): honor Droid home override 2026-10-27 11:08:54 +08:00
morluto 077de92594 fix(setup): preserve selected Hopper loader arguments 2026-10-27 07:03:11 +08:00
morluto 19f9011511 fix(setup): honor VS Code user data overrides 2026-10-27 05:42:50 +08:00
morluto 4803c4f9c2 fix(setup): preserve selected settings and Java paths 2026-10-27 05:36:09 +08:00
morluto 99062feaa7 test: bind MCP validation and cleanup faults to selected inputs 2026-10-26 23:06:36 +08:00
morluto 77468d5043 fix(providers): preserve launch selections and refresh obsolete Kuna exports 2026-10-26 22:22:27 +08:00
gensokyo-dev b675073b73 feat(mcp): scope advertised tools by family (#7228)
Scope MCP discovery, setup, doctor, status and recovery guidance by selected tool families using one contract inventory and shared catalog identity. Preserve default discovery, canonical validation and complete Evidence.

Fixes #3246. Builds on #3026. Real libcrypto workflow verifies all 5,367 exports and identical complete Evidence. Static/source/build/docs/Windows/package/Greptile checks pass; ten assertions reproduced identically on clean main and feature across Node 24/22, with cancelled coverage explicitly unverified. Merge uses the user-authorized bypass for baseline failures and unchecked human-readiness declarations, without attesting human review.

Co-authored-by: 0xLLVEL <fakhrezan1@gmail.com>
Co-authored-by: Codebuff <noreply@codebuff.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-10-26 19:50:12 +08:00
morluto 68f2d67c56 fix(paths): preserve native selections through analysis and removal 2026-10-26 18:26:17 +08:00
morluto f8161ad7b3 fix(setup): preserve selected home paths throughout skill installation 2026-10-26 18:11:54 +08:00
morluto c849a97d2a fix(setup): preserve explicit Codex home traversal 2026-10-26 15:41:03 +08:00
morluto f4987281fa fix(setup): forward supported tool and runtime selections 2026-10-26 15:15:00 +08:00
morluto b654ac8b13 fix(setup): retain auxiliary tool selections in registrations 2026-10-26 14:49:10 +08:00
morluto 6819cc5b8d fix(setup): preserve explicit configuration independently of readiness 2026-10-26 14:02:55 +08:00
morluto 1173c0a9dc test(setup): align launch fixtures with runtime and host requirements 2026-10-26 03:20:13 +08:00
morluto d69a54d592 fix(setup): register explicit MCP runtimes and preserve launcher identity 2026-10-26 02:33:31 +08:00
morluto 475f09d5ca chore(lint): enforce buffer and cancellation regression guards 2026-10-25 07:31:42 +08:00
morluto bff03bfc97 test(setup): retain Hermes policies across registration refresh 2026-10-24 22:54:05 +08:00
morluto 4d22c83b07 test(setup): align boundary assertions with owned contracts 2026-10-24 08:22:13 +08:00
morluto f5d791f2a1 fix(setup): preserve client-owned MCP policy on refresh 2026-10-24 01:47:31 +08:00
morluto 98ca6c8270 fix(setup): preserve source keys across configuration boundaries 2026-10-23 22:32:06 +08:00
morluto 47353e494d feat(config): make the bridge request ceiling configurable (#6376)
* fix(reconstruction): dedupe residual unknown ids with uniqueSorted

Current main calls uniqueBy, which is not defined, so typecheck fails.
Residual unknown ids are strings, and the adjacent lists already use
uniqueSorted.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* feat(config): make the bridge request ceiling configurable

REA_BRIDGE_MAX_REQUEST_BYTES replaces the hard-coded 16 MiB Hopper and
Cutter request payload ceiling. The default stays 16777216 bytes. Values
outside 7464 to 268435456 bytes are configuration_invalid.

Part of #6176.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(cutter): keep cleanup ownership when a sent command's reply is oversized

An authenticated command may already have changed the Cutter document
when its reply exceeds the frame ceiling. Return the existing unknown
execution, with the ceiling diagnostic in the message, so receipt
cleanup still waits. A frame that overflows before the command is sent
remains a resource constraint.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* style: format the bridge request ceiling sources

oxfmt --check failed on the five files that set and test
REA_BRIDGE_MAX_REQUEST_BYTES. Formatting only; an oversized Cutter
reply still stays an unknown execution.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(cutter): exclude the LF from the response frame budget

REA_BRIDGE_MAX_REQUEST_BYTES counts payload bytes. The Cutter response
reader and authenticated encoder were reserving one byte for the
terminating LF, so an exact-limit response was rejected. A reply that
exceeds the ceiling after the command was sent still stays an unknown
execution.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(bridge): measure escaped JSON before allocating the request

A command of U+0001 characters can expand sixfold. JSON.stringify of
that expansion can throw past Node's string ceiling before the payload
check. Count the escaped size within REA_BRIDGE_MAX_REQUEST_BYTES
first and refuse it as a resource constraint.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(config): derive the bridge request maximum from JSON expansion

A 256 MiB ceiling still lets a shorter U+0001 command expand past Node's
536870888-character string limit. The maximum is now
floor((536870888 - 296) / 7) = 76695798, the longest such command whose
authenticated frame fits in one string. Requests are still measured
before JSON.stringify.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(bridge): size the Cutter frame deadline and send the measured Hopper payload

The authenticated Cutter command is encoded after the challenge, so a
one-second read rejected an in-budget frame. That read now allows one
second per mebibyte of the ceiling and never waits longer than 25
seconds. Hello stays at one second. Hopper writes the payload it already
measured instead of serializing the same request again.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(config): bound the bridge request maximum by the serialized string

The ceiling already measures escaped JSON, so dividing Node's string limit by the seven-byte expansion rejected encoded payloads that still fit. The maximum is 536870887, one byte under that string ceiling, leaving room for the framing LF.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(hopper): serialize a bridge request when it reaches the wire

The queue kept each encoded frame, plus the caller's params, until Hopper finished the active request. A raised ceiling made a few waiting calls enough to exhaust the heap. The FIFO now keeps the params, and the frame is encoded only for the request being written.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(cutter): hash the bridge proof prefix and payload separately

An exact-limit Cutter frame plus the HMAC prefix exceeds Node's single-string ceiling, so the client threw before sending an admitted command. The prefix and payload are now separate HMAC updates, including the response proof.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(cutter): keep recovery fields when a status path exceeds the frame

A long current_file made the status reply miss the ceiling, and the fallback then dropped session_id and the completion receipts. The status now omits the path and version and still returns the session, connection proof, and up to 64 receipts. That required recovery frame is smaller than the 7464 floor.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(cutter): report an unknown path when status identity does not fit

A bounded status kept the new document generation and omitted the path, so the client filled in the descriptor's older path. The observed path is sent when it fits. When it does not, current_file is null and is not replaced with that stale path.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(cutter): count structured replies by their encoded JSON size

The response guard charged 16 bytes per primitive and two bytes per list slot, so a dense array under the configured ceiling was replaced with output_truncated. Numbers, booleans, null, and container punctuation now use their JSON lengths.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(cutter): stream authenticated responses in bounded chunks

A fitting reply was signed from retained raw bytes, escaped bytes, and a
joined frame, so a ceiling near 512 MiB could exhaust Cutter before send.
Measure and sign JSON pieces, then write the same frame in 64 KiB chunks.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(bridge): keep Cutter admission from stalling or hiding sessions

Read an unauthenticated frame off the accept loop. A command reply that
does not fit keeps completion and generation and reports an oversized path
as null. Discovery reports a ceiling mismatch instead of an absent session.
The maximum HMAC proof is opt-in, and both bridges reject non-ASCII digits.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(cutter): bound frame scans and client response copies

Search only newly read bytes for the framing LF. Unescape each socket
chunk into one response string, check the proof, and then parse it.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(cutter): keep completion, admission, and dense replies bounded

Report completed_connection only through connections that have
terminated. Cap connection threads and keep the listener up if one
fails to start. Batch scalar JSON and fail discovery when any ceiling
mismatches.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(cutter): hash requests in parts and scan escapes once

Update the client-proof prefix and request separately. Stop the response
decoder at the first quote or backslash instead of rescanning the tail.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(cutter): confirm live ceiling mismatches and omitted output

A stale descriptor from a previous ceiling is not a discovery mismatch
until its hello proves a live authenticated bridge. A response discarded
for the frame ceiling after dispatch reports output_truncated.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test(cutter): close the unauthenticated ceiling-mismatch fixture

The listener that fails the hello proof is destroyed after its challenge
so discovery cleanup does not wait on that socket.

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>
2026-10-23 06:11:21 +08:00
abdulwasea89 42e1a17d6e fix(setup): preserve concurrent client configuration edits (#4855)
* fix(setup): preserve concurrent client configuration edits

* fix(setup): normalize configuration transaction queue paths

* fix(setup): report concurrent snapshot read conflicts

* test(setup): isolate Pi workflows from installed Hopper

* test: align inherited fixtures with current analysis contracts

* test(ida): assert search recovery instead of diagnostic prose

* fix(setup): share configuration queue keys across directory aliases

Resolve parent-directory aliases for regular and missing configuration
paths so a directory symlink and its real directory serialize setup
instead of racing the same file.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-23 05:06:13 +08:00
Haoran Xu c592ea6bac fix(opencode): override inherited disabled flags (#3469)
Set disabled to false in generated OpenCode V2 registrations so a
lower-priority disabled entry cannot keep approved setup stale.

Cover layered JSON/JSONC refreshes, idempotent setup and doctor readiness,
exact backups, preserved lower settings, malformed-config refusal, and
the exclusion of disabled registrations from automatic maintenance.
Update the native V2 registration expectations.

Fixes #3318
2026-10-23 02:33:38 +08:00
Haoran Xu 4a90059fe2 fix(hermes): detach aliased server tables before editing (#3785)
* fix(hermes): detach aliased server tables before editing

Copy aliased parent mappings before setting or removing a Hermes
registration. Resolve references against the original document and remove
anchors from the private copies to preserve existing sources and consumers,
including shadowed anchor names.

Cover YAML 1.1 and 1.2 setup, refresh, doctor readiness, repeated setup and
uninstall, along with comments, exact backups and invalid-alias refusal.

Fixes #3320

* test(setup): isolate Hermes flows from host Hopper detection

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-23 02:32:48 +08:00
Yann Roberto 220414682e fix(setup): preserve explicit clients with all-detected selection (#5508)
* fix(setup): preserve explicit clients with all-detected selection

* test(filesystem): align staged cancellation cleanup assertions

---------

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
2026-10-23 02:23:58 +08:00
morluto 584937c761 feat(mcp): make MCP startup phase budgets configurable (#6304)
* feat(mcp): make MCP startup phase budgets configurable

REA_MCP_INITIALIZE_BUDGET_MS, REA_MCP_TOOLS_LIST_BUDGET_MS,
REA_MCP_FIRST_CATALOG_BUDGET_MS, and REA_MCP_DOCTOR_DEADLINE_MS keep
today's defaults and refuse values outside 1 to 2147483647 ms. Codex's
30 second startup figure stays client guidance.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(mcp): enforce the first-catalog budget while phases are pending

The packaged startup probe applied each phase timeout on its own and
checked REA_MCP_FIRST_CATALOG_BUDGET_MS only after both requests
finished. A shorter first-catalog budget now clamps the in-flight
request and cancels it from one deadline measured at startup.

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>
2026-10-22 23:54:01 +08:00
morluto 306ed79932 feat(captures): make the HAR/SAZ/qlog decoder heap configurable (#6299)
* feat(captures): make the HAR/SAZ/qlog decoder heap configurable

REA_CAPTURE_DECODER_OLD_GENERATION_MIB keeps the 192 MiB default and
refuses values outside 8 to 16384 MiB instead of falling back.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(captures): defer decoder startup and share one parsed heap

Invalid REA_CAPTURE_DECODER_OLD_GENERATION_MIB threw while CLI commands
were registered, so doctor and help never ran. Build the capture service
only when inspect-web-network-capture runs.

Resolve the heap once in composition and pass that fact to each Node
adapter. Limitation and memory-failure reports use the selected adapter's
heap, so a decoder built with a different environment does not describe
another limit.

Mock captureDecoderProcessMemoryLimitBytes in the Node adapter test so a
Windows Bun host still exercises the unavailable-bound refusal.

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>
2026-10-22 23:52:21 +08:00
morluto 9512a80804 feat(process): make the regex worker heap request configurable (#6301)
* feat(process): make the regex worker heap request configurable

REA_REGEX_WORKER_HEAP_REQUEST_MIB keeps the 128 MiB default and refuses
values outside 8 to 16384 MiB. A positive Node --max-old-space-size still
overrides the request and is not clamped by the setting.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(process): set the regex worker heap floor to the measured startup bound

On Node 22.23.4 a 5 MiB old-generation request aborts the regex worker
during startup, and 6 MiB starts it and returns a match. The setting floor
is that measured bound.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(process): raise the regex worker heap floor to 7 MiB

6 MiB passes configuration but returns ERR_WORKER_OUT_OF_MEMORY for a
trivial match on supported Linux Node 24 and Node 26.0.0. 7 MiB returned
that match on the measured 22, 24, and 26 lines. A clean-process test
runs the production worker at the floor.

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>
2026-10-22 23:43:13 +08:00
morluto c7efd3a388 feat(config): make the regex matching deadline configurable (#6267)
* feat(config): make the regex matching deadline configurable

REA_REGEX_MATCHING_DEADLINE_MS defaults to 5000 ms and refuses values
outside 1..2147483647. Recovery and capability text name the effective
deadline, its source, and how to change the setting.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(setup): preserve the regex matching deadline in registrations

Setup validated REA_REGEX_MATCHING_DEADLINE_MS but left it out of the
selected registration environment, so a caller override never reached
the launched server and matching fell back to 5000 ms.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* test(config): restore a stubbed regex matching deadline on failure

Kuna deadline assertions now unstub the environment in finally, so a
thrown construction or expectation cannot leave the setting stubbed.

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>
2026-10-22 17:10:51 +08:00
Kaoru0822 002e1b68c6 fix(ghidra): skip the Java probe without an installation (#6282)
Setup and doctor inspect every provider. With no GHIDRA_INSTALL_DIR and no
Ghidra launcher on PATH, the Ghidra inspection still ran the host `java` from
PATH. Its result was discarded because the configuration check already
rejects Ghidra, but its owned-process cleanup could still fail closed. In CI,
that cleanup reported cleanup_incomplete for an unrelated live process whose
/proc/<pid>/environ was unreadable, so `rea setup --client hermes` exited 1.

Run Java only for a selected installation, matching the existing rule for a
relative JAVA_HOME. Hermes setup tests now report the CLI JSON when an exit
code assertion fails.

Fixes #6200

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:20:12 -07:00
Kaoru0822 86357bad54 fix(setup): keep comments around REA's table in Grok Build TOML (#6261)
The shared TOML server-table editor kept comment lines immediately only
for the Codex dialect. For Grok Build it queued them with blank lines,
then discarded the queue when an REA table header followed or while it
skipped REA's table, so a comment introducing the stale REA table and a
trailing file note after it were lost on setup and uninstall.

Every comment line is now kept in place for both TOML dialects; only
blank lines that separated a removed REA table go with it. The Codex
wrapper's terminal line-break restoration moves into the shared editor,
so removing a final REA table keeps the file's last line break for
Grok Build too.

Fixes #6207

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:26:40 -07:00
ShuaixinHuang e84468c0bb fix(setup): preserve Windows environment override identity (#4946)
* fix(setup): preserve Windows environment override identity

* fix(setup): preserve selected platform and YAML alias metadata

* fix(setup): reconcile layered environment and projected YAML identities
2026-10-20 17:25:51 +08:00
ShuaixinHuang afde435c94 test(setup): use native Windows launcher in layered OpenCode fixture (#4947) 2026-10-20 17:25:38 +08:00
morluto 0e62094b69 test(setup): isolate registration checks from installed providers
Select absent Hopper, Ghidra and Java locations consistently across registration environment acceptance fixtures. Host PATH Java was executing during IDA budget checks and exposing those checks to unrelated provider cleanup failures. Keep the process ownership failure policy and all registration assertions intact.
2026-10-20 00:53:52 +08:00
morluto 22ddd82014 fix(uninstall): preflight repeated registration ownership
Read shadowed registrations from the effective JSONC syntax tree before
any client is changed. Share the same typed ownership decision with the
reread before removal, including foreign OpenCode V1 fallbacks. Remove
all admitted duplicates using one member/separator planner and grant
serializer authority only for exact admitted paths.

Setup may remove its explicitly superseded OpenCode V1 path. Preserve
inactive repeated parents, unrelated entries, comments and source backups.
Use the pinned JSONC scanner instead of handwritten string decoding.

Validation: final 86 focused cases and 9 setup acceptance cases passed;
104 additional filesystem consumer cases passed. Static/architecture,
docs and discovery checks passed. A broader 186-case run had one OMP
timeout; its isolated 9-case rerun passed, with timeout cause unverified.
Controlled compiled CLI comparisons verify removal/refusal and backups;
real developer-client execution remains unverified.

Adapted from #4977 at 4cd22d4ec2.
Closes #4976

Co-authored-by: Nikhil Bhagat <knewboy.nykhil@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 06:32:14 +08:00
Kaoru0822 b83b9caf4a fix(setup): edit the duplicate JSON member that clients read (#4957)
JSON.parse, JSONC parse, and native Claude Code keep the last duplicate
object member, and parseClientConfiguration therefore validates the last
one. The shared setup/uninstall serializer instead edited text through
jsonc-parser's modify and findNodeAtLocation, which select the first
matching member, so setup and uninstall on configurations with repeated
server tables or rea members wrote into a shadowed member and failed
readback.

Locate every JSON text edit by the effective (last) member in one place,
replacing the first-member modify path. Removing an effective member
that shadows an earlier duplicate would activate that duplicate, whatever
its ownership, so the serializer now returns a tagged shadowed_member
failure and setup and uninstall refuse before writing a backup or the
configuration.

Fixes #4952

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 22:15:47 -07:00
Kaoru0822 18aa9af2b2 fix(setup): admit only strict JSON for Claude Code configuration (#4944)
Claude Code shared the generic `json` client format, which the shared
configuration reader admits through JSONC parsing with comments and
trailing commas enabled. Native Claude Code reads `.claude.json` with a
strict JSON parser (after a UTF-8 BOM), so setup reported `ready`, wrote
a registration into a file the client rejects as corrupt, and doctor
reported it `aligned`.

Give Claude Code its own `claude_code` configuration format and parse it
at the owning boundary with strict JSON.parse after removing a leading
BOM. Setup, doctor, and uninstall all consume that parser, so comment or
trailing-comma documents are now refused as malformed before any backup
or write, while plain and BOM-prefixed JSON still configure. Clients that
natively accept JSONC keep the `json` format and its behavior.

Fixes #4940

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:57:28 -07:00
Kaoru0822 270bc38f72 fix(setup): read signed 64-bit TOML integers losslessly (#4937)
Codex and Grok client TOML was parsed with smol-toml's default reader,
which rejects any integer beyond JavaScript's safe Number range. Valid
TOML 1.0 Int64 values such as `max_bytes = 9223372036854775807` made
setup, doctor and uninstall treat the whole file as malformed.

The client TOML owner now parses with `integersAsBigInt: "asNeeded"`,
keeping safe integers as numbers and larger ones exact as bigint, and
rejects values outside signed Int64 before any write. All TOML parses in
the document owner (document read, inline string decoding and the
preserving-edit check) use that reader. The inline-table writer emits
bigint values, and setup and doctor accept a positive bigint
`startup_timeout_sec`/`tool_timeout_sec` instead of replacing or
rejecting it.

Fixes #4917

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:02:26 -07:00
morluto d818c3d263 fix(doctor): preserve unresolved client configuration evidence
Use entry metadata to discover registration evidence independently of target
readability. Preserve failed metadata inspection as a named invalid diagnostic
instead of treating all lookup failures as absence. Remove the duplicate
boolean existence wrapper; configuration parsing remains the read owner.

Cover native permission-denied targets and metadata, dangling configuration
entries, maintenance exclusion, and public doctor output without mutation.

Validation: 73 focused tests across four files, check:fast, format:check,
and six isolated completed public doctor cost comparisons passed on macOS
arm64 / Node24.18.0. Native Windows/Linux permissions were not verified;
POSIX permission controls skip unsupported hosts and root.

Fixes #4905
2026-10-18 07:10:44 +08:00
morluto 19329e43bb fix(setup): preserve launcher identity and uncertainty
Use one registration classifier for doctor, maintenance and uninstall.
Preserve unknown identity when launcher resolution fails, and compare native
paths without collapsing symlink traversal. Keep Node argv script selection
separate; ambiguous direct-launch interpretations cannot authorize removal.
Remove the superseded boolean ownership parser.

Validation: 183 focused tests passed, 2 Windows cases skipped; check:fast
and docs:check passed. Five public regressions fail on the baseline, including
foreign registration removal in an isolated fixture. Source review and authored
Node shebang controls completed on macOS with Node 24.18.0. Native Windows,
Linux and real mise upgrades remain unverified.

Closes #4895
Closes #4896
2026-10-18 06:18:34 +08:00
morluto 01cdbbdc55 fix(update): bound package-manager output retention
Reuse supervised raw-byte capture with a 4 MiB aggregate budget. Drain package-manager output through physical close, reject oversized complete replies, and let verbose installs finish with explicitly bounded failure diagnostics. Preserve existing command resolution, selected environment/cwd, runtime prerequisites and signal policy.

Own human progress backpressure and final write acknowledgements without ending borrowed stderr. Continue draining after destination failures and observe outstanding write rejections through their error event.

Validation: 152 checks across 12 focused files, followed by a 44-check rerun including two additional no-deadline waiter controls; typecheck/lint, docs and discovery pass. The public oversized-metadata regression fails on 4f7b5fb60. Fixtures execute owned Node/fake npm/Bun commands; no actual package install or registry request. Native Windows/Linux and exhausting-output/OOM scenarios were not run.

Small completed CLI checks return identical replies and token estimates. Six sequential baseline/candidate tasks separate first-process and two warm repeats; no speedup, true-cold or large-install memory claim. Existing descendant cleanup and signal behavior is outside this output-bound fix.

Closes #4888.
2026-10-18 05:57:57 +08:00
morluto 4f7b5fb602 fix(cli): route update flag through verified updater
Normalize the unambiguous root --update alias before output handling and
through direct createCli().serve calls. Reuse the existing output-value scan
and canonical update command, including selected environment, installation
ownership, Windows-aware launch, verification, maintenance and failure facts.
Retain option data and help/check precedence. Reject remaining Incur install
requests: update:false does not disable its explicit installer in0.6.1.
Remove the superseded output-only normalizer name and update its consumers.

Validation:123focused checks/7files pass, including compiled CLI with an owned
rejecting fake npm and direct serve across5formats. Original argument owner
fails6new controls/7pass; isolated baseline fails8workflow checks/2controls
pass. Static/docs/discovery1561 pass. Both scoped source reviews are clear.
Six completed equivalent current-version workflows compare baseline canonical
update with the alias; complete replies identical. Native Windows upgrade,
real package-manager installation and full install costs remain unverified.

The first baseline escaped a Vitest-only builtin mock and installed REA in the
pinned Node global prefix. Removed the newly added package and verified original
Node/npm/Corepack tools. Re-ran using the real builtin spy with synchronized
ESM exports, an independently rejecting PATH shim and owned npm prefix/cache.
Keep heavy tests/profiling stopped. Independent updater output bounds remain
tracked in #4888 rather than changing collection policy in this routing fix.

Fixes #4883
2026-10-18 05:33:21 +08:00
morluto c555caad65 fix(setup): resolve Hermes named-user homes before planning
Resolve the current named POSIX account through OS identity rather than the
caller-selected HOME/USERPROFILE. Preserve the home prefix for repeated
separators using the same joining semantics as the existing ~/ branch.
Require an absolute HERMES_HOME for unresolved names and Windows named forms
before exposing config or skill write destinations. Reuse the shared Hermes
path owner and existing diagnostics across setup, doctor, skills and uninstall.

Validation: 113 checks across seven files pass, including the compiled CLI
setup/doctor/skill/repeat/uninstall workflow over an owned profile beneath the
actual account home and a separate caller home. The isolated unchanged baseline
fails the five new checks and passes44existing checks; final repeated-separator
controls also fail that baseline. Static/docs/discovery1559 pass. Both source
reviewers clear after correcting repeated-separator composition.

Twelve completed setup dry runs compare normal and named overrides, with exact
normal-home replies unchanged. Measurements have source hashes and separate
first/warm runs; no speedup, full Hermes agent/model or native Windows/Linux
qualification claim. No provider software was installed; heavy tests/profiling
remain stopped.

Fixes #4841
2026-10-18 05:17:31 +08:00
hhang c43bc0bf66 fix(clients): preserve large TOML documents without argument spreads
Fixes #4856
2026-10-18 03:38:12 +08:00
Shivam Dwivedi c1fe0d653d fix(setup): recognize shared CLI launcher aliases (#4803) 2026-10-17 23:22:43 +08:00
morluto 9a95db6819 test(uninstall): verify current recovery snapshots through the CLI
Plan and approve Cursor setup in an isolated home, edit an unrelated server, then uninstall and verify both the historical backup and exact pre-uninstall recovery bytes. Related: #4581, PR #4580.

The new real CLI control fails on f9ccacca2 with a missing recovery file and passes with the recovery owner fix. Verified on macOS; native Windows/Linux runs remain unverified.
2026-10-17 05:01:57 +08:00