@chrono-meta/fh-gate 2.2.0 → 2.4.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.
- package/.claude/capabilities/adapters/qasp-new-code-anchor.cap +5 -2
- package/.claude/capabilities/adapters/qasp-web-rules.cap +130 -0
- package/.claude/rules/fh_4axis_gate.md +55 -0
- package/.claude-plugin/marketplace.json +2 -2
- package/CLAUDE.md +51 -6
- package/README.ja.md +14 -2
- package/README.ko.md +14 -1
- package/README.md +16 -2
- package/README.zh.md +12 -1
- package/knowledge/shared/harness-core/field_verdict_crossfamily_gate.md +231 -7
- package/knowledge/shared/harness-core/harness_incubator_doctrine.md +215 -1
- package/knowledge/shared/harness-core/ship_readiness_gate.md +168 -1
- package/knowledge/shared/learnings/subagent_invocations_log.yaml +24 -0
- package/package.json +9 -1
- package/plugins/fh-commons/.claude-plugin/plugin.json +1 -1
- package/plugins/fh-meta/.claude-plugin/plugin.json +1 -1
- package/plugins/fh-meta/CHANGELOG.md +110 -0
- package/plugins/fh-meta/skills/auto-decorrelation/SKILL.md +20 -0
- package/plugins/fh-meta/skills/steel-quench/SKILL.md +25 -2
- package/scripts/adapters/fixtures/qasp_web_rules_known_negative.json +7 -0
- package/scripts/adapters/fixtures/qasp_web_rules_known_positive.json +7 -0
- package/scripts/adapters/mate_agent_boundary.sh +27 -7
- package/scripts/adapters/qasp_web_rules.sh +171 -0
- package/scripts/capability_effect_probe.sh +104 -0
- package/scripts/capability_registry_check.sh +69 -3
- package/scripts/relay_channel.sh +151 -6
- package/scripts/selfcheck.sh +18 -0
- package/scripts/target_freeze.sh +239 -0
- package/scripts/test_adapter_lanes.sh +54 -1
- package/scripts/test_marker_axes_run_lanes.sh +19 -0
- package/scripts/test_marker_standpoint_lanes.sh +83 -0
- package/scripts/test_marker_thirdparty_lanes.sh +73 -0
- package/scripts/test_regression_guard_ci_lanes.sh +170 -0
- package/scripts/test_relay_channel_lanes.sh +146 -17
- package/scripts/test_target_freeze_lanes.sh +203 -0
- package/templates/.git-hooks/pre-commit +262 -0
- package/templates/PRE-PUBLISH-CHECKLIST.md +22 -0
- package/templates/regression_guard.sh +32 -4
|
@@ -157,8 +157,12 @@ engine under the other — and the two candidates for "④" are **context-contin
|
|
|
157
157
|
external-grounding**, which currently hold different grades, so the ambiguity is not cosmetic.
|
|
158
158
|
The collision is worse than one file's internal disagreement: **the identities are numbered ①–⑤ and the
|
|
159
159
|
engines are not numbered at all**, so a bare ① in any record is undecidable without its sentence. This
|
|
160
|
-
file shows it — a paragraph enumerating engines sits four lines above
|
|
160
|
+
file shows it — a paragraph enumerating engines sits four lines above `①③⑤ are 🟢, ②④ are 🔵 RC`,
|
|
161
161
|
where those numerals mean *identities*.
|
|
162
|
+
(🟥 That example string was itself stale until 2026-08-17: it still read `③⑤ are 🟢, ①②④ are 🔵 RC`,
|
|
163
|
+
which 632 had already superseded — so the illustration pointed at text no longer in the file.
|
|
164
|
+
Same **in-file half-fix propagation** this document names elsewhere; fixed here, and the grade
|
|
165
|
+
values in an *example* must be re-checked whenever the table moves.)
|
|
162
166
|
|
|
163
167
|
> **Legacy decode (do not delete — session records already use numbers).** Records written before
|
|
164
168
|
> 2026-08-13 say 엔진 ①~④. They decode by the **engine table order above**:
|
|
@@ -672,6 +676,169 @@ Each remedy is a run that leaves an artifact, tracked in `tracks/_meta/identity_
|
|
|
672
676
|
> An identity whose broad path *runs* is not 🔴 ideal-only. Both are 🟡: running, not yet closed. Lesson:
|
|
673
677
|
> do not score an identity by its hardest sub-mechanism — that reads a live-but-incomplete path as zero.
|
|
674
678
|
|
|
679
|
+
### ④ promotion criteria — 이 절이 **없었다는 것** 자체가 첫 발견 (2026-08-17)
|
|
680
|
+
|
|
681
|
+
②(438줄)와 Ⓑ(421줄)는 전용 승급 기준 절을 갖고, ①은 행 안에 인라인으로 갖는다.
|
|
682
|
+
**④만 없었다.** 그리고 이 파일이 ② 절 첫머리에 그 절이 왜 필요한지 이미 적어놨다 —
|
|
683
|
+
*"매 라운드가 바닥부터 기준을 재도출하지 않도록"*. **그 처방이 ④에만 적용되지 않았다.**
|
|
684
|
+
|
|
685
|
+
#### 1. 🟥 유일하게 명시돼 있던 조건은 **다른 명제를 잰다**
|
|
686
|
+
|
|
687
|
+
지금까지 ④에 대해 조건처럼 읽힌 문장은 하나뿐이었다:
|
|
688
|
+
> *"④ file-change ≠ token-introduction — the instrument is a screener, not an adjudicator"*
|
|
689
|
+
|
|
690
|
+
그런데 그 계기(`scripts/digest_landing_check.sh`)가 **자기 헤더에서 스코프를 자백한다**:
|
|
691
|
+
> *"착지 대상 = 공개 FH 자산 + `tracks/`. 비공개 companion store 는 **보지 않는다** …
|
|
692
|
+
> 따라서 **이 계기가 재는 것은 «조직 전체 전파»가 아니라 «허브 내부 착지»다**"*
|
|
693
|
+
|
|
694
|
+
반면 ④가 주장하는 명제는 `fh_three_layer_canon.md` — *"바깥에서 온 것이 **조직 안까지** 착지한다"*.
|
|
695
|
+
⇒ **그 조건을 100% 닫아도 ④의 명제는 한 글자도 안 재진다.** ①이 dominance 를 두 번 측정하고
|
|
696
|
+
«겨냥이 틀렸다»로 판정한 것과 같은 형태이고, ④는 그 판정을 **한 번도 받은 적이 없다**.
|
|
697
|
+
|
|
698
|
+
#### 2. 🟥 그리고 구조적으로 도달 불가다 — P1 과 같은 형태 (**이 파일 안에서는** 지목된 적 없다)
|
|
699
|
+
|
|
700
|
+
이 파일의 residency 규율(§Ⓑ promotion criteria 3)이 못 박는다:
|
|
701
|
+
> *"조직 환경 실적은 **증언으로 남고 측정으로 세지 않는다.** residency 때문에 이 파일에서
|
|
702
|
+
> 검증할 수 없고, 검증 못 하는 것을 숫자에 넣으면 그 숫자 전체가 못 쓰게 된다"*
|
|
703
|
+
|
|
704
|
+
그런데 **④는 대상이 조직인 유일한 행**이다. ⇒ 🟢가 요구하는 «구체적 실적 아티팩트»를
|
|
705
|
+
**이 파일 안에서는 원리적으로 만들 수 없다.** ②의 P1이 «mtime은 위조 가능 → 어떤 런도 만족
|
|
706
|
+
불가»였던 것과 정확히 같은 구조이며, P1 은 지목되어 수리됐고 **이 파일 안에서는** ④ 에 대한
|
|
707
|
+
같은 지목이 없다. ⚠️ **범위 제한이다** — 이 파일을 읽어서 내린 판단이고, 전 코퍼스 부재 스캔
|
|
708
|
+
(검색어·컨트롤 동반)은 **안 돌렸다**. 「아무도 지목한 적 없다」로 넓혀 읽지 마라.
|
|
709
|
+
|
|
710
|
+
#### 3. 이미 충족돼 있을 가능성 — 못 읽는 지점이 한 단어로 특정된다
|
|
711
|
+
|
|
712
|
+
조직 착지는 **운영자 증언으로 존재한다 — 이 세션이 검증한 것이 아니고, §2 대로 이 파일에서는
|
|
713
|
+
검증 불가다**(전부 residency 경계 안이라 종류만 적는다): 정기 조직 보고 채널로의 상시 착지 ·
|
|
714
|
+
외부 발표 채택과 그 산출이 다시 FH 기계의 근거로 인용됨(**증언 — 「관통」으로 단정하지 않는다**) ·
|
|
715
|
+
조직 내 정식 공개 1건.
|
|
716
|
+
|
|
717
|
+
🟥 **라벨을 반드시 붙인다.** Ⓑ 행이 같은 처리를 한다 — *"실적 열거는 **운영자 증언** + 실측
|
|
718
|
+
2건이고 … **증언으로 표기하고 측정으로 세지 않는다**"*. 증인이 없는 관통을 「관통」으로 적으면
|
|
719
|
+
다음 라운드가 이 절을 «④는 사실상 충족» 의 근거로 인용한다. 그게 이 파일이 반복해 자책한
|
|
720
|
+
인용 훼손 경로다.
|
|
721
|
+
|
|
722
|
+
> **못 읽는 지점 = «as ONE pipeline».** 조건이 「착지했나」가 아니라
|
|
723
|
+
> **「하나의 계기로 관통을 증인할 수 있나」**를 요구하는데, 그 증인 계기가 스스로 조직을
|
|
724
|
+
> 스코프 밖으로 선언했다. 계기 헤더도 절반 자백해뒀다 — *"«안 닫힌다»가 아니라
|
|
725
|
+
> **«닫히는데 증인이 없다»**"*, *"**파이프라인은 그날 실제로 관통했다**"*.
|
|
726
|
+
|
|
727
|
+
#### 4. 제안하는 기준 — 막힌 것은 측정이 아니라 **측정의 위치**다
|
|
728
|
+
|
|
729
|
+
```
|
|
730
|
+
지금 조직 데이터를 공개 레포로 가져와 재려 한다 → residency 가 막는다 (정당하게)
|
|
731
|
+
대안 계기를 데이터가 있는 쪽으로 옮긴다 → 조직 밖으로 나오는 것을 최소화한다
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
🟥 **초판이 여기서 두 번 틀렸고, 적대검증이 커밋 전에 잡았다. 그 정정을 남긴다.**
|
|
735
|
+
|
|
736
|
+
**틀린 것 ①** — 초판은 *"**판정만** 넘어오므로 residency 를 안 깬다"* 고 적었다. 그런데 §2 가
|
|
737
|
+
도달 불가의 **근거로** 인용한 것이 Ⓑ-3 의 *"조직 실적은 … 이 파일에서 **검증할 수 없다**"* 다.
|
|
738
|
+
**조직에서 나온 판정을 이 파일 계열의 공개 기록에 넣는 것**이 곧 그 규칙이 금지한 행위다 —
|
|
739
|
+
블로커로 인용한 규칙을 처방이 우회했다. 순환이 아니라 **자기무효화**다.
|
|
740
|
+
|
|
741
|
+
**틀린 것 ②** — 초판은 챔버 순서 증인(*"해시만 적는다, 본문 유출 0"*)을 유비로 들었다.
|
|
742
|
+
**성립하지 않는다**:
|
|
743
|
+
```
|
|
744
|
+
챔버 증인이 넘기는 것 해시 → 원문 N 개 중 무엇인지에 대해 **0 비트**
|
|
745
|
+
초판의 P4-1 이 넘기는 것 후보별 PASS/FAIL → 후보 N 개에 대해 **N 비트**
|
|
746
|
+
```
|
|
747
|
+
「조직이 이 프런티어 항목을 도입했다/안 했다」는 **그 자체가 조직 정보**다.
|
|
748
|
+
*"원본은 한 바이트도 안 나온다"* 는 **바이트 수를 정보량과 혼동한 문장**이었다. 유비를 철회한다.
|
|
749
|
+
|
|
750
|
+
**그래서 좁힌다.** 조직 밖으로 나오는 것은 **집계된 단일 verdict 하나**뿐이다:
|
|
751
|
+
|
|
752
|
+
**P4-1 (mandatory-pass)** — 조직 환경 클론에서 착지 계기가 실행되고, 공개 쪽으로는
|
|
753
|
+
**집계된 단일 verdict(PASS/FAIL 하나)** 만 기록된다.
|
|
754
|
+
🟥 **후보별 판정·건수·비율을 공개 쪽에 쓰는 것은 금지한다** — N 비트가 새는 경로다.
|
|
755
|
+
🟥 그리고 residency 예외 절차를 그대로 탄다(`CLAUDE.md §Field-Harness Diagnostic`):
|
|
756
|
+
**명시적 운영자 승인 + gitignored 감사노트**. *"«이게 충분히 sanitize 됐나»는 세션이 혼자
|
|
757
|
+
내리는 판단이 아니다"* — 이 조건이 없으면 P4-1 은 미충족이다.
|
|
758
|
+
|
|
759
|
+
**P4-1 의 선행조건 — 지금 둘 다 미충족이고, 그걸 적는 것이 이 절의 값이다**
|
|
760
|
+
1. 🟥 **잴 대상이 조직 클론에 존재해야 한다.** 계기 인터페이스는
|
|
761
|
+
`digest_landing_check.sh <digest.md> [target ...]` 인데, digest 산출물은
|
|
762
|
+
`tracks/_meta/frontier_digest_<날짜>.md` 이고 **`tracks/**` 는 gitignored**, 생성은
|
|
763
|
+
**이 머신의 launchd 매일 09:00** 이다. ⇒ **조직 클론에는 잴 digest 가 구조적으로 없다.**
|
|
764
|
+
조직 쪽 생성 경로가 생기거나 공개 digest 를 반입할 수 있어야 한다.
|
|
765
|
+
2. 🟥 **실행 주체를 이름으로 적어야 한다.** 없으면 P4-1 은 **「미도달」로 표기하고 승급 기준으로
|
|
766
|
+
세지 않는다** — 이름 없는 실행 주체는 P1 이 «어떤 런도 만족 불가» 였던 것과 같은 형태다.
|
|
767
|
+
|
|
768
|
+
**P4-2 (measured)**: 그 verdict 가 known-pair 를 가른다 — 착지한 건과 착지 안 한 건을 실제로
|
|
769
|
+
구분. 컨트롤 없는 PASS 는 이 조건을 만족시키지 않는다.
|
|
770
|
+
|
|
771
|
+
#### 5. 🟥 남는 잔여 — 닫는 게 아니라 한 칸 올리는 것이다
|
|
772
|
+
|
|
773
|
+
그 판정은 **비저자가 볼 수 없는 환경에서 나온 자기신고**다. 챔버 증인이 «저자를 신뢰하지 않는
|
|
774
|
+
기록»을 요구한 것과 **같은 문제가 조직 경계에서 재발한다**. 그래서 이 기준은 ④를 «완전히
|
|
775
|
+
닫는다»가 아니라 **«증언 → 측정으로 한 칸 올린다»**이고, 그 한계를 조건에 같이 적는다.
|
|
776
|
+
비저자 실증이 가능해지는 시점(조직 내 다른 운영자가 그 계기를 돌리는 것)이 다음 칸이다.
|
|
777
|
+
|
|
778
|
+
**강등 조건 — 이 절이 승급만 적고 강등을 안 적으면 Ⓑ 절의 목적을 못 따른다**
|
|
779
|
+
(Ⓑ 절 자기 규정: *"«어떻게 올라가나»가 아니라 «**무엇이 이 행을 내릴 수 있나**»"*):
|
|
780
|
+
- **D4-1**: P4-1 의 verdict 가 **known-pair 를 못 가르면**(착지한 건과 안 한 건이 같은 값을 받으면)
|
|
781
|
+
④는 **🔵 로 되돌린다.** 판별력 없는 PASS 는 측정이 아니다
|
|
782
|
+
- **D4-2**: 선행조건 1·2 중 하나라도 **다시 미충족이 되면**(조직 쪽 digest 경로가 사라지거나
|
|
783
|
+
실행 주체가 없어지면) ④는 **「미도달」로 되돌아간다** — 한 번 통과한 것으로 고정되지 않는다
|
|
784
|
+
- **D4-3**: residency 예외 절차(운영자 승인 + 감사노트) 없이 조직 판정이 공개 쪽에 기록되면
|
|
785
|
+
그 기록은 **무효이고 ④는 강등된다.** 이건 등급 문제가 아니라 규율 위반이다
|
|
786
|
+
|
|
787
|
+
#### 6. 부수 — 이 절을 쓰면서 확인된 stale 2건
|
|
788
|
+
|
|
789
|
+
- 🟥 **207·238줄의 «zero callers» 처방은 stale 이 아니다 — 초판이 그렇게 적었고 틀렸다.**
|
|
790
|
+
`scripts/selfcheck.sh:617` 앵커 루프에 들어간 것은 **`--self-test` 레인뿐**이고, 레포 전체에서
|
|
791
|
+
`digest_landing_check.sh <digest.md>` 를 **인자와 함께 부르는 프로덕션 호출부는 0개**다.
|
|
792
|
+
selfcheck 주석 자신이 그렇게 말한다 — *"lanes existed and ran only when a human typed the
|
|
793
|
+
command"*. ⇒ **「배선됐다」가 다른 배선이었다**: 계기의 self-test 는 도는데 계기 자체는 아무도
|
|
794
|
+
안 부른다. **그리고 이 0 은 §4 P4-1 의 미충족 선행조건이다** — 공개 레포에서조차 실행 경로가
|
|
795
|
+
없는 계기를 조직 클론에서 돌린다고 쓸 수 없다. (나머지 절반 «네 분기 앵커링»은 **미확인**.)
|
|
796
|
+
- **160줄**이 옛 등급(`③⑤ are 🟢, ①②④ are 🔵`)을 **현재형 예시**로 인용한다. 632줄이 이미
|
|
797
|
+
갱신했다. 이 파일이 스스로 이름 붙인 **파일 내부 half-fix 전파 결함**의 재발이다.
|
|
798
|
+
|
|
799
|
+
### §Gate-consequence 의 일관성 — 자백은 적혀 있고 처분은 안 됐다 (2026-08-17)
|
|
800
|
+
|
|
801
|
+
607–614줄이 **스스로** 이렇게 적어놨다:
|
|
802
|
+
> *"⑤ 는 🟢 on `intent-routing probe 94%` — **a self-measurement, not a head-to-head** …
|
|
803
|
+
> The inconsistency is real and it is **the gate's, not ②'s** … Resolving that is a **separate
|
|
804
|
+
> change** to the status definitions — flagged here, **not silently settled**."*
|
|
805
|
+
|
|
806
|
+
**그 «separate change» 가 오지 않았다.** 실측하면 **6행 중 4행이 비일관**이다:
|
|
807
|
+
```
|
|
808
|
+
Ⓑ 일관 적용 만족 — 282줄이 "§Gate consequence 를 **면제 없이 그대로 만족**한다" 고 명시
|
|
809
|
+
③ 일관 적용 보유 (moat 3–4 family blind · HITL 8/8)
|
|
810
|
+
─────────────────────────────────────────────────
|
|
811
|
+
① 비일관 예외를 정식 취득 (92-99줄 — 사전등록 2회 측정 후 미성립. 절차는 밟았다)
|
|
812
|
+
② 비일관 **미결** — 607-614 자백이 "②를 면제할지 ⑤를 재측정할지" 를 안 정했다
|
|
813
|
+
⑤ 비일관 미보유인 채 🟢 ← 자백의 대상
|
|
814
|
+
④ 비일관 언급조차 없음
|
|
815
|
+
```
|
|
816
|
+
🟥 **초판이 여기서 «6행 중 일관 적용된 행이 없다» 고 적었는데, 바로 아래 자기 표가 그걸
|
|
817
|
+
반증했다**(Ⓑ 만족 · ③ 보유). 적대검증이 잡았고 정정한다. 그리고 초판은 ②를 **「면제」로 확정
|
|
818
|
+
표기**했는데, 자백 원문은 **미결**이다 — 절의 결론(«아무것도 정하지 않는다»)과 표가 어긋나 있었다.
|
|
819
|
+
🟥 **이건 오늘 이 저장소가 반복해 만난 «미측정을 0으로 접었다»와 다른 형태다** — 접힘이 아니라
|
|
820
|
+
**적용 누락**이다. 그리고 자백이 문서에 적혀 있는데 안 고쳐진 것은 「몰랐다」가 아니라
|
|
821
|
+
**「알고 미뤘다」**라서, 다음 라운드가 그 자백을 「이미 인지된 사항」으로 읽고 또 넘길 위험이 크다.
|
|
822
|
+
|
|
823
|
+
**처분(운영자 결정 필요, 여기서 확정하지 않음)** — 둘 중 하나여야 하고 셋째는 없다:
|
|
824
|
+
- **(A) §Gate-consequence 가 모든 🟢 를 구속한다** ⇒ ⑤ 는 과대 채점이고 재측정 대상이다
|
|
825
|
+
- **(B) advisory 다** ⇒ ②·④ 를 거기에 묶어서는 안 되고, ① 이 받은 «예외»는 애초에 필요 없었다
|
|
826
|
+
|
|
827
|
+
⚠️ 이 절은 **자백을 결정으로 바꾸지 않는다.** 지금 하는 것은 「미뤄졌다는 사실 자체를 기록해서
|
|
828
|
+
다음 라운드가 그것을 인지된 사항으로 소비하지 못하게」 하는 것뿐이다.
|
|
829
|
+
|
|
830
|
+
🟥 **그런데 그것만으로는 이 절이 자기가 진단한 실패를 반복한다 — 적대검증 지적, 수용한다.**
|
|
831
|
+
607-614줄의 자백도 **이 파일의 산문**이었고, 그 매체로 **이미 한 번 실패했다**(그래서 이 절이
|
|
832
|
+
있다). 같은 매체에 한 번 더 적으면서 앵커·기한·소유자를 안 붙이면 결과가 같다.
|
|
833
|
+
`CLAUDE.md §Mechanization Boundary` 가 **채널(«기록이 있는가»)은 기계화 대상**이라고 정한다.
|
|
834
|
+
|
|
835
|
+
⇒ **파일 밖 앵커를 건다**: 세션 카드(`tracks/_meta/reference_next_session_starter.md`)의
|
|
836
|
+
🧵 블록에 **«⑤ dominance 일관성 — 운영자 결정 대기 (제기 2026-08-17)»** 를 등재한다.
|
|
837
|
+
카드는 매 세션 시작에 읽히고 이 파일은 안 읽힌다 — 그게 차이다.
|
|
838
|
+
🟥 **이 등재가 없으면 이 절은 자백의 재생산일 뿐이다.**
|
|
839
|
+
|
|
840
|
+
---
|
|
841
|
+
|
|
675
842
|
## For a field harness (e.g. pmh, qasp)
|
|
676
843
|
Same gate, its own identities. A field harness ships to its team when its identity checklist is all-green,
|
|
677
844
|
certified by a **실증상세 (demonstration-detail) doc in that harness's own repo** — the QA certificate
|
|
@@ -2182,3 +2182,27 @@
|
|
|
2182
2182
|
outcome: accepted
|
|
2183
2183
|
evidence: "tool_uses 25(계기 생존 — 카드가 경고한 `tool_uses: 0` 아님). **4/4 앵커 생존**, 매번 대응 레인만 적색(S1→2건·S2→1건·S3→2건·B1→known-pair 2건), 무관 25~28개는 통과 → 과결합 0. 복원 후 29 passed 재확인, 트리 clean. 🟥 substring 8행은 **전부 ✅ 로 판정했는데 코덱스와 갈렸고 이쪽이 졌다** — 「뚫리는 입력을 제시 못 함」을 판별력 있음으로 읽었으나, 그 단언이 *주장*하는 것(«범위 밖 보고가 났다»)은 파일명만으로 증명되지 않는다. **없음을 증명 못 함 ≠ 판별력 있음**"
|
|
2184
2184
|
cost: 135k tokens
|
|
2185
|
+
- date: 2026-08-18
|
|
2186
|
+
agent: Explore ×4 (isolated) — AX-레디 착수 전 정찰(FH 대상동결 선행자산 · qasp 해석기 어휘 · D2 스캐너 배선 · D3ⓑ 용어 채널 · B5 상태 어휘 · 호출부 0 좌표)
|
|
2187
|
+
purpose: "재발명 방지 + 좌표 확정. 착수 전 «이미 있나» 를 기계로 먼저 묻는다(오늘 이 레포에서 재발명이 한 번 났었다)"
|
|
2188
|
+
outcome: partial
|
|
2189
|
+
evidence: "6축 정찰을 4발주로 묶음(각 대상 지문 `target_freeze.sh verify` 로 시작). **정확했던 것**: 대상동결 선행자산 스캔이 «기계 없음 + 실패 2종 문서화» 를 짚어 3번째 시도의 설계를 결정 · D2 가 `bug_report.py` 호출부 0을 컨트롤 동반으로 확정 · B5 가 `rer_from_act2` 를 «어휘 매핑 어댑터 레퍼런스» 로 지목(재발명 회피) · 근거표 A3 의 팬텀 인용 `PEER_ABSENT` 발견. 🟥 **틀린 것 2건, 둘 다 내가 직접 재현해서 걸렀다**: ⓐ 「`_CAUSE_PLAIN` 커버리지 게이트가 FAIL 레인 4종을 놓친다」 → 그 4종은 `StepEvidence.triage` 가 아니라 이슈-후보 dict 로 가고 소스 주석이 이미 그렇게 갈라놨다(오탐) ⓑ 「`env_cols_source` 가 존재하지 않는다」 → 7히트 실재(주석이 말한 건 *다른 모듈*). ⇒ 정찰 산출은 소스로 닫히기 전엔 좌표가 아니다"
|
|
2190
|
+
cost: ~309k tokens (4건 합)
|
|
2191
|
+
- date: 2026-08-18
|
|
2192
|
+
agent: general-purpose (isolated) — qasp 호출부 0/불일치 스캐너 제작
|
|
2193
|
+
purpose: "«완성된 층 + 호출자 없음» 이 하루 4회 났다 — stdlib ast 기반 계기를 known-pair 로 세우고 전수 1회"
|
|
2194
|
+
outcome: accepted
|
|
2195
|
+
evidence: "**known-pair 양성 2/2 · 음성 5/5**(음성은 호출자 *경로까지* 대조). 전수 1024심볼 · ⓐ162(엄격 32)·ⓑ207·UNDECIDABLE 73. 🟥 **자기 오탐 2계열을 스스로 잡아 고쳤다**: `same_module_refs` 가 import 링크를 요구해 구조적으로 항상 0(→엄격 ⓐ 162→32) · `DeviceAdapter` 덕타이핑 미검출. 진양성 손검증 1건(`RuleAutoExpansionGate` — 외부 참조가 주석 2줄, 그 이름은 **존재하지 않는 철자**). ★ **`target_freeze.sh` 의 첫 실사용이 여기서 났다** — 회수 시 `WRONG-TARGET`(발주 중 내가 커밋 3건 투입), 위임분이 stale 판정을 안 들고 오고 현재 트리에서 전량 재실행. 미해결 자백: 손검증 1건뿐 · 미검출 미측정 · CI 미배선"
|
|
2196
|
+
cost: 167k tokens
|
|
2197
|
+
- date: 2026-08-18
|
|
2198
|
+
agent: codex/gpt-5.5 (cross-family sidecar) — FH `target_freeze.sh` 게이트 적대검증
|
|
2199
|
+
purpose: "감사 대상 동결 게이트의 fail-open / 오탐 / 셸 이식성 — 재현 명령 필수"
|
|
2200
|
+
outcome: accepted
|
|
2201
|
+
evidence: "**6건, 전부 재현 명령 동반, 내가 직접 재현해 6/6 확인.** S급 3건이 **fail-open**(`_sha` 가 `|awk` 로 rc 소실 · `ls-files -o` 실패가 파이프에 먹힘 · 라벨 문자치환 충돌로 **핀한 적 없는 라벨이 MATCH**) + A급 2(서브모듈·심볼릭링크 미검출) + 과탐 1(빈 커밋). 🟥 **레인 11/11 초록인 상태에서 전부 뚫렸다** — 컨트롤 있음 ≠ 판별력 있음. 전부 수리 + 레인 고정"
|
|
2202
|
+
cost: ~40k tokens
|
|
2203
|
+
- date: 2026-08-18
|
|
2204
|
+
agent: agy/gemini (cross-family sidecar, 2번째 계열) — 같은 게이트, **다른 축** 요구
|
|
2205
|
+
purpose: "codex 지적 목록을 먼저 주고 «그 밖의 축»(동시성·env·거짓 안심·인코딩)을 요구 — 한 계열에 몰면 같은 사각이 남는다"
|
|
2206
|
+
outcome: accepted
|
|
2207
|
+
evidence: "**6건 · codex 와 겹친 지적 0.** 최상위는 `GIT_DIR`/`GIT_WORK_TREE` 가 `git -C` 를 이긴다 — **엉뚱한 레포를 재고도 «동결했다» 고 보고**한다(계기가 대상을 틀리는 형태). 그 외 untracked **실행 비트** 미검출(이 레포가 이미 데인 축) · TOCTOU «유령 지문» · 미초기화 서브모듈은 `foreach` 가 건너뜀 · `---` 구분자 경계 · `foreach` 의 `;` rc 소실. 전부 수리, 레인 11→28. ⇒ **계열 분리가 값을 냈다** — 이 6건은 codex 를 한 번 더 돌려서는 안 나온다"
|
|
2208
|
+
cost: ~35k tokens
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chrono-meta/fh-gate",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "FH runtime adapters — run FH governance, skills, and agents via Claude or Codex with machine-parseable gates.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -84,6 +84,9 @@
|
|
|
84
84
|
"scripts/adapters/gstack_content_safety.sh",
|
|
85
85
|
"scripts/adapters/mate_agent_boundary.sh",
|
|
86
86
|
"scripts/adapters/qasp_new_code_anchor.sh",
|
|
87
|
+
"scripts/adapters/qasp_web_rules.sh",
|
|
88
|
+
"scripts/adapters/fixtures/qasp_web_rules_known_positive.json",
|
|
89
|
+
"scripts/adapters/fixtures/qasp_web_rules_known_negative.json",
|
|
87
90
|
"scripts/test_adapter_lanes.sh",
|
|
88
91
|
"scripts/test_fh_gate_regressions.sh",
|
|
89
92
|
"templates/local_fh_context.md",
|
|
@@ -111,6 +114,8 @@
|
|
|
111
114
|
"scripts/tier_census_grep.sh",
|
|
112
115
|
"scripts/test_marker_floor_lanes.sh",
|
|
113
116
|
"scripts/test_marker_crossfamily_lanes.sh",
|
|
117
|
+
"scripts/test_marker_standpoint_lanes.sh",
|
|
118
|
+
"scripts/test_marker_thirdparty_lanes.sh",
|
|
114
119
|
"scripts/test_marker_axes_run_lanes.sh",
|
|
115
120
|
"scripts/test_env_purity_lanes.sh",
|
|
116
121
|
"scripts/.env_purity_tokens.defaults",
|
|
@@ -127,6 +132,8 @@
|
|
|
127
132
|
"scripts/test_relay_channel_lanes.sh",
|
|
128
133
|
"scripts/fh_session_load.sh",
|
|
129
134
|
"scripts/branch_claim.sh",
|
|
135
|
+
"scripts/target_freeze.sh",
|
|
136
|
+
"scripts/test_target_freeze_lanes.sh",
|
|
130
137
|
"scripts/test_branch_claim_lanes.sh",
|
|
131
138
|
"scripts/hook_source_lib.sh",
|
|
132
139
|
"scripts/test_hook_source_gate_lanes.sh",
|
|
@@ -135,6 +142,7 @@
|
|
|
135
142
|
"templates/degrade_direction_scan.sh",
|
|
136
143
|
"templates/.git-hooks",
|
|
137
144
|
"templates/regression_guard.sh",
|
|
145
|
+
"scripts/test_regression_guard_ci_lanes.sh",
|
|
138
146
|
"templates/predelete_check.sh",
|
|
139
147
|
"templates/PRE-PUBLISH-CHECKLIST.md",
|
|
140
148
|
"scripts/degrade_direction_scan.sh",
|
|
@@ -10,6 +10,116 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
|
|
10
10
|
|
|
11
11
|
## Plugin Level
|
|
12
12
|
|
|
13
|
+
### [2.4.0] — 2026-08-18
|
|
14
|
+
|
|
15
|
+
🟥 **BREAKING (gate) ①**: the Axes 2–3 marker's **`standpoint:` and `thirdparty:` fields are now
|
|
16
|
+
validated by value**, not merely by presence (`validate_standpoint_leg` / `validate_thirdparty_leg`
|
|
17
|
+
in `templates/.git-hooks/pre-commit`). A marker carrying free prose where the closed enum is
|
|
18
|
+
required, a degrade value with **no substantive grounds on the same line**, or **more than one**
|
|
19
|
+
line of either field, now **blocks the commit**.
|
|
20
|
+
- **Remedy**: use the enum. `standpoint: tier1b(<harness>) — <what you read>` ·
|
|
21
|
+
`standpoint: not-applicable — <what you checked to conclude no target exists>` ·
|
|
22
|
+
`thirdparty: checked(<what prior art you searched>)`. The hook prints the accepted forms.
|
|
23
|
+
- **Why**: presence-only checking catches silence but not a **confident wrong answer** — measured on
|
|
24
|
+
the marker corpus, 4 markers used the enum correctly while **2 wrote free prose about peer-session
|
|
25
|
+
contact** and matched no enum member at all (the field-canon failure this repo already names:
|
|
26
|
+
normalizing a harness term into a general concept).
|
|
27
|
+
|
|
28
|
+
🟥 **BREAKING (gate) ②**: **Axis 1 (`regression-guard.yml`) had never actually run** — an
|
|
29
|
+
instrument error was rendering **green**. It now runs, so a repo whose Axis 1 check was
|
|
30
|
+
"passing" may go **red on its first real execution**.
|
|
31
|
+
- **Remedy**: read the actual guard output; the failures it now reports were always there.
|
|
32
|
+
- **Why**: the sample was 5/5 instrument-errors-as-green. A check that cannot fail is not a check.
|
|
33
|
+
|
|
34
|
+
🟥 **BREAKING (gate) ③**: `scripts/selfcheck.sh` now executes **`test_target_freeze_lanes.sh`**
|
|
35
|
+
(28 lanes) as part of the standard run. A consumer whose `selfcheck` was green may see new output,
|
|
36
|
+
and a genuinely broken environment (no `shasum`/`sha256sum`) now surfaces there instead of silently.
|
|
37
|
+
- **Remedy**: the lanes are self-contained (`mktemp` fixtures, no network). A missing hash tool is a
|
|
38
|
+
real finding, not a lane defect — the gate it anchors fails closed without one.
|
|
39
|
+
- **Why**: `lane-runner` flagged the suite as having **no runner** — *"a suite nothing executes is
|
|
40
|
+
prose."* The author of the lanes had not wired them.
|
|
41
|
+
|
|
42
|
+
**Added**
|
|
43
|
+
- `scripts/target_freeze.sh` + `scripts/test_target_freeze_lanes.sh` — **audit target freeze**.
|
|
44
|
+
Pin a target repo's content-addressed fingerprint before dispatching an audit; verify on return;
|
|
45
|
+
`WRONG-TARGET` (rc 1) invalidates that round's verdict wholesale. Third mechanization attempt,
|
|
46
|
+
deliberately routed **around** the two failures recorded in `steel-quench/SKILL.md` (a hook
|
|
47
|
+
advisory that fired on 100% of markers; a `base-SHA + diff-line-count` fingerprint invariant under
|
|
48
|
+
in-place edits and blind to untracked files).
|
|
49
|
+
🟥 **Cross-family review found 3 fail-open paths while its lanes were 11/11 green** — `_sha`
|
|
50
|
+
losing `shasum`'s rc through `| awk`, `git ls-files -o` failure swallowed by a pipeline, and a
|
|
51
|
+
label-sanitizing collision that returned `MATCH` for a label **never pinned**. All reproduced by
|
|
52
|
+
hand, all fixed, lanes 11 → 28.
|
|
53
|
+
- `④ promotion-criteria` section in the identity gate (its absence was itself the first finding).
|
|
54
|
+
- Incubator routing: `net-new` failure now routes to **`CURATED`** (hand the maker the prior-art
|
|
55
|
+
list and the delta it does not cover) instead of `KILL`; judgment-shaped candidates route to
|
|
56
|
+
`NOT-APPLICABLE`. KILL survives for measured precision-shortfall, hub-state dependence, and
|
|
57
|
+
inability-to-run.
|
|
58
|
+
|
|
59
|
+
**Fixed**
|
|
60
|
+
- `relay_channel` registration-time checker had a **0-line call site** — the gate existed as 42KB
|
|
61
|
+
of code that nothing invoked.
|
|
62
|
+
- `standpoint: §7` closed its `not-applicable` definition (`Q0` target-class resolution, which can
|
|
63
|
+
return **more than one** target, each owing its own tier).
|
|
64
|
+
- `mate-agent-boundary` adapter: its **calibration pair was dead** — the peer entry point hardcodes
|
|
65
|
+
its target and ignores `$1`, so the positive and negative arms were measuring **the same file**.
|
|
66
|
+
The negative arm's green was not discrimination; the live target simply happened to be failing.
|
|
67
|
+
- `package.json files[]` omitted two scripts that shipped documentation instructs consumers to run
|
|
68
|
+
(a phantom pointer inside a gate instruction).
|
|
69
|
+
|
|
70
|
+
### [2.3.0] — 2026-08-17
|
|
71
|
+
|
|
72
|
+
🟥 **BREAKING (gate) ①**: the capability effect-probe (`M6`) now watches **directory existence and
|
|
73
|
+
non-regular nodes**, not files only. A `.cap` declaring `writes: read-only` whose entry point
|
|
74
|
+
creates an **empty directory**, a **symlink**, or a **fifo/socket/device node** now returns
|
|
75
|
+
`VIOLATION` where it previously returned `✅ VERIFIED`. Registration of such a capability
|
|
76
|
+
**blocks**.
|
|
77
|
+
- **Remedy**: declare the real value (`write-local` / `write-remote`), or stop creating the node.
|
|
78
|
+
The probe prints which surface changed.
|
|
79
|
+
- **Why**: `_snapshot()` used `find -type f`, so **empty directories were invisible** — git does not
|
|
80
|
+
track them, so they are absent from the isolated-clone sandbox too. Measured with a 3-arm
|
|
81
|
+
known-pair: write-file-to-new-path → 1, write-file-to-existing-dir → 1, **empty-dirs-only → 0**
|
|
82
|
+
(the false green). A cross-family review then found the same class still open one layer down:
|
|
83
|
+
`ln -sf /etc/passwd link` and `mkfifo pipe` **also passed** after the directory axis was added.
|
|
84
|
+
Both are now caught; symlinks are compared **by target**, since existence alone makes
|
|
85
|
+
`ln -sf other link` look like no change.
|
|
86
|
+
- ⚠️ **Named residual, unchanged**: metadata-only writes (`chmod`, xattr, hardlink topology) and
|
|
87
|
+
empty directories **under `.git`** remain invisible. And the probe **still cannot discriminate an
|
|
88
|
+
adapter-class capability** — its outside-watch is a temp canary plus `$HOME`, while an adapter by
|
|
89
|
+
definition runs in the peer tree. That value stands on hand measurement, not on the probe.
|
|
90
|
+
|
|
91
|
+
🟥 **BREAKING (gate) ②**: writing `ⓓ=→thirdparty` in the Axes 2–3 marker now **requires a non-empty
|
|
92
|
+
`thirdparty:` line**. A marker with the pointer but no target **blocks the commit**.
|
|
93
|
+
- **Remedy**: the hook prints the accepted forms —
|
|
94
|
+
`checked(<what was surveyed>)` · `none-found(<what was searched>)` · `UNKNOWN` · `not-applicable`.
|
|
95
|
+
- **Why**: a pointer at nothing is not a record. Same failure the `ⓑ=→standpoint` guard closed.
|
|
96
|
+
|
|
97
|
+
**Added**
|
|
98
|
+
- `adapter/qasp-web-rules` — a cluster node wrapping a peer harness's web selector-stability rule
|
|
99
|
+
set. Enum `0=CLEAN 1=FINDINGS 2=ARGS 3=ENGINE_ERROR 10=HARNESS_ERROR 20=PEER_ABSENT`, calibration
|
|
100
|
+
pair from **FH-owned fixtures** (offline, deterministic), `writes: write-local` established by
|
|
101
|
+
cold-clone measurement. Registration bar M1–M6: **REGISTRABLE**.
|
|
102
|
+
🟥 **Consumer 0** — declared and callable, nothing calls it yet. Do not round that to "wired".
|
|
103
|
+
🟥 The declared enum is **wider than the peer's documented contract** (`0/1/3`): the underlying
|
|
104
|
+
CLI uses `parser.error()`, argparse exits **2**, and the shell wrapper propagates it verbatim.
|
|
105
|
+
The adapter declares the **real** contract, or an argument mistake renders as "the instrument broke".
|
|
106
|
+
|
|
107
|
+
**Fixed**
|
|
108
|
+
- The adapter's argument validation now runs **before** peer resolution. Previously the **same bad
|
|
109
|
+
call returned different values on different machines** — `ARGS(2)` where the peer was installed,
|
|
110
|
+
`HARNESS_ERROR(10)` where it was not — i.e. the check measured **what is installed on this box**
|
|
111
|
+
rather than **how it was called**. `ARGS` is a statement about the call; `PEER_ABSENT` is a
|
|
112
|
+
statement about the cluster; the two are independent facts.
|
|
113
|
+
- Capability entry points and their calibration fixtures are now in `files[]`. Consumers previously
|
|
114
|
+
received the **declaration without the instrument** — a `.cap` that passes the registration bar
|
|
115
|
+
and then returns `HARNESS_ERROR` inside the tarball.
|
|
116
|
+
|
|
117
|
+
**Note for consumers of the effect-probe**
|
|
118
|
+
If you hold `.cap` files, re-run the probe **before** upgrading: this release changes verdicts for
|
|
119
|
+
the three shapes above. A green result under 2.2.0 is not evidence under 2.3.0.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
13
123
|
### [2.2.0] — 2026-08-17
|
|
14
124
|
|
|
15
125
|
🟥 **BREAKING (gate)**: chamber step 6 now reads `ACTUAL.md`, **not `BUDGET.md`**. An in-flight
|
|
@@ -202,6 +202,26 @@ re-checks** it against the artifact (phantom-quench back-trace) before accepting
|
|
|
202
202
|
source-grounded is **dropped, not judged**. No sidecar-only verdict (no weak-local-judge regression).
|
|
203
203
|
Local 4090 = **canary tier** (evidence-of, never terminal verdict).
|
|
204
204
|
|
|
205
|
+
**Target freeze — a prior drop reason, checked before any of the above (2026-08-17).** Grounding a
|
|
206
|
+
finding against *today's* tree proves nothing if the sidecar reviewed *yesterday's*. Pin before
|
|
207
|
+
dispatch and verify on return:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
bash scripts/target_freeze.sh pin "$REPO" "$ROUND_LABEL" # 발주 직전
|
|
211
|
+
bash scripts/target_freeze.sh verify "$REPO" "$ROUND_LABEL" # 회수 직후
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
`rc 1` = **WRONG-TARGET → drop the whole round's findings**, not individual ones — the round read a
|
|
215
|
+
tree that moved under it, so which findings survive is not decidable from the output. `rc 10` =
|
|
216
|
+
UNKNOWN (could not measure) — that is **not** a pass; re-pin and re-dispatch. Measured trigger: three
|
|
217
|
+
occurrences in one day, one of which was sending a sidecar a **pre-repair diff** and then grounding
|
|
218
|
+
its findings against the repaired tree — every finding "failed to ground", and the instrument, not
|
|
219
|
+
the reviewer, was wrong.
|
|
220
|
+
|
|
221
|
+
🟥 **What this does NOT cover**: §L191's inlined-file pattern. When the prompt carries file contents
|
|
222
|
+
on stdin (the robust form for sidecars that have no file tools), the tree freeze says nothing about
|
|
223
|
+
**what bytes you actually sent**. That binding is still owed and is not claimed here.
|
|
224
|
+
|
|
205
225
|
## Step 6 — Degrade ladder (the intelligent scale-down)
|
|
206
226
|
|
|
207
227
|
**Consent branch first — declined ≠ degraded** (`[[capability_escalation_consent]]`): if the UAP has
|
|
@@ -425,7 +425,8 @@ over **unchanged** code:
|
|
|
425
425
|
`WRONG-TARGET` and stop on mismatch:
|
|
426
426
|
|
|
427
427
|
```bash
|
|
428
|
-
|
|
428
|
+
bash scripts/target_freeze.sh pin "$REPO" "$WAVE_LABEL" # 발주 직전 — 토큰을 프롬프트에 박는다
|
|
429
|
+
bash scripts/target_freeze.sh verify "$REPO" "$WAVE_LABEL" # 회수 직후 — rc 1 이면 WRONG-TARGET
|
|
429
430
|
```
|
|
430
431
|
|
|
431
432
|
An audit that did not pin its target **cannot be counted as a terminating round** — it may have
|
|
@@ -435,7 +436,29 @@ over **unchanged** code:
|
|
|
435
436
|
active — gate-locality on the very fix that was closing a gate-locality gap, caught by the round
|
|
436
437
|
that audited it.
|
|
437
438
|
|
|
438
|
-
> **
|
|
439
|
+
> ✅ **MECHANIZED 2026-08-17 — the residual below is the history, not the current state.**
|
|
440
|
+
> The recurrence condition this paragraph set ("mechanize on the first recurrence") fired **three
|
|
441
|
+
> times in one day**: a cross-family review was sent a **pre-repair** diff · a review's output was
|
|
442
|
+
> truncated with `tail`, losing findings and the pin itself · a scan was followed by an edit that
|
|
443
|
+
> shifted every line number. All three were "did I send / read the tree that is there now?", and
|
|
444
|
+
> the prose rule above was already in place and caught **none** of them (operator-approved as the
|
|
445
|
+
> next session's 1순위, 2026-08-17).
|
|
446
|
+
>
|
|
447
|
+
> `scripts/target_freeze.sh` (lanes: `scripts/test_target_freeze_lanes.sh`, **28/28**) takes the
|
|
448
|
+
> third attempt deliberately **through** the two failures recorded below: it content-addresses
|
|
449
|
+
> `git diff HEAD` (the **patch**, not its line count — so a same-line-count in-place edit is
|
|
450
|
+
> caught, lane A) and hashes untracked files separately (lane B), and it is **not a hook** —
|
|
451
|
+
> two explicit commands the dispatcher runs, so it cannot become the 100%-firing background noise
|
|
452
|
+
> of attempt ①. It refuses to answer at all when `assume-unchanged`/`skip-worktree` is set
|
|
453
|
+
> (exit 10 UNKNOWN, never MATCH), and a **restore-to-original lane returns MATCH** — that arm is
|
|
454
|
+
> the point: without it, "always reports WRONG" would pass every other lane.
|
|
455
|
+
> 🟥 **Scope, stated narrowly**: it freezes the *target tree*, **not the bytes you inlined into a
|
|
456
|
+
> sidecar prompt**. Where files are pasted into the prompt (`auto-decorrelation` §L191 — sidecars
|
|
457
|
+
> often cannot read a tree at all), the inlined content needs its own binding; this script does
|
|
458
|
+
> not provide it.
|
|
459
|
+
>
|
|
460
|
+
> **Named residual (HISTORICAL — superseded by the block above) — the freeze claim was
|
|
461
|
+
> SELF-ATTESTED, and deliberately not
|
|
439
462
|
> mechanized.** Criterion 1 turns on "unmodified since the previous audit", and nothing checks
|
|
440
463
|
> that. Two attempts to mechanize it on the day the rule was written were both wrong: a hook
|
|
441
464
|
> advisory that fired on 100% of markers (noise, and its convergence detector could not match the
|
|
@@ -100,14 +100,34 @@ if [ -n "$TARGET" ]; then
|
|
|
100
100
|
[ -r "$TARGET" ] || _harness_error "대상 경로를 읽을 수 없다: $TARGET"
|
|
101
101
|
fi
|
|
102
102
|
|
|
103
|
-
# peer 트리를 **변이하지 않는다** — cwd 만
|
|
104
|
-
# (기본 대상이 peer 레포 상대경로라 cwd 가 peer 여야 한다.)
|
|
103
|
+
# peer 트리를 **변이하지 않는다** — cwd 만 두고 읽기만 한다.
|
|
105
104
|
# 판정은 파이프를 통과시키지 않는다(PIPE-VERDICT).
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
105
|
+
#
|
|
106
|
+
# 🟥 **초판은 대상을 인자로 넘겼고, peer 는 그 인자를 안 읽는다** (2026-08-18 실측).
|
|
107
|
+
# peer 진입점은 `TARGET=".claude/agents/mate-failure-patcher.md"` 를 **하드코딩**하고
|
|
108
|
+
# `$1` 은 `pass()`/`fail()` 헬퍼 안에서만 쓴다. 그래서 `--known-positive` / `--known-negative`
|
|
109
|
+
# 두 arm 이 **같은 파일**(peer 실물 명세서)을 재고 있었다 ⇒ **캘리브레이션 쌍이 죽어 있었다.**
|
|
110
|
+
# 음성 arm 이 초록이던 것은 판별력이 아니라 **실물이 마침 실패 상태**여서다.
|
|
111
|
+
# 이 픽스처 파일의 헤더가 스스로 경고한 그 상태다 — *"실물을 양성 arm 으로 쓰면 계기의
|
|
112
|
+
# 판정이 남의 편집에 따라 조용히 뒤집힌다"*.
|
|
113
|
+
# ⇒ 대상이 명시되면 **peer 가 기대하는 모양의 임시 트리**를 만들어 거기서 돌린다.
|
|
114
|
+
# peer 코드를 고치지 않고(남의 레포다) peer 의 하드코딩된 상대경로를 만족시키는 방법이다.
|
|
115
|
+
_run_peer() {
|
|
116
|
+
if [ -z "$TARGET" ]; then
|
|
117
|
+
( cd "$PEER_ROOT" && bash "$ENTRY" ) 2>&1
|
|
118
|
+
return $?
|
|
119
|
+
fi
|
|
120
|
+
local stage
|
|
121
|
+
stage=$(mktemp -d) || return 10
|
|
122
|
+
mkdir -p "$stage/.claude/agents" || { rm -rf "$stage"; return 10; }
|
|
123
|
+
cp "$TARGET" "$stage/.claude/agents/mate-failure-patcher.md" || { rm -rf "$stage"; return 10; }
|
|
124
|
+
local o r
|
|
125
|
+
o=$( cd "$stage" && bash "$ENTRY" 2>&1 ); r=$?
|
|
126
|
+
rm -rf "$stage"
|
|
127
|
+
printf '%s\n' "$o"
|
|
128
|
+
return $r
|
|
129
|
+
}
|
|
130
|
+
out=$(_run_peer); rc=$?
|
|
111
131
|
printf '%s\n' "$out"
|
|
112
132
|
|
|
113
133
|
# ── 명시 재매핑 (같은 숫자, 다른 사건 — 전파가 아니다) ───────────────────────
|