Skip to content

feat(bench): per-service C2 decomposition + v8 B2 pricing (#444) - #445

Merged
jensholdgaard merged 4 commits into
mainfrom
bench-c2-per-service
Jul 9, 2026
Merged

feat(bench): per-service C2 decomposition + v8 B2 pricing (#444)#445
jensholdgaard merged 4 commits into
mainfrom
bench-c2-per-service

Conversation

@jensholdgaard

@jensholdgaard jensholdgaard commented Jul 9, 2026

Copy link
Copy Markdown
Owner

Turns the v8 C2 finding (§9.12) into standing measurement infrastructure, and records the B2 pricing that reframes #444.

Per-service C2 diagnostic

The v8 capture failed whole-corpus C2 (ratio 0.199) entirely because of the kafka broker (14,608 templates on 2.8% of lines); every application service converges cleanly (cart PASSes at 2.76M lines with 2 templates). I found that by splitting the corpus and re-running the gate five times — this makes it automatic.

  • C2Accumulator attributes each template creation to the minting line's service.name. Creation is a globally-monotonic event (RFC 0001 §6.1 id allocation), so this is O(services) memory — no per-service id set, which preserves the module's whole memory-safety argument (a non-converging corpus is exactly where a HashSet would balloon).
  • Per-service creations partition the whole-corpus end count exactly (verified end-to-end on v8: 2 + 17 + 1 + 3 + 14,608 = 14,631).
  • ourios-bench --gates c2 prints the breakdown when a corpus carries >1 service.name.
  • The gate is unchanged (whole-corpus). The breakdown is an additive diagnostic — so miner: template fragmentation on short high-cardinality-token lines (kafka, v8 C2 finding) #444's "scope C2 per service" option can be evaluated on real numbers without a code change, and I am not preempting that pillar-docs: apply RFC maturity-model amendments #2 decision.
  • Cardinality guard (MAX_SERVICES = 1024 → <other> bucket) mirrors §3.2's ethos; <unknown> bucket for the plain-text corpus form.

B2 pricing (the reframing)

service templates 1h-window query row groups pruned
cart 2 3.66 ms 48/49
kafka 14,608 3.40 ms 48/49

The deployed time/column pruning floor is identical regardless of fragmentation. So fragmentation costs template-exact query precision (kafka's dominant event is scattered across ~11,651 ids), not query latency#444 is a query-capability decision, not a performance one. Recorded in §9.12.

Tests

6 c2 unit tests (5 pre-existing + the new partition-exactness and unknown-service arms); the partition test encodes the monotonic-id invariant the attribution relies on. cargo clippy --all-targets --all-features -- -D warnings exit 0, mdbook build ✓, and confirmed end-to-end on the real v8 corpus (breakdown reproduces the by-hand table in one pass).

The miner-side de-fragmentation (the actual thesis-value fix) stays gated on the #444 direction call.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added per-service C2 breakdowns in benchmark results, showing convergence and pass/fail status for each service when multiple services are present.
    • Results now indicate when the per-service list is truncated.
  • Bug Fixes

    • Records without a service name are now included under a default “unknown” bucket instead of being dropped.
  • Documentation

    • Expanded benchmark docs with guidance on interpreting the new per-service C2 output and fragmentation-related findings.

The v8 capture (§9.12) failed whole-corpus C2 (0.199) entirely because
of one service — kafka's broker logs fragment on short offset-bearing
lines while every application service converges cleanly. Reconstructing
that by hand (split the corpus, re-run the gate 5×) is toil; make it a
first-class bench diagnostic instead.

C2Accumulator now attributes each template creation to the minting
line's service.name. Creation is a globally-monotonic event, so this
is O(services) memory — no per-service id set, preserving the module's
whole memory-safety argument (a non-converging corpus is exactly where
a HashSet would balloon). Per-service creations partition the
whole-corpus end count exactly;  prints the breakdown
whenever a corpus carries >1 service. The gate itself is unchanged
(whole-corpus) — the breakdown is additive, so #444's scope-C2-
per-service option can be judged on real numbers without a code change.

§9.12 also records the B2 pricing: the deployed time/column pruning
floor is identical on the fragmented (kafka) and converged (cart)
services — both prune 48/49 row groups at ~3.5 ms — so fragmentation
costs template-exact query *precision*, not query *latency*. That
reframes #444 as a query-capability decision, not a performance one.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jensholdgaard, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 21 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6cc47af2-80f0-4bbb-a9c6-dfbd09450e3d

📥 Commits

Reviewing files that changed from the base of the PR and between 1fecd82 and a0d02a5.

📒 Files selected for processing (4)
  • crates/ourios-bench/src/c2.rs
  • crates/ourios-bench/src/lib.rs
  • crates/ourios-bench/src/main.rs
  • docs/benchmarks.md
📝 Walkthrough

Walkthrough

Adds a per-service.name decomposition to the C2 template-count convergence gate: C2Accumulator now attributes template creations and line counts per service with a cardinality guard, finalize() computes per-service convergence/pass results, C2Result gains new fields, CLI summary output and docs are updated accordingly.

Changes

C2 per-service decomposition

Layer / File(s) Summary
PerServiceC2 schema and C2Result fields
crates/ourios-bench/src/lib.rs
Adds serde-defaulted by_service and services_truncated fields to C2Result, and defines the new public PerServiceC2 struct with service identity, line/template counts, convergence ratio, and pass outcome.
Accumulator per-service tracking
crates/ourios-bench/src/c2.rs
Introduces PerService struct, MAX_SERVICES/UNKNOWN_SERVICE constants, and updates C2Accumulator state and record()/observe() to attribute each line and template creation to a service with an <other> overflow bucket.
Finalize computation and tests
crates/ourios-bench/src/c2.rs
finalize() computes per-service convergence ratios and pass gates, sorts services, adds service_name() helper, and populates C2Result; new tests verify partitioning of the whole-corpus count and fallback for missing service.name.
CLI summary and report fixture
crates/ourios-bench/src/main.rs, crates/ourios-bench/src/report.rs
print_summary prints a per-service breakdown and truncation notice; the report.rs inconsistency test fixture is updated with the new fields.
Benchmark documentation update
docs/benchmarks.md
Documents the per-service C2 decomposition as an additive diagnostic with a fragmentation comparison table.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • jensholdgaard/ourios#54: Modifies the same C2 accumulator record()/finalize() logic and C2Result fields that this PR extends with per-service attribution.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the summary well, but it omits the required Related section and the checklist format from the template. Add the template sections Summary, Related, and Checklist, and explicitly list status for fmt, clippy, tests, docs, and RFC linkage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly reflects the main change: per-service C2 decomposition, with the B2 pricing note as a secondary detail.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bench-c2-per-service

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR extends the ourios-bench C2 convergence gate with an additive, per-service.name diagnostic breakdown to localize non-convergence in multi-service corpora (notably otel-demo v8 / #444), and records benchmark findings about fragmentation’s impact (precision vs latency) in docs/benchmarks.md.

Changes:

  • Add per-service C2 decomposition to the streaming accumulator and serialize it on C2Result (by_service, services_truncated).
  • Print the per-service C2 diagnostic in the ourios-bench CLI summary when multiple services are present.
  • Document v8 per-service C2 attribution and “B2 pricing” findings in docs/benchmarks.md.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
docs/benchmarks.md Adds narrative + table capturing v8 per-service C2 attribution and B2 query behavior under fragmentation.
crates/ourios-bench/src/report.rs Updates a unit test to construct C2Result with the new fields.
crates/ourios-bench/src/main.rs Prints per-service C2 diagnostic breakdown in CLI summary output.
crates/ourios-bench/src/lib.rs Extends C2Result JSON/schema with per-service decomposition structs/fields.
crates/ourios-bench/src/c2.rs Implements per-service attribution and computes per-service convergence results in C2Accumulator.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/ourios-bench/src/c2.rs
Comment thread crates/ourios-bench/src/lib.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/ourios-bench/src/lib.rs`:
- Around line 604-606: The `by_service` field documentation is inconsistent with
the actual `C2Accumulator::record()` path: plain-text input still gets bucketed
into `UNKNOWN_SERVICE`, so `by_service` is not empty. Update the doc comment on
`by_service` in `lib.rs` to reflect that missing `service.name` values are
accumulated under an `<unknown>`/`UNKNOWN_SERVICE` entry, and keep the wording
aligned with how the benchmark harness calls `record()` for each emitted line.

In `@docs/benchmarks.md`:
- Line 1141: The sentence in docs/benchmarks.md starts with the issue reference
"`#444`", which can be parsed ambiguously and trigger markdownlint heading-style
handling. Rephrase that line so it does not begin with "`#444`" while still
explicitly referencing the issue, and keep the wording readable in prose; update
the surrounding benchmark text in the same section if needed to preserve
meaning.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2db5006b-86dd-4aa2-9edb-84f7885cd306

📥 Commits

Reviewing files that changed from the base of the PR and between a99a496 and 1fecd82.

📒 Files selected for processing (5)
  • crates/ourios-bench/src/c2.rs
  • crates/ourios-bench/src/lib.rs
  • crates/ourios-bench/src/main.rs
  • crates/ourios-bench/src/report.rs
  • docs/benchmarks.md

Comment thread crates/ourios-bench/src/lib.rs Outdated
Comment thread docs/benchmarks.md Outdated
…ose fixes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment thread crates/ourios-bench/src/c2.rs Outdated
Comment thread crates/ourios-bench/src/main.rs
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment thread docs/benchmarks.md Outdated
Comment thread crates/ourios-bench/src/main.rs Outdated
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

@jensholdgaard
jensholdgaard merged commit abd9108 into main Jul 9, 2026
24 checks passed
@jensholdgaard
jensholdgaard deleted the bench-c2-per-service branch July 9, 2026 16:41
jensholdgaard added a commit that referenced this pull request Jul 10, 2026
* feat(bench): redefine C2 gate as per-service (#444)

C2 is specified over "a corpus from a single stable service", so
grading a multi-service OTLP capture with one whole-corpus ratio is a
category error: it conflates a noisy infra broker (high-cardinality
offset/path tokens) with clean application services, failing the gate
even when every application service converges perfectly (v8 §9.12).

Redefine the gate to fold over the per-service decomposition (#445):
a corpus passes iff every service with >= 1M lines has ratio >= 0.5,
fails if any such service is below 0.5, abstains when none reach 1M.
A single-service corpus — including the plain-text <unknown> bucket —
collapses to the whole-corpus verdict, so historical text-corpus rows
are unchanged; only multi-service OTLP corpora differ. The whole-corpus
ratio is retained as a diagnostic.

Under this gate the v8 capture flips FAIL -> PASS: cart is the sole
service clearing the 1M-line floor and it converges at ratio 1.000;
kafka's fragmentation (14,608 templates on 137k lines) is a bounded
diagnostic, not a gate failure. Token-level polishing of hostile infra
logs is an OTel Collector concern (transform/redaction processor
upstream), not the miner's — consistent with "format parsing is the
Collector's job".

RFC 0006 §3.4.3 pass condition amended (maintainer-approved 2026-07-10);
docs/benchmarks.md C2 grain + §9.12 v8 record updated. Cargo.lock synced
(main's lock still listed async-stream for ourios-ingester after the TLS
work dropped it).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X467Druw4cQeEPVp52DTG3

* docs(bench): sharpen C2 single-service collapse claim; abstain wording (#444)

Review follow-ups on #451:

- Copilot: the single-service gate is measured at the *exact* millionth
  service line (created_at_1m), not the sampled whole-corpus point, so
  the collapse is verdict-equivalence for historical converged corpora
  (ratio far from the 0.5 boundary), not bit-identity with the sampled
  whole-corpus diagnostic. Corrected the over-claim in gate_pass's doc,
  RFC 0006 §3.4.3, and benchmarks.md §C2 — no behaviour change; the
  exact-1M measurement is strictly more precise than the diagnostic, so
  special-casing len==1 to the diagnostic would regress it.
- CodeRabbit: §9.12 no longer says "every application service converges
  essentially perfectly" — cart (the sole gated service) passes; the
  smaller services abstain below the 1M-line floor and are not graded,
  though their observed counts sit at the same near-flat convergence.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X467Druw4cQeEPVp52DTG3

* fix(bench): gate every >=1M C2 service; zero-template service passes (#444)

Copilot review on #451:

- Correctness: gate_pass inferred the gated set via filter_map(|s| s.pass),
  assuming pass=Some iff a service reached 1M lines — but the per-service
  builder left pass=None when a >=1M service minted zero templates (every
  line NO_TEMPLATE), so gate_pass silently dropped it and `None` meant both
  "below 1M" and "degenerate >=1M". Fix: the builder now gates on
  lines>=1M unconditionally; a zero-template >=1M service passes trivially
  (flat count is the strongest convergence — C2's falsifier is *linear*
  growth) with an undefined ratio. `None` from gate_pass now unambiguously
  means "no service reached 1M lines". main.rs prints the new
  (ratio=None, pass=Some(true)) case. Regression test added.

- Docs: the module-level "Pass" / ratio definitions and the attribute()
  comment still described the pre-#444 whole-corpus gate; updated to the
  per-service gate (whole-corpus ratio is diagnostic-only).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X467Druw4cQeEPVp52DTG3

* docs(bench): convergence ratio range is [0, 1], not (0, 1] (#444)

Copilot review on #451: count_at_1m can be 0 (with SS > 0) when the
first template is minted only after the 1M-line mark, so the ratio's
defined range includes 0. Corrected the module-level c2.rs doc and
RFC 0006 §3.4.3 (a >=1M service that mints *zero* templates overall
stays undefined/None, distinct from ratio 0.0). Doc-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X467Druw4cQeEPVp52DTG3

* fix(bench): keep C2 whole-corpus diagnostic pair consistent; lean gate_pass (#444)

Copilot review on #451 (round 4):

- Correctness (report.rs contract): an all-NO_TEMPLATE >=1M corpus (SS=0)
  produced the mixed diagnostic pair (template_count_at_1m_lines=Some(0),
  convergence_ratio=None), which report.rs rejects as an inconsistent
  C2 result — report generation would error. This was latent pre-#444;
  the new zero-template test made the state reachable. Fix: finalize now
  gates the whole-corpus count on template_count_at_end > 0 too, so the
  pair is always both-Some or both-None. report.rs renders the SS=0 >=1M
  case as "n/a (SS 0 — no templates mined)", distinct from the sub-1M
  "corpus < 1 M lines" abstention (uses the existing corpus_at_least_1m
  flag). Two regression tests: the accumulator asserts the consistent
  (None, None) pair; report.rs asserts the render doesn't error.

- Style: gate_pass no longer allocates a temporary Vec<bool> — a single
  pass that short-circuits on the first failing gated service.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X467Druw4cQeEPVp52DTG3

* fix(bench): reject absent-measurement corruption; precise ratio-0 wording (#444)

Copilot review on #451 (round 5):

- report.rs: the (None,None) && corpus_at_least_1m arm rendered
  "no templates mined" without checking SS==0, so a corrupt ResultsFile
  with corpus_at_least_1m=true and SS>0 but no measurement would render a
  self-contradictory row instead of erroring (the surrounding contract's
  intent). Tightened: the arm now requires template_count_at_end==0; any
  >=1M/SS>0 (None,None) falls to the inconsistency error (message
  broadened to state the pair is set iff >=1M with SS>0). Regression test
  added.

- Docs: reworded the ratio-0 condition from the causal "first template
  minted after 1M" to the observable "no template minted as of the
  sample nearest the 1M mark" — count_1m is the nearest sample, not the
  exact millionth line, so a sample landing after 1M can already include
  post-1M templates. c2.rs module doc + RFC 0006 §3.4.3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X467Druw4cQeEPVp52DTG3

* docs(rfc): document C2 SS==0 semantics in RFC 0006 §3.4.3 (#444)

Copilot review on #451 (round 6) — propagate the SS==0 (zero-template)
semantics through the RFC spec text so it matches the implementation:

- Convergence ratio is defined only when SS > 0; undefined (null, paired
  with a null count_at_1m) for a >=1M corpus that mints no templates.
- Per-service pass rule now states the zero-template trivial-PASS
  exception, and that each service's count_at_1m is its *exact* millionth
  line (not the whole-corpus nearest-sample diagnostic).
- "Reported as" paragraph: the two whole-corpus fields are null for
  corpora <1M *or* SS==0, and form a matched pair (both null or both set)
  that report.rs enforces.

Doc-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X467Druw4cQeEPVp52DTG3

* fix(bench): label C2 diagnostic ratio in report; stale doc + MAX_SERVICES note (#444)

Copilot review on #451 (round 7):

- report.rs: the C2 status-table Measurement column rendered an unlabeled
  "ratio …" that reads like the gate metric, but it's the whole-corpus
  diagnostic now — on a multi-service corpus it can be sub-0.5 with a PASS
  Verdict (per-service). Labeled "whole-corpus ratio … — diagnostic;
  verdict is per-service", matching the CLI summary's phrasing.

- c2.rs: gate_pass doc still referenced "the filter_map below" after the
  round-4 rewrite to a for-loop; updated to describe the fold.

- RFC 0006 §3.4.3: documented the MAX_SERVICES=1024 cardinality cap and
  the <other> fold (c2.services_truncated) — beyond the cap the gate is no
  longer strictly per-service; the truncation is surfaced, never silent.

Doc/label-only; no behaviour change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X467Druw4cQeEPVp52DTG3

* docs(bench): note zero-template trivial-PASS in C2Result doc (#444)

Copilot review on #451 (round 8): the C2Result doc said every >=1M
service must pass "its own ratio >= 0.5" without the zero-template
exception the code and RFC 0006 §3.4.3 now carry. Added it — a >=1M
service that mints zero templates (SS=0, undefined 0/0 ratio) passes
trivially. Doc-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X467Druw4cQeEPVp52DTG3

* fix(bench): print C2 per-service breakdown for single-service corpora too (#444)

Copilot review on #451 (round 9): the CLI printed the per-service
breakdown only when by_service.len() > 1, so a single-service (or
plain-text <unknown>) corpus showed only the whole-corpus *diagnostic*
ratio, hiding the per-service exact-1M measurement that the verdict is
actually based on. Now printed whenever any service bucket exists.
Extracted the per-service status formatting into a testable
per_service_status() helper with a unit test covering the ratio
pass/fail, SS=0 trivial-pass, and abstain states.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X467Druw4cQeEPVp52DTG3

* docs(bench): sync CLI-breakdown descriptions with round-9 behaviour (#444)

Copilot review on #451 (round 10) — two stale descriptions after the
round-9 change (breakdown now prints for single-service corpora too):

- c2.rs: stable_curve_ratio_is_one's header comment said "ratio 1.0 →
  pass", but the test drives observe (no service.name) and asserts the
  per-service gate abstains (pass=None). Reworded to "whole-corpus
  diagnostic ratio 1.0", matching the body comment.
- benchmarks.md §9.12: said the CLI prints the breakdown only for
  corpora with "more than one bucket"; it now prints whenever any
  service bucket exists. Updated (and relabeled the decomposition the
  gate, not just a diagnostic).

Doc-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X467Druw4cQeEPVp52DTG3

---------

Co-authored-by: Claude Opus 4.8 (1M context) <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.

2 participants