[PR #5863] [MERGED] feat(firmware): make analysis deadlines recoverable per call #7092

Closed
opened 2026-11-01 21:45:19 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/5863
Author: @gensokyo-dev
Created: 10/21/2026
Status: ✅ Merged
Merged: 10/21/2026
Merged by: @gensokyo-dev

Base: main ← Head: feat/20261021-firmware-timeout-recovery


📝 Commits (6)

  • 3b2aea4 feat(firmware): make analysis deadlines recoverable per call
  • 59d3a9e fix(firmware): classify cancellation during launcher admission
  • c93e6f6 fix(errors): retain one command capture through repeated cleanup
  • 320a4a4 fix(firmware): retain interruptions observed during command cleanup
  • ef70dba test(errors): assert canonical output ownership in cleanup consumers
  • 272f9fb test(errors): verify capture ownership across decoder cleanup consumers

📊 Changes

23 files changed (+843 additions, -118 deletions)

View changed files

📝 docs/firmware-analysis.md (+12 -1)
📝 src/application/binary/AnalysisClientCleanup.test.ts (+14 -3)
📝 src/application/firmware/FirmwareAnalysisService.test.ts (+129 -47)
📝 src/application/firmware/FirmwareAnalysisService.ts (+17 -0)
📝 src/cli/firmwareCommands.ts (+12 -2)
📝 src/contracts/firmware/firmwareToolContracts.ts (+1 -1)
📝 src/domain/analysisErrorCleanup.test.ts (+62 -2)
📝 src/domain/analysisErrorCleanup.ts (+8 -2)
📝 src/domain/analysisErrorProjection.ts (+11 -1)
📝 src/domain/firmware/firmwareAnalysis.ts (+21 -6)
📝 src/firmware/FirmwareCommand.test.ts (+97 -2)
📝 src/firmware/FirmwareCommand.ts (+67 -26)
📝 src/firmware/FirmwareDeadline.test.ts (+56 -0)
📝 src/firmware/FirmwareFailures.ts (+5 -1)
📝 src/firmware/FirmwareProvider.ts (+7 -2)
📝 src/firmware/FirmwarePublication.ts (+2 -0)
📝 src/firmware/FirmwareRelease.ts (+1 -1)
📝 src/sqlite/SqliteDatabaseFailures.ts (+8 -8)
📝 tests/boundary/binaryDiagnostics/pwntoolsLayoutProvider.test.ts (+17 -1)
📝 tests/composition/directAnalysisCleanup.test.ts (+15 -3)

...and 3 more files

📄 Description

Summary

Fixes #5851. Firmware agents can now adjust the analysis wall-clock budget independently of publication. Previously both provider and command layers imposed a hidden fixed 120-second analysis cap.

Problem and expected behavior

Both firmware tools accept optional analysis_timeout_ms / CLI --analysis-timeout-ms (default 120000; integer 1..2147483647). A timeout identifies the actual phase/budget and exact adjustment, preserves the question/input, and explains client headroom, cleanup and unchanged fixed limits. publication_timeout_ms cannot repair an analysis timeout.

Change and scope

One provider-owned deadline spans tool resolution, snapshot and commands. Inspection includes final workspace cleanup; extraction ends analysis at inventory, then uses its independent publication/final-cleanup budget. Queue/retained-cleanup admission is excluded. Remove the command's competing clock. Full/completed-partial results retain actual settings; historical omissions stay unknown and explicit selection stays explicit. Shared validation checks only small execution metadata, not the entire inventory again. Normalize observed launcher cancellation at its boundary and preserve interruptions during command cleanup without replacing earlier failures. Shared error history now reuses one projection owner (including SQLite), retaining each command capture once through failed CLI close.

No new provider/capability, target execution, sandbox relaxation, installation behavior or larger CPU/memory/byte allowance. Maintainer scope decision: not applicable to this ordinary fix within existing firmware authority. Staging refusal classification (#5846), arbitrary kill attribution and other providers are outside this change.

Contract and boundary impact

  • Semantic owner: firmware domain contracts and provider-owned phase deadline.
  • CLI/MCP: same named optional timer contract and shared application workflow; advertised input/output schemas checked after SDK conversion.
  • Compatibility: Linux; caller-supplied Binwalk 3.1.x / Unblob 26.6.x and existing prlimit. Fixed per-process CPU remains 120 seconds.
  • Evidence: input path/digest/range, coverage, gaps and raw producer observations retained. Old absent budget is not assigned a fictional default; fresh results must retain selected/default budget.
  • Cleanup: exact existing owned process/workspace leases, no server restart after confirmed release; absent extraction destinations remain required.
  • Generated metadata: ignored catalog/skill outputs only; no package/dependency changes or committed binaries.

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process. Existing supplied analyzers only.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration. Existing private staging and explicitly selected extraction output only; no source/configuration mutation.
  • 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

Executed fail-before: 12 failures / 10 passes initially; admission cancellation 4 failures / 5 passes; repeated-close capture 1 failure / 15 passes; interruption during command cleanup 3 failures / 18 passes. Final head 272f9fb15: 535 passed / 4 platform skips across 39 exact firmware/SQLite/shared-error/CLI/native/managed/pwntools/PCAP/WABT files (151.06s). Independent queued settings, monotonic expiry, opaque reasons, completed partial facts and cleanup resolution covered. The full capture-consumer audit is 189 passed / 1 skip across 13 files. Four old history assertions exposed by Source/built CI migrated to canonical primary capture; pwntools' existing cleanup-owner snapshot remains intact, without a third generic-history copy or text-based deduplication. Subsequent commits are test-only; runtime is identical to 320a4a436.

Actual isolated Binwalk 3.1.0 / Unblob 26.6.4: baseline and initial public verifier passed independent gzip/USTAR/compiled-ELF offsets/digests, range, unknown-chunk and depth checks. Nine extra paired CLI/MCP cases cover default/selected/max settings, both 1ms analysis timeouts, publication timeout and fixed oversized refusal. A full run passed on c93e6f6b; final-head repeat had 17/18 expected endpoint outcomes, with one selected-budget MCP scan blocked by baseline report-missing #5876 (also reproduced 2/12 on pre-PR f801b2fb). Successful observations passed SDK-converted AJV 2020 schemas, bounds, immutable-source/oracle and retained-Evidence readback checks. No all-green real-provider claim.

Actual Codex CLI gpt-6.1-sol: 18 qualification attempts, 16 REA-dispatched: 10 corrected successes + 6 accurate blockers (missing providers, executable, prlimit, wrong version, fixed input cap); two zero-call tool-unavailable reports are not product passes. Latest head again corrected 1ms to 120000ms. No unchanged failed retries, shell/unexpected tools or surviving sampled PIDs. Controlled 121-second actual-tool startup experiment exceeded the old cap successfully with 135000ms on reviewed implementations; a later attempt hit baseline #5876, not a timeout. Whole completed-session costs, harness mistakes, exact oracle and limitations are in the executed evidence.

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

  • npm run test:focused -- <39 exact test files> — 535 passed / 4 platform skips, 151.06s; required artifacts built.
  • npm run check:fast — typecheck and lint passed, 62.76s.
  • npm run docs:check — generated checks and 5 consistency tests passed.
  • Architecture guards / test discovery — passed across 1699 source / 1902 test files.
  • node scripts/verify/firmware/analysis.mjs — real public verifier passed on baseline and current runtime with the same independently generated fixture.
  • Ignored public.mjs — nine CLI/MCP cases; final 17/18 expected outcomes, one independently reproduced baseline #5876; schemas/Evidence/oracle checked for actual successful results.
  • git diff --check — passed.

Compatibility, safety, and release

Additive caller control; historical Evidence readable; default sandbox/fixed resource limits unchanged. No target/extracted-code execution, mounts or aggregate containment claim. Real-engine scope: Linux x64, small generated fixture, not vendor/large firmware or non-Linux. All 22 completed Codex sessions including four setup mistakes: 2,164,724 input / 1,780,096 cached / 11,988 output tokens, 655.47s wall / 201.73s local CPU, 1261.93 MiB max sampled family RSS (500ms). One interrupted harness session and build/setup/CI costs are unmeasured; caches uncontrolled, no cold-cache or speedup claim. Known baseline CI requiredness-test issue #5845 is outside this PR; no unrelated gate/test weakening.

Author readiness

Human owner: @gensokyo-dev (account selected by the user).

  • 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.

The user explicitly directed ready-for-review creation and authorized technical/admin merge. This is not an attestation that a human inspected the final diff or evidence; those declarations remain unchecked.

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/5863 **Author:** [@gensokyo-dev](https://github.com/gensokyo-dev) **Created:** 10/21/2026 **Status:** ✅ Merged **Merged:** 10/21/2026 **Merged by:** [@gensokyo-dev](https://github.com/gensokyo-dev) **Base:** `main` ← **Head:** `feat/20261021-firmware-timeout-recovery` --- ### 📝 Commits (6) - [`3b2aea4`](https://github.com/morluto/rea/commit/3b2aea45dd8909b9e783dfd2211eabc86a01ab58) feat(firmware): make analysis deadlines recoverable per call - [`59d3a9e`](https://github.com/morluto/rea/commit/59d3a9ed9d8b2b26069730bf6f82559910f72445) fix(firmware): classify cancellation during launcher admission - [`c93e6f6`](https://github.com/morluto/rea/commit/c93e6f6b7b35026284f013428c6d695e8cdcf9f6) fix(errors): retain one command capture through repeated cleanup - [`320a4a4`](https://github.com/morluto/rea/commit/320a4a436296b1832b771f301a1aeb8e0118baf8) fix(firmware): retain interruptions observed during command cleanup - [`ef70dba`](https://github.com/morluto/rea/commit/ef70dbafcb6de1c8fea5c54e6c99e64b7b6226b9) test(errors): assert canonical output ownership in cleanup consumers - [`272f9fb`](https://github.com/morluto/rea/commit/272f9fb15910deb656f4c8786f61f2ba3d0c08c9) test(errors): verify capture ownership across decoder cleanup consumers ### 📊 Changes **23 files changed** (+843 additions, -118 deletions) <details> <summary>View changed files</summary> 📝 `docs/firmware-analysis.md` (+12 -1) 📝 `src/application/binary/AnalysisClientCleanup.test.ts` (+14 -3) 📝 `src/application/firmware/FirmwareAnalysisService.test.ts` (+129 -47) 📝 `src/application/firmware/FirmwareAnalysisService.ts` (+17 -0) 📝 `src/cli/firmwareCommands.ts` (+12 -2) 📝 `src/contracts/firmware/firmwareToolContracts.ts` (+1 -1) 📝 `src/domain/analysisErrorCleanup.test.ts` (+62 -2) 📝 `src/domain/analysisErrorCleanup.ts` (+8 -2) 📝 `src/domain/analysisErrorProjection.ts` (+11 -1) 📝 `src/domain/firmware/firmwareAnalysis.ts` (+21 -6) 📝 `src/firmware/FirmwareCommand.test.ts` (+97 -2) 📝 `src/firmware/FirmwareCommand.ts` (+67 -26) 📝 `src/firmware/FirmwareDeadline.test.ts` (+56 -0) 📝 `src/firmware/FirmwareFailures.ts` (+5 -1) 📝 `src/firmware/FirmwareProvider.ts` (+7 -2) 📝 `src/firmware/FirmwarePublication.ts` (+2 -0) 📝 `src/firmware/FirmwareRelease.ts` (+1 -1) 📝 `src/sqlite/SqliteDatabaseFailures.ts` (+8 -8) 📝 `tests/boundary/binaryDiagnostics/pwntoolsLayoutProvider.test.ts` (+17 -1) 📝 `tests/composition/directAnalysisCleanup.test.ts` (+15 -3) _...and 3 more files_ </details> ### 📄 Description ## Summary Fixes #5851. Firmware agents can now adjust the analysis wall-clock budget independently of publication. Previously both provider and command layers imposed a hidden fixed 120-second analysis cap. ## Problem and expected behavior Both firmware tools accept optional `analysis_timeout_ms` / CLI `--analysis-timeout-ms` (default 120000; integer 1..2147483647). A timeout identifies the actual phase/budget and exact adjustment, preserves the question/input, and explains client headroom, cleanup and unchanged fixed limits. `publication_timeout_ms` cannot repair an analysis timeout. ## Change and scope One provider-owned deadline spans tool resolution, snapshot and commands. Inspection includes final workspace cleanup; extraction ends analysis at inventory, then uses its independent publication/final-cleanup budget. Queue/retained-cleanup admission is excluded. Remove the command's competing clock. Full/completed-partial results retain actual settings; historical omissions stay unknown and explicit selection stays explicit. Shared validation checks only small execution metadata, not the entire inventory again. Normalize observed launcher cancellation at its boundary and preserve interruptions during command cleanup without replacing earlier failures. Shared error history now reuses one projection owner (including SQLite), retaining each command capture once through failed CLI close. No new provider/capability, target execution, sandbox relaxation, installation behavior or larger CPU/memory/byte allowance. Maintainer scope decision: not applicable to this ordinary fix within existing firmware authority. Staging refusal classification (#5846), arbitrary kill attribution and other providers are outside this change. ## Contract and boundary impact - Semantic owner: firmware domain contracts and provider-owned phase deadline. - CLI/MCP: same named optional timer contract and shared application workflow; advertised input/output schemas checked after SDK conversion. - Compatibility: Linux; caller-supplied Binwalk 3.1.x / Unblob 26.6.x and existing prlimit. Fixed per-process CPU remains 120 seconds. - Evidence: input path/digest/range, coverage, gaps and raw producer observations retained. Old absent budget is not assigned a fictional default; fresh results must retain selected/default budget. - Cleanup: exact existing owned process/workspace leases, no server restart after confirmed release; absent extraction destinations remain required. - Generated metadata: ignored catalog/skill outputs only; no package/dependency changes or committed binaries. Expected effects: - [x] Read existing files or captured data. - [x] Launch or attach to a process. Existing supplied analyzers only. - [ ] Inject instrumentation or run scripts/code. - [x] Change process memory, registers, files, or configuration. Existing private staging and explicitly selected extraction output only; no source/configuration mutation. - [ ] 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 Executed fail-before: 12 failures / 10 passes initially; admission cancellation 4 failures / 5 passes; repeated-close capture 1 failure / 15 passes; interruption during command cleanup 3 failures / 18 passes. Final head `272f9fb15`: **535 passed / 4 platform skips across 39 exact firmware/SQLite/shared-error/CLI/native/managed/pwntools/PCAP/WABT files (151.06s)**. Independent queued settings, monotonic expiry, opaque reasons, completed partial facts and cleanup resolution covered. The full capture-consumer audit is 189 passed / 1 skip across 13 files. Four old history assertions exposed by Source/built CI migrated to canonical primary capture; pwntools' existing cleanup-owner snapshot remains intact, without a third generic-history copy or text-based deduplication. Subsequent commits are test-only; runtime is identical to `320a4a436`. Actual isolated Binwalk 3.1.0 / Unblob 26.6.4: baseline and initial public verifier passed independent gzip/USTAR/compiled-ELF offsets/digests, range, unknown-chunk and depth checks. Nine extra paired CLI/MCP cases cover default/selected/max settings, both 1ms analysis timeouts, publication timeout and fixed oversized refusal. A full run passed on `c93e6f6b`; final-head repeat had **17/18 expected endpoint outcomes**, with one selected-budget MCP scan blocked by baseline report-missing #5876 (also reproduced 2/12 on pre-PR f801b2fb). Successful observations passed SDK-converted AJV 2020 schemas, bounds, immutable-source/oracle and retained-Evidence readback checks. No all-green real-provider claim. Actual Codex CLI gpt-6.1-sol: **18 qualification attempts, 16 REA-dispatched: 10 corrected successes + 6 accurate blockers** (missing providers, executable, prlimit, wrong version, fixed input cap); two zero-call tool-unavailable reports are not product passes. Latest head again corrected 1ms to 120000ms. No unchanged failed retries, shell/unexpected tools or surviving sampled PIDs. Controlled 121-second actual-tool startup experiment exceeded the old cap successfully with 135000ms on reviewed implementations; a later attempt hit baseline #5876, not a timeout. Whole completed-session costs, harness mistakes, exact oracle and limitations are in the [executed evidence](https://github.com/morluto/rea/issues/5851#issuecomment-6313469058). - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed - `npm run test:focused -- <39 exact test files>` — 535 passed / 4 platform skips, 151.06s; required artifacts built. - `npm run check:fast` — typecheck and lint passed, 62.76s. - `npm run docs:check` — generated checks and 5 consistency tests passed. - Architecture guards / test discovery — passed across 1699 source / 1902 test files. - `node scripts/verify/firmware/analysis.mjs` — real public verifier passed on baseline and current runtime with the same independently generated fixture. - Ignored `public.mjs` — nine CLI/MCP cases; final 17/18 expected outcomes, one independently reproduced baseline #5876; schemas/Evidence/oracle checked for actual successful results. - `git diff --check` — passed. ## Compatibility, safety, and release Additive caller control; historical Evidence readable; default sandbox/fixed resource limits unchanged. No target/extracted-code execution, mounts or aggregate containment claim. Real-engine scope: Linux x64, small generated fixture, not vendor/large firmware or non-Linux. All 22 completed Codex sessions including four setup mistakes: 2,164,724 input / 1,780,096 cached / 11,988 output tokens, 655.47s wall / 201.73s local CPU, 1261.93 MiB max sampled family RSS (500ms). One interrupted harness session and build/setup/CI costs are unmeasured; caches uncontrolled, no cold-cache or speedup claim. Known baseline CI requiredness-test issue #5845 is outside this PR; no unrelated gate/test weakening. ## Author readiness Human owner: @gensokyo-dev (account selected by the user). - [ ] 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. - [x] I declare this PR ready for initial maintainer review. The user explicitly directed ready-for-review creation and authorized technical/admin merge. This is not an attestation that a human inspected the final diff or evidence; those declarations remain unchecked. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] 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>
bsakaguchi 2026-11-01 21:45:19 +00:00
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#7092
No description provided.