@chrono-meta/fh-gate 1.4.93 → 1.4.95
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-plugin/marketplace.json +2 -2
- package/CLAUDE.md +1 -1
- package/knowledge/shared/harness-core/capability_composition_contract.md +25 -4
- package/knowledge/shared/learnings/subagent_invocations_log.yaml +33 -0
- package/package.json +2 -1
- package/plugins/fh-commons/.claude-plugin/plugin.json +1 -1
- package/plugins/fh-commons/skills/ko-tech-writer/SKILL.md +37 -5
- package/plugins/fh-commons/skills/mcp-circuit-breaker/SKILL.md +30 -13
- package/plugins/fh-commons/skills/token-budget-gate/SKILL.md +31 -12
- package/plugins/fh-meta/.claude-plugin/plugin.json +1 -1
- package/plugins/fh-meta/skills/field-harvest/SKILL.md +34 -11
- package/plugins/fh-meta/skills/marketplace-gate/SKILL.md +59 -31
- package/plugins/fh-meta/skills/pipeline-conductor/SKILL.md +13 -3
- package/plugins/fh-meta/skills/public-surface-audit/SKILL.md +56 -22
- package/plugins/fh-meta/skills/public-surface-audit/SKILL_detail.md +50 -11
- package/plugins/fh-meta/skills/return-path-gate/SKILL.md +36 -7
- package/scripts/capability_registry_check.sh +280 -0
- package/scripts/psa_scan_lib.sh +53 -1
- package/scripts/relay_channel.sh +6 -1
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
13
13
|
"name": "fh-meta",
|
|
14
|
-
"version": "1.4.
|
|
14
|
+
"version": "1.4.95",
|
|
15
15
|
"description": "Hub meta-operations toolkit — 35 skills + 7 agents. 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": "1.4.
|
|
20
|
+
"version": "1.4.95",
|
|
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
|
}
|
package/CLAUDE.md
CHANGED
|
@@ -598,7 +598,7 @@ Proposal format: `"I see [X]. Want me to run /[skill] to [one-line description]?
|
|
|
598
598
|
| "delete the branch", "브랜치 삭제", "브랜치 정리", "clean up branches", "force-push", "rewrite history", "지워도 돼?" (destructive intent — **proactive**, fire *before* the action) | **Destructive-Op Gate** (see above → enumerate → recover → destroy; `templates/predelete_check.sh`) |
|
|
599
599
|
| **"새 기능 검증해줘", "test this feature", "이 TC 확인해줘" — verifying the user's PRODUCT/feature (not FH itself)** | **Route to the mapped field harness first** (Cross-Project Skill Bus / registry) — the field harness owns product verification. The harness-verification rows in this table (`verify-bidirectional` · `prompt-regression` · `sim-conductor` · `pipeline-conductor`) verify the *harness*, and must not shadow a product-verification ask (a field project's *harness assets* — its skills/rules — still use those FH verification rows) |
|
|
600
600
|
| "지난주에 뭐 했지", "what did we do last week", "예전에 이거 한 적 있나" (recall intent) | **CATALOG-first recall** — read `CATALOG.md`, identify candidates by tag/date, then open only those files. Never scan session files one by one |
|
|
601
|
-
| "add this MCP server", "mount this MCP", "mcp.json에 추가", "connect this tool server" (external-MCP mount intent — **proactive**, fire *before* first tool call; mount intent only — a failing/erroring mounted server
|
|
601
|
+
| "add this MCP server", "mount this MCP", "mcp.json에 추가", "connect this tool server" (external-MCP mount intent — **proactive**, fire *before* first tool call; mount intent only — a failing/erroring mounted server routes to `/mcp-circuit-breaker` via its own skill description; its table row was removed in the 2026-07-17 row diet, so this parenthetical no longer points "above") | `templates/.claude/rules/mcp_tool_gating.md` (name-keyed ask/allow table — never trust server annotations or names; fill §3 at mount time) |
|
|
602
602
|
| "did my rule change break anything", "regression check", "test harness changes" | `/prompt-regression` |
|
|
603
603
|
| "review for the team", "CTO review", "decision-maker", "share with leadership", "approval deck" | `/apex-review` |
|
|
604
604
|
| "run full pipeline", "verify everything", "end-to-end sweep", "chain all verifications" | `/pipeline-conductor` |
|
|
@@ -353,10 +353,31 @@ Split honestly by moment; only one of the three is closable today.
|
|
|
353
353
|
|
|
354
354
|
- **Registration moment — reachable.** The reviewer is inside the registry when it applies. Pointers
|
|
355
355
|
from `.claude/registry/README.md` and `fh_detail_protocols.md §1-c` put the M1–M5 bar in front of
|
|
356
|
-
them.
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
356
|
+
them. ~~**Named residual, not built**: a `scripts/capability_registry_check.sh`…~~ → **built
|
|
357
|
+
2026-08-11.** `scripts/capability_registry_check.sh` validates the schema (closed key list — an
|
|
358
|
+
unknown key is a failure, never an ignore) and **runs each declared M4 pair**, so registration is
|
|
359
|
+
now *measured* on those axes rather than reviewed. Known-pair calibrated, 7 lanes, BLOCK/PASS
|
|
360
|
+
symmetric. Two capabilities are registered through it (`fh_psa_leak.cap` · `fh_degrade_verdict.cap`).
|
|
361
|
+
|
|
362
|
+
🟥 **What the checker measures, and the axis it provably does NOT — learned by being bitten.**
|
|
363
|
+
M1–M5 answer *"is the declaration well-formed, and does the instrument separate a case whose
|
|
364
|
+
answer we already know?"*. They do **not** answer *"is the declaration true"*, and one axis made
|
|
365
|
+
that concrete the same day it was built: a capability declaring **`writes: read-only`** passed all
|
|
366
|
+
five criteria — executable entry, closed enum with a did-not-run value, `judge: mechanical`, M4
|
|
367
|
+
known-pair green ×2, valid `requires_cwd` — and its entry point then **`rm -rf`'d this repo's
|
|
368
|
+
`scripts/` directory** on a no-argument invocation (a cleanup `trap` whose variable was reassigned
|
|
369
|
+
to a real path after the trap was installed). Tracked files were recovered by `git checkout`;
|
|
370
|
+
three untracked new scripts were not, and the recovery checkout also reverted an unrelated
|
|
371
|
+
in-flight edit. Nothing in the bar could have caught it: M4 exercised the two *declared* arms, and
|
|
372
|
+
the destructive path was the *undeclared* default arm.
|
|
373
|
+
- **Partial fix applied** (entry-point discipline, both probes): the cleanup variable is never
|
|
374
|
+
reassigned, the scan target is a separate variable, and the trap re-checks that the path it is
|
|
375
|
+
about to delete is under a temp root. Calibrated with a canary file in an isolated repo.
|
|
376
|
+
- **Structural fix, not built**: run the M4 pair under a read-only mount / sandbox and *observe*
|
|
377
|
+
whether a write is attempted. Until that exists, `writes:` (and `reversibility:`) are the
|
|
378
|
+
**registrant's claim**, and the checker prints them as such rather than implying it verified
|
|
379
|
+
them. A bar that silently accepts an unverifiable axis is how a `read-only` capability deletes a
|
|
380
|
+
directory with every light green.
|
|
360
381
|
- **Call moment — salience-only, no mechanical floor exists.** No hook can observe "a session is about
|
|
361
382
|
to compose a capability call"; the trigger is intent, exactly like the Instrument-Calibration rule.
|
|
362
383
|
The strongest available lever is structural: §ⓑ.3 makes the merged constraint set **step 2 of the
|
|
@@ -1797,3 +1797,36 @@
|
|
|
1797
1797
|
outcome: accepted
|
|
1798
1798
|
evidence: "Explore 지도가 «R-10.1=하위호환 unknown 레인·P7 는 그 경로 못 탐·R-4.3 은 sourced 가능» 3판정을 사전 특정 — 구현이 그 지도 그대로 감. codex 10R: S10·A7·B9 중 수용 21·기각 2(스펙 근거), R10 «신규 없음» CONVERGED. 라이브 자기적발 1(전제 미형성 FAIL 이 이슈 오발화 — 1차 주행에서 즉시 실측). 머지 #146(7cb45ac), 검출 1→4"
|
|
1799
1799
|
notes: "R5~R8 네 라운드가 전부 R3 증거-짝 수리의 후속 결함(«수리가 결함의 주된 출처» 4연쇄 실측) · R9 는 codex 가 내 회귀 레인의 공허성(.opine 계약 미준수로 단언 미실행)을 적발 — 레인 자체가 검증 대상이라는 사례"
|
|
1800
|
+
|
|
1801
|
+
- date: 2026-08-11
|
|
1802
|
+
session: qasp-axready-night-autonomous
|
|
1803
|
+
agents_summary: "7 열거 + 훅 집계 9 (consolidated): ① Explore 필드 정본 읽기(MTM/2막 계약/발화 자격) ② Explore 데이터-플레인 오라클 삽입지점 설계(bg) ③ codex gpt-5.5 1R (야간 5커밋 diff 적대 감사) ④ fh-meta:beginner 콜드리드 1차(기술문서 삽입 초안) ⑤ general-purpose 독립 2차 지각 QA(PDF 8쪽, 200dpi 크롭) ⑥ fh-meta:beginner 콜드리드 2차(수리본 재검 — 1차 후 고친 것을 다시 읽힌 라운드) ⑦ general-purpose@sonnet 블라인드 sim(ko-tech-writer 보강본, 심은 결함 3종)"
|
|
1804
|
+
dispatch_count: 9
|
|
1805
|
+
dispatch_count_note: "훅 집계 9 · 내가 이름으로 열거 가능한 것 7. 차이 2건은 귀속 미상이라 지어내지 않는다 — 세션 로그를 뒤져 채우는 대신 미상으로 남긴다(없는 엔트리를 만드는 것이 빠진 엔트리보다 나쁘다). 초판은 3으로 적혀 있었고 마감 체크 ④-e 가 9를 찍어 드러났다."
|
|
1806
|
+
outcome: accepted
|
|
1807
|
+
evidence: "④⑤⑥ 는 기술문서 축(같은 세션 후속) — ⑥ 이 **1차 콜드리드 수리본을 다시 읽힌 라운드**이고 거기서 «반례 흔한 단정 + 배치 오류» 가 나와 §7→§6 이동으로 이어졌다(그 경험이 스킬 Step 5 재콜드리드 규율의 근거다). ⑦ sim = 심은 결함 3/3 검출·오탐 0. ① 정본 Explore 가 «MTM=블박+화박 동시 실행, verdict 불변, 표기 4상태» 를 정본 인용으로 확정 — 이후 2-arm 실측(판정 51/51 동일 · mtm_cited 17)이 그 계약과 일치함을 확인하는 근거가 됐다. 일반 개념(«화이트박스 모드») 정규화를 사전 차단. ② 설계 Explore 가 relations.py 5곳·triage.py:258 닫힌 어휘·sourced 레인 선점 함정·데이터 리더 부재(known-positive 컨트롤 동반)를 특정 — 이번 세션은 그 능력을 안 지었으나(잔여 S1) 지도는 그대로 유효. ③ codex 1R: S/A/B/C 4축 반증 중 **헤드라인 반증 1건 수용** — 「품절 배지 검출」 주장이 로케일 축 오귀속임을 App.tsx/en.ts 근거로 지적, governor 가 소스 재확인 후 철회하고 attribution_risk 를 기계에 실었다(86dc8bf). 추가로 C-1(미생성 사유가 stdout 전용) 수용·수리, 잔여 4건은 명명"
|
|
1808
|
+
notes: "cross-family 가 **내 커밋 메시지의 주장** 을 반증한 사례 — 코드 결함이 아니라 «주장의 귀속» 이 틀린 경우라 레인·적대검증·되돌림 셋 다 못 잡았을 축이다([[feedback_grounding_audit_of_own_record]] 형). 자력 적발 0. 반대로 생성기 1차 산출의 오탐 공장 성질은 **손검사로 자력 적발**했다 — 기계 감사와 육안 표본이 서로 다른 결함을 잡았다"
|
|
1809
|
+
|
|
1810
|
+
- date: 2026-08-11
|
|
1811
|
+
session: plugin-reship-campaign-mtier-precheck
|
|
1812
|
+
agents_summary: "3 dispatches (parallel): fh-meta:challenger×3 — pmh-dev M티어 8스킬 선-적대검토 (배치1 게이트3종 · 배치2 감사/차단2종 · 배치3 오케스트레이션3종)"
|
|
1813
|
+
dispatch_count: 3
|
|
1814
|
+
outcome: accepted
|
|
1815
|
+
evidence: "M 22건·S 12건 회수, governor 소스 재검증 spot-check 9건 전건 CONFIRMED (marketplace plugin.json skills 키 부재 실측 · PSA 2층 패턴 스펙불일치 · MCB 계기 위치 stale · sidecar MEMORY.md 팬텀 · field-harvest 의무체인 Done When 미배선 등). 공통 M = 8스킬 전부 Done When check-class 0 (known-positive 컨트롤: 타 11스킬 히트) — 센서스 triage 와 일치. 배치3이 경계규칙(local_pmh_context.md:7 재인라인 금지) 발굴 → synced 7종 수리는 FH 상류 라우팅 확정"
|
|
1816
|
+
notes: "센서스(기계 grep triage) → 병렬 적대검토 → governor 재검증의 3단이 전수조사 표준 후보. 배치1이 known-pair 캘리브레이션을 자발 수행(BSD grep 오탐 후보를 스스로 기각) — challenger 에 계기 규율이 전이된 사례"
|
|
1817
|
+
|
|
1818
|
+
- date: 2026-08-11
|
|
1819
|
+
session: qasp-m1-tc-coordinates
|
|
1820
|
+
agents_summary: "1 dispatch: codex gpt-5.5 1R — M1 diff(좌표 3축·생성기 확장·entry NO_FORM·node 가드) 적대 감사, 낙관 방향(정상 FAIL/결함 PASS/BLOCKED 소실) 특정 지시"
|
|
1821
|
+
dispatch_count: 1
|
|
1822
|
+
outcome: accepted
|
|
1823
|
+
evidence: "5 findings 전건 수용·수리: F1(S — NO_FORM 이 «레시피 타깃 부재»를 «벽 부재»로 오판, SSO/타언어 벽 반례 → expect 증인 결박 + ENTRY_NO_FORM_UNVERIFIED fail-closed) · F2(venue 경유 basis 가 EVIDENCE_SPAN_SECTION 으로 오표기 — 시험관 선택이 기획서 지정으로 읽힘 → basis 분리) · F3(importer 가 generated_from 폐기 — 귀속위험이 하류 미결박 → 보존+report per_tc 표면화, exit 결박 잔여) · F4(무스코프 롤카운트 전역 오염/상쇄 → UNSCOPED_ROLE_COUNT typed, within= 잔여) · F5(부정 표시문 열거 추출 — codex 가 .venv 로 재현 실증 → 부정문 가드 양쪽). 수리 후 레인 69 + 전량 2,805 passed · 라이브 재검증 R9_1 BLOCKED→FAIL(typed)"
|
|
1824
|
+
notes: "F5 는 감사자가 처방 전에 재현을 직접 실행해 보인 사례(«짧은 함수 재현은 .venv 로 확인») — finding 수용의 소스검증 비용을 감사자가 선지불. F1 은 governor 의 «전원 부재 = 벽 부재» 가정을 반례(SSO/한국어 벽)로 무너뜨림 — 증인(positive witness) 요구가 처방으로 그대로 채택됨"
|
|
1825
|
+
|
|
1826
|
+
- date: 2026-08-11
|
|
1827
|
+
session: qasp-m1b-finding-identity
|
|
1828
|
+
agents_summary: "1 dispatch: codex gpt-5.5 1R — M1-b diff(finding 정체성 P6/P4→P7 관통) 적대 감사, **오귀속 방향** 지시(틀린 finding/화면 결박)"
|
|
1829
|
+
dispatch_count: 1
|
|
1830
|
+
outcome: accepted
|
|
1831
|
+
evidence: "4 findings 전건 수용·수리·되돌림 검증: F3(S — `references` 가 이미 5곳에서 4의미로 쓰임(finding_id·BVA source_defect_id·StateMatrix_combo_N·조인 id·row id) → 값만 보고 finding 해석 시 SM/BVA TC 오귀속, 감사자가 함수 실행으로 /orders 주입 재현 → reference_kind 선언 자격) · F2(S — sibling 위반은 행 쌍인데 조인이 첫 행에서 break, row1=/customers·row2=/orders 가 /customers 로 결박 → distinct 2+ 면 scalar 비움) · F1(S — 저신뢰 AREA_LABEL 이 선언된 유래를 이김 → 유예+충돌 typed, 유예가 좌표 손실이면 후퇴라 복원 경로 동반) · F4(M — 색인 raw / 소비 strip 불일치로 'dup'/'dup ' 미검출). 수리 4건 **각각 되돌려 정확히 그 앵커 1개씩 적색** 확인 후 커밋. 재생성 무회귀(app_id 40/51 · basis 분포 동일) · 전량 2,819 passed"
|
|
1832
|
+
notes: "감사자가 «일반 import 는 fitz/docx 부재로 막혀 P7·surface_inventory 를 직접 로드해 함수 단위로 확인» 이라고 **계기 한계를 스스로 명시**했다. 자체 적발 1건 — F3 게이트가 F 계열의 정당한 직결까지 막아 app_id 40→39(자격 게이트 도입은 기존 통과 경로에도 선언을 요구한다는 표준 회귀). peer 세션(로컬 다른 축)이 같은 라운드에 **두 축을 더** 잡았다: ⓐ 내 신규 앵커가 장식(생산자 배선 되돌려도 16 전건 초록 — 호출부 우회) ⓑ DISPLAY_MAPPING 의 case-insensitive 부분수리 함정(en.ts 직독 확인: 6종 중 5종만 통과). ★**갈림의 원인은 계열이 아니라 «무엇을 받았느냐» 다**(peer 정정 수용): codex 에게는 **diff** 를 줬고 → 코드 경로 결함 4건, peer 에게는 **내 보고서(주장)** 가 갔고 → 장치·주장 결함 4건. 계열이 같아도 diff 를 받았으면 같은 것을 봤을 것이다. 재사용 가능한 형태는 «탈상관 축은 누가 보느냐만이 아니라 **무엇을 받느냐**» — 적대검증을 아무리 붙여도 **전부 diff 를 주면 주장 축은 계속 빈다**([[feedback_grounding_audit_of_own_record]] 와 같은 축). peer 도 그 넷을 설계해서 잡은 게 아니라 **주장을 읽는 채널에 있었기 때문**이라고 자기 몫을 정직하게 낮췄다 — «피어 세션은 장치 결함을 잡는다» 가 아니라 «**주장을 받은 쪽**이 장치 결함을 잡는다» 가 맞는 모델이고, 그 차이가 다음에 누구에게 무엇을 보낼지를 바꾼다. 🟥**적발 비율을 지표로 읽지 마라**: 이 세션은 자력 1 · 외부 8 인데 그 8 = **codex(diff) 4 + peer(주장) 4** — 즉 «내가 못 봤다» 가 아니라 «**두 축을 열었다**» 다. 분모(어떤 채널을 몇 개 붙였나)를 안 적으면 리뷰를 많이 붙일수록 자력 비율이 나빠 보이고, 그 수를 성과로 읽는 순간 최적해가 «리뷰를 덜 붙이는 것» 이 된다(peer 지적). 채널을 같이 적어야 위의 «무엇을 받았느냐» 구분이 그 숫자 안에서 다시 접히지 않는다"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chrono-meta/fh-gate",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.95",
|
|
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": [
|
|
@@ -85,6 +85,7 @@
|
|
|
85
85
|
"templates/goal-quench-hook-setup.md",
|
|
86
86
|
"templates/.claude/rules/session.md",
|
|
87
87
|
"scripts/below_floor_scan.sh",
|
|
88
|
+
"scripts/capability_registry_check.sh",
|
|
88
89
|
"scripts/chamber_run.sh",
|
|
89
90
|
"scripts/fh_env_delta_scan.sh",
|
|
90
91
|
"scripts/substrate_jump_detector.sh",
|
|
@@ -60,12 +60,31 @@ model: sonnet
|
|
|
60
60
|
| 용어-머리 «**X** — 설명» | 글머리 기호 뒤 `** — ` | «**X**: 설명» 콜론형 |
|
|
61
61
|
| 콜론 나열투 («관측된 분업은: …») | 서술어 없는 `:` 도입 | 완결 문장으로 («…분업은 ~라는 것입니다») |
|
|
62
62
|
| 조각문 («걸리는 층.») | 서술어 없는 마침 | 서술어 복원 («걸리는 층입니다») |
|
|
63
|
+
| 소유 직역 「~을 갖다/가지다」 | `grep -E "을 갖\|를 갖\|을 가지\|를 가지"` | 존재문으로 (**«이전 상태를 갖지 않는다» → «이전 상태가 없다»**). 영어 `have`의 직역이고, 한국어는 소유보다 존재로 말한다. 소유가 실제 논점인 자리(권한·지분)는 남긴다 |
|
|
63
64
|
| 내부 조어·은어 | 팀 밖에서 안 쓰는 단어 (예: 렌더하다, 초록/빨강을 CI 결과 뜻으로) | 청중 어휘로 평문화. 단, **화면이 어휘를 받치면**(실제 빨간 화면을 가리키는 발화) 유지 가능 — 근거를 적는다 |
|
|
64
65
|
| 레지스터 드리프트 | 습니다↔해요↔평어 혼재 | 표본 기준 단일화 |
|
|
65
66
|
|
|
66
|
-
클래스의 성격이 갈린다: 앞
|
|
67
|
-
후보 + 눈 판정)이고, 뒤 두 줄(내부 조어·레지스터)은 **판정 클래스**다 —
|
|
68
|
-
서로 다른 check-class로 채점된다.
|
|
67
|
+
클래스의 성격이 갈린다: 앞 다섯 줄(줄표·용어-머리·콜론·조각문·소유 직역)은 **기계 검출
|
|
68
|
+
가능**(grep 후보 + 눈 판정)이고, 뒤 두 줄(내부 조어·레지스터)은 **판정 클래스**다 —
|
|
69
|
+
Done When에서 서로 다른 check-class로 채점된다.
|
|
70
|
+
|
|
71
|
+
### Step 2-b — 부분 개고 전용: 기존 본문과의 리듬 대조
|
|
72
|
+
|
|
73
|
+
**문서 전체를 새로 쓰는 경우가 아니라 기존 문서에 문단·문장을 끼워 넣는 경우**, 위 클래스가
|
|
74
|
+
전부 0이어도 **삽입분만 이질적으로 읽힐 수 있다.** 클래스 목록은 «틀린 표현»을 잡지
|
|
75
|
+
«튀는 표현»을 못 잡기 때문이다. 삽입·개고분에 한해 두 가지를 **수치로** 대조한다:
|
|
76
|
+
|
|
77
|
+
1. **문장 길이 분포** — 본문 평문 문장의 길이 중앙값·상위 10%를 먼저 구하고, 삽입분의 각
|
|
78
|
+
문장이 상위 10% 안에 드는지 본다. 넘으면 끊는다. (본문에 더 긴 문장이 있어도 근거가
|
|
79
|
+
못 된다 — 그건 그 문단의 리듬이지 삽입분의 것이 아니다.)
|
|
80
|
+
2. **어휘 반복** — 삽입분 안에서, 그리고 **직전·직후 문장까지 포함해** 같은 어간이 3회
|
|
81
|
+
이상 연달아 나오는지. 특히 같은 글자가 뜻이 다른 채로 반복되면(«검사를 더 **붙**여도 …
|
|
82
|
+
지점 쪽에 **붙**습니다») 읽는 눈이 걸린다.
|
|
83
|
+
|
|
84
|
+
> 실측(2026-08-11, 기술문서 v2.1 작업): 클래스 스캔 잔여 0인 삽입분이 본문 112문장 중
|
|
85
|
+
> 유일한 소유 직역 1건을 들여왔고, 문장 길이 **124자**(본문 중앙값 40자 · 상위 10% 78자),
|
|
86
|
+
> 「내려가」 앞 문장 포함 4회 연속 · 「붙」 한 문장 안 2회였다. 셋 다 기존 클래스 목록으로는
|
|
87
|
+
> 안 잡혔고, **읽는 사람이 «톤이 다르다»로 먼저 알아챘다.** 의도 보존으로 제외하는 항목은 **명명된 사유**(열거
|
|
69
88
|
매달기·리듬 결속·화면 받침)에 한하며, 제외 목록은 Step 5 콜드리드 짝에게 **통독이 끝난
|
|
70
89
|
뒤** 별도 패스로 전달해 대조받는다 — 사전 전달은 첫-읽기 눈을 오염시키고, 자기가 쓴
|
|
71
90
|
사유만으로 무제한 제외하지 않는다.
|
|
@@ -126,17 +145,30 @@ model: sonnet
|
|
|
126
145
|
격리 수준이었는지 이력에 적는다.** 에이전트 디스패치는 호출 세션의 권한·도구를 따른다
|
|
127
146
|
(이 스킬의 allowed-tools 밖의 일이다). 강격리도 비저자 짝도 구할 수 없으면 해당 judged
|
|
128
147
|
조건을 **미충족으로 명시**하고 발행 판단자에게 넘긴다 — 자기 검토로 대체하지 않는다.
|
|
148
|
+
- 🟥 **재콜드리드 — 지적을 반영해 고쳐 썼으면 고친 것을 다시 읽힌다.** 콜드리드 1회는
|
|
149
|
+
*초안*을 검증할 뿐이고, **발행되는 것은 수리본**이다. 수리는 결함의 주된 출처라서
|
|
150
|
+
«지적 반영»과 «통과»는 다른 사건이다. 본문이 바뀌었으면 라운드를 하나 더 돈다.
|
|
151
|
+
**정지 조건은 라운드 수가 아니라 변경이다** — 그 라운드에 **새 지적이 없거나, 있어도
|
|
152
|
+
본문을 안 고쳤을 때** 닫는다. 고쳤으면 아직 안 닫힌 것이다. 라운드마다 «지적 n건 · 반영
|
|
153
|
+
n건 · 본문 변경 여부»를 이력에 적는다.
|
|
154
|
+
> 실측(2026-08-11): 1차 콜드리드가 초안의 삽입 지점 오류를 잡았고, **그 수리가 새 결함
|
|
155
|
+
> 3종**(소유 직역 · 문장 길이 124자 · 어휘 반복)을 낳았다. 재콜드리드를 안 돌아 그대로
|
|
156
|
+
> 발행될 뻔했고, 읽는 사람이 «톤이 다르다»로 먼저 잡았다. 돌려 보니 문체보다 큰 것까지
|
|
157
|
+
> 나왔다 — 삽입분의 주장이 **반례가 흔한 단정**이었고(«검사를 아무리 늘려도 잡히지
|
|
158
|
+
> 않는다»), 자리도 닫는 절이 아니라 한계 절이 맞았다. 문장 다듬기 라운드가 **주장 범위와
|
|
159
|
+
> 배치**를 되돌렸다.
|
|
129
160
|
|
|
130
161
|
## Done When
|
|
131
162
|
|
|
132
163
|
| 조건 | check-class |
|
|
133
164
|
|---|---|
|
|
134
165
|
| 대상 매체 실물 표본 확인 기록이 산출물 이력에 존재 — 불가 시 **시도 내용·사유 포함** 명기(시도 기록 없는 «불가»는 불충족) | mandatory-pass |
|
|
135
|
-
| Step 2 **기계 클래스**(
|
|
166
|
+
| Step 2 **기계 클래스**(줄표·용어-머리·콜론·조각문·소유 직역) 스캔 잔여 0 — 컨트롤(알려진 양성 1건) 동반, 제외는 명명 사유와 함께 목록화 | measured |
|
|
136
167
|
| Step 2 **판정 클래스**(내부 조어·레지스터) 통과 | judged — 짝: 콜드리드 통독(통독 후 제외 목록 대조) |
|
|
168
|
+
| **부분 개고인 경우**(기존 문서에 삽입·수정): Step 2-b 리듬 대조 — 삽입분 각 문장이 본문 길이 상위 10% 이내 ∧ 어간 3회 연속 반복 0. 전문 신규 집필이면 N/A 명기 | measured |
|
|
137
169
|
| 본문 수치 전건(기계 추출 분모 기준)이 라벨(창 병기/재측정 대상/미확인) 동반 | measured |
|
|
138
170
|
| 렌더 산출물(HTML/PDF/이미지 — 파생 압축 자산 포함)이 존재하는 경우 전 페이지 지각 확인 — md-only 산출이면 N/A 명기 | judged — 짝: **독립 2차 지각 패스**(다른 눈이 같은 렌더를 봄) |
|
|
139
|
-
|
|
|
171
|
+
| 콜드리드가 **변경 없음으로 닫혔다** — 마지막 라운드에 새 지적이 없거나, 있어도 본문을 안 고쳤다. 지적을 반영해 고쳤으면 그 수리본으로 한 라운드 더. 라운드별 «지적 n · 반영 n · 본문 변경 여부» + 격리 수준(강/약) 이력 기록. Step 5 미적용 레지스터(낭독 대본)는 N/A 명기 | judged — 짝: 격리 검토(Step 5 정의) |
|
|
140
172
|
| 정직 수위 분리(Step 3)가 적용됨 | judged — 짝: 발행 승인자 확인 또는 격리 적대 검토. 둘 다 불가하면 **미충족으로 명시 보고**(자기 검토로 대체 금지) |
|
|
141
173
|
|
|
142
174
|
## 역할 경계 (중복 아님을 명시)
|
|
@@ -53,10 +53,20 @@ Default thresholds:
|
|
|
53
53
|
Identify the failing tool and failure mode:
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
|
-
#
|
|
57
|
-
|
|
56
|
+
# MCP mounts live in SEVERAL scopes — check all that this shell can see. Project settings.json is
|
|
57
|
+
# usually NOT one of them (it commonly holds hooks only), so a single-file read renders "no config"
|
|
58
|
+
# on a session with live MCP servers — a wrong-location instrument, not a measurement.
|
|
59
|
+
for f in .mcp.json .claude/settings.json .claude/settings.local.json; do
|
|
60
|
+
[ -e "$f" ] && { echo "== $f =="; grep -A5 '"mcpServers"' "$f" 2>/dev/null || echo "(present, no mcpServers key)"; }
|
|
61
|
+
done
|
|
62
|
+
[ -e ~/.claude.json ] && grep -c '"mcpServers"' ~/.claude.json | xargs echo "user-scope ~/.claude.json mcpServers blocks:"
|
|
58
63
|
```
|
|
59
64
|
|
|
65
|
+
An empty result above means **"no project/user-scope config found"** — never "no MCP mounted":
|
|
66
|
+
plugin-provided and remotely-managed servers appear in no local file. The live mount evidence is the
|
|
67
|
+
failing tool call itself (`mcp__{server}__{tool}` in this session); classify from that name even when
|
|
68
|
+
every config read comes back empty.
|
|
69
|
+
|
|
60
70
|
Classify failure type:
|
|
61
71
|
|
|
62
72
|
| Type | Symptom | Likely Cause |
|
|
@@ -98,6 +108,10 @@ Failure type: {TYPE} | Consecutive failures: {N}
|
|
|
98
108
|
Further calls to this tool are blocked until circuit resets.
|
|
99
109
|
```
|
|
100
110
|
|
|
111
|
+
(Blocking is **session-level discipline** — this skill's protocol, not a mechanical hook; no
|
|
112
|
+
PreToolUse gate enforces it. State it that way if asked — a protocol honestly labeled beats a
|
|
113
|
+
phantom enforcement claim.)
|
|
114
|
+
|
|
101
115
|
---
|
|
102
116
|
|
|
103
117
|
### Step 3. Log Circuit State
|
|
@@ -106,17 +120,16 @@ Write state to session-local file (in-memory is insufficient — logs survive /c
|
|
|
106
120
|
|
|
107
121
|
```bash
|
|
108
122
|
mkdir -p .claude/mcp_circuit/
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
Log entry format:
|
|
113
|
-
```yaml
|
|
123
|
+
grep -qxF '.claude/mcp_circuit/' .gitignore 2>/dev/null \
|
|
124
|
+
|| echo "NOTE: add '.claude/mcp_circuit/' to .gitignore — session state must not become a tracked file (the ignored-but-committed class public-surface-audit Step 3c hunts)"
|
|
125
|
+
cat >> .claude/mcp_circuit/circuit_log.yaml << EOF
|
|
114
126
|
- tool: {tool-name}
|
|
115
|
-
state: OPEN
|
|
127
|
+
state: OPEN # OPEN | HALF-OPEN | CLOSED — same enum as Done When
|
|
116
128
|
failure_type: {TYPE}
|
|
117
129
|
failure_count: {N}
|
|
118
130
|
tripped_at: {ISO-8601}
|
|
119
131
|
reset_at: null
|
|
132
|
+
EOF
|
|
120
133
|
```
|
|
121
134
|
|
|
122
135
|
---
|
|
@@ -133,7 +146,8 @@ Present the relevant fallback options ranked by effort (at least 3):
|
|
|
133
146
|
| **3 — Pause and retry** | Wait for server recovery (HALF-OPEN probe after cooldown) | Transient failure (TIMEOUT, RATE_LIMIT) |
|
|
134
147
|
|
|
135
148
|
> **Gating carries over to the substitute** (cross-ref the external-MCP tool-gating rule
|
|
136
|
-
> `mcp_tool_gating.md`
|
|
149
|
+
> `templates/.claude/rules/mcp_tool_gating.md` — template path; if installed live, your repo's
|
|
150
|
+
> `.claude/rules/` copy). A REST/API or
|
|
137
151
|
> workflow-automation tool adopted under Priority 1b is still an external-action surface: classify its
|
|
138
152
|
> calls under the same ask/allow tiers — reads are `allow (untrusted-read)` only after behavior
|
|
139
153
|
> confirmation; any write / send / delete / permission-change stays `ask`. Trading a gated MCP mount for
|
|
@@ -197,10 +211,13 @@ Recommendations:
|
|
|
197
211
|
|
|
198
212
|
## Done When
|
|
199
213
|
|
|
200
|
-
- Failure pattern classified (type + count)
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
-
|
|
214
|
+
- Failure pattern classified (type + count) — *judged* (adversarial pairing: an `UNKNOWN`
|
|
215
|
+
classification must state which Step 1 config reads ran and came back empty — "couldn't determine"
|
|
216
|
+
without the read evidence is not a classification)
|
|
217
|
+
- Circuit state logged to `.claude/mcp_circuit/circuit_log.yaml` (OPEN / HALF-OPEN / CLOSED) —
|
|
218
|
+
*mandatory-pass*
|
|
219
|
+
- At least 3 fallback alternatives proposed when circuit is OPEN — *measured* (count ≥3)
|
|
220
|
+
- Recovery probe offered with reset path — *mandatory-pass*
|
|
204
221
|
|
|
205
222
|
---
|
|
206
223
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: token-budget-gate
|
|
3
|
-
description: Estimates token cost before a multi-step task and outputs a Green/Yellow/Red gate verdict.
|
|
3
|
+
description: Estimates token cost before a multi-step task and outputs a 4-tier Green/Yellow/Orange/Red gate verdict. Records actual vs. estimated after completion when a mechanical usage source exists. Triggers on "token budget", "how much will this cost", "will this be expensive", "estimate tokens", before long multi-agent tasks.
|
|
4
4
|
user-invocable: true
|
|
5
5
|
allowed-tools: ["Read", "Bash"]
|
|
6
6
|
model: sonnet
|
|
@@ -76,6 +76,14 @@ Base estimates per task type:
|
|
|
76
76
|
|
|
77
77
|
Apply dimension multipliers from Step 1 to the base estimate.
|
|
78
78
|
|
|
79
|
+
**Calibration override (read leg)**: if `.claude/token_calibration/log.tsv` exists and holds ≥1 row
|
|
80
|
+
for this task type, derive the base as `median(actual_i / mult_i)` over its rows — each row's `mult`
|
|
81
|
+
column records the dimension-multiplier product that was in effect, so dividing recovers a
|
|
82
|
+
dimension-neutral base. **Never use raw `actual` as the base**: actual already contains that run's
|
|
83
|
+
multipliers, and re-applying this run's multipliers on top double-counts scope. The table above is the
|
|
84
|
+
uncalibrated default; measured local data outranks it. State which source the estimate used
|
|
85
|
+
(`base: table (uncalibrated)` or `base: calibration log, n={rows}`).
|
|
86
|
+
|
|
79
87
|
**Final formula:**
|
|
80
88
|
```
|
|
81
89
|
Estimated = base × file_multiplier × agent_multiplier × iteration_multiplier
|
|
@@ -131,35 +139,46 @@ Scope reduction options table (ORANGE/RED):
|
|
|
131
139
|
|
|
132
140
|
---
|
|
133
141
|
|
|
134
|
-
### Step 5. Post-Task Calibration (
|
|
142
|
+
### Step 5. Post-Task Calibration (offered, not required)
|
|
135
143
|
|
|
136
144
|
After task completion, if user says "how much did that cost" or "calibrate":
|
|
137
145
|
|
|
146
|
+
**`Actual` must come from a mechanical source** — the user pasting `/cost` output, or `budget.spent()`
|
|
147
|
+
in a Workflow context. A model cannot read its own token consumption by introspection; a reconstructed
|
|
148
|
+
number written into the log poisons every future estimate that reads it (the read leg in Step 2).
|
|
149
|
+
No mechanical source available → render `Actual: UNMEASURED` and **write no row**.
|
|
150
|
+
|
|
138
151
|
```
|
|
139
152
|
## Calibration
|
|
140
153
|
|
|
141
154
|
Estimated: ~16K tokens
|
|
142
|
-
Actual: ~{actual}K tokens
|
|
143
|
-
Error: {+/-N}%
|
|
144
|
-
|
|
145
|
-
Calibration note saved → improves next estimate for this task type.
|
|
155
|
+
Actual: ~{actual}K tokens (source: /cost paste | budget.spent() | UNMEASURED)
|
|
156
|
+
Error: {+/-N}% (omit when UNMEASURED)
|
|
146
157
|
```
|
|
147
158
|
|
|
148
|
-
Write calibration data:
|
|
159
|
+
Write calibration data (only when Actual is mechanically sourced):
|
|
149
160
|
```bash
|
|
150
161
|
mkdir -p .claude/token_calibration/
|
|
151
|
-
#
|
|
162
|
+
# mult = this run's dimension-multiplier product (Step 1) — stored so the read leg can divide it
|
|
163
|
+
# back out; a log without it makes every future estimate double-count scope.
|
|
164
|
+
printf '%s\t%s\t%s\t%s\t%s\n' "{task_type}" "{estimated_k}" "{actual_k}" "{mult}" "$(date +%F)" \
|
|
165
|
+
>> .claude/token_calibration/log.tsv
|
|
152
166
|
```
|
|
153
167
|
|
|
154
|
-
|
|
168
|
+
Recorded rows feed the Step 2 calibration override for the same task type (no model training — local record only).
|
|
155
169
|
|
|
156
170
|
---
|
|
157
171
|
|
|
158
172
|
## Done When
|
|
159
173
|
|
|
160
|
-
- Gate verdict output (GREEN/YELLOW/ORANGE/RED) with estimated cost breakdown
|
|
161
|
-
|
|
162
|
-
-
|
|
174
|
+
- Gate verdict output (GREEN/YELLOW/ORANGE/RED) with estimated cost breakdown, naming the estimate's
|
|
175
|
+
base source (table-uncalibrated or calibration log) — *mandatory-pass*
|
|
176
|
+
- For ORANGE/RED: scope reduction options presented and user decision recorded — *mandatory-pass*
|
|
177
|
+
- Any calibration row written this run carries a mechanically-sourced `actual` (pasted `/cost` or
|
|
178
|
+
`budget.spent()`); no mechanical source → `Actual: UNMEASURED`, no row — *mandatory-pass*
|
|
179
|
+
|
|
180
|
+
(Post-task calibration is an offer in Step 5, not a completion condition — a completion condition
|
|
181
|
+
marked "optional" is not a completion condition.)
|
|
163
182
|
|
|
164
183
|
---
|
|
165
184
|
|
|
@@ -79,7 +79,22 @@ Classify each commit using the following criteria (commit message + changed-file
|
|
|
79
79
|
|
|
80
80
|
Output the candidate list (format in §ModeA-Blocks): scanned count, FH absorption candidates with type/location/impact stars, field-only skipped count, then ask `[all / select number / skip]`. If 0 candidates, report "no absorption candidates" and exit.
|
|
81
81
|
|
|
82
|
-
## Step
|
|
82
|
+
## Step 3.5. contention-layer — Collision Gate (mandatory when candidates ≥ 1)
|
|
83
|
+
|
|
84
|
+
Run `contention-layer` on the confirmed candidate list **before any PR is created** — a new pattern
|
|
85
|
+
must be checked for collision with existing skill role clusters before registration. Skip only when
|
|
86
|
+
Step 3 found 0 candidates.
|
|
87
|
+
|
|
88
|
+
| contention-layer result | Behavior |
|
|
89
|
+
|---|---|
|
|
90
|
+
| No collision | Proceed to Step 4 |
|
|
91
|
+
| Collision / blocked registration | **No PR** — verdict `FAIL` per the enum below |
|
|
92
|
+
| Role collision needing a human call | **No PR** — verdict `ESCALATE` |
|
|
93
|
+
|
|
94
|
+
(This step previously existed only as a line *below* Done When — a cold executor reading Steps 0–4
|
|
95
|
+
had no occasion to see it before `gh pr create`. It is now in the execution path it gates.)
|
|
96
|
+
|
|
97
|
+
## Step 4. PR Creation (upon user approval, after Step 3.5)
|
|
83
98
|
|
|
84
99
|
Create a `harvest/{project}-{date}` branch in FH, apply approved patterns, commit, push, and `gh pr create` (bash + PR body checklist in §ModeA-Blocks).
|
|
85
100
|
|
|
@@ -215,24 +230,32 @@ One pass per session; never blocks the Mode B commit.
|
|
|
215
230
|
|
|
216
231
|
**Mode A (Pattern Harvest)**:
|
|
217
232
|
```
|
|
218
|
-
All stages Step 0~4
|
|
219
|
-
|
|
220
|
-
+
|
|
221
|
-
+
|
|
233
|
+
All stages through the exit point complete (Step 0~4; or
|
|
234
|
+
Step 0~3 + the 0-candidate exit, which is a valid terminal) — mandatory-pass
|
|
235
|
+
+ Step 3 harvest candidate list output (N candidates + M field-only) — measured (counts)
|
|
236
|
+
+ Step 3.5 contention-layer ran on the confirmed list (or its
|
|
237
|
+
0-candidate skip recorded) and its verdict gated Step 4 — mandatory-pass
|
|
238
|
+
+ Upon user approval, Step 4 PR creation complete (gh pr create ran) — mandatory-pass
|
|
239
|
+
+ When 0 candidates, "no absorption candidates" reported then exit — mandatory-pass
|
|
222
240
|
```
|
|
223
241
|
|
|
224
242
|
**Mode B (Session Log)**:
|
|
225
243
|
```
|
|
226
|
-
All Steps 0-B ~ 5-B executed
|
|
227
|
-
+ Step 0-B.1 detection-skip ledger applied (already-logged
|
|
228
|
-
+ Session markdown file generated from git log
|
|
229
|
-
|
|
230
|
-
+
|
|
244
|
+
All Steps 0-B ~ 5-B executed — mandatory-pass
|
|
245
|
+
+ Step 0-B.1 detection-skip ledger applied (already-logged filtered) — mandatory-pass
|
|
246
|
+
+ Session markdown file generated from git log
|
|
247
|
+
(or "all commits already logged" exit) — mandatory-pass
|
|
248
|
+
+ Hub commit created (no auto-push) — mandatory-pass
|
|
249
|
+
+ Confirmation output with push offer — mandatory-pass
|
|
231
250
|
```
|
|
232
251
|
|
|
252
|
+
The harvest-worthiness classification itself (Steps 1–2) is *judged* — its adversarial pairing is
|
|
253
|
+
Step 3.5 `contention-layer` plus the PR-side `asset-placement-gate`; no candidate registers on the
|
|
254
|
+
author's judgment alone.
|
|
255
|
+
|
|
233
256
|
Verdict: PASS (harvest candidates output and PR created, or 0 candidates confirmed) | CONDITIONAL_PASS (candidates found but PR pending user approval; or Mode B commit created, push pending) | FAIL (contention-layer blocked candidate registration; or hub path not found) | ESCALATE (role collision with existing skill requires human decision)
|
|
234
257
|
|
|
235
|
-
**→ Mandatory next: `contention-layer`** —
|
|
258
|
+
**→ Mandatory next: `contention-layer`** — executed as Step 3.5 above (kept here in closed-chain form for chain auditors: run after Step 3 candidate confirmation, before Step 4 PR creation; skip only at 0 candidates).
|
|
236
259
|
|
|
237
260
|
## Linked Skills
|
|
238
261
|
|
|
@@ -84,7 +84,7 @@ Result: **PASS** / **PARTIAL** / **FAIL**
|
|
|
84
84
|
### Check 3 — Maintenance Signals
|
|
85
85
|
|
|
86
86
|
```bash
|
|
87
|
-
cd "$REPO_PATH" 2>/dev/null || cd
|
|
87
|
+
cd "$REPO_PATH" 2>/dev/null || { echo "ABORT: cannot cd to $REPO_PATH — refusing to measure the current repo in its place"; exit 1; }
|
|
88
88
|
git log -1 --format="Last commit: %ar (%ad)" --date=short 2>/dev/null
|
|
89
89
|
ls CHANGELOG* 2>/dev/null && echo "CHANGELOG found" || echo "No CHANGELOG"
|
|
90
90
|
git tag -l 2>/dev/null | tail -5
|
|
@@ -101,47 +101,66 @@ Result: **ACTIVE** / **STALE** (60–180 days) / **ABANDONED** (180+ days)
|
|
|
101
101
|
### Check 4 — Duplication / Conflict Detection
|
|
102
102
|
|
|
103
103
|
```bash
|
|
104
|
-
# list skills in
|
|
105
|
-
|
|
106
|
-
#
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
104
|
+
# list skills in target repo (directory-based — skills are directory-registered in this ecosystem;
|
|
105
|
+
# plugin.json carries no skills array, so a manifest read is NOT a skill list. An earlier version
|
|
106
|
+
# of this check read `plugin.json["skills"]`, a key that never exists, so it rendered every healthy
|
|
107
|
+
# repo as STALE — a broken instrument, calibrated against this very repo.)
|
|
108
|
+
find "$REPO_PATH" -name "SKILL.md" 2>/dev/null | xargs -I{} dirname {} | xargs -I{} basename {} | sort > /tmp/_mkt_target_skills.txt
|
|
109
|
+
cat /tmp/_mkt_target_skills.txt
|
|
110
|
+
# compare with hub skills — SKIPPED must be visible, never silent. The readability test matters:
|
|
111
|
+
# FH_DIR set-but-wrong yields an empty ls through the pipe, which reads as "0 overlaps" — a silent
|
|
112
|
+
# skip wearing a pass. Set-but-unreadable is its own labeled state.
|
|
113
|
+
if [ -n "$FH_DIR" ] && [ -d "$FH_DIR/plugins" ]; then
|
|
114
|
+
ls "$FH_DIR"/plugins/*/skills/ 2>/dev/null | grep -v ':$' | grep -v '^$' | sort > /tmp/_mkt_hub_skills.txt
|
|
115
|
+
comm -12 /tmp/_mkt_target_skills.txt /tmp/_mkt_hub_skills.txt | sed 's/^/NAME-OVERLAP: /'
|
|
116
|
+
elif [ -n "$FH_DIR" ]; then
|
|
117
|
+
echo "SKIPPED: FH_DIR set but $FH_DIR/plugins unreadable — hub cross-check NOT run (not a CLEAN signal)"
|
|
118
|
+
else
|
|
119
|
+
echo "SKIPPED: FH_DIR unset — hub cross-check NOT run (this is not a CLEAN signal)"
|
|
120
|
+
fi
|
|
116
121
|
```
|
|
117
122
|
|
|
118
|
-
**Duplication verdict**:
|
|
123
|
+
**Duplication verdict**: name overlap with hub skills → **OVERLAP**/**CONFLICT** by role comparison.
|
|
124
|
+
Hub cross-check skipped → report `CLEAN (target-internal only — hub cross-check SKIPPED)`, never bare CLEAN.
|
|
119
125
|
|
|
120
126
|
| Criterion | Check |
|
|
121
127
|
|---|---|
|
|
122
|
-
| No name conflict with existing FH skills | name comparison |
|
|
128
|
+
| No name conflict with existing FH skills | name comparison (or visible SKIPPED) |
|
|
123
129
|
| No functional duplication | description keyword comparison |
|
|
124
|
-
| plugin.json list matches directory list | cross-check (SoT consistency) |
|
|
125
130
|
|
|
126
131
|
Result: **CLEAN** / **OVERLAP** (N candidates) / **CONFLICT** (direct conflict)
|
|
127
132
|
|
|
128
133
|
### Check 5 — Public Safety
|
|
129
134
|
|
|
135
|
+
**Primary path (no-reinvention)**: when `public-surface-audit` is installed, run it against
|
|
136
|
+
`$REPO_PATH` and map its verdict — `LEAK` → **BLOCKED** · `REVIEW` → **WARNING** · `CLEAN` → **SAFE**
|
|
137
|
+
· `NOT_CONFIGURED` → **WARNING(NOT_CONFIGURED)** (pattern source absent — not a clean bill). That
|
|
138
|
+
skill is the real token scanner; this check does not re-implement it. The `NOT_CONFIGURED` qualifier
|
|
139
|
+
survives into the Step 2 aggregate — see the 🟢 rule there (an unmeasured public surface must not be
|
|
140
|
+
absorbed into an ignorable ⚠️).
|
|
141
|
+
|
|
142
|
+
**Fallback (screening-grade only)** — when public-surface-audit is not installed:
|
|
143
|
+
|
|
130
144
|
```bash
|
|
131
|
-
#
|
|
132
|
-
grep -r "<your-ghe-url>\|internal-domain\|
|
|
145
|
+
# placeholder-literal screening — catches template residue, NOT real internal hostnames or secrets
|
|
146
|
+
grep -r "<your-ghe-url>\|internal-domain\|internal-api" \
|
|
133
147
|
"$REPO_PATH" --include="*.md" --include="*.json" --include="*.yaml" -l 2>/dev/null | head -10
|
|
134
|
-
# sensitive information exposure
|
|
135
|
-
grep -
|
|
136
|
-
"$REPO_PATH" --include="*.md" --include="*.json"
|
|
148
|
+
# sensitive information exposure (assignment shapes only)
|
|
149
|
+
grep -rE "API_KEY\s*=|SECRET\s*=|PASSWORD\s*=" \
|
|
150
|
+
"$REPO_PATH" --include="*.md" --include="*.json" --include="*.yaml" --include="*.yml" \
|
|
151
|
+
--include="*.sh" --include="*.env*" -l 2>/dev/null | head -5
|
|
137
152
|
# license
|
|
138
153
|
ls "$REPO_PATH"/LICENSE* 2>/dev/null && echo "LICENSE found" || echo "No LICENSE"
|
|
139
154
|
```
|
|
140
155
|
|
|
156
|
+
Fallback results are always labeled `(screening-grade — placeholder patterns; not a hostname/secret
|
|
157
|
+
scanner)`. A go-public action still owes the Pre-Publish Surface Gate's full chain regardless of a
|
|
158
|
+
SAFE here — this check screens listing readiness, it does not clear publication.
|
|
159
|
+
|
|
141
160
|
| Criterion | Check |
|
|
142
161
|
|---|---|
|
|
143
|
-
| No hardcoded internal domains (or clearly marked as internal-only) | grep |
|
|
144
|
-
| No sensitive information exposed | grep |
|
|
162
|
+
| No hardcoded internal domains (or clearly marked as internal-only) | public-surface-audit (or screening-grade grep, labeled) |
|
|
163
|
+
| No sensitive information exposed | public-surface-audit (or screening-grade grep, labeled) |
|
|
145
164
|
| LICENSE file exists | ls |
|
|
146
165
|
|
|
147
166
|
Result: **SAFE** / **WARNING** (N items to review) / **BLOCKED** (sensitive info exposed)
|
|
@@ -161,10 +180,14 @@ marketplace-gate — Listing Suitability Verdict
|
|
|
161
180
|
Check 4 Duplication detection: ✅ CLEAN / ⚠️ OVERLAP({N}) / ❌ CONFLICT
|
|
162
181
|
Check 5 Public safety : ✅ SAFE / ⚠️ WARNING({N}) / ❌ BLOCKED
|
|
163
182
|
|
|
164
|
-
Overall verdict
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
183
|
+
Overall verdict — counted over the ❌-class {FAIL, ABANDONED, CONFLICT, BLOCKED}
|
|
184
|
+
(each check has its own vocabulary; the aggregate counts the ❌ column, not the token "FAIL" —
|
|
185
|
+
an ABANDONED or CONFLICT is a failure even though its word differs):
|
|
186
|
+
🟢 Recommended for listing — 0 ❌-class results, AND Check 5 does not carry the
|
|
187
|
+
NOT_CONFIGURED qualifier (an unmeasured surface caps
|
|
188
|
+
the verdict at 🟡 — unmeasured ≠ pass)
|
|
189
|
+
🟡 Conditional listing — exactly 1 ❌-class result, and it is not BLOCKED
|
|
190
|
+
🔴 Listing on hold — 2+ ❌-class results, or any BLOCKED
|
|
168
191
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
169
192
|
```
|
|
170
193
|
|
|
@@ -182,12 +205,17 @@ marketplace-gate — Listing Suitability Verdict
|
|
|
182
205
|
## Done When
|
|
183
206
|
|
|
184
207
|
```
|
|
185
|
-
All steps 0–2 completed
|
|
186
|
-
+ Full 5-point check results output (Check 1–5 individual
|
|
187
|
-
|
|
208
|
+
All steps 0–2 completed — mandatory-pass
|
|
209
|
+
+ Full 5-point check results output (Check 1–5 individual
|
|
210
|
+
verdicts, skipped legs rendered as visible SKIPPED) — mandatory-pass
|
|
211
|
+
+ Overall verdict output (🟢/🟡/🔴) counted over the ❌-class — measured (❌-class count)
|
|
212
|
+
+ Before any 🟢 Recommended verdict: phantom-quench ran over
|
|
213
|
+
the target's citations/URLs/path refs; phantom refs found
|
|
214
|
+
→ verdict auto-downgrades to 🟡 Conditional — mandatory-pass
|
|
188
215
|
```
|
|
189
216
|
|
|
190
|
-
|
|
217
|
+
(The phantom-quench leg sits inside Done When on purpose — an earlier version stated it below the
|
|
218
|
+
fence, so the fence alone could be satisfied without it.)
|
|
191
219
|
|
|
192
220
|
> When `agent-composer` receives a "comprehensive marketplace listing audit" request,
|
|
193
221
|
> recommend: Wave 0 `fact-checker` → Wave 1 `marketplace-gate` + `hub-persona-auditor` in parallel.
|