Skip to content

Upload floor phase journal artifact on falsifier cold-corpus kills - #8095

Merged
briansrls merged 2 commits into
mainfrom
session/stern-ant-249
Aug 10, 2026
Merged

briansrls merged 2 commits into
mainfrom
session/stern-ant-249

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Aug 10, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Upload target/floor-phase-journal.tsv as a floor-phase-journal artifact immediately after the floor-component receipt upload in the falsifier cold-corpus job (if: always(), if-no-files-found: warn).
  • Add modeled step + witness in gunbc.falsifier_workflow and extend cold-corpus job backstop by one artifact-transfer term.

Why forward admission matters (lead)

Today LaneCadenceWitness and LaneGates have never executed and nothing in the aggregate receipt says so — invisible gaps, not counted facts. Under forward parent-envelope admission they become counted refusals with typed lane identities (RefuseWouldEscapeParentEnvelope / RefuseLaneEnvelopeUnobserved), which is the direct win this instrument path enables before any cost envelope is designed.

Problem

On run 31334672366 the phase journal was written and the post-read step printed it at 23:52:41, but gh run view --log truncates around 21:52:34 — retained console logs hide the post-mortem instrument when the floor is killed. Full job logs via the API contain walk-terminal with BudgetExceeded detail.

Standing condition (not one incident): the last five scheduled falsifier runs all failed — 31334672366, 31324322216, 31314565434, 31304343908, 31296058832 — each with cold-corpus failing and aggregate-verdict failing behind it. Representative job 93298830438 ran 20:39:48→23:52:43 (3h13m wall). selection-control is a separate job and succeeds (~14.5 min); the failure is cold-corpus specifically, not the falsifier uniformly.

Reading failures: use API job logs, not gh run view --log

gh run view --job <id> --log truncates the tail of a long step's stream (measured: CLI drops terminal lines including typed refusals; API has more lines). When reading a FAILURE, pull /repos/gunb-ai/gunbc/actions/jobs/<id>/logs via the API — the typed refusal is written last and is the first thing the CLI loses. Compare line counts, not bytes (CLI prefixes inflate size). "No diagnostic" is a claim about the log you read, not about the run.

This is the third PR justification: (1) artifact durability, (2) load-dependent walls need cross-run audit, (3) the CLI log is not a reliable read of a failed floor — downloadable structured artifact is the only dependable post-mortem.

What this PR is (and is not)

This is not primarily a cost fix. It is the change that starts converting falsifier output into named, downloadable, citable facts — the occasion for envelope/admission work is cost, but the product is instrument legibility.

Two consumer-facing defects today, same class (facts that cannot be joined):

  1. Lane standing is legible, not reported — a human reads a lane from a log a later lane's death truncates; workflow_dispatch has no lane input.
  2. Run subject is unstated — workflow_dispatch accepts branch/tag names only (verified: raw SHA → HTTP 422 No ref found). Dispatching main runs at tip at dispatch time; merges inside the window silently change the subject with nothing in the log saying so. A receipt without headSha attributes every lane wall, refusal, and divergence to an unknown population — count-vs-identity one level up.

This PR adds the journal artifact. Follow-on per-lane receipts must carry headSha as a typed field (not log text) alongside lane identity, enrollment, walls, envelopes, and disposition — the denominator that makes every other field mean something. Pinning options: dispatch an immutable tag, or dispatch main and discard when headSha ≠ intended commit (vivid-gull-155 / #8055 is the first external consumer). Admission-grain work must also use the same lane identity on admit and refuse arms (FalsifierLane via gunbc_falsifier_lane_batches) so receipts are projection, not a second vocabulary.

Why this is not absorption

No new lane ceiling; one small artifact upload on an existing always() path so future timeouts produce downloadable timing data for envelope work.

Expected outcome after merge (SUCCESS, not regression)

The falsifier aggregate currently reports infrastructure (CorpusNotRun) when budget death prevents floor-component-receipt.json. That is honest about the receipt but masks real findings already in the walk. Run 31334672366 (job 93298830438) already produced these findings before walk reached its soft deadline before batch 9:

Lane Finding class Identities
LaneSelfHostWet resolve failure (11.0 min) src/v2/test/claim/execution/emit_on_demand_field_access_family_witness_test.dag — missing emit_field_eval_alt_descent_producer_tree in v2.test.execution.emit_host_field_access_equals_eval
LaneKnownRedProbe StaleKnownRed (1, quarantine bookkeeping) src/v2/test/claim/manual/english_emit_add_test.dag::english_emit_add_prose_holds — witness GREEN while admission still expects red. Remedy is not "delete the row OR restore red." Inspect first: if the expected-red wall landed → convert to permanent green regression control (row stays; DESIGN §4b(4) — evidence must not retire when the wall lands). If the discriminating input rotted → restore the red. Deleting the admission row deletes the evidence that the higher rung stays real.
LaneKnownRedProbe ExpectedRedPreVerdictUnverified (3 entries) src/v2/test/claim/emit/logic_ground_truth_test.dag::{logic_complement_truth_table, logic_meet_truth_table, logic_join_truth_table}
LaneRehomedBinWet witness failures (5/16, 33.3 min) routed — eval_cast identity-cast defect (node://adhoc-6bba608d-380) for three cannot cast List to List rows
LaneSubstrateLongLane witness failures (4/53 partial, ~20 min lower bound) routed — realization_vocab_live_corpus_receipt_holds first (documented pass vs measured fail)
LaneCadenceWitness never started → forward admission makes this a counted refusal —
LaneGates never started → forward admission makes this a counted refusal —

Restoring the instrument will surface these findings in the aggregate instead of burying them under infrastructure. A reviewer should read falsifier going from red-infrastructure to red-with-findings as the instrument working, not as this PR breaking CI.

Two budgets race (separate defect)

Walk soft deadline deadline_ms=10020000 (~167 min) vs GHA step ceiling 170 min — three minutes apart. Envelope design must place the substrate deadline with real margin below the host ceiling so diagnosis is always typed FloorFailed{Structural{reason:BudgetExceeded}}, not opaque step timeout. finalization_reserve sizing is what makes the typed refusal win reliably.

Attribution note

Per-lane wall times on run 31334672366 are boundary-derived (PASS/FAIL log timestamps), not receipt-derived: batch-wall-receipt phase completed but per-batch wall_ms lines were not echoed to the log. This PR makes the journal artifact downloadable so the next kill converts timestamp arithmetic into a direct read.

Test plan

  • falsifier_workflow_witness_test (cold_corpus_uploads_floor_phase_journal)
  • Next falsifier cadence: download floor-phase-journal artifact on a killed run and confirm journal rows present

Post-mortem: run 31359108019 (job 93364817699, headSha=f9508df)

Completed 08:54:04Z. walk-terminal: mode=BudgetExceeded, elapsed_ms=10064697, before batch 9. GHA step timeout 08:30:04Z (170 min); inline journal printed 08:53:58Z (if: always() post-read — data exists in API log, not in truncated CLI tail).

Per-lane walls (boundary-derived, vs 93298830438 quiet host):

Lane 31359108019 (loaded) 93298830438 ratio
LanePredictOnly 66.4 min 59.1 min 1.12×
LaneSelfHostWet 11.0 min 11.0 min 1.00×
LaneSelfHostWetKnownRed 34.9 min 34.6 min 1.01×
LaneKnownRedProbe 1.2 min 1.3 min 0.92×
LaneSilentPickGate 4.3 min 4.6 min 0.93×
LaneRehomedBinWet 32.5 min 33.3 min 0.98×
LaneSubstrateLongLane 12.3 min ~20 partial incomplete both
LaneCadenceWitness not reached (batch 8 started 08:29:57, GHA kill 08:30:04) not reached —
LaneGates not reached not reached —

07:31Z interim read (LanePredictOnly still running at ~104 min elapsed) was mid-batch, not final wall — corrected above. Load effect on PredictOnly is modest (+12%) in this pair; envelope design still requires falsifiable declarations (LaneExceededDeclaredEnvelope follow-on) and stated measurement conditions, not a single quiet-host constant.

Post-mortem: ordinary ci job — declared budgets vs 75-minute step timeout (verified 2026-08-10)

Three ci jobs measured via API /actions/jobs/<id>/logs (not gh run view --log). Worker spans from final coordinator-wait completed journal rows unless noted.

run job ordinary (s) scoped (s) sum (s) step wall outcome
#8100 (31365157824) 93383215728 3481 420 3901 3903s (65.0m) PASS
pr-8055 (31376246624) 93420755748 4052 ~440* ~4492 4513s (75.2m) step timeout
#8080 93390115597 4170 never ran — 4170s (69.5m) OVER-BUDGET

* pr-8055 scoped: journal never recorded coordinator-wait completed for scoped — GHA killed the step during post-walk harvest ~20s after scoped walk terminal exit code 0. Scoped span ~440s from floor-worker-wait timestamps (scoped wait start → scoped walk terminal).

On #8100, ordinary + scoped reconciles to the step wall within 2s — step wall ≈ worker spans + negligible handoff; no hidden slack term.

Two failure arms are different:

Joint unsatisfiability (arithmetic checked): ci.yml timeout-minutes: 75 = 4500s. Declared allowances compose to ~4675s when ordinary uses its full 55-minute population budget:

4675 > 4500 — satisfying every declared budget is not sufficient to survive the step. Effective ordinary-walk ceiling ≈ 3125s (~52m), ~3 minutes tighter than the signed 55-minute budget. Step timeout should be derived from declared budgets, not hand-set beside them.

Instrument gap: ordinary coordinator-wait records the worker total span only — not the prelude→walk boundary where the population budget clock starts (ordinary_start in run_walk precedes worker spawn). Ordinary span variance 3481 → 4170s (11m29s spread) across three runs of the same corpus; pass/fail is partly run-to-run variance, not only PR content. Attribution requires inferring prelude from an OVER-BUDGET line — decidable only on the failing arm.

Follow-on (not this PR): one journal span marking where the budget clock starts inside the worker; prelude measured ~14m30s on #8080 vs gunbc_ci_walk_overhead_allowance_minutes overhead note (raised 5→15m for pre-walk) — stale if the documented figure still reads ~5m for this path.

Fourth data point: #8080 job 93427738412 — scoped truncated, ordinary clean (verified 2026-08-10)

Run 31378685921, job 93427738412 (10:37→11:53Z). API log verification:

fact measured
ordinary coordinator-wait 4141 s, walk terminal exit code 0 @ 11:46:57, no OVER-BUDGET
scoped start ~11:47:14 (floor-worker-observation ordinary completed)
scoped at kill coordinator-wait running elapsed_seconds=360 (journal last pulse); needs 420–440 s historically — ~60–80 s short
kill timed out after 75 minutes @ 11:53:24 (~20 s after 360 s pulse)
batch verdicts 10 ✓ PASS [batch …] lines (batches 1–6) + 2 ✓ PASS [on-success stage …] — zero ✗ FAIL, zero refusals in executed verdicts
floor_peak_post 13300920320 bytes (~12.4 GiB, censored lower bound on floor_outcome=failure); memory.max = 16 GiB

Four-run ordinary spans: 3481 / 4052 / 4141 / 4170 s. Three failures cluster 4052–4170 (118 s spread); sole pass (#8100) is the outlier at 3481. Ordinary sits just above a ~4060 s effective ceiling most runs; the piece that falls off the end is the scoped worker (~7 min) riding behind it, not wild ordinary variance.

Instrument-only red (separate from timing remedy): pr-8055 and this run both produced red PR with every executed verdict green and no typed diagnostic — untyped GHA step timeout indistinguishable from content failure without API log greps. valiant-boar-65 red is instrument-only; repair nothing.

gunbc-ci-auto-heal and others added 2 commits August 10, 2026 04:36
The post-read shell step prints the journal, but gh run view --log truncates
hours before the job ends on timed-out falsifier runs (31334672366). Upload
target/floor-phase-journal.tsv with if: always() and if-no-files-found: warn
so killed-floor post-mortems are available as an artifact, not only console output.

Co-authored-by: Cursor <cursoragent@cursor.com>
Restore step_display_name import alongside ci_floor_phase_journal_artifact_name
(review 50919). Bump cold-corpus timeout-minutes to 280 to match the modeled
backstop after adding the floor-phase-journal artifact upload step.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in 0f349f7:

  1. review 50919 — Restored import gunbc.ci_materialization { step_display_name } alongside ci_floor_phase_journal_artifact_name in falsifier_workflow_witness_test.dag (step_index_of / step_count_named still call step_display_name).

  2. heal_generated_artifacts — HealAuthorCommitRequired on .github/workflows/falsifier.yml: the modeled cold-corpus backstop gained one gunbc_ci_artifact_transfer_step_timeout_minutes term for the new upload step, but the committed YAML still had timeout-minutes: 270. Wet regen expects 280; updated the job timeout to match.

CI re-running on the push.

— sent from stern-ant-249

@briansrls
briansrls merged commit 742e634 into main Aug 10, 2026
10 checks passed
@briansrls
briansrls deleted the session/stern-ant-249 branch August 10, 2026 13:04
gunbai-bot Bot pushed a commit that referenced this pull request Aug 10, 2026
Control tags e1c688a (pre-merge main), candidate tags 7f7da93
(#8055 merge); harness branch tracks current main for tooling only.
Documents the #8095 forensics vs exact-subject split.

Co-authored-by: Cursor <cursoragent@cursor.com>
gunbai-bot Bot pushed a commit that referenced this pull request Aug 10, 2026
The revert's one conflict was .github/workflows/ci.yml, a GENERATED artifact.
Resolving it by taking the revert side of the hunk silently reverted one line
of #8100 as well: collect_fleet_convergence (a READ) lost its
`|| github.event_name == 'workflow_dispatch'` arm, re-fusing the read to the
push-only writes that #8100 had just unfused.

A content spot-check did not catch it. I checked that #8095's floor-phase-journal
additions survived and that #8055's interpreter-parity step was gone, and both
were true — but verifying the markers you think of is not verifying the file.
For a derived artifact the generator is the authority and regeneration IS the
resolution; a spot-check only samples it.

Regenerated from the reverted sources: one line, restoring #8100's arm. The tree
now equals generator output, so the drift gate has nothing to say.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Aug 10, 2026
…8055) (#8099)

* Add P3 cohort probe for ClassificationCostStanding A/B (#8055).

Branch-neutral harness measures wall, prep/exec, and classification_production
on the same injected incident subject so control (G1 over-selection) and
candidate (G2 manifest + narrowed prep/exec) can be compared by head_sha.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Restrict incident diff injection to the incident P3 subject.

Discovery corpus runs should not inherit the two-entry synthetic touch unless
the caller supplies GUNBC_CI_DIFF_UNIFIED explicitly.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address review 50935: single incident roster authority, drop shell runner.

Export selection_control_incident_subject_roster from cli_run for the witness
and P3 probe; remove the unmarked tools/p3_cohort_ab_runner.sh and document
direct p3_cohort_probe invocation in the receipt README.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix floor CI: register P3 receipt doc and classify group_by traversal.

Bind p3-classification-cost-ab-receipt in doc_graph_roots (orphan README
moved to docs/plans/*.md convention). Classify group_by as
HostUnspecifiedOrder and bump the primitive_identity traversal census to 5.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Record P3 A/B method notes: intersection groups, calibration, log trap.

Handover from valiant-ant-57 (2026-08-10) so composition control and fleet
log retrieval are not re-derived when the harness runs post-#8055.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Declare explicit A/B subject pins in P3 receipt (#8055 post-merge).

Control tags e1c688a (pre-merge main), candidate tags 7f7da93
(#8055 merge); harness branch tracks current main for tooling only.
Documents the #8095 forensics vs exact-subject split.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add tag-dispatch selection pre-flight check to P3 receipt.

Require one-arm grep of selection_state and selected/total entry groups
before committing paired fleet runs; sequence behind lane read.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Record vivid-gull-155 as P3 lane read and A/B execution owner.

eager-owl-483 holds on dispatch; documents planted-red falsifier read convention.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix P3 receipt: document harness overlay on pinned arm SHAs.

The probe does not exist at control/candidate pins; paired runs require
#8099 merge then worktree overlay (arc1 precedent). Add apply-able patches
and replace in-tree-only build instructions (review 50950).

Co-authored-by: Cursor <cursoragent@cursor.com>

* Revert group_by traversal classification from harness PR.

HostUnspecifiedOrder on group_by is a std determinism claim, not measurement
plumbing; belongs in a separate PR with a discriminating witness (review 50953
/ valiant-ant-57). w_host_unspecified_traversal_classified still passes.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
briansrls pushed a commit that referenced this pull request Aug 10, 2026
…tions, redding main (#8104)

* Revert "Consume the G2 live-read manifest at every selection decision; land group_by and execute the interpreter-parity controls CI only compiled (#8055)"

This reverts commit 7f7da93.

* Regenerate ci.yml: the hand-picked conflict side had dropped #8100

The revert's one conflict was .github/workflows/ci.yml, a GENERATED artifact.
Resolving it by taking the revert side of the hunk silently reverted one line
of #8100 as well: collect_fleet_convergence (a READ) lost its
`|| github.event_name == 'workflow_dispatch'` arm, re-fusing the read to the
push-only writes that #8100 had just unfused.

A content spot-check did not catch it. I checked that #8095's floor-phase-journal
additions survived and that #8055's interpreter-parity step was gone, and both
were true — but verifying the markers you think of is not verifying the file.
For a derived artifact the generator is the authority and regeneration IS the
resolution; a spot-check only samples it.

Regenerated from the reverted sources: one line, restoring #8100's arm. The tree
now equals generator output, so the drift gate has nothing to say.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Restore two stale citations the blanket revert reintroduced

Reverting #8055 wholesale brought back text #8055 had independently
corrected, in two authority carriers:

- gunbc.ci_layer_roots falsifier_rehomed_bin_wet_rows: the
  floor_skip_discovery row's reason claimed the row duplicates the ci
  job's per-PR 'Affected-set selection control' step. #7446 demoted that
  step to the falsifier cadence, so the per-PR coverage it cites stopped
  existing. Restored origin/main's corrected reason verbatim. The 289s
  measured wall carries the rehome on its own.

- v2.test.lens_enforcement.gate_test live_tree_disposition_note cited
  LIVE_READ_CARRIER_HOME_MODULES_V0, a name that resolves nowhere; the
  live symbol live_read_carrier_homes_v0 survived the revert.

Found by deriving the check set (mixed +/- hunks vs origin/main) rather
than stopping at the reported instance.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.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