Repository navigation
extdeps/git: model diff interface (name-status -z) - #6297
Conversation
…h types
git_diff_status_entry_departed_path nested an if around a match, and one
arm returned entry.old_path (Optional<FilePath>) while a sibling arm under
the outer if's else returned a bare Present{..} — the typechecker rejected
the if/match split as incompatible (Product(FilePath) vs Coproduct(Optional)).
Flattened to a single match over entry.status with three arms; green via
claim_batch on the new extdeps_git_diff_name_status_witnesses witness.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…iff_observe
Add FloorNameStatusDiffResult / floor_observe_git_diff_name_status(_for_ci),
mirroring the existing unified-diff mechanism but targeting
`git diff --name-status -z` and routing raw stdout through
extdeps.git.parse_git_diff_name_status_z + git_diff_status_entries_touched_paths
(single-authority parser, no re-parsing in the workflow layer). An unrecognized
status letter (typed DiffUnknownGitStatus) refuses (NameStatusDiffFail), never
silently drops the entry.
Also fixes a latent bug shared by the pre-existing unified-diff path: Converged
{ ShellEffectApplied { exit_code, .. } } was matched with exit_code discarded
(`_`), so a nonzero-but-"Converged" evidence value would have been read as Ok.
realize_shell_on_host already gates Converged on process success, but the
reconciliation consumer should not silently trust that invariant either -
check exit_code explicitly at the point of use. Found via `--wet` execution
of a real invalid-base-ref case (claim_batch defaults to --hermetic/mocked
shell.Exec.Run; --wet is required to exercise real host execution).
Witnesses (claim_batch --wet): floor_diff_observe_host_effect_apply_holds now
covers both the unified-diff and name-status-diff success/fail-closed paths.
floor_git_diff_name_status_range() (cli_run.rs) resolves floor_observe_git_diff_name_status_for_ci and extracts changed_paths/ departed_paths from the typed NameStatusDiffOk/NameStatusDiffFail result. run_discovery_corpus_with_options now sources changed_paths and departed_paths from this real git diff --name-status -z observation instead of the unified-diff header scrape/text scan. parse_unified_diff_line_ranges drops the `diff --git a/OLD b/NEW` header-scrape block (path grain); it stays scoped to LINE grain (hunk ranges) only, as decl-overlap attribution still needs it. Hunkless .dag paths (pure rename, mode-only, binary) are seeded into line_ranges_by_file from the name-status changed_paths so floor_diff_edits_from_line_ranges keeps attributing them at path grain with no regression. Updates floor_disposition_refusal_note to record the git-interface grain gap (name-status, rename pairs) as closed. Verified: cargo check/clippy -D warnings clean; cargo test -p v1-compiler --lib cli_run:: green except one pre-existing, unrelated flake (test_migration_delete_guard, its own separate git-diff plumbing, reproduces identically on this exact commit before this change too). .dag witnesses re-verified green under --wet (real shell execution, not the hermetic mock). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Review finding (claude/claude-opus-4-7 on #6297): the existing malformed-rename-score witness only checked the first entry's status, not that token-alignment corruption downstream of an unscored R/C token stays observable as Unknown. Adds w_malformed_rename_score_corruption_stays_fail_closed_downstream, which feeds a malformed rename token followed by further tokens through parse_git_diff_name_status_z and asserts git_diff_status_entries_any_unknown still holds - so floor_name_status_diff_from_reconciliation always routes to NameStatusDiffFail on this input, never a silently-corrupted NameStatusDiffOk. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Addressed both findings from the claude/claude-opus-4-7 review:
— sent from nimble-otter-431 |
…stream Cursor review on #6297 (composer-2.5, REQUEST_CHANGES) flagged two issues: 1. git_diff_status_entry_is_unknown was a hand-rolled match-based is-variant predicate; the codebase already has a canonical idiom for this (discriminant(v: ...) equality, see affected_set.dag's universe_has_process_of_kind and model_core.dag's axis dispatch). Dissolved into an inline discriminant comparison in the fold step. 2. parse_git_diff_name_status_z discarded final_state.pending after folding tokens, so a truncated/incomplete git diff --name-status -z stream (e.g. a trailing status letter or rename pair with no closing path token) silently produced entries == [] - indistinguishable from a legitimately empty diff. This is exactly the widen-instead-of- refuse failure DESIGN.md S5 forbids (state-space conflation between "nothing changed" and "observation is corrupt"). Split parse_git_diff_name_status_z into git_diff_name_status_parse_state (exposes the full fold state) + git_diff_name_status_parse_state_is_truncated (checks pending is terminal). floor_name_status_diff_from_reconciliation now refuses with a typed NameStatusDiffFail on a non-terminal pending state before trusting entries. New witnesses pin both: w_lone_trailing_status_token_is_typed_truncated_not_empty, w_rename_missing_new_path_is_typed_truncated_not_empty, w_complete_stream_is_never_flagged_truncated. Verified via claim_batch --wet (real fold execution, not hermetic mock). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Addressed both cursor/composer-2.5 REQUEST_CHANGES findings with fix commits:
Both pinned with new witnesses in — sent from nimble-otter-431 |
Cursor review on #6297 (composer-2.5, REQUEST_CHANGES) on the previous fix: the workflow consumer was guarded, but the exported convenience parse_git_diff_name_status_z still projected only .entries and dropped pending, so any OTHER caller of the extdeps authority could still get an empty-looking result from a truncated stream. A sibling *_is_truncated validator alongside a lossy accessor keeps the hazard structurally possible, not unrepresentable. Replaced parse_git_diff_name_status_z with a single parse authority, git_diff_name_status_parse, returning an outcome coproduct: GitDiffNameStatusComplete { entries } | GitDiffNameStatusTruncated { pending, entries }. There is no accessor that yields entries without also naming which outcome produced them - truncation can't be silently dropped by a future caller. floor_name_status_diff_from_reconciliation now matches the outcome directly instead of calling a separate state+is_truncated pair. Witness test updated to consume the outcome coproduct (test-local well_formed_entries/is_truncated helpers over the outcome, not a reintroduction of the lossy accessor), plus a new witness pinning that Complete and Truncated are distinct variants (w_truncated_outcome_is_a_distinct_variant_from_complete). Verified via claim_batch --wet (real fold execution). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Addressed cursor/composer-2.5's follow-up REQUEST_CHANGES finding: confirmed valid — the workflow consumer was guarded, but the exported Fixed by replacing it with a single parse authority, New witness — sent from nimble-otter-431 |
Run 28757531898 @ e65f569: rust gate still failed cannot cast String — stdout_lines projects plain strings; List<FilePath> mismatch bit when git_success triggers should_run_gates path selection. Revert DiffNameOnly/Merge path grain to List<String> until interpreter brands stdout_lines (dissolve-on: #6297 host). Co-authored-by: Cursor <cursoragent@cursor.com>
Run 28757531898 @ e65f569: rust gate still failed cannot cast String — stdout_lines projects plain strings; List<FilePath> mismatch bit when git_success triggers should_run_gates path selection. Revert DiffNameOnly/Merge path grain to List<String> until interpreter brands stdout_lines (dissolve-on: #6297 host). Co-authored-by: Cursor <cursoragent@cursor.com>
Run 28757870966 @ e69f7cd: rust_tests still failed cannot cast String — #6297 models List<FilePath> from stdout_lines but the host projected plain strings; cast targets with empty authored names also missed FilePath = String alias resolution. Resolve string-family cast seeds through inferred types and coerce stdout_lines list elements. Co-authored-by: Cursor <cursoragent@cursor.com>
Run 28757531898 @ e65f569: rust gate still failed cannot cast String — stdout_lines projects plain strings; List<FilePath> mismatch bit when git_success triggers should_run_gates path selection. Revert DiffNameOnly/Merge path grain to List<String> until interpreter brands stdout_lines (dissolve-on: #6297 host). Co-authored-by: Cursor <cursoragent@cursor.com>
Run 28757870966 @ e69f7cd: rust_tests still failed cannot cast String — #6297 models List<FilePath> from stdout_lines but the host projected plain strings; cast targets with empty authored names also missed FilePath = String alias resolution. Resolve string-family cast seeds through inferred types and coerce stdout_lines list elements. Co-authored-by: Cursor <cursoragent@cursor.com>
* WIP: InterfaceSummary v0: std carrier + first consumer * InterfaceSummary v0: rebase onto main (1a19d49). Std carrier + lens + firewall witness + export_signature_facts host bridge. CI interim budgets (split build/floor/rust-gate, 30min build, floor_diff relative roots). Replayed cleanly — no unrelated main reverts. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * ci: retrigger PR checks after rust gate timeout fix (b79ba13). Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: InterfaceSummary v0: std carrier + first consumer * fix: git diff name-only paths stay List<String> at runtime. Run 28757531898 @ e65f569: rust gate still failed cannot cast String — stdout_lines projects plain strings; List<FilePath> mismatch bit when git_success triggers should_run_gates path selection. Revert DiffNameOnly/Merge path grain to List<String> until interpreter brands stdout_lines (dissolve-on: #6297 host). Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: InterfaceSummary v0: std carrier + first consumer * fix: brand stdout_lines for String-family list types at runtime. Run 28757870966 @ e69f7cd: rust_tests still failed cannot cast String — #6297 models List<FilePath> from stdout_lines but the host projected plain strings; cast targets with empty authored names also missed FilePath = String alias resolution. Resolve string-family cast seeds through inferred types and coerce stdout_lines list elements. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: restore fold_list in complexity_r1_accumulator_copy. Run 28758528714 @ 03e3238: ci floor failed discovery corpus — fold is not in v2 scope; r1_copied_port_index must use fold_list from v2.std.algebra (same as main). Co-authored-by: Cursor <cursoragent@cursor.com> * fix: rustfmt v1_interpreter stdout_lines map closure. Run 28759362798 @ 1c12890: rust_tests failed cargo fmt --check on the multiline map closure in map_shell_outputs. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * WIP: InterfaceSummary v0: std carrier + first consumer * Raise rust gate CI budgets so reconcile+nextest fit the step cap. gunbc run rust_gates_ci reconcile consumed ~22m before fmt/clippy/nextest on d7dc35e, leaving nextest killed at the 30m step timeout; bump gate to 45m, warm to 46m (warm>gate witness), and rust_tests job backstop to 106m. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: InterfaceSummary v0: std carrier + first consumer * Inline bare == aliases and drop unused Bool imports (review 36011). Remove rel_path_eq/module_path_eq nicknames per §3; use == directly. Drop dead Bool imports from firewall_body fixtures. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: InterfaceSummary v0: std carrier + first consumer * Fail-closed module_key imports and add export_signature host scaffold receipt. - Add v2.std.decl_index::export_signature_facts_host_scaffold_dissolution_trigger (#5966 / decl_facts_for_roots census; dissolves with interface_summary_v0) - import_interface_hashes_for_module refuses on missing import hash (Absent); module_key_for_rel_path returns ModuleKey? - Witnesses: scaffold receipt cites #5966; unresolved import → Absent Addresses Composer REQUEST_CHANGES review 36013. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: InterfaceSummary v0: std carrier + first consumer * Raise CI floor step budget after 135m timeout on batch-1 compile-clean. Receipt run 28786036501 @ 6527d01: plan resolve ~74m plus batch-1 reconcile ~53m exhausted the 135m floor step cap before batch-2. Floor step 135→200m; ci job backstop 190→255m. Co-authored-by: Cursor <cursoragent@cursor.com> * Convert interface_summaries_from_facts to fold (missing fold_list import). Review 36025: fold_list call survived sibling refactors without its v2.std.algebra import; use fold + list_snoc_item like the rest of the file. Co-authored-by: Cursor <cursoragent@cursor.com> * Raise CI floor step to 300m after 200m timeout on batch-1 reconcile. Receipt run 28794864868 @ c3e2093: plan resolve ~73m, batch-1 first reconcile ~52m, killed at 200m cap during second reconcile before batch-1 finished. Floor 200→300m; ci job backstop 255→355m. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: InterfaceSummary v0: std carrier + first consumer * ci: restore step-level ci job backstop for floor completion. The 10m starvation-kill (#6323) cancelled the ci job mid plan-resolve (receipt: run 28811397826 @ 304fe94 — floor still in typecheck at t+8m). Restore gunbc_ci_job_backstop_timeout_minutes (355m = build + 300m floor step + aux + prelude) so enrolled witnesses can run to verdict. Co-authored-by: Cursor <cursoragent@cursor.com> * ci: align timeout disposition with live step-level backstop. gunbc_ci_job_timeout_policy_disposition now documents the active policy (ci_job emits gunbc_ci_job_backstop_timeout_minutes = 355m, RED-by-step- failure). Retire unused gunbc_ci_floor_job_runner_starvation_kill_minutes; Co-authored-by: Cursor <cursoragent@cursor.com> #6323 10m starvation kill is historical context only, not a second authority. * ci: restore 10m ci/floor job and 30m rust_tests job caps. Operator request: lower job timeouts from interim 355m/106m back to 10m starvation-kill on ci job and 30m on rust_tests. Disposition updated to match live policy. Co-authored-by: Cursor <cursoragent@cursor.com> * ci: drop unused rust job backstop helper Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: InterfaceSummary v0: std carrier + first consumer * ci: fix 10m job kill aborting release build before floor. Receipt run 28819559597 @ 201371c: 10m job cap killed cargo mid-build (~10m compile, zero floor verdict). Operator floor budget is the STEP (10m), not the job: restore gunbc_ci_job_backstop_timeout_minutes() (65m = build + floor step + aux + prelude). Align rust_tests steps (15m warm, 10m gate) to fit 30m job cap. Co-authored-by: Cursor <cursoragent@cursor.com> * ci: add value-Measure dissolve-on marker for rust_tests job timeout. Piggyback gunbc_ci_rust_tests_job_timeout_minutes_measure_grounding_ dissolution_trigger on the existing floor-step marker family (Opus 36075 non-blocking finding). Co-authored-by: Cursor <cursoragent@cursor.com> * ci: restore rust_tests step-sum job backstop (Composer 36079). Remove fixed 30m gunbc_ci_rust_tests_job_timeout_minutes — job cap was shorter than step budgets, producing cancelled silent-pass instead of RED-by-step-failure. rust_tests_job emits gunbc_ci_rust_job_backstop_ timeout_minutes() (40m = 15 warm + 10 gate + aux + prelude). Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Brian Searls <briansrls@gunb.ai> Co-authored-by: Cursor <cursoragent@cursor.com>
Summary
Models git's
git diff --name-status -zmachine interface as the singletyped authority for path-grain diff observation (extdeps/git), replacing
a unified-diff header-scrape reimplementation of the same fact.
dag/extdeps/git/git.dag:GitDiffChangeStatus(A/M/D/R<score>/C<score>,typed rename/copy similarity),
GitDiffStatusEntry, a NUL-token parser(
parse_git_diff_name_status_z), andtouched_paths/departed_pathsprojections, plus
DiffNameStatus/DiffNameStatusMergeserviceoperations (shell transport, one realization of the interface shape).
src/v2/workflow/floor_diff_observe.dag: a provider-agnosticFloorNameStatusDiffResultobservation entry point(
floor_observe_git_diff_name_status_for_ci), fail-closed on anonzero exit or an unrecognized status letter (never silently
absorbed).
src/v1/stage0/src/cli_run.rs: host cutover — the CI floor'schanged_paths/departed_pathsfor path grain now come from thistyped name-status observation instead of scraping
diff --git a/OLD b/NEWheaders out of the unified diff text. LINEgrain (hunk ranges, decl-overlap attribution) still legitimately uses
the unified diff and is untouched.
DiffPolicy) stays in the workflow layer, unmoved.Test plan
.dagwitnesses, verified green under real (--wet) shell execution,not the hermetic mock:
extdeps_git_diff_name_status_witnesses(parser: A/M/D/R/C, renameold+new paths, malformed status letter refuses typed-not-absorbed)
git_mock_consumer_is_total_holds/git_mock_omitted_member_is_red_holds(mock-corpus totality, red-on-omission control)
floor_diff_observe_host_effect_apply_holds(unified + name-statusscript serialization, real CI-policy observation, invalid-base
fail-closed control, for both diff shapes)
cargo check/cargo clippy --all-targets -- -D warnings: clean.cargo test -p v1-compiler --lib cli_run::: 115 passed, 1 pre-existingunrelated failure (
test_migration_debt_tests::delete_guard_holds_with_no_v1_test_deletions_in_diff,its own separate git-diff plumbing querying
origin/main; reproducesidentically on this exact commit and is untouched by this change).