Skip to content
Merged
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
e616790
WIP: Fix inert_lens witness-builtin scope errors in bare compile
Jul 5, 2026
3150045
Ground inert_lens witness builtins on substrate bridge stubs.
Jul 5, 2026
c33f772
Mark inert_lens bridge stubs with typed scaffold note.
Jul 5, 2026
ecaf2c2
Split CI build from floor step to fix step-timeout kill.
Jul 5, 2026
087ba3e
WIP: Fix inert_lens witness-builtin scope errors in bare compile
Jul 5, 2026
2570d4a
Give floor gate step 30m budget; dag_compile_clean exceeds 10m.
Jul 5, 2026
72bf3d9
Regenerate ci.yml: floor gate step 30m, job backstop 50m.
Jul 5, 2026
caa8cda
WIP: Fix inert_lens witness-builtin scope errors in bare compile
Jul 5, 2026
3be353b
Give release-build step 15m budget; cold compile exceeds 10m.
Jul 5, 2026
1c6ff4f
Raise release-build step budget to 30m; stage0 still compiling at 15m.
Jul 5, 2026
2e624db
Raise rust-gate step budget to 30m; cold build exceeded 15m.
Jul 5, 2026
5522b21
Deduplicate gunbc_ci_floor_run to delegate floor_only_script.
Jul 5, 2026
377834e
WIP: Fix inert_lens witness-builtin scope errors in bare compile
Jul 5, 2026
7ab5208
Fix starts_with builtin borrow and ground bare-compile resolver gaps.
Jul 5, 2026
9147456
Merge remote-tracking branch 'origin/main' into session/calm-otter-699
Jul 5, 2026
6ea42e0
WIP: Fix inert_lens witness-builtin scope errors in bare compile
Jul 5, 2026
d76a7a0
WIP: Fix inert_lens witness-builtin scope errors in bare compile
Jul 5, 2026
b96566a
WIP: Fix inert_lens witness-builtin scope errors in bare compile
Jul 5, 2026
835fc27
WIP: Fix inert_lens witness-builtin scope errors in bare compile
Jul 5, 2026
b452371
WIP: Fix inert_lens witness-builtin scope errors in bare compile
Jul 5, 2026
5c1131b
Fix lookup_ancestry_parameterized_decl return type for bare compile.
Jul 5, 2026
dc05863
Raise floor gate step budget to 45m after src/v1 compile pool.
Jul 5, 2026
abd03b9
Raise floor gate step budget to 60m; batch-1 compile needs ~43m.
Jul 5, 2026
b9fe0c0
Raise floor gate step budget to 90m; src/v1 compile pool ~78m.
Jul 5, 2026
f2d66cd
Merge remote-tracking branch 'origin/main' into session/calm-otter-699
Jul 5, 2026
1ba1895
WIP: Fix inert_lens witness-builtin scope errors in bare compile
Jul 5, 2026
dfbff0f
ci: raise release-build and rust-gate step budgets after main merge
Jul 5, 2026
10c5316
ci: split rust_tests build from rust gate step
Jul 5, 2026
4f144a0
WIP: Fix inert_lens witness-builtin scope errors in bare compile
Jul 5, 2026
f2aa0ab
Merge remote-tracking branch 'origin/main' into session/calm-otter-699
Jul 5, 2026
b4ff1a6
ci: raise rust-gate-only step budget to 45m after merge
Jul 5, 2026
373e895
Merge origin/main into session/calm-otter-699
Jul 5, 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
14 changes: 9 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ env:
jobs:
ci:
runs-on: [self-hosted, linux, arm64]
timeout-minutes: 130
timeout-minutes: 145
steps:
- name: Checkout
uses: actions/checkout@v5
Expand Down Expand Up @@ -82,7 +82,7 @@ jobs:
rm -f "$BUILD_LOG"
"$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc"
sccache --show-stats 2>/dev/null || true
timeout-minutes: 30
timeout-minutes: 45
- name: gunbc ci (.dag witnesses + gates)
run: |
ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
Expand Down Expand Up @@ -126,7 +126,7 @@ jobs:
timeout-minutes: 5
rust_tests:
runs-on: [self-hosted, linux, arm64]
timeout-minutes: 30
timeout-minutes: 105
steps:
- name: Checkout
uses: actions/checkout@v5
Expand Down Expand Up @@ -174,7 +174,7 @@ jobs:
curl -LsSf --retry 3 "https://get.nexte.st/0.9.138/$A" | tar zxf - -C "$CARGO_HOME/bin"
fi
timeout-minutes: 5
- name: v1 rust gate (fmt + clippy + nextest)
- name: Build release bins (claim_executor + gunbc)
run: |
ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
set -o pipefail
Expand All @@ -199,6 +199,9 @@ jobs:
rm -f "$BUILD_LOG"
"$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc"
sccache --show-stats 2>/dev/null || true
timeout-minutes: 45
- name: v1 rust gate (fmt + clippy + nextest)
run: |
ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
git fetch --no-tags origin main 2>/dev/null || true
set -o pipefail
Expand All @@ -221,7 +224,7 @@ jobs:
fi
fi
rm -f "$BUILD_LOG"
timeout-minutes: 15
timeout-minutes: 45
- name: rust_tests cgroup peak (placement divisor)
run: |
BIN="$(git rev-parse --show-toplevel 2>/dev/null || pwd)/target/release/claim_executor"
Expand Down Expand Up @@ -297,3 +300,4 @@ jobs:
"$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc"
sccache --show-stats 2>/dev/null || true
"$ROOT/target/release/gunbc" run --source-root dag --source-root src/v2 --entry dag/gunbc/live_deploy/apply.dag --function live_deploy_apply_srv1_wet

6 changes: 6 additions & 0 deletions dag/gunbc/ci_layer_roots.dag
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ module gunbc.ci_layer_roots

data witness_layer_roots: List<String> = ["dag", "src/v2"]

data compile_clean_source_roots_note: String = "Compile-clean pool extends witness_layer_roots with src/v1 for cross-tree import resolution only (e.g. dag/test/claim/ownership_movable_test imports v1.compiler.ownership). src/v1 stays excluded from floor witness_layer_roots per gunbc.plans.seed_debt_bundle_item_2 §1 (parse-cursor fork deferred — no floor witness discovery over src/v1)."

fn compile_clean_source_roots() -> List<String> {
concat(witness_layer_roots, ["src/v1"])
}

data witness_discovery_scan_dirs: List<String> = ["dag/test/claim", "src/v2/test/claim/manual"]

data witness_exclusion_substrings: List<String> = [
Expand Down
4 changes: 4 additions & 0 deletions dag/gunbc/ci_spec.dag
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,10 @@ fn gunbc_ci_workflow_run(spec: CiSpec) -> String {
gunbc_ci_floor_only_script(spec: spec)
}

fn gunbc_ci_floor_run(spec: CiSpec) -> String {
gunbc_ci_floor_only_script(spec: spec)
}

fn gunbc_ci_rust_gate_invoke() -> String {
ci_cargo_eagain_retry_script(
command: concat(
Expand Down
30 changes: 21 additions & 9 deletions dag/gunbc/ci_workflow.dag
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import gunbc.ci_workflow_expressions {
ci_concurrency_group, ci_setup_rust_home, ci_cache_path, ci_cache_key, ci_cache_restore_keys
}
import gunbc.ci_spec {
CiSpec, gunbc_ci_spec, gunbc_ci_workflow_run, gunbc_ci_rust_job_run,
CiSpec, gunbc_ci_spec, gunbc_ci_floor_run,
gunbc_ci_deploy_stages, DeployStage, gunbc_ci_deploy_run_script,
ci_release_build_script,
gunbc_ci_rust_gate_only_script,
Expand Down Expand Up @@ -182,13 +182,13 @@ fn ci_floor_step() -> Step {
RunStep {
name: Present { value: "gunbc ci (.dag witnesses + gates)" },
id: none,
run: gunbc_ci_workflow_run(spec: ci_floor_spec_from_roster()),
run: gunbc_ci_floor_run(spec: ci_floor_spec_from_roster()),
shell: none,
env: none,
working_directory: none,
if_condition: none,
continue_on_error: none,
timeout_minutes: Present { value: gunbc_ci_job_timeout_policy_minutes }
timeout_minutes: Present { value: gunbc_ci_floor_gate_step_timeout_minutes }
}
}

Expand Down Expand Up @@ -250,7 +250,7 @@ fn ci_rust_gate_step() -> Step {
RunStep {
name: Present { value: "v1 rust gate (fmt + clippy + nextest)" },
id: none,
run: gunbc_ci_rust_job_run(),
run: gunbc_ci_rust_gate_only_script(),
shell: none,
env: none,
working_directory: none,
Expand Down Expand Up @@ -296,26 +296,38 @@ fn ci_deploy_step(stage: DeployStage) -> Step {

data gunbc_ci_job_timeout_policy_minutes: Int = 90

data gunbc_ci_rust_gate_step_timeout_minutes: Int = 15
data gunbc_ci_rust_gate_step_timeout_minutes: Int = 45

data gunbc_ci_release_build_step_timeout_minutes: Int = 30
data gunbc_ci_rust_gate_step_budget_note: String = "Interim rust-gate-only step budget (fmt/clippy/nextest after release build): 45 = prior 30m + margin after post-main-merge cold clippy exceeded gates-only step (job 85246635625, run 28749725167 on f2aa0ab). Prior: job 85237415376 bundled build+gates at 60m (10c53165bd split); job 85235032960 bundled at 30m. Re-derive DOWNWARD when fleet cache/build path stabilizes."

data ci_rust_build_gate_step_split_note: String = "Build and rust gate are separate workflow steps (same discipline as ci_build_floor_step_split_note): bundling cargo build + rust_gates_ci under one step timeout produced step-FAILURE during v1-compiler compile with zero gate verdict (receipt: rust_tests job 85237415376, run 28746200534 on dfbff0f). Build step carries gunbc_ci_release_build_step_timeout_minutes; rust gate step carries gunbc_ci_rust_gate_step_timeout_minutes."

data gunbc_ci_aux_step_timeout_minutes: Int = 5

data gunbc_ci_prelude_allowance_minutes: Int = 5

data ci_build_floor_step_split_note: String = "Build and floor are separate workflow steps so gate budgets apply to claim_executor only, not cargo build: bundling both under one step timeout produced step-FAILURE during v1-compiler compile with zero gate verdict (receipt: PR #6259 ci job 85192573905, 2026-07-05). Build step carries gunbc_ci_release_build_step_timeout_minutes; floor step carries gunbc_ci_floor_gate_step_timeout_minutes."

data gunbc_ci_release_build_step_timeout_minutes: Int = 45

data gunbc_ci_release_build_step_budget_note: String = "Interim release-build step budget until cold v1-compiler fits 15m: 45 = prior 30m + margin after main merge (CARGO_BUILD_JOBS=6, text_lookup_work_counter). Receipt: job 85235032962 timed out at 30m still Compiling v1-compiler (~25m dep prelude + compile in progress; run 28745277854 on 1ba1895). Prior: job 85194701830 at 15m. Re-derive DOWNWARD when fleet cache/build path stabilizes."

data gunbc_ci_floor_gate_step_timeout_minutes: Int = 90

data gunbc_ci_floor_gate_step_budget_note: String = "Interim floor-gate step budget until dag_compile_clean_gate fits gunbc_ci_job_timeout_policy_minutes (10): 90 = prior 60m budget + margin; compile_clean_source_roots src/v1 pool measured ~58m shell at 60m kill (still in batch-1), ~78m full compile locally. Receipt: job 85223768433 timed out at 60m mid batch-1 compile-clean (~58m in shell, zero verdict; run 28741045613 on abd03b9). Prior: job 85219793614 at 45m (dc05863), job 85217499061 at 30m (5c1131). Re-derive DOWNWARD when S2a node store / compile-clean scoping lands."

data gunbc_ci_deploy_job_backstop_timeout_minutes: Int = 10

data gunbc_ci_job_timeout_policy_disposition: Disposition = Terminal {
reason: "gunbc CI budget semantics (operator ruling, 2026-07-05): any timed-out gate is a FAILURE, not a silent pass - no verdict == failure. The budget is enforced at the STEP level (GitHub Actions step timeout-minutes fails the step, conclusion=failure, logs + [t+Xs] phase marks intact), never as a job-level kill: the prior 10-minute job-kill policy (2026-07-04) produced conclusion=cancelled, which every consumer treated as not-red - operationally a silent pass. Receipt: the last successful main ci run was 2026-07-01T01:00Z; 29 of the next 30 main runs were cancelled; four days of merges landed with zero gate verdicts while two latent reds entered the tree (04_resolve.dag emit-fresh hard diagnostics; inert_lens witness-builtin scope errors). Step budgets are authored on-carrier: floor gunbc_ci_job_timeout_policy_minutes (90m interim landing knob — batch-1 dag_compile_clean_gate runs five sequential compile shells; receipt run 28741451143 timed out at 50m on srv1-09 with compile-clean still in first shell pass; prior receipt 28739462879 at 25m — dissolve-on: affected-set-scoped compile-clean restores the 10m forcing budget), release build gunbc_ci_release_build_step_timeout_minutes (30m — receipt runs 28746525941 srv1-08 and 28746406899 srv1-09: cold v1-compiler release compile still in-flight at 15m step kill; rust gate gunbc_ci_rust_gate_step_timeout_minutes stays 15 for rust_tests job), aux gunbc_ci_aux_step_timeout_minutes (5). Until resolver-graph work fits the floor inside the forcing budget, main runs red-by-STEP-FAILURE with [t+Xs] phase attribution: an honest, countable deficit signal, unlike the cancelled-silence it replaces. Job-level timeouts are retained only as per-job backstops = that job's step-budget sum + prelude allowance: step timeouts start at step start, so a tighter backstop could job-cancel (silence) before a step fails red, resurrecting the exact defect this policy removes. Every post-prelude step is step-budgeted and fails RED first; a backstop firing means a wedged prelude - itself a mechanism bug to investigate, never a gate verdict. default_job_timeout_minutes (extdeps/github/actions.dag) still models GitHub's 360min platform default - workflow-layer policy on top."
}

fn gunbc_ci_job_backstop_timeout_minutes() -> Int {
gunbc_ci_release_build_step_timeout_minutes + gunbc_ci_job_timeout_policy_minutes + gunbc_ci_aux_step_timeout_minutes + gunbc_ci_prelude_allowance_minutes
gunbc_ci_release_build_step_timeout_minutes + gunbc_ci_floor_gate_step_timeout_minutes + gunbc_ci_aux_step_timeout_minutes + gunbc_ci_prelude_allowance_minutes
}

fn gunbc_ci_rust_job_backstop_timeout_minutes() -> Int {
gunbc_ci_rust_gate_step_timeout_minutes + gunbc_ci_aux_step_timeout_minutes + gunbc_ci_aux_step_timeout_minutes + gunbc_ci_prelude_allowance_minutes
gunbc_ci_release_build_step_timeout_minutes + gunbc_ci_rust_gate_step_timeout_minutes + gunbc_ci_aux_step_timeout_minutes + gunbc_ci_aux_step_timeout_minutes + gunbc_ci_prelude_allowance_minutes
}

fn ci_deploy_job(stage: DeployStage) -> Job {
Expand Down Expand Up @@ -361,7 +373,7 @@ fn rust_tests_job() -> Job {
id: "rust_tests",
name: none,
runner: gunbc_ci_runner_spec(),
steps: concat(ci_prelude_steps(), [ci_nextest_install_step(), ci_rust_gate_step(), ci_rust_cgroup_measurement_step()]),
steps: concat(ci_prelude_steps(), [ci_nextest_install_step(), ci_release_build_step(), ci_rust_gate_step(), ci_rust_cgroup_measurement_step()]),
needs: [],
env: none,
outputs: none,
Expand Down
6 changes: 3 additions & 3 deletions dag/test/claim/dag_compile_clean_shard_a_witness_test.dag
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module test.claim.dag_compile_clean_shard_a_witness

import tools.dag_compile_clean_partition {
witness_partition_entry_root_is_first_witness_layer_root,
witness_partition_pool_roots_are_witness_layer_roots,
witness_partition_pool_roots_are_compile_clean_source_roots,
witness_compose_all_clean_is_clean,
witness_compose_any_failure_fails_closed,
witness_compose_associativity,
Expand All @@ -21,9 +21,9 @@ data witness_compose_red_on_injected_failure: Bool = compose_compile_clean_shard
verdicts: [ShardClean, ShardFailed { entry_path: shard_a_exemplar_entry_path }]
) != ShardClean

test fn compile_clean_partition_boundary_matches_witness_layer_roots() -> Bool {
test fn compile_clean_partition_boundary_matches_compile_clean_source_roots() -> Bool {
witness_partition_entry_root_is_first_witness_layer_root()
&& witness_partition_pool_roots_are_witness_layer_roots()
&& witness_partition_pool_roots_are_compile_clean_source_roots()
}

test fn compile_clean_shard_verdict_compose_laws_hold() -> Bool {
Expand Down
9 changes: 7 additions & 2 deletions dag/test/claim/inert_lens_hygiene_witness_test.dag
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
module test.claim.inert_lens_hygiene_witness

import v2.lens.inert_lens {
inert_lens_hygiene_has_no_unreached_modules_holds,
inert_lens_hygiene_universe_is_nonempty_holds
}

test fn inert_lens_hygiene_has_no_unreached_modules() -> Bool {
return inert_lens_unreached_module_count() == 0
return inert_lens_hygiene_has_no_unreached_modules_holds()
}

test fn inert_lens_hygiene_universe_is_nonempty() -> Bool {
return inert_lens_top_level_module_count() > 0
return inert_lens_hygiene_universe_is_nonempty_holds()
}
8 changes: 4 additions & 4 deletions dag/tools/dag_compile_clean_partition.dag
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module tools.dag_compile_clean_partition

import gunbc.ci_layer_roots { witness_layer_roots }
import gunbc.ci_layer_roots { witness_layer_roots, compile_clean_source_roots }
import std.list { List }
import std.types { String, Bool }
import std.reducible {
Expand All @@ -24,7 +24,7 @@ type CompileCleanShardVerdict
fn compile_clean_partition_boundary() -> CompileCleanPartitionBoundary {
CompileCleanPartitionBoundary {
entry_root: witness_layer_roots.first(),
pool_roots: witness_layer_roots
pool_roots: compile_clean_source_roots()
}
}

Expand Down Expand Up @@ -77,8 +77,8 @@ fn witness_partition_entry_root_is_first_witness_layer_root() -> Bool {
compile_clean_partition_boundary().entry_root == witness_layer_roots.first()
}

fn witness_partition_pool_roots_are_witness_layer_roots() -> Bool {
compile_clean_partition_boundary().pool_roots == witness_layer_roots
fn witness_partition_pool_roots_are_compile_clean_source_roots() -> Bool {
compile_clean_partition_boundary().pool_roots == compile_clean_source_roots()
}

fn witness_compose_all_clean_is_clean() -> Bool {
Expand Down
6 changes: 4 additions & 2 deletions dag/tools/dag_compile_clean_transport.dag
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module tools.dag_compile_clean_transport

import extdeps.shell
import gunbc.ci_layer_roots { witness_layer_roots }
import gunbc.ci_layer_roots { compile_clean_source_roots }
import std.disposition { Disposition, Scaffold, RealizationDispatch }
import std.decl_ref { DeclarationRef, WholeDeclaration }
import extdeps.languages.bash.program {
Expand All @@ -14,7 +14,7 @@ import extdeps.languages.bash.program {
import tools.host_prelude { ensure_gunbc_built }

fn dcc_source_root_flags() -> List<ShellWord> {
fold(witness_layer_roots, init: [], f: (acc, r) => concat(acc, [lit(text: "--source-root"), lit(text: r)]))
fold(compile_clean_source_roots(), init: [], f: (acc, r) => concat(acc, [lit(text: "--source-root"), lit(text: r)]))
}

fn dcc_pool_index_flags() -> List<ShellWord> {
Expand Down Expand Up @@ -220,6 +220,7 @@ data dcc_target_dag_marker: String = "'--target' 'dag'"
data dcc_source_root_marker: String = "'--source-root'"
data dcc_witness_root_dag_marker: String = "'dag'"
data dcc_witness_root_v2_marker: String = "'src/v2'"
data dcc_witness_root_v1_marker: String = "'src/v1'"
data dcc_pool_index_marker: String = "'--dependency-pool-index' 'primary-precedence'"

data clean_tree_compile_invocation_marker: String = "'compile' '--source-root' 'dag'"
Expand All @@ -237,6 +238,7 @@ fn shell_serializes_dcc_common_compile_invocation(script: String) -> Bool {
&& string_contains(s: script, pattern: dcc_source_root_marker)
&& string_contains(s: script, pattern: dcc_witness_root_dag_marker)
&& string_contains(s: script, pattern: dcc_witness_root_v2_marker)
&& string_contains(s: script, pattern: dcc_witness_root_v1_marker)
&& string_contains(s: script, pattern: dcc_pool_index_marker)
}

Expand Down
2 changes: 2 additions & 0 deletions src/v1/04_method.dag
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ fn builtin_function_registry() -> Map<String, Node> {
let m = map_insert(m, "hash_combine", hash_type)
let m = map_insert(m, "atom_identity_hash", hash_type)
let m = map_insert(m, "string_contains", bool_type)
let m = map_insert(m, "length", int_type)
let m = map_insert(m, "starts_with", bool_type)
let m = map_insert(m, "replace", string_type)
let m = map_insert(m, "filesystem_read", type_variable_node(id: "filesystem_read_result"))
let m = map_insert(m, "contiguous_loop_elementwise_kernel", list_of_type_variable(id: "collection_element"))
Expand Down
2 changes: 2 additions & 0 deletions src/v1/stage0/src/v1_compiler_infer_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ pub fn builtin_function_registry() -> Rc<HashMap<String, Rc<Node>>> {
let m = v1_rt::rc_map_insert(m.clone(), "hash_combine".to_string(), hash_type());
let m = v1_rt::rc_map_insert(m.clone(), "atom_identity_hash".to_string(), hash_type());
let m = v1_rt::rc_map_insert(m.clone(), "string_contains".to_string(), bool_type());
let m = v1_rt::rc_map_insert(m.clone(), "length".to_string(), int_type());
let m = v1_rt::rc_map_insert(m.clone(), "starts_with".to_string(), bool_type());
let m = v1_rt::rc_map_insert(m.clone(), "replace".to_string(), string_type());
let m = v1_rt::rc_map_insert(
m.clone(),
Expand Down
41 changes: 41 additions & 0 deletions src/v1/stage0/src/v1_interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2264,6 +2264,11 @@ pub(crate) const STD_FN_INDEX_BRIDGE_FNS: &[&str] = &["fn_arrow_decl_facts_live"

pub(crate) const STD_DATA_INDEX_BRIDGE_FNS: &[&str] = &["data_init_decl_facts_live"];

pub(crate) const INERT_LENS_BRIDGE_FNS: &[&str] = &[
"inert_lens_unreached_module_count",
"inert_lens_top_level_module_count",
];

pub fn std_node_bridge_fn_names() -> &'static [&'static str] {
STD_NODE_BRIDGE_FNS
}
Expand Down Expand Up @@ -2351,6 +2356,15 @@ fn is_v4_std_qualified_name_bridge_call(ctx: &InterpContext, func_name: &str) ->
.is_some_and(|info| info.module_name == "v2.std.qualified_name")
}

fn is_v4_inert_lens_bridge_call(ctx: &InterpContext, func_name: &str) -> bool {
if !INERT_LENS_BRIDGE_FNS.contains(&func_name) {
return false;
}
ctx.item_registry
.get(func_name)
.is_some_and(|info| info.module_name == "v2.lens.inert_lens")
}

fn eval_call(node: &Rc<Node>, env: &Rc<Env>, ctx: &InterpContext) -> InterpResult<Value> {
let func_name = {
let key = Rc::as_ptr(node) as usize;
Expand Down Expand Up @@ -2437,6 +2451,18 @@ fn eval_call(node: &Rc<Node>, env: &Rc<Env>, ctx: &InterpContext) -> InterpResul
};
}

if is_v4_inert_lens_bridge_call(ctx, &func_name) {
return match func_name.as_str() {
"inert_lens_unreached_module_count" => Ok(Value::Int(
crate::cli_run::inert_lens_unreached_module_count(),
)),
"inert_lens_top_level_module_count" => Ok(Value::Int(
crate::cli_run::inert_lens_top_level_module_count(),
)),
_ => unreachable!("inert_lens bridge fn set mismatch"),
};
}

match func_name.as_str() {
"fold_list" => return eval_fold_list_native(&args, env, ctx),
"fold_list_right" => return eval_fold_list_right_native(&args, env, ctx),
Expand Down Expand Up @@ -5309,6 +5335,21 @@ fn eval_builtin(
Ok(Some(Value::Bool(s.contains(&sub))))
}

"starts_with" => {
let s = expect_str(positional.first().copied(), "starts_with")?;
let prefix = expect_str(positional.get(1).copied(), "starts_with prefix")?;
Ok(Some(Value::Bool(s.starts_with(&prefix))))
}

"length" => match positional.first() {
Some(Value::Str(s)) => Ok(Some(Value::Int(s.chars().count() as i64))),
Some(v) => match free_monoid_to_vec(v) {
Some(items) => Ok(Some(Value::Int(items.len() as i64))),
None => Ok(None),
},
None => Ok(None),
},

"contains" => match positional.as_slice() {
[Value::Str(s), Value::Str(sub), ..] => Ok(Some(Value::Bool(s.contains(sub)))),
[xs, target, ..] => match free_monoid_to_vec(xs) {
Expand Down
Loading
Loading