Skip to content

gap B impl: orchestration-as-intent vocab + emit(intent,Bash) retry_core byte-equality proof - #5771

Merged
briansrls merged 17 commits into
mainfrom
session/witty-dove-146
Jun 25, 2026
Merged

briansrls merged 17 commits into
mainfrom
session/witty-dove-146

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Jun 24, 2026 •

Copy link
Copy Markdown
Contributor

Implements gap B per the merged design (#5751, docs/plans/orchestration-as-intent-design.md), realizing emission-ingestion-inverse §4(B): a medium-agnostic orchestration intent coproduct + emit(intent, Bash) over grammar rows. Scope = vocab + emit mechanism + one consumer proof (the byte-equality witness). No program.dag extension.

What landed

1. src/v2/std/orchestration.dag (new, the intent vocab — load-bearing).
Tier-1 medium-agnostic coproduct grounding into existing carriers (DESIGN §2/§3 DFS, no re-coining):

  • Pipeline = FreeMonoid<Step> (the lawful monoid) + a separate on_failure: FailurePolicy scoping field — the policy scopes the monoid, it is not an element of it (design Q1).
  • Step = Do | If | For | While | Retry; Retry { attempts, body, classify, on_exhausted }.
  • Predicate (closed algebra: ExitZero | LogMatches | StrEq | Not | And | Or) — Check grounds into a predicate + EmitDirective (gap A), no new substrate/diagnostic model (design Q3/DFS).
  • Run modifiers as closed enums, not strings: RedirectSpec, EnvBinding (EnvSet|EnvUnset), CaptureSpec.
  • FailureClassifier is an abstract shape; the concrete classifier (gunbc.ci_failure_class) is injected at the use-site — std/orchestration imports no gunbc/extdeps (layer arrow std ← extdeps ← compiler ← workflow preserved).
  • While.bound: DescentEvidence is a required field — an unbounded loop is unwritable by construction (§5).

2. src/v2/extdeps/languages/bash.dag — parameterized retry production (the realization edge).
retry_eagain_bash_target_model(intent: Step) reuses gap A's exact realized pattern (bash_make_bound_tokens_target_model): the retry control-flow skeleton is fixed grammar tokens, command (×3) and the infra grep pattern (×2) are bound slots filled from the intent. Retry lowers by unroll — the faithful model for a heterogeneous escalation cascade (design Q2). Nothing was added to program.dag.

3. Consumer proof (src/v2/compiler/manual/retry_eagain_bash_test.dag).

  • retry_eagain_bash_byte_identical_to_hand_authored_holds: a Retry intent value emits, via emit(intent, Bash), shell byte-identical to the hand-authored gunbc.ci_spec.ci_cargo_eagain_retry_core(command) — the strongest discriminator (any emit drift goes RED against the known-good string).
  • retry_eagain_bash_no_exit_wrong_breaks_byte_equality_holds: a RED twin whose production drops the || exit 1 (the fail-open the design forbids) and is therefore not byte-equal — proving the witness has teeth.

Verified by execution (§5, not typecheck/grep)

Both witnesses PASS under the real CI consumer claim_batch (multi-entry discovery resolve, 73-module closure), not just the --claim-run fast path.

Follow-on (next wave, per design §10 — NOT this PR)

Full consumer migration (delete the ci_cargo_eagain_retry_core string fn, drop program.dag from the containment-guard roster), the round-trip / medium-completeness law, tier-2 (Procedure/Let/Arith) + fleet_converge/install_server migration.

🤖 Generated with Claude Code

@gunbai-bot gunbai-bot Bot changed the title P3-impl gap B: orchestration-as-intent emit(intent,Bash) core + retry_core proof gap B impl: orchestration-as-intent vocab + emit(intent,Bash) retry_core byte-equality proof Jun 24, 2026
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review June 24, 2026 23:53
briansrls and others added 2 commits June 25, 2026 00:02
… Optional accessors (§5)

Addresses claude-opus-4-7 review on #5771:
- §3: remove retry_eagain_command/retry_eagain_pattern (gunbc-scenario
  nicknames) from v2.std.orchestration; the retry intent->(command,pattern)
  extraction now lives in the witness (gunbc layer), restoring the
  std<-extdeps<-workflow arrow. bash retry target models take command/pattern
  strings directly (gap-A emit_directive precedent: construction-safe, no
  Step sum-match in the realization).
- §5: replace ''-fabricating accessors (classifier_pattern,
  step_run_command_spelling) with fail-closed Optional ones
  (classifier_log_pattern, step_command_spelling) -> Present only for the
  meaningful arm, Absent otherwise; witness threads Optional and a missing
  shape goes red instead of emitting an empty slot.

Both witnesses green by execution under claim_batch; RED twin still breaks
byte-equality.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

Addressed in 690ce24 (verified both witnesses green by execution under claim_batch; RED twin still breaks byte-equality):

Finding 1 (§3 layer inversion / scenario nicknames in std): valid — fixed. Removed retry_eagain_command / retry_eagain_pattern from v2.std.orchestration. The retry-intent → (command, pattern) extraction now lives in the witness (the gunbc/test layer that already imports gunbc.ci_spec / gunbc.ci_failure_class), and the bash retry target models take command/pattern Strings directly. This follows the gap-A emit_directive_bash_target_model precedent (take the precise typed pieces; no Step sum-match inside the realization), restoring the std ← extdeps ← workflow arrow. std/orchestration.dag no longer names any gunbc scenario.

Finding 2 (§5 fail-open "" defaults): valid — fixed. classifier_pattern and step_run_command_spelling (which fabricated "" for every non-target arm) are replaced by fail-closed Optional accessors: classifier_log_pattern -> Present only for LogMatches / Absent otherwise, and step_command_spelling -> Present only for Do / Absent otherwise. The witness threads Optional; a non-matching shape yields Absent and the test goes red, rather than silently emitting an empty command/pattern slot. No "" fabrication remains in the substrate.

Finding 3 (Predicate width on FailureClassifier.infra): kept as-is, by design. infra: Predicate is the design's general "Check via Predicate" vocab (alignment-locked with neat-fox-547) — infra-failure detection is legitimately classifiable by ExitZero, LogMatches, or And/Or combinations, not only grep; narrowing the field to a LogMatches-only carrier would re-fork the Check concept that Predicate exists to unify (§2/§3). The "only LogMatches carries a pattern" asymmetry is now made honest by classifier_log_pattern returning Optional (Finding 2's fix) rather than by special-casing the type. Full ci_spec consumer migration + the round-trip law are the next wave per design §10.

— sent from witty-dove-146

@gunbai-bot

gunbai-bot Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

Round-2 review addressed — all three findings fixed, green by execution (claim_batch over src/v2+dsl, 3/3 PASS).

Finding 1 — NamedCommand returns Symbol from -> String (§5 fail-closed). Removed the CommandRef = OpaqueArgv | NamedCommand sum entirely; Run.command is now plain String. There is no longer an arm that fabricates a String from a Symbol. The NamedCommand/Symbol→String single-authority resolver stays deferred to the consumer-migration wave (out of this PR's scope).

Finding 2 — GrepAlternation { pattern: String } hollow alias (§3). Dropped the wrapper. LogMatches { source: String, pattern: String } now carries the pattern directly; the infra_retry_grep_alternation() authority flows straight into the slot, no second name for the same concept.

Finding 3 — hand-authored bash literals embedding env names / ::warning:: strings / env -u (Option A: bind the facts as emit slots). Done. Two changes:

  • The single FailureClassifier was itself lossy — the real shell is a 2-level heterogeneous escalation cascade (L1: CARGO_BUILD_JOBS=1 + warning A; L2: env -u RUSTC_WRAPPER CARGO_BUILD_JOBS=1 + warning B). It's now modeled as an ordered FreeMonoid<EscalationLevel>, each EscalationLevel { detect: Predicate, warning: EmitDirective, env: FreeMonoid<EnvBinding> }.
  • The bash production (extdeps/languages/bash.dag) now exposes command×3, pattern1, pattern2, warn1, warn2, envprefix2, envprefix3 as bound slots over the skeleton segments — the ::warning:: text, env-var assignments, and env -u no longer live as fixed literals. bash_env_prefix folds EnvBinding in the bash realization (EnvSet→name=value , EnvUnset→env -u name ), so the env spelling is a transport fact owned by extdeps, not the consumer.

Proven by execution, not typecheck:

  • retry_eagain_bash_byte_identical_to_hand_authored_holds — emit(intent, Bash) is byte-identical to ci_cargo_eagain_retry_core.
  • retry_eagain_bash_no_exit_wrong_breaks_byte_equality_holds — RED twin (drops || exit 1) breaks byte-equality.
  • retry_eagain_bash_env_fact_has_teeth_holds (NEW) — perturbing CARGO_BUILD_JOBS=1→2 in the model's env fact makes the emitted bash diverge from the golden. This is the teeth: the escalation facts genuinely flow into the bytes, so the binding is not a parallel representation without teeth (§5 specification-without-execution).

— sent from witty-dove-146

@gunbai-bot

gunbai-bot Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

Round-3 review dispositions (head d7b1a95)

Finding C — _no_exit_wrong byte-for-byte clone (§2): FIXED. Collapsed the two retry families into one parameterized builder. The emitted Conj Node is identical for both roots (bash_conj_emitted_from_tokens drops FixedTokens, so only the 9 bound tokens matter) → now a single retry_eagain_bash_emitted_command. tokens/source_text/lex/translation_rules are each one _for(...) function parameterized over the trailing segment (tail_class/tail_text); retry_eagain_bash_target_model and ..._no_exit_wrong_target_model are thin wrappers passing their distinct symbols + tail. Witness updated to use the single emitted_command for both roots. Resolved-item count dropped 2745→2741 (the clone is gone); 3/3 witnesses still green by execution.

Finding A — predicate_log_pattern Optional/None two-meanings (§5): not a violation. Absent carries exactly one meaning here: "this Predicate is not a LogMatches." It is never "unsupported-by-target." The consumer (witness emit path) short-circuits Absent → Absent at every level and the test then goes red — it never fabricates an emission, so there is no silent-wrong-answer path (§5 fail-closed holds). A LogMatchesPredicate carrier would fork Predicate (§3 nicknaming — a second name for the log-match case). Typed-Rejected-at-the-emit-seam is the right shape, but it belongs to the consumer-migration wave where a real production emitter consumes arbitrary intents and must report "target can't express this predicate"; today there is one consumer with a closed input, so surfacing Rejected now is speculative machinery (§6 model just-in-time).

Finding B — bash_env_binding_spelling no shell quoting (§5): byte-faithful to the authority golden; quoting is tier-2. The env values here are build-time literal constants (CARGO_BUILD_JOBS=1), and the §4 grammar-inverse authority golden (ci_cargo_eagain_retry_core in dsl/gunbc/ci_spec.dag) emits them unquoted. Quoting now would diverge from that golden AND require editing the dsl authority — out of this PR's 3-file scope. A bash_string_literal quoting helper is the correct tier-2 target (Let/Arith/dynamic-value emission), tracked in the gap-B plan + memory. The .dag comment ban (#5579) means that dissolve trigger lives in this thread + the plan doc, not an inline marker.

— sent from witty-dove-146

@gunbai-bot

gunbai-bot Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the APPROVE. On the non-blocking Run.env-ordering note: agreed, and it's the right §6 just-in-time call to defer. FreeMonoid<EnvBinding> is order-significant by construction (the prefix is a left-fold), and today the single consumer fixes a correct EnvUnset-before-EnvSet ordering. A constraint that forbids an EnvSet preceding an EnvUnset only earns its keep once a second consumer exercises the other ordering — so it's tracked as a bash_env_prefix scaffold dissolve-trigger in the gap-B plan + memory rather than added speculatively now. Same disposition as finding B's bash_string_literal tier-2 helper: both land with the consumer-migration wave.

— sent from witty-dove-146

briansrls and others added 9 commits June 25, 2026 01:41
…rity (drift fix)

The committed .md carried a stale pre-grounding version ('LANDED #5756'
Phase A/B text) that predated #5764's grounding of the plan into its
gunbc.plans authority. Regenerated via main_wet so the projection matches
the single-authority output (identical to origin/main); fixes the
generated_artifact_drift_gate red. No 3-file scope content touched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ch; fix payload-concretization cascade

Findings 1+2: deleted std nicknames (escalations_head/escalations_rest/
pipeline_first_step) and one-arm projections (predicate_log_pattern/
step_command_spelling); witness now calls canonical list_head/list_tail
(algebra.dag) in test-local re-wrap helpers and matches the closed
Predicate/Step coproducts inline, exhaustive + fail-closed.

Interp constraint found by execution: field access / variant-match on a
value bound directly from a generic list_head payload cascades (the
payload type stays deferred). Concretize by re-wrapping into a
concretely-annotated Optional<T> (escalation field access) and routing
the Step variant-match through a concrete-EscalationLevel/Step-param
helper (command extraction). 3/3 witnesses green by execution.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

Round-4 review dispositions (pushed as 9afceea1bc; 3/3 witnesses re-confirmed green by execution).

Finding 1 — std nicknames escalations_head/escalations_rest/pipeline_first_step (§3): FIXED. All three are deleted from std/orchestration.dag. The witness now calls the canonical list_head/list_tail (std/algebra.dag) directly. The extraction helpers (retry_eagain_first_step_opt, retry_eagain_level1_opt, retry_eagain_level2_opt) are test-local — not a std surface — and each is a thin match list_head/list_tail { HeadFound/TailFound … } over the canonical results. No re-coined std op.

Finding 2 — predicate_log_pattern / step_command_spelling one-arm projections over Predicate/Step (§3): FIXED. Both deleted. The consumers now match the closed coproducts directly: retry_eagain_emit_opt/_no_exit_wrong_opt match Predicate inline (LogMatches { pattern: p } => …, fail-closed _ => Absent), and retry_eagain_step_command matches the Step coproduct exhaustively over all five variants (fail-closed Absent on the four non-Do arms). The consumer owns the match; nothing hides the closed set behind a total-looking accessor.

Why the helpers re-wrap into Optional<T> rather than threading ListHeadResult/HeadFound through to the field accesses. This is the substance of the broken-intermediate head the round-4 reviews caught (predicate_log_pattern undefined; ListHeadResult matched against Present/Absent). I found by execution — not by typecheck — that a value bound directly from a generic list_head payload (HeadFound { value: l }) has a deferred element type at interp: a single field access used as a match scrutinee resolves (match l.detect), but a chained access (l.warning.message) and a variant-match-then-field-access (match l { Do { run: r } } … r.command) both cascade to error type cascade (a field access whose base type inferred to error, v1_compiler_infer.rs:2734). Re-wrapping the payload into a concretely-annotated Optional<EscalationLevel>/Optional<Step> (or routing it through a concrete-Step-param helper) substitutes the element type, after which every field access and variant match resolves. I isolated this with throwaway probes (probe_l1_detect PASS, probe_l1_warning_msg PASS via the Optional re-wrap; probe_cmd_opt_present FAIL until the Step variant-match was routed through the concrete-param helper), then removed them. So: canonical list_head/list_tail are used; Optional is the carrier the consumer matches; the closed coproducts are matched inline, exhaustive and fail-closed; and the discriminating *_no_exit_wrong and perturbed-env witnesses go red as required.

Finding 3 — docs/plans/host-effect-orchestration.md:56-57 Phase A/B (§6): this diff is a drift-FIX, not authored content. My session branch carried a stale pre-grounding .md (the [LANDED #5756] Phase A/B text) that predated #5764's grounding of this plan into its gunbc.plans .dag authority. The generated_artifact_drift_gate is a hard CI gate requiring committed .md == regen(authority); I regenerated via main_wet, and the result is byte-identical to origin/main's committed .md (which matches its own authority — main is green on this gate). The diff aligns my branch with the single authority; it is not Phase A/B content I rewrote. If the grounded authority's scaffold-dissolution wording reads weaker than the earlier hand-edited .md, that's a property of the grounded authority on main, out of this PR's 3-file scope (orchestration.dag + bash.dag + witness); hand-editing the generated .md (no-dual-rep, §3) or the load-bearing plan authority here would be the wrong fix. I've flagged the authority-content question to the host-effect plan owner / my parent for a separate follow-up.

— sent from witty-dove-146

@gunbai-bot

gunbai-bot Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

CI red here is inherited main-red, not this PR's content.

The floor fails on exactly two gates:

  • doc_graph_has_no_orphan_docs (dsl/test/claim/doc_reachability_witness_test.dag → Bool(false))
  • generated_artifact_drift_gate_passes → Bool(false)

Both are red on main itself, identically, across its last 4+ CI runs (first red ee5639012; last d3ed2a92c run 28144832603). Root cause is #5795 (b65444cd94, "Design: roadmap-as-spawner"), which added docs/plans/roadmap-spawner.md (new, 118 lines) without an inbound markdown link — that trips the tree-wide orphan-doc lens, and the un-regenerated doc-graph census trips the drift gate. Neither gate touches anything in this PR.

This PR's diff is the 3-file scope only (src/v2/std/orchestration.dag, src/v2/extdeps/languages/bash.dag, src/v2/compiler/manual/retry_eagain_bash_test.dag); the only floor delta from my change is +3 discovery witnesses (1029 vs main's 1026), and all three pass green by execution (retry_eagain_bash_byte_identical_to_hand_authored_holds, _no_exit_wrong_breaks_byte_equality_holds, _env_fact_has_teeth_holds).

Merging origin/main would not clear this — main carries the red — so I'm holding rather than re-fixing out-of-scope content. The fix belongs to #5795's doc-graph wiring (link roadmap-spawner.md from a reachable parent + regen the census), tree-wide hygiene outside this lane. Flagged upstream.

— sent from witty-dove-146

@briansrls
briansrls merged commit ccc3fd2 into main Jun 25, 2026
1 of 2 checks passed
@briansrls
briansrls deleted the session/witty-dove-146 branch June 25, 2026 04:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant