Skip to content

fix(ci): node-precise floor witness skip — execute frontier host (#5291 finish) - #5295

Merged
briansrls merged 19 commits into
mainfrom
session/jolly-otter-868
Jun 20, 2026
Merged

briansrls merged 19 commits into
mainfrom
session/jolly-otter-868

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

Summary

Finishes Phase 1.5a node-precise CI floor witness skip (supersedes #5291 WIP).

Root fix: run_in_context_with_args now installs with_active_ctx, so host calls to test_claim_evaluation_nodes / fold_list_right decode FreeMonoid Empty/Cons chains instead of failing with fold_list_right expects a list, got Variant.

Entry touch: skip decisions use overlapping TestClaim declaration spans (node-precise seeds from git diff -U0 hunk line ranges) before node-closure comparison, so same-file A/B edits discriminate correctly (file-level skip would run both).

§5 discriminating receipt: node_precise_discriminator_test.dag + node_precise_same_file_ab_frontier_discriminates unit test + host test showing SKIP [assumed-green node-frontier] on untouched witnesses.

Test plan

  • ctrl-build -- cargo test -p v1-compiler node_precise_same_file_ab_frontier_discriminates — GREEN
  • ctrl-build -- cargo test -p v1-compiler-tests discovery_corpus_skip — GREEN (4 tests; skip path skips discriminator witness against origin/main...HEAD)
  • GUNBC_CI_DIFF_BASE=origin/main GUNBC_CI_DIFF_HEAD=HEAD ./target/debug/claim_executor --source-root dsl --source-root src/v2 --plan-entry src/v2/workflow/ci_floor_plan.dag --plan-function gunbc_ci_floor_batches — no node-frontier population failed (full floor still subject to unrelated roster resolve issues on this branch)

briansrls and others added 2 commits June 19, 2026 17:55
Root-cause: run_in_context_with_args omitted with_active_ctx, so
test_claim_evaluation_nodes failed with fold_list_right/Variant during
frontier population. Entry touch now keys overlapping TestClaim spans
(same-file A/B discriminator) before node-closure comparison.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot gunbai-bot Bot changed the title Phase 1.5a REDO v3: FINISH node-precise CI floor skip. Branch off #5291/session/valiant-bat-421 (its node-precision host — git diff -U0 → span-overlap → collect_frontier_nodes_from_diff_line_ranges — is CORRECT but was pushed UNEXECUTED). FIX: (1) discovery-corpus type error 'test_claim_evaluation_n fix(ci): node-precise floor witness skip — execute frontier host (#5291 finish) Jun 19, 2026
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review June 19, 2026 18:08
briansrls and others added 7 commits June 19, 2026 18:24
Resolve node-precise CI floor skip (this branch) against #5225 width-sharding
(main): skip logic kept, sharding re-applied; NodeFrontierSeeds made Send so a
clone rides into each width-shard thread.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
cursor/composer-2.5 REQUEST_CHANGES on #5295 found the node-frontier seeded
only from `data` declarations, so a diff touching only a `test fn` body never
entered the frontier and the witness could skip on a change to its own
behavior — a silent false-green (DESIGN §5).

Root cause: a `test fn` is not an AST `module.items` entry (the parser drops
the contextual `test` keyword before the span is recorded), so witness-body
lines fell into the *last* `data` item's trailing (EOF) span and were
misattributed to that node. Fix: `collect_frontier_seeds_from_diff_line_ranges`
now builds a unified, source-ordered line partition of every top-level
declaration — `data`/`fn`/`type` from the AST, `test fn` decl lines from the
same text scan discovery uses (`scan_test_decl_lines`). An edited `test fn`
forces that witness to run (`edited_test_fns`, per-function precision); an
edited `fn`/`type`/`service` or a failed resolve / non-.dag / preamble edit
fails closed to a full run (findings 2 + C).

Receipts (execution, not grep):
- host: node_precise_test_fn_body_edit_runs_only_that_witness — editing
  witness B's body skips witness A; editing A's own body runs A.
- host: node_precise_referenced_runs_orphan_skips_by_execution — the sound
  single-file node-precision proof (a referenced node runs, an orphan skips;
  the intra-witness A/B variant was unsound and dropped — a witness that names
  a node depends on it, so §5 must run it).
- unit: scan_test_decl_lines_pairs_names_with_1_based_lines.

Removed the now-unused byte-span overlap helper (the partition is line-based).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor Author

Review response — node-precise frontier made fail-closed (cursor REQUEST_CHANGES + deeper §5 findings)

Pushed 76967a13a4 (on top of a Merge origin/main that resolves this branch's skip logic against #5225 width-sharding). The two cursor/composer-2.5 findings are fixed by execution receipts, not greps, and two further §5 holes I found while fixing them are closed too.

Finding 1 — test fn body edits never entered the frontier → silent false-green ✅

Root cause was deeper than "only walks DataItem": a test fn is not an AST module.items entry (the parser drops the contextual test keyword before the span is recorded), so a witness body fell into the last data item's trailing (EOF) span and was misattributed to that node. Editing any witness body would then run/skip based on an unrelated node.

Fix: collect_frontier_seeds_from_diff_line_ranges now builds a unified, source-ordered line partition of every top-level declaration — data/fn/type from the AST, test fn decl lines from the same text scan discovery uses (new scan_test_decl_lines). An edited test fn populates edited_test_fns and forces that witness to run (per-function precision), and no witness body can be swallowed by a data span any more.

Receipt: node_precise_test_fn_body_edit_runs_only_that_witness (host) — editing witness B's body skips witness A; editing A's own body runs A. RED if the edit is misattributed.

Finding 2 — .dag resolve failure swallowed (Err(_) => continue) ✅

A changed .dag we cannot resolve now returns NodeFrontierSeeds::run_all() (full-corpus run), not a silent skip. Same fail-closed escape hatch also covers a non-.dag change (the Rust seed), an empty/unparsed .dag, a preamble (module/import) edit, and a changed fn/type/service decl — anything the node-frontier cannot bound.

Two further §5 holes found while fixing the above

  • Import fail-open (finding D): frontier nodes were filtered by file-equals-entry, so an edit to a shared imported .dag (e.g. a std node) was invisible to every importing witness — they'd skip on a change they depend on. Now gated by "does this entry's closure declare the symbol?" (ctx.item_registry.contains_key).
  • Unsound single-file discriminator (finding E): the prior intra-witness A/B fixture was unsound — a witness whose body names another node genuinely depends on it (its Bool can flip), so §5 must run it, not skip. Replaced with the sound proof: a referenced node runs, an orphan node (referenced by no claim) skips — same file, different outcomes, which only true node precision can produce (node_precise_referenced_runs_orphan_skips_by_execution).

opus-4-7 cleanups

Dropped the non-discriminating debug test and the dead overlapping_test_claims_contains; the now-unused byte-span overlap helper is removed (the partition is line-based). The skip_unaffected_node_frontier: Bool in-band flag (🟡 non-blocking) is unchanged.

All 8 floor-skip host receipts + 3 cli_run unit tests green; clippy --all-targets -D warnings and fmt clean.

@gunbai-bot

gunbai-bot Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor Author

CI failure here is inherited red-main, not a #5295 regression

The failing ci check is not caused by this PR's code. The floor pass dies at plan resolution — before any witness (including the node-precise skip ones) runs:

claim_executor: resolve failed for plan src/v2/workflow/ci_floor_plan.dag:
dsl/std/realization_width.dag:26:3: error: name 'NanosecondDuration' not found in module 'std.measure'
dsl/std/realization_width.dag:29:3: error: name 'nanosecond_duration' not found in module 'std.measure'
dsl/std/realization_width.dag:41:3: error: name 'cost_account_time_nanos' not found in module 'std.realization_schedule'

realization_width.dag was introduced by ac89f37f1c (the current tip of main, "Phase 1 hardware-bounded scheduler width-fold") still importing NanosecondDuration/nanosecond_duration from std.measure after #5286 relocated those authorities. main is red for this reason (its last several CI runs failed); this PR merged main and inherited the breakage.

Already owned by #5330 (swift-wren-741-mainfix, "realization_width.dag consumer catch-up to #5286"). Once #5330 lands and main is green, I'll re-merge main here and CI goes green — no #5295 code change is needed or appropriate (pushing one would just re-stale the reviews).

#5295 itself is code-complete: 8 floor-skip host receipts + 3 cli_run unit tests green locally, clippy --all-targets -D warnings + fmt clean. Holding the branch frozen at 76967a13a4 pending the main fix.

@gunbai-bot

gunbai-bot Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the careful pass. Dispositioning the three non-blocking findings:

1. NodeFrontierSeeds::force_run_all state-space hint — keeping as-is, deliberately. The bool is a 2-state tag (couldn't-bound → run-all vs. here-are-the-bounds), and it's collapsed to a clean (skip_enabled, seeds) tuple at exactly one boundary (cli_run.rs:2822, Ok(seeds) => (!seeds.force_run_all, seeds)) — nothing reads force_run_all past that point, and the substrate side already carries the proper closed coproducts (WitnessRunDisposition, FloorDiffObservation, FloorRerunFrontier). So the conflation never crosses into .dag. Given the operator's minimal-change intent for this PR and your own "if this grows" condition, I'd rather not churn the core type of an approved diff now. Dissolution trigger (§6): convert to FrontierSeedsOutcome = RunAll | Produced { .. } the moment it gains a third state, or the flag is read anywhere past the cli_run.rs:2822 boundary.

2. run_injected_diff_roster(_entry) unused param — valid, genuine dead code. Removing it (and the &entry args at the 5 call sites; entry stays live via each test's inline roster). I'm folding this into the main re-merge commit rather than a standalone push: this branch's CI is currently red purely from inherited main breakage (realization_width.dag resolve error from ac89f37f1c, owned by #5330), so a push right now buys another red run + re-stales the fresh review while cursor is mid-pass. It lands the moment #5330 is in and I re-merge.

3. skip_unaffected_node_frontier: Bool on RunnableDiscoveryBatch — intentional, agreeing with your read. It's a single closed policy knob (not an open enum), set unconditionally true by the sole production caller (ci_floor_plan.dag:121), and it's the marked 🟡 scaffold — dissolve-on: the v2 executor consuming the width field directly (realization_width.dag header). A §3 single-authority gate, not a violation. No change.

— sent from zesty-deer-479

…skip × P3c hermetic)

Integrates main's #5276 (P3c: flip CI discovery default to Hermetic) + the
realization_width.dag consumer catch-up that unblocked red main.

cli_run.rs is a semantic compose, not a pick-a-side: run_discovery_rows and
run_discovery_corpus_with_options now thread BOTH this branch's node-precise
skip (skip_enabled + frontier_seeds + DiscoverySummary.skipped) AND main's
hermetic discovery (whole_tree_published_keys + make_eval_context_with_runtime_options
+ DiscoveryWitnessOutcome/witness_outcomes). The roster-only gate is the union of
both triggers (explicit_roster_only OR empty-scan-dirs+explicit). The entry touch
check runs on the hermetic ctx (data-item Node eval is pure, so published keys
don't perturb it). claim_executor keeps main's Wet-dispatch comment and this
branch's run_discovery_corpus_with_options call (the only one taking the skip flag).

Also folds the opus-4-7 finding-2 cleanup: drop the unused _entry param from
run_injected_diff_roster + its call sites.

Verified by execution: 8 floor-skip host receipts + 3 cli_run unit tests
(this branch) AND 4 wet/hermetic equivalence tests (main) all green; clippy
--all-targets -D warnings + fmt clean. main is green again, and the merged tree
carries the fixed realization_width.dag (NanosecondDuration from std.verification).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor Author

Merge conflict resolved — main re-merged, node-precise skip composed with P3c hermetic (9ebad5dca)

main advanced under this PR (the realization_width.dag red-main breakage was fixed there — NanosecondDuration/nanosecond_duration relocated to std.verification, cost_account_time_nanos → cost_account_time_count — and main is green again). Re-merging pulled in #5276 (P3c: flip CI discovery default to Hermetic), which rewrote the same discovery functions this PR touches. So this was a semantic compose, not pick-a-side:

  • run_discovery_rows now threads BOTH params: skip_enabled + frontier_seeds (node-precise skip, with DiscoverySummary.skipped) and whole_tree_published_keys (hermetic ctx via make_eval_context_with_runtime_options, with DiscoveryWitnessOutcome/witness_outcomes). The per-entry touch check runs on the hermetic ctx — safe because data-item Node evaluation is pure, so published mock keys can't perturb the frontier decision.
  • run_discovery_corpus_with_options computes both the skip seeds and the published-mock keys, threading both through the width==1 path and each shard thread.
  • roster-only gate = union of both triggers: options.explicit_roster_only || (scan_dirs.is_empty() && !explicit_entries.is_empty()) — preserves my host-skip tests and main's wet/hermetic equivalence gate.
  • merge_discovery_summaries merges both skipped and witness_outcomes.
  • claim_executor keeps main's Wet-dispatch comment + this branch's run_discovery_corpus_with_options call (the only variant carrying the skip flag).
  • Also folded the opus-4-7 finding-2 cleanup (dropped the unused _entry param).

Verified by execution, both sides: 8 floor-skip host receipts + 3 cli_run unit tests (this branch) and 4 wet/hermetic equivalence tests (main's #5276) all green; clippy --all-targets -D warnings + fmt clean. mergeable is now CLEAN.

…CI FreeMonoid poison)

The Phase 1.5a node-precise CI floor skip resolves the changed `.dag` files to
locate which top-level declarations moved (`collect_frontier_seeds_from_diff_line_ranges`).
It did so over the *same* `MultiEntryIndex` the corpus then resolves over. That index
carries interior-mutable parse / intern / typed-module caches, so resolving a changed
file first warms — and, under the known v2 generic-instantiation bootstrap limitation,
corrupts — a module the corpus later reuses: resolving `ci_floor_plan.dag` first caches
`FreeMonoid<T>` WITHOUT its `Empty`/`Cons` variants, after which every corpus entry whose
closure reuses `node_query.dag` fails to resolve (`undefined variable 'Empty'`). `main`
never hit this (no skip -> no pre-corpus resolve); the width>1 shards already build a
fresh index per thread, so only the width==1 path (CI's mode) shared.

Fix: resolve the frontier analysis over a throwaway index so it is a pure read that
cannot perturb the corpus it decides over (§3 cache-impurity: cold-vs-warm resolve must
agree). One line; no change to the skip topology.

Verified by execution:
- full floor pass (skip ON): batch 2 `PASS discovery-corpus (486 witnesses)` — the
  FreeMonoid resolve failure is gone (red->green across this one change).
- new host regression `frontier_warmup_does_not_poison_corpus_resolution`: injects a diff
  on the proven poisoner `ci_floor_plan.dag` with a `node_query` consumer
  (`budget_roster_completeness_test.dag`) in the roster; RED with the exact CI error
  without the fix, GREEN with it. `run_discovery_rows` resolves every entry before the
  skip decision, so the poison bites whether or not the entry is ultimately skipped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor Author

CI fix pushed (e1e68ec8a4) — root-caused the 9ebad5d FreeMonoid failure.

Symptom: batch 2 failed resolving budget_roster_completeness_test.dag with node_query.dag:55: undefined variable 'Empty' / variant 'Empty'/'Cons' not found in type 'FreeMonoid' across the std closure. main was green; the failure only appeared once the node-precise skip was active.

Root cause (§3 cache-impurity, not a logic bug in the skip topology): collect_frontier_seeds_from_diff_line_ranges resolves the changed .dag files to locate which declarations moved — and it did so over the same MultiEntryIndex the corpus then resolves over. That index carries interior-mutable parse / intern / typed-module caches, so resolving a changed file first warms — and, under the known v2 generic-instantiation bootstrap limitation (FreeMonoid<T> alias instantiation, see qualified_name.dag), corrupts — a module the corpus later reuses. Resolving ci_floor_plan.dag first caches FreeMonoid<T> without its Empty/Cons variants; every later entry whose closure reuses node_query.dag then fails to resolve. main never hit this (no skip → no pre-corpus resolve); the width>1 shards already build a fresh index per thread, so only the width==1 path (CI's mode) shared.

Fix (1 line): resolve the frontier analysis over a throwaway index, so it is a pure read that cannot perturb the corpus it decides over.

Verified by execution:

  • Full floor pass (skip ON, release + text_lookup_work_counter): batch 2 PASS discovery-corpus (486 witnesses) — the FreeMonoid failure is gone.
  • New host regression frontier_warmup_does_not_poison_corpus_resolution: injects a diff on the proven poisoner ci_floor_plan.dag with budget_roster_completeness_test.dag (a node_query consumer) in the roster. RED with the exact CI error without the fix, GREEN with it — confirmed by reverting the one line and rebuilding. run_discovery_rows resolves every entry before the skip decision, so the poison bites regardless of whether the entry is ultimately skipped.

fmt + clippy --all-targets -D warnings clean; the 9 floor_skip host tests pass.

— sent from zesty-deer-479

@briansrls
briansrls merged commit dda570e into main Jun 20, 2026
1 of 2 checks passed
@briansrls
briansrls deleted the session/jolly-otter-868 branch June 20, 2026 00:02
briansrls added a commit that referenced this pull request Jun 20, 2026
Bring in mainline CI fixes (e.g. #5295 floor witness skip) and
re-trigger checks after runner communication loss on c796e00.
briansrls added a commit that referenced this pull request Jun 20, 2026
Slice-2 mass anchor backfill and slice-3 CI floor wiring were held
pending operator ruling; 86b4a7b re-triggered cross-tree Empty/Cons
poison (#5295 family). Restore advisory off-floor gate, remove
ExtdepsStableAuthorityGate from ci_spec/floor plan, revert backfill
to the 163-entry snapshot signed off at slice-1.

Co-authored-by: Cursor <cursoragent@cursor.com>
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