Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
ee58357
WIP: MAIN RED #4: eight runner-slot/fleet-capacity witnesses return B…
Aug 23, 2026
9306822
Merge remote-tracking branch 'origin/main' into wk9020
Aug 23, 2026
1dad471
Fix record-like if condition brace parsing
Aug 23, 2026
0d15443
Merge remote-tracking branch 'origin/main' into session/swift-heron-558
Aug 23, 2026
f043553
Unenrol the seventeen rows this fix made pass, and keep the four besi…
Aug 23, 2026
556857a
Convert the one ArgvCommand site the seal missed, through a builder r…
Aug 23, 2026
348e012
Merge remote-tracking branch 'origin/pr-9031' into session/swift-hero…
Aug 23, 2026
830cd93
Handle record-like conditions on operator RHS
Aug 23, 2026
057f9c7
An enrolled identity that cannot execute is what reds main, not what …
Aug 23, 2026
63409bf
Enrolled-but-never-planned is not a parking spot: it refuses the whol…
Aug 23, 2026
7981ec6
Merge remote-tracking branch 'origin/pr-9037' into session/swift-hero…
Aug 23, 2026
704c2a8
The srv4 activation witness re-spelled two programs the seal then moved
Aug 23, 2026
b19795e
Merge remote-tracking branch 'origin/fix/argv-command-ls-seal' into f…
Aug 23, 2026
09d96bb
Repin the srv4 enable witness on the grounded sudo spelling, and stop…
Aug 23, 2026
fedaca4
Merge remote-tracking branch 'origin/pr-9020' into session/swift-hero…
Aug 23, 2026
0279359
Remove trailing whitespace from expected-red roster
Aug 23, 2026
a47aded
join is not a std.types export: the two derived patterns build with c…
Aug 23, 2026
70b96fa
Drop the enable-conjunct change: #9031 owns that row, and the derivat…
Aug 23, 2026
1cd8a6b
Revert "Remove trailing whitespace from expected-red roster"
Aug 23, 2026
6df07e0
Revert "Merge remote-tracking branch 'origin/pr-9020' into session/sw…
Aug 23, 2026
537a88e
Merge remote-tracking branch 'origin/pr-9031-latest' into session/swi…
Aug 23, 2026
7bc717b
Merge remote-tracking branch 'origin/pr-9038' into session/swift-hero…
Aug 23, 2026
e0ba6da
Name the no-brace parser retry debt
Aug 23, 2026
28e6a7f
Reconcile expected-red liveness authority
Aug 23, 2026
fee6b9f
The 57s qualified-spelling claim is a whole-tree policy resolve, not …
Aug 23, 2026
4aff5e6
Scope the compile-clean policy read to its own import closure, refusi…
Aug 23, 2026
894485c
Merge remote-tracking branch 'origin/main' into session/swift-heron-558
Aug 23, 2026
1e2de9b
Merge remote-tracking branch 'origin/pr-9044' into session/swift-hero…
Aug 23, 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 dag/gunbc/ci_spec.dag

Large diffs are not rendered by default.

16 changes: 9 additions & 7 deletions dag/test/claim/runner_host_deploy_witness_test.dag
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,16 @@ test fn srv4_runner_installer_command_cites_installer_with_env() -> Bool {
installer_path: "/tmp/install-actions-runner.sh",
pem_src_path: "/tmp/app.pem",
)
let c = match outcome {
RunnerCommandReady { command: cmd } => shell_command_render(command: cmd)
RunnerCommandRefused { host_label: _, reason: _ } => ""
match outcome {
RunnerCommandRefused { host_label: _, reason: _ } => false
RunnerCommandReady { command: cmd } => {
let c = shell_command_render(command: cmd)
string_contains(s: c, pattern: "'CTRL_RUNNER_HOST_LABEL=srv4'")
&& string_contains(s: c, pattern: "'CTRL_RUNNER_JOB_USER=ghrunner'")
&& string_contains(s: c, pattern: "'CTRL_RUNNER_APP_PEM_SRC=/tmp/app.pem'")
&& string_contains(s: c, pattern: "'/usr/bin/sudo' '-E' 'bash' '/tmp/install-actions-runner.sh'")
}
}
string_contains(s: c, pattern: "'CTRL_RUNNER_HOST_LABEL=srv4'")
&& string_contains(s: c, pattern: "'CTRL_RUNNER_JOB_USER=ghrunner'")
&& string_contains(s: c, pattern: "'CTRL_RUNNER_APP_PEM_SRC=/tmp/app.pem'")
&& string_contains(s: c, pattern: "'/usr/bin/sudo' '-E' 'bash' '/tmp/install-actions-runner.sh'")
}

test fn srv4_runner_app_from_secret_manager() -> Bool {
Expand Down
304 changes: 304 additions & 0 deletions docs/probes/qualified_name_resolution_cost_2026-08-23.md

Large diffs are not rendered by default.

23 changes: 21 additions & 2 deletions src/v1/02_parse.dag
Original file line number Diff line number Diff line change
Expand Up @@ -4571,11 +4571,30 @@ fn parse_expr_no_brace(tokens: TokenStream, ctx: ParseContext) -> ExprResult {
parse_expr_bp_no_brace(tokens: tokens, ctx: ctx, min_bp: 0)
}

// This retries when parse_prefix consumes the brace that the surrounding if/match owns.
// Simply forbidding record literals in this path would reject valid conditions:
// `if x == Present { value: y } { ... }` has a legitimate record literal and a distinct branch
// brace. The retry distinguishes the swallowed-branch case while preserving that condition.
fn parse_expr_bp_no_brace(tokens: TokenStream, ctx: ParseContext, min_bp: Int) -> ExprResult {
let tok = token_stream_first(stream: tokens)
let next = token_stream_first(stream: token_stream_advance(stream: tokens, n: 1))
let r = parse_prefix(tokens: tokens, ctx: ctx)
if has_err(err: r.err) { return r }
let lhs = r.expr
parse_expr_loop_no_brace(tokens: r.tokens, ctx: r.ctx, lhs: lhs, min_bp: min_bp)
let parsed = parse_expr_loop_no_brace(tokens: r.tokens, ctx: r.ctx, lhs: r.expr, min_bp: min_bp)
let leading_ident_brace = match tok { Present { value: t } => is_ident_shape(shape: t.shape) Absent => false } && tok_is_lbrace(tok: next)
let stopped_at_infix = match infix_bp(tokens: parsed.tokens) { Present { value: _ } => true Absent => false }
if leading_ident_brace && !has_err(err: parsed.err) && !tok_is_lbrace(tok: token_stream_first(stream: parsed.tokens)) && !stopped_at_infix {
let span = token_span(tok: tok)
let lhs = make_named_expr_node(name: tok.value.text, expr_data: ExprVar { binding_kind: none }, children: [], inferred: none, span: span, name_span: span)
parse_expr_loop_no_brace(
tokens: token_stream_advance(stream: tokens, n: 1),
ctx: ctx,
lhs: lhs,
min_bp: min_bp
)
} else {
parsed
}
}

fn parse_expr_loop_no_brace(tokens: TokenStream, ctx: ParseContext, lhs: Node, min_bp: Int) -> ExprResult {
Expand Down
29 changes: 29 additions & 0 deletions src/v1/stage0/src/bin/parse_witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,27 @@ fn parser_e2e() {
assert_eq!(module.name, "test");
}

fn uppercase_condition_does_not_consume_then_branch_as_record_literal() {
let source = "module test\nfn choose(flag: Bool) -> Int {\n if Present { 1 } else { 2 }\n}";
let result = parse_source(source);
assert!(
result.error.is_none(),
"uppercase condition should leave the following brace for the then-branch: {:?}",
result.error
);
}

fn uppercase_rhs_condition_does_not_consume_then_branch_as_record_literal() {
let source =
"module test\nfn choose(flag: Bool) -> Int {\n if flag == Present { 1 } else { 2 }\n}";
let result = parse_source(source);
assert!(
result.error.is_none(),
"uppercase condition RHS should leave the following brace for the then-branch: {:?}",
result.error
);
}

fn parse_real_source() {
let source =
"module test\ntype Foo { x: Int }\ntype Bar = Foo\nfn identity(x: Int) -> Int { x }";
Expand Down Expand Up @@ -989,6 +1010,14 @@ fn floor_suite() -> Vec<WitnessCase> {
tokenize_produces_correct_kinds,
),
("parser_e2e", parser_e2e),
(
"uppercase_condition_does_not_consume_then_branch_as_record_literal",
uppercase_condition_does_not_consume_then_branch_as_record_literal,
),
(
"uppercase_rhs_condition_does_not_consume_then_branch_as_record_literal",
uppercase_rhs_condition_does_not_consume_then_branch_as_record_literal,
),
("parse_real_source", parse_real_source),
("parse_fold_with_fn_lambda", parse_fold_with_fn_lambda),
("parse_fn_lambda_in_call_arg", parse_fn_lambda_in_call_arg),
Expand Down
75 changes: 74 additions & 1 deletion src/v1/stage0/src/cli_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3079,11 +3079,84 @@ const COMPILE_CLEAN_DIAGNOSTIC_POLICY_ENTRY: &str = "dag/gunbc/compile_clean_dia
/// Whether `UnlistedImportUse` blocks compile-clean per the single policy row
/// (`compile_clean_unlisted_import_use_enforcement` in `gunbc.compile_clean_diagnostic_policy`).
/// Both the floor receipt path and the CLI transport must read this — never restate the predicate.
/// The policy entry's OWN import closure, as an explicit source set.
///
/// Why this exists rather than a whole-tree resolve: reading one nullary `Bool` used to cost a
/// full resolve+typecheck over `default_source_roots()` — the whole tree — which is both
/// enormously oversized (the policy module has three imports) and, more seriously, a function
/// answering a question about the CALLER's world by consulting a DIFFERENT one. Measured, same
/// probe, only the caller's roots varied: 216ms when the caller's roots happened to match the
/// whole-tree key, 44886ms when they did not and the resolve paid a cold whole-tree load
/// (`docs/probes/qualified_name_resolution_cost_2026-08-23.md`).
///
/// FAIL-CLOSED BY CONSTRUCTION (DESIGN §5): every arm that cannot produce the exact closure
/// REFUSES with a typed, located message naming the module and the file. It must never fall back
/// to the whole tree — that arm would restore today's cost, zero the deficit's frequency by
/// construction, and make the widening unrankable ever after. Note the contrast with
/// `resolve_virtual_source_with_imports`, whose BFS silently SKIPS an import it cannot resolve;
/// a silent skip here would narrow the policy closure and answer from a graph missing the very
/// module the answer depends on.
fn compile_clean_policy_entry_closure_sources(
roots: &[String],
entry_rel: &str,
) -> Result<Vec<Rc<v1_compiler_compile::SourceFile>>, String> {
let ws = process_workspace_root();
let module_index = build_module_path_index(roots);
let read = |rel: &str| -> Result<String, String> {
let abs = ws.join(rel);
std::fs::read_to_string(&abs).map_err(|e| {
format!(
"compile_clean_diagnostic_policy closure: cannot read `{}` ({e})",
abs.display()
)
})
};

let entry_content = read(entry_rel)?;
let mut seen: HashMap<String, Rc<v1_compiler_compile::SourceFile>> = HashMap::new();
let mut queue: Vec<String> = vec![entry_content.clone()];
while let Some(content) = queue.pop() {
for module_path in extract_import_paths(&content) {
let Some(rel_path) = module_index.get(&module_path) else {
return Err(format!(
"compile_clean_diagnostic_policy closure: import `{module_path}` \
(reached from `{entry_rel}`) names no module in the source roots"
));
};
// `entry_rel` may be absolute (an entry argument typically is) while the module
// index stores workspace-relative keys, so compare canonically — a string compare
// would miss and admit the entry twice under two spellings.
if same_canonical_file(rel_path, entry_rel) || seen.contains_key(rel_path) {
continue;
}
let file_content = read(rel_path)?;
seen.insert(
rel_path.clone(),
Rc::new(v1_compiler_compile::SourceFile {
path: rel_path.clone(),
content: file_content.clone(),
}),
);
queue.push(file_content);
}
}

let mut sources: Vec<Rc<v1_compiler_compile::SourceFile>> =
seen.into_iter().map(|(_, v)| v).collect();
sources.sort_by(|a, b| a.path.cmp(&b.path));
sources.push(Rc::new(v1_compiler_compile::SourceFile {
path: entry_rel.to_string(),
content: entry_content,
}));
Ok(sources)
}

pub fn compile_clean_unlisted_import_use_blocks_from_policy() -> Result<bool, String> {
let roots = default_source_roots();
let entry = resolve_entry_file_under_roots(&roots, COMPILE_CLEAN_DIAGNOSTIC_POLICY_ENTRY)
.map_err(|e| format!("compile_clean_diagnostic_policy resolve: {e}"))?;
let (graph, indices) = resolve_entry_graph_shared(&roots, &entry)
let sources = compile_clean_policy_entry_closure_sources(&roots, &entry)?;
let (graph, indices) = resolved_graph_from_sources(sources, ResolveTypecheckGate::Strict)
.map_err(|e| format!("compile_clean_diagnostic_policy resolve: {e}"))?;
let ctx = make_eval_context(&graph, indices, v1_interpreter::ExecutionMode::Hermetic);
match v1_interpreter::run_in_context_with_args(
Expand Down
42 changes: 40 additions & 2 deletions src/v1/stage0/src/v1_compiler_parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12857,12 +12857,50 @@ pub fn parse_expr_bp_no_brace(
min_bp: i64,
) -> Rc<ExprResult> {
{
let tok = token_stream_first(tokens.clone());
let next = token_stream_first(token_stream_advance(tokens.clone(), 1));
let r = parse_prefix(tokens.clone(), ctx.clone());
if has_err(r.err.clone()) {
return r;
}
let lhs = r.expr.clone();
parse_expr_loop_no_brace(r.tokens.clone(), r.ctx.clone(), lhs.clone(), min_bp.clone())
let parsed = parse_expr_loop_no_brace(
r.tokens.clone(),
r.ctx.clone(),
r.expr.clone(),
min_bp.clone(),
);
let leading_ident_brace = (match tok.clone() {
Some(t) => is_ident_shape(t.shape.clone()),
None => false,
} && tok_is_lbrace(next.clone()));
let stopped_at_infix = match infix_bp(parsed.tokens.clone()) {
Some(_) => true,
None => false,
};
if (((leading_ident_brace.clone() && !has_err(parsed.err.clone()))
&& !tok_is_lbrace(token_stream_first(parsed.tokens.clone())))
&& !stopped_at_infix.clone())
{
{
let span = token_span(tok.clone());
let lhs = make_named_expr_node(
tok.clone().unwrap().text.clone(),
Rc::new(ExprData::ExprVar { binding_kind: None }),
Rc::new(vec![]),
None,
span.clone(),
span.clone(),
);
parse_expr_loop_no_brace(
token_stream_advance(tokens.clone(), 1),
ctx.clone(),
lhs.clone(),
min_bp.clone(),
)
}
} else {
parsed
}
}
}

Expand Down
22 changes: 7 additions & 15 deletions src/v2/workflow/floor_expected_red.dag
Original file line number Diff line number Diff line change
Expand Up @@ -486,10 +486,10 @@ fn floor_expected_red_chunk_20() -> List<String> {
// is the whole point of authoring them as reds instead of as assertions of today's behaviour, which
// would have been a change detector pointing the wrong way.
//
// THE FILE DECLARES ReadsLiveTree and is therefore DeclinedLiveTree today, so these three are
// enrolled and not yet planned. That is stated rather than worked around: the declaration is honest
// (compile_dag_rust_emit_check walks the live tree) and the decline arm's deletion is in flight
// (gunbc#8977, gunbc#8982). Until it lands they are held here so that admission does not red main.
// THE THREE ROWS STAY ENROLLED HERE AS THE AUTHORED REDS THEY ARE. Their home currently declares
// ReadsLiveTree and is declined before execution, so floor_expected_red_is_live excludes them from
// the live roster until that decline is removed. Keeping identity and temporary liveness separate
// preserves the enrolment and gives the coupling below one mechanism rather than two accounts.
//
// The partition of the 164 and the measurements behind this family are
// docs/plans/receipts/floor-runtime-error-partition-2026-08-23/.
Expand All @@ -506,19 +506,11 @@ fn floor_expected_red_chunks() -> List<List<String>> {
// but exclude the now-green family from the live expected-red roster.
//
// THE THREE compile_accepted_unevaluable_program_control ROWS ARE EXCLUDED FOR THE OPPOSITE
// REASON, AND CHUNK 21 SAYS SO IN A SENTENCE EXECUTION REFUTES. That chunk's annotation reads
// "until it lands they are held here so that admission does not red main". Held-in-the-roster is
// exactly what reds main: the floor requires every ENROLLED identity to be observed among the
// EXECUTED claims, so an identity that is enrolled and never planned refuses the whole run with
// cause=ExpectedRedIdentityDidNotExecute. It is not a quiet parking spot. Measured twice, on the
// authoring PR's own run (32644795043, which was merged red) and again on gunbc#9031
// (32649496046), where it was the sole floor refusal once the ArgvCommand seal that had been
// masking it was repaired.
//
// The rows are correct and stay in chunk 21. What is wrong is only their LIVENESS: the file
// REASON. They remain the authored-red identities in chunk 21; only their LIVENESS is false. The file
// declares ReadsLiveTree, the DeclinedLiveTree arm declines it (declined_live=899 on that run),
// and the arm's deletion is still unmerged (gunbc#8977, gunbc#8982 both OPEN at the time of
// writing) -- so the enrolment was authored against a precondition that had not landed.
// writing). A declined identity is never executed, while live expected-red enrolment requires an
// observed failure, so the filter keeps the identity and temporary execution standing distinct.
//
// RESTORATION TRIGGER, and it is a COUPLING someone must honour rather than a note: when either
// #8977 or #8982 lands and these identities become executable, DELETE these three exclusions in
Expand Down
Loading