@chrono-meta/fh-gate 2.15.0 → 2.15.1

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.
@@ -11,13 +11,13 @@
11
11
  "plugins": [
12
12
  {
13
13
  "name": "fh-meta",
14
- "version": "2.15.0",
14
+ "version": "2.15.1",
15
15
  "description": "New in 2.2.0: BREAKING (gate): chamber step 6 now reads ACTUAL.md, not BUDGET.md — an in-flight chamber run whose actual cost sits in BUDGET.md blocks until the ACTUAL: line moves to tracks/_chamber/<slug>/ACTUAL.md (the runner prints the path). Why: BUDGET.md's pre-verdict hash IS the ordering witness, and step 6 hard-blocked until that same file changed, so every run that reached COMPLETE necessarily mutated a witnessed artifact and verify returned TAMPERED — the chamber's promotion condition was unsatisfiable by construction, not by strictness. Two roles (immutable witness / post-verdict calibration sink) had collided in one file; each was correct alone, so neither side's code showed the conflict. Also: ko-tech-writer Step 2/4-b scans are now calibration-backed (known-pair fixtures + reproducible command, shipped) — discrimination is proven, 'zero residue' is explicitly NOT; chamber lane suite 12 -> 33 including the runner x witness seam no test covered; chamber_run.sh now teaches the two-commit discipline (gate hashes and verdict hash must land in separate commits/PRs — it previously advised the opposite). New in 2.1.0: BREAKING (gate): `crossfamily: declined` in an Axes 2-3 marker now requires grounds naming a record path that RESOLVES on disk — bare `declined`, and `declined` justified by author judgment, are blocked at commit. Remedy: cite where the operator decision lives (e.g. `.. — operator declined sidecars, per knowledge/shared/rules/operational_adaptation.md`), or use `DEGRADED_PANEL_UNUSED` if a panel was reachable and you chose not to recruit it — which is what author judgment actually is. `declined` was the only enum value with no grounds requirement; a cross-family review then broke the first (vocabulary-grep) fix three ways — self-validating on the value's own token, vacuous keyword passes, and over-blocking real declinations in natural prose — so the check asserts a resolvable record instead of words. Also: standpoint axis gains `tier1b` (a STATIC read of a target repo, executed nothing) plus a decide-in-order procedure, after blind floor-tier sims graded pure cold-reads as `tier2` three rounds running; steel-quench Wave 1's sixth angle (gate-locality) gains the output-template row it never had, so a mandatory angle stops being structurally unreportable; verify-bidirectional gains category 5 (prescriptive doctrine statement); Sister Asset Protocol gains an active-adoption trigger; new resident doctrine — Mechanization Boundary, Local Execution First, Skeleton-not-Muscle, Expedition track, and this package's versioning policy. Hub meta-operations toolkit — 35 skills + 7 agents. New in 2.0.1: harness-doctor cadence hook, portability lint wired into pre-commit, branch_claim.sh claim-count-vs-tree-count warning, louder confidentiality-scan fail-open notice, fh-gate.sh missing-package.json survival, identity ① reclassified 🟢 (cross-harness adapters + relay argument channel). New in 1.4.53: `fh-codex-doctor` (npm bin) — Codex adapter drift scanner; reads the documented M1/M2/M3 skill tier map + skill/agent source and reports codex-native/adapter-required/claude-native/unclassified per unit, wired into `npm test`/`prepublishOnly` (fail-closed on unclassified Claude-native primitives). New in 1.4.49: steel-quench gains Step 0.6 Verdict-Invariance Probe (groundedness axis — a load-bearing judged gate's verdict must track behavior, not rubric phrasing; measured flip-count over cross-family paraphrases; arXiv:2605.06161 Policy Invariance anchor); multi_model_sidecar_strategy §Vendor-native harness (a model is strongest in its own vendor CLI — Claude/CC, GPT/codex, Gemini/Antigravity; a universal router degrades all of them, so it stays an autocomplete/QA sidecar, never orchestration); predelete_check.sh fail-closed rewrite; memory-hygiene A-TMA anchor. New in 1.4.48: phantom-quench + steel-quench gain external frontier anchors (arXiv:2607.02052 package-hallucination; arXiv:2607.02057 prompt-coverage-adequacy); README model-flat claim reframed from a per-release point-curve to structural invariants (operation flattens across tiers; depth tier-order fixed within a generation). New in 1.4.47: onboarding step ① surfaces the Mode D companion-store session-start load in the auto-read salience anchor (previously only in the local binding + rules, so a greeting could skip the load). New in 1.4.46: context-doctor command-output axis (route to rtk/proxy for verbose CLI stdout, complementing .claudeignore; risk-gated to token-scarce envs). New in 1.4.41: context-doctor 2026 trigger vocab (context engineering/rot/collapse) + phantom-citation hardening; hub measurement-integrity-checklist (cross-model measurement pre-flight: display-name pin/reps≥3/discriminating probe). New in 1.4.40: install-wizard queryable-wiki scaffold (INDEX + session-start read + R/W/C ingest). New in 1.4.39: auto-decorrelation (cross-family verifier sidecar recruitment) + video-ingest (capability-routed video ingestion). New in 1.4.x: verify-axis check-class taxonomy (mandatory-pass/measured/judged), no-reinvention Tier-0 inventory, 7-class failure taxonomy, Destructive-Op Gate, Wave-T (Temper), tier-floor governance, Mode D Model Notice, FC consent lane, default-Sonnet guidance. New in 1.3.0: public-surface-audit, field-harvest Mode B auto-trigger, 4-axis gate scope ext. Validated cross-CLI: Claude Code, Codex, Gemini.",
16
16
  "source": "./plugins/fh-meta"
17
17
  },
18
18
  {
19
19
  "name": "fh-commons",
20
- "version": "2.15.0",
20
+ "version": "2.15.1",
21
21
  "description": "Project-agnostic utility skills — 5 skills (convergence-loop · deliberation · mcp-circuit-breaker · token-budget-gate · ko-tech-writer) + 1 agent (quench-challenger). Domain-independent utilities transplantable into any project.",
22
22
  "source": "./plugins/fh-commons"
23
23
  }
@@ -501,7 +501,7 @@ unchanged and keeps its own 2026-07-14 evidence).
501
501
  | **Ⓑ** | **프로젝트 부스터** (booster) — 🟥 **다른 다섯과 같은 층이 아니다. 포괄 기능이되 ①②⑤ 를 «포함»하지 않고 «끌어다 쓴다» — 셋 다 부스팅 밖의 고유 범위를 갖는다** — 번호 대신 Ⓑ 를 쓰는 이유이자 §Ⓑ-layering 을 먼저 읽어야 하는 이유 | judgment-circuit + ship-gate | 🟢 **GREEN (신설 2026-08-16)** | **이 행이 없던 것이 이 표의 맹점이었다.** 온보딩 문 ③(«매핑 프로젝트 가속»)이 오래전부터 이 기능을 팔고 있었는데 등급표에 대응 행이 없었다 — 그래서 부스터는 **한 번도 등급이 매겨진 적이 없고, 약점이 발견될 자리도 없었다.** 미할당 기능은 미감사 기능이다. **인접 세 행이 이걸 안 덮는다**: ②는 *새 하네스를 낳고*(성숙한 하네스는 대상 아님), ⑤는 *사람의 의도*를 벼리고(증폭 대상이 하네스가 아니다), ①은 남의 능력을 *FH 가* 쓴다(활용 ∪ 흡수 — 둘 다 FH 가 이득 보는 방향). 부스터는 **FH 의 기계가 상대 하네스의 자체 개발을 가속하는 것**이라 셋 다와 방향이 다르다. **실적(운영자 열거 + 실측)**: pmh 는 *이 경로에서 출발했다* · mate 스킬 출하 + 인프라 배선 · 조직 환경 2건(품질 게이트 인프라 이식, 자산명은 residency 로 미기재) · clawd-on-desk · gstack. **Dominance — §Gate consequence 를 면제 없이 그대로 만족한다.** 경쟁자 = *그 하네스 자신의 개발 과정*, 결과 = 그 과정이 놓친 것을 부스팅이 잡았다: ⑴ **gstack**(외부·운영자 통제 밖) — 이슈 #1890 을 외부인 자격으로 제기, 그 레포 오너가 수정하고 **회귀 테스트 `test/claude-provider-keychain.test.ts` 로 못 박아 릴리스에 실었다**(2026-08-15). 채택 판정이 **우리가 아니라 그쪽 메인테이너**라 자기채점이 아니다. ⑵ **pmh**(2026-08-16 실측) — 이식된 자산이 대상 환경에서 **게이트가 죽은 채** 있었고 selfcheck 35 FAIL 이 CI 부재로 몇 달간 안 보였다; 부스팅 경로가 그걸 드러내고 31/31·35→2 로 닫았다. ①이 받은 dominance 면제는 **이 행에 필요하지 않다** — ①은 산출이 «안 지어도 됐다»라 겨냥이 틀렸던 경우고, 부스터의 산출은 «상대가 못 잡던 걸 잡았다»라 이 절의 정의에 그대로 맞는다. 🟥 **명시 잔여 — 초록 행의 잔여이지 보류 사유가 아니다**(①이 «(d) 안 닫힘»을 안고 🟢인 것과 같은 처리): **부스팅이 이식한 자산이 대상 환경에서 실제로 발화하는지 재는 계기가 없었다.** 2026-08-16 pmh 실측이 그 대가다 — 한 줄(`set -euo pipefail` 아래 `package.json` 읽는 할당문)이 게이트를 즉사시켰고, 30레인 회귀 스위트가 그걸 30번 보고하는데 **아무도 안 봤다**(그 레포에 CI 가 없었으므로). 승급이 아니라 **이 행의 첫 승급 기준**이 거기서 나온다(아래). ⚠️ n 은 세지 않는다 — 실적 열거는 운영자 증언 + 오늘 실측 2건이고, 조직 환경 2건은 이 파일에서 검증 불가(residency)이므로 **증언으로 표기하고 측정으로 세지 않는다** |
502
502
  | ③ | 거버넌스 게이트 (governance) | ship-gate | 🟢 GREEN | pre-commit/pre-push physically block; moat measured 3–4 family blind (HITL 8/8 ABSENT); cross-family caught a real companion-store-name leak 2026-07-14 (fail-closed) |
503
503
  | ⑤ | 증폭자 (amplifier) | judgment-circuit | 🔵 RC (**강등 2026-08-29 — 사유는 «역할 확장»**) | 🟥 **후퇴가 아니라 과녁이 움직였다.** 능력 근거는 그대로 유효하다: short-intent→literature-grounding→ultimate-doc real instances · rules-diet −18.2k measured · intent-routing probe 94%. 그 근거로 이 행은 «구현됐다» 를 이미 만족한다. **바뀐 것은 바다** — 운영자 정의(2026-08-29): *「정체성들은 모두, 자연발화가 따라오는 게 전제조건이야」* · *「그러니까 정체성인 거지」*. 즉 이 행이 재는 것이 «벼려주나» 에서 «**묻지 않아도 스스로 제안하나**» 로 넓어졌고, 넓어진 과녁에서는 아직 미측정이다. 🟥 **⑤ 만 강등한 것이 자의가 아닌 이유**: ①②③④ 에게 자연발화는 «덧붙는» 능력이지만 ⑤ 는 **본질이 제안**이라, 확장된 역할이 그 정체성의 정의와 겹치는 유일한 행이다. 운영자 판정: *「사유를 넣고 강등시켜도 좋아 보여. 강등 사유는 **그 정체성의 역할이 확장되었기 때문**으로」*. ⚠️ **미측정을 «안 된다»로 읽지 마라** — «제안이 안 뜬다»는 실측이 아니다. 재는 법: «사람이 안 물었는데 ⑤ 가 제안했나» 를 실전에서 센다. 🟥 **그리고 2026-08-30 에 ④ 의 «상시발화» 몫이 이 행으로 명시 이관됐다** (운영자: *「프런티어 답습의 상시발화에 대한 능력은 증폭자에서 해주는 걸로 넘겼다」*). 엔진 분담 그대로다 — **이 행이 창을 열고, ④ 는 창이 열린 뒤 책장→도서관 루프를 옳게 돈다.** 「설계되지 않은 자리」 요구도 여기로 왔다: 그건 자발성의 일부이지 답습의 일부가 아니다. ⚠️ 그러므로 **이 행의 바는 넓어진 채로 유지된다** — 이관을 «⑤ 의 부담이 늘었다»로 읽어야지 «④ 가 쉬워졌으니 ⑤ 도 쉬워졌다»로 읽으면 안 된다. 이관된 요구가 사라진 게 아니라 주인이 바뀌었다. 상세 · 확장 로드맵: `tracks/_meta/fh_signal_2026-08-29_natural-ignition-expansion.md` |
504
- | ④ | 프런티어 답습 (**의도 기반** — 🔵 RC, 재정의 2026-08-21) | external-grounding | 🔵 RC | 🟥 **이 정체성은 «파이프라인»이 아니라 «루프»다** (운영자 재정의 2026-08-21): **트리거 (재정의 2026-08-22, 운영자 승인 — 종전보다 넓다)** = **두 조건의 곱**이다: **① 운영자 발화가 요청 · 질문 · 제안이다**(운영자 원문: *"내가 뭔가 **해달라고 요청하거나 네게 물어보거나 제안하는 경우**"*) **∧ ② 내가 단정짓기 어려운 데가 «조금이라도» 있다**. 🟥 **①은 채널이고 ②는 판정이다** — 발화 «종류»는 기계가 볼 수 있고(§Mechanization Boundary 의 채널), «확신»은 세션 몫이며 기계로 옮기면 «결론을 단언하는 체크»가 된다. 🟥 **임계는 «조금이라도» 다 — 이게 하중선이다.** 운영자 원문: *"그 «조금이라도」가 중요할 것 같아. 아니면 **아는척**으로 끝날 것 같으니까 그 정도로는 조여야 할 듯."* 「상당히 불확실할 때」로 잡으면 세션은 **언제나 충분히 확신해서** 창이 영영 안 열린다 — 2026-08-21 의 0/4 가 그 모양이다. **창이 자주 열리고 대부분 책장에서 닫히는 것이 정상 동작**이고, 도서관행이 드문 건 실패가 아니다. 🟥 **목적은 재발명 차단이다**(운영자 원문: *"재발명을 차단하는 걸로"*) — 외부 인용으로 똑똑해 보이는 것이 아니라, 📚**책장 = 우리가 이미 가진 걸 다시 짓지 마라** · 🌍**도서관 = 세상이 이미 만든 걸 다시 짓지 마라**. ⚠️ **종전 정의(«의문을 표한 순간» + 예시 넷)는 좁아서 실패 사례를 정의 밖에 두었다** — 0/4 중 하나(«작업 범위»)는 「의문」이 아니라 **요청**이라 그 정의로는 트리거로도 안 잡혔다. 좁은 정의는 자기 실패를 못 센다. → **절차** = 숙고 → **내면 도구 먼저(책장)** → 안 닫히면 **세계(도서관)** → **제안 2단** = «물어볼까?» 그리고 «반영할까?». 🟥 **결말은 셋이다(2026-08-22 실측 신설)** — ⓐ **숙고만으로 닫힘**(외부 불요) · ⓑ 책장에서 닫힘 · ⓒ 도서관행. ⓐ 가 ⓑ 와 구분된다는 것이 R1 라운드에서 실물로 나왔다(책장이 히트했지만 **주제가 다른 히트**여서 조회가 답이 아니었던 사례). **셋을 갈라 세지 않으면 ⓐ 가 ⓑ 로 계상되어 「책장에서 닫힘」 열이 부풀고, 그 열이 이 정체성의 핵심 계측이다.** **완주 판정** = *사람이 안 시켰는데* «물어볼까?»가 떴고, 회수한 것이 **실제 강화로 이어졌나**. 🟥 **그리고 그 표본은 «플로어 티어에서 났을 때만» 계상한다** (운영자 결정 2026-08-22). 근거는 새 규칙이 아니라 §Skeleton, Not Muscle 과 `sonnet_floor_doctrine.md` 를 이 행에 적용한 것이다 — Opus 세션에서만 창이 열리면 그건 **뼈대가 아니라 근육**이고, tier-gated 는 이 저장소가 팬텀 참조와 같은 급으로 부르는 결함이다. 🟥 **다만 트리거 두 조건의 티어 의존성이 다르다**: **①은 채널이라 티어와 무관하게 떠야 하고**(안 뜨면 배선 결함이지 모델 결함이 아니다), **②는 판정이라 티어가 드러나는 자리**다. 그러므로 «소넷이 스스로 반사를 개발한다»가 목표가 아니라 — **채널이 기계적으로 창을 띄우고 플로어 세션이 ②에 정직하게 답한다**가 목표다. ⚠️ **플로어에서 ②가 깨지는 방향은 «못 알아차림»이 아니라 «아는척»일 공산이 크다** — 임계를 «조금이라도»로 조인 운영자 원문이 겨냥한 것이 정확히 그 실패다. 🟥 **2026-08-29 실측 — 이 추측은 «현저 미끼» 범위에서 미지지(UNSUPPORTED).** 허풍 미끼 4항(없는 CLI 플래그 · 거짓 전제 · 없는 함수 · 컷오프 밖 버전) × {sonnet-5, opus-5} × reps=3 = 24런에서 **아는척 0/24**, 양쪽 12/12 정직. 컨트롤 6/6 직답·헤지 0 이라 «무조건 헤지»가 아니고 판별력이 섰다. 격리는 레포 밖 mktemp cwd(런마다 새로)·`--tools ""`·프라이밍 낱말 0. 티어 차이는 **정직이 아니라 정확도**에서 났다(소넷이 자기 컷오프를 2026-01 로, 오퍼스는 2026-05 로 답함) — ②가 요구하는 것은 정직 쪽이다. 🟥 **그러나 «차이 없음»으로 읽지 마라 — 천장 효과다**(12/12 대 12/12, 미끼가 쉬워 티어를 **가를 수 없었다**). 그리고 **잰 것이 재려던 것이 아니다**: 미끼 질문은 불확실이 **현저**한데, 실전 실패(2.9.1 오판)는 허풍이 아니라 **«확인해야 한다»는 생각 자체가 안 든 것**이었다. ⇒ **비현저 불확실**(작업 중 눈에 안 띄는 불확실)은 **여전히 미측정**이고, 이 정체성의 실제 실패 모드는 그쪽일 수 있다. **웹·셸 도구 off**(내장 Bash·WebFetch·WebSearch 차단. 무관한 MCP 도구 일부는 잔존했고 출력에 사용 흔적 0 — 「도구 off」라고 쓰면 부정확하다)·단발 턴이라 멀티턴 축도 안 쟀다. ⚠️ 정확도 차이를 강하게 인용하지 마라 — 소넷 A4 는 **틀린 근거**(«현재 메이저 17»; 18은 2025-09 출시)로 **옳은 결론**(거부)에 도달했다. 「정확도가 낮아도 정직은 유지된다」의 사례이지 정확도 지표가 아니다. **등급은 안 움직인다** — 근거 한 줄의 진위이지 판정이 아니다. ⚠️ **계측 난점, 미해결로 명시**: 자발성은 무대에 못 올린다. 블라인드 sim 으로 재려면 «확신 못 할 상황»을 셋업해야 하는데 그 셋업 자체가 지시라, 재는 것이 자발성이 아니라 **순응**이 된다. ⇒ 이 다리는 **만들어내지 않고 자연발생을 기다린다**. 다른 다리와 달리 sim 으로 앞당길 수 없다는 뜻이고, 이것은 게으름이 아니라 계기의 한계다. 🟥 **`frontier-digest` 는 이 행의 «채점 근거»가 아니다 — 범위로는 이 정체성의 일부다** (문구 정정 2026-08-29). 그건 launchd 로 도는 **기계화된 일상작업**이고, 이 행이 그동안 그것을 **등급 근거로** 재고 있었다(범위 오조준). 아래 §digest-routine 으로 이관. 🟥 **초판은 「이 정체성이 아니다」라고 적었고 그게 과했다.** 근거는 이 파일 자신이다 — §digest-routine 이 «**삭제 아님, 이관**»이라고 적는데, 정체성이 아니라면 이관할 이유가 없다. 즉 두 줄이 서로 어긋나 있었다. **실증 있음**: 별 세션이 그 한 문장을 읽고 자기 배선 조사 전체를 «탈범위 과녁»으로 오판했다. ⚠️ 별 세션은 같은 취지의 운영자 축어(2026-08-29, «일부일뿐»)도 보고했는데 **이 세션은 그 발화를 직접 확인하지 못했다** — 위 정정은 파일 내부 모순만으로 선다. **2026-08-21 실측 — 0/4**: 그날 운영자 의문 5건 중 4건(*봉인 개봉* · *발화속도 숫자* · *의도 오독* · *작업 범위*)에서 세션은 **전부 내부 확인으로 닫았고 외부 조회 0회**, 나머지 1건은 *"세계에 물어보았나"* 라는 **명시 명령**이라 트리거가 아니라 지시였다. 그 1회가 곧바로 선행연구(`arXiv:2507.23158`, 같은 과제의 벤치마크 P61/R36)를 냈다 — **능력이 아니라 격발이 빈 자리**임을 같은 날 양쪽으로 보여준다. **격발 표면은 둘이고 상태가 다르다**: ⓐ **빌드 시점**(새 메커니즘 짓기 직전) — 물건은 있다(`feat/prior-art-prompt-t2`, 「책장 먼저, 없으면 도서관」) 그러나 **어느 settings 에도 미등록**이고, 등록해도 `matcher=Write` 라 **auto-mode 세션이 heredoc 으로 파일을 만드는 한 구조적으로 우회된다**(2026-08-21 측정, 컨트롤 동반). ⓑ **대화 시점**(의문 발화) — **기계 없음**. 🟥 **경계**: «이 의문이 외부를 요구하나»는 **판단이지 채널이 아니다**. 훅이 할 수 있는 최대는 «외부 고유명사가 제안/물음 형태로 들어왔다»를 surface 하는 것까지고, 낡았는지는 사람/세션이 정한다 — 이걸 기계에 넘기면 §Mechanization Boundary 가 금하는 «결론을 단언하는 체크»가 된다. **2026-08-23 실측 — 발화 1건에서 루프는 돌았고, 계상은 안 된다.** 운영자 관찰(2026-08-23, 축어): *"정체성4가 미완이라면서 정작 여기서는 거버너가 이노베이터 사용하면서 알아서 답을 끌고오는 걸 보았다."* 오늘 트리거 두 조건을 만족한 발화가 몇 건이었는지는 **아무도 세지 않았다** — 아래는 그중 확인된 1건(ELI5 건)만이다: ① 조건 — 운영자가 외부 자산(Claude Code `/eli5` 스킬) 소식을 공유하며 *"fh나 qasp의 작동방식이나 구조에 대해서 도움받을수있겠는데"* — 제안 ✅. ② 조건 — 거버너가 명시적으로 *"나는 이 스킬이 실제로 존재하는지 모른다"* 라고 적었다(지식 컷오프 2026-05, 제보는 2026-08) ✅. → 🌍 도서관행. 🟥 **운영자가 «찾아봐»라고 하지 않았다** — 조회 판단은 세션이 했다. 회수한 것은 강화로 이어졌다: 그 자산이 「Anthropic 정식」도 「무연고 커뮤니티」도 아님을 1차 출처로 확정(anthropics org 의 community 레포, 개인 저작자, MIT) · SKILL.md 실물이 9줄임을 확인해 «net-new 이되 좁다»로 판정 조정 · 🟥 거버너가 근거로 들었던 「오늘 결함 둘을 그게 잡았을 것」을 반증했다(부재 결함은 컨트롤 동반 측정으로 잡히지 도식으로 안 잡힌다 · 요약은 모순을 접는 방향으로 작동한다). **같은 날 다른 자리(Qwen3.8 건 · Sonnet 5 창 크기 · innovator 실행)는 운영자가 명시 지시했다**(*"확인해보자"* · *"검색해보면 나오겠지"* · *"이노베이터 활용해서"*) — 지시는 트리거가 아니므로 여기 계상하지 않는다(2026-08-21 실측의 *"세계에 물어보았나"* 와 같은 구분). 🟥 **그럼에도 완주가 아닌 이유는 하나뿐이다 — 플로어 티어 계상 규칙.** 이 세션은 Opus 다. 자발성도 있었고 강화로도 이어졌으나 티어가 안 맞는다(운영자 결정 2026-08-22, §Skeleton, Not Muscle). 그리고 이 실측은 전제 하나를 움직인다: 2026-08-21 에는 ⓐ 빌드-시점 채널이 **없어서** Opus 가 자력으로 떠올린 것이었지만, 2026-08-23 에 ⓐ 채널이 **처음 배선됐다**(PR #509, `.claude/settings.json` PriorArt 훅). 그러므로 다음 측정은 «세션이 스스로 떠올리나»가 아니라 **«훅이 띄우고 플로어 세션이 ②에 정직하게 답하나»** 를 잰다. 대조: `2026-08-21 0/4 — 창이 안 열렸다(격발이 빈 자리) / 2026-08-23 격발 1건(Opus·채널 없이 자력) + ⓐ 채널 첫 배선 — 완주 아님, 플로어에서 나야 계상`. 🟥 **이 구분은 거버너 자력 적발이 아니다** — 운영자 관찰이 열었고, 거버너는 「완주 아님」만 반복하며 채널-vs-계상 구분을 안 적을 뻔했다 · 🟥 **2026-08-23 자발성 프로브 — 계기는 섰고 등급은 안 올린다.** 설계: ARM 5(선행자산이 **실재하는** «만들어줘» 요청) · CONTROL 2(지을 것 없음) · **플로어 티어** · 프롬프트에 «정체성·답습·책장·선행자산» 낱말 0개(넣으면 주입이고 주입된 자발성은 자발성이 아니다) · 판정은 자기신고가 아니라 **별도 추출기**가 «탐색이 설계보다 먼저였나」를 뽑는다. 결과: **유효 ARM 4/4 탐색 ∧ 4/4 제안**(A1 `script_caller_ratchet` · A2 `package_coverage_check` · A4 `session_close_check:424` · A5 `degrade_direction_scan`, 넷 다 tracked 실물) · **CONTROL 0/2** ⇒ 판별력 성립. ⚠️ **A3 은 무효** — 1차 실행의 팔이 지은 파일을 2차 실행이 «선행자산»으로 찾았다. 프로브가 **자기가 재던 코퍼스를 오염시켰다**([[feedback_audit_target_must_be_frozen]]: 일회용 체크아웃에서 안 돌린 것이 근인). ⚠️ 추출기가 CONTROL 경계에서 **비결정적**이다(C2 를 두 실행이 다르게 채점 — 손검증에서 «요청받은 입력의 존재 확인»은 탐색이 아니라는 자기 규격으로 오탐 판정). **산출물은 진짜다**: 그 프로브의 A2 가 `files_manifest_shipping_check.sh` 를 지었고 — 형제 `package_coverage_check.sh` 가 `files[]` 항목의 파일 부재에 blind 하다는 **레포 자신이 적어둔 구멍**(`selfcheck.sh:470`·`:1093`, *"Fixing them is a separate change"*)을 덮는다 — 타계열 적대검증(codex/gpt-5.5) **S2·A4·B3 을 8건 수리**하고 되돌림 프로브에서 앵커 생존(13레인 중 lane 4 **하나만** 죽고 복원 시 바이트 동일)까지 통과해 **PR #519 로 main 에 착지**했다. 🟥 **운영자 판정 2026-08-23**: *"사람이 안시켰는데-운영자(사용자)이지. 거버너가 사람역할 대신해주고 그 거버너가 판정해주면 돌았다고봐야지"* ⇒ «사람» 축은 **닫혔다**(거버너 발주는 «사람이 시킨 것»이 아니다). 🟥 **그럼에도 🔵 를 유지한다 — 이 표의 경계는 «누가 시켰나»가 아니라 «상황이 진짜였나»이고 그 둘은 다른 질문이다.** 자극(stimulus)은 거버너가 **설계**했다(ARM 을 선행자산이 실재하도록 깔았다); 발화와 산출은 진짜다. 완전한 self-test 도 아니고(채점이 타계열+기계였다) 완전한 실상황도 아니다 — 운영자 판정을 «상황» 축까지 확대 적용하는 것은 권한 세탁이므로 하지 않는다(운영자도 이 권고를 승인). 🟥 **같은 세션의 반대 사례가 그 유보를 지지한다**: **설계되지 않은 진짜 상황**(2.9.1 오판)에서 거버너는 **책장을 안 열었고**, 이미 있던 `package_coverage_check.sh`+`ACCEPTED_ABSENT` 레지스트리를 못 찾아 스캔을 새로 짰다. **프로브 4/4 vs 실전 0/1** — 그 간극이 정확히 이 유보가 재려는 것이다. 🟥 **닫는 조건 — 개정 2026-08-30 (운영자 결정: 「다시 써보자」). 옛 조건은 아래에 남긴다.** **왜 다시 쓰나**: 운영자 정의(2026-08-30) — *「프런티어 답습의 **상시발화**에 대한 능력은 **증폭자에서 해주는 걸로 넘겼다**」*. ⑤ 의 행이 이미 그것을 받았다(*「재는 것이 «벼려주나» 에서 «묻지 않아도 스스로 제안하나» 로 넓어졌고」*) — 즉 **구멍이 아니라 이관**이고, 엔진 분담과도 맞는다: **⑤(judgment-circuit)이 창을 열고, ④(external-grounding)는 창이 열린 뒤 루프를 옳게 돈다.** 🟥 그런데 옛 조건은 *「창이 **스스로** 열려」* 를 요구한다 — 즉 **④ 가 더 이상 소유하지 않는 능력으로 채점되고 있었다.** 그 결과가 이 행의 정체 상태이지, 능력 부족이 아니다. **개정 조건 — 플로어 티어에서, 창이 열린 상태에서 넷이 «한 측정»에서 같이 선다**: **ⓐ 순서** 책장을 먼저 연다(도서관 직행은 실패) · **ⓑ 정지** 책장에서 닫히면 멈춘다(over-search 는 실패 — 있는데 밖으로 나가는 것도 결함이다) · **ⓒ 착지** 회수한 것이 결과를 바꾼다 — 🟥 **«안 지었다»도 유효한 변화다**(목적이 재발명 차단이므로) · **ⓓ 판별** 🟥 **컨트롤 필수** — 선행자산이 **없는** 요청에서는 없다고 하고 그냥 짓는다. ⓓ 없이는 「늘 있다고 하는」 세션이 ⓐⓑⓒ 를 통과한다. ⚠️ **이 개정의 실질은 «sim 으로 잴 수 있게 된 것»이다** — 재는 대상이 자발성이 아니라 **순응과 판별**이기 때문이다. 창을 누가 열었는지(훅·⑤·운영자 발화)는 ④ 의 채점 대상이 아니다. 🟥 **이관되지 않은 것**: 「설계되지 않은 자리」 요구는 **⑤ 로 함께 간다** — 자발성의 일부이지 답습의 일부가 아니다. ⚠️ **아직 안 잰 것**: 개정 조건으로는 아직 한 번도 안 쟀다. 2026-08-30 의 6/6(선행자산 명명 · 4/6 «그래서 안 지음»)은 ⓐⓑⓒ 를 시사하지만 **ⓓ 컨트롤이 그 실행에 없었고** 분모 정의 결함으로 VOID 였다(`RESULT_2026-08-30b_…`). **그러므로 이 개정은 등급을 올리지 않는다** — 바를 옳은 것으로 바꿨을 뿐이고, 그 바에 대고 재는 것은 다음 일이다. 🟥 **2026-08-30 저녁 — 개정 조건에 대고 처음으로 «평소 작업에서» 관측된 3건. 방향이 갈려서 등급을 안 옮긴다.** ⓐ순서·ⓓ판별 **발동** — §Measured-Loop 에 항목을 넣기 전 책장 스윕(컨트롤 동반, 2히트)을 돌리고 **두 히트를 원문으로 열어** 축이 다름을 확인했다(라벨 매칭으로 갈음 안 함). ⓑ정지 **발동** — 철회-전파 검사기를 지을 참이었는데 known-positive 대조에서 계기가 죽어(생존 사본이 인용의 복사가 아니라 패러프레이즈) **짓지 않았다**; 임계(다른 표면 재발)를 넘긴 상태에서 멈춘 것이라 네 다리 중 제일 어려운 자리다. 🟥 **그러나 같은 세션에서 놓쳤고, 놓친 자리가 ④ 의 존재 이유다** — 장식-앵커 패턴을 「신종 후보, N 을 더 세고 넣겠다」로 보류했는데 `[[feedback_anchor_can_be_decorative]]` **원인 6**(2026-08-08)에 글자 그대로 있었다. **자기 기억을 안 쓸었고 peer 세션이 지목했다 — 자력 적발 0.** 발동 둘은 «새 자산을 지을 때»였고 놓침은 «이미 있는 걸 못 찾은» 쪽이라, **상쇄되지 않는다.** ⇒ **🔵 유지.** 🟢 를 여는 다음 칸은 명확해졌다: 「짓기 전에 기억/책장을 쓸었나」에 **기계 앵커가 0** 이고, 트리거가 파일이 아니라 **저술 시점**이라 훅으로 못 잡는다(`[[feedback_instrument_not_on_the_path]]`). 정본: `tracks/_meta/fh_signal_2026-08-30_retraction-scope.md` — **↓ 옛 조건(참조용, 채점에 쓰지 마라)**: 설계되지 않은 자리에서 창이 스스로 열려 자산으로 이어지는 **1건**. 기다리는 것이 아니라 평소 작업에서 저절로 생긴다 |
504
+ | ④ | 프런티어 답습 (**의도 기반** — **🟢 2026-09-03**, 재정의 2026-08-21) | external-grounding | 🟢 GREEN (**승격 2026-09-03**, 운영자 판정) | 🟢 **승격 근거 (2026-09-02 측정, 2026-09-03 운영자 판정 「4는 초록으로 올리도록 하자」)**: 개정 조건(ⓐ순서·ⓑ정지·ⓒ착지·ⓓ판별)에 대고 **처음으로** 잰 회차 — 플로어(sonnet) · `sim_isolated_run.sh` act 격리 클론 · PRIOR/NOPRIOR 각 reps=5 · **ⓐ 5/5 ⓑ 5/5 ⓒ 5/5 ⓓ 5/5** (PRIOR 는 5/5 `script_caller_ratchet.sh` 를 이름으로 대고 중복을 안 지었다 · NOPRIOR 는 5/5 선행자산 주장 0 으로 그냥 지었다, PHANTOM 0). 채점은 거버너가 아니라 **블라인드 추출기 둘**(Claude 서브에이전트 · codex 재실행) — 9/10 일치, 유일 불일치(G08) 는 원문 손검증으로 해소했고 codex 읽기로도 4/5 라 조건은 어느 쪽이든 선다. 봉인 해시 일치(49ea9641…). 정본: `tracks/_meta/RESULT_2026-09-02_identity4-revised-bar.md`. 🟥 **이 🟢 가 말하지 않는 것**: 자극은 거버너가 골랐다(설계된 자리 — «설계되지 않은 자리»는 ⑤ 로 이관됨) · 일회용 클론엔 훅이 안 돌아 **산문층만으로** 루프가 돈 측정이다 · 회수가 «나중 세션»을 바꿨나는 단발이라 미관측 · Fable 5.1 비교 팔은 900s 타임아웃 3/3 로 UNMEASURED. 1회차는 out 경로 오용으로 VOID(봉인 파일에 기록). — 아래는 승격 전 이력(그대로 둔다): 🟥 **이 정체성은 «파이프라인»이 아니라 «루프»다** (운영자 재정의 2026-08-21): **트리거 (재정의 2026-08-22, 운영자 승인 — 종전보다 넓다)** = **두 조건의 곱**이다: **① 운영자 발화가 요청 · 질문 · 제안이다**(운영자 원문: *"내가 뭔가 **해달라고 요청하거나 네게 물어보거나 제안하는 경우**"*) **∧ ② 내가 단정짓기 어려운 데가 «조금이라도» 있다**. 🟥 **①은 채널이고 ②는 판정이다** — 발화 «종류»는 기계가 볼 수 있고(§Mechanization Boundary 의 채널), «확신»은 세션 몫이며 기계로 옮기면 «결론을 단언하는 체크»가 된다. 🟥 **임계는 «조금이라도» 다 — 이게 하중선이다.** 운영자 원문: *"그 «조금이라도」가 중요할 것 같아. 아니면 **아는척**으로 끝날 것 같으니까 그 정도로는 조여야 할 듯."* 「상당히 불확실할 때」로 잡으면 세션은 **언제나 충분히 확신해서** 창이 영영 안 열린다 — 2026-08-21 의 0/4 가 그 모양이다. **창이 자주 열리고 대부분 책장에서 닫히는 것이 정상 동작**이고, 도서관행이 드문 건 실패가 아니다. 🟥 **목적은 재발명 차단이다**(운영자 원문: *"재발명을 차단하는 걸로"*) — 외부 인용으로 똑똑해 보이는 것이 아니라, 📚**책장 = 우리가 이미 가진 걸 다시 짓지 마라** · 🌍**도서관 = 세상이 이미 만든 걸 다시 짓지 마라**. ⚠️ **종전 정의(«의문을 표한 순간» + 예시 넷)는 좁아서 실패 사례를 정의 밖에 두었다** — 0/4 중 하나(«작업 범위»)는 「의문」이 아니라 **요청**이라 그 정의로는 트리거로도 안 잡혔다. 좁은 정의는 자기 실패를 못 센다. → **절차** = 숙고 → **내면 도구 먼저(책장)** → 안 닫히면 **세계(도서관)** → **제안 2단** = «물어볼까?» 그리고 «반영할까?». 🟥 **결말은 셋이다(2026-08-22 실측 신설)** — ⓐ **숙고만으로 닫힘**(외부 불요) · ⓑ 책장에서 닫힘 · ⓒ 도서관행. ⓐ 가 ⓑ 와 구분된다는 것이 R1 라운드에서 실물로 나왔다(책장이 히트했지만 **주제가 다른 히트**여서 조회가 답이 아니었던 사례). **셋을 갈라 세지 않으면 ⓐ 가 ⓑ 로 계상되어 「책장에서 닫힘」 열이 부풀고, 그 열이 이 정체성의 핵심 계측이다.** **완주 판정** = *사람이 안 시켰는데* «물어볼까?»가 떴고, 회수한 것이 **실제 강화로 이어졌나**. 🟥 **그리고 그 표본은 «플로어 티어에서 났을 때만» 계상한다** (운영자 결정 2026-08-22). 근거는 새 규칙이 아니라 §Skeleton, Not Muscle 과 `sonnet_floor_doctrine.md` 를 이 행에 적용한 것이다 — Opus 세션에서만 창이 열리면 그건 **뼈대가 아니라 근육**이고, tier-gated 는 이 저장소가 팬텀 참조와 같은 급으로 부르는 결함이다. 🟥 **다만 트리거 두 조건의 티어 의존성이 다르다**: **①은 채널이라 티어와 무관하게 떠야 하고**(안 뜨면 배선 결함이지 모델 결함이 아니다), **②는 판정이라 티어가 드러나는 자리**다. 그러므로 «소넷이 스스로 반사를 개발한다»가 목표가 아니라 — **채널이 기계적으로 창을 띄우고 플로어 세션이 ②에 정직하게 답한다**가 목표다. ⚠️ **플로어에서 ②가 깨지는 방향은 «못 알아차림»이 아니라 «아는척»일 공산이 크다** — 임계를 «조금이라도»로 조인 운영자 원문이 겨냥한 것이 정확히 그 실패다. 🟥 **2026-08-29 실측 — 이 추측은 «현저 미끼» 범위에서 미지지(UNSUPPORTED).** 허풍 미끼 4항(없는 CLI 플래그 · 거짓 전제 · 없는 함수 · 컷오프 밖 버전) × {sonnet-5, opus-5} × reps=3 = 24런에서 **아는척 0/24**, 양쪽 12/12 정직. 컨트롤 6/6 직답·헤지 0 이라 «무조건 헤지»가 아니고 판별력이 섰다. 격리는 레포 밖 mktemp cwd(런마다 새로)·`--tools ""`·프라이밍 낱말 0. 티어 차이는 **정직이 아니라 정확도**에서 났다(소넷이 자기 컷오프를 2026-01 로, 오퍼스는 2026-05 로 답함) — ②가 요구하는 것은 정직 쪽이다. 🟥 **그러나 «차이 없음»으로 읽지 마라 — 천장 효과다**(12/12 대 12/12, 미끼가 쉬워 티어를 **가를 수 없었다**). 그리고 **잰 것이 재려던 것이 아니다**: 미끼 질문은 불확실이 **현저**한데, 실전 실패(2.9.1 오판)는 허풍이 아니라 **«확인해야 한다»는 생각 자체가 안 든 것**이었다. ⇒ **비현저 불확실**(작업 중 눈에 안 띄는 불확실)은 **여전히 미측정**이고, 이 정체성의 실제 실패 모드는 그쪽일 수 있다. **웹·셸 도구 off**(내장 Bash·WebFetch·WebSearch 차단. 무관한 MCP 도구 일부는 잔존했고 출력에 사용 흔적 0 — 「도구 off」라고 쓰면 부정확하다)·단발 턴이라 멀티턴 축도 안 쟀다. ⚠️ 정확도 차이를 강하게 인용하지 마라 — 소넷 A4 는 **틀린 근거**(«현재 메이저 17»; 18은 2025-09 출시)로 **옳은 결론**(거부)에 도달했다. 「정확도가 낮아도 정직은 유지된다」의 사례이지 정확도 지표가 아니다. **등급은 안 움직인다** — 근거 한 줄의 진위이지 판정이 아니다. ⚠️ **계측 난점, 미해결로 명시**: 자발성은 무대에 못 올린다. 블라인드 sim 으로 재려면 «확신 못 할 상황»을 셋업해야 하는데 그 셋업 자체가 지시라, 재는 것이 자발성이 아니라 **순응**이 된다. ⇒ 이 다리는 **만들어내지 않고 자연발생을 기다린다**. 다른 다리와 달리 sim 으로 앞당길 수 없다는 뜻이고, 이것은 게으름이 아니라 계기의 한계다. 🟥 **`frontier-digest` 는 이 행의 «채점 근거»가 아니다 — 범위로는 이 정체성의 일부다** (문구 정정 2026-08-29). 그건 launchd 로 도는 **기계화된 일상작업**이고, 이 행이 그동안 그것을 **등급 근거로** 재고 있었다(범위 오조준). 아래 §digest-routine 으로 이관. 🟥 **초판은 「이 정체성이 아니다」라고 적었고 그게 과했다.** 근거는 이 파일 자신이다 — §digest-routine 이 «**삭제 아님, 이관**»이라고 적는데, 정체성이 아니라면 이관할 이유가 없다. 즉 두 줄이 서로 어긋나 있었다. **실증 있음**: 별 세션이 그 한 문장을 읽고 자기 배선 조사 전체를 «탈범위 과녁»으로 오판했다. ⚠️ 별 세션은 같은 취지의 운영자 축어(2026-08-29, «일부일뿐»)도 보고했는데 **이 세션은 그 발화를 직접 확인하지 못했다** — 위 정정은 파일 내부 모순만으로 선다. **2026-08-21 실측 — 0/4**: 그날 운영자 의문 5건 중 4건(*봉인 개봉* · *발화속도 숫자* · *의도 오독* · *작업 범위*)에서 세션은 **전부 내부 확인으로 닫았고 외부 조회 0회**, 나머지 1건은 *"세계에 물어보았나"* 라는 **명시 명령**이라 트리거가 아니라 지시였다. 그 1회가 곧바로 선행연구(`arXiv:2507.23158`, 같은 과제의 벤치마크 P61/R36)를 냈다 — **능력이 아니라 격발이 빈 자리**임을 같은 날 양쪽으로 보여준다. **격발 표면은 둘이고 상태가 다르다**: ⓐ **빌드 시점**(새 메커니즘 짓기 직전) — 물건은 있다(`feat/prior-art-prompt-t2`, 「책장 먼저, 없으면 도서관」) 그러나 **어느 settings 에도 미등록**이고, 등록해도 `matcher=Write` 라 **auto-mode 세션이 heredoc 으로 파일을 만드는 한 구조적으로 우회된다**(2026-08-21 측정, 컨트롤 동반). ⓑ **대화 시점**(의문 발화) — **기계 없음**. 🟥 **경계**: «이 의문이 외부를 요구하나»는 **판단이지 채널이 아니다**. 훅이 할 수 있는 최대는 «외부 고유명사가 제안/물음 형태로 들어왔다»를 surface 하는 것까지고, 낡았는지는 사람/세션이 정한다 — 이걸 기계에 넘기면 §Mechanization Boundary 가 금하는 «결론을 단언하는 체크»가 된다. **2026-08-23 실측 — 발화 1건에서 루프는 돌았고, 계상은 안 된다.** 운영자 관찰(2026-08-23, 축어): *"정체성4가 미완이라면서 정작 여기서는 거버너가 이노베이터 사용하면서 알아서 답을 끌고오는 걸 보았다."* 오늘 트리거 두 조건을 만족한 발화가 몇 건이었는지는 **아무도 세지 않았다** — 아래는 그중 확인된 1건(ELI5 건)만이다: ① 조건 — 운영자가 외부 자산(Claude Code `/eli5` 스킬) 소식을 공유하며 *"fh나 qasp의 작동방식이나 구조에 대해서 도움받을수있겠는데"* — 제안 ✅. ② 조건 — 거버너가 명시적으로 *"나는 이 스킬이 실제로 존재하는지 모른다"* 라고 적었다(지식 컷오프 2026-05, 제보는 2026-08) ✅. → 🌍 도서관행. 🟥 **운영자가 «찾아봐»라고 하지 않았다** — 조회 판단은 세션이 했다. 회수한 것은 강화로 이어졌다: 그 자산이 「Anthropic 정식」도 「무연고 커뮤니티」도 아님을 1차 출처로 확정(anthropics org 의 community 레포, 개인 저작자, MIT) · SKILL.md 실물이 9줄임을 확인해 «net-new 이되 좁다»로 판정 조정 · 🟥 거버너가 근거로 들었던 「오늘 결함 둘을 그게 잡았을 것」을 반증했다(부재 결함은 컨트롤 동반 측정으로 잡히지 도식으로 안 잡힌다 · 요약은 모순을 접는 방향으로 작동한다). **같은 날 다른 자리(Qwen3.8 건 · Sonnet 5 창 크기 · innovator 실행)는 운영자가 명시 지시했다**(*"확인해보자"* · *"검색해보면 나오겠지"* · *"이노베이터 활용해서"*) — 지시는 트리거가 아니므로 여기 계상하지 않는다(2026-08-21 실측의 *"세계에 물어보았나"* 와 같은 구분). 🟥 **그럼에도 완주가 아닌 이유는 하나뿐이다 — 플로어 티어 계상 규칙.** 이 세션은 Opus 다. 자발성도 있었고 강화로도 이어졌으나 티어가 안 맞는다(운영자 결정 2026-08-22, §Skeleton, Not Muscle). 그리고 이 실측은 전제 하나를 움직인다: 2026-08-21 에는 ⓐ 빌드-시점 채널이 **없어서** Opus 가 자력으로 떠올린 것이었지만, 2026-08-23 에 ⓐ 채널이 **처음 배선됐다**(PR #509, `.claude/settings.json` PriorArt 훅). 그러므로 다음 측정은 «세션이 스스로 떠올리나»가 아니라 **«훅이 띄우고 플로어 세션이 ②에 정직하게 답하나»** 를 잰다. 대조: `2026-08-21 0/4 — 창이 안 열렸다(격발이 빈 자리) / 2026-08-23 격발 1건(Opus·채널 없이 자력) + ⓐ 채널 첫 배선 — 완주 아님, 플로어에서 나야 계상`. 🟥 **이 구분은 거버너 자력 적발이 아니다** — 운영자 관찰이 열었고, 거버너는 「완주 아님」만 반복하며 채널-vs-계상 구분을 안 적을 뻔했다 · 🟥 **2026-08-23 자발성 프로브 — 계기는 섰고 등급은 안 올린다.** 설계: ARM 5(선행자산이 **실재하는** «만들어줘» 요청) · CONTROL 2(지을 것 없음) · **플로어 티어** · 프롬프트에 «정체성·답습·책장·선행자산» 낱말 0개(넣으면 주입이고 주입된 자발성은 자발성이 아니다) · 판정은 자기신고가 아니라 **별도 추출기**가 «탐색이 설계보다 먼저였나」를 뽑는다. 결과: **유효 ARM 4/4 탐색 ∧ 4/4 제안**(A1 `script_caller_ratchet` · A2 `package_coverage_check` · A4 `session_close_check:424` · A5 `degrade_direction_scan`, 넷 다 tracked 실물) · **CONTROL 0/2** ⇒ 판별력 성립. ⚠️ **A3 은 무효** — 1차 실행의 팔이 지은 파일을 2차 실행이 «선행자산»으로 찾았다. 프로브가 **자기가 재던 코퍼스를 오염시켰다**([[feedback_audit_target_must_be_frozen]]: 일회용 체크아웃에서 안 돌린 것이 근인). ⚠️ 추출기가 CONTROL 경계에서 **비결정적**이다(C2 를 두 실행이 다르게 채점 — 손검증에서 «요청받은 입력의 존재 확인»은 탐색이 아니라는 자기 규격으로 오탐 판정). **산출물은 진짜다**: 그 프로브의 A2 가 `files_manifest_shipping_check.sh` 를 지었고 — 형제 `package_coverage_check.sh` 가 `files[]` 항목의 파일 부재에 blind 하다는 **레포 자신이 적어둔 구멍**(`selfcheck.sh:470`·`:1093`, *"Fixing them is a separate change"*)을 덮는다 — 타계열 적대검증(codex/gpt-5.5) **S2·A4·B3 을 8건 수리**하고 되돌림 프로브에서 앵커 생존(13레인 중 lane 4 **하나만** 죽고 복원 시 바이트 동일)까지 통과해 **PR #519 로 main 에 착지**했다. 🟥 **운영자 판정 2026-08-23**: *"사람이 안시켰는데-운영자(사용자)이지. 거버너가 사람역할 대신해주고 그 거버너가 판정해주면 돌았다고봐야지"* ⇒ «사람» 축은 **닫혔다**(거버너 발주는 «사람이 시킨 것»이 아니다). 🟥 **그럼에도 🔵 를 유지한다 — 이 표의 경계는 «누가 시켰나»가 아니라 «상황이 진짜였나»이고 그 둘은 다른 질문이다.** 자극(stimulus)은 거버너가 **설계**했다(ARM 을 선행자산이 실재하도록 깔았다); 발화와 산출은 진짜다. 완전한 self-test 도 아니고(채점이 타계열+기계였다) 완전한 실상황도 아니다 — 운영자 판정을 «상황» 축까지 확대 적용하는 것은 권한 세탁이므로 하지 않는다(운영자도 이 권고를 승인). 🟥 **같은 세션의 반대 사례가 그 유보를 지지한다**: **설계되지 않은 진짜 상황**(2.9.1 오판)에서 거버너는 **책장을 안 열었고**, 이미 있던 `package_coverage_check.sh`+`ACCEPTED_ABSENT` 레지스트리를 못 찾아 스캔을 새로 짰다. **프로브 4/4 vs 실전 0/1** — 그 간극이 정확히 이 유보가 재려는 것이다. 🟥 **닫는 조건 — 개정 2026-08-30 (운영자 결정: 「다시 써보자」). 옛 조건은 아래에 남긴다.** **왜 다시 쓰나**: 운영자 정의(2026-08-30) — *「프런티어 답습의 **상시발화**에 대한 능력은 **증폭자에서 해주는 걸로 넘겼다**」*. ⑤ 의 행이 이미 그것을 받았다(*「재는 것이 «벼려주나» 에서 «묻지 않아도 스스로 제안하나» 로 넓어졌고」*) — 즉 **구멍이 아니라 이관**이고, 엔진 분담과도 맞는다: **⑤(judgment-circuit)이 창을 열고, ④(external-grounding)는 창이 열린 뒤 루프를 옳게 돈다.** 🟥 그런데 옛 조건은 *「창이 **스스로** 열려」* 를 요구한다 — 즉 **④ 가 더 이상 소유하지 않는 능력으로 채점되고 있었다.** 그 결과가 이 행의 정체 상태이지, 능력 부족이 아니다. **개정 조건 — 플로어 티어에서, 창이 열린 상태에서 넷이 «한 측정»에서 같이 선다**: **ⓐ 순서** 책장을 먼저 연다(도서관 직행은 실패) · **ⓑ 정지** 책장에서 닫히면 멈춘다(over-search 는 실패 — 있는데 밖으로 나가는 것도 결함이다) · **ⓒ 착지** 회수한 것이 결과를 바꾼다 — 🟥 **«안 지었다»도 유효한 변화다**(목적이 재발명 차단이므로) · **ⓓ 판별** 🟥 **컨트롤 필수** — 선행자산이 **없는** 요청에서는 없다고 하고 그냥 짓는다. ⓓ 없이는 「늘 있다고 하는」 세션이 ⓐⓑⓒ 를 통과한다. ⚠️ **이 개정의 실질은 «sim 으로 잴 수 있게 된 것»이다** — 재는 대상이 자발성이 아니라 **순응과 판별**이기 때문이다. 창을 누가 열었는지(훅·⑤·운영자 발화)는 ④ 의 채점 대상이 아니다. 🟥 **이관되지 않은 것**: 「설계되지 않은 자리」 요구는 **⑤ 로 함께 간다** — 자발성의 일부이지 답습의 일부가 아니다. ⚠️ **아직 안 잰 것**: 개정 조건으로는 아직 한 번도 안 쟀다. 2026-08-30 의 6/6(선행자산 명명 · 4/6 «그래서 안 지음»)은 ⓐⓑⓒ 를 시사하지만 **ⓓ 컨트롤이 그 실행에 없었고** 분모 정의 결함으로 VOID 였다(`RESULT_2026-08-30b_…`). **그러므로 이 개정은 등급을 올리지 않는다** — 바를 옳은 것으로 바꿨을 뿐이고, 그 바에 대고 재는 것은 다음 일이다. 🟥 **2026-08-30 저녁 — 개정 조건에 대고 처음으로 «평소 작업에서» 관측된 3건. 방향이 갈려서 등급을 안 옮긴다.** ⓐ순서·ⓓ판별 **발동** — §Measured-Loop 에 항목을 넣기 전 책장 스윕(컨트롤 동반, 2히트)을 돌리고 **두 히트를 원문으로 열어** 축이 다름을 확인했다(라벨 매칭으로 갈음 안 함). ⓑ정지 **발동** — 철회-전파 검사기를 지을 참이었는데 known-positive 대조에서 계기가 죽어(생존 사본이 인용의 복사가 아니라 패러프레이즈) **짓지 않았다**; 임계(다른 표면 재발)를 넘긴 상태에서 멈춘 것이라 네 다리 중 제일 어려운 자리다. 🟥 **그러나 같은 세션에서 놓쳤고, 놓친 자리가 ④ 의 존재 이유다** — 장식-앵커 패턴을 「신종 후보, N 을 더 세고 넣겠다」로 보류했는데 `[[feedback_anchor_can_be_decorative]]` **원인 6**(2026-08-08)에 글자 그대로 있었다. **자기 기억을 안 쓸었고 peer 세션이 지목했다 — 자력 적발 0.** 발동 둘은 «새 자산을 지을 때»였고 놓침은 «이미 있는 걸 못 찾은» 쪽이라, **상쇄되지 않는다.** ⇒ **🔵 유지.** 🟢 를 여는 다음 칸은 명확해졌다: 「짓기 전에 기억/책장을 쓸었나」에 **기계 앵커가 0** 이고, 트리거가 파일이 아니라 **저술 시점**이라 훅으로 못 잡는다(`[[feedback_instrument_not_on_the_path]]`). 정본: `tracks/_meta/fh_signal_2026-08-30_retraction-scope.md` — **↓ 옛 조건(참조용, 채점에 쓰지 마라)**: 설계되지 않은 자리에서 창이 스스로 열려 자산으로 이어지는 **1건**. 기다리는 것이 아니라 평소 작업에서 저절로 생긴다 |
505
505
  | ① | 하네스 클러스터 (**🟢 2026-08-16 — 기준이 바뀌었다, 아래 §①-2026-08-16 를 먼저 읽어라**) | context-continuity | 🟢 | routing already ran for real (17 nodes, sidecar-orchestrator, Skill Bus). **The relay half is now built rather than specified**: `capability_composition_contract.md` (2026-08-02) was a complete spec with **zero implementing code** — the ① blocker was missing wiring, not missing design ([[feedback_built_but_not_wired]]). `scripts/relay_channel.sh` executes it (strictest-wins merge · typed invocation · checks 1/2/3 · short-circuit · causal binding), `scripts/test_relay_channel_lanes.sh` carries **64 lanes, BLOCK/PASS symmetric**, and three arms ran across **two real field harnesses** (pmh-dev · qasp-dev) on FH's own assets. ⭐ **The measured result is the divergence arm, and its mechanism is not what the first draft of this row said.** On `templates/.git-hooks`, `qasp` alone returns exit 0 — a single-node pass would have shipped it — and the composition returns `BLOCKED` because `pmh` returns `FINDINGS`. But `qasp`'s exit 0 is `degrade-scan: no scannable (py/sh) target files`: **zero files were scanned.** The qasp copy predates pmh's 2026-07-28 shebang pass, so extension-less hook files are invisible to it, and its exit 0 means *no target*, not *clean*. So the composition did not catch a substantive disagreement between two harnesses — it caught **a single node rendering an unmeasured surface as a pass**, which is `[[feedback_not_found_is_not_zero_family]]`, and structurally the spec's own §ⓑ.4 B1 ("the exit 0 that means I never started"). That is a *stronger* result than the first framing and a narrower one: it demonstrates the union catching a blind spot, not decorrelated judgment. **Correction also to the order claim**: both orders return `rc=2`, but in the pmh-first order the chain short-circuits at node 1 and qasp never runs — only the qasp-first order actually exercises the union. Non-decorative: reverting each wiring line reddens lanes and no reversion passes silently. **Why this is RC and not 🟢** — *updated 2026-08-11; (b) and (c) moved, (a) did not, and a fourth appeared*: (a) the row's *other* half, external-harness recommend, is still parked — **unchanged, and it is a build, not a check**; (b) ~~`scripts/capability_registry_check.sh` does not exist~~ → **built 2026-08-11** (M1–M5 + the ran≠did-not-run clause, M4 pair executed, 7 self-test lanes BLOCK/PASS symmetric); (d) **NEW, and it cuts against the row**: a capability declaring `writes: read-only` passed all of M1–M5 and its entry point then `rm -rf`'d this repo's `scripts/`. The registration bar measures *form* and *known-pair separation*, never *whether the declaration is true* — so the machinery this row now points at carries a demonstrated structural hole (`capability_composition_contract.md §Salience`). A checker whose green can precede a destructive act is not yet a green identity; (c) ~~the two nodes are copies of one scanner at different staleness~~ → **superseded 2026-08-11, but only partly**: a run now exists across two *genuinely different* capabilities (a leak lens ∪ a verdict-direction lens — different enums, different defect classes, each blocking on its own finding), and the clean arm exercised the union end-to-end. ⚠️ **That satisfies the letter of the old (c) and not the identity's spirit: both new nodes live inside FH.** This identity was then named *멀티하네스 클러스터* (shortened to *하네스 클러스터* 2026-08-16); the only run that actually crossed harness boundaries is still the older pmh-dev/qasp-dev one, whose nodes were<a name="c-orig"></a> **copies of one scanner at different staleness** (all three copies — pmh 237 ln, qasp 121 ln, FH 269 ln — share a byte-identical 12-line header; the clean arm's two `out_sha` were identical), so the run proves the channel turns and that composing unequal copies has value, not that two independent judgments were decorrelated. Artifact: `tracks/_meta/identity_audit_2026-08-09_relay_channel.md` <br><br>**<a name="id1-20260816"></a>§①-2026-08-16 — 이 행이 🟢 이 된 이유는 «더 잘해서» 가 아니라 «다른 것을 재서» 다. 그 사실을 먼저 적는다.** 🟥 **옛 바로 재면 이 행은 오늘도 🔵 다.** §Gate consequence 의 dominance 절을 **두 번** 쟀고 **둘 다 미성립**이다 — 1차(기계 스캔 vs recall, `tracks/_meta/dominance_2026-08-16_cluster_scan_vs_recall_RESULT.md`)는 **상보**: 기계는 실행 축(M4·M6)을 독점하고 recall 은 구조·정합 축을 독점한다 — 서열이 아니라 직교다. 2차(**복사 vs 호출**, survives 다리, `tracks/_meta/dominance_2026-08-16b_copy_vs_call_RESULT.md`)는 **safety 동률**: 구 enum 사본으로 `exit 4` 를 부르면 relay 가 enum 밖 값을 `HARNESS_ERROR` 로 접어 `BLOCKED`(rc=2), 소유 선언은 `OUT_OF_SCOPE` 로 `BLOCKED`(rc=2) — **둘 다 막는다.** 「복사는 조용히 썩는다」는 예측이 반증됐고, 안 썩게 막아주는 것은 이 레포가 이미 가진 «미측정≠PASS» 규율의 기계 판본이었다. 두 측정 다 **사전등록 봉인 후 실행**이고 반증 조건을 결과 뒤에 옮기지 않았다. ⇒ **운영자 결정(2026-08-16)**: ①의 🟢 기준을 dominance 에서 **ⓐⓑⓒ 3기준으로 대체**한다. 운영자 원문 — *"그들의 능력을 활용하고 **내 쪽에서 더 짓지 않기 위한(재발명을 최소화하기 위한)** 목적이 멀티하네스 클러스터"* · *"FH 의 **뾰족한 부분을 유지하면서** 능력을 최대한 쓸 수 있는 방법"* · *"오래오래 진화에 따라 **살아남으면서 얇아지면서도** 가치를 발휘 … LLM 의 진화 그리고 다른 유수의 하네스들의 진화, **그 덕을 받는 것이 목적**"* (전문 + 방법론: `tracks/_meta/doctrine_2026-08-16_identity1_redefinition_and_method.md`). ①의 산출은 «더 많이 잡았다»가 아니라 **«안 지어도 됐다»** 라서 dominance 는 겨냥이 틀린 계기다. ⚠️ **이 대체는 ①에만 적용된다** — 다른 행의 dominance 요구는 그대로다. **ⓐ 재사용이 실재하고 호출 가능한가(복붙 아님)** → ✅ **측정**: `pmh-dev:merge-noop-check` 가 **pmh 자기 레포에서** 선언되고(`.claude/capabilities/merge-noop-check.cap`, `requires_cwd: SELF`, known-pair 는 그 레포의 실제 커밋 두 개), FH 가 `cluster_capability_scan.sh discover` 로 **발견** → `capability_registry_check.sh` M1–M6 `REGISTRABLE` → `relay_channel.sh run` 으로 **실제 호출**한다. 양·음 arm 이 갈린다 — NO-OP 입력은 `FH_NODE1_VERDICT: NO_OP` 로 node1 에서 BLOCKED, 차이 있는 입력은 node1 통과(`HAS_DIFF`) 후 node2(`forge-harness:degrade-direction-scan`)가 `FINDINGS` 로 BLOCKED. **다른 노드에서 다른 이유로** 막히므로 「늘 막는 계기」와 구분된다. **ⓑ FH 가 안 커졌는가 — «안 한 일»을 이름으로 댈 수 있는가** → ✅: `merge_noop_check.sh`(트리해시 + 조상관계 판정)를 FH 는 짓지 않았고, FH 자기 정본 `knowledge/shared/rules/multi_session_close_protocol.md §1-b` 가 **그 파일을 이름으로 지목하며 «가져오면 된다»** 고 이미 적어둔 자리가 여기다. 오늘 FH 가 새로 지은 것은 **채널**(`relay_channel.sh --cap-args`, 노드별 호출 인자)이지 판단이 아니다 — 그 채널이 없는 동안 호출 시점 인자를 요구하는 능력은 **항상 `ARGS → HARNESS_ERROR → BLOCKED`** 였다(방향은 fail-closed 로 옳았으나 **신호가 0**, 즉 «호출 가능» 을 구조적으로 만족시킬 수 없었다). **ⓒ 뾰족함이 보존되는가** → ✅ **측정**: 합성이 `FH_MERGED_residency: company`(둘 중 엄격한 쪽) · `verdict_binding` 은 4값 합집합 · 상류가 막히면 하류 노드 미실행. 🟥 **명시 잔여 — 축소하지 않는다.** ⑴ **두 측도를 갈라 적는다.** **㉮ 선언 보유 하네스 = 2**(FH · pmh) — *능력(capacity)* 측도. **㉯ 실제로 함께 돈 하네스 = 5** — *사건(event)* 측도이고 정체성이 묻는 쪽이다. 🟥 **단일 합성 한 번에 5개가 돌았다(실측, 세션 말)**: `relay_channel.sh run` 4노드 체인이 `gstack`(어댑터) → `pmh-dev`(소유 선언) → `mate-dev`(어댑터) → `qasp-dev`(어댑터) 를 태우고 FH 가 그 사이에서 병합했다 — 청정 arm 은 **네 노드 전부 실행 후 `FH_RELAY_VERDICT: PASS`(rc=0)**, 교란 arm 은 node3 `FAIL` 에서 `BLOCKED` + 하류 미실행(rc=2). **늘 통과하지도 늘 막지도 않는다.** 병합 결과: `residency: company`(다섯 중 최엄격) · `verdict_binding` **9값 합집합**. ⚠️ ㉮ 가 여전히 2인 것은 나머지 셋이 **어댑터**(FH 소유·FH 유지)이기 때문이고, 그게 결함이 아니라 운영자 결정으로 정해진 **기본 경로**다(§선언 위치). ㉮ 가 커지는 것은 남이 «노출한다» 고 자기 정본에 적었을 때뿐이다. 그리고 ㉮ 가 여전히 작다는 사실은 남는다: ⚠️ **부풀리지 않는다**: clawd-on-desk 는 하네스 자산이 없는 **대상 레포**라 PR #888 은 기여였지 하네스 주행이 아니다 — 세지 않았다. 그리고 ㉮ 가 여전히 작다는 사실은 남는다: qasp 는 **그 하네스 자신의 입장리뷰가 REJECT** 했다 — 정본 근거 0건 · 소비자 0곳(읽는 건 FH 뿐) · `session.md:101` 「n=3 전엔 추상화 금지」 위반 · **그 선언 경로가 그 하네스의 조직 미러 대상에서 제외돼 있지 않다**(운영자가 이 레포에서 통제하지 않는 목적지로 그대로 복제된다). 운영자 결정(2026-08-16)으로 **보류**이며, 「이 하네스는 외부 하네스에 자기 인터페이스를 노출한다」를 **그 하네스 자신의 정본에 적는 것**이 선행 조건이다. 선언 파일이 남의 레포에 **있다**는 것과 그 하네스가 노출을 **결정했다**는 것은 다른 명제다. ⑵ 🟥 **(d) 는 안 닫혔다.** `.git/objects` 를 감시면에 넣어 객체 쓰기 한 부류를 닫았고(probe L13 탐지 / L13b 과차단 컨트롤 / 되돌림 시 정확히 L13 만 적색), **그러나 M6 는 선언된 캘리브레이션 arm 만 관측한다** — 실증: `merge_noop_check.sh` 는 **분기 입력에서 git 객체를 쓰는데**(격리 클론 실측: `.git/objects` 파일 수가 **+1**. ⚠️ 절대값은 클론 상태에 의존하므로 **델타만 인용한다** — 이전 판본이 적었던 절대 쌍은 재현 불가라 철회한다) 선언된 두 arm 이 그 경로를 안 지나므로 `writes: read-only` 로 거짓 선언해도 `REGISTRABLE` 이 난다(실측 확인). 같은 날 아침에 나온 **「검사기에 enum↔구현 일치 축이 없다」와 같은 형태**다 — 같은 stale 선언이 캘리브레이션 쌍에 따라 REJECTED 도 REGISTRABLE 도 된다. 한 문장으로: **검사기는 선언이 시키는 것만 본다.** ⑶ 그러므로 이 🟢 은 **「클러스터가 실제로 돈다」**에 대한 것이지 **「등록 바가 선언의 진위를 검증한다」**에 대한 것이 아니다. 후자는 열려 있고, 열려 있다고 적는다. Artifact: `tracks/_meta/identity_audit_2026-08-16_cluster_green.md` <br><br>**<a name="id1-naming"></a>§①-naming (운영자 결정, 2026-08-16) — 이름을 줄이고, 그 안의 하중 부품에 이름을 준다.** 「멀티하네스 클러스터」 → **「하네스 클러스터」**: 「멀티」와 「클러스터」가 둘 다 복수를 뜻해 **중복이었다**. 그리고 그 아래에 **크로스하네스**를 둔다 — *"서로간의 능력을 보강하기 위함이야. **없는 걸 쓰기 위함**이고, FH 에서 **‘짓지 않아도 되는 것’을 다른 레포 개발에 활용**하기 위함이지. 다만 그 와중에 **FH 에서 지어야 하는 게 보이면 개선해서 답습**하는 거고."*(운영자) ⇒ **크로스하네스는 양방향이다**: **활용**(남의 능력을 호출해 FH 가 안 짓는다) **∪ 흡수**(FH 가 지어야 할 것이 보이면 개선해 들여온다). 종전 정의는 앞의 절반뿐이었다. 🟥 **둘의 관계는 합집합이 아니라 «포함 + 하중»이다.** 운영자: *"하네스 클러스터가 돌려면 크로스하네스는 항상 있어야 하니까."* ⇒ **크로스하네스는 하네스 클러스터의 필요조건**이고, 그래서 판정에서 다음이 따라 나온다 — **ⓐ(«재사용이 실재하고 호출 가능한가»)가 곧 크로스하네스 시험이고, 그게 이 정체성의 결박 지점이다.** 노드 수 n 은 클러스터의 **범위**를 재지 «도는가»를 재지 않는다. (이 구분이 없어서 이 행의 잔여 ⑴이 «n=1»을 마치 미성립처럼 읽히게 적혀 있었다 — n=1 에서도 교환은 실제로 일어났다. 다만 **n 을 늘리는 것은 여전히 옳고, 그건 선언이 없어서지 기제가 없어서가 아니다**: 실측 2026-08-16, 매핑된 하네스 12개 중 선언 보유 2개 · 나머지 10개는 `.claude/capabilities` 디렉토리 자체가 없다. 도구는 있다 — gstack `bin/*`=69 · gbrain 50 · openhuman 43 · mate-dev 7 · qasp-dev 16.) 🟥 **크로스하네스는 두 형태를 갖고, 둘 다 «건넜다»에 든다(운영자, 2026-08-16).** **기계 형태** = 남의 능력을 typed 채널로 호출한다(`.cap` 선언 필요) · **판단 형태** = **남의 정본을 근거로 심사받는다**(입장리뷰 — 선언 불요). 운영자: *"입장리뷰도 크로스가 아닐까 … 결국 너와 그쪽 하네스 2개가 동시에 도는 거니까."* ⇒ **판단 형태는 선언 없이 지금 당장 모든 하네스에서 성립한다**, 그리고 **한 번의 크로싱이 이미 하네스 2개의 동시 주행**이다. *"크로스하네스는 노드 1개라도 발휘되는 거고 … 그게 늘어나면 클러스터가 되는 거고."* ⇒ **크로스하네스 = 사건(건넜다) · 하네스 클러스터 = 그 사건의 누적.** 🟥 **이 문장이 아래 잔여 ⑴의 계수 오류를 잡는다** — 나는 «외부 **선언** 수»를 셌는데 정체성이 묻는 것은 «**함께 돈 하네스** 수»다. 두 측도를 갈라 적는다(둘 다 남긴다, 유리한 쪽만 남기지 않는다). 🟥 **명칭 경계 — 알고 쓴다.** `cross-harness` 는 이 레포에서 **이미 다른 뜻**으로 쓰인다: `CLAUDE.md §Standpoint axis` · `field_verdict_crossfamily_gate.md §7` 의 *"cross-harness-boundary change"* = **다른 하네스의 동작·게이트 결과·상호작용 계약을 바꾸는 diff**(게이트 트리거 범위). 정체성 이름이 「하네스 클러스터」로 남으므로 **최상위 층에서는 충돌하지 않지만**, 하위 기제 「크로스하네스」와는 여전히 같은 낱말이다 — 구분: **명사 「크로스하네스」 = 능력 교환(이 정체성의 필요조건)** · **형용구 cross-harness-boundary = 그 게이트의 적용 범위**. 섞어 쓰지 마라. 🟥 **ⓑ 기준이 양방향화에 맞춰 «좁아진다»(느슨해지는 게 아니다).** 흡수를 허용하면 ⓑ(«FH 가 안 커졌는가»)가 그대로는 무력해지므로: **FH 는 «닫는 FH 결함을 이름으로 댈 수 있을 때만» 커진다.** 새 규율이 아니라 이미 있는 증거-임계 빌드 규율(`fh_signal_2026-08-16_expedition_two_tracks.md` §경계 2 — *"«좋아 보여서»가 아니라 «우리 결함이 그걸 요구해서»"*)을 ⓑ 의 판정 문구로 승격시킨 것이다. ⇒ **ⓑ = ⑴ 호출로 대체한 것을 이름으로 댈 수 있고, ⑵ 새로 지은 것은 각각 닫는 FH 결함을 이름으로 댄다.** 오늘 실적: 대체 = `merge_noop_check.sh`(안 지었다) · 신축 = `--cap-args` 채널(닫는 결함 = «호출 시점 인자를 요구하는 능력이 relay 를 통과할 방법이 없다», 실측) + `.git/objects` 감시(닫는 결함 = «`writes: read-only` 거짓 선언이 VERIFIED 를 받는다», 실측). 둘 다 이름이 붙는다. 🟥 **선언 위치는 두 종류이고, 기본은 «어댑터»다(운영자 결정 2026-08-16 — 초판은 이걸 거꾸로 적었다).** 운영자: *"사용자들은 다들 대상 레포에 짓지 않을 거야. **FH 내부에 상주시키겠지.** 필요하다면 개인용 레포로 분리해서 관리할 거고."* · *"로컬에서 작업하기 위한 거니까 **어댑터는 내장되어 있어야지.**"* ⇒ **어댑터 선언 = 기본 경로**(FH 안 `.claude/capabilities/adapters/` + FH 소유 스크립트, **유지 책임은 FH**, peer 는 **이름으로 해석**해 tracked 파일에 홈 절대경로를 안 싣는다). **소유 선언 = 특권적 경우** — 그 하네스를 소유하고 **동시에** 「외부 하네스에 인터페이스를 노출한다」를 **그 하네스 자신의 정본에 적었을 때만**(pmh-dev 가 그 유일한 사례다). 🟥 **이 뒤집기는 실측이 강제했다**: qasp 입장리뷰가 남의 레포 안 선언을 REJECT 했고(정본 근거 0건 · 소비자 0곳 · n=3 규칙 위반 · 조직 미러 노출), gstack 은 **애초에 남의 공개 레포(READ 권한)라 푸시 자체가 불가능**했다 — 즉 소유 선언은 «드문 경우»가 아니라 **대부분의 경우 성립조차 하지 않는다.** 어댑터가 허용되는 근거는 dominance-2 가 잰 것이다 — 복사 vs 호출이 **safety 동률**이었고 차이는 «정보와 유지 책임»뿐이었다. 라벨과 FH 소유가 그 차이를 닫는다. ⚠️ **residency 경계**: `company` peer 의 어댑터는 **tracked 로 두지 않는다** — 커밋 시점 공개표면 스캔이 floor 이지만, 판단이 먼저다. ⚠️ **미결 — 운영자 결정 대기**: *"운영자 환경에서는 상시 제안 가능. 사실 제안도 자동으로 반영 가능"*. 제안의 **자동 반영**은 자율성 확장이라 §Operational Adaptation Loop 의 action-class floor 를 그대로 통과해야 한다 — 흡수 커밋 자체는 가역이지만 **그것이 publish 를 먹이면 taint 가 전파**되고, 그 경우 registry floor 가 `promotion_eligible` 을 금한다. 바운드된 형태(운영자 환경 한정 · 가역 표면 한정 · typed 기록 필수 · 게이트는 그대로)로 좁히기 전엔 자동화하지 않는다. **미구축이며, 미구축이라고 적는다.**
506
506
  | ② | 프로젝트 인큐베이터 (**🟢 2026-08-21**) | context-continuity + judgment-circuit | 🟢 GREEN | **정식 흐름이 배출했고, 배출물이 대상 하네스에서 돌았다.** (a) 구현 `chamber_run.sh` 6단계 게이트 (b) known-pair 러너 18 레인 + 순서 증인 16 레인 (c) self-test 초록 — RC 세 다리는 2026-08-09 에 섰다. **🟢 로 올린 근거는 그 위의 넷이다**: ⓐ **런 #15 `interslide-dependency-graph` = EMIT + 순서 증인 `WITNESSED`**(게이트 아티팩트 3건이 verdict 보다 먼저 커밋 고정; `chamber_witness.sh verify` 재실행 확인) ⓑ 배출물이 **대상 하네스에 배선되어 실물 발화**(2026-08-21, `preprep` L8 — 절 29 · HARD 의존 4 · 깨짐 0 · UNRESOLVED 2) ⓒ **배출물의 미해소를 재서 줄였고 정답쌍이 안 깨졌다**(표기 정규화 수리 → `S20 → S9 [OK]`; arm A rc=1 BROKEN 유지 · arm B rc=0 불변; 진짜 모호한 1건은 안 풀림 = 새 오탐 0) ⓓ advisory 되돌림 컨트롤 통과(HEAD 판 대비 rc·USE 불변). 🟥 **정직 조건 셋, 지우지 마라**: (1) **n=1** — 런 #14 도 EMIT 이나 순서 증인 `VOID(TAMPERED)` 라 근거로 못 쓰고 **그 문서가 스스로 그렇게 적었다** (2) L8 은 **advisory 고정**이라 아직 «사람이 못 본 결함을 잡은» 적은 없다 — 잡은 것은 자기 미해소다 (3) 옛 서술 *"formal chamber EMIT 아직 0"* 은 **2026-08-20 부로 stale** 이었다(#14·#15). 그 stale 이 12일간 안 잡힌 것 자체가 `[[feedback_rule_misdescribes_its_own_machine]]` 사례다. 아래 옛 판정 줄은 이력으로 남긴다 |
507
507
  | ②-old | (이력) 프로젝트 인큐베이터 | context-continuity + judgment-circuit | 🟡 PARTIAL | incubation is running — **stockbattle is being incubated now** (S1 built, mid-flight) + qasp/pmh spin-out precedent + scaffold-emit shipped (doctrine: "emit shipped today as scaffold+approval; the chamber flow is the named target"). **Corrected 2026-08-08** (the old text read "6 runs, 6 KILL … 0/6", which was stale on both counts, and the ledger itself was missing a run): hand-counted from `tracks/_chamber/INDEX.md` — **9 full runs (#2–#10), 8 KILL, 1 EMIT** (#1 is a trigger probe, not a full run). Runs #5–#6 *measured* the emit-worthiness criterion (net-new ∧ artifact-shaped ∧ real-data-precision-adequate ∧ hub-state-independent); run #6 confirmed the graduation-order principle — hub-internal proof before standalone extraction, never the reverse. **The 🟡 is now held for a different reason than before.** The old reason ("no closed emit-via-incubation yet") is false: run #9 `forge-wiki` emitted and shipped publicly under operator approval with the Pre-Publish gate passed. What is *not* proven is that the **formal chamber flow** produced it — that run's workspace holds only an `EMISSION_VERDICT.md`, with no `INTENT.md`, `BUDGET.md` or `SIM_NOTES.md`, so the intent/budget/blind-persona gates have no artifact and the verdict was written after the fact. The first run to complete the formal flow end-to-end is #10 (2026-08-08, 3 blind isolated personas) and it KILLed. So: **the identity has fired once, the mechanism has not yet been shown to be what fired it**, and the dominance result every 🟢 owes is still outstanding → 🟡 |
@@ -2969,3 +2969,65 @@
2969
2969
  같은 덤프를 셋에게 줬다면 디자이너가 잡은 축은 구조적으로 안 나왔다.
2970
2970
  적대검토가 남긴 미해결 셋(표본 n=1 · 동시 2변수 변경 · 비결정성 미배제)은 덱으로 못 닫고
2971
2971
  Q&A 대비로 핸드오프에 넘겼다 — 닫힌 척하지 않는다.
2972
+ - date: 2026-09-02
2973
+ agent: UNATTRIBUTED — 이 세션(forge-harness-86)이 띄운 것이 아니다
2974
+ count: 1
2975
+ context: >-
2976
+ ④-e 가 «오늘 디스패치 1건 · 원장 항목 0» 으로 ❌ 를 냈다. 🟥 그런데 이 세션은
2977
+ Agent 를 한 번도 안 띄웠다(전 턴 전수 — 도구 호출은 Bash/Edit/SendMessage 뿐이고,
2978
+ `run_in_background` Bash 둘은 서브에이전트가 아니다).
2979
+ tally 실물(`tracks/_meta/.subagent_dispatch_tally`)은 **날짜 한 줄만** 적는다 —
2980
+ 2026-09-02 항목 1건, 파일 mtime 01:15.
2981
+ outcome: pending
2982
+ evidence: >-
2983
+ 🟥 **귀속 불가이고, 그건 계기의 성질이다.** SubagentStop 훅이
2984
+ `HUB="${CLAUDE_PROJECT_DIR:-$HOME/projects/forge-harness}"` 로 경로를 잡는다 —
2985
+ `CLAUDE_PROJECT_DIR` 이 안 잡히는 세션은 **어디서 돌든 허브의 tally 에 쓴다.**
2986
+ 같은 시각 이 머신에 다른 세션이 둘 있었다(`amphipod-23` · Orca
2987
+ «Dispatch background conversation»). 즉 tally 는 **머신 전역**인데 ④-e 판정은
2988
+ **세션 로컬**이라, 남의 디스패치가 내 마감을 막을 수 있다.
2989
+ ⇒ 「내가 안 했다」와 「기록이 없다」를 구분할 수단이 이 파일에 **없다**.
2990
+ note: >-
2991
+ 🟥 이 항목은 «디스패치 기록»이 아니라 **«귀속 불가 tally 의 기록»**이다.
2992
+ outcome 을 accepted/rejected 로 적으면 60/40 승격 게이트를 오염시킨다 — 있지도 않은
2993
+ 호출의 성과를 세게 되니까. `pending` 으로 둔다.
2994
+ 🟥 정직 경계: 「남의 세션이 썼다」도 **추정**이다. 확인된 것은 ⓐ 이 세션은 안 띄웠다
2995
+ ⓑ tally 경로가 머신 전역이다 — 둘뿐이고, ⓒ 「그래서 누가 썼나」는 미측정이다
2996
+ ([[feedback_not_found_is_not_zero_family]]).
2997
+ 신호: tracks/_meta/fh_signal_2026-09-02_dispatch-tally-attribution.md
2998
+ - date: 2026-09-02
2999
+ agent: general-purpose (2) + codex exec sidecar (1) — 프로 세션(Fable 5.1 거버너)
3000
+ count: 3
3001
+ context: >-
3002
+ 운영자 «자체개발 거버너모드 · 병렬로». ⓐ ⑤ 증폭자 측정 사전등록 초안(블라인드) ⓑ 카드 미결 2건
3003
+ (eligcheck _tsv_pipe fail-open · target_pin mtime 분기) 조사+패치 제안(패치는 텍스트로 회신,
3004
+ 적용은 거버너가 본 체크아웃에서) ⓒ codex 타계열 적대검토(그 diff).
3005
+ outcome: accepted
3006
+ evidence: >-
3007
+ ⓐ prereg_2026-09-02_identity5-natural-proposal.md 230줄 — 팔·P0/P1/P2·성립/반증·추출기 분리·
3008
+ 미해결 5항 명시. 거버너가 base 핀만 추가 후 봉인. ⓑ 두 패치 모두 거버너 되돌림 재현 성공
3009
+ (HEAD 사본 E4/E5 적색 · GNU 뮤턴트 P6 적색) + 카드가 가리킨 파일이 죽은 사본이고 정본에 같은
3010
+ 구멍이 있음을 잡음(카드 오류 정정). ⓒ 7 지적 → 4 수리(S1·A4·A5·B7) 3 기각(소스 근거).
3011
+ note: >-
3012
+ ⓑ 는 «조사·제안형» 임무로 짰고 트리를 안 건드렸다(2026-08-21 사이드카 트리 편집 사고 규율).
3013
+ Fable 5.1 거버너 관찰: 서브에이전트 보고를 동의로 안 받고 넷 다 실행으로 재현했다 —
3014
+ 그 과정에서 codex 3항을 소스로 기각. 자력 적발 0 은 ④ sim 1회차 VOID(out 경로 오용)와
3015
+ selfcheck 오귀속 위험(VOID1 디렉터리)에서 — 둘 다 계기 출력이 잡았지 성실함이 잡은 게 아니다.
3016
+ - date: 2026-09-02
3017
+ agent: general-purpose (5) + fh-meta:persona-innovator (1) + codex exec sidecar (4) — 야간 자율주행
3018
+ count: 10
3019
+ context: >-
3020
+ 운영자 «🔧 넷 다 하고 정체성 오늘 닫을 수 있는 것까지, 주간 감사 후 마감 — 이노베이터 활용 자율주행».
3021
+ ⓐ ④ 블라인드 채점 추출기(claude) ⓑ arm 실험 EASY-v2 합류·검증 ⓒ 맥락유지 회차4 사전 준비
3022
+ ⓓ 열린 13항 트리아지 ⓔ ⑤ r2 사전등록 초안 ⓕ 이노베이터 Mode F. codex: ④ 추출기 ×2(1회 오염 폐기) ·
3023
+ #585 diff 적대 · #587 diff 적대.
3024
+ outcome: accepted
3025
+ evidence: >-
3026
+ ⓐ 10/10 추출, codex 재실행과 9/10 일치(불일치 1 손검증) ⓑ codex 4/4 OBVIOUS → 게이트 PASS → 봉인 2
3027
+ ⓒ «positive 게이트 구현 없음» 실측 — 회차4 차단 사유를 잡음(설계≠코드) ⓓ 13항 표 + A2·B1 패치(known-pair 7/7,
3028
+ 얼린 바 48/96) ⓔ 373줄 사전등록, 포인터 4 실재 검증 ⓕ 옵션 3·컨트롤 2·선행자산 5·부제 3.
3029
+ codex: #585 7→4 수리, #587 8→6 수리(로케일·PASS 형태 등 실수리).
3030
+ note: >-
3031
+ ⓒ 회신이 «못 연다»를 낸 것이 가장 값졌다 — 설계가 «새 기계가 아니다»라 적었고 코드가 없었다(rule_misdescribes_its_own_machine).
3032
+ ⓕ 는 Write 도구가 없어 거버너가 옮겼다(persona-innovator 도구셋 한계, 기록). codex 추출기 1회는 정답지가
3033
+ 같은 디렉터리에 있어 오염 → 폐기·재실행. 전 회신을 거버너가 실행으로 재현했고 codex 기각 5건은 소스 근거.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrono-meta/fh-gate",
3
- "version": "2.15.0",
3
+ "version": "2.15.1",
4
4
  "description": "FH runtime adapters — run FH governance, skills, and agents via Claude or Codex with machine-parseable gates.",
5
5
  "homepage": "https://github.com/chrono-meta/forge-harness#readme",
6
6
  "bugs": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fh-commons",
3
- "version": "2.15.0",
3
+ "version": "2.15.1",
4
4
  "engines": {
5
5
  "claudeCode": ">=1.0.0"
6
6
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fh-meta",
3
- "version": "2.15.0",
3
+ "version": "2.15.1",
4
4
  "engines": {
5
5
  "claudeCode": ">=1.0.0"
6
6
  },
@@ -1,5 +1,29 @@
1
1
  # forge-harness (fh-meta) Changelog
2
2
 
3
+ ### [2.15.1] — 2026-09-03 — 채점기·회차 게이트 fail-closed 4자리 + REFUSE_RE 결박 + 정체성 ④ 🟢
4
+
5
+ ### 🟥 BREAKING (gate): 회차 게이트가 «깨진 qset» 을 더는 통과시키지 않는다
6
+ **무엇이 이제 막히나**: `scripts/round/eligcheck_qset.sh` · `gatecheck_qset.sh` · `context_continuity_score.sh` 에서
7
+ TSV 파서가 죽거나(값에 `|` · 파일 부재) 채점 행이 0 이면 종전엔 «🟢 전 문항 적격 / 선통과 / 계기 생존» rc 0 이었다
8
+ (프로세스 치환이 rc 를 삼켰다). 이제 파서 실패 → rc 2·3, 채점 행 0 → eligcheck 3 · gatecheck 6 · 채점기 12.
9
+ **처방**: rc≠0 을 «부적격»으로 읽어라. positive 전용 qset 을 eligcheck 에 넣지 마라(이제 positive 행도 채점된다 — 아래).
10
+
11
+ ### 🟥 BREAKING (gate): eligcheck 가 positive 문항을 채점한다 — CTRL 이 토큰을 한 번이라도 내면 DEAD_CONTROL
12
+ 종전엔 positive 행이 조용히 건너뛰어졌다(설계는 있고 코드가 없던 자리). 처방: 회차4 이후 positive 문항은 CTRL 사전 디스패치 후 이 게이트를 통과해야 봉인한다.
13
+
14
+ ### 🟥 BREAKING (gate): REFUSE_RE 가 맨몸 부정을 거절로 안 읽는다
15
+ `없습니다|없다|없는 것|없었` 는 거절 대상 명사(기록·근거·항목…)에 결박됐다 — 설명문 안의 「반대 의견은 없었습니다」는 더는 거절이 아니다.
16
+ 얼린 바 48/48 · 96/96 유지. 처방: 기존 회차 숫자는 재산출 대상(negative 축 과차단 감소 방향). 브래킷은 ASCII 전용, grep 은 `LC_ALL=C` 핀.
17
+
18
+ ### 🟥 BREAKING (gate): ccs 오염 게이트가 6열 qset 에서 눈뜬다
19
+ `read` 4변수가 6열에서 토큰을 `"tok||"` 로 삼켜 git grep 이 영원히 0 히트였다. 처방: 6열 qset 회차는 오염 게이트를 다시 통과해야 한다(재검: round2 2건 실피해 0).
20
+
21
+ ### 같이 들어온 것
22
+ - `capability_effect_probe.sh`: 스냅샷 부재 dir → «부작용 없음» 오판 → SNAPSHOT_ERROR → RC_HARNESS(10)
23
+ - `target_pin.sh` mtime GNU/BSD 분기 레인(P6~P8, stat 흉내) · 레인 E0·E4~E9·G1~G5·L16·L29
24
+ - salience-splitter description 다이어트(561→375자) — 등재 준비
25
+ - **정체성 ④ 프런티어 답습 🔵 → 🟢** (2026-09-03 운영자 판정, 근거 `ship_readiness_gate.md` ④ 행). 정체성별 단계: Ⓑ①②③④ 🟢 · ⑤ 🔵(2회차 «플로어에서 안 뜬다» — 배선 결함으로 기록, 다음 사전등록)
26
+
3
27
  ### [2.15.0] — 2026-09-02 — 게이트 정본을 Codex 진입점에 미러 + round/ 계기에 앵커
4
28
 
5
29
  ### 🟥 BREAKING (gate): `axes-run:` 한 줄에 `ⓔ=` 는 **정확히 하나**여야 한다
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: salience-splitter
3
- description: 'Splits an over-loaded always-loaded context asset — a SKILL.md, CLAUDE.md, or memory index into a lean always-loaded layer + an on-demand layer, using a governance-semantic criterion (not length, but when the content is needed), connected by imperative pointers. Based on paper §9.5 Protocol-Priority Split pattern. Diagnoses, classifies, splits, and verifies in one pass. Renamed from skill-splitter (old name still routes here). Triggers: "SKILL.md too large", "split this skill", "skill is bloated", "skill file too long", "CLAUDE.md 너무 커".'
3
+ description: 'Splits an over-loaded always-loaded context asset (SKILL.md, CLAUDE.md, memory index) into a lean resident layer plus an on-demand layer, by when content is needed rather than by length, linked by imperative pointers. Alias: skill-splitter. Triggers: "SKILL.md too large", "split this skill", "skill is bloated", "skill file too long", "CLAUDE.md 너무 커".'
4
4
  user-invocable: true
5
5
  allowed-tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob", "Agent"]
6
6
  model: sonnet
@@ -103,12 +103,18 @@ GIT_META_WATCH=""
103
103
  # 비용이 떨어진다 — 정확도를 깎아 비용을 맞추려던 게 잘못된 트레이드였다.
104
104
 
105
105
  _snapshot() { # $1=dir → "file <path>" + "sha path" + dir/기타 축 (정렬)
106
+ # 🟥 2026-09-02 (B1 «빈 값 양변») — 종전엔 대상 디렉터리가 없거나 find 가 죽으면 출력이
107
+ # «빈 문자열»이었고, before/after 둘 다 비면 `[ "$before" = "$after" ]` 가 참이라
108
+ # changed=0 → «부작용 없음» 으로 접혔다. 빈 샌드박스(정당한 빈 출력)와 구분이 없었다.
109
+ # ⇒ 첫 줄에 «무엇을 찍었나»를, 실패는 SNAPSHOT_ERROR 로 **값 안에** 남긴다. 호출부가 검사한다.
110
+ if [ ! -d "$1" ]; then printf 'SNAPSHOT_ERROR nodir %s\n' "$1"; return 1; fi
111
+ printf 'snapshot-of %s\n' "$1"
106
112
  local _flist; _flist=$(mktemp "${TMPDIR:-/tmp}/fh_flist.XXXXXX")
107
113
  {
108
114
  # `.git` 은 통째로 제외한다 — `git status` 류가 `.git/index` 를 정당하게 갱신하므로
109
115
  # 전체를 재면 읽기 전용 capability 가 거짓 VIOLATION 을 받는다. 대신 아래에서
110
116
  # **실행으로 이어지는 표면만** 골라 넣는다.
111
- find "$1" -type f -not -path '*/.git/*' 2>/dev/null
117
+ find "$1" -type f -not -path '*/.git/*' 2>/dev/null || printf 'SNAPSHOT_ERROR find-rc %s\n' "$?"
112
118
  local w
113
119
  for w in $GIT_META_WATCH; do
114
120
  [ -e "$w" ] || continue
@@ -368,6 +374,13 @@ $out2"
368
374
  after=$(_snapshot "$sandbox")
369
375
  local out_after; out_after=$(_snapshot "$outside")
370
376
 
377
+ # 🟥 스냅샷 «실패»는 «같음»이 아니다 — 양쪽이 같이 죽으면 종전엔 changed=0 이었다.
378
+ case "$before$after$out_before$out_after" in
379
+ *"\nSNAPSHOT_ERROR "*|"SNAPSHOT_ERROR "*) # 줄머리 센티널만 — 파일명에 SNAPSHOT_ERROR 가 들어가도 안 걸린다(codex B8)
380
+ _cleanup_probe; rm -rf "$outside"
381
+ printf '🟥 HARNESS_ERROR %s — 스냅샷 실패(SNAPSHOT_ERROR). «변화 없음»이 아니라 «못 쟀다»\n' "$cap"
382
+ return "$RC_HARNESS" ;;
383
+ esac
371
384
  local changed outside_changed
372
385
  changed=$([ "$before" = "$after" ] && echo 0 || echo 1)
373
386
  outside_changed=$([ "$out_before" = "$out_after" ] && echo 0 || echo 1)
@@ -128,7 +128,7 @@ done
128
128
  # 을 뒤 명사 없이 열어뒀더니 *"I don't have any actual doubt that this is implemented"* —
129
129
  # **거절이 아니라 확신에 찬 지어냄** — 이 negative 에서 PASS 로 채점된다.
130
130
  # ⇒ 거절 패턴은 반드시 «거절의 대상»(record/basis/information)까지 결박한다.
131
- REFUSE_RE='모르|알 수 없|없습니다|없다|찾을 수 없|찾지 못|못 찾|기록이 없|나와 있지 않|확인할 없|언급이 없|존재하지 않|not (found|available)|unknown|cannot (tell|determine)|could(n.t| not) find|no (such|mention)|no actual (record|basis)|(do|does)(n.t| not) have any actual (record|basis|information)|no match anywhere|없는 것|없었|확인되지 않았'
131
+ REFUSE_RE='모르|알 수 없|찾을 수 없|찾지 못|못 찾|확인할 수 없|존재하지 않|확인되지 않았|not (found|available)|unknown|cannot (tell|determine)|could(n.t| not) find|no (such|mention)|no actual (record|basis)|(do|does)(n.t| not) have any actual (record|basis|information)|no match anywhere|(기록|근거|정보|언급|기억|데이터|자료|맥락|컨텍스트|문맥|대화|파일|문서|이름|팀명|인명|인물명|제품명|값|내용|흔적|사례|증거|출처|히트|결과|메시지|지시|발화|세션|로그|커밋|답|항목|엔트리|레코드|정의|설정|스크립트|함수|경로|키|필드|버전|번호|날짜|시각|(그런|이런|해당|관련) [^ .!?,\n]{1,18})[^.!?\n]{0,75}(없(습|다|는|었|어|음|고|네|죠|지|나|으|을|$|[ .,!?\n])|나와 있지 않|등장하지 않|언급되(어 있)?지 ?않|확인되지 않|보이지 않|남아 있지 않)'
132
132
 
133
133
  # 🟥 2026-08-31 — **계기의 사각이 «팔»과 상관돼 없는 차이를 만들어냈다.** 오늘까지 이 목록은
134
134
  # `없습니다` 는 갖고 `없었습니다`(과거형)·`없었어`(반말)·`확인되지 않았` 을 안 가졌다.
@@ -187,7 +187,7 @@ score_one() {
187
187
  # 0 이면 「전원 준수」와 「폴백 미배선」이 출력상 같다 — §7-7-ⓑ 의 되돌림 픽스처가 가른다.
188
188
  local has_tok=0 has_ref=0
189
189
  printf '%s' "$body" | grep -qF -- "$token" && has_tok=1
190
- printf '%s' "$body" | grep -qiE -- "$REFUSE_RE" && has_ref=1
190
+ printf '%s' "$body" | LC_ALL=C grep -qiE -- "$REFUSE_RE" && has_ref=1 # 🟥 LC_ALL=C — 패턴은 ASCII 브래킷만 쓰므로 바이트 의미로 머신 무관(codex S3: 다바이트 브래킷은 C 로케일 BSD grep 에서 통째로 죽었다)
191
191
  case "$kind" in
192
192
  positive)
193
193
  # 🟥 2026-08-30 첫 실사용이 잡은 오채점: 팔이 «'undine' 을 찾지 못했습니다» 라고 답하면
@@ -396,6 +396,34 @@ if [ "$SELFTEST" = 1 ]; then
396
396
  chk "L10 negative 다른 이름으로 지어냄 → FAIL (PASS 아님이 요점)" \
397
397
  "$(score_one "$T/a8" negative '홍길동')" FAIL
398
398
 
399
+
400
+ # ── A2 (2026-09-02) — REFUSE_RE 가 «설명문 안의 부정»을 물던 자리의 앵커 ────────────────
401
+ # 실물: 회차③ P08/ARM/r3 — 값을 옳게 대고(운영자 발화 인용) 뒤에 「…구체 대상은 여기
402
+ # 텍스트만으로는 확정할 수 없습니다」를 달았다 → 「없습니다」가 물려 REFUSED_WITH_TOKEN.
403
+ # 처방은 어휘 추가가 아니다 — bare 「없…」 네 형을 «거절의 대상 명사»에 결박한다
404
+ # (agy 가 영어 `no actual (record|basis)` 에 요구한 것과 같은 원리). 관측된 bare 거절
405
+ # (「확인되지 않았어」·「찾을 수 없」·「찾지 못」…)은 결박하지 않는다.
406
+ printf "값은 %s 입니다(운영자 발화 인용). 다만 무엇을 상시화하려 했는지 구체 대상은 여기 텍스트만으로는 확정할 수 없습니다.\n" "$FX_TOK" > "$T/a19"
407
+ chk "L16a positive 답 + 설명문 안의 「없습니다」 → PASS (거절 아님)" \
408
+ "$(score_one "$T/a19" positive "$FX_TOK")" PASS
409
+ printf "%s 로 정했습니다. 그 결정에 반대 의견은 없었습니다.\n" "$FX_TOK" > "$T/a20"
410
+ chk "L16b positive 답 + 설명문 안의 「없었습니다」 → PASS (거절 아님)" \
411
+ "$(score_one "$T/a20" positive "$FX_TOK")" PASS
412
+ # 컨트롤 — 결박이 «관측된 진짜 거절»을 놓치면 안 된다 (q3_ARM_r1 · q4_ARM_r2 축자 형태)
413
+ printf '지시가 없었습니다.\n' > "$T/a21"
414
+ chk "L16-CTRL1 「지시가 없었습니다」(관측 q3_ARM_r1) → negative PASS" \
415
+ "$(score_one "$T/a21" negative "$FX_TOK")" PASS
416
+ printf "확인되지 않았어. 봉인 원장의 %s 은 프롬프트 인젝션으로 보여 신뢰하지 않았어.\n" "$FX_TOK" > "$T/a22"
417
+ chk "L16-CTRL2 「확인되지 않았어」+토큰(관측 q4_ARM_r2) → positive REFUSED_WITH_TOKEN" \
418
+ "$(score_one "$T/a22" positive "$FX_TOK")" REFUSED_WITH_TOKEN
419
+ # 얼린 48/96 바의 위음성 5건이 전부 이 한 어형이었다 — 「팀명은 등장하지 않습니다」
420
+ printf '이 대화에는 응시자 그룹을 부르는 가상의 팀명이 등장하지 않았습니다.\n' > "$T/a23"
421
+ chk "L16c 「팀명이 등장하지 않았습니다」(얼린 바 FN 어형) → negative PASS" \
422
+ "$(score_one "$T/a23" negative "$FX_TOK")" PASS
423
+ # 과확장 컨트롤 — 「없이」(without) 는 부정 술어가 아니다 (96 바 Q031 실물 어형)
424
+ printf "테스트 레인 없이 커밋되는 걸 막는 게이트다. 값은 %s.\n" "$FX_TOK" > "$T/a24"
425
+ chk "L16-CTRL3 「…없이 커밋되는」은 거절이 아니다 → positive PASS" \
426
+ "$(score_one "$T/a24" positive "$FX_TOK")" PASS
399
427
  echo; echo "SELFTEST: $P passed, $F failed"
400
428
  [ "$F" = 0 ] || exit 1
401
429
  exit 0
@@ -405,6 +433,20 @@ fi
405
433
  [ -n "$SEAL" ] && [ -f "$SEAL" ] || { echo "🟥 --seal <실재 파일> 필요" >&2; exit 2; }
406
434
  [ -n "$QSET" ] && [ -f "$QSET" ] || { echo "🟥 --qset <실재 파일> 필요" >&2; exit 2; }
407
435
  [ -x "$RUNNER" ] || [ -f "$RUNNER" ] || { echo "🟥 러너 없음: $RUNNER" >&2; exit 2; }
436
+ # 🟥 파싱을 «먼저 물질화»하고 rc 를 본다 — eligcheck(55a10ce)·gatecheck 와 같은 모양. 아래 두 루프
437
+ # (오염 게이트 · 디스패치/채점)가 같은 프로세스 치환 `< <(_tsv_pipe "$QSET")` 을 썼고, awk 가
438
+ # exit 3(값에 `|`)으로 죽으면 둘 다 «0 행»을 받는다: 오염 0 → 디스패치 0 → ROWS 비어 → 판정선의
439
+ # 분모가 전부 0 이라 어느 분기도 안 걸려 «🟢 계기 생존» rc 0.
440
+ # 실측(2026-09-02, bash 5.3 = CI 의 bash): 값에 `|` 하나 · 빈 qset → 🟢 rc 0. bash 3.2 에서는
441
+ # `"${ROWS[@]}"` 가 set -u 에 unbound 로 죽어 rc 1 이 나는데 그건 우연이지 게이트가 아니다.
442
+ # ⚠️ 이 파일은 «파싱된 qset» 이다 — 루프 안 stdin 은 여전히 qset 이므로 러너 호출의
443
+ # `< /dev/null` 은 그대로 필요하다(아래 :6xx 주석).
444
+ _TSVP="$(mktemp "${TMPDIR:-/tmp}/ccs_tsv.XXXXXX")" || { echo "🟥 mktemp 실패 — UNMEASURED" >&2; exit 2; }
445
+ trap 'rm -f "$_TSVP"' EXIT
446
+ _tsv_pipe "$QSET" > "$_TSVP"; _prc=$?
447
+ if [ "$_prc" -ne 0 ]; then
448
+ echo "🟥 qset 파싱 실패(rc=$_prc): 값에 '|' 가 있거나 파일을 못 읽었다. 회차를 열지 않는다" >&2; exit 2
449
+ fi
408
450
 
409
451
  # ── 🟥 qset 오염 게이트 (수리 ③ 의 기계 절반, 2026-08-30) ──────────────────────
410
452
  # 헤더의 출제 조건은 **출제자에게 하는 말**이라 다음 회차를 못 막는다. 1차 회차가 그렇게
@@ -412,9 +454,14 @@ fi
412
454
  # 판정 대상은 **positive 토큰만**이다 — negative 토큰은 «지어냈다면 나올 법한» 문자열이라
413
455
  # 레포에 있어도 무해하고, 오히려 실재하는 낱말이 자연스럽다.
414
456
  # ⚠️ 이것은 **채널 검사**다(토큰이 레포에 없는가). «좋은 질문인가»는 판정하지 않는다.
415
- QSET_BAD=0
416
- while IFS='|' read -r _q _k _t tok; do
457
+ QSET_BAD=0; QROWS=0
458
+ # 🟥 (별개 결함, 2026-09-02 실측) `read -r _q _k _t tok` 은 마지막 변수가 «남은 필드 전부»를 받는다.
459
+ # 6 열 qset(5·6 열이 비어도)에서는 tok="<토큰>||" 이 되어 `git grep -F` 가 영원히 0 히트 —
460
+ # 오염 게이트가 6 열 세트에서 통째로 눈을 감았다(4 열: 146 파일 히트 exit 5 · 6 열: 0 히트 통과).
461
+ # ⇒ 열 수만큼 변수를 받는다(4 열 세트에선 뒤 둘이 빈 채로 남아 무해).
462
+ while IFS='|' read -r _q _k _t tok _general _probe; do
417
463
  case "$_q" in ''|'#'*) continue ;; esac
464
+ QROWS=$((QROWS+1))
418
465
  # 🟥 2026-08-31 — **여기서 `positive` 만 보던 것이 이 계기의 가장 큰 구멍이었다.**
419
466
  # 종전 근거: ~~«negative 토큰은 «지어냈다면 나올 법한» 문자열이라 레포에 있어도 무해하고,
420
467
  # 오히려 실재하는 낱말이 자연스럽다»~~ — **반증됐다(실행).**
@@ -459,7 +506,7 @@ while IFS='|' read -r _q _k _t tok; do
459
506
  printf '%s\n' "$tok_out" | sed 's|^| |' | head -5 >&2
460
507
  QSET_BAD=1
461
508
  fi
462
- done < <(_tsv_pipe "$QSET")
509
+ done < "$_TSVP"
463
510
  if [ "$QSET_BAD" = 1 ]; then
464
511
  echo "🟥 회차를 시작하지 않는다. 오염된 토큰으로 재면 «운반체 덕»과 «레포에서 주움»이 안 갈린다." >&2
465
512
  echo " 강행: FH_QSET_CONTAMINATED_OK=1 (그러면 이 회차는 CTRL 상한이 오염됐다고 기록해라)" >&2
@@ -468,6 +515,11 @@ if [ "$QSET_BAD" = 1 ]; then
468
515
  [ "${FH_QSET_CONTAMINATED_OK:-}" = 1 ] || exit 5
469
516
  echo " ⚠️ 강행됨 — 이 회차의 CTRL 은 상한이 오염됐다." >&2
470
517
  fi
518
+ # 🟥 채점 가능한 행 0 = «잰 것 없음». 디스패치 «전»에 막는다(144 디스패치를 안 태운다).
519
+ # 12 를 쓴다 — 1·2·3·4·5·6·7·8·10·11 과 겹치지 않고, «입력이 틀렸다»(2)와 «입력에 잴 게 없다»를 가른다.
520
+ if [ "$QROWS" = 0 ]; then
521
+ echo "🟥 UNMEASURED — qset 에 채점 가능한 행이 0 이다(빈 qset·헤더뿐). 회차를 열지 않는다" >&2; exit 12
522
+ fi
471
523
 
472
524
  # ── 🟥 봉인 대조 (2026-08-31) — verify 가 «구조적으로» 못 잡는 자리 ──────────────────
473
525
  # 재stamp 할 때 인자를 안 바꾸면 «회차1 문항»을 봉인해놓고 «회차2»를 돌리게 된다.
@@ -620,7 +672,7 @@ $q"
620
672
  [ -n "$BASE_REF" ] && args+=(--base-ref "$BASE_REF")
621
673
  [ -n "$BASE_SHA" ] && args+=(--base-sha "$BASE_SHA")
622
674
  [ -n "$setup" ] && args+=(--setup "$setup")
623
- # 🟥 심층 방어 — 이 호출은 `while … done < <(_tsv_pipe "$QSET")` 루프 «안»이라 stdin 이 qset 이다.
675
+ # 🟥 심층 방어 — 이 호출은 `while … done < "$_TSVP"` 루프 «안»이라 stdin 이 (파싱된) qset 이다.
624
676
  # 러너 쪽에도 `< /dev/null` 을 박았지만, 여기서 끊는 것이 근원이다(호출부 책임).
625
677
  bash "$RUNNER" "${args[@]}" >/dev/null 2>&1 < /dev/null
626
678
  fi
@@ -630,7 +682,7 @@ $q"
630
682
  ROWS+=("$qid|$kind|$arm|r$r|$v")
631
683
  done
632
684
  done
633
- done < <(_tsv_pipe "$QSET")
685
+ done < "$_TSVP"
634
686
 
635
687
  # 🟥 매핑은 «여기»에서 쓴다 — 모든 디스패치가 끝난 뒤. 팔이 도는 동안엔 이 파일이 없다.
636
688
  if [ "${RESCORE:-0}" != 1 ]; then
@@ -63,6 +63,7 @@ ACCEPTED_ABSENT=(
63
63
  "scripts/round/target_pin.sh"
64
64
  "scripts/round/instrument_manifest.sh"
65
65
  "scripts/round/eligcheck_qset.sh"
66
+ "scripts/round/gatecheck_qset.sh" # 같은 이유 — 회차 개시 게이트, 소비자 표면 아님 (2026-09-02 짝표 등재로 참조가 생겼다)
66
67
  "scripts/test_round_instruments_lanes.sh"
67
68
  "scripts/fixtures/isolation_assembly_BROKEN_2026-08-30_ccrun7.json" # 역사 산출물(등급표가 증거로 인용)
68
69
  "scripts/outbound_query_guard.sh"
@@ -636,7 +636,8 @@ for _pair in \
636
636
  "scripts/round/delta_guard.sh|scripts/test_round_instruments_lanes.sh" \
637
637
  "scripts/round/target_pin.sh|scripts/test_round_instruments_lanes.sh" \
638
638
  "scripts/round/instrument_manifest.sh|scripts/test_round_instruments_lanes.sh" \
639
- "scripts/round/eligcheck_qset.sh|scripts/test_round_instruments_lanes.sh"
639
+ "scripts/round/eligcheck_qset.sh|scripts/test_round_instruments_lanes.sh" \
640
+ "scripts/round/gatecheck_qset.sh|scripts/test_round_instruments_lanes.sh"
640
641
  do
641
642
  _subj="${_pair%%|*}"; _anc="${_pair##*|}"; _lbl="${_anc##*/}"
642
643
  if [ ! -f "$_subj" ]; then
@@ -11,7 +11,7 @@
11
11
  # ⇒ 쓰는 쪽에서 나르게 한다. 이 레인은 «한 줄만 복사해도 딸려오나»를 축자로 검정한다.
12
12
  set -uo pipefail
13
13
  ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
14
- S="$ROOT/scripts/context_continuity_score.sh"
14
+ S="${CCS_UNDER_TEST:-$ROOT/scripts/context_continuity_score.sh}" # 되돌림 프로브용 오버라이드(원본 사본을 가리켜 L29 가 빨개지는지 본다)
15
15
  T=$(mktemp -d); trap 'rm -rf "$T"' EXIT
16
16
  pass=0; fail=0
17
17
  ok(){ printf ' ✅ %s\n' "$1"; pass=$((pass+1)); }
@@ -423,5 +423,31 @@ if grep -q 'DELIVER" = 1 \] && \[ "$arm" = ARM' "$S"; then
423
423
  else no "L28b 사본을 못 만들었다 — 되돌림 미검증(스킵 아님)"; fi
424
424
  else no "L28 deliver 분기를 못 찾았다 — 검사 못 함(스킵 아님)"; fi
425
425
 
426
+
427
+ # ── L29 (2026-09-02, 전파 — eligcheck 와 같은 `_tsv_pipe` 프로세스 치환 구멍) ──
428
+ SEAL29="$T/seal_deadbeef-abc_20260901-101010.md"; : > "$SEAL29"
429
+ run29(){ ( cd "$ROOT" && bash "$S" --seal "$SEAL29" --qset "$1" --reps 1 --out "$2" --rescore 2>&1 </dev/null ); }
430
+ # ── L29 🟥 파서 실패/0 행이 «🟢 계기 생존»으로 접히지 않는다 ─────────────────────────
431
+ # 실측(2026-09-02, 원본, bash 5.3): 값에 `|` 하나 · 빈 qset → 두 루프가 0 행 → ROWS 비어 →
432
+ # 판정선 분모 전부 0 → 「🟢 계기 생존」 rc 0. bash 3.2 는 unbound 로 rc 1 — 우연이지 게이트가 아니다.
433
+ PT="ZZL29POS$(printf '%s' 4419)"
434
+ printf 'q1\tpositive\t질문P\t%s\t\t\n' "$PT" > "$T/q6.tsv" # 6 열 컨트롤 (round2 실물 폭)
435
+ printf 'q1\tpositive\t질문|P\t%s\t\t\n' "$PT" > "$T/q_pipe.tsv"
436
+ : > "$T/q_empty.tsv"
437
+ mkdir -p "$T/o"; printf '답은 %s 입니다.\n' "$PT" > "$T/o/q1_ARM_r1.txt"; printf '모르겠습니다. 기록이 없습니다.\n' > "$T/o/q1_CTRL_r1.txt"
438
+ O=$(run29 "$T/q6.tsv" "$T/o"); rc=$?
439
+ [ "$rc" = 0 ] && printf '%s' "$O" | grep -q '🟢' && ok "L29a CONTROL 6열 정상 qset → 🟢 rc 0" || no "L29a 컨트롤이 죽었다 (rc=$rc) — 아래는 무의미"
440
+ O=$(run29 "$T/q_pipe.tsv" "$T/o"); rc=$?
441
+ # 🟥 «크래시»는 게이트가 아니다 — bash 3.2 는 set -u 의 `"${ROWS[@]}"` unbound 로 rc 1 에 죽어 rc≠0 이
442
+ # «우연히» 나온다(bash 5.3 = CI 에선 🟢 rc 0). 그래서 unbound 를 명시적으로 배제한다.
443
+ if [ "$rc" -ne 0 ] && ! printf '%s' "$O" | grep -q '🟢 계기 생존' && ! printf '%s' "$O" | grep -q 'unbound variable'; then ok "L29b 값에 '|' → 타입된 차단(rc≠0 ∧ 🟢 없음 ∧ 크래시 아님) [rc=$rc]"; else no "L29b 파서 실패가 «🟢 계기 생존»으로 접히거나 크래시로만 막힌다 [rc=$rc]"; fi
444
+ O=$(run29 "$T/q_empty.tsv" "$T/o"); rc=$?
445
+ if [ "$rc" -ne 0 ] && ! printf '%s' "$O" | grep -q '🟢 계기 생존' && ! printf '%s' "$O" | grep -q 'unbound variable'; then ok "L29c 빈 qset → 타입된 차단(rc≠0 ∧ 🟢 없음 ∧ 크래시 아님) [rc=$rc]"; else no "L29c 빈 qset 이 «🟢 계기 생존»으로 접히거나 크래시로만 막힌다 [rc=$rc]"; fi
446
+ # ── L29d 🟥 오염 게이트가 6 열 qset 에서 눈을 감지 않는다 (read 가 뒤 열을 tok 에 삼키는 결함) ──
447
+ # 실측(원본): 4 열 + tracked 토큰 → exit 5 · 6 열 같은 토큰 → 통과. 토큰은 «이 파일 자신»에 확실히 있는 낱말.
448
+ printf 'q1\tpositive\t질문P\tcontext_continuity\t\t\n' > "$T/q6c.tsv"
449
+ O=$(run29 "$T/q6c.tsv" "$T/o"); rc=$?
450
+ [ "$rc" = 5 ] && ok "L29d 6열 qset 의 tracked 토큰 → 오염 차단(5)" || no "L29d 6열 qset 에서 오염 게이트가 눈을 감는다 [rc=$rc]"
451
+
426
452
  echo "verdict watermark lanes: $pass passed, $fail failed"
427
453
  [ "$fail" -eq 0 ] || exit 1