@chrono-meta/fh-gate 2.5.1 โ 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/rules/fh_4axis_gate.md +26 -3
- package/.claude-plugin/marketplace.json +2 -2
- package/AGENTS.md +24 -3
- package/CATALOG.md +41 -0
- package/CLAUDE.md +77 -15
- package/README.ja.md +36 -11
- package/README.ko.md +36 -11
- package/README.md +116 -18
- package/README.zh.md +32 -11
- package/docs/USER_GUIDE.md +118 -0
- package/docs/platform_sustainability.md +174 -0
- package/knowledge/shared/GLOSSARY.md +26 -1
- package/knowledge/shared/harness-core/fh_detail_protocols.md +44 -2
- package/knowledge/shared/harness-core/field_verdict_crossfamily_gate.md +19 -5
- package/knowledge/shared/harness-core/harness_incubator_doctrine.md +129 -2
- package/knowledge/shared/harness-core/multi_model_sidecar_strategy.md +32 -0
- package/knowledge/shared/harness-core/ship_readiness_gate.md +77 -8
- package/knowledge/shared/learnings/subagent_invocations_log.yaml +110 -0
- package/knowledge/shared/rules/knowledge_layer_seam.md +1 -1
- package/package.json +17 -3
- package/plugins/fh-commons/.claude-plugin/plugin.json +1 -1
- package/plugins/fh-meta/.claude-plugin/plugin.json +1 -1
- package/plugins/fh-meta/CHANGELOG.md +136 -0
- package/plugins/fh-meta/agents/persona-innovator.md +170 -0
- package/plugins/fh-meta/skills/auto-decorrelation/SKILL.md +44 -0
- package/plugins/fh-meta/skills/fh/SKILL.md +31 -0
- package/plugins/fh-meta/skills/goal-quench/SKILL_detail.md +1 -1
- package/plugins/fh-meta/skills/harness-doctor/SKILL.md +7 -1
- package/plugins/fh-meta/skills/harvest-loop/SKILL.md +32 -0
- package/plugins/fh-meta/skills/public-surface-audit/SKILL_detail.md +16 -1
- package/plugins/fh-meta/skills/steel-quench/SKILL.md +97 -0
- package/scripts/adapters/fixtures/mate_agent_boundary_known_negative.md +31 -0
- package/scripts/adapters/fixtures/mate_agent_boundary_known_positive.md +56 -0
- package/scripts/adapters/peer_resolve.sh +58 -6
- package/scripts/cluster_capability_scan.sh +60 -18
- package/scripts/digest_landing_check.sh +181 -10
- package/scripts/fh_hub_identity.sh +83 -0
- package/scripts/fh_session_load.sh +53 -5
- package/scripts/fh_track_resolve.sh +114 -0
- package/scripts/field_canon_preload.sh +50 -5
- package/scripts/package_coverage_check.sh +17 -0
- package/scripts/prior_art_prompt.sh +168 -0
- package/scripts/psa_scan_lib.sh +201 -15
- package/scripts/residency_admission_check.sh +204 -0
- package/scripts/selfcheck.sh +117 -1
- package/scripts/test_adapter_lanes.sh +67 -2
- package/scripts/test_heavy_classifier_lanes.sh +144 -0
- package/scripts/test_marker_defense_lanes.sh +152 -0
- package/scripts/test_marker_soul_check_lanes.sh +211 -0
- package/scripts/test_prior_art_prompt_lanes.sh +128 -0
- package/scripts/test_psa_singlefile_lanes.sh +351 -1
- package/scripts/test_residency_admission_lanes.sh +60 -0
- package/scripts/test_track_resolve_lanes.sh +158 -0
- package/templates/.git-hooks/pre-commit +400 -4
- package/templates/.git-hooks/pre-push +17 -2
- package/templates/settings.PriorArt.snippet.json +15 -0
- package/scripts/test_satellite_publish_gate_lanes.sh +0 -339
|
@@ -202,6 +202,50 @@ re-checks** it against the artifact (phantom-quench back-trace) before accepting
|
|
|
202
202
|
source-grounded is **dropped, not judged**. No sidecar-only verdict (no weak-local-judge regression).
|
|
203
203
|
Local 4090 = **canary tier** (evidence-of, never terminal verdict).
|
|
204
204
|
|
|
205
|
+
๐ฅ **What you SEND decides which axis you get โ put the MARKER in the payload, not just the diff**
|
|
206
|
+
(2026-08-19). Sidecars have been receiving the *diff* only. That buys a review of the **code** and
|
|
207
|
+
buys nothing on the **record**: the Axes 2+3 marker is self-attested, and this repo has already
|
|
208
|
+
written down that the closing move is *"cross-family reading that marker"* โ then never wired the
|
|
209
|
+
marker into the thing that recruits cross-family. Measured twice: (a) a release marker's false
|
|
210
|
+
`not-applicable` passed the new typed lanes untouched, because **form was correct**; (b) this skill's
|
|
211
|
+
own dispatch on 2026-08-19 sent a diff and no marker, so the round could not have caught a false
|
|
212
|
+
axis claim even in principle.
|
|
213
|
+
|
|
214
|
+
**So the payload is two parts**: the frozen diff **and** the marker for this change โ **as it stands
|
|
215
|
+
at dispatch time**: `axes-run:` ยท `controls:` ยท `standpoint:` ยท `thirdparty:` ยท `residual:`.
|
|
216
|
+
|
|
217
|
+
๐ฅ **`crossfamily:` is NOT in the payload โ it is this round's OUTPUT.** Step 6 below says every rung
|
|
218
|
+
*emits* that value and "the rung is not done until its verdict is recorded", so requiring it in the
|
|
219
|
+
thing you send is circular: you would be shipping a field this dispatch has not produced yet. Send the
|
|
220
|
+
marker with that line **absent or `UNKNOWN`**, and fill it from the result. (Caught by a blind
|
|
221
|
+
floor-tier sim of this very paragraph, 2026-08-19 โ the first draft listed `crossfamily:` among the
|
|
222
|
+
payload fields and no reader could have satisfied it.) Ask the sidecar one extra
|
|
223
|
+
question: *"does the record match the diff โ is any axis claimed that the diff shows no trace of, and
|
|
224
|
+
is any residual missing that the diff implies?"*
|
|
225
|
+
|
|
226
|
+
โ ๏ธ **Scope, deliberately narrow.** This asks whether the record is **consistent with the artifact**.
|
|
227
|
+
It does NOT ask the sidecar to score honesty โ ยซis this marker truthfulยป is a *conclusion*, and
|
|
228
|
+
ยงMechanization Boundary forbids freezing that into machinery. Consistency is checkable from two
|
|
229
|
+
documents; honesty is not.
|
|
230
|
+
โ ๏ธ **You cannot observe that the sidecar READ it โ say so rather than implying otherwise.** Putting the
|
|
231
|
+
marker in the payload and the sidecar actually using it are different events, and nothing here
|
|
232
|
+
distinguishes them: a silently-ignored marker looks exactly like a marker that was read and raised
|
|
233
|
+
nothing. The cheap partial anchor is to require the return to **quote one marker line it checked** โ
|
|
234
|
+
a reply that quotes nothing did not demonstrably read it. That is evidence-of-reading, not proof, and
|
|
235
|
+
it does not close ยงMechanization Boundary's named self-attestation residual. Three independent
|
|
236
|
+
readers flagged this same gap on the day the paragraph was written (a peer session, and two blind
|
|
237
|
+
floor-tier sims), which is why it is stated here instead of left to the reader to notice.
|
|
238
|
+
|
|
239
|
+
โ ๏ธ **Prose, not a check** โ measured recurrence is 2, below this repo's own Nโฅ3 bar
|
|
240
|
+
(`[[feedback_mechanize_at_repetition_prose_before]]`). On the third occurrence, mechanize it here.
|
|
241
|
+
โ ๏ธ **Residency still governs**: a marker can name company assets. Sanitize before any external-family
|
|
242
|
+
dispatch, exactly as with the diff โ the marker is not exempt because it is metadata.
|
|
243
|
+
|
|
244
|
+
*Origin*: sister-asset read of `raphaelchristi/harness-evolver`'s `harness-critic` agent, whose whole
|
|
245
|
+
role is auditing the **evaluator** rather than the artifact. Its detection signatures (score jumps,
|
|
246
|
+
suspiciously fast convergence) do **not** port โ FH markers carry no score โ but the *target* does.
|
|
247
|
+
Full assessment incl. what was deliberately not imported: `tracks/_audit/proposal_2026-08-19_sister_harness-evolver.md`.
|
|
248
|
+
|
|
205
249
|
**Target freeze โ a prior drop reason, checked before any of the above (2026-08-17).** Grounding a
|
|
206
250
|
finding against *today's* tree proves nothing if the sidecar reviewed *yesterday's*. Pin before
|
|
207
251
|
dispatch and verify on return:
|
|
@@ -46,6 +46,37 @@ the session card and CATALOG, exactly as the greeting path would.
|
|
|
46
46
|
End with "pick a door, say a phrase, or just state your task". Do not auto-run anything โ this
|
|
47
47
|
command is a map, not a dispatcher.
|
|
48
48
|
|
|
49
|
+
|
|
50
|
+
## Step 3.5 โ ๊ฐ์ด๋ ยท Q&A (๐ ๋ฌธ์ ๊ณจ๋์ ๋๋ง ์ง์
)
|
|
51
|
+
|
|
52
|
+
๐ฅ **Q&A ๋ net-new ๊ธฐ๋ฅ์ด ์๋๋ค.** FH ์ ๋ํด ๋ฌป๊ณ ๋ตํ๋ ๊ฒ์ ์ด๋ฏธ ๋๋ค(CLAUDE.md ๊ฐ ์์ฃผ๋ผ
|
|
53
|
+
์ธ์
์ด ๋ฌธยท๊ฒ์ดํธยท์คํฌ์ ์๋ค). ์ด ์ ์ด ๋ํ๋ ๊ฒ์ **ํ๋๋ฟ**์ด๋ค โ ใ๋ฌด์์ ๊ทผ๊ฑฐ๋ก ๋ตํ๋,
|
|
54
|
+
๊ทธ๋ฆฌ๊ณ ์์ผ๋ฉด ์๋ค๊ณ ๋งํ๋คใ๋ **๊ณ์ฝ**. ๊ทธ๋์ ์ ์คํฌ์ ๋ง๋ค์ง ์๊ณ ์ฌ๊ธฐ ๋ถ์ธ๋ค.
|
|
55
|
+
|
|
56
|
+
**โ ๊ฐ์ด๋** โ `docs/USER_GUIDE.md` ์ **๊ฒฝ๋ก์ 3์ค ๋ชฉ์ฐจ**๋ฅผ ์ถ๋ ฅํ๋ค. ์น์ธํ๋ฉด ํ๋ซํผ opener ๋ฅผ
|
|
57
|
+
์ ์ํ๋ค(`uname -s`: Darwinโ`open` ยท Linuxโ`xdg-open` ยท MINGW/MSYSโ`start`). opener ๊ฐ ์์ผ๋ฉด
|
|
58
|
+
์กฐ์ฉํ ๊ฑด๋๋ด๋ค โ ๊ฒฝ๋ก๋ ์ด๋ฏธ ๋๊ฐ์ผ๋ฏ๋ก ์์ค์ด ์๋ค.
|
|
59
|
+
๐ฅ **์ ๋ฌธ ์ธ๋ผ์ธ ์ถ๋ ฅ ๊ธ์ง.** ์๋ ์คํ๋ ์ ํ๋ค.
|
|
60
|
+
|
|
61
|
+
**โ Q&A** โ 1๋ฌธ 1๋ต. ๊ทผ๊ฑฐ๋ ์๋ ์ฝํผ์ค **์์์๋ง** ์ฐพ๋๋ค:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
1 docs/USER_GUIDE.md ์ฌ์ฉ๋ฒ ยท FAQ
|
|
65
|
+
2 CHEATSHEET.md ๋ช
๋ น ยท ํธ๋ฆฌ๊ฑฐ ๋ฌธ๊ตฌ
|
|
66
|
+
3 knowledge/shared/GLOSSARY.md ์ฉ์ด
|
|
67
|
+
4 README.md ยงGet started/ยงLearn more ์ค์น ยท ์ง์
๊ฒฝ๋ก
|
|
68
|
+
5 CATALOG.md ใ์์ ์ ๋ญ ํ์งใ
|
|
69
|
+
6 ์ค์น๋ SKILL.md frontmatter ใ๋ฌด์จ ์คํฌ ์์ดใ
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**degrade โ ์ฝํผ์ค์ ์์ผ๋ฉด**
|
|
73
|
+
๐ฅ **์ง์ด๋ด์ง ์๋๋ค.** ใ๋ชป ์ฐพ์ โ ์ฝํผ์ค N๊ฐ๋ฅผ ๋ดค๊ณ ์ฌ๊ธฐ์ ์๋คใ + **๋ค์ ํ ๊ฑธ์**(์ด๋ ํ์ผ์
|
|
74
|
+
์ด์ง ยท `/install-doctor` ๊ฐ์ ์ค์ ์ง๋จ ๊ฒฝ๋ก)์ ์ค๋ค. ใ์๋ง ์ด๋ด ๊ฒ์ด๋คใ ํํ์ ๋ต์ **๊ธ์ง**๋ค.
|
|
75
|
+
์ด๊ฑด ยงInstrument Calibration ์ ยซ๋ฏธ์ธก์ ์ 0์ผ๋ก ๋ ๋ํ์ง ์๋๋คยป ์ ๊ฐ์ ๊ท์จ์ด๋ค.
|
|
76
|
+
๋ต๋ง๋ค `file:line` ์ ๋จ๋ค โ ๊ทผ๊ฑฐ ์๋ ๋ฌธ์ฅ์ ํฌํ
์ด๋ค.
|
|
77
|
+
|
|
78
|
+
โ ๏ธ ์ฝํผ์ค ๋ฐ ์ง๋ฌธ(๋๋ฉ์ธ ์์
ยท ์ฝ๋)์ ์ด ์ ์ด ์๋๋ผ ํ์๋๋ก ์ฒ๋ฆฌํ๋ค. Q&A ๋ **FH ์ฌ์ฉ๋ฒ**์ฉ์ด๋ค.
|
|
79
|
+
|
|
49
80
|
## Done When
|
|
50
81
|
|
|
51
82
|
| Condition | Check class |
|
|
@@ -214,7 +214,7 @@ fi
|
|
|
214
214
|
No Stop hook is required. After the Codex goal/session completes, resolve changed files with git and run:
|
|
215
215
|
|
|
216
216
|
```bash
|
|
217
|
-
FH_BACKEND=codex npx @chrono-meta/fh-gate "{changed-files}" quick codex-goal
|
|
217
|
+
FH_BACKEND=codex npx --package @chrono-meta/fh-gate fh-gate "{changed-files}" quick codex-goal
|
|
218
218
|
```
|
|
219
219
|
|
|
220
220
|
For high-stakes or external-facing work, use `full` instead of `quick`. Treat `BLOCKED` or `ESCALATE` the same as the Claude path: fix and re-run the gate, or surface the decision to the user.
|
|
@@ -149,7 +149,13 @@ running tool itself). Full procedure: `knowledge/shared/harness-core/measurement
|
|
|
149
149
|
`M-n ยท <verbatim row text or its threshold> ยท <measured value>`. If you cannot quote the row, **you do not
|
|
150
150
|
have a finding** โ downgrade to an observation. Origin (2026-07-20, instrument defect n+4, the *fourth* in
|
|
151
151
|
a single run): a run fired `M-1 ยท CLAUDE.md 816 lines โ exceeds the FH threshold of 500`. The string `500`
|
|
152
|
-
|
|
152
|
+
did not occur anywhere in this file at the time (a later grep finds 2 โ both in this narrative, added by
|
|
153
|
+
this very post-mortem; the self-referential claim drifted and is corrected here rather than re-asserted).
|
|
154
|
+
๐ฅ **And that grep was scoped wrong**: it searched this file only. The 500 was NOT invented from nothing โ
|
|
155
|
+
`docs/platform_sustainability.md` carried it as a live standard until 2026-08-20, contradicting this row.
|
|
156
|
+
The lesson is not "the run hallucinated" but **"the absence check was run against the wrong corpus"**
|
|
157
|
+
([[feedback_absence_measurement_needs_control]] โ a no-hit grep is evidence only when its scope covers
|
|
158
|
+
where the thing would actually live). The meta-harness row it claimed to read says raw
|
|
153
159
|
line count is **"Not a verdict."** So the run invented a threshold *and* fired a row this skill explicitly
|
|
154
160
|
disables for meta-harnesses โ the exact recurrence of the 2026-07-15 inversion documented below, which had
|
|
155
161
|
already been patched *in the skill*. The patch held; the **run** ignored it. A verdict grounded in a
|
|
@@ -54,6 +54,38 @@ Session end
|
|
|
54
54
|
โ edit-manifest VERIFY: check pending predictions in edit_manifest.yaml
|
|
55
55
|
โ memory-hygiene scan: staleness check on memory/*.md entries (skip if < 7 days)
|
|
56
56
|
โ
|
|
57
|
+
[Step 0-d] Session Retrospective (close_retro ๊ฐ granted ์ผ ๋๋ง)
|
|
58
|
+
๐ฅ ์ ์คํฌ์ ๋ง๋ค์ง ์๋๋ค โ ํ๊ณ ์ฐ์ถ์ ๊ทธ๋๋ก Step 2(contention-layer) โ Step 3 โ 3.5(๋ฑ๊ธ)
|
|
59
|
+
๋ก **์ด๋ฏธ ์๋ ํ์ดํ๋ผ์ธ**์ ํ๋ค. ใ๊ฐ์ ํฌ์ธํธ ์ ๋ฆฌใ๊ฐ ๊ฑฐ๊ธฐ์ ๊ณต์ง๋ก ๋ถ๋๋ค.
|
|
60
|
+
|
|
61
|
+
์ง์
์กฐ๊ฑด (๊ธฐ๊ณ์ , ์ด ์์๋ก):
|
|
62
|
+
1. `tracks/_meta/user_adaptation_profile.md` frontmatter ์ `close_retro`
|
|
63
|
+
granted โ ์คํ
|
|
64
|
+
declined โ ๊ฑด๋๋ด๋ค. **๋ค์ ๋ฌป์ง ์๋๋ค**(operational_adaptation.md no-re-nag)
|
|
65
|
+
unset / UAP ๋ถ์ฌ / ephemeral โ **์คํํ์ง ์๊ณ , ์ง์ด๋ด์ง๋ ์๋๋ค.**
|
|
66
|
+
์ด์์ ๋งฅ๋ฝ์ด๋ฉด(= `CLAUDE.local.md` ์กด์ฌ, `psa_detect_operator_context()` ์ ๊ฐ์
|
|
67
|
+
ํ๋ณ์) **์ต์ด ๋ง๊ฐ 1ํ๋ง** ์ ์ํ๊ณ ๋ต์ UAP ์ ๊ธฐ๋กํ๋ค. ๊ทธ ์ด์ ๋ฌป์ง ์๋๋ค.
|
|
68
|
+
๐ฅ `CLAUDE.local.md` ์กด์ฌ๊ฐ ํ๋ณ์์ธ ์ด์ ๋ ๊ทธ๊ฒ์ด **gitignored** ๋ผ fresh cloneยทCI ์ฒดํฌ์์ยท
|
|
69
|
+
์ํฌํธ๋ฆฌ ์ด๋์๋ ์ ๋ฐ๋ผ์ค๊ธฐ ๋๋ฌธ์ด๋ค. ๊ธฐ๊ฐ๋ ํ๋ณด: ใtracks/_meta ๊ฐ ๋น์ด์์ง ์์ใ โ
|
|
70
|
+
`.gitkeep` ์ด tracked ๋ผ **fresh clone ์ด ๋ง์กฑ์ํจ๋ค**(psa_scan_lib.sh ์ฃผ์์ ์ค์ธก).
|
|
71
|
+
๐ฅ **์ด์์ ๋งฅ๋ฝ์ด๋ผ๊ณ ์๋ granted ๊ฐ ์๋๋ค.** ํ์ผ์ด ์กด์ฌํด์ ์น์ธ๋๋ ๊ฒ ์๋๋ผ
|
|
72
|
+
**์ด์์ ๋ฐํ๊ฐ ์ธ์ฉ๋ผ ๊ธฐ๋ก๋๋ ์๊ฐ** ์น์ธ๋๋ค. ์ ์๋ ์ธ์
์ด ์๊ธฐ ๊ถํ์ ๋ํ๋ ํํ๋ค.
|
|
73
|
+
|
|
74
|
+
์ฐ์ถ: ์ค๋์ `tracks/_meta/fh_signal_{date}_{source}.md` ์ `retro: close` ๋ฅผ ๋ฌ๊ณ
|
|
75
|
+
`## Session Retrospective` 4ํ๋๋ฅผ ์ฑ์ด๋ค(ํ์ ์ ๋ณธ = fh_detail_protocols.md).
|
|
76
|
+
ใ์์ใยทใ0ใ๋ ์ ํจํ ๊ฐ์ด๊ณ , **๋น์ฐ๋ ๊ฒ๋ง ์ ๋๋ค.**
|
|
77
|
+
|
|
78
|
+
Done When:
|
|
79
|
+
+ ์ค๋์ signal ํ์ผ์ด ์กด์ฌํ๊ณ `retro: close` ๋ฅผ ๋ฌ๊ณ ์๋ค โ mandatory-pass
|
|
80
|
+
+ Session Retrospective 4ํ๋๊ฐ ์ ๋ถ ์ฑ์์ก๋ค โ mandatory-pass
|
|
81
|
+
+ ์ ์ ๊ฑด์๋ **์ธ์์ง ํ์ํ์ง ์์๋ค** โ measured
|
|
82
|
+
+ FH Registration Candidate ๊ฐ ๋น๋ฉด ๊ทธ ์ด์ ๊ฐ ํ ์ค ์ ํ ์๋ค โ mandatory-pass
|
|
83
|
+
|
|
84
|
+
โ ๏ธ `session_close_check.sh` ์ ๊ธฐ๊ณ ๊ฒ์ฌ๋ฅผ **๋ถ์ด์ง ์๋๋ค.** ๊ฐ์ธ๊ฒ ๋ถ์ผ ์ ์๋ ํํ๋
|
|
85
|
+
ยซ์ค๋์ signal ์ด ์๋ยป ์ธ๋ฐ ๊ทธ๊ฑด *์กด์ฌ*๋ง ์ฌ๊ณ *ํ๊ณ ํ๋*๋ ๋ชป ์ฐ๋ค โ CLAUDE.md ๊ฐ โฃ ๋ฉ๋ชจ๋ฆฌ
|
|
86
|
+
์์์ ๋ํด ๊ฐ์ ์ด์ ๋ก ๊ฒ์ฌ๋ฅผ ๋บ๋ค(ยซa check that can be satisfied without doing the work
|
|
87
|
+
is a decorationยป). ๊ฐ์ ํ๋จ์ ๊ทธ๋๋ก ์ ์ฉํ๋ค.
|
|
88
|
+
|
|
57
89
|
[Step 0] Regression Guard
|
|
58
90
|
โ Check: does anything from this session conflict with or regress a validated skill?
|
|
59
91
|
โ โ Regression detected: flag, route to contention-layer
|
|
@@ -25,9 +25,24 @@ if [ -r "scripts/psa_scan_lib.sh" ]; then
|
|
|
25
25
|
# Feed every tracked file as path<TAB>line, the stream psa_scan_tagged consumes. Sourcing the lib
|
|
26
26
|
# without these calls is a no-op scan โ measured on this repo (PSA_STREAM stayed unset), so the
|
|
27
27
|
# calls are spelled out here rather than pointed at.
|
|
28
|
+
# ๐ฅ rc ๋ฅผ ๋ฐ๋์ ๋ฐ์๋ผ (2026-08-21 ๋ฐฐ์ ๋ฆฌ๋ทฐ S-1). ์ด ํ์ดํ๋ **์๋ ๋ซ๋ ธ๋ ๋ฐ๋ก ๊ทธ ์ง์
์ **์ด๊ณ ,
|
|
29
|
+
# ๋ฐ๋ก ์๋ coverage ์กฐ๊ฑด์ด `$?` ๋ฅผ ๋ฎ์ผ๋ฏ๋ก ์ฌ๊ธฐ์ ์ ๋ฐ์ผ๋ฉด ๊ณ์ฝ์ด ์์ค๋๋ค.
|
|
30
|
+
# ๊ณ์ฝ: 0=์ ๊ณ ํ ๊ฒ ์์ ยท 1=์ ์ถ(์ด๋ฏธ ์ธ์๋จ) ยท 3=NOT SCANNED(๊ณ๊ธฐ ์ฌ๋ง)
|
|
31
|
+
# โ ๏ธ `_psa_rc=0` ์ ๋ฐ๋์ `while` **๋ฐ**์ ๋๋ค โ ์์ ๋๋ฉด ๋ฃจํ ๋ณธ๋ฌธ์ด๋ผ ๋งค ์ค ์ด๊ธฐํ๋๊ณ
|
|
32
|
+
# ํ์ดํ ์๋ธ์
ธ์ ๊ฐํ๋ค(์ดํ์ด ๊ทธ๋ ๊ฒ ๋ฃ์๊ณ `bash -n` ์ ํต๊ณผํ๋ค. ๋ฌธ๋ฒ์ ๋ง๊ณ ์๋ฏธ๊ฐ ํ๋ฆฐ๋ค).
|
|
33
|
+
_psa_rc=0
|
|
28
34
|
while IFS= read -r f; do
|
|
29
35
|
awk -v p="$f" '{printf "%s\t%s\n", p, $0}' "$f" 2>/dev/null
|
|
30
|
-
done < /tmp/_psa_tracked.txt | psa_scan_tagged
|
|
36
|
+
done < /tmp/_psa_tracked.txt | psa_scan_tagged || _psa_rc=$?
|
|
37
|
+
# ๐ฅ 3 ์ ยซ๊นจ๋ยป ์ด ์๋๋ผ ยซ์ ์๋คยป ๋ค. ์ฌ๊ธฐ์ ๋ฉ์ถฐ์ผ ํ๋ค โ ์ด ์คํฌ์ publish ์ง์ ์
|
|
38
|
+
# Pre-Publish Gate ๊ฐ 1๋ฒ์ผ๋ก ์ฒด์ด๋ํ๋ ๋ ์ฆ์ด๊ณ , ๊ทธ ์๋ฆฌ์์ ๋ฏธ์ธก์ ์ ํต๊ณผ์ํค๋ฉด
|
|
39
|
+
# ์๋ coverage ์ค์ด ยซdefaults-only ๋ก๋ ์ค์บํ๋คยป ๋ ์ธ์๊น์ง ์น๋๋ค.
|
|
40
|
+
if [ "$_psa_rc" -eq 3 ]; then
|
|
41
|
+
echo "โ INSTRUMENT DEAD: the scanner did not run (rc=3). NOT SCANNED is not clean."
|
|
42
|
+
echo " Fix first โ run under bash (zsh special vars can blank PATH inside the matcher),"
|
|
43
|
+
echo " and confirm psa_load ran (PSA_STREAM non-empty). Do NOT report a verdict from this run."
|
|
44
|
+
exit 3
|
|
45
|
+
fi
|
|
31
46
|
[ "$PSA_OVERRIDE_PRESENT" -eq 1 ] \
|
|
32
47
|
|| echo "coverage: defaults-only โ operator literals NOT CONFIGURED (identity/company classes UNSCANNED)"
|
|
33
48
|
else
|
|
@@ -84,6 +84,54 @@ External CLIs available: [yes/no โ Wave 5 available]
|
|
|
84
84
|
|
|
85
85
|
---
|
|
86
86
|
|
|
87
|
+
## Step 0.35 โ Org Constraint Load (์กฐ์ง ์ ์ฝ ์ ์ฌ)
|
|
88
|
+
|
|
89
|
+
**์กฐ์ง ์ ์ฝ์ ๋ชจ๋ฅด๋ ์ ๋ ๊ฒ์ฆ์ ํ๋ฐฉ์ ์น๋ค** โ ์กฐ์ง์ด ์ด๋ฏธ ๊ฒฐ์ ํ ๊ฒ์ ๊ณต๊ฒฉํ๊ฑฐ๋, ์กฐ์ง ์ ์ฑ
|
|
90
|
+
ํ์์๋ง ์ฑ๋ฆฝํ๋ ์ค์ ๊ณต๊ฒฉ์ ๋์น๋ค. ๊ณต๊ฒฉ ๊ฐ๋๋ฅผ ์ ํ๊ธฐ **์ ์** ์กฐ์ง์ธต์ ์ฝ๋๋ค.
|
|
91
|
+
๊ณ์ฝ: `knowledge/shared/rules/knowledge_layer_seam.md` (์ด ์คํฌ์ด **2ํธ ์๋น์**;
|
|
92
|
+
1ํธ๋ `phantom-quench` Step 2-O).
|
|
93
|
+
|
|
94
|
+
**์ ์ฐจ**: ์ง์
์ธ๋ฑ์ค(`knowledge/{org}/INDEX.md` ยท `index.md` ยท `README.md` ยท `readme.md` โ
|
|
95
|
+
ํ์ ๊ธฐ์ ๊ฐ์ ํ๋ณด ์งํฉ) โ ๋์๊ณผ **๊ด๋ จ๋** ์ ์ฑ
ยท์ฉ์ดยท๋๋ฉ์ธ ์ฌ์ค๋ง ๋ก๋. ์ ์ ์ค์บ ๊ธ์ง(๊ณ์ฝ K2).
|
|
96
|
+
๋ถ์ฌ๋ฉด **ยซ์กฐ์ง ์ ์ฝ ๋ฏธ์ยป์ผ๋ก ๋ช
์ํ๊ณ ์งํ** โ ์๋ ์ ์ฝ์ ์ถ๋ก ์ผ๋ก ๋ง๋ค์ง ์๋๋ค.
|
|
97
|
+
๐ฅ `not found` ๋ ยซ์ ์ฝ ์์ยป ์ด ์๋๋ค. ๋ฏธ์์ ๋ฏธ์์ผ๋ก ์ ๋๋ค.
|
|
98
|
+
|
|
99
|
+
**๋ก๋ํ ๊ฒ์ ์ฉ๋๋ ๋ฑ ๋**
|
|
100
|
+
1. **๊ณต๊ฒฉ์ ์ฌ์ค ๊ทผ๊ฑฐ**: "์กฐ์ง ์ ์ฑ
P ํ์์ ์ด ์ค๊ณ๋ X ๋ฅผ ์๋ฐํ๋ค" โ **์ ํจํ ๊ณต๊ฒฉ**
|
|
101
|
+
2. **ํ๋ฐฉ ํํฐ**: ์กฐ์ง์ด ์ด๋ฏธ ๊ฒฐ์ ยท๋ฌธ์ํํ ์ฌํญ์ "์ ์ ํ๋"๋ก ๊ณต๊ฒฉํ์ง ์๋๋ค. ๋์
|
|
102
|
+
**๊ทธ ๊ฒฐ์ ์์ฒด๋ฅผ ๊ณต๊ฒฉ**ํ๋ค(๊ทธ ๊ฒฐ์ ์ด ์ง๊ธ๋ ์ ํจํ๊ฐ). **๊ฒฐ์ ์ ์กด์ฌ๋ ๋ฉด์ ๊ฐ ์๋๋ค.**
|
|
103
|
+
|
|
104
|
+
### โ ์ธํ ์ฐจ๋จ โ ์ด ๋ฐฐ์ ์ ์ ์ผํ ์ํ
|
|
105
|
+
|
|
106
|
+
> **์กฐ์ง์ธต์ ๊ณต๊ฒฉ์ ๋ฌด์ฅํด์ ํ ์ ์๋ค.** ์กฐ์ง ์ํค์ *"์ด๊ฑด ์น์ธ๋ ํจํด"*, *"์ด ์ผ์ด์ค๋ ์์ธ"*,
|
|
107
|
+
> *"๊ณผ๊ฑฐ์ ๊ฒํ ์๋ฃ"* ๊ฐ ์์ด๋ **๊ทธ๊ฒ์ ๊ณต๊ฒฉ์ ๊ธฐ๊ฐํ๋ ๊ทผ๊ฑฐ๊ฐ ์๋๋ค.**
|
|
108
|
+
|
|
109
|
+
์ด์ : ์กฐ์ง์ธต์ **๋ฌด์**(์ฌ์คยท์ ์ฑ
)๋ง ๊ณต๊ธํ๊ณ **์ด๋ป๊ฒ ํ์ ํ๋**๋ ๊ณต๊ธํ์ง ์๋๋ค(๊ณ์ฝ ยง1-a).
|
|
110
|
+
"์น์ธ๋จ"์ *์กฐ์ง์ด ๊ทธ๋ ๊ฒ ์ ํ๋ค*๋ **์ฌ์ค**์ด์ง *๊ทธ ๊ฒฐ์ ์ด ์ณ๋ค*๋ **ํ์ **์ด ์๋๋ค.
|
|
111
|
+
์ ๋ ๊ฒ์ฆ์ ์ผ์ด ์ ํํ ๊ทธ ํ์ ์ ๋ค์ ํ๋ ๊ฒ์ด๋ค.
|
|
112
|
+
|
|
113
|
+
| ์กฐ์ง์ธต์ ์๋ ๊ฒ | ํ์ฉ๋๋ ์ฌ์ฉ | ๊ธ์ง |
|
|
114
|
+
|---|---|---|
|
|
115
|
+
| ์ ์ฑ
ยท๊ท์น | ์๋ฐ์ ๊ณต๊ฒฉ ๊ทผ๊ฑฐ๋ก | **๋ฉด์ ๊ทผ๊ฑฐ๋ก** |
|
|
116
|
+
| "์น์ธ๋ ํจํด" | ๊ทธ ์น์ธ์ ๊ทผ๊ฑฐ๋ฅผ ๊ณต๊ฒฉ ๋์์ผ๋ก | ๊ณต๊ฒฉ ๊ธฐ๊ฐ |
|
|
117
|
+
| "๊ณผ๊ฑฐ ๊ฒํ ์๋ฃ" | ๊ทธ๋์ ์ ์ ๊ฐ ์์ง ์ฐธ์ธ์ง ํ์ธ | ์ฌ๊ฒํ ์๋ต |
|
|
118
|
+
| stale ํ์ด์ง(`review_after` ๊ฒฝ๊ณผ) | **์ ์ฝ์ผ๋ก ์ฐ์ง ์๋๋ค** โ ๋ฏธ์ ์ฒ๋ฆฌ | ์ต์ ์ผ๋ก ๊ฐ์ |
|
|
119
|
+
|
|
120
|
+
**๋ณด๊ณ ์๋ฌด**: ์กฐ์ง์ธต ๋๋ฌธ์ ๊ณต๊ฒฉ์ ์กฐ์ ํ์ผ๋ฉด(๊ฐ๋ ์ถ๊ฐ ยท ํ๋ฐฉ ์ ๊ฑฐ) **๋ฌด์์ ์ ์กฐ์ ํ๋์ง
|
|
121
|
+
Wave 1 ์ถ๋ ฅ์ ๋จ๊ธด๋ค.** ์กฐ์ฉํ ์กฐ์ ์ ๊ฒ์ฆ ๋ฒ์ ์ถ์์ ๊ตฌ๋ณ๋์ง ์๋๋ค.
|
|
122
|
+
|
|
123
|
+
**๋ฐ์ถ ๊ธ์ง**(K1-s): cross-provider/cross-family ์ฑ๋ฆฐ์ ์ ์กฐ์ง์ธต **์๋ฌธ์ ๋๊ธฐ์ง ์๋๋ค** โ
|
|
124
|
+
๋์ด๊ฐ๋ ๊ฒ์ **sanitized ์ ์ฝ ์์ฝ**๋ฟ์ด๋ค. (CLAUDE.md ยงField-Harness Diagnostic ์ residency
|
|
125
|
+
๊ท์น๊ณผ ๊ฐ์ floor ์ด๊ณ , ์ด ์คํฌ์ด ๊ทธ๊ฒ์ ๋์จํ๊ฒ ๋ง๋ค์ง ์๋๋ค.)
|
|
126
|
+
|
|
127
|
+
> **์ถ์ฒ**: ์ ํ๋(sibling harness)์ ์ ๋ก๋ฅผ ์ด์ํ๋ค. FH ์๊ธฐ ์ ๋ณธ์ด ์ด ์๋ฆฌ๋ฅผ **๋ช
์์ ์ผ๋ก
|
|
128
|
+
> ใ๋ฏธ๋ฐฐ์ โ ์ฝ์์ด ์๋๋ผ ํ๋ณดใ**๋ก ์ ์ด๋๊ณ ์์๋ค(`knowledge_layer_seam.md` ยง0 ๋ฐฐ์ ํํฉ).
|
|
129
|
+
> ์ด ์ ์ด ๊ทธ ํ์ ํ๋ณด์์ ๋ฐฐ์ ์ผ๋ก ์ฎ๊ธด๋ค.
|
|
130
|
+
> ๐ฅ **์ด์ํ ๊ฒ์ ์ ์ฐจ์ด์ง ๊ทธ์ชฝ์ ๊ธฐ๊ณ-์ฃผ์ฅ์ด ์๋๋ค** โ ์๋ณธ์๋ ํ
์ด ์ด ์ ์ ๊ฐ์ ํ๋ค๋
|
|
131
|
+
> ์ทจ์ง์ ์์ ์ด ๋ธ๋ ค ์์์ผ๋, ์ค์ธกํ๋ ๊ทธ ํ
๋ ์ธ์ด **์กด์ฌํ์ง ์์๋ค**(`axis2-defense` ํ
ํํธ 0,
|
|
132
|
+
> ์ปจํธ๋กค `crossfamily` 21). ๊ทธ๋์ **๊ฐ์ ์์ ์ ์ ๊ฐ์ ธ์๋ค.** ์ด ์ ์ ์ค๋ ๊ธฐ์ค
|
|
133
|
+
> **์ด๋ฆฌ์ธ์ค ์ธต์ด๊ณ ๊ธฐ๊ณ ๋ฐ๋ฅ์ด ์๋ค** โ ๊ทธ๋ ๊ฒ ์ ๋ ๊ฒ์ด ํฌํ
์ ๋ค์ฌ์ค์ง ์๋ ์ ์ผํ ๋ฐฉ๋ฒ์ด๋ค.
|
|
134
|
+
|
|
87
135
|
## Step 0.4 โ Specialized Reviewer Discovery
|
|
88
136
|
|
|
89
137
|
For the target artifact, scan installed agents for a domain-specific adversarial reviewer:
|
|
@@ -211,6 +259,55 @@ A finding here is a real-code attack (Wave 1 execution principle) โ cite the e
|
|
|
211
259
|
|
|
212
260
|
---
|
|
213
261
|
|
|
262
|
+
## Wave 1-D โ Defense Questions (floor tiers ยท mechanically required)
|
|
263
|
+
|
|
264
|
+
Three questions, asked of **your own findings and numbers**, before Wave 1 is done. They are written
|
|
265
|
+
out rather than left to judgment because that is exactly what makes them portable: measured n=6 in
|
|
266
|
+
the origin field, a floor-tier pass executes the attack angles above without defect but **does not
|
|
267
|
+
spontaneously ask these three**, while a stronger tier does. That is a **checklist gap, not a
|
|
268
|
+
capability gap** โ and by `sonnet_floor_doctrine.md` a harness whose behaviour depends on which model
|
|
269
|
+
is driving is *defective*, not merely limited.
|
|
270
|
+
|
|
271
|
+
| # | Question | What a real answer looks like |
|
|
272
|
+
|:---:|---|---|
|
|
273
|
+
| **์ฌํ์ฑ** | Can another session reproduce this verdict from the same inputs? | The exact command, or `file:line`, another session runs. "It's reproducible" is not an answer. |
|
|
274
|
+
| **๋น๊ต๊ณต์ ์ฑ** | Were the two arms measured under the same conditions? | reps, inputs and environment named for **both** arms. An asymmetry you found and left in place counts โ say so. |
|
|
275
|
+
| **์ถ์ ์ธต์** | Is each number a measurement, an estimate, or a quotation? | Which, per number โ and for a measurement, what showed the instrument works **on this target** (known-pair). |
|
|
276
|
+
|
|
277
|
+
**Where the answers go** โ one line in the Axes 2+3 marker:
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
axis2-defense: reproducibility=<โฆ> fairness=<โฆ> estimation-layer=<โฆ>
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
**Enforcement, stated exactly.** `templates/.git-hooks/pre-commit` โ `validate_defense_leg()` runs
|
|
284
|
+
this **at the floor tiers only** (`floor-status: sonnet-floor` or `below-floor`), and checks
|
|
285
|
+
**presence ยท completeness ยท non-vacuity**: all three sub-answers must exist and `ok`/`yes`/`n/a` is
|
|
286
|
+
rejected as a filled form rather than an answer. Fixtures: `scripts/test_marker_defense_lanes.sh`
|
|
287
|
+
(17 lanes: known-pairs both directions, two over-block controls, four prescription assertions, and a
|
|
288
|
+
call-site pin โ because a suite that extracts the function and calls it directly stays green when
|
|
289
|
+
the hook stops calling it, which is precisely the failure being imported against).
|
|
290
|
+
๐ฅ **It cannot check whether the answers are TRUE.** That stays with the operator and the weekly
|
|
291
|
+
audit, exactly like every other marker field โ do not read the hook's PASS as verification.
|
|
292
|
+
|
|
293
|
+
**Why the trigger is narrow.** `below-floor` occurs **0 times** across the existing marker corpus, so
|
|
294
|
+
gating on it alone would be a decoration that never fires; `sonnet-floor` occurs 11. The wide reading
|
|
295
|
+
("any marker carrying numbers") is deliberately **not** taken โ pricing this axis at a near-universal
|
|
296
|
+
rate is the over-trigger `field_verdict_crossfamily_gate.md ยง7` rejects, and a field required
|
|
297
|
+
everywhere becomes a rubber stamp.
|
|
298
|
+
|
|
299
|
+
> **Provenance, and what was deliberately NOT imported.** Absorbed from a sibling harness
|
|
300
|
+
> (2026-08-20). That document additionally amends its floor rule so a below-floor pass carrying this
|
|
301
|
+
> line **plus** a crossfamily record passes **without the operator ack**. ๐ฅ That is a *loosening* of
|
|
302
|
+
> an existing FH gate and **was not adopted** โ here the leg is purely additive and `below-floor`
|
|
303
|
+
> still requires `below-floor-ack`, unchanged.
|
|
304
|
+
> ๐ฅ The same document asserted its own hook read this field and its own fixture suite pinned it.
|
|
305
|
+
> Measured twice with a control (`crossfamily` โ 21 hits in the same files): **both were 0**. The
|
|
306
|
+
> prose was portable; the machine was not. Everything claimed in this section's *Enforcement*
|
|
307
|
+
> paragraph was built here, and the fixture file named there is the receipt.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
214
311
|
## Wave 2 โ Defense Principles
|
|
215
312
|
|
|
216
313
|
**3 Defense Principles**: (1) Reinforce with external cases via WebSearch โ "unique to us" or "structural pattern"?
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# [CALIBRATION FIXTURE โ known-negative] ์ ๋ณด๊ฒฝ๊ณ ๋ถ๋ณ์์ด **๋น ์ง** ํฉ์ฑ ๋ช
์ธ์
|
|
2
|
+
|
|
3
|
+
> ๐ฅ **์ด๊ฒ์ ์คํ๋๋ ์์ด์ ํธ ์ ์๊ฐ ์๋๋ค.** `scripts/blackbox_invariant_check.sh` ์
|
|
4
|
+
> ์บ๋ฆฌ๋ธ๋ ์ด์
์ ์ค **๋งํ์ผ ํ๋ ์ชฝ**(expect = FAIL, exit 1)์ด๋ค. ์ง์
|
|
5
|
+
> `agent_boundary_known_positive.md`.
|
|
6
|
+
>
|
|
7
|
+
> ์ด ํ์ผ์ด ํ์ํ ์ด์ : ์์ฑ๋ง ์ธ์ฐ๋ฉด ใ๋ถ๋ณ์์ด ์ด์์๋คใ์ ใ๊ฒ์ฌ๊ธฐ๊ฐ ์๋ฌด๊ฒ๋ ์ ๋ณธ๋คใ๊ฐ
|
|
8
|
+
> ๊ฐ์ ์ด๋ก์ผ๋ก ๋ณด์ธ๋ค. ์์ฑ arm ์ ๊ณ๊ธฐ์ **ํ๋ณ๋ ฅ์ด ์๋์ง**๋ฅผ ์ฌ๋ ์๋ฆฌ๋ค.
|
|
9
|
+
>
|
|
10
|
+
> **์๋์ ์ผ๋ก ์๋ฐํ๋ค** โ ๋ถ๋ณ์ ๋ฌธ์ฅ๋ค์ ์ ๋ถ ๋บ๋ค. ์ค ์๋ณ์๋ ๋ด์ง ์๋๋ค(๊ทธ๊ฑด T1 ์ด
|
|
11
|
+
> ์ก๋ ๋ณ๊ฐ์ ์๋ฐ์ด๊ณ , ์ฌ๊ธฐ์ ๊ทธ๊ฒ๊น์ง ํธ๋ฆฌ๊ฑฐํ๋ฉด ์ด๋ ์ถ์ด ๋ง์๋์ง ํ๋ ค์ง๋ค).
|
|
12
|
+
|
|
13
|
+
## ์
๋ ฅ ์ธํฐํ์ด์ค
|
|
14
|
+
|
|
15
|
+
์ธ๋ถ findings ๋ฅผ ๋ฐ๋๋ค. `finding_id` ๋ ๋ถํฌ๋ช
์๋ณ์๋ค(์ดํ ์ ์ฝ ์์).
|
|
16
|
+
`location` ์ ํน์ ์ ๋์ด๊ฐ ๋ณด์ด๋ฉด ํ๊ธฐํ๋ค(denylist).
|
|
17
|
+
|
|
18
|
+
## ํฌ์ ๊ท์น
|
|
19
|
+
|
|
20
|
+
์ฃผ์
ํ์ดํ๊ฐ ๋ฏผ๊ฐ ์ ๋ณด๋ฅผ ์ง์ด๋ค. ๋ฐ์ ์
๋ ฅ์ ๊ทธ๋๋ก ๋ด์ ํ์๋ก ์ ๋ฌํ๋ค.
|
|
21
|
+
๊ธ์ง ๋์์ ์ด ๋ ํฌ ๋ฐ์ ํ์ผ์ด๋ค.
|
|
22
|
+
|
|
23
|
+
## ์์ ๊ท์น
|
|
24
|
+
|
|
25
|
+
1. ํ์ ๊ทผ๊ฑฐ๋ ์ธ์ฉ ๊ฐ๋ฅํ ์ฆ๊ฑฐ๋ก ๋จ๊ธด๋ค.
|
|
26
|
+
2. ์ฆ๊ฑฐ ์๋ ์ถ์ ์ ์ ๋ขฐ๋๋ฅผ ์ฌ๋ฆฌ์ง ์๋๋ค.
|
|
27
|
+
3. ์คํจ๋ฅผ ์ฑ๊ณต์ผ๋ก ์ผํค์ง ์๋๋ค.
|
|
28
|
+
4. ์ฌํ ์ ์ฐจ ์์ด ์์ ์์ ์ ์ํ์ง ์๋๋ค.
|
|
29
|
+
5. ๋๋ฉ์ธ ๋ฐ์ดํฐ๋ ๋ก๊ทธ์ ๋จ๊ธฐ์ง ์๋๋ค.
|
|
30
|
+
6. ReadยทGrepยทGlob ์ผ๋ก ๊ธ์ง๋ ์์ค๋ฅผ ์ด์ง ์๋๋ค.
|
|
31
|
+
7. ์ ๋ขฐ๋๋ ๊ทผ๊ฑฐ์ ๊ฐ๋์ ๋ฐ๋ผ ์ ํ๋ค.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# [CALIBRATION FIXTURE โ known-positive] ์ ๋ณด๊ฒฝ๊ณ ๋ถ๋ณ์ ํฉ์ฑ ๋ช
์ธ์
|
|
2
|
+
|
|
3
|
+
> ๐ฅ **์ด๊ฒ์ ์คํ๋๋ ์์ด์ ํธ ์ ์๊ฐ ์๋๋ค.** `scripts/blackbox_invariant_check.sh` ์
|
|
4
|
+
> ์บ๋ฆฌ๋ธ๋ ์ด์
์ ์ค **ํต๊ณผํด์ผ ํ๋ ์ชฝ**(expect = PASS, exit 0)์ด๋ค. ์ง์
|
|
5
|
+
> `agent_boundary_known_negative.md` ์ด๊ณ ๊ทธ์ชฝ์ ๋งํ์ผ ํ๋ค(expect = FAIL, exit 1).
|
|
6
|
+
>
|
|
7
|
+
> **์ ์ค๋ฌผ ๋ช
์ธ์๋ฅผ ์ฐ์ง ์๋**: ์ค๋ฌผ์ ํ์ด ๊ณ์ ๊ณ ์น๋ ์ด์์๋ ๋ฌธ์๋ผ, ๊ทธ๊ฒ์ ์์ฑ
|
|
8
|
+
> arm ์ผ๋ก ์ฐ๋ฉด ๊ณ๊ธฐ์ ํ์ ์ด ๋จ์ ํธ์ง์ ๋ฐ๋ผ ์กฐ์ฉํ ๋ค์งํ๋ค(๊ฐ์ฌ ๋์์ ์ผ๋ ค์ผ ํ๋ค).
|
|
9
|
+
> ์ค๋ฌผ ๋ช
์ธ์๋ ์ธ์ ์๋ ๊ธฐ๋ณธ ๋์์ผ๋ก ๊ณ์ ๊ฒ์ฌ๋๋ค โ ์ด ํ์ผ์ด ๊ทธ๊ฒ์ ๋์ฒดํ์ง ์๋๋ค.
|
|
10
|
+
>
|
|
11
|
+
> ์๋ณ์๋ ์ ๋ถ ํฉ์ฑ์ด๋ค. ์ค์ ์๋น์คยท๋ ํฌยทํ๋ ์ด๋ฆ์ ํ ๊ฑด๋ ๋ด์ง ์๋๋ค.
|
|
12
|
+
|
|
13
|
+
## ์
๋ ฅ ์ธํฐํ์ด์ค
|
|
14
|
+
|
|
15
|
+
์ธ๋ถ ์ ์ ๋ถ์์์ ์จ findings ๋ฅผ ๋ฐ๋, ์ด ์์ด์ ํธ๋ ๊ทธ findings ์ **์๋ณธ ์์ค**๋ฅผ ์ ๋
|
|
16
|
+
์ฝ์ง ์๋๋ค. ์ฃผ์
์ธก์ด ํฌ์ํ ๊ฒฐ๊ณผ๋ง ๋ณธ๋ค.
|
|
17
|
+
|
|
18
|
+
- `finding_id` โ ๋ถํฌ๋ช
์๋ณ์. ์ดํ ์ ์ฝ: `^[a-f0-9]{6,64}$` ๋ง ํ์ฉํ๋ค.
|
|
19
|
+
์์ ๋ฌธ์์ด์ด๋ฉด ๊ฒฝ๋กยท๋ฐ์ท๋ฅผ ์ค์ด ๋๋ฅด๋ ์ฐํ ์ด๋ฐ ์ฑ๋์ด ๋๋ค.
|
|
20
|
+
- `location` โ allowlist ์ ๊ท์ `^<FE-REDACTED>::[0-9]+$` ๋ง ํ์ฉํ๋ค.
|
|
21
|
+
denylist(โํน์ ์ ๋์ด๊ฐ ๋ณด์ด๋ฉด ํ๊ธฐโ)๋ ์๋๊ฒฝ๋กยท`file:///` ๋ฑ์ผ๋ก ๋ซ๋ฆฐ๋ค.
|
|
22
|
+
|
|
23
|
+
## ํฌ์ ๊ท์น
|
|
24
|
+
|
|
25
|
+
**ํฌ์์ ์ํํ๋ ์ฃผ์ฒด๋** ์ฃผ์
์ธก(ํ์ดํ๋ผ์ธ)์ด๋ค. ์ํ ์ฃผ์ฒด๋ฅผ ์ ์ง ์์ผ๋ฉด redact ๊ท์น์ด
|
|
26
|
+
์ํ์ ์๋ ๊ณต์ํ๊ฐ ๋๋ค. ๋ฐ๋ผ์ ์ด ์์ด์ ํธ๋ ์
๋ ฅ์ **"๊ทธ๋๋ก" ์ ๋ฌํ์ง ์๋๋ค** โ
|
|
27
|
+
ํฌ์๋ ํํ๋ง ํ์๋ก ๋๊ธด๋ค.
|
|
28
|
+
|
|
29
|
+
๊ธ์ง ๋์์ **์์น๊ฐ ์๋๋ผ ์ถ์ฒ**๋ก ์ ์ํ๋ค. ๋ ํฌ ์์ ๋ณต์ฌ๋ ์ฌ๋ณธ, ๋น๋ ์ฐ์ถ๋ฌผ,
|
|
30
|
+
`sourcesContent` ๋ฅผ ๋ด์ ์์ค๋งต ์ ๋ถ ๋์ผํ๊ฒ ๊ธ์ง๋ค. "๋ ํฌ ๋ฐ"์ผ๋ก ์ ์ํ๋ฉด ๋ ํฌ ์
|
|
31
|
+
์ฌ๋ณธ์ด ํต์งธ๋ก ๋ฉด์ ๋๋ค.
|
|
32
|
+
|
|
33
|
+
### ํ์ฌ ๋ฐฐ์ ์ํ
|
|
34
|
+
|
|
35
|
+
์ด ํฌ์ ํ์ดํ๋ **์์ง ์ฝ๋๋ก ๊ตฌํ๋์ด ์์ง ์๋ค.** ๋ฏธ๊ตฌํ ํต์ ๋ฅผ ๊ตฌํ๋ ๊ฒ์ฒ๋ผ ์ ์ผ๋ฉด
|
|
36
|
+
๊ทธ ์์ฒด๊ฐ ๋๊ด ๋ฐฉํฅ ๊ฒฐํจ์ด๋ค.
|
|
37
|
+
|
|
38
|
+
๊ทธ๋์ **์ฌ๋กฏ์ ํ์ฌ ์ฌ์ฉํ์ง ์๋๋ค.** ์ ์๋์ง ์์ ์ ์ฐจ์ must-never ๋ถ๋ณ์์ ์น์ง
|
|
39
|
+
์๊ธฐ ์ํด, ํ์ฑํ **๊ฒฝ๋ก๋ฅผ ๋์ง ์๋๋ค.**
|
|
40
|
+
|
|
41
|
+
## ์์ ๊ท์น
|
|
42
|
+
|
|
43
|
+
1. ํ์ ๊ทผ๊ฑฐ๋ ์ธ์ฉ ๊ฐ๋ฅํ ์ฆ๊ฑฐ๋ก ๋จ๊ธด๋ค.
|
|
44
|
+
2. ์ฆ๊ฑฐ ์๋ ์ถ์ ์ ์ ๋ขฐ๋๋ฅผ ์ฌ๋ฆฌ์ง ์๋๋ค.
|
|
45
|
+
3. ์คํจ๋ฅผ ์ฑ๊ณต์ผ๋ก ์ผํค์ง ์๋๋ค.
|
|
46
|
+
4. ์ฌํ ์ ์ฐจ ์์ด ์์ ์์ ์ ์ํ์ง ์๋๋ค.
|
|
47
|
+
5. ๋๋ฉ์ธ ๋ฐ์ดํฐ๋ ๋ก๊ทธ์ ๋จ๊ธฐ์ง ์๋๋ค.
|
|
48
|
+
6. **๋ฉ๋ชจ๋ฆฌ ์ฐ๊ธฐ ๊ธ์ง** โ **์ถ์ฒ๊ฐ ํ์ดํธ๋ฐ์ค๋ฉด ์ ์ฅํ์ง ์๋๋ค.** ์ ์ฅ๋ ๊ฐ์ ๋ค์ ํธ์ถ์
|
|
49
|
+
์๋ ์ฃผ์
๋๋ฏ๋ก, ์ฝ์ง ์์ ๊ธฐํ์กฐ์ฐจ ์์ด ์ธ์
๊ฒฝ๊ณ๋ฅผ ๋์ด ์ค์ผ์ด ์ง์๋๋ค.
|
|
50
|
+
7. ์ํ ๋ถ๋ณ์: ์ธ๋ถ findings ๊ทผ๊ฑฐ๋ง ์๊ณ ๋ฐํ์ ์ฆ๊ฑฐ(XML)๊ฐ ์์ผ๋ฉด ์ ๋ขฐ๋๋ MEDIUM ์
|
|
51
|
+
๋์ง ๋ชปํ๋ค. ์ด ์กฐํญ์ **๋ค๋ฅธ ๋ชจ๋ ์กฐํญ์ ์ฐ์ **ํ๋ค.
|
|
52
|
+
8. ๊ธ์ง๋ ์์ค์ **๋ฅ๋ ํ์**์ ํ์ง ์๋๋ค. ์ด ๊ธ์ง๋ **๋๊ตฌ ๋ฌด๊ด**์ด๋ค โ ReadยทGrepยทGlob
|
|
53
|
+
๋ฟ ์๋๋ผ `Bash` ๋ฅผ ๊ฒฝ์ ํ ์ด๋๋ ๊ฐ์ ์๋ฐ์ด๋ค. ๋๊ตฌ๋ฅผ ์ด๊ฑฐํ๋ ํํ๋ก ์ ์ผ๋ฉด ์ด๊ฑฐ๋์ง
|
|
54
|
+
์์ ๊ฒฝ๋ก๊ฐ ๊ทธ๋๋ก ์ฐํ๋ก๊ฐ ๋๋ค.
|
|
55
|
+
ํ์ ์ฑ๋(๋ฆฌํฌํธยท์ฒจ๋ถ)์์ **์กฐ์ฐ**ํ ๊ฒฝ์ฐ๋ ๋ณ๊ฐ๋ค: ์ด๊ธฐ ์ ์๋ ์ ์ ์์ผ๋ฏ๋ก
|
|
56
|
+
"์ฝ์ง ๋ง๋ผ"๋ ์ดํ ๋ถ๊ฐ๋ฅํ ์๋ฌด๊ฐ ๋๋ค. ์กฐ์ฐ ์์๋ ์ค๋จํ๊ณ ๋ณด๊ณ ํ๋ค.
|
|
@@ -35,6 +35,38 @@
|
|
|
35
35
|
# rc=3 NO_ROOTS โ ๋ฃจํธ ๋ชฉ๋ก ์์ฒด๊ฐ ๋น์๋ค(์ ์ ํ์. ใ์๋คใ๊ฐ ์๋๋ค)
|
|
36
36
|
# stderr : rc!=0 ์ผ ๋ ํ ์ค ์ฌ์
|
|
37
37
|
|
|
38
|
+
# โโ ๋จ์ผ ์์ค ๋ฐฐ์ (2026-08-21 F-1) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
39
|
+
# ๐ฅ ์ ์ฃผ์์ด ยซ์ค์บ๋์ ๊ฐ์ ์์์ฌ์ผ ํ๋คยป ๊ณ **๊ด๋ก๋ก** ์ ์ด ๋์๋ ๊ทธ ์ค๋ณต์ ์ฌ๊ธฐ์ ๋ซ๋๋ค.
|
|
40
|
+
# `scripts/fh_track_resolve.sh` ๊ฐ track ์ด๋ฆ โ ๋ ํฌ ๋ฃจํธ ํด์์ ๋จ์ผ ์์ค์ด๊ณ ,
|
|
41
|
+
# ์๋ `FH_PROJECTS_HOME` ํ์ ๊ทธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ถ๋ฅธ๋ค.
|
|
42
|
+
#
|
|
43
|
+
# โ ๏ธ **`FH_CLUSTER_ROOTS` ํ์ ๋ซํ์ง ์๋๋ค โ ์กฐํ ๋ชจ๋ธ์ด ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ด๋ค.**
|
|
44
|
+
# ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ยซ๋ฃจํธ ํ๋ ๋ฐ์ `$root/$c`ยป ๋ฅผ ๋ฌป๋๋ค. ์ด ํ์ ยซ์์ ์ ๋๊ฒฝ๋ก ๋ชฉ๋ก์
|
|
45
|
+
# `basename` ์ด ๋ณ์นญ์ธ๊ฐยป ๋ฅผ ๋ฌป๋๋ค. ์ด๋ฆ๋ง ๊ฐ๊ณ ์๋ฏธ๊ฐ ๋ค๋ฅธ ๋์ ์ต์ง๋ก ํฉ์น๋ฉด ๊ทธ๊ฑด
|
|
46
|
+
# ์ด ์๋ฆฌ๊ฐ ๋ง์ผ๋ ค๋ ๊ฒฐํจ๊ณผ ๊ฐ์ ์ข
๋ฅ๋ค. ๊ทธ๋์ ๊ทธ ํ์ ์๊ธฐ ์ด๊ฑฐ๋ฅผ ์ ์งํ๋ค
|
|
47
|
+
# (โ `fh_peer_alias_candidates` ๋ ๋จ๋๋ค. ๋ถ์ฌ ๋ฉ์์ง์ ๊ฐ๋ฑ ํด๋ฐฑ๋ ์ด๊ฑธ ์ด๋ค).
|
|
48
|
+
#
|
|
49
|
+
# ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์์ผ๋ฉด **์๋ฆฌ ์ด์ ๋์**์ผ๋ก ๊ฐ๋ฑํ๋ค โ ๋ค๋ฅธ ์ธ ์๋น์์ ๊ฐ์ ํํ๋ค.
|
|
50
|
+
# (ํด๋ฐฑ์ ์๋์ ์ผ๋ก ์ ๊ตฌํ ๊ทธ๋๋ก๋ค. ๊ณต๋ฐฑ ๊ฒฐํจ๊น์ง ํฌํจํด์ ยซ์๋ฆฌ ์ด์ ยป ์ด๋ค.)
|
|
51
|
+
_FH_TRLIB="$(cd -P "$(dirname "${BASH_SOURCE[0]:-$0}")/.." 2>/dev/null && pwd)/fh_track_resolve.sh"
|
|
52
|
+
# shellcheck source=scripts/fh_track_resolve.sh
|
|
53
|
+
[ -f "$_FH_TRLIB" ] && . "$_FH_TRLIB"
|
|
54
|
+
type fh_resolve_track_root >/dev/null 2>&1 || fh_resolve_track_root() {
|
|
55
|
+
local n="$1" root="$2" c hits="" first="" nh
|
|
56
|
+
for c in "$n" "${n}-dev" "$(printf '%s' "$n" | tr '_' '-')"; do
|
|
57
|
+
[ -d "$root/$c" ] || continue
|
|
58
|
+
case " $hits " in *" $c "*) continue ;; esac
|
|
59
|
+
hits="$hits $c"; [ -n "$first" ] || first="$c"
|
|
60
|
+
done
|
|
61
|
+
nh=$(printf '%s' "$hits" | wc -w | tr -d ' ')
|
|
62
|
+
if [ "${nh:-0}" -gt 1 ]; then
|
|
63
|
+
printf '%s|AMBIGUOUS:%s' "$root/$n" "$(printf '%s' "$hits" | sed 's/^ //; s/ /,/g')"; return 0
|
|
64
|
+
fi
|
|
65
|
+
[ -n "$first" ] || { printf '%s|UNRESOLVED' "$root/$n"; return 0; }
|
|
66
|
+
[ "$first" = "$n" ] && { printf '%s|' "$root/$n"; return 0; }
|
|
67
|
+
printf '%s|alias:%s' "$root/$first" "$first"
|
|
68
|
+
}
|
|
69
|
+
|
|
38
70
|
# ๋ณ์นญ ํ๋ณด โ ๋ซํ ๋ชฉ๋ก. ์ค์บ๋์ `_resolve_root` ์ **๊ฐ์ ์์**์ฌ์ผ ํ๋ค.
|
|
39
71
|
fh_peer_alias_candidates() { # $1=name โ ํ๋ณด๋ฅผ ์ค ๋จ์๋ก
|
|
40
72
|
printf '%s\n' "$1" "$1-dev" "$(printf '%s' "$1" | tr '_' '-')"
|
|
@@ -74,13 +106,33 @@ EOF
|
|
|
74
106
|
printf 'peer-resolve: ํ๋ก์ ํธ ํ์ด ์๋ค: %s (์ ์ ํ์์ด์ง ยซpeer ์์ยป ์ด ์๋๋ค)\n' "$home" >&2
|
|
75
107
|
return 3
|
|
76
108
|
fi
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
109
|
+
# ๐ฅ ์ฌ๊ธฐ๊ฐ ๋จ์ผ ์์ค๋ก ๋ซํ ์๋ฆฌ๋ค. ์ ์ธ๋ผ์ธ ๋ฃจํ(๋ณ์นญ 3์ข
+ ๊ณต๋ฐฑ ๊ตฌ๋ถ์ dedup)๋ฅผ
|
|
110
|
+
# `fh_resolve_track_root` ๋ก ๋์ฒดํ๋ค. ์ถ๋ ฅ ๊ณ์ฝ์ **์๋์์ ์ ํ๊ธฐ๋ก ๋ณต์**ํ๋ค โ
|
|
111
|
+
# ์๋น์ 4์ข
๊ณผ ๋ ์ธ์ ์ฌ์ ํ rc(0/1/2/3) + ์ stderr ๋ฌธ๊ตฌ๋ฅผ ์ฝ๋๋ค.
|
|
112
|
+
local rr note
|
|
113
|
+
rr="$(fh_resolve_track_root "$n" "$home" dir)"
|
|
114
|
+
note="${rr##*|}"
|
|
115
|
+
case "$note" in
|
|
116
|
+
AMBIGUOUS:*)
|
|
117
|
+
# ์ ํ๊ธฐ ๋ณต์: ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ **ํ๋ณด ์ด๋ฆ**์ ์ฝค๋ง๋ก ์ฃผ๊ณ , ์ ๋ฉ์์ง๋ **์ ๋๊ฒฝ๋ก**๋ฅผ
|
|
118
|
+
# ยซ, ยป ๋ก ์ด์ด ๋ถ์๋ค. ๊ณต๋ฐฑ ์๋ ์ด๋ฆ์์๋ ๋ฐ์ดํธ ๋์ผํ๋ค.
|
|
119
|
+
local _l="${note#AMBIGUOUS:}" _c _paths=""
|
|
120
|
+
while IFS= read -r _c; do
|
|
121
|
+
[ -n "$_c" ] || continue
|
|
122
|
+
if [ -n "$_paths" ]; then _paths="$_paths, $home/$_c"; else _paths="$home/$_c"; fi
|
|
123
|
+
done <<EOF
|
|
124
|
+
$(printf '%s' "$_l" | tr ',' '\n')
|
|
83
125
|
EOF
|
|
126
|
+
printf 'peer-resolve: ํ ์ด๋ฆ์ ๋ ํฌ ์ฌ๋ฟ โ ๊ณ ๋ฅด์ง ์๋๋ค: %s\n' "$_paths" >&2
|
|
127
|
+
return 2
|
|
128
|
+
;;
|
|
129
|
+
UNRESOLVED)
|
|
130
|
+
first="" # ์๋ ๊ณตํต ยซ๋ถ์ฌยป ๋ถ๊ธฐ๋ก ๋จ์ด์ง๋ค (rc=1 ยท ์ ๋ฌธ๊ตฌ ๊ทธ๋๋ก)
|
|
131
|
+
;;
|
|
132
|
+
*)
|
|
133
|
+
first="${rr%|*}"
|
|
134
|
+
;;
|
|
135
|
+
esac
|
|
84
136
|
fi
|
|
85
137
|
|
|
86
138
|
nh=$(printf '%s' "$hits" | wc -w | tr -d ' ')
|
|
@@ -76,6 +76,31 @@ CAP_SUBDIR=".claude/capabilities"
|
|
|
76
76
|
# ํ
์คํธยท๋ค๋ฅธ ๋ฐฐ์น๋ฅผ ์ํด `FH_CLUSTER_ROOTS`(์ฝ๋ก ๊ตฌ๋ถ ์ ๋๊ฒฝ๋ก ๋ชฉ๋ก)๋ก ํต์งธ ๋์ฒดํ ์ ์๋ค.
|
|
77
77
|
PROJECTS_HOME="${FH_PROJECTS_HOME:-$HOME/projects}"
|
|
78
78
|
|
|
79
|
+
# track ์ด๋ฆ โ ๋ ํฌ ๋ฃจํธ ํด์์ scripts/fh_track_resolve.sh ๊ฐ ๋จ์ผ ์์ค๋ค (2026-08-21 F-1).
|
|
80
|
+
# ๐ฅ **์ด ํ์ผ์ด ๊ทธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์๋ณธ์ด๋ค** โ ๋ซํ ๋ณ์นญ 3์ข
+ ๋ณ์นญ ํ๋ฉดํ + ๋ชจํธ๊ฑฐ๋ถ๋ ์ฌ๊ธฐ์
|
|
81
|
+
# ๋ฝ์๋ธ ๊ฒ์ด๊ณ , ๊ฐ๋ผ์ ธ ์๋ ๋๋จธ์ง ๋ ์๋น์(fh_session_load.sh ยท field_canon_preload.sh)๊ฐ
|
|
82
|
+
# ๊ฐ์ ๋ฒ์ ์ฐ๊ฒ ๋๋ ๊ฒ์ด ์ด ๋ฐฐ์ ์ ์ ๋ถ๋ค. ์ด ํ์ผ์ ๋์์ ๋ฐ๋์ง ์๋๋ค.
|
|
83
|
+
# ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์์ผ๋ฉด **์๋ฆฌ ์ด์ ๋์**(= ์๋ ์ธ๋ผ์ธ ๊ตฌํ)์ผ๋ก ๊ฐ๋ฑํ๋ค โ ๋ค๋ฅธ ๋ ์๋น์์
|
|
84
|
+
# ๊ฐ์ ํํ๋ค. ์ ์คํจ ๋ชจ๋๋ฅผ ๋ง๋ค์ง ์๋๋ค.
|
|
85
|
+
_FH_TRLIB="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)/fh_track_resolve.sh"
|
|
86
|
+
# shellcheck source=scripts/fh_track_resolve.sh
|
|
87
|
+
[ -f "$_FH_TRLIB" ] && . "$_FH_TRLIB"
|
|
88
|
+
type fh_resolve_track_root >/dev/null 2>&1 || fh_resolve_track_root() {
|
|
89
|
+
local n="$1" root="$2" c hits="" first=""
|
|
90
|
+
for c in "$n" "$n-dev" "$(printf '%s' "$n" | tr '_' '-')"; do
|
|
91
|
+
[ -d "$root/$c" ] || continue
|
|
92
|
+
case " $hits " in *" $c "*) continue ;; esac
|
|
93
|
+
hits="$hits $c"; [ -n "$first" ] || first="$c"
|
|
94
|
+
done
|
|
95
|
+
local nh; nh=$(printf '%s' "$hits" | wc -w | tr -d ' ')
|
|
96
|
+
if [ "${nh:-0}" -gt 1 ]; then
|
|
97
|
+
printf '%s|AMBIGUOUS:%s' "$root/$n" "$(printf '%s' "$hits" | sed 's/^ //;s/ /,/g')"; return 0
|
|
98
|
+
fi
|
|
99
|
+
[ -n "$first" ] || { printf '%s|UNRESOLVED' "$root/$n"; return 0; }
|
|
100
|
+
[ "$first" = "$n" ] && { printf '%s|' "$root/$n"; return 0; }
|
|
101
|
+
printf '%s|alias:%s' "$root/$first" "$first"
|
|
102
|
+
}
|
|
103
|
+
|
|
79
104
|
_die() { printf 'โ %s\n' "$1" >&2; exit "$RC_HARNESS"; }
|
|
80
105
|
|
|
81
106
|
# โโ `.cap` ํ์ผ ์ด๊ฑฐ โ **๋จ ํ๋์ ์์ค** โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
@@ -150,20 +175,24 @@ _enumerate_harnesses() {
|
|
|
150
175
|
# ๐ฅ ๊ทธ๋๋ ยซ์กฐ์ฉํ ์ถ์ธกยป ํ์ง๋ ์๋๋ค. ๋ณ์นญ์ **๋ซํ ๋ชฉ๋ก**์ด๊ณ , ๋ง์ ๋ณ์นญ์
|
|
151
176
|
# `_ALIAS_USED` ๋ก ํ๋ฉดํ๋๋ค. ์ฌ๋ฌ ๊ฐ๊ฐ ๋์์ ๋ง์ผ๋ฉด **๊ณ ๋ฅด์ง ์๊ณ ๋ชจํธ๋ก ๋ธ๋ค** โ
|
|
152
177
|
# ๋ ์ค ํ๋๋ฅผ ์กฐ์ฉํ ๊ณ ๋ฅด๋ ๊ฒ์ด ์ด ํ์ผ์ด ๋ฐ๋ํ๋ ๊ทธ ์ ํ์ด๋ค.
|
|
178
|
+
# ๐ฅ ์ด ํจ์๋ ์ด์ **์ด๋ํฐ**๋ค โ ํด์์ `fh_resolve_track_root`(๋จ์ผ ์์ค)๊ฐ ํ๊ณ , ์ฌ๊ธฐ์๋
|
|
179
|
+
# ์ด ํ์ผ์ **ํ์ ๊ณ์ฝ**์ผ๋ก ์ฎ๊ธด๋ค. ๋ ๊ณ์ฝ์ด ๋ฏธ๋ฌํ๊ฒ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์กฐ์ฉํ ํต๊ณผ์ํค์ง
|
|
180
|
+
# ์๋๋ค:
|
|
181
|
+
# ๋ผ์ด๋ธ๋ฌ๋ฆฌ `alias:<c>` โ ์ฌ๊ธฐ `๊ฒฝ๋ก ๋ณ์นญ โ alias:<c>` (OK ํ์ DETAIL ๋ก ์ง์ ์ถ๋ ฅ๋จ)
|
|
182
|
+
# ๋ผ์ด๋ธ๋ฌ๋ฆฌ `UNRESOLVED` โ ์ฌ๊ธฐ ๋น ๋ฌธ์์ด (๋ถ์ฌ๋ `_harness_status` ๊ฐ
|
|
183
|
+
# UNREACHABLE ๋ก ํ์ ํ๋ค)
|
|
184
|
+
# `AMBIGUOUS:<...>` ๋ ์์ชฝ์ด ๊ฐ์ ํ๊ธฐ์ด๊ณ `_harness_status` ์ `AMBIGUOUS:*` ๋ถ๊ธฐ๊ฐ
|
|
185
|
+
# ๊ทธ๋๋ก ๋ฐ๋๋ค. ์ ์ด๋ `dir` โ ์ด ์ค์บ๋๋ ยซ๋๋ ํ ๋ฆฌ๊ฐ ์๋ยป ๋ฅผ ๋ฌป๋๋ค(git ๋ ํฌ ์ฌ๋ถ๊ฐ
|
|
186
|
+
# ์๋๋ค). ๊ทธ ์ฐจ์ด๋ ์๋์ด์ง ๊ฐ๋ผ์ง์ด ์๋๋ค(๋ผ์ด๋ธ๋ฌ๋ฆฌ ํค๋ ์ฐธ์กฐ).
|
|
153
187
|
_resolve_root() { # $1=track ์ด๋ฆ โ "<root>|<alias-note>"
|
|
154
|
-
local
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
printf '%s|AMBIGUOUS:%s' "$PROJECTS_HOME/$n" "$(printf '%s' "$hits" | sed 's/^ //;s/ /,/g')"
|
|
163
|
-
return
|
|
164
|
-
fi
|
|
165
|
-
[ -n "$first" ] && [ "$first" != "$n" ] && note="๊ฒฝ๋ก ๋ณ์นญ โ alias:$first"
|
|
166
|
-
printf '%s|%s' "$PROJECTS_HOME/${first:-$n}" "$note"
|
|
188
|
+
local rr note
|
|
189
|
+
rr="$(fh_resolve_track_root "$1" "$PROJECTS_HOME" dir)"
|
|
190
|
+
note="${rr#*|}"
|
|
191
|
+
case "$note" in
|
|
192
|
+
alias:*) printf '%s|๊ฒฝ๋ก ๋ณ์นญ โ %s' "${rr%%|*}" "$note" ;;
|
|
193
|
+
UNRESOLVED) printf '%s|' "${rr%%|*}" ;;
|
|
194
|
+
*) printf '%s' "$rr" ;;
|
|
195
|
+
esac
|
|
167
196
|
}
|
|
168
197
|
|
|
169
198
|
# ํ ํ๋ค์ค์ ์ํ๋ฅผ ํ์ ํ๋ค. ์ถ๋ ฅ ํ ์ค: "<name>\t<STATUS>\t<n>\t<detail>"
|
|
@@ -590,12 +619,25 @@ EOF
|
|
|
590
619
|
# ([[feedback_ci_measures_state_not_transition]] ์ ๋ฐ์ดํฐ ํ๋ณธ).
|
|
591
620
|
# ์ต์ปค๋ฅผ **์ถ์ ๋๋ ํ์ผ**๋ก ์ฎ๊ธด๋ค โ `.claude/capabilities/*.cap` ์ ์ปค๋ฐ๋ผ ์์ด
|
|
592
621
|
# ์ด๋ ์ฒดํฌ์์์์๋ ์กด์ฌํ๋ค. ์์ง ๊ฒฝ๋ก๊ฐ ์ฃฝ์ผ๋ฉด ์ด ์นด์ดํธ๊ฐ 0 ์ด ๋์ด ๋นจ๊ฐ์ง๋ค.
|
|
622
|
+
# ๐ฅ 2026-08-20 โ ์ด ๋ ์ธ์ **๋ ๊ตฐ๋ฐ๊ฐ ์ ์์ ์ฒดํฌ์์์ ๊ฒฐ๋ฐ**๋ผ ์์๊ณ , ์๋น์ ์ค์น์์
|
|
623
|
+
# ์ ๊ฑด ์ ์์ด์๋ค(์ค์ธก: ๋ ์ง์คํธ๋ฆฌ ์ค๋ฌผ 2.5.1 ์์ `discover` rc=10 โ selfcheck FAIL).
|
|
624
|
+
# โ ์ ์ : `discover` ๋ `tracks/` ๋งคํ ๋ชฉ๋ก์ ์ ์ ํ๋๋ฐ `tracks/` ๋ gitignored ๋ผ
|
|
625
|
+
# **๋ฐฐํฌ๋ฌผ์ ๊ตฌ์กฐ์ ์ผ๋ก ์กด์ฌํ ์ ์๋ค.** ๋ถ์ฌ๋ ยซ๋ฅ๋ ฅ 0ยป ์ด ์๋๋ผ **๋ฏธ์ธก์ **์ด๋ฏ๋ก
|
|
626
|
+
# FAIL ์ด ์๋๋ผ ์ด๋ฆ ์๋ SKIP ์ผ๋ก ๋ธ๋ค([[feedback_not_found_is_not_zero_family]]).
|
|
627
|
+
# โ ๐ฅ **์ดํ์ด ์ฌ๊ธฐ์ ํ๋ ธ๊ณ , cross-family(codex/gpt-5.5)๊ฐ ์ก์๋ค โ ์๋ ฅ ์ ๋ฐ 0.**
|
|
628
|
+
# ๊ธฐ๋ ๋ฌธ์์ด `^forge-harness\(hub\)` ๋ฅผ ยซํด๋๋ช
๊ฒฐ๋ฐยป ์ผ๋ก ์ฝ๊ณ `basename` ์ ๋๋ก
|
|
629
|
+
# ๋ฐ๊ฟจ๋๋ฐ, **์์ฐ์(:128)๋ ๋ฆฌํฐ๋ด `forge-harness(hub)` ๋ฅผ ๋ธ๋ค.** ์ฆ ์ ๋๋ก ๋ฐ๊พธ๋ฉด
|
|
630
|
+
# ์ด๋ฆ์ด ๋ค๋ฅธ ํธ๋ฆฌ์์ ๊ธฐ๋์ ์ฐ์ถ์ด ๊ฐ๋ ค **๊ฑฐ์ง FAIL** ์ด ๋๋ค โ ์ด ํ์ผ์ด ๋ฐ๋ก ์์์
|
|
631
|
+
# ๊ฒฝ๊ณ ํ๋ divergent-normalizer ๋ฅผ ์๋ฆฌ๊ฐ ์๋ก ๋ง๋ ๊ผด์ด๋ค. ๋๋๋ ธ๋ค.
|
|
632
|
+
# ์ง๋จ ์ ์ : ์ด ๋ผ๋ฒจ์ ยซ๋๋ ํฐ๋ฆฌ ์ด๋ฆยป์ด ์๋๋ผ **ํ๋ธ์ ์์ ์๋ณ์**๋ค. ์์ชฝ์ด ๊ฐ์
|
|
633
|
+
# ์์๋ฅผ ์ฐ๋ ํ ์ด๋ ์ฒดํฌ์์์์๋ ์ผ์นํ๋ฏ๋ก ๊ฒฐ๋ฐ์ด ์๋๋ค. ๊ฒฐ๋ฐ์ โ ํ๋์๋ค.
|
|
634
|
+
local _hubroot
|
|
635
|
+
_hubroot="$(cd -P "$(dirname "$SELF")/.." && pwd)"
|
|
636
|
+
tracked_n="$(_cap_files "$_hubroot/.claude/capabilities" | wc -l | tr -d ' ')"
|
|
593
637
|
out="$(bash "$SELF" discover 2>&1)"; rc=$?
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
tracked_n="$(_cap_files "$(cd -P "$(dirname "$SELF")/.." && pwd)/.claude/capabilities" | wc -l | tr -d ' ')"
|
|
598
|
-
if [ "${tracked_n:-0}" -lt 1 ]; then
|
|
638
|
+
if [ ! -d "$_hubroot/tracks" ]; then
|
|
639
|
+
echo " โญ L13c SKIP โ tracks/ ๋ถ์ฌ๋ผ discover ์ ์ ์ ๊ฐ ์๋ค(gitignored, ๋ฐฐํฌ๋ฌผ์ ๊ตฌ์กฐ์ ๋ถ์ฌ). ๋ฏธ์ธก์ ์ด์ง ยซ0๊ฑดยป ์๋"
|
|
640
|
+
elif [ "${tracked_n:-0}" -lt 1 ]; then
|
|
599
641
|
f=$((f+1)); echo " โ L13c ์ ์ ํ์ โ ์ถ์ ๋๋ .claude/capabilities/*.cap ์ด 0๊ฑด์ด๋ค(์ต์ปค ๋์ ๋ถ์ฌ)"
|
|
600
642
|
elif printf '%s' "$out" | grep -qE '^forge-harness\(hub\)[[:space:]]+OK[[:space:]]+'"$tracked_n"'[[:space:]]'; then
|
|
601
643
|
p=$((p+1)); echo " โ
L13c ์ค๋ฌผ ์์ง์ด ์ด์ ์๋ค โ ํ๋ธ ์์ ์ ์ถ์ ์ ์ธ ${tracked_n}๊ฑด์ ์ค์ ๋ก ์ง์๋ค"
|