-
Notifications
You must be signed in to change notification settings - Fork 1
ops(active-trajectory): binary direction split + NUL-safe parsing + lease-rejected-after-dry-run message + deferred follow-ups #836
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
9314d9f
e17c5ca
d2bf214
52d8e03
6d3d2b4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -105,36 +105,74 @@ Best blade (Amara): *"Line-count dominance is a smoke detector. Content equivale | |||||
|
|
||||||
| The drift trajectory is a metric; the GATE is the ledger. Hand-counts drift; ledgers from `git diff --numstat` don't. | ||||||
|
|
||||||
| The ledger is computed in two passes (text via `numstat`, binary direction via `name-status`). Per multi-AI review 2026-04-29T10:50Z: binary files emit `-/-` in `numstat` because lines aren't countable, but they CAN be erased on hard-reset, so they need direction classification — `acehack-only` vs `lfg-only` vs `modified-on-both`. | ||||||
|
|
||||||
| **The shell snippet below is ILLUSTRATIVE, NOT DURABLE.** Per multi-AI review 2026-04-29T11:05Z (Codex + Copilot 7-thread cluster + Amara): the inline awk/grep approach below has real NUL-safety bugs and is not portable across awk implementations: | ||||||
|
||||||
|
|
||||||
| - `awk $3` with default whitespace FS breaks on paths with spaces (need `FS='\t'`). | ||||||
| - `grep -Ff` reads newline-delimited patterns, not NUL-delimited (the `ORS="\0"` write doesn't compose with `grep -f`). | ||||||
| - `numstat -z` rename/copy records are `adds<TAB>dels<TAB>NUL old<NUL>new<NUL>`, not just one NUL-delimited row. | ||||||
| - `name-status -z` rename/copy rows are `status<NUL>old<NUL>new<NUL>` (3 fields), not `status<NUL>path<NUL>` (2 fields). The toggle parser desynchronizes. | ||||||
| - `RS='\0'` / `ORS='\0'` is a gawk extension; macOS BSD awk doesn't support it. | ||||||
| - `/tmp/binary-paths.nul` is a fixed path with no `mktemp` + `trap` cleanup; clobber-prone under concurrency. | ||||||
|
|
||||||
| The durable home for the gate-runner is `tools/zero-zero-zero/check-gate.sh` (deferred follow-up, see "Deferred follow-ups" below). That script must be tested against fixtures including: paths with spaces, binary add, binary delete, binary modify, binary rename, binary copy, gawk-vs-BSD-awk. | ||||||
|
AceHack marked this conversation as resolved.
|
||||||
|
|
||||||
| **Stopgap rule for this round**: if `binary_modified_files` is non-zero in this ledger, do NOT rely on the inline snippet to classify direction. Use `git diff --name-status -z origin/main..acehack/main -- <path>` per binary file + direct `git show` evidence, manually, until the gate-runner script exists. | ||||||
|
AceHack marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
| ```bash | ||||||
| git diff --numstat origin/main..acehack/main | awk ' | ||||||
| # Binary files: numstat emits "-\t-\t<path>". They have no countable lines, | ||||||
| # but content can still be lost on hard-reset. Count them separately so | ||||||
| # they require explicit classification rather than being silently dropped. | ||||||
| $1 == "-" && $2 == "-" { | ||||||
| binary_files += 1 | ||||||
| next | ||||||
| } | ||||||
| { | ||||||
| add += $1; del += $2; files += 1 | ||||||
| if ($1 == 0) zero_files += 1 | ||||||
| } | ||||||
| END { | ||||||
| print "text_modified_files=" files | ||||||
| print "zero_acehack_only_files=" zero_files | ||||||
| print "potential_loss_lines=" add | ||||||
| print "lfg_newer_lines=" del | ||||||
| print "binary_modified_files=" (binary_files+0) | ||||||
| if ((binary_files+0) > 0) { | ||||||
| print "WARNING: binary files in diff need separate classification (lines uncountable)." | ||||||
| print "Run: git diff --name-status origin/main..acehack/main | awk '\''$1!~/^[D]$/'\'' | grep -F -f <(git diff --numstat origin/main..acehack/main | awk '\''$1==\"-\"{print $3}'\'')" | ||||||
| } | ||||||
| } | ||||||
| ' | ||||||
| # Pass 1: text files (numstat reports lines) | ||||||
| git diff --numstat -z origin/main..acehack/main \ | ||||||
| | awk -v RS='\0' ' | ||||||
|
AceHack marked this conversation as resolved.
Outdated
|
||||||
| $1 != "-" && $2 != "-" { | ||||||
| add += $1; del += $2; files += 1 | ||||||
| if ($1 == 0) zero_files += 1 | ||||||
| } | ||||||
|
AceHack marked this conversation as resolved.
Outdated
|
||||||
| END { | ||||||
| print "text_modified_files=" files | ||||||
| print "zero_acehack_only_text_files=" zero_files | ||||||
| print "potential_loss_lines=" add | ||||||
| print "lfg_newer_lines=" del | ||||||
| } | ||||||
| ' | ||||||
|
|
||||||
| # Pass 2: binary files split by direction (name-status reports A/M/D/R/T) | ||||||
| # - "A" from AceHack-side perspective = AceHack-only (hard-reset ERASES) → loss-relevant | ||||||
| # - "D" from AceHack-side perspective = LFG-only (hard-reset ADDS) → not a loss | ||||||
| # - "M"/"R"/"T" = modified on both sides → needs semantic classification | ||||||
| git diff --numstat -z origin/main..acehack/main \ | ||||||
| | awk -v RS='\0' 'BEGIN{ORS="\0"} $1 == "-" && $2 == "-" { print $3 }' \ | ||||||
| > /tmp/binary-paths.nul | ||||||
| if [ -s /tmp/binary-paths.nul ]; then | ||||||
| git diff --name-status -z origin/main..acehack/main \ | ||||||
| | awk -v RS='\0' ' | ||||||
| # name-status with -z: status<NUL>path or for renames status<NUL>old<NUL>new | ||||||
| BEGIN{i=0} | ||||||
| {if (i==0) {st=$0; i=1} else {p=$0; print st "\t" p; i=0}} | ||||||
|
AceHack marked this conversation as resolved.
Outdated
|
||||||
| ' \ | ||||||
|
AceHack marked this conversation as resolved.
Outdated
|
||||||
| | grep -Ff /tmp/binary-paths.nul \ | ||||||
|
AceHack marked this conversation as resolved.
Outdated
AceHack marked this conversation as resolved.
Outdated
AceHack marked this conversation as resolved.
Outdated
|
||||||
| | awk -F'\t' ' | ||||||
| $1=="A" { ace_only += 1 } | ||||||
| $1=="D" { lfg_only += 1 } | ||||||
| $1 ~ /^[MRTC]/ { modified_both += 1 } | ||||||
|
AceHack marked this conversation as resolved.
Outdated
|
||||||
| END { | ||||||
| print "binary_acehack_only_files=" (ace_only+0) | ||||||
| print "binary_lfg_only_files=" (lfg_only+0) | ||||||
| print "binary_modified_or_renamed_files=" (modified_both+0) | ||||||
| } | ||||||
| ' | ||||||
|
AceHack marked this conversation as resolved.
Outdated
AceHack marked this conversation as resolved.
Outdated
|
||||||
| fi | ||||||
| ``` | ||||||
|
|
||||||
| Per Codex 2026-04-29T10:42Z catch (PR #835): the prior version of this script silently excluded binary files via `$1 != "-" && $2 != "-"`. `git diff --numstat` emits `-/-` for binary content because it can't count lines, but binary files CAN still be erased on hard-reset. New version counts them separately and surfaces a warning when present. | ||||||
| Per Codex 2026-04-29T10:42Z catch + Amara 2026-04-29T10:50Z direction-split: the prior one-pass version silently excluded binary files via `$1 != "-" && $2 != "-"`. The conceptual fix (split direction into three buckets) is correct. The inline implementation above is illustrative only — see the warning block above this code; the durable NUL-safe + portable implementation lives in the deferred gate-runner script. | ||||||
|
|
||||||
| Verified 2026-04-29T10:43Z: the 5 binary-classified files in the current diff are all LFG-only (status `D` from AceHack perspective; hard-reset ADDS them, doesn't erase AceHack content), so this specific instance has zero binary-loss surface. The script fix is for general correctness. | ||||||
| **Reset-loss surface for binary files:** | ||||||
|
|
||||||
| - `binary_acehack_only_files` → would be ERASED on hard-reset; this is the gate-relevant count. | ||||||
| - `binary_lfg_only_files` → would be ADDED on hard-reset; not a loss. | ||||||
| - `binary_modified_or_renamed_files` → exists on both with content/mode/path differences; needs semantic classification (e.g., is the AceHack version more correct, or is LFG's the canonical?). | ||||||
|
|
||||||
| Verified 2026-04-29T10:43Z: the 5 binary-classified files in the current diff have status `D` (LFG-only), so `binary_acehack_only_files = 0` and `binary_modified_or_renamed_files = 0` in this specific round. | ||||||
|
|
||||||
| Current ledger (computed 2026-04-29T10:25Z): | ||||||
|
|
||||||
|
|
@@ -150,14 +188,15 @@ unclassified_lines = 176 HEURISTIC_LFG_DOMINATES — pending per-file sema | |||||
| Hard-reset is signoff-eligible ONLY when: | ||||||
|
|
||||||
| ```text | ||||||
| unclassified_lines = 0 | ||||||
| unsafe_lines = 0 | ||||||
| binary_acehack_only_files = 0 (binary files exist only on LFG, OR each binary file has been classified) | ||||||
| fresh-clone fsck = clean | ||||||
| hard-reset preflight = clean | ||||||
| ls-remote-vs-fetch SHA match = verified | ||||||
| dry-run push shape = clean | ||||||
| maintainer signoff = yes | ||||||
| unclassified_lines = 0 | ||||||
| unsafe_lines = 0 | ||||||
| binary_acehack_only_files = 0 (would be ERASED on hard-reset) | ||||||
| binary_modified_or_renamed_classified = all (each must be SAFE_TO_RESET_LFG_SUPERSEDES or NEEDS_FORWARD_SYNC) | ||||||
|
AceHack marked this conversation as resolved.
Outdated
|
||||||
| fresh-clone fsck = clean | ||||||
| hard-reset preflight = clean | ||||||
| ls-remote-vs-fetch SHA match = verified | ||||||
| dry-run push shape = clean | ||||||
| maintainer signoff = yes | ||||||
| ``` | ||||||
|
|
||||||
| Per multi-AI review 2026-04-29T10:35Z: dry-run push shape verification is added to the gate. Validates refspec + credentials + push shape before the real destructive operation. The real lease still matters at the real push (server-side check); dry-run is an additive safety check, not a replacement. | ||||||
|
|
@@ -358,6 +397,15 @@ A peer-call to Grok this session reported the inverse claim ("AceHack has the se | |||||
|
|
||||||
| **Hard-reset is NOT YET signoff-eligible.** The strict gate above requires `unclassified_lines = 0`, and the current ledger says `unclassified_lines = 176` (18 files in HEURISTIC_LFG_DOMINATES). The next agent-owned work is per-file semantic inspection of those 18 files to either promote each to SAFE_TO_RESET_LFG_SUPERSEDES (with named evidence) or downgrade to NEEDS_FORWARD_SYNC. | ||||||
|
|
||||||
| ### Deferred follow-ups (NOT blocking 0/0/0 progress, captured for visibility) | ||||||
|
|
||||||
| Per multi-AI review 2026-04-29T10:50Z packet: | ||||||
|
|
||||||
| - **Gate-runner script** (now bumped to highest priority among deferred follow-ups): build `tools/zero-zero-zero/check-gate.sh` that emits a machine-readable summary of all 9 gate conditions and fails closed. Replaces the prose ledger AND the illustrative inline snippet above with a verifiable-by-execution gate. Per multi-AI review 2026-04-29T11:05Z (Codex P1 + Copilot 5 threads + Amara): the durable script must be tested against fixtures: paths with spaces, binary add, binary delete, binary modify, binary rename, binary copy, gawk-vs-BSD-awk portability, `mktemp` + `trap` cleanup. Until the script lands, binary direction MUST be classified manually via `git diff --name-status -z` per file + direct `git show` evidence. Best blade (Amara): *"The binary hole is found. The gate condition is right. The parser still needs teeth."* | ||||||
|
||||||
| - **Gate-runner script** (now bumped to highest priority among deferred follow-ups): build `tools/zero-zero-zero/check-gate.sh` that emits a machine-readable summary of all 9 gate conditions and fails closed. Replaces the prose ledger AND the illustrative inline snippet above with a verifiable-by-execution gate. Per multi-AI review 2026-04-29T11:05Z (Codex P1 + Copilot 5 threads + Amara): the durable script must be tested against fixtures: paths with spaces, binary add, binary delete, binary modify, binary rename, binary copy, gawk-vs-BSD-awk portability, `mktemp` + `trap` cleanup. Until the script lands, binary direction MUST be classified manually via `git diff --name-status -z` per file + direct `git show` evidence. Best blade (Amara): *"The binary hole is found. The gate condition is right. The parser still needs teeth."* | |
| - **Gate-runner script** (now bumped to highest priority among deferred follow-ups): build `tools/zero-zero-zero/check-gate.sh` that emits a machine-readable summary of all 11 gate conditions and fails closed. Replaces the prose ledger AND the illustrative inline snippet above with a verifiable-by-execution gate. Per multi-AI review 2026-04-29T11:05Z (Codex P1 + Copilot 5 threads + Amara): the durable script must be tested against fixtures: paths with spaces, binary add, binary delete, binary modify, binary rename, binary copy, gawk-vs-BSD-awk portability, `mktemp` + `trap` cleanup. Until the script lands, binary direction MUST be classified manually via `git diff --name-status -z` per file + direct `git show` evidence. Best blade (Amara): *"The binary hole is found. The gate condition is right. The parser still needs teeth."* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This refers to a “shell snippet below” / “inline snippet”, but the snippet has been removed in this revision, so the wording is now misleading. Suggest rephrasing to refer to the previously-removed snippet (or delete the “below/inline” references) so readers don’t hunt for code that isn’t there.