Skip to content

refactor(codex): count native child tokens in run metrics - #8569

Merged
waynesun09 merged 10 commits into
fullsend-ai:mainfrom
dhshah13:refactor/6970-codex-child-usage
Oct 20, 2026
Merged

waynesun09 merged 10 commits into
fullsend-ai:mainfrom
dhshah13:refactor/6970-codex-child-usage

Conversation

@dhshah13

@dhshah13 dhshah13 commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds Codex sub-agent token usage to the run totals and per_model_usage, read from each child's rollout inside the sandbox after codex exits. A failed or partial read prints a warning, keeps the children it read, and never fails the run. No agent on main can spawn yet (#7829 turns codex's multi-agent tools off), so at merge the only change is a parent-only per_model_usage for a Codex agent with registered roles.

Related Issue

Part of #6970.

Changes

  • Child ids come from completed spawn_agent items, read off a tee of the --json stream.
  • The fold also runs after a non-zero codex exit: codex writes a child's token_usage_record as each response completes.
  • Usage source: each child's last token_usage_record (the thread's cumulative total), not the token_count ADR 0126 names, because codex zeroes token_count's counters when a request overflows the context window.
  • docs/cli/run.md documents codex per_model_usage. docs/runtimes/codex.md and docs/contributing/runtime-implementation.md change in the codex runtime: run the review/retro sub-agent rosters through codex's native spawn_agent roles #6970 PR that turns delegation on.

Testing

  • make lint passes
  • Tests added in internal/runtime/codex_subagents_test.go

Checklist

  • PR title follows Conventional Commits (correct type, ! for breaking changes)
  • Commits are signed off (DCO) — human and human-directed agent sessions only
  • I wrote this contribution myself and can explain all changes in it

🤖 Generated with Claude Code

A Codex child is a separate thread: its tokens never reach the parent's
exec --json stream and live only in the child's rollout. This adds the
read and the fold, called by nothing yet: codexChildUsageReadCommand
(one bounded in-sandbox command, ids validated and shell-quoted),
parseCodexChildUsage (the first turn_context, the last token_count),
codexChildIDs (the completed spawn_agent receivers off a tee of the
stream) and foldCodexChildUsage (the parent's entry first and always,
one request per child thread with usage, child reasoning to the run
total only), plus delegating() on the runner-held digest set.

Fixtures: four child rollouts modelled on the 0.157.0 paid probe and
one stream with completed and failed spawns.

Signed-off-by: Dharit Shah <dhshah@redhat.com>
When a Codex agent has registered sub-agent roles or its exec --json
stream reports a completed spawn, Run reads the children's rollouts with
one bounded sandbox command after codex exits and folds each child's
last cumulative usage into the totals and per_model_usage. The ids come
off a tee of the stream; parseCodexStream's signature is unchanged. A
failed read is a printer warning, never a failed run, and a killed,
cancelled or timed-out iteration reports the parent's tokens only.

Inert until the multi-agent tools are turned on: no agent on main can
spawn, so the one visible change is that a delegating agent's
metrics.json gains per_model_usage with the parent's entry.

Signed-off-by: Dharit Shah <dhshah@redhat.com>
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Count Codex sub-agent tokens in run metrics

✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Include Codex child-thread tokens in run totals and per-model usage after successful runs.
• Preserve parent-only metrics when rollout reads fail or Codex exits unsuccessfully.
• Document the accounting rules and test stream collection, rollout parsing, and run behavior.
Diagram

graph TD
  RUN["Codex Run"] --> STREAM["Stream collector"] --> GATE{"Clean exit and delegation?"} -->|yes| READ["Bounded rollout read"] --> FOLD["Usage fold"] --> METRICS["Run metrics"]
  ROLES["Registered roles"] --> GATE
  GATE -->|no| METRICS
  READ -->|read failure| FOLD
Loading
High-Level Assessment

The single bounded post-run read is appropriate because the parent stream excludes child tokens and the rollouts hold their cumulative usage. Per-child sandbox commands would add overhead; failing the run on an accounting read would unnecessarily change its outcome.

Files changed (11) +978 / -8

Enhancement (3) +310 / -0
codex_integrity.goIdentify delegation from runner-held roles +4/-0

Identify delegation from runner-held roles

• Adds a helper that determines whether Codex registered sub-agent roles using the runner-held digest set rather than the agent-writable manifest.

internal/runtime/codex_integrity.go

codex_run.goFold child usage after a successful Codex run +20/-0

Fold child usage after a successful Codex run

• Tees the parent stream to collect child IDs without changing the event parser. After a clean exit, folds child usage when roles or spawns indicate delegation; read failures produce a warning without failing the run.

internal/runtime/codex_run.go

codex_subagents.goRead and account for native child-thread usage +286/-0

Read and account for native child-thread usage

• Adds bounded rollout retrieval, completed-spawn ID collection, and parsing of each child's model and last cumulative token snapshot. Folds available usage into run totals and per-model entries while retaining the parent entry on read failure.

internal/runtime/codex_subagents.go

Tests (6) +631 / -0
codex_subagents_test.goTest child usage collection and run accounting +597/-0

Test child usage collection and run accounting

• Covers shell command execution, ID validation, stream scanning, token arithmetic, retries, and read failures. End-to-end tests verify successful folds, parent-only breakdowns, warnings, and nonzero exits.

internal/runtime/codex_subagents_test.go

child_usage_failed.jsonlFixture for a child without token usage +5/-0

Fixture for a child without token usage

• Represents a child whose model request fails before a token-count event, so it contributes neither tokens nor a request.

internal/runtime/testdata/codex/child_usage_failed.jsonl

child_usage_no_model.jsonlFixture for usage without a model +2/-0

Fixture for usage without a model

• Provides a token-count event without turn context to verify that usage is attributed to the unknown-model bucket.

internal/runtime/testdata/codex/child_usage_no_model.jsonl

child_usage_other_model.jsonlFixture for a child on a different model +6/-0

Fixture for a child on a different model

• Supplies nonzero token categories for a child whose model differs from the parent's, exercising a separate per-model entry.

internal/runtime/testdata/codex/child_usage_other_model.jsonl

child_usage_same_model.jsonlFixture for cumulative same-model usage +7/-0

Fixture for cumulative same-model usage

• Contains two cumulative token snapshots for a child on the parent's model, verifying that only the last snapshot is folded.

internal/runtime/testdata/codex/child_usage_same_model.jsonl

collab_spawn.ndjsonFixture for completed and failed collaboration calls +14/-0

Fixture for completed and failed collaboration calls

• Provides completed and failed spawns, wait and close calls, and parent usage to test child-ID selection and run-level behavior.

internal/runtime/testdata/codex/collab_spawn.ndjson

Documentation (2) +37 / -8
run.mdDocument Codex per-model accounting +16/-8

Document Codex per-model accounting

• Adds Codex to the runtimes that emit per-model usage and explains its model keys, zero dollar cost, child request counts, unknown-model bucket, and parent-only metrics on cancellation or timeout.

docs/cli/run.md

README.mdDescribe Codex child-accounting fixtures +21/-0

Describe Codex child-accounting fixtures

• Documents the spawn stream and rollout fixtures, their provenance, and the usage cases each represents.

internal/runtime/testdata/codex/README.md

@fullsend-ai-review

fullsend-ai-review Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 2:35 PM UTC · Completed 2:51 PM UTC

Commit: fc09465 · View workflow run →

Runtime: pi · Model: sonnet → claude-sonnet-5-5 · Effort: high · Cost: $3.17

@qodo-code-review

qodo-code-review Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

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

Grey Divider


Remediation recommended

1. Regressed child counters undercount tokens ✓ Resolved
Description
codexChildUsageReadCommand selects only the last cumulative token_count snapshot for each child,
unlike the parent stream processor, which retains per-field high-water values. If a child's later
snapshot reports a lower counter, its previously recorded usage is lost from the run totals and
per-model entry.
Code

internal/runtime/codex_subagents.go[86]

+		`for id in %s; do command -p find %s -type f -name "rollout-*-$id.jsonl" 2>/dev/null | while IFS= read -r f; do printf '%%s %%s\n' %s "$id"; command -p grep -a -e '"type":"turn_context"' -- "$f" 2>/dev/null | command -p head -n 1; command -p grep -a -e '"type":"token_count"' -- "$f" 2>/dev/null | command -p tail -n 1; done; done | command -p head -c %d`,
Evidence
The existing parent processor explicitly guards against cumulative snapshots dropping, but the new
child command discards every snapshot except the last before its parser can apply the same
protection.

internal/runtime/codex_progress.go[116-133]
internal/runtime/codex_progress.go[590-599]
internal/runtime/codex_subagents.go[85-87]

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

## Issue description
Selecting the last child snapshot can discard usage when a cumulative counter regresses.
## Fix Focus Areas
- internal/runtime/codex_subagents.go[85-87]
- internal/runtime/codex_subagents.go[125-133]
## Recommended Fix
Compute a per-field high-water snapshot across each child's token-count events before folding it, consistent with the parent stream's cumulative-counter handling, while keeping the runner-side read bounded.

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


2. A sandbox read error can expose credentials ✗ Dismissed
Description
foldCodexChildUsage places captured stderr into an error after applying only sanitizeOutput,
and Run forwards that error to StepWarn. When the sandbox command emits credential-bearing text,
the warning path can publish it because sanitizeOutput removes formatting characters but does not
perform secret redaction.
Code

internal/runtime/codex_subagents.go[R252-257]

+	stdout, stderr, exitCode, err := sandbox.Exec(sandboxName, cmd, 10*time.Second)
+	if err != nil {
+		return 0, fmt.Errorf("reading the child rollouts: %w", err)
+	}
+	if exitCode != 0 {
+		return 0, fmt.Errorf("reading the child rollouts: exited %d: %s", exitCode, strings.TrimSpace(sanitizeOutput(stderr)))
Evidence
The changed code captures sandbox stderr, embeds it in the returned error, and emits that error
through the user-facing warning printer. The documented Go credential-redaction guidance requires
secret replacement and redactor scanning, while sanitizeOutput only removes formatting/control
sequences.

Rule 3092695: Consult Go credential redaction guide for external-facing code changes
internal/runtime/codex_subagents.go[252-257]
internal/runtime/codex_run.go[667-671]
internal/runtime/sanitize.go[9-16]
docs/contributing/go-code.md[465-493]

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 child-rollout read error includes captured sandbox `stderr`, and the warning path only applies formatting sanitization rather than the credential-redaction process required for external output. Credential-bearing subprocess output could therefore appear in run warnings.

## Fix Focus Areas
- internal/runtime/codex_subagents.go[252-257]
- internal/runtime/codex_run.go[667-671]
- docs/contributing/go-code.md[465-493]

## Recommended Fix
Apply the repository's prescribed secret replacement and `security.SecretRedactor` scanning to captured `stderr` and the final warning text before sending it to `StepWarn`. Preserve useful non-sensitive error context while ensuring runner, provider, and registered runtime secrets are removed.

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


3. Missing child rollouts go unwarned ✗ Dismissed
Description
codexChildUsageReadCommand suppresses find and grep errors, and the pipeline reports the final
head command's success even when no rollout was read. If a completed spawn's rollout is missing or
unreadable, foldCodexChildUsage silently omits that child's tokens instead of reaching the warning
path.
Code

internal/runtime/codex_subagents.go[86]

+		`for id in %s; do command -p find %s -type f -name "rollout-*-$id.jsonl" 2>/dev/null | while IFS= read -r f; do printf '%%s %%s\n' %s "$id"; command -p grep -a -e '"type":"turn_context"' -- "$f" 2>/dev/null | command -p head -n 1; command -p grep -a -e '"type":"token_count"' -- "$f" 2>/dev/null | command -p tail -n 1; done; done | command -p head -c %d`,
Evidence
The shell command hides lookup and read errors behind the final head; the fold warns only on a
nonzero command result and otherwise skips records without usage. The new test also demonstrates
that a requested ID with no rollout yields no record.

internal/runtime/codex_subagents.go[85-87]
internal/runtime/codex_subagents.go[252-263]
internal/runtime/codex_subagents_test.go[114-140]

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

## Issue description
A completed spawn can have a missing or unreadable rollout, but the shell pipeline succeeds and no warning is emitted.
## Fix Focus Areas
- internal/runtime/codex_subagents.go[85-87]
- internal/runtime/codex_subagents.go[248-263]
## Recommended Fix
Preserve read failures and check that each requested child ID has a successfully read rollout; return an error for missing or unreadable rollouts so Run can warn while retaining the parent metrics.

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


View medium (1)
4. Truncated reads silently lose child tokens ✓ Resolved
Description
codexChildUsageReadCommand caps the combined output at 1 MiB, while parseCodexChildUsage returns
parsed records without indicating that the output was cut short. If selected rollout lines exceed
that cap, later children—or a cut-off usage line—are omitted from both token totals and the
breakdown without a warning.
Code

internal/runtime/codex_subagents.go[R85-87]

+	return fmt.Sprintf(
+		`for id in %s; do command -p find %s -type f -name "rollout-*-$id.jsonl" 2>/dev/null | while IFS= read -r f; do printf '%%s %%s\n' %s "$id"; command -p grep -a -e '"type":"turn_context"' -- "$f" 2>/dev/null | command -p head -n 1; command -p grep -a -e '"type":"token_count"' -- "$f" 2>/dev/null | command -p tail -n 1; done; done | command -p head -c %d`,
+		strings.Join(quoted, " "), shellQuote(sessionsDir), shellQuote(codexChildUsageMarker), codexChildUsageMaxBytes), nil
Evidence
The cap applies to all children together. The parser skips malformed or cut-off lines and has no
error return, and the fold counts only the records it received.

internal/runtime/codex_subagents.go[40-44]
internal/runtime/codex_subagents.go[85-87]
internal/runtime/codex_subagents.go[94-135]
internal/runtime/codex_subagents.go[259-285]

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 output cap can discard child usage while the fold treats the bounded read as complete.
## Fix Focus Areas
- internal/runtime/codex_subagents.go[85-87]
- internal/runtime/codex_subagents.go[94-135]
- internal/runtime/codex_subagents.go[252-285]
## Recommended Fix
Make truncation detectable, check scanner errors, and return a read error when the bounded output is incomplete. Keep the existing successful-run behavior while surfacing the loss through Run's warning.

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


Grey Divider

Context sources
❌ Tickets: failed to load — Ticket collection could not establish complete evidence
✅ Compliance rules (platform): 88 rules
✅ Skills: 5 invoked
  writing-user-docs
  writing-adrs
  check-patch-coverage
  cutting-releases
  adr-corner
✅ Cross-repo context — repo relationships
  Explored: repo: fullsend-ai/agents (sha: 2da538b8) — View relationship
Review mode: Auto: ⚖️ Balanced: Downgraded extended -> standard: change is below the extended eligibility bar (hunks 14/18, lines 986/200; both must reach the floor). Router rationale: Complex runtime accounting spans parsing, sandbox execution, metrics, and failure paths.

Grey Divider

Tip of the day
💡 Did you know, you can open the rule or relationship behind a finding in one click

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread internal/runtime/codex_subagents.go Outdated
Comment thread internal/runtime/codex_subagents.go Outdated
Comment thread internal/runtime/codex_subagents.go Outdated
Comment thread internal/runtime/codex_subagents.go Outdated
@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Site preview

Preview: https://16a5ab64-site.fullsend-ai.workers.dev

Commit: 949bd95b55b5d0f94c391f5f67e594a844e65343

@codecov

codecov Bot commented Oct 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@fullsend-ai-review fullsend-ai-review Bot added the risk/moderate PR risk: moderate label Oct 19, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

<!-- fullsend:risk-assessment -->
Risk Assessment: moderate (2/5)

Details

Large diff and high historical churn in touched runner files are balanced by zero protected or security paths, strong alignment with tracking issue #6970, and additive metrics counting that remains inert until native multi-agent tools are enabled.

Previous run

<!-- fullsend:risk-assessment -->
Risk Assessment: moderate (2/5)

Details

Large diff and high historical churn in touched runner files are balanced by zero protected or security paths, strong alignment with tracking issue #6970, and additive metrics counting that remains inert until multi-agent tools are enabled.

Previous run (2)

<!-- fullsend:risk-assessment -->
Risk Assessment: moderate (2/5)

Details

Large diff and high historical churn in touched runner files are balanced by zero protected or security paths, strong alignment with tracking issue #6970, and additive metrics counting that remains inert until multi-agent tools are enabled.

Previous run (3)

<!-- fullsend:risk-assessment -->
Risk Assessment: moderate (2/5)

Details

Large diff and high historical churn in touched runner files are balanced by zero protected or security paths, strong alignment with tracking issue #6970, and additive metrics counting that remains inert until multi-agent tools are enabled.

Previous run (4)

<!-- fullsend:risk-assessment -->
Risk Assessment: moderate (2/5)

Details

Large diff and high historical churn in touched runner files are balanced by zero protected or security paths, strong alignment with tracking issue #6970, and additive metrics counting that remains inert until multi-agent tools are enabled.

Previous run (5)

<!-- fullsend:risk-assessment -->
Risk Assessment: moderate (2/5)

Details

Moderate risk reflects a medium-to-large additive change primarily composed of tests with no protected or security-sensitive paths, balanced against elevated churn and coupling in touched runner files.

Previous run (6)

<!-- fullsend:risk-assessment -->
Risk Assessment: moderate (2/5)

Details

Moderate risk: large change size and elevated churn in touched documentation and runtime files are mitigated by zero protected or security-sensitive paths, comprehensive test coverage, and clear alignment with a structured multi-PR issue breakdown.

@fullsend-ai-review

fullsend-ai-review Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Review

Findings

Low

  • [stale-doc] docs/runtimes/codex.md:283 — The "Keep review and retro on Claude Code" paragraph says fullsend does not yet support "persona wiring or child token accounting". This PR adds child token accounting, so that clause becomes inaccurate at merge, although delegation stays off. The PR body defers this doc to the codex runtime: run the review/retro sub-agent rosters through codex's native spawn_agent roles #6970 PR that turns delegation on.
    Remediation: Drop "or child token accounting" from the sentence, or note that child usage is folded into per_model_usage once delegation is enabled.
  • [incomplete-doc] docs/contributing/runtime-implementation.md:1241 — The codex internals section does not describe the new child-rollout usage fold (spawn_agent id tee, in-sandbox read command, last token_usage_record rule, warning-only failures), and still says spawn_agent is "not reachable in v1". The PR body defers this to the codex runtime: run the review/retro sub-agent rosters through codex's native spawn_agent roles #6970 PR that turns delegation on.
    Remediation: Add a short subsection on the child usage fold, or confirm it lands in the delegation PR.

Earlier findings

  • f_d8b1f40a55c7bea8 — resolved_by_change: the read command now treats an id with several rollouts as unreadable, reads the last two lines of each record type, and the parser falls back past a torn line.
  • f_381c7f3b793a8010 — resolved_by_change: foldCodexChildUsage now folds the stdout from a failed or timed-out read and returns a warning afterwards.
Previous run

<!-- fullsend:review-findings-v2:eyJ2ZXJzaW9uIjoyLCJhY3Rpb24iOiJyZXF1ZXN0LWNoYW5nZXMiLCJmaW5kaW5ncyI6W3sic2V2ZXJpdHkiOiJtZWRpdW0iLCJjYXRlZ29yeSI6ImVkZ2UtY2FzZSIsImZpbGUiOiJpbnRlcm5hbC9ydW50aW1lL2NvZGV4X3N1YmFnZW50cy5nbyIsImlkIjoiZl9kOGIxZjQwYTU1YzdiZWE4IiwibGluZSI6NzYsImFjdGlvbmFibGUiOnRydWV9LHsic2V2ZXJpdHkiOiJsb3ciLCJjYXRlZ29yeSI6ImxvZ2ljLWVycm9yIiwiZmlsZSI6ImludGVybmFsL3J1bnRpbWUvY29kZXhfc3ViYWdlbnRzLmdvIiwiaWQiOiJmXzM4MWM3ZjNiNzkzYTgwMTAiLCJsaW5lIjoyMjUsImFjdGlvbmFibGUiOmZhbHNlfSx7InNldmVyaXR5IjoibG93IiwiY2F0ZWdvcnkiOiJzdGFsZS1kb2MiLCJmaWxlIjoiZG9jcy9ydW50aW1lcy9jb2RleC5tZCIsImlkIjoiZl81MTM5ZWM1OWU2ODFkN2Q5IiwibGluZSI6MjgxLCJhY3Rpb25hYmxlIjpmYWxzZX0seyJzZXZlcml0eSI6ImxvdyIsImNhdGVnb3J5IjoiaW5jb21wbGV0ZS1kb2MiLCJmaWxlIjoiZG9jcy9jb250cmlidXRpbmcvcnVudGltZS1pbXBsZW1lbnRhdGlvbi5tZCIsImlkIjoiZl8xZjRhZDIxODMzMzFkZjBmIiwibGluZSI6MTA4MCwiYWN0aW9uYWJsZSI6ZmFsc2V9LHsic2V2ZXJpdHkiOiJtZWRpdW0iLCJjYXRlZ29yeSI6ImxvZ2ljLWVycm9yIiwiZmlsZSI6ImludGVybmFsL3J1bnRpbWUvY29kZXhfcnVuLmdvIiwiaWQiOiJmX2ZkYmY3N2Y5ZDJhZDE3YzIiLCJsaW5lIjo2NjcsImFjdGlvbmFibGUiOnRydWV9LHsic2V2ZXJpdHkiOiJsb3ciLCJjYXRlZ29yeSI6InNlY3JldC1leHBvc3VyZSIsImZpbGUiOiJpbnRlcm5hbC9ydW50aW1lL2NvZGV4X3N1YmFnZW50cy5nbyIsImlkIjoiZl8yZjczZjJkMTE3OGI5Y2NhIiwibGluZSI6MzA0LCJhY3Rpb25hYmxlIjpmYWxzZX1dLCJkaXNwb3NpdGlvbnMiOlt7ImlkIjoiZl81MTM5ZWM1OWU2ODFkN2Q5Iiwic3RhdHVzIjoib3BlbiJ9LHsiaWQiOiJmXzFmNGFkMjE4MzMzMWRmMGYiLCJzdGF0dXMiOiJvcGVuIn0seyJpZCI6ImZfZmRiZjc3ZjlkMmFkMTdjMiIsInN0YXR1cyI6InJlc29sdmVkX2J5X2NoYW5nZSJ9LHsiaWQiOiJmXzJmNzNmMmQxMTc4YjljY2EiLCJzdGF0dXMiOiJyZXNvbHZlZF9ieV9jaGFuZ2UifV19 -->

Review

Findings

Medium

  • [edge-case] internal/runtime/codex_subagents.go:76 — The read command picks the last line that matches token_usage_record before checking that it is valid JSON (grep ... | tail -n 1). If a rollout ends with a partly written record, for example after a cancel or kill, parseCodexChildUsage drops that line and the child's earlier valid cumulative record never reaches the parser. The child then counts nothing. No warning is raised: the unreadable and over-max counters don't cover this case.
    Remediation: Select the last record that decodes successfully rather than the last matching text line, keeping the output bound. Add a command-level fixture test with a complete usage record followed by a truncated matching record, and assert that the earlier usage is kept.

Low

  • [logic-error] internal/runtime/codex_subagents.go:225 — When the rollout read fails, every child already read is thrown away. sandbox.ExecContext returns the captured stdout on a timeout (exit 124), but the early returns at lines 225-230 skip parsing it. The PR body says a partial read "keeps the children it read". The test for a non-zero read exit locks in the discard. Impact is small: the run gets a warning and only the metrics are undercounted.
    Remediation: Parse and fold the complete records in stdout even when Exec returns an error or a non-zero exit, and return the read failure as a warning alongside the folded count. Add a test whose fake read prints one complete child record and then fails.
  • [stale-doc] docs/runtimes/codex.md:281 — Still says native delegation is off partly because codex "does not yet support ... child token accounting". This PR adds that accounting. The PR body defers the doc change to the codex runtime: run the review/retro sub-agent rosters through codex's native spawn_agent roles #6970 PR that turns delegation on. (id: f_5139ec59e681d7d9)
  • [incomplete-doc] docs/contributing/runtime-implementation.md:1080 — The Codex runtime internals section does not describe the post-exit child rollout read and the fold into per_model_usage (foldCodexChildUsage, codexChildUsageReadCommand). The PR body defers this to the codex runtime: run the review/retro sub-agent rosters through codex's native spawn_agent roles #6970 PR. (id: f_1f4ad2183331df0f)

Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR
Previous run (2)

<!-- fullsend:review-findings-v2:eyJ2ZXJzaW9uIjoyLCJhY3Rpb24iOiJhcHByb3ZlIiwiZmluZGluZ3MiOlt7InNldmVyaXR5IjoibG93IiwiY2F0ZWdvcnkiOiJzdGFsZS1kb2MiLCJmaWxlIjoiZG9jcy9ydW50aW1lcy9jb2RleC5tZCIsImlkIjoiZl81MTM5ZWM1OWU2ODFkN2Q5IiwibGluZSI6MjgxLCJhY3Rpb25hYmxlIjpmYWxzZX0seyJzZXZlcml0eSI6ImxvdyIsImNhdGVnb3J5IjoiaW5jb21wbGV0ZS1kb2MiLCJmaWxlIjoiZG9jcy9jb250cmlidXRpbmcvcnVudGltZS1pbXBsZW1lbnRhdGlvbi5tZCIsImlkIjoiZl8xZjRhZDIxODMzMzFkZjBmIiwibGluZSI6MTA4MCwiYWN0aW9uYWJsZSI6ZmFsc2V9LHsic2V2ZXJpdHkiOiJtZWRpdW0iLCJjYXRlZ29yeSI6ImxvZ2ljLWVycm9yIiwiZmlsZSI6ImludGVybmFsL3J1bnRpbWUvY29kZXhfcnVuLmdvIiwiaWQiOiJmX2ZkYmY3N2Y5ZDJhZDE3YzIiLCJsaW5lIjo2NjcsImFjdGlvbmFibGUiOnRydWV9LHsic2V2ZXJpdHkiOiJsb3ciLCJjYXRlZ29yeSI6InNlY3JldC1leHBvc3VyZSIsImZpbGUiOiJpbnRlcm5hbC9ydW50aW1lL2NvZGV4X3N1YmFnZW50cy5nbyIsImlkIjoiZl8yZjczZjJkMTE3OGI5Y2NhIiwibGluZSI6MzA0LCJhY3Rpb25hYmxlIjpmYWxzZX1dLCJkaXNwb3NpdGlvbnMiOlt7ImlkIjoiZl81MTM5ZWM1OWU2ODFkN2Q5Iiwic3RhdHVzIjoib3BlbiJ9LHsiaWQiOiJmXzFmNGFkMjE4MzMzMWRmMGYiLCJzdGF0dXMiOiJvcGVuIn0seyJpZCI6ImZfZmRiZjc3ZjlkMmFkMTdjMiIsInN0YXR1cyI6InJlc29sdmVkX2J5X2NoYW5nZSJ9LHsiaWQiOiJmXzJmNzNmMmQxMTc4YjljY2EiLCJzdGF0dXMiOiJyZXNvbHZlZF9ieV9jaGFuZ2UifV19 -->

Review

Findings

Low

  • [stale-doc] docs/runtimes/codex.md:281 — The sentence saying delegation is off because Codex "does not yet support persona wiring or child token accounting" is partly stale now that this PR folds child rollout usage into RunMetrics/per_model_usage. Delegation itself is still off, so the rest of the sentence holds. The PR body defers this doc to the later codex runtime: run the review/retro sub-agent rosters through codex's native spawn_agent roles #6970 PR that turns delegation on.
    Remediation: drop "child token accounting" from the reason when delegation is enabled (or now).
  • [incomplete-doc] docs/contributing/runtime-implementation.md:1080 — The "codex runtime internals" section and its one-iteration flowchart do not describe the post-exit child-rollout fold (marker lines, 1 MiB bound, max-token check, last-turn_context model, warn-only failure). The PR body defers this doc to the later codex runtime: run the review/retro sub-agent rosters through codex's native spawn_agent roles #6970 PR.
    Remediation: add a short subsection and a fold step in the flowchart when delegation lands.
Previous run (3)

<!-- fullsend:review-findings-v2:eyJ2ZXJzaW9uIjoyLCJhY3Rpb24iOiJhcHByb3ZlIiwiZmluZGluZ3MiOlt7InNldmVyaXR5IjoibG93IiwiY2F0ZWdvcnkiOiJzdGFsZS1kb2MiLCJmaWxlIjoiZG9jcy9ydW50aW1lcy9jb2RleC5tZCIsImlkIjoiZl81MTM5ZWM1OWU2ODFkN2Q5IiwibGluZSI6MjcxLCJhY3Rpb25hYmxlIjpmYWxzZX0seyJzZXZlcml0eSI6ImxvdyIsImNhdGVnb3J5IjoiaW5jb21wbGV0ZS1kb2MiLCJmaWxlIjoiZG9jcy9jb250cmlidXRpbmcvcnVudGltZS1pbXBsZW1lbnRhdGlvbi5tZCIsImlkIjoiZl8xZjRhZDIxODMzMzFkZjBmIiwibGluZSI6MTA4MywiYWN0aW9uYWJsZSI6ZmFsc2V9LHsic2V2ZXJpdHkiOiJtZWRpdW0iLCJjYXRlZ29yeSI6ImxvZ2ljLWVycm9yIiwiZmlsZSI6ImludGVybmFsL3J1bnRpbWUvY29kZXhfcnVuLmdvIiwiaWQiOiJmX2ZkYmY3N2Y5ZDJhZDE3YzIiLCJsaW5lIjo2NjcsImFjdGlvbmFibGUiOnRydWV9LHsic2V2ZXJpdHkiOiJsb3ciLCJjYXRlZ29yeSI6InNlY3JldC1leHBvc3VyZSIsImZpbGUiOiJpbnRlcm5hbC9ydW50aW1lL2NvZGV4X3N1YmFnZW50cy5nbyIsImlkIjoiZl8yZjczZjJkMTE3OGI5Y2NhIiwibGluZSI6MzA0LCJhY3Rpb25hYmxlIjpmYWxzZX1dLCJkaXNwb3NpdGlvbnMiOlt7ImlkIjoiZl9mZGJmNzdmOWQyYWQxN2MyIiwic3RhdHVzIjoicmVzb2x2ZWRfYnlfY2hhbmdlIn0seyJpZCI6ImZfMmY3M2YyZDExNzhiOWNjYSIsInN0YXR1cyI6InJlc29sdmVkX2J5X2NoYW5nZSJ9LHsiaWQiOiJmXzUxMzllYzU5ZTY4MWQ3ZDkiLCJzdGF0dXMiOiJvcGVuIn0seyJpZCI6ImZfMWY0YWQyMTgzMzMxZGYwZiIsInN0YXR1cyI6Im9wZW4ifV19 -->

Review

Findings

Low

  • [stale-doc] docs/runtimes/codex.md:271 (f_5139ec59e681d7d9) — The text says native delegation is off because Codex "does not yet support persona wiring or child token accounting". This PR adds the child token accounting, and metrics.json now gains per_model_usage for a delegating agent. The deferral to a later PR in the codex runtime: run the review/retro sub-agent rosters through codex's native spawn_agent roles #6970 series is stated in the PR body. Persona wiring is still missing, so the sentence is only partly stale.
    Remediation: Drop the child-token-accounting clause in the PR that makes delegation reachable, or in this one.
  • [incomplete-doc] docs/contributing/runtime-implementation.md:1083 (f_1f4ad2183331df0f) — The codex flowchart artifacts node lists metrics.json (runtime: codex) and does not mention the child rollout read or per_model_usage. The PR body defers this to the same later PR.
    Remediation: Add the child-rollout read to the codex flowchart and runtime internals section.

Earlier findings

  • f_fdbf77f9d2ad17c2 — resolved_by_change: the fold in codex_run.go no longer depends on exitCode == 0. TestCodexRun_NonZeroExitStillReadsTheChildren covers exit 137 with a retry.
  • f_2f73f2d1178b9cca — resolved_by_change: codex_subagents.go now passes the child model through redactSummary before using it as a per_model_usage key. The Run warning is redacted as well.
Previous run (4)

<!-- fullsend:review-findings-v2:eyJ2ZXJzaW9uIjoyLCJhY3Rpb24iOiJyZXF1ZXN0LWNoYW5nZXMiLCJmaW5kaW5ncyI6W3sic2V2ZXJpdHkiOiJtZWRpdW0iLCJjYXRlZ29yeSI6ImxvZ2ljLWVycm9yIiwiZmlsZSI6ImludGVybmFsL3J1bnRpbWUvY29kZXhfcnVuLmdvIiwiaWQiOiJmX2ZkYmY3N2Y5ZDJhZDE3YzIiLCJsaW5lIjo2NjcsImFjdGlvbmFibGUiOnRydWV9LHsic2V2ZXJpdHkiOiJsb3ciLCJjYXRlZ29yeSI6InNlY3JldC1leHBvc3VyZSIsImZpbGUiOiJpbnRlcm5hbC9ydW50aW1lL2NvZGV4X3N1YmFnZW50cy5nbyIsImlkIjoiZl8yZjczZjJkMTE3OGI5Y2NhIiwibGluZSI6MzA0LCJhY3Rpb25hYmxlIjpmYWxzZX0seyJzZXZlcml0eSI6ImxvdyIsImNhdGVnb3J5Ijoic3RhbGUtZG9jIiwiZmlsZSI6ImRvY3MvcnVudGltZXMvY29kZXgubWQiLCJpZCI6ImZfNTEzOWVjNTllNjgxZDdkOSIsImxpbmUiOjI3MSwiYWN0aW9uYWJsZSI6ZmFsc2V9LHsic2V2ZXJpdHkiOiJsb3ciLCJjYXRlZ29yeSI6ImluY29tcGxldGUtZG9jIiwiZmlsZSI6ImRvY3MvY29udHJpYnV0aW5nL3J1bnRpbWUtaW1wbGVtZW50YXRpb24ubWQiLCJpZCI6ImZfMWY0YWQyMTgzMzMxZGYwZiIsImxpbmUiOjEwODMsImFjdGlvbmFibGUiOmZhbHNlfV19 -->

Review

Findings

Medium

  • [logic-error] internal/runtime/codex_run.go:667 — The exitCode == 0 guard skips foldCodexChildUsage, which is the only place the parent's per_model_usage entry is added, as well as the child rollout read. A delegating iteration that reports parent tokens and then exits non-zero still adds those tokens to the run totals in aggregateRunMetrics, but gets no matching per-model entry. If a retry iteration supplies a breakdown, metrics.json understates that model and breaks the breakdown-sums-to-totals invariant that foldCodexChildUsage documents. The two-iteration test only covers exit-zero folds.
    Remediation: Record the parent entry for every delegating iteration, including non-zero exits, and keep the exit-zero restriction only on the child rollout read. Add a cross-iteration test with one successful iteration and one non-zero iteration that reports parent usage.

Low

  • [secret-exposure] internal/runtime/codex_subagents.go:304 — The child model comes from an agent-writable rollout (turn_context payload.model, TrimSpace only) and becomes a per_model_usage map key in metrics.json with no redaction. A planted credential-shaped model string would reach that artifact. Transcripts get Codex redaction; this path does not. The pi fold does the same today, so this is hardening and not a new class of exposure.
    Remediation: Run the decoded child model through the shared redactor, or bucket values that do not look like a model id under unknown, and add a test.
  • [stale-doc] docs/runtimes/codex.md:271 — Says native delegation is off because Fullsend "does not yet support persona wiring or child token accounting". This PR adds Codex child token accounting. The advice to keep review and retro on Claude Code still holds. The PR body defers this doc to a later PR in the series.
    Remediation: In the follow-up, say child token accounting is implemented while persona wiring and enabling delegation are pending, and mention per_model_usage in the Artifacts row.
  • [incomplete-doc] docs/contributing/runtime-implementation.md:1083 — The Codex iteration flowchart and sub-agent internals do not show the post-exit child rollout read and per_model_usage fold. The Pi section covers its equivalent. The PR body defers this to the PR that makes delegation reachable.
    Remediation: In the follow-up, add the child read and fold to the Codex flowchart and document foldCodexChildUsage under the Codex sub-agents internals.

Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR
Previous run (5)

Review

Findings

Low

  • [error-handling] internal/runtime/codex_subagents.go:96 — The read command hides real rollout-read failures. In POSIX sh a pipeline returns the status of its last command, so a failing find or grep is masked by the while loop, head -n 1, tail -n 1 or the outer head -c, and their stderr goes to /dev/null. An unreadable sessions directory or rollout file gives exit 0 and no usage lines. foldCodexChildUsage treats that as a successful read and the child's tokens are dropped without the warning the PR description promises ("A failed read is a warning"). The failure tests only make the outer sandbox exec fail or exit non-zero; none causes a failure inside the pipeline.
    Remediation: Propagate find/grep read errors, or print a structured error marker that parseCodexChildUsage recognizes and returns as an error. Treat grep exit 1 (no match) differently from exit >= 2 (read error), keep the children that were read successfully, and add a test with a failure inside the pipeline, such as an unreadable rollout file.

Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR
Previous run (6)

Review

Findings

Low

  • [error-handling] internal/runtime/codex_subagents.go:86 — The read command hides failures. Every find/grep sends stderr to /dev/null, and the pipeline's exit status comes from the final head -c. A missing or unreadable sessions directory, or a missing child rollout, therefore returns exit 0 with empty stdout. foldCodexChildUsage returns success with nothing folded and prints no warning, although its comment says an error means "a read that did not happen or did not finish". The failure-path tests never run the generated command; they make the fake openshell exit 1 instead.
    Remediation: Warn when spawned IDs > 0 but no marker lines came back, or document that a missing rollout counts as no usage. Add a test that runs the generated command against a missing sessions directory.

  • [error-handling] internal/runtime/codex_subagents.go:121 — Hitting the 1 MiB read cap gives a successful but incomplete result. head -c can cut a JSONL line in half or drop later children. parseCodexChildUsage skips malformed lines without counting them and never checks scanner.Err(), so the fold reports success with no warning. The pi fold reports skipped lines (foldPiSubagentUsage returns skipped).
    Remediation: Count skipped or malformed lines and warn, as foldPiSubagentUsage does, or detect the cap by reading one extra byte.

  • [logic-error] internal/runtime/codex_run.go:667 — The fold runs whenever exitCode == 0. Codex also exits 0 on an interrupted turn, and the lastResult.IsError check (line 677) comes after the fold. An interrupted exit-0 iteration still folds child usage, which contradicts the comment at lines 662-666 saying only clean exits are read. The read also calls sandbox.Exec, which uses context.Background(), instead of ExecContext(ctx).
    Remediation: Gate the fold on the last result not being an error or incomplete result, or reword the comment to match the behaviour. Pass ctx through via sandbox.ExecContext.

  • [accounting-manipulation] internal/runtime/codex_subagents.go:278 — The non-negative clamps don't stop integer overflow. A rollout counter near MaxInt64 passes counters()/nonNegative unchanged, and adding it to the parent's m.InputTokens wraps the total negative. The other counters and the per-model entries have the same unchecked additions. Advisory: the rollouts are agent-writable and foldPiSubagentUsage uses the same unchecked addition; nothing gates on these totals.
    Remediation: Use saturating addition, or reject implausible counter values and keep the parent totals when a record fails that check.

  • [stale-doc] docs/runtimes/codex.md:271 — Lines 271-273 say fullsend turns off Codex native delegation "because it does not yet support persona wiring or child token accounting". This PR adds child token accounting and persona wiring exists from earlier PRs in the series. Delegation is still disabled in codex_config.go, now pending the multi-agent tools work (codex runtime: run the review/retro sub-agent rosters through codex's native spawn_agent roles #6970), so the stated reason is stale. The advice to keep review/retro on Claude is still right. The PR does not change this file.
    Remediation: Reword the rationale: child token accounting and persona wiring are in place, and native delegation stays disabled until the multi-agent tools are enabled (codex runtime: run the review/retro sub-agent rosters through codex's native spawn_agent roles #6970).

  • [missing-doc] docs/runtimes/codex.md:143 — The "At a glance" metrics row and the cost paragraph don't mention that metrics.json now includes per_model_usage (cost_usd 0) for an agent with registered sub-agent roles or a spawn in its stream. The PR documents this only in docs/cli/run.md.
    Remediation: Add a short note or a link to the per_model_usage section of docs/cli/run.md.

  • [stale-doc] docs/contributing/runtime-implementation.md:1083 — The Codex iteration flowchart node reads metrics.json (runtime: codex) without per_model_usage, unlike the pi node at line 656. The Codex internals section doesn't describe the post-run child rollout read and token fold.
    Remediation: Add per_model_usage to the flowchart node and briefly describe the child rollout fold in the Codex internals section.


Labels: PR changes the Codex agent runtime metrics code.


Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added the component/runner Agent runner behavior and lifecycle label Oct 19, 2026
Codex writes a token_count with its usage counters at zero when a
request overflows the context window, and writes a token_count only
after the response's tools finish, so a child's last token_count could
read zero or miss its last response. The read now takes the thread
total of the child's last token_usage_record, which codex writes as
each response completes and never resets. A read cut at its 1 MiB bound
is returned as an error, which Run prints as a warning, and a child
with a counter past 2^40 is skipped so planted values cannot wrap the
run's totals. The Run comment says the read follows any exit 0.

Signed-off-by: Dharit Shah <dhshah@redhat.com>
@dhshah13

Copy link
Copy Markdown
Contributor Author

Deferred: docs/runtimes/codex.md (the At a glance metrics row, the cost paragraph and the reason delegation is off) and, in docs/contributing/runtime-implementation.md, the codex flowchart node and a note on the child read change with the PR of the #6970 order that makes delegation reachable, which owns those docs; the body now says so.

@fullsend-ai-review

fullsend-ai-review Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 4:37 PM UTC · Completed 4:47 PM UTC

Commit: 73f0c68 · View workflow run →

Runtime: pi · Model: sonnet → claude-sonnet-5-5 · Effort: high · Cost: $2.70

@dhshah13 dhshah13 added the ok-to-test Allow e2e CI to run after maintainer review (must be re-applied after each push) label Oct 19, 2026
fullsend-ai-review[bot]

This comment was marked as outdated.

A rollout the read could not open, or one a failed search of the
sessions directory did not find, looked like a child with no usage: a
pipeline's status is its last command's, and find and grep send their
errors to /dev/null. The read now prints an unreadable marker for such
a child, and the fold returns it as an error, which Run prints as a
warning, keeping the children it did read. A missing sessions
directory warns the same way; a rollout missing from a directory
searched without error still adds nothing.

Signed-off-by: Dharit Shah <dhshah@redhat.com>
@dhshah13

Copy link
Copy Markdown
Contributor Author

Done in 9517fa6: description cut from about 770 words to 220, nothing asked of maintainers; the one place it differs from ADR 0126 (token_usage_record, not token_count) is a single Changes bullet with its reason. Code comments trimmed to what the code does not say.

@fullsend-ai-review

fullsend-ai-review Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 9:54 AM UTC · Completed 10:01 AM UTC

Commit: 9517fa6 · View workflow run →

Runtime: pi · Model: sonnet → claude-sonnet-5-5 · Effort: high · Cost: $1.74

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review
fullsend-ai-review Bot dismissed their stale review October 20, 2026 10:01

Superseded by updated review

…hild-usage

Signed-off-by: Dharit Shah <dhshah@redhat.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 2:22 PM UTC · Completed 2:31 PM UTC

Commit: bdcc01f · View workflow run →

Runtime: pi · Model: sonnet → claude-sonnet-5-5 · Effort: high · Cost: $1.96

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review
fullsend-ai-review Bot dismissed their stale review October 20, 2026 14:31

Superseded by updated review

@fullsend-ai-review fullsend-ai-review Bot removed the ready-for-merge All reviewers approved — ready to merge label Oct 20, 2026
A failed or timed-out read now folds the stdout that came back instead
of discarding it, and the read keeps the last two record and
turn_context lines so a torn last line falls back to the one before.
A line that does not decode is reported, the cut warning says the
child at the cut may be counted short, and a codex stopped at the
budget or cancelled warns that its children can record more after the
read.

Signed-off-by: Dharit Shah <dhshah@redhat.com>
Comment thread internal/runtime/codex_subagents.go Outdated
Codex writes one rollout per thread, so a second file named for the same
id is planted. Each copy was folded as its own child, multiplying the
child's tokens and requests; such an id now prints the unreadable marker
and none of its copies count.

Signed-off-by: Dharit Shah <dhshah@redhat.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 7:01 PM UTC · Completed 7:08 PM UTC

Commit: 949bd95 · View workflow run →

Runtime: pi · Model: sonnet → claude-sonnet-5-5 · Effort: high · Cost: $1.30

@fullsend-ai-review fullsend-ai-review Bot added the ready-for-merge All reviewers approved — ready to merge label Oct 20, 2026

@waynesun09 waynesun09 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM at 949bd95. Both earlier findings are fixed with tests (forked-child model from the last turn_context, duplicate rollouts count nothing). Live validation fits the #6970 PR that turns delegation on.

@waynesun09
waynesun09 added this pull request to the merge queue Oct 20, 2026
Merged via the queue into fullsend-ai:main with commit 2136b3c Oct 20, 2026
82 checks passed
@rh-hemartin

Copy link
Copy Markdown
Member

Hey! Didn't got the time to review after asking for simplifications, thanks for doing them, much cleaner now.

This branch was successfully deployed

2 active deployments
site-preview — 949bd95b Deployed Oct 20, 2026 by github-actions[bot]
dev — 949bd95b Deployed Oct 20, 2026 by dhshah13 via behaviour #17388
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/runner Agent runner behavior and lifecycle ok-to-test Allow e2e CI to run after maintainer review (must be re-applied after each push) ready-for-merge All reviewers approved — ready to merge risk/moderate PR risk: moderate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants