Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
335e151
docs: add a simple high-level gunbc ROADMAP task tracker
briansrls Jun 17, 2026
141f048
docs(roadmap): correct the resolve-blowup framing — un-enrolled compl…
briansrls Jun 17, 2026
0c3c179
docs(roadmap): correct overstated 'ci.yml generated from CiFloorSpec'…
briansrls Jun 17, 2026
8c64f80
WIP: 6/17 continuity (help me keep track of all the work thats happen…
briansrls Jun 17, 2026
fb2b2e6
docs(roadmap): slim to one line per task with indented breakdown
briansrls Jun 17, 2026
bc1060d
Merge remote-tracking branch 'origin/main' into session/merry-owl-830
briansrls Jun 17, 2026
c1b922c
Merge remote-tracking branch 'origin/main' into session/merry-owl-830
briansrls Jun 18, 2026
92444b7
WIP: 6/17 continuity (help me keep track of all the work thats happen…
briansrls Jun 18, 2026
2905b31
WIP: 6/17 continuity (help me keep track of all the work thats happen…
briansrls Jun 18, 2026
aa66dca
Remove resolution-coalescing design doc (review artifact; rationale m…
briansrls Jun 18, 2026
fb43af5
Merge remote-tracking branch 'origin/main' into session/merry-owl-830
briansrls Jun 18, 2026
23e820a
Merge remote-tracking branch 'origin/main' into session/merry-owl-830
briansrls Jun 18, 2026
6474fc3
Merge remote-tracking branch 'origin/main' into session/merry-owl-830
briansrls Jun 18, 2026
dafa991
WIP: 6/17 continuity (help me keep track of all the work thats happen…
briansrls Jun 18, 2026
50a1248
increment 3: realization materialization arm — reconcile→Share collap…
briansrls Jun 18, 2026
504bbcc
fix(realization): dissolve undispositioned is_share predicate; refres…
briansrls Jun 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,4 @@ still a violation) · internal review finds missing tests, external review finds

- `cargo test --workspace` · `cargo clippy --all-targets -- -D warnings` · `cargo fmt --all --check`
- one-time: `git config core.hooksPath .githooks` (pre-push runs `cargo fmt`)
- CI (`gunbc ci`, all `v1-compiler` seed bins, no shell gate): two composed passes in `.github/workflows/ci.yml` — (1) `claim_batch --roster-from-discovery` over `src/v2` plus the hand-enrolled Bool witnesses (`--source-root dsl`, shared module index; incl. the dsl compile-clean witness); (2) `gunbc run --entry dsl/tools/ci_gates.dag` sequences the effectful ProcessExit gates (rust fmt/clippy selector, emit-host MVP smokes, layering-imports host scan + perturb receipts, dsl whole-tree compile-clean, ci.yml drift+parse — SCAFFOLD on `--target rust` pending the `v1.compiler.dag_collect` identity-key fix) behind one resolve. Parse fallback: hand-written `yaml_check` bin (SCAFFOLD — dissolves when runner pins actionlint/PyYAML or parse becomes extdeps-only; see `src/v1/stage0/src/bin/yaml_check.rs`).
- CI (`gunbc ci` generates `.github/workflows/ci.yml`; all `v1-compiler` seed bins, no shell gate): **one** composed floor pass — `claim_executor --source-root src/v2 --source-root dsl --plan-entry src/v2/workflow/ci_floor_plan.dag --plan-function gunbc_ci_floor_batches`. The v2 scheduler decides the batches from the single-authority spec (`gunbc.ci_spec`); the only structural fact the plan adds is *compile-clean gates the rest* (batch-1 `dsl_compile_clean_gate` → batch-2 everything else, a dependency edge). Witness **discovery is tree-wide and marker-driven** (roster derived from `gunbc.ci_layer_roots`: `witness_layer_roots = [src/v2, dsl]`, `witness_discovery_scan_dirs = [dsl/test/claim]`): the source-root pass walks every `*_test.dag` under **both** trees and auto-enrolls each `test fn` — fail-closed, a `test fn` in a non-`_test.dag` file is a hygiene violation, so a witness cannot silently hide; the scan-dir pass adds `unified_claim_*` BoolWitnessClaim decls. So a new witness is floor-covered by *naming it* `<x>_test.dag` with a `test fn`, not by hand-enrolling it (`discover_floor_corpus_rows` in `cli_run.rs`). Batch-2 also carries the effectful gates: rust fmt/clippy monolith gate (when a `.rs` changes), emit-host MVP smokes, layering-imports scan + perturb receipts, source-root-ingest, and the `ci.yml` drift+parse gate (ci.yml == `gunbc ci` output). The compile-clean gate is `--target rust` — SCAFFOLD pending the `v1.compiler.dag_collect` identity-key fix that blocks `--target dag`. Parse fallback: hand-written `yaml_check` bin (SCAFFOLD — `src/v1/stage0/src/bin/yaml_check.rs`).
2 changes: 1 addition & 1 deletion dsl/std/effects.dag
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ fn create_double_init_collapsible(a: EffectShape, b: EffectShape) -> Bool {
match b {
CreateEffect { cause: cause_b } =>
match cause_b {
CreateIfAbsent { key_source: kb } => key_source_eq(a: ka, b: kb)
CreateIfAbsent { key_source: kb } => key_source_eq(left: ka, right: kb)
PostAlways => false
}
_ => false
Expand Down
62 changes: 60 additions & 2 deletions dsl/std/realization.dag
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,16 @@
// - v2/test/claim/realization_schedule_witness.dag enrolls in CI discovery when
// v2 self-compile-clean closes the Empty-in-generic sequence_outcome gap.
// - cache_interface.dag → Materialization rows become extdeps/realization handlers
// - RealizedStep / Placement / Materialization return in the feature follow-on
// - RealizedStep / Placement / Materialization re-introduced (increment 3: reconcile→Share);
// their ContentHash intent + licensed_by return in increment 4 (cross-tree content-hash)
// - target digest → content_hash(subgraph) when dsl/v2 cross-tree Node import lands

module std.realization

import std.types { Bool, String, List }
import std.effects {
EffectShape, ReadEffect, UpsertEffect, DeleteEffect, CreateEffect, AppendEffect,
key_source_eq
key_source_eq, create_double_init_collapsible
}
import std.realization_schedule {
RealizationPlan,
Expand Down Expand Up @@ -79,3 +80,60 @@ fn independence_from_effect_shapes(left: EffectShape, right: EffectShape) -> Ind
AppendEffect => Unknown
}
}

// --- Materialization arm (increment 3: reconcile → Share) ----------------------
//
// A RealizedStep is one node's realization: WHERE it runs (placement), HOW its
// result is materialized (recompute / memoize / share), and its cost. The intent
// digest (ContentHash) + licensed_by return in increment 4 when cross-tree Node
// content-hashing lands (trim marker above); for now the step carries its source
// EffectShape so reconcile can key the Share collapse on KeySource identity.

type Placement = LocalInProcess | LocalFilesystem | RemoteNetwork

type Materialization = Recompute | Memoize | Share

type RealizedStep {
shape: EffectShape
placement: Placement
materialization: Materialization
cost: CostAccount
}

// Mark every accumulator step whose effect is the same-KeySource create-if-absent
// twin of `s` as Share (s collapses INTO the shared materialization; not appended).
fn mark_collapsible_share(acc: List<RealizedStep>, s: RealizedStep) -> List<RealizedStep> {
acc |> map(e =>
if create_double_init_collapsible(a: e.shape, b: s.shape) {
RealizedStep {
shape: e.shape,
placement: e.placement,
materialization: Share,
cost: e.cost
}
} else {
e
}
)
}

// Does `s` have a same-KeySource create-if-absent twin already in `acc`?
fn has_collapsible_peer(acc: List<RealizedStep>, s: RealizedStep) -> Bool {
let peers = acc |> filter(e => create_double_init_collapsible(a: e.shape, b: s.shape))
!((peers |> length) == 0)
}

// Collapse same-KeySource create-if-absent steps into one shared materialization.
// Two steps with KeySource-equal CreateIfAbsent effects reconcile to ONE step whose
// materialization is Share; distinct identities (or non-create effects) stay separate.
// The collapse decision is create_double_init_collapsible (std.effects, KeySource-keyed) —
// reconcile only consumes it, never re-derives KeySource equality (§3 single authority).
fn reconcile(steps: List<RealizedStep>) -> List<RealizedStep> {
steps |> fold(init: [], f: (acc, s) =>
if has_collapsible_peer(acc: acc, s: s) {
mark_collapsible_share(acc: acc, s: s)
} else {
concat(acc, [s])
}
)
}
87 changes: 87 additions & 0 deletions dsl/test/claim/realization_reconcile_witness_test.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// dsl/test/claim/realization_reconcile_witness.dag — by-execution witnesses for
// std.realization reconcile → Share collapse (increment 3 materialization arm).
//
// GREEN: two same-KeySource CreateIfAbsent steps collapse to ONE Share.
// RED-if-wrong: two different-KeySource steps stay TWO un-Shared; PostAlways never collapses.
// The only difference between the GREEN and RED create cases is the InputField string,
// so a reconcile that collapsed on anything but KeySource equality (or fail-open) goes red.
// Run: gunbc run --source-root dsl --entry <this> --function reconcile_share_collapse_witnesses --claim-run

module test.claim.realization_reconcile_witness

import std.types { Bool, String, List }
import std.effects { CreateEffect, CreateIfAbsent, PostAlways, InputField }
import std.realization {
RealizedStep, LocalInProcess,
Materialization, Recompute, Memoize, Share,
reconcile,
}
import std.realization_schedule { cost_account_predicted_zero }

// Test-local Share discriminator. `is_share` is NOT in std.realization: reconcile sets
// `materialization: Share` directly and nothing in std/ reads it back, so a Materialization
// `is_*` predicate there would be an undispositioned std/ predicate (review #5168). The
// only consumer is this witness, so the match lives here (single owner, std/ stays fold-clean).
fn is_share(m: Materialization) -> Bool {
match m {
Share => true
Recompute => false
Memoize => false
}
}

fn step_create_if_absent(field: String) -> RealizedStep {
RealizedStep {
shape: CreateEffect { cause: CreateIfAbsent { key_source: InputField { field: field } } },
placement: LocalInProcess,
materialization: Recompute,
cost: cost_account_predicted_zero()
}
}

fn step_post_always() -> RealizedStep {
RealizedStep {
shape: CreateEffect { cause: PostAlways },
placement: LocalInProcess,
materialization: Recompute,
cost: cost_account_predicted_zero()
}
}

fn has_exactly_one_share(steps: List<RealizedStep>) -> Bool {
(steps |> filter(e => is_share(m: e.materialization)) |> length) == 1
}

fn has_no_share(steps: List<RealizedStep>) -> Bool {
(steps |> filter(e => is_share(m: e.materialization)) |> length) == 0
}

// GREEN (+): two same-KeySource create-if-absent steps collapse to ONE Share.
fn witness_same_keysource_collapses_to_share() -> Bool {
let out = reconcile(steps: [
step_create_if_absent(field: "id"),
step_create_if_absent(field: "id")
])
(out |> length) == 1 && has_exactly_one_share(steps: out)
}

// RED-if-wrong (−): two DIFFERENT-KeySource steps do NOT collapse (stay two un-Shared).
fn witness_different_keysource_does_not_collapse() -> Bool {
let out = reconcile(steps: [
step_create_if_absent(field: "id"),
step_create_if_absent(field: "other")
])
(out |> length) == 2 && has_no_share(steps: out)
}

// Fail-closed (−): PostAlways create-always never collapses (no proven identity).
fn witness_post_always_never_collapses() -> Bool {
let out = reconcile(steps: [ step_post_always(), step_post_always() ])
(out |> length) == 2 && has_no_share(steps: out)
}

test fn reconcile_share_collapse_witnesses() -> Bool {
witness_same_keysource_collapses_to_share()
&& witness_different_keysource_does_not_collapse()
&& witness_post_always_never_collapses()
}