@chrono-meta/fh-gate 1.4.74 → 1.4.76

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.
Files changed (28) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/AGENTS.md +18 -0
  3. package/CHEATSHEET.md +1 -1
  4. package/CLAUDE.md +14 -1
  5. package/knowledge/shared/harness-core/harness_frontier_diagnosis_2026-06-02.md +1 -1
  6. package/knowledge/shared/harness-core/meta_harness_engineering_definition.md +1 -1
  7. package/knowledge/shared/harness-core/multi_model_sidecar_strategy.md +6 -0
  8. package/knowledge/shared/learnings/subagent_invocations_log.yaml +29 -1
  9. package/package.json +7 -1
  10. package/plugins/fh-commons/.claude-plugin/plugin.json +1 -1
  11. package/plugins/fh-meta/.claude-plugin/plugin.json +1 -1
  12. package/plugins/fh-meta/skills/auto-decorrelation/SKILL.md +38 -3
  13. package/plugins/fh-meta/skills/sim-conductor/SKILL_detail.md +6 -0
  14. package/plugins/fh-meta/skills/steel-quench/SKILL_detail.md +6 -0
  15. package/scripts/degrade_direction_scan.sh +17 -2
  16. package/scripts/memory_link_check.py +237 -0
  17. package/scripts/memory_nearcheck.py +131 -0
  18. package/scripts/package_coverage_check.sh +25 -4
  19. package/scripts/selfcheck.sh +35 -0
  20. package/scripts/session_close_check.sh +31 -1
  21. package/scripts/sidecar_wait.sh +76 -0
  22. package/scripts/test_card_drift_probe.sh +77 -0
  23. package/scripts/test_degrade_scan_shell_probes.sh +26 -0
  24. package/scripts/test_memory_link_check.sh +134 -0
  25. package/scripts/test_session_close_lanes.sh +99 -0
  26. package/templates/degrade_direction_scan.sh +17 -2
  27. package/plugins/fh-meta/skills/context-bridge-dispatch/SKILL.md +0 -32
  28. package/plugins/fh-meta/skills/self-marketing-lint/SKILL.md +0 -30
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env bash
2
+ # test_session_close_lanes.sh — known-pair anchor for session_close_check.sh ② (harvest-loop
3
+ # obligation) and ⑤ (card-last invariant).
4
+ #
5
+ # WHY (2026-07-28): ② used to be an UNSATISFIABLE warning — it fired whenever an FH asset was
6
+ # touched today and the script had no way to observe whether harvest-loop ran, so no session could
7
+ # ever discharge it. A line that fires on every healthy close is noise, and noise trains the runner
8
+ # to skim past the ❌ lines that matter. The repair gave it a mechanical discharge (a harvest-loop
9
+ # decision recorded in TODAY's fh_completed file). This file is that repair's regression anchor:
10
+ # the fix is only real if the ⚠️ still fires when NOTHING is recorded, and stops firing when it is.
11
+ #
12
+ # Lanes (each is a decision the gate must get right, not a smoke test):
13
+ # ②-N FH asset touched today, no harvest-loop line anywhere → ⚠️ MUST fire
14
+ # ②-P1 same, plus "harvest-loop 실행 완료" → ✅ must NOT fire
15
+ # ②-P2 same, plus an explicit SKIP note → ✅ must NOT fire
16
+ # (CLAUDE.md ② accepts "harvest-loop (or an explicit skip note)" — a recorded skip is
17
+ # a discharged obligation, not an evaded one)
18
+ # ②-C no FH asset touched today → neither line appears at all
19
+ # (over-firing is a defect in its own right — the whole reason this repair exists)
20
+ # ⑤-N a close artifact newer than the card → ❌ card-last MUST fire (exit 1)
21
+ # ⑤-P card is the newest artifact → ✅ card-last holds
22
+ #
23
+ # Exit 0 = 7/7 lanes calibrated · exit 1 = the gate's instrument is wrong (do not trust its verdict)
24
+
25
+ set -uo pipefail
26
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
27
+ CHECK="$SCRIPT_DIR/session_close_check.sh"
28
+ TODAY=$(date +%Y-%m-%d)
29
+ FAILED=0
30
+
31
+ if [ ! -f "$CHECK" ]; then
32
+ echo "FAIL session-close lanes: subject $CHECK missing"
33
+ exit 1
34
+ fi
35
+
36
+ # Builds a throwaway repo whose HEAD commit touches (or does not touch) an FH asset path.
37
+ _fixture() { # $1=touch_fh_asset(0/1) $2=completed-file body (empty = no file)
38
+ local touch_fh="$1" body="$2" T
39
+ T=$(mktemp -d)
40
+ ( cd "$T" \
41
+ && git init -q . \
42
+ && git config user.email anchor@local && git config user.name anchor \
43
+ && if [ "$touch_fh" = 1 ]; then echo x > CLAUDE.md; else echo x > unrelated.txt; fi \
44
+ && git add -A && git commit -qm "fixture" ) >/dev/null 2>&1
45
+ mkdir -p "$T/tracks/_meta"
46
+ [ -n "$body" ] && printf '%s\n' "$body" > "$T/tracks/_meta/fh_completed_${TODAY}.md"
47
+ printf '# card\n' > "$T/tracks/_meta/reference_next_session_starter.md"
48
+ printf '%s' "$T"
49
+ }
50
+
51
+ _lane() { # $1=name $2=grep-pattern $3=expect(0/1) $4=fixture dir
52
+ local name="$1" pat="$2" expect="$3" T="$4" out hit
53
+ out=$(bash "$CHECK" "$T" 2>/dev/null)
54
+ hit=0
55
+ printf '%s\n' "$out" | grep -q "$pat" && hit=1
56
+ rm -rf "$T"
57
+ if [ "$hit" = "$expect" ]; then
58
+ echo "✅ $name (hit=$hit, expected=$expect)"
59
+ else
60
+ echo "❌ $name — hit=$hit, expected=$expect"
61
+ printf '%s\n' "$out" | sed 's/^/ /'
62
+ FAILED=1
63
+ fi
64
+ }
65
+
66
+ WARN2='⚠️ ② FH assets changed today'
67
+ OK2='✅ ② FH assets changed today'
68
+
69
+ _lane "②-N no harvest-loop decision recorded → warns" "$WARN2" 1 "$(_fixture 1 '- 항목 하나')"
70
+ _lane "②-P1 harvest-loop run recorded → silent" "$WARN2" 0 "$(_fixture 1 '- harvest-loop 실행 완료')"
71
+ _lane "②-P2 explicit skip note → silent" "$WARN2" 0 "$(_fixture 1 '- harvest-loop: skipped — 3-repo session, deferred')"
72
+ _lane "②-P1 run recorded → prints the ✅ form" "$OK2" 1 "$(_fixture 1 '- harvest-loop 실행 완료')"
73
+ _lane "②-C no FH asset touched → no ② line at all" ' ② ' 0 "$(_fixture 0 '- 항목 하나')"
74
+
75
+ # ⑤ card-last: an artifact newer than the card is the bug class the invariant exists to catch.
76
+ T=$(_fixture 1 '- harvest-loop 실행 완료')
77
+ touch "$T/tracks/_meta/fh_completed_${TODAY}.md" # make it strictly newer than the card
78
+ if bash "$CHECK" "$T" >/dev/null 2>&1; then
79
+ echo "❌ ⑤-N artifact newer than card → expected exit 1, got 0 (card-last not enforced)"
80
+ FAILED=1
81
+ else
82
+ echo "✅ ⑤-N artifact newer than card → exit 1 (card-last enforced)"
83
+ fi
84
+ touch "$T/tracks/_meta/reference_next_session_starter.md" # card becomes newest
85
+ if bash "$CHECK" "$T" >/dev/null 2>&1; then
86
+ echo "✅ ⑤-P card newest → exit 0"
87
+ else
88
+ echo "❌ ⑤-P card newest → expected exit 0, got 1 (over-blocking: trains --no-verify)"
89
+ bash "$CHECK" "$T" 2>&1 | sed 's/^/ /'
90
+ FAILED=1
91
+ fi
92
+ rm -rf "$T"
93
+
94
+ if [ "$FAILED" -ne 0 ]; then
95
+ echo "SESSION-CLOSE LANES: FAIL — the gate's instrument is miscalibrated"
96
+ exit 1
97
+ fi
98
+ echo "SESSION-CLOSE LANES: PASS (7/7)"
99
+ exit 0
@@ -150,9 +150,24 @@ for f in "${FILES[@]}"; do
150
150
  # S5 — the pipefail-fallback disarm: `... | grep -c ... || echo 0` appends a SECOND line under
151
151
  # `set -o pipefail`, so the later `-gt` integer test becomes a bash error (= false) and the guard
152
152
  # passes silently, with the error going only to stderr. Measured class, 2026-07-26.
153
+ #
154
+ # NARROWED 2026-07-28 after hand-verifying all 9 hits this repo produced: 9/9 were false
155
+ # positives, i.e. the probe was pure noise for its own class, and 100% FP trains dismissal of
156
+ # the one hit that will matter. Two distinct causes, both mechanically reproduced:
157
+ # (a) `a || b || echo 0` was read as a pipeline — the old regex could anchor its `\|` on the
158
+ # SECOND bar of the first `||`. No pipe exists, so no second line can ever be produced.
159
+ # (Every `_mtime() { stat -c %Y … || stat -f %m … || echo 0; }` in the tree was flagged.)
160
+ # (b) a real pipeline whose failing stage emits NOTHING (`… | jq -r … || echo 0`) — the
161
+ # fallback then supplies the only line, which is exactly the intended behavior.
162
+ # The disarm needs BOTH a real pipe AND a final stage that emits regardless of upstream failure
163
+ # — a counter (`grep -c`, `wc`). That is the measured shape: `find … | grep -c . || echo 0`
164
+ # yields "9\n0" and the `-gt` guard goes silent. Verified as a known pair (both directions) in
165
+ # scripts/test_degrade_scan_shell_probes.sh; narrowing without that anchor would just trade a
166
+ # noisy probe for a blind one.
153
167
  while IFS= read -r m; do
154
- emit "$f" "${m%%:*}" "S5:pipefail-fallback(sh)" "\`|| echo 0\` fallback on a pipeline — under \`set -o pipefail\` this yields a multi-line value whose integer comparison errors out and silently passes the guard; split the pipeline and sanitize to an integer"
155
- done < <(grep -nE '\|[^|]+\|\|[[:space:]]*echo[[:space:]]+[\"'"'"']?0' "$f" 2>/dev/null \
168
+ emit "$f" "${m%%:*}" "S5:pipefail-fallback(sh)" "\`|| echo 0\` fallback on a pipeline ending in a counter (grep -c/wc) that stage emits even when an upstream stage fails, so under \`set -o pipefail\` the value gains a SECOND line, the integer comparison errors out, and the guard passes silently; split the pipeline and sanitize to an integer"
169
+ done < <(grep -nE '[^|]\|[[:space:]]*([a-z]+[[:space:]]+)*(grep[^|]*-c|wc)[^|]*\|\|[[:space:]]*echo[[:space:]]+[\"'"'"']?0' "$f" 2>/dev/null \
170
+ | grep -vE '^[0-9]+:[[:space:]]*#' \
156
171
  | grep -vE '#[[:space:]]*noqa[:[:space:]]*degrade')
157
172
  fi
158
173
 
@@ -1,32 +0,0 @@
1
- ---
2
- name: context-bridge-dispatch
3
- description: >-
4
- DEPRECATED — merged into agent-composer Step 3-a (2026-06-02).
5
- Context Card injection (N≤2 standard / N≥3 Registry mode) + coordination-overhead budget + Focus Mode
6
- are now part of agent-composer Step 3. Invoke /agent-composer for parallel dispatch.
7
- user-invocable: false
8
- allowed-tools: []
9
- model: sonnet
10
- deprecated: true
11
- deprecated_reason: absorbed into agent-composer Step 3-a
12
- deprecated_date: 2026-06-02
13
- successor: agent-composer
14
- ---
15
-
16
- # context-bridge-dispatch — DEPRECATED
17
-
18
- > **Merged into `agent-composer` Step 3-a (2026-06-02).**
19
- > Context Card injection, Registry mode, coordination-overhead budget, and Focus Mode are now part of agent-composer Step 3.
20
- > Use `/agent-composer` for all parallel dispatch with context injection.
21
-
22
- ## Content preserved at
23
-
24
- `plugins/fh-meta/skills/agent-composer/SKILL.md §Step 3-a` — the live successor.
25
-
26
- > The original pre-merge content is preserved in git history (this stub's earlier revisions); the
27
- > shipped `SKILL_detail.md` archive was removed in the curator shrink (2026-06-16) as redundant with
28
- > git history. No live content lost — the functional content lives in agent-composer Step 3-a.
29
-
30
- ## Done When
31
-
32
- Deprecated — no active execution path. Done When: skill is never directly invoked; all dispatch routes through `/agent-composer` Step 3-a (the successor). This entry satisfies the harness-doctor L2 M-tier requirement for missing Done When (CLAUDE.md §New Skill Creation Pre-Commit Gate).
@@ -1,30 +0,0 @@
1
- ---
2
- name: self-marketing-lint
3
- description: >-
4
- DEPRECATED — merged into harness-doctor --lint mode (2026-06-02).
5
- Language pattern detection (self-marketing, cushion words, version labels) is now Step 3-L of harness-doctor.
6
- Use /harness-doctor --lint instead.
7
- user-invocable: false
8
- allowed-tools: []
9
- model: sonnet
10
- deprecated: true
11
- deprecated_reason: absorbed into harness-doctor Step 3-L (--lint mode)
12
- deprecated_date: 2026-06-02
13
- successor: harness-doctor
14
- ---
15
-
16
- # self-marketing-lint — DEPRECATED
17
-
18
- This skill was absorbed into **harness-doctor** on 2026-06-02. Its self-marketing /
19
- cushion-word / version-brag detection patterns now live in **harness-doctor Step 3-L
20
- (`--lint` mode)**, which carries the canonical baseline.
21
-
22
- **Use instead:**
23
-
24
- ```
25
- /harness-doctor --lint
26
- ```
27
-
28
- Triggers that previously reached this skill (`check FH files`, `remove marketing
29
- language`, `description diet`) now route to harness-doctor Step 3-L. This stub remains
30
- only so old references resolve.