@chrono-meta/fh-gate 1.4.98 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -357,6 +357,67 @@ CTLPY
357
357
  [ "$_BARE_CTL" = FIRED ]
358
358
  chk $? "CONTROL: that detector fires on a planted declared-shipped subject (got $_BARE_CTL)"
359
359
 
360
+ echo ""
361
+ echo "── directional_diff_gate verdict arm: exit 0 is not a pass ──"
362
+ # WHY THIS LANE EXISTS (2026-08-15): the block wiring directional_diff_gate.sh --self-test gates on
363
+ # the subject's terminal verdict, not on rc=0 alone, and both halves of that were put there by a
364
+ # cross-family round rather than by the author. Its first draft gated on rc=0 plus a SUBSTRING of
365
+ # the verdict, and two reachable inputs satisfied it while nothing ran:
366
+ # · `✅ calibration passed (0 pairs)` — the subject's own verdict line is
367
+ # `[ "$f" -eq 0 ] && echo "✅ calibration passed ($n pairs)"`, so deleting every lane prints a
368
+ # PASS with n=0. Deletion read as a pass is the quietest face of the not-found-is-not-zero class.
369
+ # · `usage: calibration passed (28 pairs)` — a prose/usage line carrying the words.
370
+ # Without this lane both repairs are reversible to green, which is anchor-is-decorative.
371
+ # LIFTED from selfcheck.sh, not re-spelled — a lane that restates the condition stops seeing edits
372
+ # to it, which is the failure the two lanes above were written to avoid.
373
+ DD_ARM=$(sed -n '/^ _dd_verdict=\$(printf/,/^ fi ;;$/p' "$SELFCHECK" | sed 's/ ;;$//')
374
+ if [ -z "$DD_ARM" ]; then
375
+ echo "FAIL the directional_diff_gate verdict arm is no longer where this lane lifts it from."
376
+ echo " If the block was moved or renamed, update the lane WITH the subject."
377
+ exit 1
378
+ fi
379
+ # An empty lift is not the only bad lift. If the END anchor stops matching — re-indent the arm, or
380
+ # move it out of the `case` — the START anchor still matches and the range runs to EOF, which is
381
+ # non-empty and therefore passes the guard above. What saves it today is luck, not design: the
382
+ # `;;`-stripping applies to every line in the range, so downstream case arms lose their terminators
383
+ # and `eval` dies of a syntax error. A downstream span that happened to be self-contained would
384
+ # instead `eval` several hundred lines of selfcheck.sh, once per fixture, at the repo root. Bound
385
+ # the lift by size so the failure is a lane message rather than an accident. Cross-family, 2026-08-15.
386
+ if [ "$(printf '%s\n' "$DD_ARM" | wc -l)" -gt 15 ]; then
387
+ echo "FAIL the lifted verdict arm is $(printf '%s\n' "$DD_ARM" | wc -l) lines — the sed END anchor"
388
+ echo " stopped matching and the range ran past the block. Fix the anchor, do not widen this bound."
389
+ exit 1
390
+ fi
391
+ dd_arm_says() { # $1 = the subject's stdout; echoes PASS or FAIL
392
+ ( _out="$1"; fail=0; _show_failure() { :; }
393
+ eval "$DD_ARM" ) | grep -oE '^(PASS|FAIL)' | head -1
394
+ }
395
+
396
+ [ "$(dd_arm_says '✅ calibration passed (28 pairs)')" = PASS ]
397
+ chk $? "a real verdict with a non-zero pair count passes"
398
+
399
+ [ "$(dd_arm_says '✅ calibration passed (0 pairs)')" = FAIL ]
400
+ chk $? "every lane deleted (0 pairs, exit 0) is caught, not certified"
401
+
402
+ [ "$(dd_arm_says 'usage: calibration passed (28 pairs)')" = FAIL ]
403
+ chk $? "a usage/prose line carrying the words does not satisfy the gate"
404
+
405
+ # CONTROL — the pre-repair form (bare substring, no pair-count floor) must ACCEPT both bad
406
+ # fixtures. Without it these lanes could pass because the fixtures are wrong rather than because
407
+ # the repair works.
408
+ _pre() { printf '%s\n' "$1" | grep -oE 'calibration passed \([0-9]+ pairs\)' | tail -1; }
409
+ [ -n "$(_pre '✅ calibration passed (0 pairs)')" ] && [ -n "$(_pre 'usage: calibration passed (28 pairs)')" ]
410
+ chk $? "CONTROL: the pre-repair substring form accepts both — the fixtures discriminate"
411
+
412
+ # SCOPE of these four lanes, stated because the inherited §SCOPE block below is about a different
413
+ # anchor and does not cover them. The lift is the `0)` arm's BODY only, so these lanes see a change
414
+ # to the verdict predicate and are blind to the routing around it: widening `case ... in 0)` to
415
+ # `0|1)`, dropping `< /dev/null`, dropping the `$_LANE_TO` wrapper, or deleting the rc=124
416
+ # HARNESS-ERROR arm all leave every lane here green. Those are guarded by review, not by this file.
417
+ # The `_pre` control is also a RE-SPELLING of the pre-repair form rather than a lift of it — it has
418
+ # to be, since that form no longer exists in the subject to lift, but it means the control asserts
419
+ # what the old code did from memory. Both limits found by cross-family review, 2026-08-15.
420
+
360
421
  # ── SCOPE OF THIS ANCHOR — stated so it is not over-trusted ───────────────────
361
422
  # These lanes catch REVERSION (the run-twice form coming back, the helper being gutted, the
362
423
  # call-site redirect returning). They do NOT catch deliberate EVASION: a cross-family round
@@ -44,6 +44,36 @@
44
44
  # Re-point the class's `owner` or `mode` after the grant and the join fails: that is the point.
45
45
 
46
46
  classes:
47
+ # ---- REAL, ADOPTABLE class (not illustrative) -------------------------------------
48
+ # Ships with fh_node_check.sh's consent-gated auto-pull. Copy this block verbatim into your
49
+ # own tracks/_meta/consent_classes.yaml, then grant it in your UAP frontmatter to enable the
50
+ # apply arm. Without both, the check surfaces "N commits behind" and never touches the repo —
51
+ # absent is not granted.
52
+ #
53
+ # Read the reason before adopting: this class takes a DIFFERENT verdict from the `local-commit`
54
+ # example further down, on a deliberately narrow ground. If your integration branch is not
55
+ # PR-only/protected, that ground does not hold for you and you should not adopt it.
56
+ - name: repo-freshness-autopull
57
+ owner: scripts/fh_node_check.sh
58
+ mode: ff-only-merge-on-default-branch
59
+ target: this repo's own default branch, in the local clone, when it is already checked out
60
+ capabilities: [network, repo-mutation]
61
+ sinks: []
62
+ feeds: []
63
+ promotion_eligible: true
64
+ lease_days: 92
65
+ reason: >
66
+ A fast-forward pull introduces nothing new: every commit it brings down is already on the
67
+ integration branch, which is PR-only and server-side protected, so all of it has passed the
68
+ gates. `local-commit` below is classified feeds:[go-public] because it CREATES ungated
69
+ content that publish can then ship; this makes the tree MATCH canon instead. Publish packs
70
+ the working tree, so a tree matching origin is strictly safer to publish from than a stale
71
+ one. Blast radius also excludes personal state by construction — a pull touches tracked
72
+ files only, and session/memory/companion state is gitignored or outside the repo.
73
+ Envelope (enforced in code, not prose): applies ONLY when the default branch is already
74
+ checked out, never switches branches, and --ff-only refuses a divergence rather than
75
+ absorbing it. Lanes: scripts/test_node_check_lanes.sh lane10-a..e + CONTROL.
76
+
47
77
  # ---- promotion-eligible example -------------------------------------------------
48
78
  - name: dispatch-readonly-sim-local-artifact
49
79
  owner: fh-meta:sim-conductor # the gate/skill that does the asking