Skip to content

docs(concepts): memo groups, properties, requirements, per-stage interfaces and rules - #1224

Open
zzylol wants to merge 39 commits into
mainfrom
docs/memo-group-model
Open

zzylol wants to merge 39 commits into
mainfrom
docs/memo-group-model

Conversation

@zzylol

@zzylol zzylol commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Why

The formulation refactor (#1207) changes the memo's groups, candidates, properties and requirements across several PRs, but no single page defines them. This doc fixes the definitions before more code changes, so that the PRs and the paper use one model.

What

Adds docs/design_docs/concepts/memo-groups-properties-requirements.md, linked from the concepts index. It uses the optimization problem formulation's terms throughout (workload $(q, \mathcal T_q, A_q)$, memo group, candidate $v = (e_v, p_v)$, property requirement $r_{c,i}$, $\succeq$, $P_{c,i}$, $\mathcal E$, $\alpha$), and marks each #1207 extension.

  • Notation table and the KLL example in those terms.
  • 1. Properties and property requirements: each dimension of $p^{\log}$ and $p^{\mathrm{phys}}$ with its values and code; the invalid combinations; each requirement with who states it, what it constrains and which row checks it. Error propagation: each consumer's $g_c$, the propagation factors $\lambda_{q,c,i}$ row (K) uses, read from the query expression, and the per-input error cap = min(validity cap of a non-linear $g_c$, pruning cap $\max_q \varepsilon_q/\lambda_{q,c,i}$).
  • 2. Decision tree of properties: one level per decision ($e_v$, $\boldsymbol\theta$, $\omega$, $\tau$, $\ell$, $\sigma$) with its prune rule and code; why the order changes enumeration efficiency but not $\mathcal C$.
  • 3. Data structures and interfaces per stage (Tracking: implement the optimization formulation (memo candidates, properties, edges y_{u,c,i}, MILP) as named code per stage #1207 target): Stage 0, Pass 1, Pass 2, Stage 2, Stage 3, export, each with what it deletes.
  • 4. Rules per pass and stage: how each rule (Pass 1's ways to compute, Pass 2's ten rules, Stage 2's expansion and edges) adds groups, candidates and edges through the section 3 interfaces, and its status in the Tracking: implement the optimization formulation (memo candidates, properties, edges y_{u,c,i}, MILP) as named code per stage #1207 plan.
  • 5. Printing every logical DAG a memo group represents: what one logical DAG is (rows (A), (C)–(G) over logical candidates), pseudocode that lists each DAG exactly once by choosing one producer per consumer input with sharing and cycle checks, a printer that marks shared nodes, the A/B example (2 and 4 DAGs), an upper bound on the count, and the same procedure for physical DAGs.

New abstractions (approved by the user 2026-11-05)

  • ErrorPropagation { factor_per_input, validity_cap } and error_propagation(consumer) (section 3): each consumer's propagation factors and validity cap, the source of $\lambda$ and the validity cap.

How

The definitions follow the formulation in #1207, #1203 and #1200: properties are products of dimensions, ℓ ≠ None is "materialized", and accuracy is checked at the query root (row (K)), not per edge. Every struct is labeled as code today (with its path) or as the target of #1200 / #1203. The group's expression is the existing IR; no new identity type.

Before / After

Verification

Docs only. Mermaid syntax checked by eye; links checked.

🤖 Generated with Claude Code

https://claude.ai/code/session_01K1M6br9PL4SDeVS1XpezKJ

…y decision tree

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1M6br9PL4SDeVS1XpezKJ
@zzylol zzylol added documentation Improvements or additions to documentation optimizer Workload optimization and plan selection extensibility labels Nov 5, 2026
zzylol and others added 4 commits November 5, 2026 19:01
…idates over existing IR

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… definitions with the code and #1200

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
 formulation

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…earlier modeling section

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…les per pass and stage

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@zzylol zzylol changed the title docs(concepts): memo groups, properties, requirements and the property decision tree docs(concepts): memo groups, properties, requirements, per-stage interfaces and rules Nov 5, 2026
zzylol and others added 11 commits November 5, 2026 20:29
… pruning caps

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lRequirement.consumer_{timing,schedule}

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…presents

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…l interfaces; satisfies_logical

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…meters, window_layout}, LogicalRequirement {parameter_floor}, r^phys = f(p^phys_c); at-a-glance tables

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@milindsrivastava1997

milindsrivastava1997 commented Nov 6, 2026 •

Copy link
Copy Markdown
Collaborator

Comparing this doc with PR 1213 (memo representation proposal). Four places where the models differ.

1. Accuracy

  • PR 1213: each consumer carries its own ε. The budget is split up front; a shared producer is built for the min.
  • This PR: no ε on inputs. Row (K) checks the composed error at the query root; error_cap only drops producers that can never fit.
B = p99 / p50, target ε .01
PR 1213:  each operand gets .005
This PR:  any split with λ·ε_p99 + λ·ε_p50 ≤ .01, e.g. .002 + .008

2. Sketch family

  • PR 1213: one summary group; Kll vs. DD is a property of its candidate.
  • This PR: family is part of the expression, so one state group per family. A consumer picks a family by which group it reads.
PR 1213:  S  SummaryState(quantile, data, 300s)
               [SummaryAgg <-G1 | sketch ∈ {Kll, DD}]
          G2 [Est <-S]

This PR:  K  SummaryAgg[KLL](G1)
          D  SummaryAgg[DD](G1)
          G2 [Est <-K] [Est <-D]

Also: the §2 decision tree shows SummaryAgg[KLL] and SummaryAgg[DDSketch] as candidates of one group G, which contradicts the Example and the Pass 1 table.

3. One operator per candidate

  • PR 1213: S is a group, but multi-operator candidates remain (its open question 4).
  • This PR: every operator is its own group.
Today:    G2 [Est ← SummaryAgg Kll <-G1]
PR 1213:  S  [Merge ← TWChain <-G0]        still two operators
This PR:  G2 [Est <-K]    K [SummaryAgg θ <-G1]

4. Producer variants: stored vs. derived

  • PR 1213: no variants stored. A producer's θ is computed from the strictest requirement of the consumers that share it (built_for).
  • This PR: each θ is a stored candidate. Each consumer picks one that meets its requirement; sharing = two consumers pick the same one.
q50 ε .01, q99 ε .001 over data[5m]

This PR:  K candidates: k(.01), k(.001)
          q50 reads either; q99 reads only k(.001)
          shared plan: both read k(.001)

PR 1213:  S has one candidate
          enumeration decides q50, q99 share → built for ε .001 → k(.001)

@milindsrivastava1997

milindsrivastava1997 commented Nov 6, 2026 •

Copy link
Copy Markdown
Collaborator
  • Should candidates be a field on Memo or MemoGroup? Latter makes more sense imo
  • What is operator: Operator<MemoGroupId> and how is it different from OperatorNode? Instead of expression: CandidateExpression, in CandidateForMemoGroup, can't we just reuse logical_node: Rc<OperatorNode> from MemoGroup?
  • Should LogicalEdge.input be renamed to LogicalEdge.input_index_of_consumer?
  • What is PhysicalCandidateKey? Do you mean PhysicalCandidateId?
  • Didn't understand the MILP data structs (e.g. Context) but can come back to this later.
  • Didn't understand Periodic vs TumblingWindowGrid for the schedule property

@zzylol

zzylol commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor Author
  • Should candidates be a field on Memo or MemoGroup? Latter makes more sense imo

Yeah it should be under MemoGroup.
candidates field is a vector of vector of Candidate data structure, in Memo, so conceptually, it is under a group.

@zzylol

zzylol commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor Author

Comparing this doc with PR 1213 (memo representation proposal). Four places where the models differ.

1. Accuracy

  • PR 1213: each consumer carries its own ε. The budget is split up front; a shared producer is built for the min.
  • This PR: no ε on inputs. Row (K) checks the composed error at the query root; error_cap only drops producers that can never fit.
B = p99 / p50, target ε .01
PR 1213:  each operand gets .005
This PR:  any split with λ·ε_p99 + λ·ε_p50 ≤ .01, e.g. .002 + .008

For this, it has the possibility to not be each operand gets .005.

2. Sketch family

  • PR 1213: one summary group; Kll vs. DD is a property of its candidate.
  • This PR: family is part of the expression, so one state group per family. A consumer picks a family by which group it reads.
PR 1213:  S  SummaryState(quantile, data, 300s)
               [SummaryAgg <-G1 | sketch ∈ {Kll, DD}]
          G2 [Est <-S]

This PR:  K  SummaryAgg[KLL](G1)
          D  SummaryAgg[DD](G1)
          G2 [Est <-K] [Est <-D]

Also: the §2 decision tree shows SummaryAgg[KLL] and SummaryAgg[DDSketch] as candidates of one group G, which contradicts the Example and the Pass 1 table.

Yeah, agree, the sketch algorithm should be the candidate dimension. But it is like this PR's way because later if we want to model each operator as one group to avoid duplicated nodes in the plans, and being more flexible about choices, it may be easier to build one group for a sketch algorithm.

3. One operator per candidate

  • PR 1213: S is a group, but multi-operator candidates remain (its open question 4).
  • This PR: every operator is its own group.
Today:    G2 [Est ← SummaryAgg Kll <-G1]
PR 1213:  S  [Merge ← TWChain <-G0]        still two operators
This PR:  G2 [Est <-K]    K [SummaryAgg θ <-G1]

I thought per operator is its own group will give us more flexibility. Didn't quite get the example; it seems not to be comparing the same aggregation?

4. Producer variants: stored vs. derived

  • PR 1213: no variants stored. A producer's θ is computed from the strictest requirement of the consumers that share it (built_for).
  • This PR: each θ is a stored candidate. Each consumer picks one that meets its requirement; sharing = two consumers pick the same one.
q50 ε .01, q99 ε .001 over data[5m]

This PR:  K candidates: k(.01), k(.001)
          q50 reads either; q99 reads only k(.001)
          shared plan: both read k(.001)

PR 1213:  S has one candidate
          enumeration decides q50, q99 share → built for ε .001 → k(.001)

I don't see there is a difference. The difference in representation only comes from storing the producer vs storing the consumer in MemoGroup.

…functions)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@zzylol

zzylol commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author
  • Should LogicalEdge.input be renamed to LogicalEdge.input_index_of_consumer?

Sure.

  • What is PhysicalCandidateKey? Do you mean PhysicalCandidateId?

It's not 'PhysicalCandidateId', it's The name of a physical candidate that Stage 2 pruned. It names the pruned candidate by its content instead:

/// A pruned physical candidate, named by what it would have been.
pub struct PhysicalCandidateKey { pub logical: CandidateForMemoGroupId, pub properties: PhysicalProperties }

They exist for DAG viewer tool to display.

  • Didn't understand the MILP data structs (e.g. Context) but can come back to this later.

Context comes from these:

How often a candidate runs, and so what it costs, depends on its lifetime ℓ:

  • Materialized candidate (ℓ ≠ None). Its result is kept, so it runs once per its own schedule σ and every consumer reads that one result. One variable is enough: did we pick it or not (x_v).
  • Unmaterialized candidate (ℓ = None). Nothing is kept, so it runs inside whatever execution needs it. Each query evaluation that reads it runs it again. Its cost depends on how many places run it, so the MILP needs one variable per (place, candidate). That place is a context κ.

Row functions: one per constraint family, as see in the overleaf table. We should just call them constraints.

@zzylol

zzylol commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author

What is operator: Operator<MemoGroupId> and how is it different from OperatorNode? Instead of expression: CandidateExpression, in CandidateForMemoGroup, can't we just reuse logical_node: Rc<OperatorNode> from MemoGroup?

Both use the same operator enum Operator<C>, with the same variants and arguments (Scan, Filter, SummaryAgg { family, … }, …). They differ in C, the type of the children:

OperatorNode (operator: Operator<Rc<OperatorNode>>) Operator<MemoGroupId>
Children other OperatorNodes: the root of a whole sub-DAG down to the scans memo group ids: one operator over its input groups
Other fields result_kind, schema, guarantee (from θ), and on main timing, materialization none
Meaning a fixed plan fragment: every input's producer is already chosen, all the way down $e_v = \operatorname{op}v(G{v,1}, \dots, G_{v,n})$: which candidate of $G_{v,i}$ feeds input $i$ is left to the edges ($y$)
Conversion node.operator.map_children(|child| group_of(child)) (exists today)

Example: G3 = p95 of the KLL state. As an OperatorNode it is SummaryEstimate(q=0.95) → SummaryAgg[KLL](k=345) → Scan, so k = 345 is baked in. As Operator<MemoGroupId> it is SummaryEstimate(q=0.95)(G2), and each consumer's edge picks k = 200 or k = 345 from G2.

Why a candidate cannot reuse the group's logical_node:

  1. One group has several candidates with different operators. G3 can be SummaryEstimate(G2), an exact quantile over G1, or a rollup reading a finer group. The group has one logical_node (the frontend's form), so each candidate needs its own operator.
  2. An Rc<OperatorNode> pins every input's producer. That is today's root_node / private-node problem: two consumers cannot pick different sizes of one state, and rules have to copy consumers. Children that are group ids leave the choice to the edges.
  3. An OperatorNode carries properties (guarantee from θ; on main also the physical fields). A candidate keeps those in logical_properties (θ, ω), and Stage 2 adds (τ, ℓ, σ).

Two simplifications this question points to, proposed (not yet decided):

  • Drop the one-field CandidateExpression wrapper and write expression: Operator<MemoGroupId> directly.
  • Store the group the same way: MemoGroup { expression: Operator<MemoGroupId>, schema, parents, queries } instead of logical_node: Rc<OperatorNode> + child_groups, which hold the same input information twice. Hash-consing already keys on Operator<MemoGroupId> (find_or_add_group).

zzylol and others added 6 commits November 5, 2026 22:04
…red, grid width from the window layout, per-input validity caps, metric rule, (K) encoding, (J) definitions, (L)/budgets out of scope

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…unds, not cost

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Sketch state)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1M6bq8xVaGKyinf4ohK6q
…latency ignored for now

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1M6bq8xVaGKyinf4ohK6q
zzylol and others added 2 commits November 6, 2026 14:33
…ends (no refresh interval)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1M6bq8xVaGKyinf4ohK6q
@milindsrivastava1997

milindsrivastava1997 commented Nov 6, 2026 •

Copy link
Copy Markdown
Collaborator
  • Rename CandidateForMemoGroupId.index to be more descriptive
  • Rename Memo.candidate() to be Memo.get_candidate()
  • Is InvalidLogicalProperties an error type? If yes, pls add the Error suffix
  • Rename LogicalRequirement to LogicalRequirements
  • Rename LogicalRequirement.parameter_floor to parameter_floor_for_required_accuracy
  • Rename satisfies_logical to does_producer_satisfy_logical_requirements. Similar for does_producer_satisfy_physical_requirements
  • Rename Medium to StorageMedium
  • What does Schedule mean? How does it relate to the window_layout logical property?
  • Rename PhysicalCandidate.logical to logical_candidate_id
  • Rename PhysicalASAPMemoCandidates.logical to logical_candidates. Similarly many names in PhysicalCandidate, PhysicalEdge, and PhysicalASAPMemoCandidates. PhysicalCandidateKey.
  • Do we need some function like combine_requirements_into_stricter_requirement? This is used in docs(proposals): memo representation — compressing the space of logical DAGs #1213 with Requirement and RequirementField framing, and seems helpful. I imagine that in this design, this logical is implicitly embedded in different places. Is it helpful (and easy) to make it explicit?
  • Need to rename Context to be more descriptive.

zzylol and others added 2 commits November 6, 2026 15:11
…anchored at phase 0

A OneEvaluation result belongs to one evaluation context and runs on that
context's schedule, chosen by Stage 3 through x_{κ,v}. Every tumbling grid
is anchored at the epoch; a phase is absorbed by the width, whose candidates
come from the gcd closure of ranges, steps and phases. A consumer in κ reads
a windowed chain iff w | I_κ and w | φ_κ (delivers_on). The only invalid
combination left is (IngestionTime, OneEvaluation).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1M6bq8xVaGKyinf4ohK6q
…uation context per schedule

A sketch build's θ must be in its family's list; a requirement's floor is
any value of the parameter type (the weakest θ with ε ≤ cap, or a direct
need such as heap_size ≥ k). Heap variants take heap sizes from the 1-2-5
series 10 … 10 000; KMV and UnivMon distinct-count lists stop at ε = 0.01.
satisfies_physical takes producer and consumer only. Context::Evaluation
is keyed by the evaluation schedule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1M6bq8xVaGKyinf4ohK6q
@zzylol

zzylol commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author
  • Rename CandidateForMemoGroupId.index to be more descriptive

Done: index_in_group (its position in the group's candidates list).

  • Rename Memo.candidate() to be Memo.get_candidate()

Kept as candidate(). Rust accessors don't take a get_ prefix (API guidelines, C-GETTER), and the codebase follows that (groups(), timing(), lifetime()).

  • Is InvalidLogicalProperties an error type? If yes, pls add the Error suffix

Yes. Renamed to LogicalPropertiesError, and likewise PhysicalPropertiesError.

  • Rename LogicalRequirement to LogicalRequirements

Agreed. It matches LogicalProperties.

  • Rename LogicalRequirement.parameter_floor to parameter_floor_for_required_accuracy

Agreed. The floor comes from the accuracy needed at that input; for a top-k reader, heap_size ≥ k is part of the same requirement.

  • Rename satisfies_logical to does_producer_satisfy_logical_requirements. Similar for does_producer_satisfy_physical_requirements

Agreed on the meaning, without does_ (Rust predicates don't use it): producer_satisfies_logical_requirements and producer_satisfies_physical_requirements.

  • Rename Medium to StorageMedium

Agreed.

  • What does Schedule mean? How does it relate to the window_layout logical property?

Schedule (σ) has been removed; physical properties are now just (timing, lifetime).

  • A OneEvaluation result belongs to one execution context: the queries with the same evaluation schedule share it.
  • Window grids are anchored at phase 0. Phase differences between queries are absorbed by the window width (the logical window_layout), whose candidates come from the gcd of the queries' ranges, steps and phases.
  • A consumer in context κ can read a materialized window chain iff the width w divides κ's interval and phase.
  • Rename PhysicalCandidate.logical to logical_candidate_id
  • Rename PhysicalASAPMemoCandidates.logical to logical_candidates. Similarly many names in PhysicalCandidate, PhysicalEdge, and PhysicalASAPMemoCandidates. PhysicalCandidateKey.

Agreed:

Struct Now New
PhysicalCandidate logical, properties logical_candidate_id, physical_properties
PhysicalCandidateKey logical, properties logical_candidate_id, physical_properties
PhysicalEdge, LogicalEdge producer, consumer producer_candidate_id, consumer_candidate_id
PhysicalASAPMemoCandidates logical, candidates logical_candidates, physical_candidates

Easy (the strictest of several floors of one family is their componentwise maximum), but not added now, because nothing would call it:

  • correctness is checked per edge: a producer shared by several consumers satisfies each consumer's requirements separately;
  • candidates come from the predefined θ list, not from "the weakest producer covering this set of consumers";
  • the two implicit combines are the gcd closure of window widths and max(k) for heap sizes, and the lists already contain those values.

It becomes useful with requirement-driven (top-down) enumeration as in #1213; we add LogicalRequirements::strictest(a, b) -> Option<Self> then.

  • Need to rename Context to be more descriptive.

Agreed: ExecutionContext and ExecutionContextId, the formulation's term.

zzylol and others added 11 commits November 6, 2026 15:37
LogicalPropertiesError, PhysicalPropertiesError, LogicalRequirements
(parameter_floor_for_required_accuracy), producer_satisfies_logical_requirements,
producer_satisfies_physical_requirements, StorageMedium, ExecutionContext
and ExecutionContextId; PhysicalCandidate / PhysicalCandidateKey fields
logical_candidate_id and physical_properties; edge fields
producer_candidate_id and consumer_candidate_id; PhysicalASAPMemoCandidates
fields logical_candidates and physical_candidates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1M6bq8xVaGKyinf4ohK6q
…ne-off queries supported

An evaluation context is Evaluation { recurrence, range_evaluation },
deduplicated by equality. delivers_on takes the context: w divides the
evaluation grid of FixedIntervalAt (interval, step, phase), every
Scheduled time, or a OneTime query's time; never when the times are not
known. ρ_κ reuses execution_demand's evaluation counting. EvaluationSchedule
is deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1M6bq8xVaGKyinf4ohK6q
find_or_add_group returns the node rules' SchemaDerivationError;
add_candidate checks the candidate's expression by the same rules and
requires the group's output schema and kind (CandidateError).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1M6bq8xVaGKyinf4ohK6q
MemoGroup holds expression, schema and result kind (no logical node or
child list); Memo's groups are private behind groups(), added only through
find_or_add_group (hash-consing on the expression), and Stage 0 adds each
query with add_query. Appendix A reads memo.groups().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1M6bq8xVaGKyinf4ohK6q
…inition over group ids

A memo group is its expression and its GroupProperties (schema, result kind,
summary coverage, shareable_when_equal), derived once from its input groups'
expressions and properties by the node rules, never from node trees. A
group's summary coverage has a SummaryDefinition: the residual links over
group ids.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1M6bq8xVaGKyinf4ohK6q
…Input; coverage only in the memo

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1M6bq8xVaGKyinf4ohK6q
…roup examples

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1M6bq8xVaGKyinf4ohK6q
…fine fused groups

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1M6bq8xVaGKyinf4ohK6q
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation extensibility optimizer Workload optimization and plan selection

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants