Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ee1ab5f
Realize rust shell stderr capture so the fixture-closure union can em…
Oct 6, 2026
b3f513c
Refuse capture channels without a declared stderr_capture, and refuse…
Oct 6, 2026
acb64ad
Execute the emitted capture drain instead of grepping its source.
Oct 6, 2026
17103b4
Stop interpolating rust format names inside 05_emit_rust.dag strings.
Oct 6, 2026
5bd68be
Bind stderr capture before spawn and execute the remaining discrimina…
Oct 6, 2026
06f434a
Read Complete capture's ceiling from the host-budget join, not the en…
Oct 6, 2026
a2935a4
Drop the unapproved seed-growth row and unused capture helpers.
Oct 6, 2026
adedd46
Record the 2026-10-06 seed-growth ruling for rust stderr capture.
Oct 6, 2026
b5e75b9
Restore the host-budget join, including cgroup v1, for interpreter an…
Oct 6, 2026
82bc8b9
Move emit_shell_call capture notes above the declaration.
Oct 6, 2026
451906b
Compose the host budget only in v1_rt::resolve_host_budget_join.
Oct 6, 2026
03ca2f8
Name Complete overflow from the host-budget join, and read Darwin via…
Oct 6, 2026
c314ba2
Cite every emit_host capture item and type-check stderr_capture once.
Oct 6, 2026
d2a817c
Install the seed-emitted stage0 mirrors for the typed capture wall.
Oct 6, 2026
add0a2a
Merge origin/main so stage0 regen is against current main mirrors.
Oct 6, 2026
0638cf5
Close stage0 regen after merging main: emit the host-budget comment.
Oct 6, 2026
5084eb4
Identify stderr_capture by DeclarationRef, not last-segment name.
Oct 6, 2026
8584f64
Delegate host-budget cgroup observation through v1_rt.
Oct 6, 2026
c764d47
Drop the host-budget cgroup value adapter.
Oct 6, 2026
ea3ede1
Install stage0 mirrors for stderr-capture DeclarationRef and host-bud…
Oct 6, 2026
7ace852
Merge origin/main into session/bright-tern-639.
Oct 7, 2026
ab5dded
Install v1_rt.rs from required-regen after the main merge.
Oct 7, 2026
c87fad0
Restore #[test] placement after the main merge splice of emit_host.
Oct 7, 2026
e8154cb
Compose the #13466 gunbc-reach control with realized rust stderr capt…
Oct 7, 2026
4ccd0a5
Merge origin/main into session/bright-tern-639.
Oct 8, 2026
370ee5a
Re-derive the #13466 gap-population tests after rust realizes capture…
Oct 8, 2026
f8d9cfe
Record that Complete's host-budget ceiling is generated rust_runtime_…
Oct 8, 2026
5881f25
Retire the rust capture-gap drop now that the channels are realized.
Oct 8, 2026
5d9a72d
walk_cgroup, entry_presence: put the self-recursion in tail position …
Oct 9, 2026
77f9006
Merge #13472 (session/bright-tern-639) into integration/silent-lark-156
Oct 9, 2026
fd4421d
Merge remote-tracking branch 'origin/fix/tail-recursive-effect-walks'…
Oct 9, 2026
181dd1b
integration/silent-lark-156: regenerate generated artifacts after mer…
Oct 9, 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
4 changes: 2 additions & 2 deletions dag/gunbc/host/host_budget_source.dag
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,8 @@ fn kernel_budget_sourcing_static_source(g: KernelBudgetSourcing) -> HostBudgetSo
// may bound a refusal; it may not stand in for a reading.

// THE CGROUP-v1 ARM JOINS THIS SAME DECLARED MIRROR rather than opening a second one. The seed's
// memory_governor CgroupV1HierarchicalMemoryLimit arm, CgroupV1MemoryLimitValue,
// cgroup_v1_hierarchical_limit_from_stat and cgroup_v1_unlimited_bytes hand-realize
// v1_rt HostBudgetCgroupV1 arm, host_budget_cgroup_v1_from_stat and
// host_budget_cgroup_v1_unlimited_bytes hand-realize
// BudgetSourceCgroupV1HierarchicalMemoryLimit here and extdeps.linux.cgroup_v1_memory's parse, under
// the bootstrap constraint stated in the note below: the budget bounds the resolve, so it is read
// before any .dag value exists. The mirror keeps the model's three states (limited / unlimited /
Expand Down
19 changes: 13 additions & 6 deletions dag/gunbc/live_deploy/member_observe.dag
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module gunbc.live_deploy.member_observe

import std.types { String, Bool, List, Int, NonEmptyStr, CommitSha, FilePath }
import std.optional { Optional, Present, Absent }
import std.algebra { trim }
import std.content_hash { content_hash_atom }
import extdeps.crypto.hash { Digest, sha256sum_argv, sha256sum_line_digest }
Expand Down Expand Up @@ -159,20 +160,26 @@ fn entry_presence_in_parent(arm: ObservationArm, parent: String, name: String) -
}

fn entry_presence(arm: ObservationArm, path: String) -> EntryPresence {
entry_presence_above(arm: arm, path: path, below: Absent)
}

// The ancestor walk in tail position, so the Rust realization lowers it to a loop. `below` is the
// cause read one level down: an ancestor that is present answers with that cause, an absent one
// answers absent, and the root answers with its own cause -- the same answers the nested walk gave.
fn entry_presence_above(arm: ObservationArm, path: String, below: Optional<String>) -> EntryPresence {
let parent = path_parent(path: path)
let name = path_basename(path: path)
match entry_presence_in_parent(arm: arm, parent: parent, name: name) {
EntryPresent => EntryPresent
EntryPresent => match below {
Absent => EntryPresent
Present { value: cause } => EntryPresenceIndeterminate { cause: cause }
}
EntryAbsent => EntryAbsent
EntryPresenceIndeterminate { cause } =>
if parent == "/" {
EntryPresenceIndeterminate { cause: cause }
} else {
match entry_presence(arm: arm, path: parent) {
EntryAbsent => EntryAbsent
EntryPresent => EntryPresenceIndeterminate { cause: cause }
EntryPresenceIndeterminate { cause: ancestor_cause } => EntryPresenceIndeterminate { cause: ancestor_cause }
}
entry_presence_above(arm: arm, path: parent, below: Present { value: cause })
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,14 @@
module gunbc.rung_drop.fixture_closure_union_unmodeled_stderr_capture

import std.types { NonEmptyStr }
import gunbc.rung_drop { RungDrop, Standing, TypedDeclaration, ReplacementStaged }
import gunbc.rung_drop { RungDrop, Retired, TypedDeclaration, ReplacementStaged }
import gunbc.guarantee_rung { Mitigatable, MechanicallyPreventable }
import gunbc.stderr_capture_gap_exclusion { exclusion, StderrCaptureGapExclusion }

// THE FIXTURE-CLOSURE UNION RENDERS EVERY RECORDED MEMBER THROUGH THE RUST EMITTER. After
// #13437 the walker closes by reference, so a fixture that reaches extdeps.gunbc compiles
// gunbc.WitnessBin.Run into the union. That operation declares stderr_truncated /
// stderr_total_bytes / stderr_retained_bytes, which v1.compiler.emit shell_channel_realized_by_target
// refuses for rust: the emitted Command body implements no WitnessStderrCapturePolicy.
// emit_artifact then returns no files for the WHOLE union, so those three diagnostics abort
// every other member's render and refuse unrelated floors (specimen: #13420).
//
// THE EARLIEST UNJUSTIFIED BOUNDARY IS THE UNION, NOT THE WALL. The wall is the honest
// capability gap (05_emit names the next-rung trigger: the emitted realization implementing
// the declared policy). std.shell_stream_capture still homes the policy on the interpreter
// drain until that trigger fires. Binding a fabricating rust handler (truncated=false) is the
// fail-open 05_emit already refuses. So the union must not render the unmodeled operation:
// a typed exclusion keyed on that diagnostic fact, never a silent skip, and a real emit error
// in a member the union still renders still refuses.

fn capture_gap_exclusion_population() -> StderrCaptureGapExclusion {
exclusion
}

// RETIRED — TRIGGER FIRED. gunbc#13472 realized rust shell WitnessStderrCapturePolicy
// (v1.compiler.emit shell_channel_realized_by_target is true for the three capture-
// accounting channels). The union no longer strips WitnessBin.Run. Discriminating
// controls stay enrolled: fixture_closure_union_controls gunbc-reach emit, plus
// emit_host realization tests (DESIGN §4b(4)).

data fixture_closure_union_unmodeled_stderr_capture: RungDrop = RungDrop {
identity: "fixture_closure_union_unmodeled_stderr_capture" as NonEmptyStr,
Expand All @@ -32,7 +17,9 @@ data fixture_closure_union_unmodeled_stderr_capture: RungDrop = RungDrop {

declared: "2026-10-06",

standing: Standing,
standing: Retired {
trigger_fired: "2026-10-08 -- gunbc#13472. THE CAPABILITY, EXECUTED: v1.compiler.emit shell_channel_realized_by_target returns true for ShellChanStderrTruncated, ShellChanStderrTotalBytes and ShellChanStderrRetainedBytes on rust because emit_shell_call implements the declared WitnessStderrCapturePolicy. WitnessBin.Run emits without TransportEmissionNotModeled; the union strip of that service is deleted; this exclusion population is empty. DISCRIMINATING CONTROL, ENROLLED: v1_compiler.cli_run fixture_closure_union_controls admits a fixture whose closure reaches extdeps.gunbc, and a real emit error beside that reach still refuses as FixtureClosureUnionEmitRefused at module=efr_member. Answering the channels as untruncated whole-stream lengths did not discharge this. Deleting the channels from the interface did not discharge this." as NonEmptyStr
},

declaration: TypedDeclaration {
previous: MechanicallyPreventable,
Expand All @@ -41,9 +28,7 @@ data fixture_closure_union_unmodeled_stderr_capture: RungDrop = RungDrop {

reason: ReplacementStaged { replacement: "the rust emitted realization implementing the declared WitnessStderrCapturePolicy, the same next-rung trigger v1.compiler.emit shell_channel_realized_by_target already names" },

population: [
"exactly gunbc.stderr_capture_gap_exclusion.exclusion (consumed here as capture_gap_exclusion_population): gunbc.WitnessBin.Run in extdeps.gunbc. Output channels stderr_truncated, stderr_total_bytes, stderr_retained_bytes, each a TransportEmissionNotModeled ShellChannelNotRealizedByTarget for target rust. A later shell operation with the same capture-gap fact is NOT a member: the union still renders it and still refuses. The union compiles and evaluates that record; deleting either this module or the carrier refuses the seed compile",
],
population: [],

restoration_trigger: "THE CAPABILITY: the rust emitted shell realization implements the operation's declared WitnessStderrCapturePolicy, sufficient for v1.compiler.emit shell_channel_realized_by_target to return true for ShellChanStderrTruncated, ShellChanStderrTotalBytes and ShellChanStderrRetainedBytes. WHAT THAT MUST BE SUFFICIENT FOR: those operations emit for rust without TransportEmissionNotModeled, this exclusion has an empty population and this row and the union's strip of those services delete together. Answering the channels as untruncated whole-stream lengths does NOT discharge it. Deleting the channels from the interface does NOT discharge it. Silently omitting the module from the union without naming this cause does NOT discharge it.",
}
Expand Down
34 changes: 23 additions & 11 deletions dag/gunbc/runner/runner_microvm_lifecycle_realize.dag
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import gunbc.runner_microvm_network_observe { observe_slot_network_readings }
import extdeps.virtualization.firecracker { FirecrackerVmConfig, firecracker_vm_config_document }

import std.types { String, NonEmptyStr, Bool, List, Int }
import std.optional { Present, Absent }
import std.nat { Nat }
import std.checked_arithmetic { checked_int_magnitude, CheckedNatReady, CheckedNatOverflow }
import extdeps.clock { clock_unix_millis_read, epoch_secs_of_millis, ClockUnixMillisObserved, ClockUnixMillisRefused }
Expand Down Expand Up @@ -162,6 +163,8 @@ type CgroupWalkNode { path: NonEmptyStr, pids: List<Int> }

type CgroupWalk { nodes: List<CgroupWalkNode> }

type CgroupWalkPending { path: NonEmptyStr, depth: Int }

fn cgroup_procs_path(cgroup_path: NonEmptyStr) -> NonEmptyStr {
cgroup_v2_child_path(parent: cgroup_path, child: cgroup_v2_procs_interface_file)
}
Expand Down Expand Up @@ -192,17 +195,26 @@ fn cgroup_child_names(cgroup_path: NonEmptyStr) -> List<String>

fn walk_cgroup(cgroup_path: NonEmptyStr, depth: Int) -> CgroupWalk
{
let here = CgroupWalkNode { path: cgroup_path, pids: cgroup_procs_pids(cgroup_path: cgroup_path) }
if depth <= 0 {
CgroupWalk { nodes: [here] }
} else {
fold(cgroup_child_names(cgroup_path: cgroup_path), init: CgroupWalk { nodes: [here] }, f: (acc, name) =>
CgroupWalk {
nodes: concat(
acc.nodes,
walk_cgroup(cgroup_path: cgroup_v2_child_path(parent: cgroup_path, child: trim(s: name) as NonEmptyStr), depth: depth - 1).nodes,
),
})
walk_cgroup_pending(pending: [CgroupWalkPending { path: cgroup_path, depth: depth }], nodes: [])
}

// The subtree walk in tail position, so the Rust realization lowers it to a loop. The pending
// list is the unvisited frontier in preorder: a node's children go ahead of its later siblings,
// so nodes come out in the order the nested walk produced, and each cgroup is read the same way.
fn walk_cgroup_pending(pending: List<CgroupWalkPending>, nodes: List<CgroupWalkNode>) -> CgroupWalk
{
match pending.first() {
Absent => CgroupWalk { nodes: nodes }
Present { value: next } => {
let here = CgroupWalkNode { path: next.path, pids: cgroup_procs_pids(cgroup_path: next.path) }
let children = if next.depth <= 0 {
[]
} else {
map(cgroup_child_names(cgroup_path: next.path), name =>
CgroupWalkPending { path: cgroup_v2_child_path(parent: next.path, child: trim(s: name) as NonEmptyStr), depth: next.depth - 1 })
}
walk_cgroup_pending(pending: concat(children, pending.skip(n: 1)), nodes: concat(nodes, [here]))
}
}
}

Expand Down
71 changes: 71 additions & 0 deletions dag/gunbc/rust_shell_stderr_capture_seed_growth.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
module gunbc.rust_shell_stderr_capture_seed_growth

import gunbc.roadmap_model { RoadmapNodeId }
import gunbc.seed_growth { SeedGrowthJustification }
import std.decl_ref { DeclarationRef, WholeDeclaration }

// Seed-growth obligation for rust shell stderr capture (#13472), homed beside the
// obligation it declares rather than inside gunbc.seed_growth_admission, which owns
// the roster and the join.
//
// THE AUTHORIZER. Operator ruling 2026-10-06 (escalation msg_7853a1af, via
// silent-lark-156): "Admit, exact scope with seed-growth row". The admitted
// SeedFeatureCompletion is scoped to the rust shell handler realizing
// WitnessStderrCapturePolicy (stderr_truncated / stderr_total_bytes /
// stderr_retained_bytes) and the emit_host.rs tests that compile and run that
// fragment. This row records that ruling; it does not mint a second one.
//
// PURPOSE PASSES (gunbc.v1_maintenance_standing v1_seed_standing): the fixture-closure
// union must emit extdeps.gunbc WitnessBin.Run or the required floor stays red after
// #13437, which blocks the D2 self-host lane. The seed is the only rust shell emitter.
//
// THE FIVE REFUSED CLASSES. NewLanguageBehavior: no. NewCompatibilityObligation: no.
// NewEscapeHatchOrAdmissionRow: no — absent policy and Complete overflow refuse.
// SeedFeatureCompletion FIRES and is admitted on the ruling above. PublicSurfaceGrowth:
// the emit_host additions are cfg(test) discriminators, not a published CLI.
//
// Hand items below are the emit_host executing harness. The rust-item authority keeps
// the inline-module path, so every citation is
// v1_compiler.cli_run.emit_host.fixture_closure_union_tests.
//
// THE COMPLETE CEILING IS NOT A SECOND HAND MODULE (review 77633). Complete overflow
// reads v1_rt::read_host_budget_bytes / resolve_host_budget_join. Those functions
// live in rust_runtime_source (runtime_rust.dag rt_host_budget) because an emitted
// crate has no memory_governor. The stage0 v1_rt.rs mirror is generated
// (gunbc.generated_artifact / derived_generated_stage0_repo_paths), so it is not a
// SeedGrowthJustification hand item and must not be listed here. memory_governor
// wraps the same join; this change deletes the second composer rather than adding
// one. The 2026-10-06 ruling's handler scope includes that ceiling: current_boundary
// already names WitnessStderrCaptureCompleteBudgetExceeded with the admitted limit.
data rust_shell_stderr_capture_seed_growth_justification: SeedGrowthJustification = SeedGrowthJustification {
hand_authored_declarations: [
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "STDERR_CAPTURE_MEMBER", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "STDERR_CAPTURE_UNMODELED_SIBLING", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "STDERR_CAPTURE_WITHOUT_POLICY", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "STDERR_CAPTURE_STRING_POLICY", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "STDERR_CAPTURE_OPTIONAL_POLICY", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "STDERR_CAPTURE_COLLECTION_POLICY", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "STDERR_CAPTURE_HOMONYM_POLICY", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "GUNBC_MODULE_REACH_MEMBER", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "declared_stderr_capture_channels_do_not_refuse_the_union", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "an_unmodeled_shell_channel_still_refuses_the_union", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "capture_channels_without_stderr_capture_input_refuse_the_union", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "capture_channels_refuse_unless_stderr_capture_is_the_required_scalar_policy", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "capture_channels_with_string_stderr_capture_refuse_the_union", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "capture_channels_with_optional_stderr_capture_refuse_the_union", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "capture_channels_with_collection_stderr_capture_refuse_the_union", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "capture_channels_with_homonym_stderr_capture_refuse_the_union", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "reaching_extdeps_gunbc_does_not_refuse_the_union_for_capture_channels", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "rustc_and_run_emitted_capture", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "emitted_bounded_tail_truncates_and_keeps_the_tail", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "emitted_bounded_tail_under_cap_is_complete", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "emitted_complete_over_budget_refuses", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "emitted_complete_under_budget_retains_all", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "emitted_stdin_and_long_stderr_does_not_deadlock", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.cli_run.emit_host.fixture_closure_union_tests", decl_name: "emitted_absent_policy_refuses_before_spawn", field: WholeDeclaration }
],
reason: "Operator ruling 2026-10-06 (msg_7853a1af): admit SeedFeatureCompletion, exact scope the rust shell handler realizing WitnessStderrCapturePolicy (stderr_truncated / stderr_total_bytes / stderr_retained_bytes) and its emit_host.rs tests. The rust shell handler must realize those channels so the fixture-closure union can emit WitnessBin.Run. Complete's admitted limit is the existing host-budget join on rust_runtime_source (v1_rt::read_host_budget_bytes), not a new seed-retained module and not a second composer in memory_governor. These host tests compile and run the emitted drain against a child process, and they refuse a name-only, String, optional, or collection stderr_capture at TransportEmissionNotModeled. A .contains() on the drain string is not a consumer (DESIGN section 5). They stay rust because the subject is the rust realization fragment the seed emits.",
owning_dissolution_lane: "v1-hand-queue-drain" as RoadmapNodeId,
trigger: "Delete these items when the v2-native emitter realizes the shell transport's stderr capture, a .dag witness compiles the emitted rust crate and runs the same six discriminators plus the typed-policy emit refusals without a host rustc harness, and WitnessBin.Run still emits. The union digest_hex control stays.",
current_boundary: "Bind and validate a required scalar stderr_capture: WitnessStderrCapturePolicy before spawn; start stdout and stderr drains immediately; write stdin concurrently; wait and join; project BoundedTail or return WitnessStderrCaptureCompleteBudgetExceeded with the measured total and the admitted limit from v1_rt::read_host_budget_bytes (rust_runtime_source / runtime_rust.dag rt_host_budget; memory_governor wraps the same join). No fallback tail length. Capture-accounting channels without that typed required scalar refuse at the rust emit diagnostic (one shared predicate) and, if that wall is skipped, as a pre-spawn return Err. Python and go still refuse those channels at emit. Unmodeled keys such as stderr_digest_hex still refuse."
}
Loading
Loading