[GH-ISSUE #6519] [Bug] Update maintenance reports current after dropping an unresolved client registration #3911

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

Originally created by @coygeek on GitHub (Oct 23, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/6519

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Setup, packaging, or upgrade

Observed behavior

Executed the production registration reader and update-maintenance planner against an isolated Claude Code configuration whose rea launcher names a missing absolute path. Registration inspection correctly returned state: "unknown", the configured command, and recovery guidance. planIntegrationMaintenance then returned only {"status":"current","plannedActions":[]}, exactly as it did for an empty home.

This is a production-function reproduction, not an executed rea update. No package installation, setup execution, native client session, or provider run was performed. The connection to the public update result is source-derived below.

Reproduction

One initial probe ran with the locked dependencies and Node 24.18.0. Its operations were:

  1. Create two disposable homes, empty and missing-launcher, and run from inside each. Supply an environment containing only that home, USERPROFILE, the real Node directory plus system directories in PATH, and an isolated npm_config_prefix. All inherited client/provider overrides were absent. Neither home contains a skill.

  2. Leave the first home empty. In the second, write .claude.json containing the following, replacing /tmp/rea-trial with the disposable home and leaving the launcher absent:

    {"mcpServers":{"rea":{"command":"/tmp/rea-trial/missing-rea.mjs","args":["mcp"]}}}
    
  3. Import readClientRegistrationInspections from src/application/ClientRegistrationStatus.ts and planIntegrationMaintenance from src/application/UpdateMaintenance.ts through the checkout's tsx loader. Set entryPoint to the checkout's existing absolute scripts/rea.mjs path. Execute:

    const inspections = await readClientRegistrationInspections(
      home, entryPoint, { environment },
    );
    let executeCalls = 0;
    const maintenance = await planIntegrationMaintenance(
      home, entryPoint, environment,
      async () => { executeCalls++; throw new Error("Must not execute setup"); },
    );
    
  4. Record both results and compare .claude.json with its original bytes. Both cases returned current; only the second had an unknown inspection. executeCalls remained zero and the configuration was unchanged. Each case ran once; fixtures were then removed.

Expected behavior

Maintenance should retain the unresolved registration and its diagnostic without admitting it for mutation. A result such as unavailable, or an explicitly partial result with the skipped diagnostic, would preserve the distinction from an empty/current installation.

The repository's ownership contract requires consumers to preserve uncertainty and says unresolved identity must not become absent or aligned. The maintenance guide describes a scoped plan for existing integrations; preserving a diagnostic does not require changing its ownership restriction.

Impact and scope

The observed planner suppresses actionable recovery information for an enabled registration with an unresolved launcher. Source-derived impact: after a verified package upgrade, the public update result includes this current result and gives only restart guidance, leaving the unresolved integration unexplained. This does not invalidate the verified package-version update itself.

No configuration mutation or data loss occurred. Scope established here is one missing-launcher Claude Code fixture on Linux and an empty-home control. Production frequency, other clients/platforms, and invalid/unreadable configurations were not tested. Running a separately scoped doctor check and repairing the selected launcher is a proposed workaround; that public recovery flow was not executed.

REA version

Source revision e073f64be0a5a30c32d8b3cec23f9bd411080903, main; package metadata 6.7.0. Findings concern this revision, not a separately reproduced npm release.

Runtime and platform

Node.js v24.18.0; Linux x64, kernel 7.2.8-9-omarchy; repository-locked dependencies loaded with tsx. No Hopper, Ghidra, or native agent client was invoked.

Target and artifact context

Disposable Claude Code .claude.json with one enabled stdio rea registration, an absent launcher, and no installed skill. No analysis target.

Interface

Package or setup

Earliest failure stage

Setup or provider admission

Relevant output or evidence

Trimmed initial probe output, with fixture paths normalized:

{
  "name": "missing-launcher",
  "inspections": [{
    "status": {
      "client": "claude_code",
      "command": ["/tmp/rea-trial/missing-rea.mjs", "mcp"],
      "state": "unknown",
      "remediation": "The existing registration was retained because its executable identity cannot be verified. Check the registered launcher path, symlink targets and access permissions. Run the installed REA CLI or a supported package runner, then rerun rea doctor; no registration was changed."
    },
    "activation": "enabled"
  }],
  "maintenance": {"status":"current","plannedActions":[]},
  "executeCalls": 0,
  "configurationUnchanged": true
}

The empty-home control had inspections: [] and the same maintenance result. These observations establish the production planner's loss of diagnostics. An actual global-package upgrade and its CLI output remain unexecuted.

Typed outcome or recovery expected

Retain the client, configured command, unknown state, and recovery guidance in maintenance output. Keep the registration out of automatic writes until ownership is established.

Analysis or suspected cause

Source-derived: the registration reader preserves unknown, but maintenance filters it out without retaining diagnostics. An empty eligible scope becomes current. The updater publishes that result with restart-only guidance.

Additional context

Searched GitHub issues with repo:morluto/rea is:issue, each of is:open and is:closed, and each query pair: "update" "unknown", "maintenance" "current", "UpdateMaintenance", and "maintenance" "registration". Also compared the supplied open-issue inventory. No exact report of this consumer-side diagnostic loss was found.

Closest matches: closed #4895 fixes the classifier returning foreign instead of unknown; closed #4905 fixes discovery omitting unreadable targets. This probe receives the correctly preserved unknown result and loses it in maintenance. Open #3862 concerns erroneous Codex per-tool-table rejection; this valid Claude Code fixture has no such table. Open #3556 concerns optional Frida binding readiness after updating, not client-registration diagnostics.

AI-assisted source review and one initial production-function probe. No post-draft reproduction or independent re-verification was performed.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: The executed maintenance planner reports current while discarding an observed unresolved registration and its recovery guidance. This is a bounded diagnostic failure; no data loss or mutation was observed. Public upgrade behavior is source-derived.
  • Workaround status: unverified
  • Workaround basis: The registration reader demonstrably retains the diagnostic, and a separate scoped doctor check followed by launcher repair is a plausible recovery path, but that public workflow was not executed.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6519 ## Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ## Area Setup, packaging, or upgrade ## Observed behavior Executed the production registration reader and update-maintenance planner against an isolated Claude Code configuration whose `rea` launcher names a missing absolute path. Registration inspection correctly returned `state: "unknown"`, the configured command, and recovery guidance. `planIntegrationMaintenance` then returned only `{"status":"current","plannedActions":[]}`, exactly as it did for an empty home. This is a production-function reproduction, not an executed `rea update`. No package installation, setup execution, native client session, or provider run was performed. The connection to the public update result is source-derived below. ## Reproduction One initial probe ran with the locked dependencies and Node 24.18.0. Its operations were: 1. Create two disposable homes, `empty` and `missing-launcher`, and run from inside each. Supply an environment containing only that home, `USERPROFILE`, the real Node directory plus system directories in `PATH`, and an isolated `npm_config_prefix`. All inherited client/provider overrides were absent. Neither home contains a skill. 2. Leave the first home empty. In the second, write `.claude.json` containing the following, replacing `/tmp/rea-trial` with the disposable home and leaving the launcher absent: ```json {"mcpServers":{"rea":{"command":"/tmp/rea-trial/missing-rea.mjs","args":["mcp"]}}} ``` 3. Import `readClientRegistrationInspections` from `src/application/ClientRegistrationStatus.ts` and `planIntegrationMaintenance` from `src/application/UpdateMaintenance.ts` through the checkout's `tsx` loader. Set `entryPoint` to the checkout's existing absolute `scripts/rea.mjs` path. Execute: ```js const inspections = await readClientRegistrationInspections( home, entryPoint, { environment }, ); let executeCalls = 0; const maintenance = await planIntegrationMaintenance( home, entryPoint, environment, async () => { executeCalls++; throw new Error("Must not execute setup"); }, ); ``` 4. Record both results and compare `.claude.json` with its original bytes. Both cases returned `current`; only the second had an `unknown` inspection. `executeCalls` remained zero and the configuration was unchanged. Each case ran once; fixtures were then removed. ## Expected behavior Maintenance should retain the unresolved registration and its diagnostic without admitting it for mutation. A result such as `unavailable`, or an explicitly partial result with the skipped diagnostic, would preserve the distinction from an empty/current installation. The repository's [ownership contract](https://github.com/morluto/rea/blob/e073f64be0a5a30c32d8b3cec23f9bd411080903/AGENTS.md#L19-L21) requires consumers to preserve uncertainty and says unresolved identity must not become absent or aligned. The [maintenance guide](https://github.com/morluto/rea/blob/e073f64be0a5a30c32d8b3cec23f9bd411080903/docs/installation.md#L481-L484) describes a scoped plan for existing integrations; preserving a diagnostic does not require changing its ownership restriction. ## Impact and scope The observed planner suppresses actionable recovery information for an enabled registration with an unresolved launcher. Source-derived impact: after a verified package upgrade, the public update result includes this `current` result and gives only restart guidance, leaving the unresolved integration unexplained. This does not invalidate the verified package-version update itself. No configuration mutation or data loss occurred. Scope established here is one missing-launcher Claude Code fixture on Linux and an empty-home control. Production frequency, other clients/platforms, and invalid/unreadable configurations were not tested. Running a separately scoped doctor check and repairing the selected launcher is a proposed workaround; that public recovery flow was not executed. ## REA version Source revision `e073f64be0a5a30c32d8b3cec23f9bd411080903`, main; package metadata `6.7.0`. Findings concern this revision, not a separately reproduced npm release. ## Runtime and platform Node.js `v24.18.0`; Linux x64, kernel `7.2.8-9-omarchy`; repository-locked dependencies loaded with `tsx`. No Hopper, Ghidra, or native agent client was invoked. ## Target and artifact context Disposable Claude Code `.claude.json` with one enabled stdio `rea` registration, an absent launcher, and no installed skill. No analysis target. ## Interface Package or setup ## Earliest failure stage Setup or provider admission ## Relevant output or evidence Trimmed initial probe output, with fixture paths normalized: ```json { "name": "missing-launcher", "inspections": [{ "status": { "client": "claude_code", "command": ["/tmp/rea-trial/missing-rea.mjs", "mcp"], "state": "unknown", "remediation": "The existing registration was retained because its executable identity cannot be verified. Check the registered launcher path, symlink targets and access permissions. Run the installed REA CLI or a supported package runner, then rerun rea doctor; no registration was changed." }, "activation": "enabled" }], "maintenance": {"status":"current","plannedActions":[]}, "executeCalls": 0, "configurationUnchanged": true } ``` The empty-home control had `inspections: []` and the same maintenance result. These observations establish the production planner's loss of diagnostics. An actual global-package upgrade and its CLI output remain unexecuted. ## Typed outcome or recovery expected Retain the client, configured command, `unknown` state, and recovery guidance in maintenance output. Keep the registration out of automatic writes until ownership is established. ## Analysis or suspected cause Source-derived: [the registration reader preserves `unknown`](https://github.com/morluto/rea/blob/e073f64be0a5a30c32d8b3cec23f9bd411080903/src/application/ClientRegistrationStatus.ts#L308-L337), but [maintenance filters it out without retaining diagnostics](https://github.com/morluto/rea/blob/e073f64be0a5a30c32d8b3cec23f9bd411080903/src/application/UpdateMaintenance.ts#L65-L84). [An empty eligible scope becomes `current`](https://github.com/morluto/rea/blob/e073f64be0a5a30c32d8b3cec23f9bd411080903/src/application/UpdateMaintenance.ts#L97-L105). [The updater publishes that result with restart-only guidance](https://github.com/morluto/rea/blob/e073f64be0a5a30c32d8b3cec23f9bd411080903/src/application/Update.ts#L230-L244). ## Additional context Searched GitHub issues with `repo:morluto/rea is:issue`, each of `is:open` and `is:closed`, and each query pair: `"update" "unknown"`, `"maintenance" "current"`, `"UpdateMaintenance"`, and `"maintenance" "registration"`. Also compared the supplied open-issue inventory. No exact report of this consumer-side diagnostic loss was found. Closest matches: closed [#4895](https://github.com/morluto/rea/issues/4895) fixes the classifier returning `foreign` instead of `unknown`; closed [#4905](https://github.com/morluto/rea/issues/4905) fixes discovery omitting unreadable targets. This probe receives the correctly preserved `unknown` result and loses it in maintenance. Open [#3862](https://github.com/morluto/rea/issues/3862) concerns erroneous Codex per-tool-table rejection; this valid Claude Code fixture has no such table. Open [#3556](https://github.com/morluto/rea/issues/3556) concerns optional Frida binding readiness after updating, not client-registration diagnostics. AI-assisted source review and one initial production-function probe. No post-draft reproduction or independent re-verification was performed. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: The executed maintenance planner reports current while discarding an observed unresolved registration and its recovery guidance. This is a bounded diagnostic failure; no data loss or mutation was observed. Public upgrade behavior is source-derived. - Workaround status: unverified - Workaround basis: The registration reader demonstrably retains the diagnostic, and a separate scoped doctor check followed by launcher repair is a plausible recovery path, but that public workflow was not executed.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3911
No description provided.