Skip to content

[AI-894] Host Pi as an unattended review-flow reviewer - #1102

Merged
realtonyyoung merged 29 commits into
mainfrom
claude-tyoung/ai-894-pi-reviewer-lane
Sep 22, 2026
Merged

realtonyyoung merged 29 commits into
mainfrom
claude-tyoung/ai-894-pi-reviewer-lane

Conversation

@realtonyyoung

Copy link
Copy Markdown
Collaborator

Part of AI-894 (no GitHub issue in this repo; the issue closes after rollout, so no closing keyword).

What & why

Pi is the one supported harness with no ACP endpoint, so it could not ride the ACP reviewer work. This adds an unattended review-flow lane over a contained pi --mode rpc child: start_review_flow(vendor: "pi") advertises pi and launches a reviewer that reports through submit_review_result.

Containment is by argv plus one per-launch TypeScript extension that bridges the flow-result MCP server and supplies worktree-scoped read-only file tools; no Pi built-in tool is reachable. One ordered tool list renders both the extension manifest and the --tools allowlist, and the host verifies the child's live tool set from a ready.json before any prompt is sent. Coded failure reasons reach the server through a reap-verdict gate lifted out of the ACP runtime and now shared with Pi. Every recorded pi version is a minimum (floors, not pins).

Interactive Pi and ACP behaviour are unchanged, except ACP's post-registration Running is now gated (closing the same interval for ACP).

Where to look

  • The read boundary: PiReviewerExtension (component-wise realpath containment, no symlink following, literal search), PiReviewerToolSurface (one list → manifest + allowlist), and host-verified ready.json.
  • ReapVerdictGate lift: ACP delegates to it unchanged; PiRpcHostedAgentRuntime composes the same gate. Interactive launches never consult the reviewer ladder.

Verification

  • Merged tree (origin/main incl. [AI-2857] Spawn detached children without inheriting the agent's handles #978): 17 test classes / 226 tests green; AOT publish clean (no IL2026/IL3050).
  • Containment cert against real pi 0.85.1 (KCAP_PI_REVIEWER_CONTAINMENT=1): 14/14 pass, and 14/14 skip cleanly without the gate. The three live certs (hosted, memory, reviewer) are written and skip until run at deploy.

🤖 Generated with Claude Code

realtonyyoung and others added 23 commits September 21, 2026 16:34
ReapVerdictGate carries its own line-collapsing sanitizer instead of
calling AcpHostedAgentRuntime.SanitizeForForward, so it names no ACP
type — a later task composes it from the Pi runtime too.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ReapVerdictGate's SanitizeReason dropped SanitizeForForward's
surrogate-safe 500-char cap, leaving reap reasons (agent-influenced
text) uncapped on the report/log path. SanitizeForForward now
delegates to the gate's copy instead of duplicating it, so ACP keeps
its one sanitizer and the gate stays vendor-neutral.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
For partitioned servers by role instead of trusting the caller to
list the result channel first, so a launcher's own server ordering
can never silently reorder the advertised tool list.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CreateOwnerOnly trusted CreateDirectory's mode argument without a
read-back, unlike the Kiro/Antigravity/OpenCode siblings it mirrors —
an existing root or dir with leftover looser bits would silently
re-narrow and proceed instead of refusing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The npm-offline claim and 8 of 10 planted text-token sources had no
positive control, so a dead observable and a real suppression looked
identical. Also splits PiContainmentRun into its own file.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… floors

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Composes ReapVerdictGate on PiRpcHostedAgentRuntime and wires PiRoundCeiling
into it, guarded on a new PiReviewerGuards being non-null so an interactive
launch keeps today's behaviour in every case. Three review-flow-only guards
share one reap routine: an unanswerable dialog, a round past its ceiling, and
a command-shaped prompt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The reviewer ladder is read by both advertisement and launch, so a daemon
cannot offer a reviewer it would refuse to start. A Pi reap is a deliberate
coded reason, so its exception omits the transport suffix ACP adds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Widens CaptureServerConnection.VerdictCaptureRuntime from
AcpHostedAgentRuntime to ITerminationVerdictSource so the shared
check-to-send race test can drive it with a Pi runtime too.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@linear-code

linear-code Bot commented Sep 22, 2026

Copy link
Copy Markdown

AI-894

@qodo-code-review

qodo-code-review Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Large files can crash a review ✓ Resolved 🐞 Bug ☼ Reliability
Description
read_file loads, decodes, and splits the entire file before applying MAX_READ_LINES or
MAX_READ_BYTES, and it measures the latter using UTF-16 string length rather than UTF-8 bytes.
When Pi requests a large text file, its child process can exhaust memory and fail the unattended
review even though the tool advertises a bounded 256 KB response.
Code

src/Capacitor.Cli.Core/Harness/Pi/PiReviewerExtension.cs[R130-132]

+                const buf = readFileSync(target);
+                if (isBinary(buf)) throw new Error("binary file");
+                const lines = buf.toString("utf8").split("\n");
Relevance

●●● Strong

Unbounded pre-limit file allocation is a concrete reliability defect in the advertised bounded tool.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The tool promises a 256 KB response, but the complete buffer and complete line array are allocated
before any limit is checked; the output check also uses JavaScript string length rather than encoded
byte length.

src/Capacitor.Cli.Core/Harness/Pi/PiReviewerExtension.cs[117-139]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The reviewer file tool reads and decodes a complete file before enforcing its advertised line and byte limits, allowing large files to exhaust the Pi child and making the byte limit inaccurate for multibyte UTF-8 content.

## Fix Focus Areas
- src/Capacitor.Cli.Core/Harness/Pi/PiReviewerExtension.cs[117-145]

## Recommended Fix
Read the file incrementally through a bounded stream or file handle, inspect only the bounded prefix needed for binary detection, count returned UTF-8 bytes with `Buffer.byteLength`, and stop as soon as either the requested line count or byte limit is reached without materializing the complete file.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Reviews with an empty task never finish ✓ Resolved 🐞 Bug ≡ Correctness
Description
ValidateReviewerContext documents blank input as invalid but only rejects command-shaped prompts,
while StartReviewerAsync skips SendUserInputAsync when ctx.Prompt is null or empty. Because
the orchestrator copies LaunchAgentCommand.Prompt directly into this context, a review-flow
command without a prompt returns an idle runtime that neither starts a reviewer turn nor arms the
turn deadline.
Code

src/Capacitor.Cli.Daemon/Harness/Pi/PiRpcHostedAgentRuntimeFactory.cs[R277-278]

+            if (!string.IsNullOrEmpty(ctx.Prompt))
+                await runtime.SendUserInputAsync(ctx.Prompt).ConfigureAwait(false);
Relevance

●●● Strong

Blank prompts can produce an idle reviewer with no turn or deadline, a concrete lifecycle defect.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new factory explicitly states that blank input would launch a reviewer that cannot report, but
its validation only tests for slash-prefixed prompts and its launch path conditionally omits the
initial send. The orchestrator preserves the inbound nullable prompt, and the reviewer deadline is
armed only from the prompt-writing path.

src/Capacitor.Cli.Daemon/Harness/Pi/PiRpcHostedAgentRuntimeFactory.cs[277-279]
src/Capacitor.Cli.Daemon/Harness/Pi/PiRpcHostedAgentRuntimeFactory.cs[308-319]
src/Capacitor.Cli.Daemon/Services/AgentOrchestrator.cs[2000-2000]
src/Capacitor.Cli.Daemon/Harness/Pi/PiRoundCeiling.cs[28-35]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Pi review-flow launches currently accept a null, empty, or whitespace-only initial prompt. The factory then returns a live runtime without sending a prompt, so no review turn starts and no reviewer timeout is armed.

## Fix Focus Areas
- src/Capacitor.Cli.Daemon/Harness/Pi/PiRpcHostedAgentRuntimeFactory.cs[308-319]
- src/Capacitor.Cli.Daemon/Harness/Pi/PiRpcHostedAgentRuntimeFactory.cs[277-279]

## Recommended Fix
In `ValidateReviewerContext`, reject `string.IsNullOrWhiteSpace(ctx.Prompt)` with a coded `pi_reviewer_...` launch-context error before creating the launch directory. Keep the command-prefix validation after the nonblank check, and make the initial prompt send unconditional once validation has succeeded.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. A test can erase inherited settings ✓ Resolved 📘 Rule violation ☼ Reliability
Description
Reviewer_env_names_the_manifest_and_drops_the_variables_that_repoint_pi directly sets two process
environment variables and restores both to null instead of using EnvScope.Exclusive. If either
variable had an inherited value, the cleanup discards it and exposes concurrent environment readers
to the temporary values.
Code

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerLaunchTests.cs[R111-112]

+        Environment.SetEnvironmentVariable("JITI_ALIAS", "x");
+        Environment.SetEnvironmentVariable("PI_EXPERIMENTAL", "1");
Relevance

●●● Strong

Explicit EnvScope rule directly prohibits these ambient environment mutations.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2821221 requires every test environment mutation to use EnvScope, with Exclusive and bare
[NotInParallel] when real process-environment readers are involved. The added test directly writes
and clears both variables even though BuildPsi derives its child environment from the ambient
process environment.

Rule 2821221: Use EnvScope for all environment variable mutations in tests
test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerLaunchTests.cs[109-124]
src/Capacitor.Cli.Daemon/Harness/Pi/PiLaunchEnvironment.cs[41-49]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test mutates process-wide environment variables directly and clears them afterward, which does not preserve inherited values and bypasses the required environment scope helper.

## Fix Focus Areas
- test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerLaunchTests.cs[109-124]

## Recommended Fix
Create disposable `EnvScope.Exclusive` scopes for `JITI_ALIAS` and `PI_EXPERIMENTAL`, retain the bare `[NotInParallel]` constraint, and remove the direct setters and manual cleanup.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Two JSON checks bypass helpers ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
ToolNames and ToolResultTexts compare JsonElement.ValueKind directly with
JsonValueKind.Array instead of using the shared IsArray property. Both request-shape checks in
the new containment bench therefore duplicate the project’s centralized JSON type classification.
Code

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiContainmentBench.cs[351]

+        request.TryGetProperty("tools", out var tools) && tools.ValueKind == JsonValueKind.Array
Relevance

●●● Strong

Direct JSON kind checks violate an explicit repository helper rule and are straightforward to
correct.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2270023 requires changed JsonElement shape checks to use JsonElementExtensions. The two
added methods compare ValueKind directly, while the repository exposes IsArray for this exact
check.

Rule 2270023: Use JsonElementExtensions helpers instead of direct JsonValueKind comparisons
test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiContainmentBench.cs[350-356]
src/Capacitor.Models.Transcripts/JsonElementExtensions.cs[7-12]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new containment bench directly compares `JsonElement.ValueKind` with `JsonValueKind.Array` in two request-shape checks instead of using the shared `JsonElementExtensions.IsArray` property.

## Fix Focus Areas
- test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiContainmentBench.cs[350-356]

## Recommended Fix
Replace both `ValueKind == JsonValueKind.Array` comparisons with the corresponding `IsArray` helper and retain the existing enumeration behavior.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (5)
5. Pi certs can overload subprocesses ✓ Resolved 📘 Rule violation ▣ Testability
Description
PiReviewerContainmentCertTests and PiReviewerLiveCertTests run real child processes without
applying ParallelLimiter<SubprocessLimit> to either class. When the suite executes at full
parallel width, these gated certifications compete with every other subprocess-heavy fixture outside
the shared limit.
Code

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerContainmentCertTests.cs[16]

+public class PiReviewerContainmentCertTests {
Relevance

●●● Strong

Explicit subprocess-limiter rule directly applies to both real-process test classes.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2808212 requires test classes that run real subprocesses to use
ParallelLimiter<SubprocessLimit>. The two new classes lack that attribute, while their execution
paths create a real PiRpcProcess or invoke the unseamed production runtime factory.

Rule 2808212: Use ParallelLimiter<SubprocessLimit> for test classes running real subprocesses
test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerContainmentCertTests.cs[5-16]
test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiContainmentBench.cs[291-291]
test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerLiveCertTests.cs[13-37]
test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerLiveCertTests.cs[120-143]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Two new certification classes launch real Pi and related child processes without joining the suite-wide subprocess limiter.

## Fix Focus Areas
- test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerContainmentCertTests.cs[16-16]
- test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerLiveCertTests.cs[37-37]

## Recommended Fix
Annotate both test classes with `[ParallelLimiter<SubprocessLimit>]` so their real child processes participate in the shared subprocess concurrency budget.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Two comments cite a dated probe ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The XML documentation for PiReviewerContainmentCertTests and PiContainmentBench describes their
implementation through the dated docs/probes/2026-09-21-pi-reviewer process artifact. A later
reader must retain knowledge of that historical probe to interpret why the fixtures have their
current shape.
Code

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerContainmentCertTests.cs[6]

+/// GATED containment cert: the C# port of <c>docs/probes/2026-09-21-pi-reviewer/probe.py</c>, driving
Relevance

●●● Strong

Recent history accepted removing process or issue references from comments.

PR-#627
PR-#710

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2897915 prohibits comments from depending on dated external process artifacts or historical
implementation narration. Both added XML comments reference the same calendar-dated probe path, and
one explicitly calls the test a port of that artifact.

Rule 2897915: Avoid time-sensitive or process-reference metadata in code comments
test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerContainmentCertTests.cs[5-11]
test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiContainmentBench.cs[9-16]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Two new XML comments identify the fixtures through a dated probe artifact instead of documenting only their current containment purpose and invariants.

## Fix Focus Areas
- test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerContainmentCertTests.cs[5-11]
- test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiContainmentBench.cs[9-16]

## Recommended Fix
Remove the dated probe path and historical port/source wording, then describe the current containment scenarios and why each canary or hostile call is behaviorally necessary.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Launch tests bypass temp injection ✓ Resolved 📘 Rule violation ▣ Testability
Description
PiReviewerLaunchDirTests manually constructs a disposable TempDir inside each of its eight tests
rather than declaring one injected [TempDir] property. Every launch-directory case consequently
owns its fixture lifecycle separately instead of using the framework-managed test-class resource.
Code

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerLaunchDirTests.cs[11]

+        using var state = new TempDir();
Relevance

●●● Strong

Explicit TempDir rule directly prohibits manual allocation in test classes.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2808173 requires a single injected public required TempDir property in test classes and
explicitly disallows new TempDir() calls. All eight added test methods manually allocate their own
instance.

Rule 2808173: Use injected [TempDir] public required property in test classes instead of manual fields
test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerLaunchDirTests.cs[7-26]
test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerLaunchDirTests.cs[37-73]
test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerLaunchDirTests.cs[82-112]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new test class manually creates `TempDir` instances in every test even though test classes must receive temporary directories through a public required `[TempDir]` property.

## Fix Focus Areas
- test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerLaunchDirTests.cs[7-13]
- test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerLaunchDirTests.cs[23-112]

## Recommended Fix
Add one `[TempDir] public required TempDir Tmp { get; init; }` property, replace each local `state` with `Tmp`, and remove all manual `new TempDir()` and disposal statements.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Search patterns can freeze a review ✓ Resolved 🐞 Bug ➹ Performance
Description
globMatches recursively explores every path split for each ** without memoization, a
pattern-size bound, or a deadline check inside the matcher. A model-supplied pattern containing
repeated ** against a sufficiently deep repository path recomputes states combinatorially and
blocks the synchronous extension event loop beyond the advertised search budget.
Code

src/Capacitor.Cli.Core/Harness/Pi/PiReviewerExtension.cs[R82-84]

+            if (g[gi] === "**") {
+              for (let k = ni; k <= p.length; k++) if (match(gi + 1, k)) return true;
+              return false;
Relevance

●● Moderate

Performance risk is plausible, but no closely matching historical acceptance precedent was found.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Every ** loops over all remaining path positions and recursively recalculates the same states,
while the only time check runs before globMatches and therefore cannot interrupt that recursion.

src/Capacitor.Cli.Core/Harness/Pi/PiReviewerExtension.cs[80-89]
src/Capacitor.Cli.Core/Harness/Pi/PiReviewerExtension.cs[190-192]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Repeated recursive wildcards cause combinatorial glob matching, and the surrounding search deadline cannot interrupt one synchronous match once it starts.

## Fix Focus Areas
- src/Capacitor.Cli.Core/Harness/Pi/PiReviewerExtension.cs[61-90]
- src/Capacitor.Cli.Core/Harness/Pi/PiReviewerExtension.cs[177-203]

## Recommended Fix
Memoize results by glob-segment and path-segment indices, reject excessively long or complex patterns, and propagate the search deadline into matching so recursive work terminates once the budget expires.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Queued prompts trigger false timeouts ✓ Resolved 🐞 Bug ≡ Correctness
Description
HandleEvent calls PiRoundCeiling.UserEcho() only when IsOurOwnEcho finds the prompt in
_sentPrompts, whose existing echo memory evicts entries after 16 unconsumed prompts. If more than
16 inputs are queued before their echoes arrive, an accepted round remains counted as owed after Pi
settles, so the new ceiling stays armed and reaps a successfully settled reviewer as timed out.
Code

src/Capacitor.Cli.Daemon/Harness/Pi/PiRpcHostedAgentRuntime.cs[R379-382]

        if (IsOurOwnEcho(frame, envelopes)) {
            _logger.LogDebug("Pi: dropped the echo of a prompt this daemon sent (agentId={AgentId}).", _agentId);
+            _ceiling?.UserEcho();
            return;
Relevance

●● Moderate

The eviction-induced timeout scenario is specific and complex; no matching historical precedent was
found.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Accepted prompt responses increment the ceiling's owed count, but only a successfully deduplicated
echo decrements it; the deduplication list drops its oldest entry above 16, and settlement
deliberately preserves any remaining owed count and rearms the timer.

src/Capacitor.Cli.Daemon/Harness/Pi/PiRpcHostedAgentRuntime.cs[378-385]
src/Capacitor.Cli.Daemon/Harness/Pi/PiRpcHostedAgentRuntime.cs[640-667]
src/Capacitor.Cli.Daemon/Harness/Pi/PiRoundCeiling.cs[44-78]
src/Capacitor.Cli.Daemon/Services/AgentOrchestrator.cs[4189-4200]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Reviewer timeout accounting depends on a bounded transcript-deduplication cache, so cache eviction can prevent accepted rounds from ever being marked started and settled.

## Fix Focus Areas
- src/Capacitor.Cli.Daemon/Harness/Pi/PiRpcHostedAgentRuntime.cs[378-385]
- src/Capacitor.Cli.Daemon/Harness/Pi/PiRpcHostedAgentRuntime.cs[640-667]
- src/Capacitor.Cli.Daemon/Harness/Pi/PiRoundCeiling.cs[44-78]

## Recommended Fix
Keep reviewer round accounting separate from the bounded transcript echo cache, retaining each accepted reviewer prompt until its corresponding user echo is consumed, and add a test that queues more than 16 prompts before processing their echoes and settlement.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 64 rules
✅ Cross-repo context — repo relationships
  Explored: repo: kurrent-io/kcap-server (sha: 76815545)
Review mode: 🧠 Deep: This security-sensitive, cross-cutting reviewer lane spans many independent runtime, containment, tool-surface, process-lifecycle, and ACP integration paths, creating unusually high density of subtle defects that benefit from redundant review.

Grey Divider

Tip of the day
💡 Did you know, you can route each action level your way: inline, summary, both, or drop

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiContainmentBench.cs Outdated
Comment thread test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerLaunchTests.cs Outdated
Comment thread test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerLaunchDirTests.cs Outdated
Comment thread test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerContainmentCertTests.cs Outdated
Comment thread src/Capacitor.Cli.Core/Harness/Pi/PiReviewerExtension.cs Outdated
Comment thread src/Capacitor.Cli.Core/Harness/Pi/PiReviewerExtension.cs Outdated
Comment thread src/Capacitor.Cli.Daemon/Harness/Pi/PiRpcHostedAgentRuntime.cs
Comment thread src/Capacitor.Cli.Daemon/Harness/Pi/PiRpcHostedAgentRuntimeFactory.cs Outdated
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add contained Pi reviewer lane for unattended review flows

✨ Enhancement 🐞 Bug fix 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Enables Pi as a gated, unattended review-flow reviewer on supported POSIX hosts.
• Constrains reviewers to verified read-only tools and an injected result channel.
• Shares race-safe termination verdict handling across Pi and ACP runtimes.
Diagram

sequenceDiagram
    participant Flow as Review Flow
    participant Orch as Orchestrator
    participant Factory as Pi Factory
    participant Launch as Launch Directory
    participant Pi as Pi RPC Child
    participant Ext as Reviewer Extension
    participant Result as Result MCP
    Flow->>Orch: Start Pi reviewer
    Orch->>Factory: Build review launch
    Factory->>Launch: Write manifest and extension
    Factory->>Pi: Spawn contained process
    Pi->>Ext: Load sole extension
    Ext->>Result: Discover result tools
    Ext-->>Factory: Report active tools
    Factory->>Pi: Send round prompt
    Pi->>Ext: Invoke allowed tools
    Ext->>Result: Submit verdict
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Add an ACP adapter for Pi
  • ➕ Would reuse the existing unattended ACP reviewer implementation and protocol guards.
  • ➕ Could reduce vendor-specific runtime logic if Pi later exposes ACP-compatible behavior.
  • ➖ Pi currently has no ACP endpoint, requiring a substantial protocol translation layer.
  • ➖ Would still need Pi-specific containment and tool-surface verification.
2. Contain Pi with an OS sandbox only
  • ➕ Could provide broader filesystem and process isolation as defense in depth.
  • ➕ Would reduce reliance on Pi tool-registration behavior.
  • ➖ Requires platform-specific sandbox implementations and policy maintenance.
  • ➖ Does not replace readiness checks or safe MCP tool registration.
  • ➖ Conflicts with the current cross-environment authentication and child-process requirements.

Recommendation: Keep the PR's explicit RPC extension and allowlist approach. It directly accommodates Pi's native protocol, derives the manifest and CLI allowlist from one canonical tool list, and fails closed before prompting. An OS sandbox remains a useful future defense-in-depth layer, but is not a simpler replacement for the current verified tool boundary.

Files changed (61) +7665 / -522

Enhancement (17) +1160 / -50
PiReviewerExtension.csAdd the contained Pi reviewer extension +263/-0

Add the contained Pi reviewer extension

• Introduces the sole reviewer extension, with worktree-confined read, list, and literal-search tools, approved MCP bridging, and atomic active-tool readiness reporting.

src/Capacitor.Cli.Core/Harness/Pi/PiReviewerExtension.cs

PiReviewerSystemPrompt.csDefine the isolated reviewer system prompt +18/-0

Define the isolated reviewer system prompt

• Supplies explicit unattended-review instructions that replace operator prompts and require result submission through the injected tool.

src/Capacitor.Cli.Core/Harness/Pi/PiReviewerSystemPrompt.cs

DaemonRunner.csWire Pi reviewer lifecycle into the daemon +14/-2

Wire Pi reviewer lifecycle into the daemon

• Binds Pi's opt-out flag, version-floor seeding, capability advertisement, policy version, and stale launch-directory cleanup.

src/Capacitor.Cli.Daemon/DaemonRunner.cs

PiLaunchEnvironment.csSanitize the Pi reviewer environment +15/-0

Sanitize the Pi reviewer environment

• Adds the reviewer manifest variable and removes environment variables that can redirect Pi packages, sessions, or extension transpilation.

src/Capacitor.Cli.Daemon/Harness/Pi/PiLaunchEnvironment.cs

PiReviewerCapability.csImplement Pi reviewer eligibility checks +91/-0

Implement Pi reviewer eligibility checks

• Evaluates consent, POSIX support, binary availability, verified version floor, and operator-recorded minimum with coded denial reasons.

src/Capacitor.Cli.Daemon/Harness/Pi/PiReviewerCapability.cs

PiReviewerDecision.csDefine Pi reviewer eligibility outcomes +12/-0

Define Pi reviewer eligibility outcomes

• Adds explicit decisions for allowed, disabled, unsupported, unresolved, and incompatible version states.

src/Capacitor.Cli.Daemon/Harness/Pi/PiReviewerDecision.cs

PiReviewerGuards.csDefine reviewer runtime guard settings +6/-0

Define reviewer runtime guard settings

• Encapsulates the per-round ceiling and bounded abort grace used only by unattended Pi reviewers.

src/Capacitor.Cli.Daemon/Harness/Pi/PiReviewerGuards.cs

PiReviewerLaunchDir.csManage secure per-launch reviewer directories +153/-0

Manage secure per-launch reviewer directories

• Creates owner-only launch assets, performs all-or-nothing writes, removes directories without following links, and sweeps stale epochs.

src/Capacitor.Cli.Daemon/Harness/Pi/PiReviewerLaunchDir.cs

PiReviewerLaunchPaths.csModel Pi reviewer launch paths +4/-0

Model Pi reviewer launch paths

• Defines paths for the extension, manifest, system prompt, session store, and readiness report.

src/Capacitor.Cli.Daemon/Harness/Pi/PiReviewerLaunchPaths.cs

PiReviewerManifest.csRender the reviewer extension manifest +54/-0

Render the reviewer extension manifest

• Serializes the worktree root, file tools, MCP server processes, environments, and approved tool mappings.

src/Capacitor.Cli.Daemon/Harness/Pi/PiReviewerManifest.cs

PiReviewerReadiness.csVerify Pi's live tool surface +29/-0

Verify Pi's live tool surface

• Compares the extension's readiness report with the expected canonical tool list and fails on missing or unexpected tools.

src/Capacitor.Cli.Daemon/Harness/Pi/PiReviewerReadiness.cs

PiReviewerReapedException.csRepresent guarded reviewer termination +6/-0

Represent guarded reviewer termination

• Adds a dedicated exception carrying the coded reason when a guard reaps Pi during launch.

src/Capacitor.Cli.Daemon/Harness/Pi/PiReviewerReapedException.cs

PiReviewerTool.csModel an exposed Pi reviewer tool +5/-0

Model an exposed Pi reviewer tool

• Defines the Pi name and optional MCP server/tool mapping for each permitted reviewer tool.

src/Capacitor.Cli.Daemon/Harness/Pi/PiReviewerTool.cs

PiReviewerToolSurface.csCentralize the Pi reviewer tool surface +57/-0

Centralize the Pi reviewer tool surface

• Builds one deterministic list for the manifest and CLI allowlist, preserving result-channel priority and excluding Pi built-ins.

src/Capacitor.Cli.Daemon/Harness/Pi/PiReviewerToolSurface.cs

PiRoundCeiling.csEnforce per-round reviewer deadlines +120/-0

Enforce per-round reviewer deadlines

• Tracks prompt writes, acceptance, echoes, busy periods, queued rounds, and terminal state under one synchronized timeout invariant.

src/Capacitor.Cli.Daemon/Harness/Pi/PiRoundCeiling.cs

PiRpcHostedAgentRuntime.csAdd unattended safeguards to the Pi runtime +102/-2

Add unattended safeguards to the Pi runtime

• Composes the shared verdict gate, enforces round timeouts, rejects command prompts and blocking dialogs, and performs bounded abort-and-terminate reaping without changing interactive launches.

src/Capacitor.Cli.Daemon/Harness/Pi/PiRpcHostedAgentRuntime.cs

PiRpcHostedAgentRuntimeFactory.csLaunch contained Pi review-flow reviewers +211/-46

Launch contained Pi review-flow reviewers

• Adds capability advertisement, validation, secure launch assets, containment arguments, readiness verification, prompt delivery, coded failure classification, and cleanup for review-flow launches.

src/Capacitor.Cli.Daemon/Harness/Pi/PiRpcHostedAgentRuntimeFactory.cs

Bug fix (2) +122 / -36
AgentOrchestrator.csGate every agent status against termination verdicts +40/-36

Gate every agent status against termination verdicts

• Routes all status sends through one helper, supports verdict-producing Pi runtimes, and prevents late non-failure statuses from clearing launch failures.

src/Capacitor.Cli.Daemon/Services/AgentOrchestrator.cs

ReapVerdictGate.csExtract the shared reap verdict gate +82/-0

Extract the shared reap verdict gate

• Centralizes single-shot reap claims, launch-window snapshots, status-send ordering, task publication, and bounded reason sanitization.

src/Capacitor.Cli.Daemon/Services/ReapVerdictGate.cs

Refactor (6) +255 / -351
PiMcpExtensionInstaller.csReuse the shared Pi MCP client source +7/-187

Reuse the shared Pi MCP client source

• Replaces the duplicated embedded MCP stdio client with the shared source while preserving interactive bridge behavior.

src/Capacitor.Cli.Core/Harness/Pi/PiMcpExtensionInstaller.cs

PiMcpStdioClientSource.csExtract reusable Pi MCP stdio client +209/-0

Extract reusable Pi MCP stdio client

• Adds shared embedded TypeScript for MCP handshakes, calls, failure propagation, and orphan-safe child teardown.

src/Capacitor.Cli.Core/Harness/Pi/PiMcpStdioClientSource.cs

AcpHostedAgentRuntime.csDelegate ACP termination gating to shared logic +20/-161

Delegate ACP termination gating to shared logic

• Replaces ACP-local reap synchronization and sanitization with the vendor-neutral ReapVerdictGate while preserving behavior.

src/Capacitor.Cli.Daemon/Services/AcpHostedAgentRuntime.cs

AcpHostedAgentRuntimeFactory.csGeneralize reaped-launch classification +3/-3

Generalize reaped-launch classification

• Reclassifies launch failures through ITerminationVerdictSource instead of depending directly on the ACP runtime type.

src/Capacitor.Cli.Daemon/Services/AcpHostedAgentRuntimeFactory.cs

ITerminationVerdictSource.csDefine the runtime termination-verdict contract +10/-0

Define the runtime termination-verdict contract

• Introduces a vendor-neutral interface for synchronized verdict reads and gated non-failure status sends.

src/Capacitor.Cli.Daemon/Services/ITerminationVerdictSource.cs

TerminationVerdict.csDefine vendor-neutral termination verdicts +6/-0

Define vendor-neutral termination verdicts

• Represents a coded reap reason and whether termination occurred inside the runtime's launch window.

src/Capacitor.Cli.Daemon/Services/TerminationVerdict.cs

Tests (31) +3167 / -65
canary.tsAdd extension discovery canary +24/-0

Add extension discovery canary

• Adds a probe extension that records loading and exposes a uniquely named tool for containment experiments.

docs/probes/2026-09-21-pi-reviewer/ext/canary.ts

ready.tsAdd extension readiness probe +34/-0

Add extension readiness probe

• Measures asynchronous extension startup, failure behavior, and Pi's active tool reporting lifecycle.

docs/probes/2026-09-21-pi-reviewer/ext/ready.ts

result.tsAdd probe result-channel extension +37/-0

Add probe result-channel extension

• Provides a test review-result tool and records extension loads and calls for empirical verification.

docs/probes/2026-09-21-pi-reviewer/ext/result.ts

probe.pyAdd reproducible Pi behavior probe +544/-0

Add reproducible Pi behavior probe

• Implements a scripted local provider and real Pi RPC harness for reproducing the reviewer containment measurements without model cost.

docs/probes/2026-09-21-pi-reviewer/probe.py

PiMcpExtensionInstallerTests.csAdjust MCP bridge source assertion +1/-1

Adjust MCP bridge source assertion

• Updates the installer test for the extracted MCP client constructor and generalized process arguments.

test/Capacitor.Cli.Core.Tests.Unit/Harness/Pi/PiMcpExtensionInstallerTests.cs

PiReviewerExtensionTests.csTest reviewer extension containment invariants +62/-0

Test reviewer extension containment invariants

• Pins realpath containment, symlink avoidance, literal search, spawn limits, noninteractive behavior, fail-closed loading, and readiness reporting.

test/Capacitor.Cli.Core.Tests.Unit/Harness/Pi/PiReviewerExtensionTests.cs

GatedReviewerRegistryTests.csCover Pi reviewer registry wiring +2/-1

Cover Pi reviewer registry wiring

• Verifies the Pi registry entry maps to the new daemon configuration flag.

test/Capacitor.Cli.Daemon.Tests.Unit/GatedReviewerRegistryTests.cs

PiContainmentBench.csAdd a real Pi containment test bench +367/-0

Add a real Pi containment test bench

• Builds isolated credentials, hostile repository fixtures, a scripted provider, and a stub MCP server to exercise production reviewer arguments against real Pi.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiContainmentBench.cs

PiContainmentRun.csModel containment certification results +8/-0

Model containment certification results

• Captures readiness, offered tools, request text, tool results, session location, and diagnostics from a containment run.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiContainmentRun.cs

PiHostedLaunchTests.csRemove obsolete reviewer refusal expectations +3/-39

Remove obsolete reviewer refusal expectations

• Updates interactive Pi launch coverage now that unattended review-flow support is implemented.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiHostedLaunchTests.cs

PiHostedRuntimeLiveCertTests.csApply minimum-version semantics to hosted certification +16/-7

Apply minimum-version semantics to hosted certification

• Records the installed Pi version and validates it against a cert floor rather than treating versions as exact pins.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiHostedRuntimeLiveCertTests.cs

PiReviewerCapabilityTests.csTest the Pi reviewer eligibility ladder +69/-0

Test the Pi reviewer eligibility ladder

• Covers consent, platform, availability, verified and operator floors, unresolved versions, coded denials, and acceptance of newer builds.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerCapabilityTests.cs

PiReviewerContainmentCertTests.csCertify Pi reviewer containment against real Pi +212/-0

Certify Pi reviewer containment against real Pi

• Adds gated tests proving exact tool exposure, built-in denial, path confinement, symlink safety, result delivery, session containment, and offline package suppression.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerContainmentCertTests.cs

PiReviewerLaunchDirTests.csTest secure reviewer launch-directory handling +119/-0

Test secure reviewer launch-directory handling

• Covers owner-only permissions, complete asset creation, rollback, stale cleanup, safe deletion, and path sanitization.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerLaunchDirTests.cs

PiReviewerLaunchTests.csTest Pi reviewer launch construction +336/-0

Test Pi reviewer launch construction

• Pins exact arguments and environment, capability advertisement, pre-launch validation, readiness ordering, failure classification, and cleanup.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerLaunchTests.cs

PiReviewerLiveCertTests.csAdd end-to-end Pi reviewer certification +308/-0

Add end-to-end Pi reviewer certification

• Adds a gated live test that finds a seeded defect, observes its fix in the same process, and submits round-specific findings and clean verdicts.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerLiveCertTests.cs

PiReviewerManifestTests.csTest reviewer manifest rendering +52/-0

Test reviewer manifest rendering

• Verifies root, file tools, MCP process configuration, environment, mappings, and equality with the CLI allowlist.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerManifestTests.cs

PiReviewerReadinessTests.csTest active-tool readiness verification +31/-0

Test active-tool readiness verification

• Accepts exact tool matches regardless of order and rejects unreadable, missing, or unexpected entries.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerReadinessTests.cs

PiReviewerRuntimeGuardTests.csTest Pi reviewer runtime guards +167/-0

Test Pi reviewer runtime guards

• Covers blocking dialogs, command prompts, round timeouts, launch-window classification, bounded aborts, normal exits, and interactive isolation.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerRuntimeGuardTests.cs

PiReviewerToolSurfaceTests.csTest canonical reviewer tool selection +78/-0

Test canonical reviewer tool selection

• Verifies ordering, result-channel naming, safe server prefixes, unclassified-server rejection, built-in collision prevention, and allowlist rendering.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiReviewerToolSurfaceTests.cs

PiRoundCeilingTests.csTest round timeout state transitions +161/-0

Test round timeout state transitions

• Exercises queued prompts, rejected and failed writes, delayed lifecycle frames, terminal shutdown, and the timer invariant.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiRoundCeilingTests.cs

PiRpcRuntimeFakes.csExtend Pi runtime test controls +19/-4

Extend Pi runtime test controls

• Adds selective write parking or failure, dialog frames, reviewer guards, and injected time providers to runtime fakes.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiRpcRuntimeFakes.cs

PiRpcTests.csPin the safe outbound RPC command set +10/-0

Pin the safe outbound RPC command set

• Asserts the runtime can construct only get-state, prompt, and abort commands, excluding shell and export commands.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiRpcTests.cs

PiScriptedProvider.csAdd a scripted local Pi model provider +92/-0

Add a scripted local Pi model provider

• Implements an OpenAI-compatible streaming endpoint that forces tool calls and records Pi's actual requests.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiScriptedProvider.cs

PiScriptedStep.csModel scripted provider responses +7/-0

Model scripted provider responses

• Defines plain response and forced tool-call steps for containment certification.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/PiScriptedStep.cs

ReviewerCertFloor.csShare live-cert version-floor validation +19/-0

Share live-cert version-floor validation

• Provides minimum-version checks for Pi live certifications, while allowing pending first-run baselines.

test/Capacitor.Cli.Daemon.Tests.Unit/Harness/Pi/ReviewerCertFloor.cs

AgentOrchestratorPiVerdictTests.csTest Pi verdict propagation through orchestration +210/-0

Test Pi verdict propagation through orchestration

• Verifies launch-failure reporting, post-window teardown, Running and Completed suppression, reconnect behavior, and status-publication atomicity.

test/Capacitor.Cli.Daemon.Tests.Unit/Services/AgentOrchestratorPiVerdictTests.cs

AgentStatusSendPathTests.csEnforce a single status-send path +26/-0

Enforce a single status-send path

• Pins all AgentStatusChangedAsync calls to the orchestrator's verdict-aware helper.

test/Capacitor.Cli.Daemon.Tests.Unit/Services/AgentStatusSendPathTests.cs

CaptureServerConnection.csGeneralize verdict-aware server capture +2/-2

Generalize verdict-aware server capture

• Updates the status-race test seam to observe any ITerminationVerdictSource, including Pi.

test/Capacitor.Cli.Daemon.Tests.Unit/Services/CaptureServerConnection.cs

ReapVerdictGateTests.csTest shared reap verdict synchronization +119/-0

Test shared reap verdict synchronization

• Covers single claims, launch-window snapshots, starter failures, status-send exclusion, publication races, reap tasks, and reason sanitization.

test/Capacitor.Cli.Daemon.Tests.Unit/Services/ReapVerdictGateTests.cs

PiMemoryIndexLiveCertTests.csUse floor semantics for Pi memory certification +32/-11

Use floor semantics for Pi memory certification

• Renames the version baseline as a minimum floor and rejects live runs below it while accepting newer Pi builds.

test/Capacitor.Cli.Tests.Unit/Harness/Pi/PiMemoryIndexLiveCertTests.cs

Documentation (3) +2945 / -15
README.mdDocument unattended Pi reviewer behavior +52/-15

Document unattended Pi reviewer behavior

• Documents Pi review-flow support, containment guarantees, opt-out configuration, version floors, worktree restrictions, and the result-channel bridge.

README.md

findings.mdRecord Pi containment probe findings +343/-0

Record Pi containment probe findings

• Documents 36 experimental arms covering extension discovery, tool clamping, prompt inheritance, sessions, offline behavior, readiness, and RPC lifecycle semantics.

docs/probes/2026-09-21-pi-reviewer/findings.md

summary.jsonStore Pi probe evidence +2550/-0

Store Pi probe evidence

• Records the complete machine-readable output from the Pi 0.85.1 containment probe run.

docs/probes/2026-09-21-pi-reviewer/summary.json

Other (2) +16 / -5
GatedReviewers.csRegister Pi as a gated reviewer +4/-2

Register Pi as a gated reviewer

• Adds Pi and its opt-out environment variable to the shared gated-reviewer registry and usage list.

src/Capacitor.Cli.Core/GatedReviewers.cs

DaemonConfig.csConfigure Pi reviewer gating and timeout +12/-3

Configure Pi reviewer gating and timeout

• Adds the enabled-by-default Pi reviewer switch and configurable per-turn timeout.

src/Capacitor.Cli.Daemon/DaemonConfig.cs

realtonyyoung and others added 3 commits September 22, 2026 00:01
read_file streamed a whole hostile file into memory before applying its
line/byte caps and counted bytes as UTF-16 length; it now reads through a
fixed buffer, refuses on a bounded binary prefix, and measures returned
size with Buffer.byteLength. globMatches backtracked combinatorially on a
crafted "**" run; it is now memoised by (glob-seg, path-seg), refuses an
over-complex pattern, and carries the search deadline so a match aborts
with the budget.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A normal Pi reviewer death did not claim the reap slot, so a racing round
timer, a buffered dialog, or a command-shaped input could still publish a
verdict over an ordinary teardown, and dispose sampled the reap once and
could miss a later claim. The gate now seals under its lock — EnterTerminal
seals before disarming the ceiling, dispose awaits the reap the seal
returns — so a claim after teardown is refused.

The ceiling's UserEcho rode the 16-entry transcript-dedup cache, so past
16 queued rounds an evicted echo left `owed` stuck and reaped a settled
reviewer. Round accounting now rides its own uncapped tally.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A null/empty/whitespace prompt slipped past reviewer-context validation, so
the launch skipped the first-prompt send and returned an idle runtime with
no round started and no ceiling armed — the round then hung forever.
Validation now refuses a blank prompt with the launch-context-incomplete
code before the launch directory is created, and the first-prompt send is
unconditional once validation passes. The launch tests also move the env
test onto EnvScope.Exclusive so it no longer discards inherited values.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
realtonyyoung and others added 3 commits September 22, 2026 00:01
Use the shared JsonElement.IsArray helper in the containment bench, bound
the two real-child cert classes to the shared subprocess budget with
ParallelLimiter<SubprocessLimit>, inject TempDir into the launch-dir tests
instead of constructing one per test, and rewrite the fixture doc comments
to describe the containment purpose rather than a dated probe path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A line-based offset is honoured by scanning to it, so a large offset on a
large file traversed the whole file regardless of the returned-byte cap,
pinning the reviewer's event loop and delaying its abort. read_file now
refuses a file over a 1 MB read ceiling before opening it and caps total
bytes scanned per call as a backstop against a file that grew past its
stat size.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
DisposeAsync abandoned an already-won reap after a fixed 5s wait, so a
slow-but-legitimate teardown could be cut short before the promised
terminate ran, and a fault after the timeout went unobserved. It now
attaches an unconditional fault-observing continuation before the wait and
sizes the wait to the reap's own bounded ladder (abort grace + stop grace),
so a normal teardown is not cut short while a stuck one still cannot hang.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant