[PR #3513] fix(browser): keep an undecodable Electron worker target uncertain #5792

Open
opened 2026-10-31 01:09:28 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/3513
Author: @NIU-123370
Created: 10/14/2026
Status: 🔄 Open

Base: main ← Head: fix/worker-inventory-uncertainty


📝 Commits (2)

  • b49396d fix(browser): keep an undecodable Electron worker target uncertain
  • 6d1b0c5 test(browser): keep the Electron worker fixture URL escaped

📊 Changes

3 files changed (+224 additions, -14 deletions)

View changed files

➕ src/browser/CdpElectronWorkers.test.ts (+148 -0)
📝 src/browser/CdpElectronWorkers.ts (+23 -7)
📝 src/browser/CdpPageCaptureWorkers.test.ts (+53 -7)

📄 Description

Summary

Refs #3378.

This branch was dirty against main because the web producer's half of this fix
landed on main in
4cc044be
(morluto, co-authored with the #3850/#3901 authors) and is a superset of what this PR
first proposed: it already admits the target type before the non-worker filter. So
src/browser/CdpPageCaptureWorkers.ts is no longer touched here, and the PR now
carries the remaining producer plus the coverage that main does not have.

inspect-electron-page still answered workers: [] with no unavailable marker and no
exclusion whenever a delivered TargetInfo record could not be read as carrying a
type: src/browser/CdpElectronWorkers.ts decided it with
cdpStringValue(target.type) ?? "" and then !type.includes("worker") continue, so an
absent, null, numeric or empty discriminator became a definite negative. That is the
same unknown-to-empty collapse baron described for the web producer, at the second
producer, and the shape the reporter of #3378 could not distinguish from "no workers".

Problem and expected behavior

  • Trigger: Target.getTargets replies
    { targetInfos: [{ targetId: "worker-1", url: <file url>, openerId: "electron-page", attached: true }] }
    with no type, and the same record with type: null, type: 42, type: "".
  • Violated invariant: a discriminator this host could not decode cannot establish that
    the entry is not a worker, so the section cannot be reported as a complete empty
    inventory.
  • Expected now: each such entry is recorded in the invalid_protocol_value ledger for
    the workers section, a valid worker delivered after it still survives, a delivered
    empty array stays a valid empty result, and a decodable non-worker type (page)
    stays out of the malformed ledger. All four inventory shapes — missing, malformed,
    explicitly empty, valid — remain distinguishable, which is what #3378 and morluto's
    audit comment ask for at the producing CDP parser.

Change and scope

  • src/browser/CdpElectronWorkers.ts
    • admit the discriminator before the non-worker filter and count undecodable entries;
    • read the inventory through admitRecords, the owner 4cc044be added, instead of a
      private Array.isArray check;
    • the per-entry invalid_protocol_value writes for a non-record entry, a missing
      targetId and a non-boolean attached are aggregated into one counted write at the
      end, mirroring the web producer's ledger. Observably the same ledger:
      CdpCaptureCompleteness.exclude sums counts per (section, reason) and
      canonicalExclusions orders by (section, reason), so neither the entry, its
      count, nor its position changes. Arm E2 vs E1 below isolates exactly that.
  • src/browser/CdpElectronWorkers.test.ts (new, 10 cases) — the same altitude as main's
    own CdpPageCaptureWorkers.test.ts: valid-empty control, missing/non-array
    inventory, the four undecodable discriminator shapes, the decodable non-worker
    control, and malformed entries beside a valid survivor.
  • src/browser/CdpPageCaptureWorkers.test.ts (+5 cases) — the four discriminator shapes
    plus the non-worker control for the web producer. 4cc044be implements that guard
    and nothing in the repository pins it; arms W1/W3 show these five cases are precisely
    what fails if the guard is removed.
  • Intentionally not included: tests/boundary/browser/cdpElectronProvider.test.ts
    already carries an inventory-level Electron table
    (["workers", "Target.getTargets", () => ({ targetInfos: null })]) and the per-entry
    discriminator belongs next to it. I left that file alone because #4040 and #4529 are
    open on it; the successor is one row in that table plus the same four shapes, once
    those lanes land. No new TargetInfo literal was added anywhere: each producer's file
    keeps one builder and the four arms feed through it.

Contract and boundary impact

  • Semantic owner and earliest changed stage: CdpCaptureCompleteness remains the only
    completeness owner and admitRecords the only inventory-admission owner; the earliest
    changed stage is Electron worker inventory decoding.
  • Contribution scope fit and linked maintainer decision: ordinary fix inside an existing
    boundary, and it follows the single-owner direction in morluto's 2026-10-15 comment
    rather than starting a parallel repair.
  • CLI and MCP/tool-catalog contract: no schema, flag or description change.
    inspect-electron-page now reports unavailable_sections: ["workers"] plus an
    invalid_protocol_value exclusion for a reply it previously reported as a clean empty
    inventory.
  • Provider, bridge, target-format, or platform compatibility: CDP Electron inventory
    decoding only; no provider or platform gate touched.
  • Evidence, artifact, provenance, or reconstruction contract: comparisons that treated
    two such Electron captures as equal on workers now see the uncertainty. No retained
    field is renamed or removed.
  • Target selection, authority, side effects, and cleanup details: unchanged — still
    exactly one Target.getTargets call, no new command, no attach.
  • Generated metadata (docs/public/product-catalog.json), package, or installation
    impact: none.

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

Base reproduction, measured: running the new Electron file with only
src/browser/CdpElectronWorkers.ts replaced by the origin/main version gives
5 failed | 5 passed (10) (arm E1). Reverting only the discriminator admission while
keeping the ledger aggregation gives the identical set (arm E2), which is the direct
evidence that the aggregation changes nothing observable and that the discriminator is
the only behavior this PR alters at that producer.

Mutation arms, each actually run against the final two test files, tree restored and
re-verified between arms (every arm was re-run once more after the review revision
6d1b0c5f, same results):

arm producer mutation observed killed by
C web none (control) 9 passed (9) —
W1 web main's guard collapsed to ?? "" 4 failed | 5 passed (9) the four discriminator cases
W2 web empty string treated as decodable 1 failed | 8 passed (9) the empty case
W3 web guard kept, ledger write removed 4 failed | 5 passed (9) the four discriminator cases
C electron none (control) 10 passed (10) —
E1 electron the origin/main producer (base defect) 5 failed | 5 passed (10) four discriminator cases + mixed-entry
E2 electron discriminator reverted, aggregation kept 5 failed | 5 passed (10) the same five
E3 electron empty string accepted as decodable 1 failed | 9 passed (10) the empty case
E4 electron over-broad: a decodable non-worker is malformed too 1 failed | 9 passed (10) the non-worker control
E5 electron non-record entries dropped from the ledger 1 failed | 9 passed (10) mixed-entry
E6 electron a malformed entry abandons the inventory 6 failed | 4 passed (10) mixed-entry, four discriminator cases, control
E7 electron malformed count collapsed into a section-level null 5 failed | 5 passed (10) four discriminator cases + mixed-entry
E8 electron admitRecords replaced by an inline Array.isArray 10 passed (10) nothing — equivalent mutation
E9 electron required targetId/attached guards stop counting 1 failed | 9 passed (10) mixed-entry
E10 electron missing/non-array inventory no longer stops the read 3 failed | 7 passed (10) the three inventory-table cases
E11 electron non-array reported as provider_unavailable instead 3 failed | 7 passed (10) the three inventory-table cases

E8 is recorded as an equivalent mutation, not hidden: admitRecords is literally
that predicate, so adopting the owner is an ownership change and not a behavior change.
The inventory-level behavior it shares is pinned by E10/E11 instead, each of which kills
the three inventory-table cases on its own.

Review revision 6d1b0c5f, taken after the Greptile [P2] on head b49396d5: the
fixture built its URL as file://${fileURLToPath(import.meta.url)}, which discards
percent-encoding. Measured rather than argued — for a real file at
<tmp>/…/p%25x/w#e/worker.js, authorizedElectronFile returns undefined for the
re-prefixed string and the resolved path for pathToFileURL(...).href, so on such a
checkout the valid-worker fixtures would have degraded into out_of_target_scope and
the survivor cases would fail. import.meta.url is already the escaped form. A
#-only checkout cannot be used as the experiment because vitest's own module
resolution fails there first (Cannot find module), which is why the probe pins the
authorizer directly instead of the whole file.

Remaining proof gaps: the malformed replies are delivered through a stubbed
CdpConnection at unit altitude, matching how main's own CdpPageCaptureWorkers.test.ts
works; no real Electron app or live Chrome was made to send an undecodable type, and
the Electron boundary lane (verify:electron) was not run. #3378's web symptom is
already fixed on main (4cc044be refs #3376/#3379/#3850 but not #3378); after this lands
both producers keep the four inventory states apart and the issue can be closed against
the two.

Validation performed

Node 24.18.0, base 5120eb44 (main advanced to 060eb43b5 while the branch was being
rebased; mergeable = true at push time).

  • npx vitest run src/browser/CdpElectronWorkers.test.ts src/browser/CdpPageCaptureWorkers.test.ts
    → Test Files 2 passed (2), Tests 19 passed (19).
  • npx vitest run src/browser/ on this head → 38 files / 571 passed; the same command
    on an unmodified origin/main tree → 37 files / 556 passed. The delta is exactly
    this PR's one new file and 15 new cases, with 0 failures on either side.
  • npx vitest run tests/boundary/browser/ on this head → 52 passed | 1 skipped (53 files),
    666 passed | 6 skipped (672); identical counts on the unmodified trunk tree ⇒ net
    regression 0 in that lane.
  • npm run typecheck exit 0 · npm run lint exit 0
    (Checked resolved module boundaries in 2036 source files., and 0 diagnostics naming
    either changed file) · ./node_modules/.bin/oxfmt --check on the three files →
    All matched files use the correct format. · git diff --check clean.
  • npm run verify:test-discovery → Discovered all 1511 test files exactly once. ·
    npm run verify:architecture-guards → Architecture guards passed across 1483 source files.
  • npm run jscpd, one tree with only these three files swapped: trunk 5120eb44 =
    2472 clones / 25610 duplicated lines / 3.3443% (3041 files); this head =
    2478 / 25674 / 3.3518% (3042 files). Not clone-neutral: the patch adds 6 clone
    groups and 64 duplicated lines (+0.0074 pp against the 3.5% ceiling). The growth is a
    second producer's test file mirroring main's brand-new web-producer test file; I did
    not fold the two harnesses into one shared fixture because that would mean editing the
    file main landed two days ago, and I would rather ask than presume.
  • Not run: verify:electron and any real Electron/Chrome runtime, check:ci, other
    platforms. npm run build was run only because the boundary lane needs dist/.

Compatibility, safety, and release

  • Breaking changes or migration steps: none in schema. A caller that relied on a silent
    empty workers array for an Electron reply with an undecodable target type now sees
    the uncertainty, which is the reported defect.
  • Real Hopper/Ghidra, browser, or OS coverage: none required for this decoding fix; all
    evidence is protocol-level through the repository's own stubs.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: no new CDP command, no new origin
    scope, no new retained content; malformed protocol data is disclosed rather than
    interpreted.

Author readiness

Human owner: @NIU-123370

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/3513 **Author:** [@NIU-123370](https://github.com/NIU-123370) **Created:** 10/14/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/worker-inventory-uncertainty` --- ### 📝 Commits (2) - [`b49396d`](https://github.com/morluto/rea/commit/b49396d582857c318b920417ce0571920901d3e5) fix(browser): keep an undecodable Electron worker target uncertain - [`6d1b0c5`](https://github.com/morluto/rea/commit/6d1b0c5f0de4c4dc3dbf0f1f8ad6e3a9a8f4ece1) test(browser): keep the Electron worker fixture URL escaped ### 📊 Changes **3 files changed** (+224 additions, -14 deletions) <details> <summary>View changed files</summary> ➕ `src/browser/CdpElectronWorkers.test.ts` (+148 -0) 📝 `src/browser/CdpElectronWorkers.ts` (+23 -7) 📝 `src/browser/CdpPageCaptureWorkers.test.ts` (+53 -7) </details> ### 📄 Description ## Summary Refs #3378. This branch was `dirty` against main because the web producer's half of this fix landed on main in [`4cc044be`](https://github.com/morluto/rea/commit/4cc044be68f813e96907e6cedcf422d0a3170de3) (morluto, co-authored with the #3850/#3901 authors) and is a superset of what this PR first proposed: it already admits the target type before the non-worker filter. So `src/browser/CdpPageCaptureWorkers.ts` is no longer touched here, and the PR now carries the remaining producer plus the coverage that main does not have. `inspect-electron-page` still answered `workers: []` with no unavailable marker and no exclusion whenever a delivered `TargetInfo` record could not be read as carrying a type: `src/browser/CdpElectronWorkers.ts` decided it with `cdpStringValue(target.type) ?? ""` and then `!type.includes("worker") continue`, so an absent, `null`, numeric or empty discriminator became a definite negative. That is the same unknown-to-empty collapse baron described for the web producer, at the second producer, and the shape the reporter of #3378 could not distinguish from "no workers". ## Problem and expected behavior - Trigger: `Target.getTargets` replies `{ targetInfos: [{ targetId: "worker-1", url: <file url>, openerId: "electron-page", attached: true }] }` with no `type`, and the same record with `type: null`, `type: 42`, `type: ""`. - Violated invariant: a discriminator this host could not decode cannot establish that the entry is not a worker, so the section cannot be reported as a complete empty inventory. - Expected now: each such entry is recorded in the `invalid_protocol_value` ledger for the `workers` section, a valid worker delivered after it still survives, a delivered empty array stays a valid empty result, and a **decodable** non-worker type (`page`) stays out of the malformed ledger. All four inventory shapes — missing, malformed, explicitly empty, valid — remain distinguishable, which is what #3378 and morluto's audit comment ask for at the producing CDP parser. ## Change and scope - `src/browser/CdpElectronWorkers.ts` - admit the discriminator before the non-worker filter and count undecodable entries; - read the inventory through `admitRecords`, the owner `4cc044be` added, instead of a private `Array.isArray` check; - the per-entry `invalid_protocol_value` writes for a non-record entry, a missing `targetId` and a non-boolean `attached` are aggregated into one counted write at the end, mirroring the web producer's ledger. Observably the same ledger: `CdpCaptureCompleteness.exclude` sums counts per `(section, reason)` and `canonicalExclusions` orders by `(section, reason)`, so neither the entry, its count, nor its position changes. Arm E2 vs E1 below isolates exactly that. - `src/browser/CdpElectronWorkers.test.ts` (new, 10 cases) — the same altitude as main's own `CdpPageCaptureWorkers.test.ts`: valid-empty control, missing/non-array inventory, the four undecodable discriminator shapes, the decodable non-worker control, and malformed entries beside a valid survivor. - `src/browser/CdpPageCaptureWorkers.test.ts` (+5 cases) — the four discriminator shapes plus the non-worker control for the **web** producer. `4cc044be` implements that guard and nothing in the repository pins it; arms W1/W3 show these five cases are precisely what fails if the guard is removed. - Intentionally not included: `tests/boundary/browser/cdpElectronProvider.test.ts` already carries an inventory-level Electron table (`["workers", "Target.getTargets", () => ({ targetInfos: null })]`) and the per-entry discriminator belongs next to it. I left that file alone because #4040 and #4529 are open on it; the successor is one row in that table plus the same four shapes, once those lanes land. No new `TargetInfo` literal was added anywhere: each producer's file keeps one builder and the four arms feed through it. ## Contract and boundary impact - Semantic owner and earliest changed stage: `CdpCaptureCompleteness` remains the only completeness owner and `admitRecords` the only inventory-admission owner; the earliest changed stage is Electron worker inventory decoding. - Contribution scope fit and linked maintainer decision: ordinary fix inside an existing boundary, and it follows the single-owner direction in morluto's 2026-10-15 comment rather than starting a parallel repair. - CLI and MCP/tool-catalog contract: no schema, flag or description change. `inspect-electron-page` now reports `unavailable_sections: ["workers"]` plus an `invalid_protocol_value` exclusion for a reply it previously reported as a clean empty inventory. - Provider, bridge, target-format, or platform compatibility: CDP Electron inventory decoding only; no provider or platform gate touched. - Evidence, artifact, provenance, or reconstruction contract: comparisons that treated two such Electron captures as equal on `workers` now see the uncertainty. No retained field is renamed or removed. - Target selection, authority, side effects, and cleanup details: unchanged — still exactly one `Target.getTargets` call, no new command, no attach. - Generated metadata (`docs/public/product-catalog.json`), package, or installation impact: none. Expected effects: - [x] Read existing files or captured data. - [ ] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage Base reproduction, measured: running the new Electron file with only `src/browser/CdpElectronWorkers.ts` replaced by the `origin/main` version gives `5 failed | 5 passed (10)` (arm E1). Reverting only the discriminator admission while keeping the ledger aggregation gives the identical set (arm E2), which is the direct evidence that the aggregation changes nothing observable and that the discriminator is the only behavior this PR alters at that producer. Mutation arms, each actually run against the final two test files, tree restored and re-verified between arms (every arm was re-run once more after the review revision `6d1b0c5f`, same results): | arm | producer | mutation | observed | killed by | | --- | --- | --- | --- | --- | | C | web | none (control) | `9 passed (9)` | — | | W1 | web | main's guard collapsed to `?? ""` | `4 failed \| 5 passed (9)` | the four discriminator cases | | W2 | web | empty string treated as decodable | `1 failed \| 8 passed (9)` | the empty case | | W3 | web | guard kept, ledger write removed | `4 failed \| 5 passed (9)` | the four discriminator cases | | C | electron | none (control) | `10 passed (10)` | — | | E1 | electron | the `origin/main` producer (base defect) | `5 failed \| 5 passed (10)` | four discriminator cases + mixed-entry | | E2 | electron | discriminator reverted, aggregation kept | `5 failed \| 5 passed (10)` | the same five | | E3 | electron | empty string accepted as decodable | `1 failed \| 9 passed (10)` | the empty case | | E4 | electron | over-broad: a decodable non-worker is malformed too | `1 failed \| 9 passed (10)` | the non-worker control | | E5 | electron | non-record entries dropped from the ledger | `1 failed \| 9 passed (10)` | mixed-entry | | E6 | electron | a malformed entry abandons the inventory | `6 failed \| 4 passed (10)` | mixed-entry, four discriminator cases, control | | E7 | electron | malformed count collapsed into a section-level `null` | `5 failed \| 5 passed (10)` | four discriminator cases + mixed-entry | | E8 | electron | `admitRecords` replaced by an inline `Array.isArray` | `10 passed (10)` | **nothing — equivalent mutation** | | E9 | electron | required `targetId`/`attached` guards stop counting | `1 failed \| 9 passed (10)` | mixed-entry | | E10 | electron | missing/non-array inventory no longer stops the read | `3 failed \| 7 passed (10)` | the three inventory-table cases | | E11 | electron | non-array reported as `provider_unavailable` instead | `3 failed \| 7 passed (10)` | the three inventory-table cases | E8 is recorded as an **equivalent mutation**, not hidden: `admitRecords` is literally that predicate, so adopting the owner is an ownership change and not a behavior change. The inventory-level behavior it shares is pinned by E10/E11 instead, each of which kills the three inventory-table cases on its own. Review revision `6d1b0c5f`, taken after the Greptile [P2] on head `b49396d5`: the fixture built its URL as `file://${fileURLToPath(import.meta.url)}`, which discards percent-encoding. Measured rather than argued — for a real file at `<tmp>/…/p%25x/w#e/worker.js`, `authorizedElectronFile` returns `undefined` for the re-prefixed string and the resolved path for `pathToFileURL(...).href`, so on such a checkout the valid-worker fixtures would have degraded into `out_of_target_scope` and the survivor cases would fail. `import.meta.url` is already the escaped form. A `#`-only checkout cannot be used as the experiment because vitest's own module resolution fails there first (`Cannot find module`), which is why the probe pins the authorizer directly instead of the whole file. Remaining proof gaps: the malformed replies are delivered through a stubbed `CdpConnection` at unit altitude, matching how main's own `CdpPageCaptureWorkers.test.ts` works; no real Electron app or live Chrome was made to send an undecodable `type`, and the Electron boundary lane (`verify:electron`) was not run. #3378's web symptom is already fixed on main (`4cc044be` refs #3376/#3379/#3850 but not #3378); after this lands both producers keep the four inventory states apart and the issue can be closed against the two. ## Validation performed Node 24.18.0, base `5120eb44` (main advanced to `060eb43b5` while the branch was being rebased; `mergeable = true` at push time). - `npx vitest run src/browser/CdpElectronWorkers.test.ts src/browser/CdpPageCaptureWorkers.test.ts` → `Test Files 2 passed (2)`, `Tests 19 passed (19)`. - `npx vitest run src/browser/` on this head → `38 files / 571 passed`; the same command on an unmodified `origin/main` tree → `37 files / 556 passed`. The delta is exactly this PR's one new file and 15 new cases, with 0 failures on either side. - `npx vitest run tests/boundary/browser/` on this head → `52 passed | 1 skipped (53 files)`, `666 passed | 6 skipped (672)`; identical counts on the unmodified trunk tree ⇒ net regression 0 in that lane. - `npm run typecheck` exit 0 · `npm run lint` exit 0 (`Checked resolved module boundaries in 2036 source files.`, and 0 diagnostics naming either changed file) · `./node_modules/.bin/oxfmt --check` on the three files → `All matched files use the correct format.` · `git diff --check` clean. - `npm run verify:test-discovery` → `Discovered all 1511 test files exactly once.` · `npm run verify:architecture-guards` → `Architecture guards passed across 1483 source files.` - `npm run jscpd`, one tree with only these three files swapped: trunk `5120eb44` = `2472 clones / 25610 duplicated lines / 3.3443%` (3041 files); this head = `2478 / 25674 / 3.3518%` (3042 files). **Not clone-neutral:** the patch adds 6 clone groups and 64 duplicated lines (+0.0074 pp against the 3.5% ceiling). The growth is a second producer's test file mirroring main's brand-new web-producer test file; I did not fold the two harnesses into one shared fixture because that would mean editing the file main landed two days ago, and I would rather ask than presume. - Not run: `verify:electron` and any real Electron/Chrome runtime, `check:ci`, other platforms. `npm run build` was run only because the boundary lane needs `dist/`. ## Compatibility, safety, and release - Breaking changes or migration steps: none in schema. A caller that relied on a silent empty `workers` array for an Electron reply with an undecodable target type now sees the uncertainty, which is the reported defect. - Real Hopper/Ghidra, browser, or OS coverage: none required for this decoding fix; all evidence is protocol-level through the repository's own stubs. - Package or release metadata impact: none. - Security, privacy, process, or containment review: no new CDP command, no new origin scope, no new retained content; malformed protocol data is disclosed rather than interpreted. ## Author readiness Human owner: @NIU-123370 - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [ ] This PR addresses a concrete problem or an agreed enhancement. - [ ] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [ ] The PR has one focused outcome and the title follows `type(scope): outcome`. - [ ] Related issue is linked, or the reason for not linking one is stated above. - [ ] Tests cover changed observable behavior and meaningful failure paths. - [ ] Owning docs, contracts, and generated metadata are updated where needed. - [ ] User-visible CLI/MCP changes include representative output. - [ ] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
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#5792
No description provided.