[GH-ISSUE #5459] [Bug] Analysis-view projection budget refusals recommend increasing worker memory #3318

Closed
opened 2026-10-31 00:39:06 +00:00 by bsakaguchi · 1 comment
Owner

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

Before submitting

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

Area

CLI

Observed behavior

After a successful HAR inspection, inspect-analysis-view correctly refuses API-surface, environment-manifest and environment-state projections above their fixed representation budget, but its recovery action recommends sufficient worker/host memory. That advice cannot raise the fixed projection allowance for an unchanged request.

Reproduction

An independent verifier ran this script end to end from the baseline source checkout with dependencies and the built runtime prepared. It generates a local 3000-record HAR, isolates configuration, and runs only local inspection commands.

python3 - <<'PY'
import datetime, json, os, pathlib, subprocess, tempfile
work = pathlib.Path(tempfile.mkdtemp(prefix="rea-projection-check-"))
env = {k: v for k, v in os.environ.items() if not k.startswith("REA_")}
for key, name in [("HOME", "home"), ("XDG_CONFIG_HOME", "config"),
                  ("XDG_DATA_HOME", "data"), ("XDG_CACHE_HOME", "cache"),
                  ("XDG_STATE_HOME", "state")]:
    folder = work / name
    folder.mkdir()
    env[key] = str(folder)
entries = []
for i in range(3000):
    entries.append({
        "startedDateTime": datetime.datetime.now(datetime.timezone.utc).isoformat(),
        "time": 1.0,
        "request": {"method": "GET",
                    "url": f"https://api.example.test/resource/{i}/detail?x={i}",
                    "httpVersion": "HTTP/1.1", "cookies": [], "headers": [],
                    "queryString": [], "headersSize": -1, "bodySize": 0},
        "response": {"status": 200, "statusText": "OK",
                     "httpVersion": "HTTP/1.1", "cookies": [], "headers": [],
                     "content": {"size": 2, "mimeType": "application/json", "text": "{}"},
                     "redirectURL": "", "headersSize": -1, "bodySize": 2},
        "cache": {}, "timings": {"send": 0, "wait": 1.0, "receive": 0}})
capture = work / "capture.har"
capture.write_text(json.dumps({"log": {"version": "1.2",
    "creator": {"name": "fixture", "version": "1"}, "entries": entries}}))
def run(label, arguments):
    result = subprocess.run(["node", "scripts/rea.mjs", *arguments, "--format", "json"],
                            env=env, capture_output=True, text=True, timeout=60)
    (work / (label + ".json")).write_text(result.stdout)
    (work / (label + ".stderr")).write_text(result.stderr)
    value = json.loads(result.stdout)
    print(json.dumps({"case": label, "exit": result.returncode,
                      "code": value.get("code"), "message": value.get("message"),
                      "details": value.get("details"), "remediation": value.get("remediation")}))
    return value
parent = run("capture", ["inspect-web-network-capture", str(capture), "har"])
for kind in ["api-surface", "environment-manifest", "environment-state"]:
    view = {"kind": kind}
    if kind == "api-surface":
        view.update(offset=0, limit=10)
    request = work / (kind + "-request.json")
    request.write_text(json.dumps({"source": {"kind": "inline", "evidence": parent},
                                  "view": view}))
    run(kind, ["inspect-analysis-view", str(request)])
subset = run("subset", ["inspect-web-network-capture", str(capture), "har",
    *[argument for i in range(50) for argument in ["--record", str(i)]]])
request = work / "subset-request.json"
request.write_text(json.dumps({"source": {"kind": "inline", "evidence": subset},
    "view": {"kind": "api-surface", "offset": 0, "limit": 10}}))
result = run("subset-view", ["inspect-analysis-view", str(request)])
print(json.dumps({"subset_records": result["normalized_result"]["records"],
                  "groups": len(result["normalized_result"]["groups"])}))
PY

The full capture inspection succeeds. Each full-capture projection exits 1 with the refusal below. Only API-surface supports the pagination fields used here. The 50-record subset and its API-surface view both succeed. Additional executed controls used API-surface limit 1 and evidence-file sources for all three views; each still returned the same projection-budget refusal for this fixture.

Expected behavior

Keep refusing excess projection representation cost without a partial view, but describe the fixed 96 MiB allowance and give recovery advice that applies to it. Increasing worker/host memory alone cannot change this allowance.

docs/web-network-captures.md:371-394 defines the accounting and distinguishes it from actual V8/process memory, decoder replies and MCP transport admission. Lines 490-500 and 590-598 apply the accounting to manifest and state views. This expectation is grounded in those documented distinctions. Preserve appropriate guidance for genuine process-memory exhaustion.

Impact and scope

P3 wording defect. All three schema-correct CLI requests reproduced the same misleading recovery advice. The intentional refusal, numeric allowance and non-retryable status remain correct. No incorrect analysis result, crash or data loss was observed. MCP was not exercised.

Selecting records 0 through 49 produced a successful subset view with records.examined: 50, records.total: 3000, and one group. This reduces coverage; it does not provide a complete view above the fixed allowance. Callers can use the representation-budget message and numeric allowance rather than the worker-memory advice.

REA version

6.7.0; source commit 074768901f3cdc8205b61773fb1faf6f6c7b3ca8.

Runtime and platform

Node v26.12.0; Darwin arm64. No external analysis engine is required.

Target and artifact context

Generated HAR 1.2 with 3000 GET requests to distinct numeric paths under https://api.example.test/resource/{i}/detail?x={i}, each with an empty JSON response. The numeric segments group together. The independent run's HAR was 1,509,860 bytes and its complete inspection Evidence was 5,247,644 stdout bytes. These are serialized sizes, not representation charges, and may vary with generated timestamps.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

The capture inspection exited 0. Each full-capture view exited 1 with empty stderr, code and category equal to resource_constraint, retryable: false, details.resource: "memory", and details.reported_limits.output_bytes: 100663296.

API-surface message:

API-surface retained state and temporary work exceed the projection representation budget.

The other two messages name their respective views. All three returned this remediation.action:

Review the reported worker memory limits and available host memory. Retry with sufficient memory or a smaller artifact; REA retains tighter inherited limits.

The script above and additional controls supplied these observed outputs through the built CLI. The successful subset control preserves explicit reduced coverage.

Typed outcome or recovery expected

Preserve resource_constraint, the fixed allowance, non-retryable status and no-partial-view behavior. The recovery action should explain the representation allowance and applicable options without implying that more worker/host memory admits the unchanged request. No particular replacement resource enum is required; this accounting includes retained state, clones and temporary work as well as output.

Analysis or suspected cause

Source-derived reasoning at the tested revision: src/domain/analysisView/WebNetworkProjectionAccumulator.ts:54-61 produces the budget error as a memory constraint without a specific recovery action. src/domain/analysisErrorPresentation.ts:67-78 then supplies the generic worker-memory fallback. Correcting this producer should preserve advice for actual process-memory failures.

Additional context

Prepared with AI assistance and independently reproduced through the supported CLI. The submission check fetched upstream main and found no later commits touching the cited documentation or failure-source files. Applicability to current main was source-checked, not runtime-reproduced there.

Related but separate: #5405 concerns Rust/IL2CPP input-size admission and evidence-output advice. #3538 and its proposed fix #3550 concern JavaScript parent-result capacity after static checkpoints. This report concerns already-inspected HAR projections and their fixed representation accounting; fixing either other producer does not correct this path.

The documentation also offers evidence-file sources to reduce inline-envelope charges for some inputs. That did not avoid this fixture's refusal. Record reduction is one demonstrated way to obtain a subset view, not a claim that it is the only option for every input. No last-known-good or first-bad revision was established.

Originally created by @coygeek on GitHub (Oct 20, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5459 ### 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 CLI ### Observed behavior After a successful HAR inspection, `inspect-analysis-view` correctly refuses API-surface, environment-manifest and environment-state projections above their fixed representation budget, but its recovery action recommends sufficient worker/host memory. That advice cannot raise the fixed projection allowance for an unchanged request. ### Reproduction An independent verifier ran this script end to end from the baseline source checkout with dependencies and the built runtime prepared. It generates a local 3000-record HAR, isolates configuration, and runs only local inspection commands. ```sh python3 - <<'PY' import datetime, json, os, pathlib, subprocess, tempfile work = pathlib.Path(tempfile.mkdtemp(prefix="rea-projection-check-")) env = {k: v for k, v in os.environ.items() if not k.startswith("REA_")} for key, name in [("HOME", "home"), ("XDG_CONFIG_HOME", "config"), ("XDG_DATA_HOME", "data"), ("XDG_CACHE_HOME", "cache"), ("XDG_STATE_HOME", "state")]: folder = work / name folder.mkdir() env[key] = str(folder) entries = [] for i in range(3000): entries.append({ "startedDateTime": datetime.datetime.now(datetime.timezone.utc).isoformat(), "time": 1.0, "request": {"method": "GET", "url": f"https://api.example.test/resource/{i}/detail?x={i}", "httpVersion": "HTTP/1.1", "cookies": [], "headers": [], "queryString": [], "headersSize": -1, "bodySize": 0}, "response": {"status": 200, "statusText": "OK", "httpVersion": "HTTP/1.1", "cookies": [], "headers": [], "content": {"size": 2, "mimeType": "application/json", "text": "{}"}, "redirectURL": "", "headersSize": -1, "bodySize": 2}, "cache": {}, "timings": {"send": 0, "wait": 1.0, "receive": 0}}) capture = work / "capture.har" capture.write_text(json.dumps({"log": {"version": "1.2", "creator": {"name": "fixture", "version": "1"}, "entries": entries}})) def run(label, arguments): result = subprocess.run(["node", "scripts/rea.mjs", *arguments, "--format", "json"], env=env, capture_output=True, text=True, timeout=60) (work / (label + ".json")).write_text(result.stdout) (work / (label + ".stderr")).write_text(result.stderr) value = json.loads(result.stdout) print(json.dumps({"case": label, "exit": result.returncode, "code": value.get("code"), "message": value.get("message"), "details": value.get("details"), "remediation": value.get("remediation")})) return value parent = run("capture", ["inspect-web-network-capture", str(capture), "har"]) for kind in ["api-surface", "environment-manifest", "environment-state"]: view = {"kind": kind} if kind == "api-surface": view.update(offset=0, limit=10) request = work / (kind + "-request.json") request.write_text(json.dumps({"source": {"kind": "inline", "evidence": parent}, "view": view})) run(kind, ["inspect-analysis-view", str(request)]) subset = run("subset", ["inspect-web-network-capture", str(capture), "har", *[argument for i in range(50) for argument in ["--record", str(i)]]]) request = work / "subset-request.json" request.write_text(json.dumps({"source": {"kind": "inline", "evidence": subset}, "view": {"kind": "api-surface", "offset": 0, "limit": 10}})) result = run("subset-view", ["inspect-analysis-view", str(request)]) print(json.dumps({"subset_records": result["normalized_result"]["records"], "groups": len(result["normalized_result"]["groups"])})) PY ``` The full capture inspection succeeds. Each full-capture projection exits 1 with the refusal below. Only API-surface supports the pagination fields used here. The 50-record subset and its API-surface view both succeed. Additional executed controls used API-surface limit 1 and evidence-file sources for all three views; each still returned the same projection-budget refusal for this fixture. ### Expected behavior Keep refusing excess projection representation cost without a partial view, but describe the fixed 96 MiB allowance and give recovery advice that applies to it. Increasing worker/host memory alone cannot change this allowance. `docs/web-network-captures.md:371-394` defines the accounting and distinguishes it from actual V8/process memory, decoder replies and MCP transport admission. Lines 490-500 and 590-598 apply the accounting to manifest and state views. This expectation is grounded in those documented distinctions. Preserve appropriate guidance for genuine process-memory exhaustion. ### Impact and scope P3 wording defect. All three schema-correct CLI requests reproduced the same misleading recovery advice. The intentional refusal, numeric allowance and non-retryable status remain correct. No incorrect analysis result, crash or data loss was observed. MCP was not exercised. Selecting records 0 through 49 produced a successful subset view with `records.examined: 50`, `records.total: 3000`, and one group. This reduces coverage; it does not provide a complete view above the fixed allowance. Callers can use the representation-budget message and numeric allowance rather than the worker-memory advice. ### REA version 6.7.0; source commit `074768901f3cdc8205b61773fb1faf6f6c7b3ca8`. ### Runtime and platform Node v26.12.0; Darwin arm64. No external analysis engine is required. ### Target and artifact context Generated HAR 1.2 with 3000 GET requests to distinct numeric paths under `https://api.example.test/resource/{i}/detail?x={i}`, each with an empty JSON response. The numeric segments group together. The independent run's HAR was 1,509,860 bytes and its complete inspection Evidence was 5,247,644 stdout bytes. These are serialized sizes, not representation charges, and may vary with generated timestamps. ### Interface CLI ### Earliest failure stage Transport or result projection ### Relevant output or evidence The capture inspection exited 0. Each full-capture view exited 1 with empty stderr, `code` and `category` equal to `resource_constraint`, `retryable: false`, `details.resource: "memory"`, and `details.reported_limits.output_bytes: 100663296`. API-surface message: ```text API-surface retained state and temporary work exceed the projection representation budget. ``` The other two messages name their respective views. All three returned this `remediation.action`: ```text Review the reported worker memory limits and available host memory. Retry with sufficient memory or a smaller artifact; REA retains tighter inherited limits. ``` The script above and additional controls supplied these observed outputs through the built CLI. The successful subset control preserves explicit reduced coverage. ### Typed outcome or recovery expected Preserve `resource_constraint`, the fixed allowance, non-retryable status and no-partial-view behavior. The recovery action should explain the representation allowance and applicable options without implying that more worker/host memory admits the unchanged request. No particular replacement resource enum is required; this accounting includes retained state, clones and temporary work as well as output. ### Analysis or suspected cause Source-derived reasoning at the tested revision: `src/domain/analysisView/WebNetworkProjectionAccumulator.ts:54-61` produces the budget error as a memory constraint without a specific recovery action. `src/domain/analysisErrorPresentation.ts:67-78` then supplies the generic worker-memory fallback. Correcting this producer should preserve advice for actual process-memory failures. ### Additional context Prepared with AI assistance and independently reproduced through the supported CLI. The submission check fetched upstream main and found no later commits touching the cited documentation or failure-source files. Applicability to current main was source-checked, not runtime-reproduced there. Related but separate: #5405 concerns Rust/IL2CPP input-size admission and evidence-output advice. #3538 and its proposed fix #3550 concern JavaScript parent-result capacity after static checkpoints. This report concerns already-inspected HAR projections and their fixed representation accounting; fixing either other producer does not correct this path. The documentation also offers evidence-file sources to reduce inline-envelope charges for some inputs. That did not avoid this fixture's refusal. Record reduction is one demonstrated way to obtain a subset view, not a claim that it is the only option for every input. No last-known-good or first-bad revision was established.
Author
Owner

@morluto commented on GitHub (Oct 21, 2026):

Closing as fixed on main by github.com/morluto/rea@ef59174c1e, retained at 67a6477f01.

The shared analysis-view projection accumulator now attaches named fixed-projection recovery, inherited by the reported network/environment projections. The guidance explicitly excludes worker/host-memory adjustments and unchanged retries; shared projection regressions cover the non-retryable contract. The original large HAR was not replayed in this audit.

This audit inspected the current producer, regression source, issue discussion and main ancestry. Tests/runtime reproductions were not rerun, and no additional real-provider or platform coverage is implied.

<!-- gh-comment-id:6324332996 --> @morluto commented on GitHub (Oct 21, 2026): Closing as fixed on main by https://github.com/morluto/rea/commit/ef59174c1edd6ed9adb0722b86a5b9a57217e310, retained at 67a6477f011ae358fc333e5a6e26c86d932654ed. The shared analysis-view projection accumulator now attaches named fixed-projection recovery, inherited by the reported network/environment projections. The guidance explicitly excludes worker/host-memory adjustments and unchanged retries; shared projection regressions cover the non-retryable contract. The original large HAR was not replayed in this audit. This audit inspected the current producer, regression source, issue discussion and main ancestry. Tests/runtime reproductions were not rerun, and no additional real-provider or platform coverage is implied.
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#3318
No description provided.