Repository navigation
Resolve Hack 1: typed matchers + cardinality-driven CLI generation - #30
Conversation
…ort From impls, error context - Add `cardinality: Cardinality` field to `CliEntrypoint`, replacing `type_id == "List"` string matching with `cardinality.allows_many()` queries throughout CLI generation and makegen registry - Add typed `OutputMatcher` variants: `IsBool`, `IsInt`, `IsString`, `IsRequest`, `IsResponse`, `IntGe(i64)`, `IntLe(i64)` — all generate real codegen assertions instead of the comment-only `Satisfies` hack - Migrate existing `Satisfies` usages in CI/makegen graph mocks to typed variants - Add `ShellResponse::ok()` and `ShellResponse::failed()` constructors - Add `From<T> for TransportRequest/TransportResponse` for all 5 transport types - Add `ExecError::context()` method and `ResultExt` trait for structured error context - Add `propagate_skipped()` helper for skip propagation pattern (8 sites) - Update TODO docs to reflect completed work https://claude.ai/code/session_01EaBXwSmZrbVcpbFoV44Aju
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bf4a9a6eb7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| expr: Expr::var(&output_var) | ||
| .method("as_int", vec![]) | ||
| .method("is_some_and", vec![ | ||
| Expr::Closure { | ||
| args: vec!["n".to_string()], | ||
| body: Box::new(Expr::Str(format!("n >= {}", threshold))), |
There was a problem hiding this comment.
Fix IntGe/IntLe codegen to emit boolean expressions
The new IntGe/IntLe matchers build the closure body with Expr::Str, which the Rust renderer turns into a string literal. That generates code like var.as_int().is_some_and(|n| "n >= 2"), where the closure returns &str instead of bool, so the generated tests won’t compile when these matchers are used (IntLe has the same pattern). This should emit a boolean expression node rather than a string literal (or use a dedicated expression variant for binary ops).
Useful? React with 👍 / 👎.
Migrate all call sites to use the new helpers introduced in the previous commit, eliminating boilerplate and manual construction: - propagate_skipped(): 8 sites in 3 files (bootstrap/ops, ci/ops, llm-ops) — replaces 5-10 line if-matches-return blocks - ShellResponse::ok()/failed(): graph_mock files, bin/ci, ops tests, git-ops tests — replaces 3-field struct literals - From impls: TransportResponse/TransportRequest wrapping replaced with .into() across graph_mock files, bin/ci, ops tests Fix cardinality Empty absence testing (Hack 5): - cardinality_case_mock_value() now emits Value::Unit for scalar Empty (String, Bool, Int) instead of concrete "empty content" (false, 0, ""). Collection types keep empty collections. - Aligns with contract::witnesses() which already uses Value::Unit for absence. Cardinality boundary tests now exercise the actual absent-vs-present boundary. 14 files changed, -84 net lines. 1062 tests pass, zero clippy warnings. https://claude.ai/code/session_01EaBXwSmZrbVcpbFoV44Aju
The IntGe/IntLe matchers used Expr::Str to build the closure body,
which rendered as a string literal ("n >= 2") instead of a boolean
expression (n >= 2). Generated tests using these matchers would fail
to compile because the closure returned &str instead of bool.
Fix: Add Expr::BinOp { left, op, right } and Expr::IntLit(i64) to
the test IR. BinOp renders as `left op right` (e.g., `n >= 2`).
IntLit renders as a bare integer (not Value::Int(n)), needed inside
closures that operate on unwrapped i64 values.
Before: x.as_int().is_some_and(|n| "n >= 2") // &str, won't compile
After: x.as_int().is_some_and(|n| n >= 2) // bool, correct
https://claude.ai/code/session_01EaBXwSmZrbVcpbFoV44Aju
…gger Two BLOCKING inline review findings on PR #2164: 1. **Bootstrap snapshot missing carrier** (line 41 finding) — P2 facts- flow-forward violation. Ran `cargo run -p v3-compiler --bin regen_bootstrap --features bootstrap-regen-fresh`; refreshes `bootstrap_generated.rs` + `bootstrap_generated_without_parse_surface.rs` + `bootstrap_std_generated.rs` so `CoproductProjection` is present for downstream consumers. 2. **WireTagValue 🟡 SCAFFOLD with "none" trigger** (line 67 finding) — INVARIANTS.md P5 violation. Replace "Dissolution trigger: none" with a named two-clause checkable trigger: (a) §1.8 gates #29-#30 close (closure-predicate consumers land), AND (b) at least one non-StringTag arm added in response to an observed wire surface, OR explicit Practice-4 closure receipt naming the substrate observation that all REST/LLM wire boundaries are string-shaped. Plus re-escalate-to-Mgr clause if a consumer surfaces a wire-tag shape StringTag cannot express. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…1702 re-dispatch enabler (#2164) * WIP: Substrate S5: Variant-aware projection metadata carrier — Anthropic #170 * fix(s5): correct DeclarationRef import + refresh parse manifest Mgr review BLOCKING (PR #2164): - Import was `v3.spec.v3_l1 { DeclarationRef }` (empty record `{}`) but brief + Director's path-(a) ratification reference the `dsl/std/serialization.dag::DeclarationRef = String` alias. - Switch to `import std.serialization { DeclarationRef }` to match the disposition'd shape. - Inline doc-comment surfaces the two-co-existing-DeclarationRefs P2 concern as a separate substrate gap (likely folds into audit-row #14 module-convergence dissolution trigger). Refresh `parse_corpus_manifest.txt` for the new `src/v3/std/coproduct_projection.dag` file row (regenerated via `cargo test -p v3-compiler refresh_handwritten_parse_snapshot_manifest -- --ignored`). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(s5): regen bootstrap snapshot + name WireTagValue dissolution trigger Two BLOCKING inline review findings on PR #2164: 1. **Bootstrap snapshot missing carrier** (line 41 finding) — P2 facts- flow-forward violation. Ran `cargo run -p v3-compiler --bin regen_bootstrap --features bootstrap-regen-fresh`; refreshes `bootstrap_generated.rs` + `bootstrap_generated_without_parse_surface.rs` + `bootstrap_std_generated.rs` so `CoproductProjection` is present for downstream consumers. 2. **WireTagValue 🟡 SCAFFOLD with "none" trigger** (line 67 finding) — INVARIANTS.md P5 violation. Replace "Dissolution trigger: none" with a named two-clause checkable trigger: (a) §1.8 gates #29-#30 close (closure-predicate consumers land), AND (b) at least one non-StringTag arm added in response to an observed wire surface, OR explicit Practice-4 closure receipt naming the substrate observation that all REST/LLM wire boundaries are string-shaped. Plus re-escalate-to-Mgr clause if a consumer surfaces a wire-tag shape StringTag cannot express. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(s5): add CoproductProjection to bootstrap_authority + refresh manifest CI failures on PR #2164 sha 4952323: - `parse_stage4_prep::handwritten_parse_snapshot_matches_manifest`: stale hash for `coproduct_projection.dag` — manifest carried the pre-`e65efb82b` hash (before WireTagValue trigger expansion). - `pb1_bootstrap_full_snapshot_test::bootstrap_authority_rows_match_full_bootstrap_source_files`: the new `src/v3/std/coproduct_projection.dag` was bundled by the build.rs std staging but missing from `bootstrap_authority.dag`'s authority map → P2 single-authority gap. Fixes: - Add `"src/v3/std/coproduct_projection.dag": V3StdAuthority` row (alphabetical between computation_model and cross_target_coverage). - Re-run `regen_bootstrap` + `refresh_handwritten_parse_snapshot_manifest` so `bootstrap_generated*.rs` + `parse_corpus_manifest.txt` reflect the current carrier content + authority. Both tests verified green locally. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: Substrate S5: Variant-aware projection metadata carrier — Anthropic #170 * fix(s5): resolve codex BLOCKING + lane2 stack overflow via typed DeclarationRef Three concurrent findings on PR #2164 sha 0e18508: 1. **Codex BLOCKING** (sha 0e18508): `bootstrap_authority.dag` omits `dsl/std/serialization.dag`, so `import std.serialization { DeclarationRef }` cannot materialize the String-alias authority in generated snapshots → silent mis-resolution at bootstrap time. 2. **Codex non-blocking** (sha c9ebf46): `v3.spec.v3_l1::DeclarationRef` "resolves to a typed declaration reference" (not String); the debt-paydown row prose treating it as a String alias is incorrect. 3. **CI v3 lane2 stack overflow** (sha 0e18508): `lane2_stage_2d_ symbolic_cost_test::branch_reports_constant_when_both_arms_constant` stack-overflows on the 2MB test-thread default after my carrier adds traversal pressure to the bootstrap; reproduces locally. Resolution path (codex's option (b)): switch carrier to import the structural typed `DeclarationRef` from `v3.spec.v3_l1` (already in `V3SpecAuthority`, no authority gap), reverting Mgr's prior `std.serialization` BLOCKING — the tri-way tension resolves cleanly: - No bootstrap-authority gap (v3_l1 is already authoritative) - No stack-budget regression (no new files added to bootstrap) - Debt-paydown row retitled per codex non-blocking guidance: "unrefined-any-declaration handle" — same #1175 substrate gap classification as MethodRef (`methods.dag:31`) + CallableRef (`services.dag:86-100`); dissolution trigger is the shared refinement-typing-on-DeclarationRef landing. - Inline doc-comment in carrier surfaces the tri-way tension and selection rationale for future readers. Additional carrier reduction (separate from BLOCKINGs but absorbed in this commit since it's the lane2 stack-overflow root cause): - `FieldShape {}` removed; `FieldProjection.Fields { fields: Map<String, FieldShape> }` collapsed to `FieldProjection.Populated` placeholder. Defers populated-case detail to first paydown PR per Mgr-disposed sliced-follow-up; same Practice-4 SCAFFOLD discipline. Gate 3 (i) trivial in-PR demo (Mgr-disposed at #2154 c#4400893282) attempted via `data anthropic_chat_message_projection: CoproductProjection` but blocked by DSL parser limitation: `Map<K, Record>` literals are not supported in `src/v3/std/` layer (zero precedent; tried both inline records and ident-reference values, both surfaced `expected field label, got StringLit("UserMessage")` parse errors). Surfaced as substrate-tooling gap; gate 3 reverts to (ii) defer-to- first-paydown disposition. Inline doc-comment in carrier captures the parser limitation for the lane. All gates green locally: - `cargo run regen_bootstrap` ✓ - `cargo test refresh_handwritten_parse_snapshot_manifest --ignored` ✓ - `parse_stage4_prep::handwritten_parse_snapshot_matches_manifest` ✓ - `pb1_bootstrap_full_snapshot_test` 8/8 ✓ - `lane2_stage_2d_symbolic_cost_test::branch_reports_constant_when_both_arms_constant` ✓ (no overflow) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(s5): single-authority debt prose — remove stale String-alias references gpt-5-5-pro REQUEST_CHANGES on PR #2164 sha 6de6a4d (BLOCKING): substrate scaffolds need a single live authority for what is debt and what dissolves it. After the import-switch to typed v3.spec.v3_l1 DeclarationRef, several comments still described the prior String-alias disposition, and `VariantId`'s dissolution trigger named an audit-row #14 OR string-bridge OR-trigger that conflicted with the ledger's new shared-with-#1175 trigger. Fixes: 1. **Top-of-file "DeclarationRef alias debt" block** (was: "DeclarationRef = String alias accepted for this slice; ... 2-clause OR-trigger audit-row #14 OR string-bridge"): retitled "DeclarationRef debt — unrefined-any-declaration handle"; describes the typed-import path and shared #1175 dissolution. 2. **`VariantId` SCAFFOLD trigger** (was: "(a) audit-row #14 closes module-convergence OR (b) string-identity-bridge surfaces"): rewritten to single-authority shared-#1175 trigger paired with `DeclarationRef` ledger row — no separate OR-trigger applies; the carrier-level dissolution is single-keyed on #1175. 3. **`CoproductProjection.declaration` doc** (was: "carries the `DeclarationRef = String` alias soft-typed handle per Director observation #1 disposition (b)"): rewritten to describe the structural typed reference + shared #1175 trigger. Remaining mention of "`DeclarationRef = String` alias" at the import- site comment is intentional historical context — it explains what was rejected (and why) in the selection rationale; not a current-state characterization of the carrier. All local gates green post-fix: - `regen_bootstrap` ✓ + manifest refresh ✓ - `parse_stage4_prep::handwritten_parse_snapshot_matches_manifest` ✓ - `lane2_stage_2d_symbolic_cost_test::branch_reports_constant_when_both_arms_constant` ✓ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * WIP: Substrate S5: Variant-aware projection metadata carrier — Anthropic #170 * fix(s5): bump lane2 symbolic-cost test stack to 8MB; restore FieldProjection Post-merge of main (commit f29f34c brought in 36 lines of dsl/std/integer.dag + extdeps changes) re-triggered lane2_stage_2d_symbolic_cost_test:: branch_reports_constant_when_both_arms_constant stack overflow that had been resolved at sha 0998705. Carrier-shape reduction alone could not keep this PR under the 2MB cliff after the merge. **Substrate-tooling fix**: apply the existing 8MB-stack-thread precedent (m2_substrate_inhabitance_test.rs:23-35's `with_full_bootstrap_stack` pattern) to the failing test. The test's existing doc-comment explicitly documents it as a ratchet exception that pays a cold bootstrap+pipeline compile and is on the budget edge; the named dissolution trigger ("cache bootstrap Dag state as input to compile_to_dag") remains the load-bearing fix. Stack bump is the cliff-edge workaround until that lands. With the test-thread budget fixed, restore FieldProjection (`Empty | Populated`) on `CoproductVariantProjection.field_projection` — brings the carrier back to brief's path-(a)-ratified shape (per- variant single-keyed fact: payload projection + wire-tag value). Populated-case detail (typed `Map<String, FieldShape>` payload field projection) still deferred to first paydown PR consumer per Mgr- disposed sliced-follow-up. Verified locally: - regen_bootstrap ✓ - refresh_handwritten_parse_snapshot_manifest ✓ - parse_stage4_prep::handwritten_parse_snapshot_matches_manifest ✓ - pb1_bootstrap_full_snapshot_test 8/8 ✓ - lane2_stage_2d_symbolic_cost_test::branch_reports_constant_when_both_arms_constant ✓ (no overflow) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(s5): disambiguate debt-row PR reference per cursor exploratory cursor/composer-2 sha f29f34c exploratory note flagged that the debt-paydown row's 'PR introducing #1947' phrasing was ambiguous; clarified to 'PR #2164, closing #1947' since #1947 is the work-item issue and #2164 is the PR ID. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…product Authored against current main (squash-author per Mgr disposition (b2) at gunbc#2063 c#4403150939). Preserved branch `origin/codex/cc1-target-integer-structural-fold` is the design reference; its 3 cited tip commits were not self-contained — the underlying `AnthropicMessages200ContentBlock` coproduct was introduced by earlier preserved-branch commits not in the cited set, so a history-preserving rebase was infeasible. v2 source `dsl/extdeps/llm/anthropic.dag`: - Replace `AnthropicMessages200TextBlock` record with `AnthropicMessages200ContentBlock` coproduct (6 variants: MessagesTextBlock | MessagesThinkingBlock | MessagesRedactedThinkingBlock | MessagesToolUseBlock | MessagesServerToolUseBlock | MessagesWebSearchToolResultBlock). - Add `AnthropicServerToolName` enum (8 variants from Anthropic's generated OpenAPI SDK). - Update `AnthropicMessages200Body.content: List<AnthropicMessages200ContentBlock>`. - Add `anthropic_messages_200_content_block_wire_contract` row. - Refresh `structural_coverage_gap_anthropic_messages_200_residual` rows to track post-coproduct residuals. v3 mirror `src/v3/std/anthropic_schema.dag`: - Mirror coproduct + enum. `MessagesRedactedThinkingBlock.data` is mirrored as `redacted_data` (data is a v3 keyword); the lockstep ratchet maps that single label. Lockstep test `src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs`: - New `assert_anthropic_disj_lockstep` helper applies the `data → redacted_data` label remap before disj-lockstep comparison. - Replace `anthropic_messages_200_text_block_lockstep` with `anthropic_messages_200_content_block_lockstep`. - New `anthropic_server_tool_name_lockstep`. Bootstrap regen + parse manifest refresh follow. §1.8 ledger: gates #29 (anthropic_wire_typed_serde_alignment) + #30 (anthropic_unit_enum_role_serialization_correct) advance via schema-mirror + lockstep extension. Gate #68 demonstration deferred to follow-up (deterministic-mock test not in scope per Mgr discretion). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…1981 [S5 cascade cleared; ready] (#2208) * WIP: Grounding G5: Anthropic #1702 re-dispatch — recreated supersession of #1 * G5 Anthropic #1702 re-dispatch: AnthropicMessages200 content-block coproduct Authored against current main (squash-author per Mgr disposition (b2) at gunbc#2063 c#4403150939). Preserved branch `origin/codex/cc1-target-integer-structural-fold` is the design reference; its 3 cited tip commits were not self-contained — the underlying `AnthropicMessages200ContentBlock` coproduct was introduced by earlier preserved-branch commits not in the cited set, so a history-preserving rebase was infeasible. v2 source `dsl/extdeps/llm/anthropic.dag`: - Replace `AnthropicMessages200TextBlock` record with `AnthropicMessages200ContentBlock` coproduct (6 variants: MessagesTextBlock | MessagesThinkingBlock | MessagesRedactedThinkingBlock | MessagesToolUseBlock | MessagesServerToolUseBlock | MessagesWebSearchToolResultBlock). - Add `AnthropicServerToolName` enum (8 variants from Anthropic's generated OpenAPI SDK). - Update `AnthropicMessages200Body.content: List<AnthropicMessages200ContentBlock>`. - Add `anthropic_messages_200_content_block_wire_contract` row. - Refresh `structural_coverage_gap_anthropic_messages_200_residual` rows to track post-coproduct residuals. v3 mirror `src/v3/std/anthropic_schema.dag`: - Mirror coproduct + enum. `MessagesRedactedThinkingBlock.data` is mirrored as `redacted_data` (data is a v3 keyword); the lockstep ratchet maps that single label. Lockstep test `src/v3/compiler/tests/integration/anthropic_schema_lockstep_test.rs`: - New `assert_anthropic_disj_lockstep` helper applies the `data → redacted_data` label remap before disj-lockstep comparison. - Replace `anthropic_messages_200_text_block_lockstep` with `anthropic_messages_200_content_block_lockstep`. - New `anthropic_server_tool_name_lockstep`. Bootstrap regen + parse manifest refresh follow. §1.8 ledger: gates #29 (anthropic_wire_typed_serde_alignment) + #30 (anthropic_unit_enum_role_serialization_correct) advance via schema-mirror + lockstep extension. Gate #68 demonstration deferred to follow-up (deterministic-mock test not in scope per Mgr discretion). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Address PR review: add caller: Json? to MessagesWebSearchToolResultBlock Anthropic's Messages API reference lists web_search_tool_result with caller alongside content/tool_use_id/type. The initial scaffold dropped it. Add caller: Json? on both v2 source and v3 mirror; extend the residual row to track the caller-payload typing alongside the content-payload typing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Soften scaffold comment: variant-aware projection is tracked debt, not pre-merge gate Per PR review (gpt-5-5-pro exploratory observation): the scaffold trigger comment said "before this draft can merge" while the residual row at :208-213 already tracks the same item as tracked debt with an explicit trigger. Reword to point at the residual list rather than implying a pre-merge gate. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…om cluster-analysis audit + today's merges (#2399) Addresses PR #2358 §8 meta-finding (closure-claims-vs-HEAD drift) via explicit Status refresh on §1.8 rows. Cluster-analysis audit on main (PR #2300 / docs/audit/r3-cluster-analysis-2026-05-09.md §1) identified 9 gates likely-promotable from DECLARED → CONSUMER_LANDED + named specific PRs as evidence. Today's session adds 1 more (#92 via PR #2340). Per cluster-analysis audit §1 closing note: "PM surface, not authoring: ledger refresh is Mgr-owned per docs/r3-program-plan.md §10 cadence. This list is input to next refresh cycle." PM (deep-wolf-155) interpretation: Mgr-cadence-discipline holds, but the cluster-analysis was published 2026-05-09T03:25Z + at least 9 gates are mechanically derivable from PR-history. Authoring this sweep as PM-tier signal-into-next-refresh; lane Mgrs review their lane's rows in this PR before merge. **Updates** (10 candidates): | Gate | From | To | Evidence | |---|---|---|---| | #25 omni_openapi_backend_emission_demo | DECLARED | CONSUMER_LANDED | PR #2251 (Shape B OpenAPI) | | #29 anthropic_wire_typed_serde_alignment | DECLARED | CONSUMER_LANDED | PR #2208 + #2164 | | #30 anthropic_unit_enum_role_serialization_correct | DECLARED | CONSUMER_LANDED | PR #2208 | | #53 workflow_substrate_carriers_landed | DECLARED | CONSUMER_LANDED (partial) | PR #2160 WorkflowSecret + CronExpression β-ratified | | #54 timing_lens_carrier_landed | DECLARED | CONSUMER_LANDED | PR #2360 (post-T-LBP COMPLETE) | | #76 e_p_per_call_descent_evidence_full_coverage | DECLARED | CONSUMER_LANDED | PR #2147 carrier + #2190 consumer | | #77 e_p_call_pattern_lookup_authoritative | DECLARED | DECLARED + verify-pending note | T-E-P P1 slices 1-7; Mgr review needed | | #78 e_p_sub_value_relation_per_call_landed | DECLARED | CONSUMER_LANDED | T-E-P P1 slices 1-7 | | #92 complexity_violation_compile_error_demonstrated | RECEIPT (ambiguous) | CONSUMER_LANDED + PASSING | PR #2340 | | #96 value_body_substrate_mirror_isomorphism_executable | DECLARED | CONSUMER_LANDED | PR #2288 (CI-visible integration) | Each cite includes PR# + brief evidence summary. #77 retained as DECLARED with verify-pending note (cluster-analysis audit said "verify"; Mgr review recommended before promotion). **Verification**: R4-carve dissolution discipline ratchet still passes (32 citations, all properly annotated). No new drift introduced. **Mgr review path**: Substrate Mgr (warm-wolf-698) reviews #29/#30/#53/ #54/#76/#77/#78/#96 lane rows. Verification Mgr (wise-bear-525) reviews #92/#96 lane rows. Grounding Mgr (sunny-koi-893) reviews #25 lane row. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
This PR completes two major infrastructure improvements:
Satisfiescomment-only codegen with typed matcher variants that generate real assertionsCardinalitythroughCliEntrypointto eliminate string-matching ontype_idBoth changes improve test reliability and code maintainability by making implicit assumptions explicit and serializable.
Key Changes
OutputMatcher Typed Variants
IsBool,IsInt,IsString,IsRequest,IsResponsetype checkersIntGe(i64)andIntLe(i64)for integer range assertionsAssert::Truecodegen (via method chains like.as_int().is_some())Satisfiesusages inci/graph_mock.rsandmakegen/graph_mock.rsSatisfiesremains as escape hatch for truly custom predicatesgenerates_assertion()to returntruefor all typed matchersCliEntrypoint Cardinality Integration
cardinality: Cardinalityfield toCliEntrypointtype_idfor backward compatibilitywith_cardinality()builder methodtype_id == "List"string checks withcardinality.allows_many()calls in:rust_type()— derives collection types from cardinalityvalue_constructor()— uses cardinality to selectValue::str_listvs scalar constructorsis_repeatable()— new method for CLI flag repeatabilitygenerate_arg_parsing()— collection vs scalar argument handlinggenerate_print_inputs()— debug output formattinggenerate_help_options()— type hints in help textmakegen/registry.rsto useep.cardinality.allows_many()directlySupporting Infrastructure
ExecError::context()method andResultExttrait for structured error contextShellResponse::ok()/failed()constructors for transport response modelingFrom<T> for TransportRequest/Responseimpls for all 5 transport typespropagate_skipped()helper to eliminate repeated skip-propagation patternsImplementation Details
Codegen for typed matchers: Uses method chains on
Valueaccessors:IsBool→var.as_bool().is_some()IntGe(n)→var.as_int().is_some_and(|n| n >= threshold)Cardinality inference:
CliEntrypoint::new()maps"List"and"Set"type_ids toZERO_OR_MOREfor backward compatibility, but new code should usewith_cardinality()explicitly.Migration scope: All existing usages in CI and makegen graph mocks updated; no breaking changes to public APIs.
Testing
https://claude.ai/code/session_01EaBXwSmZrbVcpbFoV44Aju