@chrono-meta/fh-gate 2.0.1 โ 2.2.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 +77 -1
- package/.claude-plugin/marketplace.json +3 -3
- package/AGENTS.md +26 -3
- package/CLAUDE.md +240 -4
- package/knowledge/shared/harness-core/capability_composition_contract.md +68 -0
- package/knowledge/shared/harness-core/fh_three_layer_canon.md +38 -12
- package/knowledge/shared/harness-core/field_verdict_crossfamily_gate.md +115 -3
- package/knowledge/shared/harness-core/harness_incubator_doctrine.md +82 -0
- package/knowledge/shared/harness-core/harness_terminal_correlation_and_recommendations.md +85 -10
- package/knowledge/shared/harness-core/ship_readiness_gate.md +241 -1
- package/knowledge/shared/learnings/subagent_invocations_log.yaml +102 -0
- package/knowledge/shared/rules/sister_asset_protocol.md +12 -0
- package/package.json +7 -2
- package/plugins/fh-commons/.claude-plugin/plugin.json +1 -1
- package/plugins/fh-commons/agents/quench-challenger.md +6 -1
- package/plugins/fh-commons/skills/ko-tech-writer/fixtures/known_negative.md +19 -0
- package/plugins/fh-commons/skills/ko-tech-writer/fixtures/known_positive.md +20 -0
- package/plugins/fh-meta/.claude-plugin/plugin.json +1 -1
- package/plugins/fh-meta/CHANGELOG.md +88 -0
- package/plugins/fh-meta/skills/auto-decorrelation/SKILL.md +14 -2
- package/plugins/fh-meta/skills/steel-quench/SKILL_detail.md +13 -0
- package/plugins/fh-meta/skills/verify-bidirectional/SKILL.md +34 -1
- package/scripts/capability_registry_check.sh +75 -12
- package/scripts/chamber_run.sh +39 -5
- package/scripts/chamber_witness.sh +25 -0
- package/scripts/fh-gate.sh +16 -1
- package/scripts/ko_tech_writer_calibrate.py +127 -0
- package/scripts/package_coverage_check.sh +10 -0
- package/scripts/prepublish_scope_note.sh +139 -0
- package/scripts/publish_freshness_check.sh +21 -2
- package/scripts/selfcheck.sh +32 -6
- package/scripts/test_fh_gate_regressions.sh +21 -9
- package/scripts/test_ko_tech_writer_lanes.sh +61 -0
- package/scripts/test_marker_axes_run_lanes.sh +87 -3
- package/scripts/test_marker_crossfamily_lanes.sh +31 -1
- package/templates/.git-hooks/pre-commit +225 -10
- package/templates/subagent-tally-hook.json +2 -2
|
@@ -10,6 +10,94 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
|
|
10
10
|
|
|
11
11
|
## Plugin Level
|
|
12
12
|
|
|
13
|
+
### [2.2.0] โ 2026-08-17
|
|
14
|
+
|
|
15
|
+
๐ฅ **BREAKING (gate)**: chamber step 6 now reads `ACTUAL.md`, **not `BUDGET.md`**. An in-flight
|
|
16
|
+
chamber run whose actual cost was written into `BUDGET.md` will **block at step 6** until the value
|
|
17
|
+
moves to a new `ACTUAL.md` in the same workspace.
|
|
18
|
+
- **Remedy**: the runner prints the exact path when it blocks โ move the `ACTUAL:` line to
|
|
19
|
+
`tracks/_chamber/<slug>/ACTUAL.md`. `BUDGET.md` keeps `ESTIMATE:` only.
|
|
20
|
+
- **Why**: `BUDGET.md`'s pre-verdict hash IS the ordering witness (`ship_readiness_gate ยงโก P1`), and
|
|
21
|
+
step 6 was hard-blocking until that same file changed. So **every run that reached COMPLETE
|
|
22
|
+
necessarily mutated a witnessed artifact** and `verify` returned `TAMPERED` โ identity โก's only
|
|
23
|
+
promotion condition was unsatisfiable by construction, not by strictness. Measured on chamber run
|
|
24
|
+
#11, the first run ever taken through step 7. Two roles (immutable witness / post-verdict
|
|
25
|
+
calibration sink) had collided in one file; each was correct alone, so neither side's code showed
|
|
26
|
+
the conflict.
|
|
27
|
+
|
|
28
|
+
**Added**
|
|
29
|
+
- `scripts/ko_tech_writer_calibrate.py` + `scripts/test_ko_tech_writer_lanes.sh` + two known-pair
|
|
30
|
+
fixtures โ the discrimination of `ko-tech-writer` Step 2 (five translationese classes) and
|
|
31
|
+
Step 4-b (universal-claim candidates) is now **reproducible**: positive โฅ1 / negative 0 per class,
|
|
32
|
+
plus two META controls. Wired into `selfcheck.sh` and shipped in `files[]`.
|
|
33
|
+
๐ฅ **What this does NOT prove**: "zero residue" in any real document. Discrimination and residue
|
|
34
|
+
are different propositions; the suite prints that warning itself.
|
|
35
|
+
- Chamber lane suite **12 โ 33 lanes**, including the **runner ร witness seam** that no test covered
|
|
36
|
+
(the runner's lanes excluded the witness by design; the witness self-test ran it standalone).
|
|
37
|
+
|
|
38
|
+
**Changed**
|
|
39
|
+
- `chamber_run.sh` now teaches the **two-commit discipline** where the actor reads it: gate hashes
|
|
40
|
+
and the verdict hash must land in **separate commits** (and, for a squash-merge repo, **separate
|
|
41
|
+
PRs**). Committing them together yields `UNORDERED` โ the runner previously advised the opposite.
|
|
42
|
+
- `chamber_witness.sh do_record` skips a byte-identical re-record of the same
|
|
43
|
+
`(run, artifact, sha)` triple. A **changed** artifact still appends โ that is the tamper evidence.
|
|
44
|
+
|
|
45
|
+
**Fixed**
|
|
46
|
+
- `harness_terminal_correlation_and_recommendations.md` Appendix: Step 2 / Step 4 rows move from
|
|
47
|
+
๐ฅ `UNCALIBRATED` to ๐ก **partially resolved**, with the reproduction command recorded. The
|
|
48
|
+
original claims ("zero residue" in that document; Step 4's numeric extraction half) remain
|
|
49
|
+
**unverified and are labelled as such**.
|
|
50
|
+
|
|
51
|
+
**Known residual (not closed)**
|
|
52
|
+
- Identity โก stays **RC**. No run has yet been `WITNESSED` on `main`; the two-PR prescription is
|
|
53
|
+
reasoned from the verify logic, and its efficacy is provable only by the next EMIT run.
|
|
54
|
+
- `--delete-branch` still orphans ordering evidence โ warned in prose, not blocked.
|
|
55
|
+
- Of Step 2's five "machine-detectable" classes, only two ship an actual grep in `SKILL.md`; the
|
|
56
|
+
calibration surfaced that the doc over-claims. C4's pattern is a closed noun list with **low recall**.
|
|
57
|
+
|
|
58
|
+
### [2.1.0] โ 2026-08-17
|
|
59
|
+
|
|
60
|
+
๐ฅ **BREAKING (gate)**: `crossfamily: declined` in an Axes 2-3 marker now requires grounds naming a
|
|
61
|
+
record path that **resolves on disk**. Bare `declined`, and `declined` justified by author judgment,
|
|
62
|
+
are **blocked at commit**.
|
|
63
|
+
- **Remedy**: cite where the operator decision lives โ e.g.
|
|
64
|
+
`crossfamily: declined โ operator declined sidecars, per knowledge/shared/rules/operational_adaptation.md`
|
|
65
|
+
- **Or use the value that describes what actually happened**: if a panel was reachable and you chose
|
|
66
|
+
not to recruit it, that is `DEGRADED_PANEL_UNUSED`, not `declined`.
|
|
67
|
+
- **Why**: `declined` was the only value in the enum with no grounds requirement, so an author
|
|
68
|
+
judgment flowed into the nearest permissive token and passed clean. A cross-family review then
|
|
69
|
+
broke the first (vocabulary-grep) fix three ways โ self-validating on the value's own token,
|
|
70
|
+
vacuous keyword passes, and over-blocking genuine declinations phrased in natural prose โ so the
|
|
71
|
+
check asserts a **resolvable record** rather than words. It proves a cited record EXISTS, not that
|
|
72
|
+
it says what is claimed; that residual is the marker's own declared scope, stated in the code.
|
|
73
|
+
|
|
74
|
+
**Added**
|
|
75
|
+
- `standpoint:` gains **`tier1b`** (a STATIC read of a target repo โ executed nothing) plus a
|
|
76
|
+
decide-in-order procedure, after blind floor-tier sims graded pure cold-reads as `tier2` for three
|
|
77
|
+
rounds, defeating three separate rewordings via the enum's own internal logic.
|
|
78
|
+
- steel-quench Wave 1's sixth angle (**gate-locality**) gains the output-template row it never had โ
|
|
79
|
+
a mandatory angle that was structurally unreportable. Gate-locality failing its own check.
|
|
80
|
+
- `verify-bidirectional` category 5 โ **prescriptive doctrine statement**, the operator-correction
|
|
81
|
+
shape that fell between its doubt-shaped triggers and its "simple correction, no review" exception.
|
|
82
|
+
- Sister Asset Protocol gains an **active-adoption** condition โ all four prior conditions were
|
|
83
|
+
passive discovery, so installing an external framework and running it against our own asset
|
|
84
|
+
matched none of them.
|
|
85
|
+
- Resident doctrine: **Mechanization Boundary** (machinery at irreversible edges and channels;
|
|
86
|
+
judgment left to evolution) ยท **Local Execution First** (CI is a backstop, never the discovery
|
|
87
|
+
mechanism) ยท **Skeleton-not-Muscle** (a wiring change is done when the floor tier executes it) ยท
|
|
88
|
+
**Expedition** track ยท **this package's versioning policy** (major reserved for built-anew /
|
|
89
|
+
identity-established / capability-class change โ never for tightening an existing gate).
|
|
90
|
+
|
|
91
|
+
**Fixed**
|
|
92
|
+
- `fh-gate.sh` survives a missing or unreadable `package.json`; `selfcheck.sh` decides npm-surface
|
|
93
|
+
applicability at the call site.
|
|
94
|
+
- `capability_registry_check.sh` M3 basename-token matching (a path containing "claude" was silently
|
|
95
|
+
rejected) + a stdin channel for calibration arms.
|
|
96
|
+
- `subagent-tally-hook.json` root resolution is 3-tier, matching the convention the sibling
|
|
97
|
+
`SessionStart` hook already used.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
13
101
|
### [2.0.1] โ 2026-08-16
|
|
14
102
|
|
|
15
103
|
- **feat(cadence)**: `harness-doctor` 30์ผ ์บ๋์ค๊ฐ ์ฐ๋ฌธ ์ ์์์ SessionStart ํ
์ผ๋ก ์น๊ฒฉ โ
|
|
@@ -264,8 +264,20 @@ enforceable layer) from the **declined** case above (chosen floor, first-class,
|
|
|
264
264
|
**shared-body / cross-harness-boundary** change โ scoped by *effect* (alters another harness's
|
|
265
265
|
behavior, gate outcome, or interaction contract), not merely by touching a synced file path โ also
|
|
266
266
|
emit `standpoint:` alongside `crossfamily:` in the same marker โ recruiting family diversity here
|
|
267
|
-
does not substitute for it. Values: `tier1` (content-only, the default) ยท
|
|
268
|
-
(
|
|
267
|
+
does not substitute for it. Values: `tier1` (content-only, the default) ยท **`tier1b(<harness>)`
|
|
268
|
+
(STATIC read of the target's own files โ executed nothing)** ยท `tier2(<harness>)`
|
|
269
|
+
(peer-simulated โ **EXECUTED CODE in** the target's own repo and observed the result.
|
|
270
|
+
๐ฅ **Reading the target's real files, however cold, is `tier1b`, not this.** The discriminator is
|
|
271
|
+
mechanical: *name the command you ran and the output you saw*; cannot name one โ `tier1b`, always.
|
|
272
|
+
This line said **"ran the target's own repo, content only"** until 2026-08-17 โ actively teaching
|
|
273
|
+
the opposite of the canon it summarizes. ๐ฅ **RETRACTED (2026-08-17)**: this passage used to add
|
|
274
|
+
that blind Sonnet sims *"STILL graded a pure cold-read `tier2`, both quoting this phrasing"* after
|
|
275
|
+
the other two copies were fixed. Those runs had **`tool_uses: 0`** โ nothing was read, so nothing
|
|
276
|
+
was measured, and the claim that the sims "reached for this copy" was itself unfounded
|
|
277
|
+
(`tracks/_meta/fh_completed_2026-08-16.md:690`; the live re-run inverted the grade at reps=1, below
|
|
278
|
+
bar). **The reason to fix this copy needs no sim**: a summary that states the opposite of its canon
|
|
279
|
+
teaches the opposite to whoever reads only the summary, and **two of three copies fixed is a fix
|
|
280
|
+
that does not exist** โ that is gate-locality, not a measurement. See `ยง7` for the canon) ยท `tier2b(<harness>)` (same operator,
|
|
269
281
|
target's real runtime โ local wiring visible, but not an independent reviewer) ยท `tier3(<harness>)`
|
|
270
282
|
(a *different* operator of the target harness ran it โ the only fully independent + local-wiring
|
|
271
283
|
rung) ยท `not-applicable` (no target-harness standpoint exists โ most same-repo dispatches) ยท
|
|
@@ -60,9 +60,22 @@ Added Wave 1 attack angles: N items
|
|
|
60
60
|
| Bus factor | S/A/B | [single-person dependency area] | โ/โณ/ร |
|
|
61
61
|
| Platform obsolescence | S/A/B | [vulnerability point] | โ/โณ/ร |
|
|
62
62
|
| Self-referential structure | S/A/B | [closed circuit detection result] | โ/โณ/ร |
|
|
63
|
+
| Gate-locality | S/A/B | [any gate defined only where the enforcing actor never reads it] | โ/โณ/ร |
|
|
63
64
|
|
|
64
65
|
S-grade blockers: N / A-grade: N / B-grade: N
|
|
65
66
|
|
|
67
|
+
> ๐ฅ **The 6th row was missing until 2026-08-16, and its absence was itself a gate-locality defect.**
|
|
68
|
+
> `SKILL.md` Wave 1 has defined **six** angles since Gate-locality was added; this template shipped
|
|
69
|
+
> **five rows**, and `quench-challenger.md` still said "5 angles" and omitted it from the
|
|
70
|
+
> enumeration. So a mandatory angle had **no slot to be reported in** โ an agent filling this table
|
|
71
|
+
> correctly would report the other five and structurally never surface the sixth. That is the exact
|
|
72
|
+
> shape Gate-locality itself is the check for: *a requirement placed where the actor who must
|
|
73
|
+
> satisfy it does not read it.* Found by a sister-asset audit (an external adversarial framework's
|
|
74
|
+
> **typed** attack registry vs. this repo's seven overlapping prose lists) โ the fragmentation is
|
|
75
|
+
> what let the three copies drift apart silently. If you add a Wave 1 angle, it lands in **three**
|
|
76
|
+
> places or it does not land: `SKILL.md`'s table, this template, and `quench-challenger.md`'s
|
|
77
|
+
> role-separation paragraph.
|
|
78
|
+
|
|
66
79
|
Optional numeric score (0.0โ1.0):
|
|
67
80
|
overall_score: {score}
|
|
68
81
|
[0.0โ0.3] S-grade present โ immediate blocker, do not proceed
|
|
@@ -39,8 +39,41 @@ Also triggered in external user environments by these natural language phrases:
|
|
|
39
39
|
| "what's your basis?", "why do you think that?" | Baseline grep trigger |
|
|
40
40
|
| "check that one more time" | Self-validation request |
|
|
41
41
|
|
|
42
|
+
### ๐ฅ 5. Prescriptive doctrine statement โ the category that fell through (added 2026-08-16)
|
|
43
|
+
|
|
44
|
+
Every trigger above is shaped as **doubt about a claim**. A large class of operator correction is not
|
|
45
|
+
doubt at all โ it is a **standing rule being handed over**, stated as fact or instruction:
|
|
46
|
+
|
|
47
|
+
| Shape | Real examples (2026-08-16 session) |
|
|
48
|
+
|---|---|
|
|
49
|
+
| *"X should also include Y"* | *"์
์ฅ๋ฆฌ๋ทฐ์๋ ์ ์ ๋ฆฌ๋ทฐ๋ฟ๋ง ์๋๋ผ **๋์ ๋ฆฌ๋ทฐ๋ ํฌํจ๋์ด์ผ ํ ๊ฑฐ์ผ**"* |
|
|
50
|
+
| *"the real point of X is Z"* (redefining, not doubting) | *"๋ถ์คํ
๋ณด๋ค ์ธํ๋ฒ ์ดํฐ์ ์ฅ์ ์ ๊ทธ ๋ ํฌ ์ ์ฒด๋ฅผ ๊ฐ์ธ์ โฆ**๋ชจ๋ ๊ฒ์ ์กฐ์ํ ์ ์๋ ๊ถํ**์ด ์๋ ๊ฑฐ์ผ"* |
|
|
51
|
+
| *"isn't this too late / wrong-ordered?"* (rhetorical, expects agreement) | *"์ด ์คํจ๊ฐ CI ํ์ธ ๋จ๊ณ์์์ผ ๋ฐ๊ฒฌ๋๋ ๊ฑด ๋งค์ฐ **๋ฆ์ ๊ฒ ์๋๊น**"* |
|
|
52
|
+
| *"from now on, do W at Z"* | *"์์ผ๋ก๋ ๋ง๊ฐํ ๋ ๊ทธ ๊ฐ๋๋ก ์ด์ด๊ฐ ์ ์๊ฒ **์์์ ์ ๋ฆฌํด์ค**"* |
|
|
53
|
+
|
|
54
|
+
**Why these were missed 4 times out of 4** โ they sit in the blind spot between the triggers (which
|
|
55
|
+
expect a *challenge*) and the Exceptions below (which release a *simple correction* with "no
|
|
56
|
+
review"). A doctrine statement is neither: it does not dispute a claim, and it is not a one-off fix
|
|
57
|
+
to apply and forget. Treated as the exception, it gets a verbal acknowledgment and evaporates at
|
|
58
|
+
session end. **Measured**: four such statements in one session, all acknowledged in conversation,
|
|
59
|
+
**zero landed in any file** until a later review grepped for them and found nothing.
|
|
60
|
+
|
|
61
|
+
**The tell is grammatical, and it is language-independent** โ the listed phrases above are all
|
|
62
|
+
English interrogatives, which is why a Korean declarative (`~ํด์ผ ํ ๊ฑฐ์ผ` ยท `~์ธ ๊ฑฐ์ผ` ยท `~์๋๊น`)
|
|
63
|
+
matched none of them. Do not fix this by appending more literals (Grep-Collision Treadmill, P10);
|
|
64
|
+
the discriminator is: **does this utterance describe how I should behave from now on, rather than
|
|
65
|
+
what is wrong with this one output?** If yes, it is this category regardless of language or phrasing.
|
|
66
|
+
|
|
67
|
+
**Required action** โ an acknowledgment is not compliance. The statement must land **in a file** in
|
|
68
|
+
the same session: canon (`CLAUDE.md` / `knowledge/`) if it governs future behavior, memory if it is
|
|
69
|
+
about this operator, a signal file if it needs a decision first. Then say WHERE it landed, so the
|
|
70
|
+
operator can see it did.
|
|
71
|
+
|
|
42
72
|
**Exceptions** (this skill does NOT apply):
|
|
43
|
-
- Simple user correction ("this is wrong, redo it") = direct negation โ immediate correction (no review)
|
|
73
|
+
- Simple user correction ("this is wrong, redo it") = direct negation โ immediate correction (no review).
|
|
74
|
+
โ ๏ธ **Not the same as category 5 above** โ "redo this" is scoped to one output; "from now on do X"
|
|
75
|
+
is a standing rule. When both readings fit, take it as category 5: over-landing costs a file edit,
|
|
76
|
+
under-landing loses the rule entirely.
|
|
44
77
|
- This harness AI self-catch (no external counter-argument) = `fact-checker` rule (narrow 1 / broad N+1)
|
|
45
78
|
|
|
46
79
|
## Execution Steps
|
|
@@ -54,7 +54,7 @@ RC_OK=0; RC_REJECT=1; RC_HARNESS=10
|
|
|
54
54
|
# `summary`/`tags` ๋ **์ถ์ฒ ์ ์ฉ**(2026-08-16, cluster-wizard). ํ์ ์๋ ์ ์ฐ์ด๊ณ
|
|
55
55
|
# `cluster_capability_scan.sh recommend` ์ ์ดํ ๋งค์นญ์๋ง ์ฐ์ธ๋ค. ๋ซํ ๋ชฉ๋ก์ ๋ฃ๋ ์ด์ ๋
|
|
56
56
|
# ์ด ๋ชฉ๋ก์ ๋ชฉ์ ์ด ยซ์คํ ์ถ ๋ฌด์ ๋๋กญ ๋ฐฉ์งยป ์ด๊ธฐ ๋๋ฌธ์ด๋ค โ ์ ๋ฃ์ผ๋ฉด ์ ๋นํ ํค๊ฐ SCHEMA ๋ก ๋งํ๋ค.
|
|
57
|
-
CLOSED_KEYS="id entry requires_cwd summary tags verdict_channel verdict_enum verdict_stdout_key upstream_argv echoes_upstream approval reversibility residency degrade tier_floor writes judge verdict_binding calibration_positive_args calibration_positive_expect calibration_negative_args calibration_negative_expect"
|
|
57
|
+
CLOSED_KEYS="id entry requires_cwd summary tags verdict_channel verdict_enum verdict_stdout_key upstream_argv echoes_upstream approval reversibility residency degrade tier_floor writes judge verdict_binding calibration_positive_args calibration_positive_expect calibration_negative_args calibration_negative_expect calibration_positive_stdin calibration_negative_stdin"
|
|
58
58
|
|
|
59
59
|
# ใ์ ๋์๋คใ๋ฅผ ๋ปํ๋ ์ด๋ฆ๋ค โ ์ถ๊ฐ์กฐํญ(ยงโ.4 B1)์ด ์๊ตฌํ๋ ๊ตฌ๋ถํญ
|
|
60
60
|
DIDNOTRUN_NAMES="DID_NOT_RUN DIDNOTRUN NOT_RUN NO_TARGET SKIPPED UNMEASURED NOT_CONFIGURED HARNESS_ERROR"
|
|
@@ -70,6 +70,9 @@ _parse() {
|
|
|
70
70
|
CAP_id=""; CAP_entry=""; CAP_requires_cwd=""; CAP_verdict_channel=""
|
|
71
71
|
CAP_verdict_enum=""; CAP_verdict_stdout_key=""; CAP_judge=""; CAP_writes=""
|
|
72
72
|
CAP_cal_pos_args=""; CAP_cal_pos_expect=""; CAP_cal_neg_args=""; CAP_cal_neg_expect=""
|
|
73
|
+
# ๋ค์ค capfile ์คํ์์ ์ ํ์ผ์ ์ ์ธ์ด ๋ค ํ์ผ๋ก ์์ง ์๊ฒ ํ๋ค โ ์ด๊ธฐํ ๋๋ฝ์
|
|
74
|
+
# "๋ค ํ์ผ์ด ์ ์ธํ์ง ์์ stdin ์ผ๋ก ๋์๋ค" ๋ฅผ ๋ง๋ค๊ณ , ๊ทธ๊ฑด ์กฐ์ฉํ ํต๊ณผํ๋ค.
|
|
75
|
+
CAP_cal_pos_stdin=""; CAP_cal_neg_stdin=""
|
|
73
76
|
UNKNOWN_KEYS=""; CAP_requires_cwd_was_self=0
|
|
74
77
|
# ใ์ ์ธํ๋๋ฐ ๊ฐ์ด ๋น์๋คใ์ ใ์ ์ธ ์์ฒด๊ฐ ์๋คใ๋ ๋ค๋ฅธ ์ฌ์ค์ด๋ค โ ๊ด์ธก ๋ฒ์ ๋ธ๋ก์ด
|
|
75
78
|
# ๋์ ๊ตฌ๋ถํด ์ ์ผ๋ ค๋ฉด ํ์๊ฐ ๊ทธ ๊ตฌ๋ถ์ ๋ณด์กดํด์ผ ํ๋ค(๋น ๋ฌธ์์ด ํ๋๋ก๋ ๋ชป ๋๋๋ค).
|
|
@@ -93,6 +96,8 @@ _parse() {
|
|
|
93
96
|
calibration_positive_args) CAP_cal_pos_args="$val"; CAP_cal_pos_args_seen=1 ;;
|
|
94
97
|
calibration_positive_expect) CAP_cal_pos_expect="$val" ;;
|
|
95
98
|
calibration_negative_args) CAP_cal_neg_args="$val"; CAP_cal_neg_args_seen=1 ;;
|
|
99
|
+
calibration_positive_stdin) CAP_cal_pos_stdin="$val" ;;
|
|
100
|
+
calibration_negative_stdin) CAP_cal_neg_stdin="$val" ;;
|
|
96
101
|
calibration_negative_expect) CAP_cal_neg_expect="$val" ;;
|
|
97
102
|
esac
|
|
98
103
|
done < "$1"
|
|
@@ -119,10 +124,43 @@ _validate_arm_args() { # $1=args โ ์
ธ ๋ฉํ๋ฌธ์/์์๊ฒฝ๋ก ํ์ถ์
|
|
|
119
124
|
return 0
|
|
120
125
|
}
|
|
121
126
|
|
|
122
|
-
|
|
127
|
+
# stdin ํ์ผ ๊ฒ์ฆ โ args ์ ๊ฐ์ ๊ท์จ(๋ฉํ๋ฌธ์ยท์์๊ฒฝ๋ก ํ์ถ ๊ฑฐ๋ถ) + ์ค์ฌ ํ์ธ.
|
|
128
|
+
_validate_arm_stdin() { # $1=์ ์ธ๋ ๊ฒฝ๋ก(๋น ๊ฐ ํ์ฉ)
|
|
129
|
+
[ -n "$1" ] || return 0
|
|
130
|
+
case "$1" in
|
|
131
|
+
*'|'*|*';'*|*'&'*|*'>'*|*'<'*|*'`'*|*'$('*|*$'\n'*)
|
|
132
|
+
_fail "M4" "์บ๋ฆฌ๋ธ๋ ์ด์
stdin ๊ฒฝ๋ก์ ์
ธ ๋ฉํ๋ฌธ์๊ฐ ์๋ค: $1"; return 1 ;;
|
|
133
|
+
*'../'*|/*)
|
|
134
|
+
_fail "M4" "์บ๋ฆฌ๋ธ๋ ์ด์
stdin ๊ฒฝ๋ก๊ฐ ๋ ํฌ ๋ฐ์ ๊ฐ๋ฆฌํจ๋ค(์๋๊ฒฝ๋ก๋ง ํ์ฉ): $1"; return 1 ;;
|
|
135
|
+
esac
|
|
136
|
+
[ -f "$CAP_requires_cwd/$1" ] || {
|
|
137
|
+
_fail "M4" "์บ๋ฆฌ๋ธ๋ ์ด์
stdin ํ์ผ์ด ์๋ค: $1 (์ ์ธ์ ์ค์ฌํ๋ ํฝ์ค์ฒ๋ฅผ ๊ฐ๋ฆฌ์ผ์ผ ํ๋ค)"; return 1; }
|
|
138
|
+
return 0
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
_run_arm() { # $1=extra args ยท $2=stdin ํ์ผ(์ ํ) โ ARM_RC / ARM_NAME. ํ์ดํ๋ก ์ฝ์ง ์๋๋ค(PIPE-VERDICT).
|
|
142
|
+
# โโ STDIN ์ ํญ์ ์ ์๋๋ค. ์์ํ์ง ์๋๋ค. โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
143
|
+
# ์ค์ธก 2026-08-16 (์๊ธฐ์ ์ธ ์บ ํ์ธ, the-bible arm): ์ด ํจ์๋ `> /dev/null 2>&1` ๋ก
|
|
144
|
+
# stdout/stderr ๋ง ๋ง๊ณ **stdin ์ ๊ฒ์ฌ๊ธฐ์ ๊ฒ์ ๋ฌผ๋ ค๋ฐ์๋ค.** ๊ฒฐ๊ณผ๊ฐ ๋ ๊ฐ์ง๋ก ๋๋นด๋ค.
|
|
145
|
+
# โ **๋น๊ฒฐ์ **: ๊ฐ์ ์ ์ธ์ด ํฐ๋ฏธ๋ยทํ์ดํยทCI ์ด๋์ ๋๋ฆฌ๋๋์ ๋ฐ๋ผ arm ์ ์
๋ ฅ์ด ๋ฌ๋ผ์ง๋ค.
|
|
146
|
+
# ํ์ ๊ณ๊ธฐ ์์ ๋น๊ฒฐ์ ์ ๊ทธ ์์ฒด๋ก ๊ฒฐํจ์ด๋ค โ ์ด๋ก์ ์ด์ ๊ฐ ์คํ ํ๊ฒฝ์ ๋ฌ๋ฆฌ๊ฒ ๋๋ค.
|
|
147
|
+
# โ **ํํ ๋ถ๊ฐ**: ๋์์ stdin ์ผ๋ก ๋ฐ๋ ์ง์
์ (JSON ๋ธ๋ฆฌ์ง ๋ฑ)์ ์ยท์ arm ์ด **๋ ๋ค ๋น
|
|
148
|
+
# ์
๋ ฅ**์ผ๋ก ๋์ ๊ฐ์ ์ฝ๋๋ฅผ ๋ด๊ณ , ํ๋ณ ์คํจ๋ก REJECT ๋๋ค. ๋ฅ๋ ฅ์ด ์์ด์๊ฐ ์๋๋ผ
|
|
149
|
+
# **์คํค๋ง์ ์ฑ๋์ด ์์ด์** ๋งํ ๊ฒ์ด๋ค. ์ค์ ๋ก 4๋ฐฉํฅ์ผ๋ก ๊ฐ๋ฆฌ๋ ๊ฒ์ดํธ๊ฐ ๊ทธ๋ ๊ฒ ๋งํ๋ค.
|
|
150
|
+
# โ ์ ์ธ๋ ํ์ผ์ด ์์ผ๋ฉด ๊ทธ๊ฑธ ๋จน์ด๊ณ , ์์ผ๋ฉด **๋ช
์์ ์ผ๋ก /dev/null** ์ ๋จน์ธ๋ค. ํ์๊ฐ
|
|
151
|
+
# ์ค์ํ๋ค โ "์ ์ธ ์ ํ์ผ๋ ์์"์ด ์๋๋ผ "์ ์ธ ์ ํ์ผ๋ฉด ๋น ์
๋ ฅ"์ด๋ผ๊ณ **์ ํด์ผ** โ ๊ฐ ๋ซํ๋ค.
|
|
152
|
+
# ๐ฅ `set --` ๋ ์์น ์ธ์๋ฅผ **๋ฎ์ด์ด๋ค** โ ๊ทธ ๋ค์ `$2` ๋ stdin ํ์ผ์ด ์๋๋ผ entry ์ ๋ ๋ฒ์งธ
|
|
153
|
+
# ํ ํฐ์ด๋ค. ์ดํ์ด ๊ทธ๊ฑธ ๋ฐ์๊ณ , ๊ทธ ๊ฒฐ๊ณผ ๋ arm ์ด **์ง์
์ ์คํฌ๋ฆฝํธ ์์ ์ stdin ์ผ๋ก ๋จน์๋ค.**
|
|
154
|
+
# ๋ฐ๊ฒฌ ๊ฒฝ์๊ฐ ์ด ์์ ์ ์์ ์ด๋ค: ๊ทธ๋ **์์ฑ arm ๋ง ๋นจ๊ฐ์ก๊ณ ์์ฑ arm ์ ํต๊ณผํ๋ค** โ ์คํฌ๋ฆฝํธ
|
|
155
|
+
# ์์ค์ ๋ง์นจ ์์ฑ ํฝ์ค์ฒ์ ๊ฐ์ ํ ํฐ์ด ๋ค์ด ์์ด์๋ค. ์ฆ **๋ ๋ค ํ๋ฆฐ ์
๋ ฅ์ ๋จน์๋๋ฐ ํ๋๊ฐ
|
|
156
|
+
# ์ฐ์ฐํ ๊ธฐ๋๊ฐ๊ณผ ๋ง์๋ค.** ํ์ชฝ๋ง ๋ณด๊ณ ์์์ผ๋ฉด ยซ์์ฑ์ ๋๋๋ฐ ์์ฑ์ด ์ด์ํ๋คยป๋ก ์ค์งํ๋ค.
|
|
157
|
+
# โ set -- ์์์ ์ด๋ฆ ์๋ ๋ณ์๋ก ์ก๋๋ค.
|
|
158
|
+
local _stdin="${2:-}"
|
|
123
159
|
( cd "$CAP_requires_cwd" 2>/dev/null || exit 127
|
|
124
160
|
# shellcheck disable=SC2086 # argv ํ ํฐ ๋ถ๋ฆฌ๋ ์๋ (noglob ๋ก ํ์ฅ์ ๋งํ ์๋ค)
|
|
125
|
-
set -- $CAP_entry $1
|
|
161
|
+
set -- $CAP_entry $1
|
|
162
|
+
if [ -n "$_stdin" ]; then "$@" < "$_stdin"; else "$@" < /dev/null; fi
|
|
163
|
+
) > /dev/null 2>&1
|
|
126
164
|
ARM_RC=$?
|
|
127
165
|
ARM_NAME="$(_enum_name_of "$ARM_RC" "$CAP_verdict_enum")"
|
|
128
166
|
}
|
|
@@ -256,11 +294,35 @@ _check_one() {
|
|
|
256
294
|
# โโ M3 ๋ชจ๋ธ ๋
๋ฆฝ์ฑ (์ ์ธ ๊ฒ์ฌ + ๋ช
๋ฐฑํ ๋ชจ์๋ง) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
257
295
|
case "$CAP_judge" in
|
|
258
296
|
mechanical)
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
297
|
+
# ํ ํฐ์ BASENAME ์ผ๋ก ๋ณธ๋ค โ ๋ฌธ์์ด ์ ์ฒด ๋ถ๋ถ๋งค์นญ์ด ์๋๋ค.
|
|
298
|
+
#
|
|
299
|
+
# ์ค์ธก 2026-08-16 (์๊ธฐ์ ์ธ ์บ ํ์ธ, qasp-dev arm ์ด ์ง๋ชฉ): ์ด ๊ฒ์ฌ๋ `*claude*` ์ฒ๋ผ
|
|
300
|
+
# entry **๋ฌธ์์ด ์ ์ฒด**์ ๋ถ๋ถ๋งค์นญํ๋ค. ๊ทธ๋์ ์ง์
์ ์ด ๋ชจ๋ธ์ ์ ํ ์ ๋ถ๋ฅด๋๋ฐ๋
|
|
301
|
+
# **๊ฒฝ๋ก์ ๊ทธ ๋จ์ด๊ฐ ์๋ค๋ ์ด์ ๋ง์ผ๋ก** REJECT ๋ฌ๋ค โ ์ค์ ์ฌ๋ก๋ ์คํฌ๋์นํจ๋ ๊ฒฝ๋ก
|
|
302
|
+
# `/private/tmp/claude-501/...` ์๊ณ , ๊ฒฝ๋ก๋ง ๋ฐ๊พธ๋ ๊ฐ์ ์ ์ธ์ด PASS ํ๋ค.
|
|
303
|
+
# ๊ตฌ์กฐ์ ์ผ๋ก ๋ ๋์ ๊ฒฝ์ฐ๊ฐ ๋ ์๋ค: โ ์ง์
์ ์ด `.claude/` ์๋ ์ฌ๋ ํ๋ค์ค๋ **์ ๋ถ**
|
|
304
|
+
# ๋งํ๋ค(FH ์๊ธฐ ์ ์ธ์ด `.claude/capabilities/` ์ ์ฌ๋ ๊ฑธ ์๊ฐํ๋ฉด ๋จ ์๊ธฐ๊ฐ ์๋๋ค)
|
|
305
|
+
# โ `scripts/claude_md_lint.sh` ์ฒ๋ผ ์ด๋ฆ์ ๊ทธ ๋จ์ด๊ฐ ๋ ์์ ๊ธฐ๊ณ ์คํฌ๋ฆฝํธ๋ ๋งํ๋ค.
|
|
306
|
+
#
|
|
307
|
+
# ๊ณผ์ฐจ๋จ์ ยซ์์ ํ ๋ฐฉํฅยป์ด ์๋๋ค โ ์ ๋ณธ์ด ๋ช
์ํ๋ฏ override ๋ฅผ ์ต๊ดํ์์ผ ๊ฐ์ ํ
์
|
|
308
|
+
# ๋ค๋ฅธ ๊ฒ์ดํธ๊น์ง ๋ฌด์ฅํด์ ์ํจ๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ์คํ์ **๋ฌด์**์ด์๋ค: ๊ฑฐ๋ถ ์ฌ์ ๊ฐ
|
|
309
|
+
# "๋ชจ๋ธ CLI ๋ฅผ ๋ถ๋ฅธ๋ค" ๋ก ์ฐํ๋ฏ๋ก, ์ฝ๋ ์ฌ๋์ ์๊ธฐ ์ง์
์ ์ ์์ฌํ์ง ๊ฒฝ๋ก๋ฅผ ์์ฌํ์ง ์๋๋ค.
|
|
310
|
+
#
|
|
311
|
+
# ์ด ๊ฒ์ฌ๊ฐ ์ค์ ๋ก ๋ตํ ์ ์๋ ์ง๋ฌธ์ ยซentry ์ค์ด ๋ชจ๋ธ CLI ๋ฅผ **์ง์ ์ด๋ฆ์ผ๋ก** ๋ถ๋ฅด๋๊ฐยป
|
|
312
|
+
# ๋ฟ์ด๋ค. ๋ํผ ์์์ ๋ถ๋ฅด๋ ๊ฑด ์ ์ธ ์ธต์์ ์๋ ๋ชป ๋ณธ๋ค(M6 ํจ๊ณผ ํ๋ก๋ธ์ ๋ชซ).
|
|
313
|
+
# ๊ทธ๋ฌ๋ ๊ฐ ํ ํฐ์ basename ์ ๋ณด๊ณ , ํ์ฅ์๋ฅผ ๋ผ๊ณ , **์ ํํ ๊ทธ ์ด๋ฆ์ผ ๋๋ง** ๋ง๋๋ค.
|
|
314
|
+
_m3_bad=""
|
|
315
|
+
for _tok in $CAP_entry; do
|
|
316
|
+
_base="${_tok##*/}"; _base="${_base%.sh}"; _base="${_base%.js}"; _base="${_base%.py}"
|
|
317
|
+
case "$_base" in
|
|
318
|
+
claude|codex|gemini|copilot|ollama|llm) _m3_bad="$_base" ;;
|
|
319
|
+
esac
|
|
320
|
+
done
|
|
321
|
+
if [ -n "$_m3_bad" ]; then
|
|
322
|
+
_fail "M3" "judge: mechanical ์ ์ธ์ธ๋ฐ entry ๊ฐ ๋ชจ๋ธ CLI ๋ฅผ ์ง์ ๋ถ๋ฅธ๋ค: $_m3_bad ($CAP_entry)"
|
|
323
|
+
else
|
|
324
|
+
_ok "M3" "judge: mechanical (entry ํ ํฐ์ ๋ชจ๋ธ CLI ์์ โ basename ๊ธฐ์ค)"
|
|
325
|
+
fi ;;
|
|
264
326
|
model) _ok "M3" "judge: model โ ์ ์ธ๋จ(ํฉ๋ฒ). ์กฐํฉ์์ ์ด PASS ๋ NON_CLEARING ์ด๋ค" ;;
|
|
265
327
|
'') _fail "M3" "judge ์ถ ๋ฏธ์ ์ธ โ ๋ชจ๋ธ ๊ฐ์
์ฌ๋ถ๊ฐ ๋ถ๋ช
์ด๋ฉด ์กฐํฉ์ด ๊ณ์ฐ๋ ์ ์๋ค" ;;
|
|
266
328
|
*) _fail "M3" "judge ๊ฐ์ด {mechanical|model} ๋ฐ: '$CAP_judge'" ;;
|
|
@@ -314,15 +376,16 @@ _check_one() {
|
|
|
314
376
|
elif [ "$FILE_FAILED" -eq 1 ] && [ -z "${CRC_FORCE_M4:-}" ]; then
|
|
315
377
|
printf ' โญ M4 โ ์์ ์ถ์ด ์คํจํด ์คํ ์๋ต(SKIPPED, PASS ์๋)\n'
|
|
316
378
|
OBS_WHY="์์ ์ถ ์คํจ๋ก M4 ์๋ต"
|
|
317
|
-
elif ! _validate_arm_args "$CAP_cal_pos_args" || ! _validate_arm_args "$CAP_cal_neg_args"
|
|
379
|
+
elif ! _validate_arm_args "$CAP_cal_pos_args" || ! _validate_arm_args "$CAP_cal_neg_args" \
|
|
380
|
+
|| ! _validate_arm_stdin "${CAP_cal_pos_stdin:-}" || ! _validate_arm_stdin "${CAP_cal_neg_stdin:-}"; then
|
|
318
381
|
printf ' โญ M4 โ args ๊ฒ๋ฌธ ์คํจ๋ก arm ์ ์คํํ์ง ์์๋ค(SKIPPED, PASS ์๋)\n'
|
|
319
382
|
OBS_WHY="args ๊ฒ๋ฌธ ์คํจ"
|
|
320
383
|
else
|
|
321
384
|
local pos_name neg_name pos_rc neg_rc pos_name2 pos_rc2
|
|
322
|
-
_run_arm "$CAP_cal_pos_args"; pos_rc="$ARM_RC"; pos_name="$ARM_NAME"
|
|
385
|
+
_run_arm "$CAP_cal_pos_args" "${CAP_cal_pos_stdin:-}"; pos_rc="$ARM_RC"; pos_name="$ARM_NAME"
|
|
323
386
|
[ "$pos_rc" = "127" ] && _fail "M4" "requires_cwd ๋ก ์ง์
์คํจ โ arm ์ ๋๋ฆด ์ ์๋ค"
|
|
324
|
-
_run_arm "$CAP_cal_pos_args"; pos_name2="$ARM_NAME"; pos_rc2="$ARM_RC" # reps=2 (M3 ๋ถ๋ถ ๋ฐฉ์ด)
|
|
325
|
-
_run_arm "$CAP_cal_neg_args"; neg_rc="$ARM_RC"; neg_name="$ARM_NAME"
|
|
387
|
+
_run_arm "$CAP_cal_pos_args" "${CAP_cal_pos_stdin:-}"; pos_name2="$ARM_NAME"; pos_rc2="$ARM_RC" # reps=2 (M3 ๋ถ๋ถ ๋ฐฉ์ด)
|
|
388
|
+
_run_arm "$CAP_cal_neg_args" "${CAP_cal_neg_stdin:-}"; neg_rc="$ARM_RC"; neg_name="$ARM_NAME"
|
|
326
389
|
# ๊ด์ธก ์์ฅ์ ๋จ๊ธด๋ค โ ํ์ ๊ณผ ๋ฌด๊ดํ๊ฒ, ์ด ์คํ์ด **์ค์ ๋ก ๋ฐ์ exit** ๋ง ์ ๋๋ค.
|
|
327
390
|
OBS_STATE=run; OBS_POS_RC="$pos_rc"; OBS_POS_RC2="$pos_rc2"; OBS_NEG_RC="$neg_rc"
|
|
328
391
|
OBS_POS_NAME="$pos_name"; OBS_NEG_NAME="$neg_name"
|
package/scripts/chamber_run.sh
CHANGED
|
@@ -56,7 +56,15 @@ _witness_record() { # $1 = artifact path
|
|
|
56
56
|
return 0
|
|
57
57
|
fi
|
|
58
58
|
if bash "$_WITNESS" record "$SLUG" "$1" >/dev/null 2>&1; then
|
|
59
|
-
|
|
59
|
+
# ๐ฅ ยซ์ปค๋ฐํด์ผ ๋๋คยป ๋ก๋ง ์ ์ผ๋ฉด **ํ๋ฆฐ ์ฒ๋ฐฉ์ ๊ฐ๋ฅด์น๋ค**(2026-08-17 ๋ฐ #12 ์ค์ธก:
|
|
60
|
+
# ๋ค ํด์๋ฅผ ํ ์ปค๋ฐ์ ๋ฐฐ์นํ๋๋ ๋ธ๋์น์์๋ถํฐ UNORDERED). verify ๋
|
|
61
|
+
# `[ verdict_ts -le pre_max_ts ]` ๋ก ํ์ ํ๋ฏ๋ก **๊ฐ์ ์ปค๋ฐ = ๊ฐ์ ์ด = ์คํจ**๋ค.
|
|
62
|
+
if [ "$(basename "$1")" = "EMISSION_VERDICT.md" ]; then
|
|
63
|
+
echo " โณ ์์ ์ฆ์ธ: EMISSION_VERDICT.md ํด์ ๊ธฐ๋ก๋จ"
|
|
64
|
+
echo " ๐ฅ ์ด ํด์๋ **๊ฒ์ดํธ ํด์๋ค๊ณผ ๋ค๋ฅธ ์ปค๋ฐ**์ผ๋ก ์ฌ๋ ค์ผ ํ๋ค. ๊ฐ์ด ์ปค๋ฐํ๋ฉด UNORDERED ๋ค."
|
|
65
|
+
else
|
|
66
|
+
echo " โณ ์์ ์ฆ์ธ: $(basename "$1") ํด์ ๊ธฐ๋ก๋จ โ **verdict ๋ณด๋ค ๋จผ์ , ๋ณ๋ ์ปค๋ฐ์ผ๋ก** ์ฌ๋ ค๋ผ"
|
|
67
|
+
fi
|
|
60
68
|
else
|
|
61
69
|
echo " โ ๏ธ ์์ ์ฆ์ธ ๊ธฐ๋ก ์คํจ: $(basename "$1") (์ฆ์ธ ์์ โ ๋ฏธ์ธก์ ์ด์ง 0์ด ์๋๋ค)"
|
|
62
70
|
fi
|
|
@@ -125,8 +133,11 @@ if [ ! -f "$WS/BUDGET.md" ]; then
|
|
|
125
133
|
|
|
126
134
|
# Route through goal-quench's budget gate for an expensive run, then record here.
|
|
127
135
|
# Demo-scale runs may self-cap โ but an ESTIMATE line is mandatory (this is the entry cap).
|
|
136
|
+
#
|
|
137
|
+
# ๐ฅ ACTUAL ์ ์ด ํ์ผ์ ์ ์ง ๋ง๋ผ โ step 6 ์ด ๋ณ๋ ACTUAL.md ๋ฅผ ์ด๋ค.
|
|
138
|
+
# ์ด์ : ์ด ํ์ผ์ ํ์ -์ ํด์๊ฐ ์์ ์ฆ์ธ(ship_readiness_gate ยงโก P1)์ด๋ค. ์ฌํ์
|
|
139
|
+
# ์ด ํ์ผ์ ๊ณ ์น๋ฉด ์ฆ์ธ์ด TAMPERED ๋ก ์ฃฝ๋๋ค (2026-08-17 ๋ฐ #11 ์ค์ธก).
|
|
128
140
|
ESTIMATE: <e.g. ~3 persona dispatches, demo-scale, self-capped | or a token budget>
|
|
129
|
-
ACTUAL: <filled at step 6>
|
|
130
141
|
EOF
|
|
131
142
|
echo " โ step 3 BLOCKED: record an ESTIMATE in $WS/BUDGET.md (budget-entry gate G2), then re-run."; exit 1
|
|
132
143
|
fi
|
|
@@ -194,7 +205,12 @@ if [ -f "$_WITNESS" ]; then
|
|
|
194
205
|
echo " โ
์ด EMIT ์ ์์ ์ฆ์ธ์ ๊ฐ์ง๋ค โ identity โก ์น๊ฒฉ ๊ทผ๊ฑฐ๋ก ์ฌ์ฉ ๊ฐ๋ฅ"
|
|
195
206
|
else
|
|
196
207
|
echo " ๐ฅ ์ด EMIT ์๋ ์์ ์ฆ์ธ์ด ์๋ค(rc=${_wrc:-?}) โ identity โก ์น๊ฒฉ ๊ทผ๊ฑฐ๋ก ์ฐ์ง ๋ง๋ผ."
|
|
197
|
-
echo "
|
|
208
|
+
echo " ์ฒ๋ฐฉ โ ์ปค๋ฐ์ **ํฉ์น์ง ๋ง๋ผ**. ์ธ ๊ฒฝ๋ก๊ฐ ๊ฐ๊ฐ ์ฆ์ธ์ ์ฃฝ์ธ๋ค(2026-08-17 ์ค์ธก):"
|
|
209
|
+
echo " โ ํ ์ปค๋ฐ์ ๋ฐฐ์น โ ๊ฐ์ ์ด๋ผ UNORDERED (๋ฐ #12 ์์ ์ฌํ)"
|
|
210
|
+
echo " โก --squash ๋จธ์ง โ ๊ฒ์ดํธ+verdict ๊ฐ main ์์ ํ ์ปค๋ฐ์ผ๋ก ์ ํ๋ค (๋ฐ #11)"
|
|
211
|
+
echo " โข --delete-branch โ ์์๋ฅผ ๋ด์ ์ปค๋ฐ์ด ๋๋ฌ ๋ถ๊ฐ๊ฐ ๋๋ค"
|
|
212
|
+
echo " ์ฌ๋ฐ๋ฅธ ํํ: ๊ฒ์ดํธ ํด์ ์ปค๋ฐ โ (๋ณ๋) verdict ํด์ ์ปค๋ฐ, **๋ PR ๋ก ๋ถ๋ฆฌํด ๊ฐ๊ฐ ๋จธ์ง**."
|
|
213
|
+
echo " ๊ทธ๋ฌ๋ฉด squash ํด๋ main ์ 2์ปค๋ฐ์ด ๋จ์ ์์๊ฐ ๋ณด์กด๋๋ค."
|
|
198
214
|
# โ
์ถ๋ ฅ๋ง ํ๊ณ exit 0 ์ผ๋ก ๋๋ด๋ฉด, stdout ์ ์ ์ฝ๋ ํธ์ถ์์๊ฒ๋ ์ฆ์ธ ์๋ EMIT ๋
|
|
199
215
|
# **์ฑ๊ณต**์ด๋ค(cross-family F8). EMIT ์ ์น๊ฒฉ ์ฃผ์ฅ์ด๋ฏ๋ก ๊ธฐ๊ณ์ ์ผ๋ก ๊ตฌ๋ถ๋์ด์ผ ํ๋ค.
|
|
200
216
|
WITNESS_EMIT_FAIL=1
|
|
@@ -203,8 +219,26 @@ if [ -f "$_WITNESS" ]; then
|
|
|
203
219
|
fi
|
|
204
220
|
|
|
205
221
|
# STEP 6 โ actual cost / carry-forward record.
|
|
206
|
-
|
|
207
|
-
|
|
222
|
+
# ๐ฅ ๋ณ๋ ํ์ผ์ด๋ค. BUDGET.md ๊ฐ ์๋๋ค โ ๊ทธ๋ฆฌ๊ณ ๊ทธ ๋ถ๋ฆฌ๊ฐ ์ด ๊ฒ์ดํธ์ ํต์ฌ์ด๋ค.
|
|
223
|
+
# 2026-08-17 ๋ฐ #11(์ฒซ ํ์ ์์ฃผ)์ด ์ค์ธกํ ๊ฒฐํจ: step 3 ์ด BUDGET.md ์ ํด์๋ฅผ ์์ ์ฆ์ธ์ผ๋ก
|
|
224
|
+
# ๊ธฐ๋กํ๋๋ฐ step 6 ์ด ๊ฐ์ ํ์ผ์ ACTUAL ์ ์๊ตฌํ๋ฉฐ ํ๋ ์ฐจ๋จํ๋ค โ ์์ฃผํ๋ฉด ๋ฐ๋์
|
|
225
|
+
# ์ฆ์ธ ์ํฐํฉํธ๊ฐ ์ฌํ ๋ณ๊ฒฝ๋๊ณ verify ๊ฐ TAMPERED ๋ฅผ ๋ธ๋ค โ **์์ฃผํ ๋ฐ์ ๊ตฌ์กฐ์ ์ผ๋ก
|
|
226
|
+
# โก ์น๊ธ ๊ทผ๊ฑฐ๊ฐ ๋ ์ ์์๋ค.** ๋์ ์ ์ ์ค์๊ฐ ์๋๋ผ ํ ํ์ผ์ ๋ ์ญํ (โ ๋ถ๋ณ ์๊ตฌ =
|
|
227
|
+
# ์ฆ์ธ ยท โก๋ณ๊ฒฝ ์๊ตฌ = ์ฌํ ์บ๋ฆฌ๋ธ๋ ์ด์
)์ด ๊ฒน์น ๊ฒ์ด๊ณ , ๊ฐ๋ณ๋ก๋ ๋ ๋ค ์ณ์์ ์ด๋ ์ชฝ
|
|
228
|
+
# ์ฝ๋๋ฅผ ์ฝ์ด๋ ์ ๋ณด์๋ค. ๊ทธ๋์ ์คํ(P1 ์ด BUDGET ์ ์ฆ์ธ์ผ๋ก ์ง๋ชฉ)์ ์ ๊ฑด๋๋ฆฌ๊ณ
|
|
229
|
+
# **๋ณ๊ฒฝ ์๊ตฌ๋ง** ๋นผ๋ธ๋ค. ACTUAL.md ๋ ์ ์์ ํ์ ํ ์ฐ๋ฌผ์ด๋ฏ๋ก **์ฆ์ธ์ ๊ธฐ๋กํ์ง ์๋๋ค.**
|
|
230
|
+
if [ ! -f "$WS/ACTUAL.md" ]; then
|
|
231
|
+
cat > "$WS/ACTUAL.md" <<EOF
|
|
232
|
+
# ACTUAL โ $SLUG (chamber run, ํ์ ํ ๊ธฐ๋ก)
|
|
233
|
+
#
|
|
234
|
+
# ์ด ํ์ผ์ **์์ ์ฆ์ธ ๋์์ด ์๋๋ค** โ ํ์ ํ์ ์ฐ์ด๋ ๊ฒ์ด ์ ์์ด๋ฏ๋ก ํด์๋ฅผ ๊ฑธ์ง ์๋๋ค.
|
|
235
|
+
# ESTIMATE ๋ BUDGET.md ์ ์๊ณ ๊ทธ ํ์ผ์ ํ์ ์ ์ ์ผ์ด ์๋ค. ๋์กฐ๋ ์ฌ๋์ด ํ๋ค.
|
|
236
|
+
ACTUAL: <number/summary โ dispatch ์ ยท ํ ํฐ ยท ์์ฐ ๋๋น ํธ์ฐจ>
|
|
237
|
+
EOF
|
|
238
|
+
fi
|
|
239
|
+
if grep -qE '^ACTUAL:[[:space:]]*<' "$WS/ACTUAL.md" || ! grep -qE '^ACTUAL:[[:space:]]*\S' "$WS/ACTUAL.md"; then
|
|
240
|
+
echo " โ step 6 BLOCKED: record ACTUAL cost in $WS/ACTUAL.md (actual-vs-estimate calibration)."
|
|
241
|
+
echo " ๐ฅ BUDGET.md ๊ฐ ์๋๋ค โ ๊ทธ ํ์ผ์ ํ์ ์ ์ฆ์ธ์ด๋ผ ์ฌํ ๋ณ๊ฒฝํ๋ฉด ์ฆ์ธ์ด ์ฃฝ๋๋ค."
|
|
208
242
|
echo " Expected โ a LINE PREFIX, not a heading:"
|
|
209
243
|
echo " ACTUAL: <number/summary> โ this form is checked"
|
|
210
244
|
echo " ## ACTUAL โ a heading does NOT satisfy it"
|
|
@@ -140,6 +140,31 @@ HDR
|
|
|
140
140
|
echo "โ ์์ฅ ํค๋ ์ฐ๊ธฐ ์คํจ: $LEDGER" >&2; return 10
|
|
141
141
|
fi
|
|
142
142
|
fi
|
|
143
|
+
# โโ ๋ฉฑ๋ฑ: ๊ฐ์ (run, artifact, sha) ์ผ์คํญ์ด ์ด๋ฏธ ์์ผ๋ฉด ๋ค์ ์ ์ ๋๋ค โโโโโโโโโโ
|
|
144
|
+
# ๊ธฐ์ 2026-08-17 ๋ฐ #11(์ฒซ ํ์ ์์ฃผ): ์ด ํจ์๊ฐ **๋ฌด์กฐ๊ฑด append** ๋ผ์ ๋ฌ๋๋ฅผ advance
|
|
145
|
+
# ํ ๋๋ง๋ค step 2~5 ๊ฐ ์ฌ์คํ๋๋ฉฐ ๊ฐ์ ํด์๊ฐ ๋ค์ ์์๋ค โ 4์คํ
๋ฐ์ **์ํธ๋ฆฌ 11๊ฐ**.
|
|
146
|
+
# ์ฆ์ธ ํ์ ์์ฒด๋ ์ ํ๋ฆฌ์ง๋ง(๊ฐ์ ํด์๋ ๊ฐ์ ๊ฒฐ๋ก ) ๊ณต๊ฐ tracked ํ์ผ์ด ๋ถํ๊ณ ,
|
|
147
|
+
# verify ์ถ๋ ฅ์ด ๊ฐ์ ์ค์ ์ฌ๋ฌ ๋ฒ ๋ฑ์ด **์ฝ๋ ์ฌ๋์ด ใ๋ช ๊ฑด์ด ๋ฌธ์ ์ธ๊ฐใ๋ฅผ ์ค๋
**ํ๋ค.
|
|
148
|
+
# ๐ฅ ๋ด์ฉ์ด ๋ฐ๋ ๊ฒฝ์ฐ๋ **์ฌ์ ํ ์ ์ํธ๋ฆฌ๋ก ๋จ๋๋ค** โ ๊ทธ๊ฒ TAMPERED ๋ฅผ ์ฑ๋ฆฝ์ํค๋
|
|
149
|
+
# ์ฆ๊ฑฐ์ด๋ฏ๋ก ์ฌ๊ธฐ์ ์ ์ผ๋ฉด ์ ๋๋ค. ์ ๋ ๊ฒ์ ยซ์์ ํ ๋์ผํ ์ฌ๊ธฐ๋กยป๋ฟ์ด๋ค.
|
|
150
|
+
# ๐ฅ ์คํ์
์ฃผ์ โ `- run: ` ๋ **7์**๋ผ ๊ฐ์ 8๋ถํฐ๋ค. ์ดํ์ด 9๋ก ์ผ๊ณ (cross-family
|
|
151
|
+
# gpt-5.5 ์ ๋ฐ, A๊ธ) ๊ทธ๋ฌ๋ฉด ์ฌ๋ฌ๊ทธ ์ฒซ ๊ธ์๊ฐ ์๋ ค **์ด๋ค ์ ์ ์ํธ๋ฆฌ์๋ ๋งค์นญ๋์ง ์๋๋ค**
|
|
152
|
+
# โ ๊ฐ๋๊ฐ ์กฐ์ฉํ ๋ฌด๋ ฅํ๋๊ณ append ๊ฐ ๊ณ์๋๋ค. ์ฌํ: `printf -- '- run: g2\n' |
|
|
153
|
+
# awk '{print substr($0,9)}'` โ `2`. **๋ ์ธ์ด ์ด๊ฑธ ๋ชป ์ก์๋ค**(์๋ L14 ์ ์ค๋ก ๋ซ์).
|
|
154
|
+
# ์ธ์ ์ฑ๋ ๊ฐ์ ํ๋ค: run โ artifact โ sha256 ์ด **์ฐ์**์ผ ๋๋ง ์ธ์ . ์ ๊ทธ๋ฌ๋ฉด ๊นจ์ง
|
|
155
|
+
# YAML ์์ stale run/art ๊ฐ ๋ฌด๊ดํ sha ์ ์ง์ง์ด **ํ์ํ append ๋ฅผ ๋๋ฌ๋ฒ๋ฆฐ๋ค**(๊ฐ์ ๋ฆฌ๋ทฐ B๊ธ).
|
|
156
|
+
if awk -v r="$slug" -v a="$base" -v s="$h" '
|
|
157
|
+
/^- run: / { run=substr($0,8); art=""; prev="run"; next }
|
|
158
|
+
/^ artifact: / { if (prev=="run") { art=substr($0,13); prev="art" }
|
|
159
|
+
else { art=""; prev="" } ; next }
|
|
160
|
+
/^ sha256: / { if (prev=="art" && run==r && art==a && substr($0,11)==s) { found=1; exit }
|
|
161
|
+
prev=""; next }
|
|
162
|
+
{ prev="" }
|
|
163
|
+
END { exit(found?0:1) }
|
|
164
|
+
' "$LEDGER" 2>/dev/null; then
|
|
165
|
+
echo "witnessed(already): $slug/$base โ ๋์ผ ํด์๊ฐ ์ด๋ฏธ ์์ฅ์ ์๋ค(์ฌ๊ธฐ๋ก ์ ํจ)"
|
|
166
|
+
return 0
|
|
167
|
+
fi
|
|
143
168
|
if ! printf -- '- run: %s\n artifact: %s\n sha256: %s\n recorded: %s\n' \
|
|
144
169
|
"$slug" "$base" "$h" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$LEDGER" 2>/dev/null; then
|
|
145
170
|
echo "โ ์์ฅ append ์คํจ: $LEDGER" >&2; return 10
|
package/scripts/fh-gate.sh
CHANGED
|
@@ -34,7 +34,22 @@ set -euo pipefail
|
|
|
34
34
|
FH_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
35
35
|
# Single source of truth: read version from the package.json shipped alongside this script.
|
|
36
36
|
# No jq dependency (users may not have it); fall back to "unknown" if unreadable.
|
|
37
|
-
VERSION
|
|
37
|
+
# VERSION โ the `|| true` is load-bearing under `set -euo pipefail`, and it is the ONLY part that
|
|
38
|
+
# is. Without it, a package.json that is missing OR unreadable makes this pipeline non-zero, and
|
|
39
|
+
# because the whole thing is an ASSIGNMENT, `set -e` aborts the script right here โ so the
|
|
40
|
+
# `:-unknown` fallback on the next line never runs and the gate exits 1 before doing any work.
|
|
41
|
+
# MEASURED 2026-08-16: a sibling harness carries this file verbatim but ships no package.json (it
|
|
42
|
+
# is not an npm package), so its gate was dead on every invocation and its 30-lane regression
|
|
43
|
+
# suite reported 30 failures that were all this one line. One lane appeared to PASS only because
|
|
44
|
+
# its expected exit code happened to be 1 โ the textbook signature of a dead control. Nobody had
|
|
45
|
+
# looked, because that repo had no CI. Latent HERE too, not merely a sibling's problem: a copy of
|
|
46
|
+
# this script run from a directory with no package.json died the same way.
|
|
47
|
+
# A `[ -f "$FH_ROOT/package.json" ]` guard was written first and then REMOVED, because a 4-way
|
|
48
|
+
# mutant matrix refuted it: with the file merely absent either mechanism alone suffices, but with
|
|
49
|
+
# the file present-and-unreadable the guard passes and only `|| true` survives. A guard that
|
|
50
|
+
# covers nothing `|| true` does not already cover is decoration, and the first version of this
|
|
51
|
+
# comment claimed both were load-bearing โ that claim was false.
|
|
52
|
+
VERSION="$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$FH_ROOT/package.json" 2>/dev/null | head -1 || true)"
|
|
38
53
|
VERSION="${VERSION:-unknown}"
|
|
39
54
|
CALLER_CWD="$(pwd -P)"
|
|
40
55
|
_TMPDIR="${TMPDIR:-/tmp}"
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""ko_tech_writer_calibrate.py โ `ko-tech-writer` Step 2 / Step 4-b ์ค์บ์ **ํ๋ณ๋ ฅ** known-pair.
|
|
4
|
+
|
|
5
|
+
์ ํ์ด์ฌ์ธ๊ฐ (์์ง ์ ํ์ ์ทจํฅ์ด ์๋๋ผ ์ค์ธก ๊ฒฐ๊ณผ๋ค)
|
|
6
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
7
|
+
`SKILL.md` Step 4 ๊ฐ ํ์ฉ ์์ง์ ๋ช
์ํ๋ค: *"์ ๋์ฝ๋ ์ธ์ ์์ง(ripgrep ยท GNU grep UTF-8
|
|
8
|
+
๋ก์ผ์ผ ยท Python `re` โ **`grep -P` ๋ ์์ธ**)"*. ์ดํ์ `rg` ๋ก ๊ณ ์ ํ๊ณ **CI ์์ ์ฃฝ์๋ค** โ
|
|
9
|
+
ubuntu-latest ์ ripgrep ์ด ์๋ค(2026-08-17 ์ค์ธก, `HARNESS ERROR ... exited 10`).
|
|
10
|
+
๊ฐ์ ์คํ์์ ์ด์์ฑ ๋ฆฐํธ๋ ๊ฑธ๋ ธ๋ค: ์
ธ ํ์ผ ์์ `[๊ฐ-ํฃ]` ๋ฌธ์ ๋ฒ์๋
|
|
11
|
+
**GNU grep C ๋ก์ผ์ผ์์ exit 2 ๋ก ์ฃฝ๊ณ ๊ทธ ๊ฒฐ๊ณผ๊ฐ ยซ๋ฌด๋งค์นยป ๋ก ์ฝํ๋ค** โ ์ฆ fail-open.
|
|
12
|
+
|
|
13
|
+
Python `re` ๋ โ ์ธ ํ์ฉ ์์ง ์ค **์ด๋์๋ ์๋ ์ ์ผํ ๊ฒ**์ด๊ณ โ ์ ๋์ฝ๋๋ฅผ ๊ธฐ๋ณธ์ผ๋ก
|
|
14
|
+
์ธ์ํ๋ฉฐ โ ํจํด์ด ์
ธ ๋ฐ์ผ๋ก ๋๊ฐ ๋ก์ผ์ผ ๋ฌธ์ ๋ฅผ ๊ตฌ์กฐ์ ์ผ๋ก ์์ค๋ค. **๊ฒฉํ๊ฐ ์๋๋ผ
|
|
15
|
+
์ ๋ณธ์ด ์ด๋ฏธ ํ์ฉํ ๋ฑ๊ฐ ์์ง์ผ๋ก์ ์ด๋**์ด๋ค.
|
|
16
|
+
|
|
17
|
+
๋ฌด์์ ์ฃผ๊ณ ๋ฌด์์ ์ ์ฃผ๋๊ฐ โ ์์ง ๋ง๋ผ
|
|
18
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
19
|
+
์ค๋ค ๊ฐ ์ค์บ์ด **์์ฑ์ ์ก๊ณ ์์ฑ์ ์ ์ก๋๊ฐ**(=ํ๋ณ๋ ฅ). ์ฌํ ์ปค๋งจ๋์ ์คํ ์ถ๋ ฅ.
|
|
20
|
+
์ ์ค๋ค ๊ทธ ์ค์บ์ด **์์ ๋ฌธ์์์ ์์ฌ 0๊ฑด์ธ๊ฐ**. ๊ทธ๊ฑด ๋ฌธ์๋ง๋ค ๋ฐ๋ก ์ฌ๋ ๊ฒ์ด๋ค.
|
|
21
|
+
โ ์ด๊ฑธ ํต๊ณผํ๋ค๊ณ ยซStep 2 ์์ฌ 0ยป ์ ์ฃผ์ฅํ๋ฉด
|
|
22
|
+
`harness_terminal_correlation_and_recommendations.md` ์ ๊ฐ๋ฑ ์ฌ์ ๊ฐ ๊ทธ๋๋ก ์ฌ๋ฐํ๋ค.
|
|
23
|
+
|
|
24
|
+
exit: 0 ์ ๋ ์ธ ํ๋ณ ยท 1 ํ๋ณ ์คํจ ยท 10 harness error(ํฝ์ค์ฒ ๋ถ์ฌ)
|
|
25
|
+
"""
|
|
26
|
+
import os
|
|
27
|
+
import re
|
|
28
|
+
import sys
|
|
29
|
+
|
|
30
|
+
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
31
|
+
FIX = os.path.join(HERE, "..", "plugins", "fh-commons", "skills", "ko-tech-writer", "fixtures")
|
|
32
|
+
POS = os.path.join(FIX, "known_positive.md")
|
|
33
|
+
NEG = os.path.join(FIX, "known_negative.md")
|
|
34
|
+
|
|
35
|
+
# (๋ผ๋ฒจ, ํจํด) โ Step 2 ์ ยซ๊ธฐ๊ณ ๊ฒ์ถ ๊ฐ๋ฅยป 5ํด๋์ค + Step 4-b ์ 2ํจํด.
|
|
36
|
+
#
|
|
37
|
+
# ๐ฅ ์ ๋ณธ์ ๋ถ๋ฅ๊ฐ ๊ณผ์ฅ์ด๋ผ๋ ๊ฒ์ด ์ฒซ ์บ๋ฆฌ๋ธ๋ ์ด์
์์ ๋๋ฌ๋ฌ๋ค. SKILL.md ๋
|
|
38
|
+
# "์ ๋ค์ฏ ์ค์ ๊ธฐ๊ณ ๊ฒ์ถ ๊ฐ๋ฅ" ์ด๋ผ ์ ์๋๋ฐ, **์ค์ ๋ก grep ์ ์ฃ๊ณ ์๋ ๊ฒ์
|
|
39
|
+
# C1(์คํ)ยทC5(์์ ์ง์ญ) ๋๋ฟ**์ด๊ณ C2ยทC3ยทC4 ์ ยซ๊ฒ์ถ ํํธยป ์นธ์ ์ฐ๋ฌธ ์์ ์ด๋ค.
|
|
40
|
+
# ํนํ C4 ๋ ยซ์์ ์ด ์๋ ๋ง์นจยป ์ด๋ผ๋ ์์ ๋ฟ ํจํด์ด ์๋ค.
|
|
41
|
+
LANES = [
|
|
42
|
+
("C1 ์คํ ์ด์ด๋ถ์", r"(๋ค|๊ฒ|์) โ "),
|
|
43
|
+
("C2 ์ฉ์ด-๋จธ๋ฆฌ", r"^\s*[-*]\s+\*\*[^*]+\*\* โ "),
|
|
44
|
+
("C3 ์ฝ๋ก ๋์ดํฌ", r"[๊ฐ-ํฃ]์: "),
|
|
45
|
+
# C4: SKILL.md ์ ํจํด์ด ์๋ค. ์๋๋ **ํ๋ณด ๊ฒ์ถ**์ด์ง ํ์ ์ด ์๋๋ค
|
|
46
|
+
# (SKILL.md ์์ ์ ๊ท์จ: "grep์ ํ๋ณด๋ฅผ ํ์ํ ๋ฟ, ๋จ๊ธธ์ง ํ์ ์ ๋ฌธ๋งฅ์ผ๋ก").
|
|
47
|
+
# ๋ซํ ๋ช
์ฌ ์ดํ๋ผ **recall ์ด ๋ฎ๋ค** โ ๋ฎ์ ์ชฝ์ด ๊ณผ์ฐจ๋จ๋ณด๋ค ์์ ํ ๋ฐฉํฅ์ด๊ณ ,
|
|
48
|
+
# ๋ํ๋ ค๋ฉด ์ดํ๋ฅผ ๋๋ฆฌ๋ ๊ฒ ์๋๋ผ ํํ์ ๋ถ์์ด ํ์ํ๋ค.
|
|
49
|
+
("C4 ์กฐ๊ฐ๋ฌธ(ํ๋ณดยท๋ซํ ์ดํ)", r"(์ธต|๊ฒ|์ |์ถ|๊ฑด|๋ฟ|๋ฐ|์
)\.\s*(<!--|$)"),
|
|
50
|
+
("C5 ์์ ์ง์ญ", r"(์|๋ฅผ) (๊ฐ|๊ฐ์ง)"),
|
|
51
|
+
("C6 ์ ์นญ ์ดํ", r"์ ๋ถ|๋ชจ๋|ํ๋๋|์ ํ|์ผ์ |์์ธ ์์ด"),
|
|
52
|
+
("C6b ๋ถ์ ํ ์ ์นญ", r"(์|๋ชป) ?(ํ|๋ง๋ค|๋์ค|์กํ)|์ง ์์(๋ค|์ต๋๋ค)"),
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
# ์ ๋ ์กํ๋ฉด ์ ๋๋ ํ ํฐ โ ใ๋ ์ก๋๋คใ๋ฅผ ๋ด๋ ์ฃฝ์ ๊ณ๊ธฐ ๋ฐฐ์ ์ฉ
|
|
56
|
+
NEVER = r"ZZZ_absent_token_ZZZ"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def count(path, pattern):
|
|
60
|
+
"""ํจํด์ ๋งค์นญ๋๋ **์ค ์**. ํ์ผ ๋ถ์ฌ๋ ์์ธ๋ก ์ฌ๋ฆฐ๋ค(๋ฌด์ 0 ๊ธ์ง)."""
|
|
61
|
+
rx = re.compile(pattern, re.MULTILINE)
|
|
62
|
+
n = 0
|
|
63
|
+
with open(path, encoding="utf-8") as fh:
|
|
64
|
+
for line in fh:
|
|
65
|
+
if rx.search(line.rstrip("\n")):
|
|
66
|
+
n += 1
|
|
67
|
+
return n
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def main():
|
|
71
|
+
for p in (POS, NEG):
|
|
72
|
+
if not os.path.isfile(p):
|
|
73
|
+
sys.stderr.write("harness error: fixture missing %s\n" % p)
|
|
74
|
+
return 10
|
|
75
|
+
|
|
76
|
+
print("engine: python%d.%d re (unicode-aware)"
|
|
77
|
+
% (sys.version_info[0], sys.version_info[1]))
|
|
78
|
+
print("known-positive: %s" % os.path.relpath(POS, os.path.join(HERE, "..")))
|
|
79
|
+
print("known-negative: %s" % os.path.relpath(NEG, os.path.join(HERE, "..")))
|
|
80
|
+
print("")
|
|
81
|
+
|
|
82
|
+
npass = nfail = 0
|
|
83
|
+
for label, pat in LANES:
|
|
84
|
+
p = count(POS, pat)
|
|
85
|
+
n = count(NEG, pat)
|
|
86
|
+
if p >= 1 and n == 0:
|
|
87
|
+
print("OK %s -- positive %d / negative 0 (discriminates)" % (label, p))
|
|
88
|
+
npass += 1
|
|
89
|
+
elif p < 1:
|
|
90
|
+
print("FAIL %s -- MISSES the positive (positive %d). A blind instrument." % (label, p))
|
|
91
|
+
nfail += 1
|
|
92
|
+
else:
|
|
93
|
+
print("FAIL %s -- HITS the negative (negative %d). Over-blocks; no discrimination."
|
|
94
|
+
% (label, n))
|
|
95
|
+
nfail += 1
|
|
96
|
+
|
|
97
|
+
# META ์ปจํธ๋กค 1 โ ์๋ ํ ํฐ์ด ์์ชฝ ๋ค 0์ธ๊ฐ (๊ณ๊ธฐ๊ฐ ยซ๋ ์ก๋๋คยป ๋ฅผ ๋ด์ง ์๋๋ค)
|
|
98
|
+
if count(POS, NEVER) == 0 and count(NEG, NEVER) == 0:
|
|
99
|
+
print("OK META control -- an absent token matches nothing in either fixture")
|
|
100
|
+
npass += 1
|
|
101
|
+
else:
|
|
102
|
+
print("FAIL META control -- an absent token matched. Do not trust this suite.")
|
|
103
|
+
nfail += 1
|
|
104
|
+
|
|
105
|
+
# META ์ปจํธ๋กค 2 โ ๋ ํฝ์ค์ฒ๊ฐ ์ค์ ๋ก ๋ค๋ฅธ ํ์ผ์ธ๊ฐ
|
|
106
|
+
with open(POS, encoding="utf-8") as a, open(NEG, encoding="utf-8") as b:
|
|
107
|
+
if a.read() != b.read():
|
|
108
|
+
print("OK META control -- positive/negative fixtures differ")
|
|
109
|
+
npass += 1
|
|
110
|
+
else:
|
|
111
|
+
print("FAIL META control -- the two fixtures are identical; results are meaningless")
|
|
112
|
+
nfail += 1
|
|
113
|
+
|
|
114
|
+
print("")
|
|
115
|
+
if nfail == 0:
|
|
116
|
+
print("CALIBRATED (%d lanes) -- Step 2 five classes + Step 4-b two patterns discriminate."
|
|
117
|
+
% npass)
|
|
118
|
+
print(" NOT proven: 'zero residue' in any real document. That is measured per document.")
|
|
119
|
+
print(" Citing this suite as evidence of 'zero residue' reproduces the very downgrade")
|
|
120
|
+
print(" recorded in harness_terminal_correlation_and_recommendations.md.")
|
|
121
|
+
return 0
|
|
122
|
+
print("NOT CALIBRATED (%d/%d failed)" % (nfail, npass + nfail))
|
|
123
|
+
return 1
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
if __name__ == "__main__":
|
|
127
|
+
sys.exit(main())
|
|
@@ -51,6 +51,16 @@ ACCEPTED_ABSENT=(
|
|
|
51
51
|
# read as claims about THEIR file. The shipped docs name it as the place verdicts live in the
|
|
52
52
|
# harness repo, which is a pointer for contributors, not a promise of a shipped artifact.
|
|
53
53
|
".claude/regression/ablation_verdicts.md"
|
|
54
|
+
# ์ฑ๋ฒ **์์ ์ฆ์ธ ์์ฅ**(ship_readiness_gate ยงโก P1). ๋ฐ๋ก ์ ablation_verdicts ์ **๊ฐ์
|
|
55
|
+
# ๋
ผ๊ฑฐ**๋ค: ์ด๊ฑด THIS repo ์ ์ฑ๋ฒ ๋ฐ์ด ์ธ์ ๋ฌด์์ ๊ณ ์ ํ๋์ง์ ๋ํ ๊ธฐ๋ก์ด๊ณ , ์๋น์์
|
|
56
|
+
# ์ฑ๋ฒ ๋ฐ์ ๊ทธ๋ค ๊ฒ์ด๋ค โ ์ถํ ๋ฌธ์์์ ์ธ์ฉ๋ ์ฑ๋ก ๋ธ๋ ค๊ฐ๋ฉด ์๋น์๊ฐ **์๊ธฐ ๋ฐ์ ๋ํ
|
|
57
|
+
# ์ฃผ์ฅ**์ผ๋ก ์ฝ๋๋ค. ๊ฒ๋ค๊ฐ ์ด ์์ฅ์ ์ฐ๋ฆฌ ๋ฐ slugยท์๊ฐ์ ๋ด์ ๊ณต๊ฐ ํ๋ฉด์ด๋ผ ์๋น์์๊ฒ
|
|
58
|
+
# ๋ณด๋ด๋ ๊ฒ์ ์ ๋ณด ์ ์ถ ๋ฐฉํฅ์ผ๋ก๋ ํ๋ ธ๋ค.
|
|
59
|
+
# ๐ฅ **๋ถ์ฌ๊ฐ ์๋น์ ์ชฝ ๊ธฐ๋ฅ์ ๊นจ์ง ์๋๋ค** โ `chamber_witness.sh do_record` ๋ ์์ฅ์ด
|
|
60
|
+
# ์์ผ๋ฉด ํค๋๋ฅผ ๋ง๋ค์ด ์์ฑํ๋ค(๊ฐ์ ํ์ผ์ `[ ! -f "$LEDGER" ]` ๋ถ๊ธฐ). ์ฆ ์คํฌ๋ฆฝํธ๋
|
|
61
|
+
# ์ถํ๋๊ณ ์์ฅ์ ์๋น์ ๋จธ์ ์์ ์ฒ์ ์ธ ๋ ์๊ธด๋ค. ใ์์ผ๋ฉด ์ฃฝ๋๋คใ๊ฐ ์๋๋ผ
|
|
62
|
+
# ใ์๋ ๊ฒ ์ ์ ์ด๊ธฐ ์ํใ๋ค.
|
|
63
|
+
"knowledge/shared/learnings/chamber_ordering_witness.yaml"
|
|
54
64
|
"scripts/sync-to-be.sh"
|
|
55
65
|
"scripts/sync_guard_check.sh"
|
|
56
66
|
# Return path (companion store โ hub) and its anchor. Same reason as the forward path above: the
|