@chrono-meta/fh-gate 1.4.99 โ 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/capabilities/adapters/gstack-content-safety.cap +110 -0
- package/.claude/capabilities/adapters/mate-agent-boundary.cap +110 -0
- package/.claude/capabilities/adapters/qasp-new-code-anchor.cap +116 -0
- package/.claude/capabilities/degrade-direction-scan.cap +24 -0
- package/.claude/capabilities/public-surface-scan.cap +24 -0
- package/.claude-plugin/marketplace.json +3 -3
- package/AGENTS.md +9 -3
- package/CHEATSHEET.md +17 -1
- package/CLAUDE.md +2 -2
- package/README.ja.md +55 -20
- package/README.ko.md +86 -20
- package/README.md +57 -20
- package/README.zh.md +49 -19
- package/knowledge/shared/harness-core/fh_three_layer_canon.md +96 -5
- package/knowledge/shared/harness-core/field_verdict_crossfamily_gate.md +36 -0
- package/knowledge/shared/harness-core/harness_incubator_doctrine.md +1 -1
- package/knowledge/shared/harness-core/harness_terminal_correlation_and_recommendations.md +214 -0
- package/knowledge/shared/harness-core/harness_verification_core_extended.md +1 -1
- package/knowledge/shared/harness-core/ship_readiness_gate.md +29 -10
- package/knowledge/shared/learnings/subagent_invocations_log.yaml +73 -0
- package/package.json +13 -3
- package/plugins/fh-commons/.claude-plugin/plugin.json +1 -1
- package/plugins/fh-meta/.claude-plugin/plugin.json +2 -2
- package/plugins/fh-meta/CHANGELOG.md +45 -0
- package/scripts/adapters/gstack_content_safety.sh +186 -0
- package/scripts/adapters/mate_agent_boundary.sh +120 -0
- package/scripts/adapters/peer_resolve.sh +99 -0
- package/scripts/adapters/qasp_new_code_anchor.sh +159 -0
- package/scripts/branch_claim.sh +14 -0
- package/scripts/capability_effect_probe.sh +701 -0
- package/scripts/capability_registry_check.sh +313 -16
- package/scripts/cluster_capability_scan.sh +629 -0
- package/scripts/fh_session_load.sh +70 -0
- package/scripts/portability_lint.sh +257 -0
- package/scripts/publish_freshness_check.sh +204 -0
- package/scripts/relay_channel.sh +70 -7
- package/scripts/selfcheck.sh +166 -1
- package/scripts/test_adapter_lanes.sh +296 -0
- package/scripts/test_capability_entrypoint_shipping.sh +83 -6
- package/scripts/test_relay_channel_lanes.sh +76 -0
- package/templates/.git-hooks/pre-commit +14 -2
|
@@ -41,7 +41,14 @@ command -v node >/dev/null 2>&1 || {
|
|
|
41
41
|
# Discover entry points by convention. A DISCOVERY of zero is an instrument failure, not a clean
|
|
42
42
|
# result: this check exists precisely because the surface it guards is invisible to reference
|
|
43
43
|
# walking, so "found nothing to check" must never render as "everything ships".
|
|
44
|
-
|
|
44
|
+
# ๐ฅ 2026-08-16: ๋ฐ๊ฒฌ ๊ท์ฝ์ด **ํ ๋ฒ๋ฟ**์ด์๋ค(`scripts/*_capability.sh`, maxdepth 1). ๊ฐ์ ๋
|
|
45
|
+
# ๋์
๋ **์ด๋ํฐ ์ง์
์ **(`scripts/adapters/*.sh` โ ๋จ์ ํ๋ค์ค ๋ฅ๋ ฅ์ FH ์์์ ๋ถ๋ฅด๋ ๊ธฐ๋ณธ
|
|
46
|
+
# ๊ฒฝ๋ก)์ ์ด๋ฆ๋ ์์น๋ ๊ทธ ๊ท์ฝ ๋ฐ์ด๋ผ **์ด ๊ฒ์ฌ์ ๊ตฌ์กฐ์ ์ผ๋ก ์ ๋ณด์๋ค.** ์ฆ ์ด๋ํฐ ์คํฌ๋ฆฝํธ๊ฐ
|
|
47
|
+
# `files[]` ์์ ๋น ์ ธ๋ ์ด ๊ฒ์ฌ๋ ์ด๋ก์ด์๋ค โ ๊ฒ์ฌ๊ธฐ๊ฐ ์งํค๋ ค๋ ๋ฐ๋ก ๊ทธ ๊ฒฐํจ์ด ๊ฒ์ฌ๊ธฐ ์์ ์
|
|
48
|
+
# ์ฌ๊ฐ์์ ์ฌํ๋ ์ ์์๋ค. ๋ ๊ท์ฝ์ **ํฉ์งํฉ**์ผ๋ก ๋ณธ๋ค(๋นผ์ง ๋ง๊ณ ๋ํ๋ค).
|
|
49
|
+
ENTRIES=$( { find scripts -maxdepth 1 -type f -name '*_capability.sh' 2>/dev/null
|
|
50
|
+
find scripts/adapters -maxdepth 1 -type f -name '*.sh' 2>/dev/null
|
|
51
|
+
} | LC_ALL=C sort -u )
|
|
45
52
|
n=$(printf '%s\n' "$ENTRIES" | grep -c . || true)
|
|
46
53
|
n=$(( ${n:-0} + 0 ))
|
|
47
54
|
if [ "$n" -eq 0 ]; then
|
|
@@ -53,6 +60,16 @@ fi
|
|
|
53
60
|
FILES_JSON=$(node -e 'process.stdout.write(JSON.stringify(require("./package.json").files||[]))' 2>/dev/null) || {
|
|
54
61
|
echo " INSTRUMENT ERROR: could not read package.json files[]"; exit 1; }
|
|
55
62
|
|
|
63
|
+
# โ
`mktemp` โ ์ดํ์ `${TMPDIR:-/tmp}/cap_entry_$$.txt` ์๋ค. TMPDIR ์๋ ํ๊ฒฝ(๋ฆฌ๋
์ค CIยท
|
|
64
|
+
# ์ปจํ
์ด๋๊ฐ ํํ๋ค)์์ ๊ณต์ฉ `/tmp` + PID ๊ธฐ๋ฐ **์์ธก ๊ฐ๋ฅํ ์ด๋ฆ**์ด๋ผ, ๋ฏธ๋ฆฌ ์ฌ์ด๋ ์ฌ๋งํฌ๋ฅผ
|
|
65
|
+
# `>` ๋ฆฌ๋ค์ด๋ ํธ๊ฐ ๋ฐ๋ผ๊ฐ ๋์ ํ์ผ์ ๋ฎ์ด์ด๋ค(CWE-377, ๋ณด์ ํจ์ค [B]). ์ด ํ์ผ์ selfcheck ์
|
|
66
|
+
# ๋ฐฐ์ ๋ผ **์๋น์ ๋จธ์ ์์ `npm test` ๋ก ๋๋ค**.
|
|
67
|
+
# โ ๏ธ `mktemp -t <prefix>` ๋ **BSD ์ ์ฉ**์ด๋ค โ GNU ๋ ํ
ํ๋ฆฟ์ X ๋ฅผ ์๊ตฌํ๊ณ
|
|
68
|
+
# `mktemp: too few X's in template` ๋ก ์ฃฝ๋๋ค(2026-08-16 CI ์ค์ธก: ๋ก์ปฌ macOS ์ด๋ก ยท ubuntu ์ ์).
|
|
69
|
+
# ์ด ๋ ํฌ๊ฐ ์ด๋ฏธ ๊ธฐ๋กํ `stat -f` BSD-first ์ ๊ฐ์ ์ผ๊ตด์ด๋ค. ์์ชฝ์์ ๋๋ ํํ๋
|
|
70
|
+
# **๋ช
์ ํ
ํ๋ฆฟ + X ๋ค์**๋ฟ์ด๋ค. (๊ณ๊ธฐ๊ฐ fail-closed ๋ก ๋ง์ ์ค ๋์ ์กฐ์ฉํ ์ ์ง๋๊ฐ๋ค.)
|
|
71
|
+
_CAP_TMP=$(mktemp "${TMPDIR:-/tmp}/cap_entry.XXXXXXXX") || { echo " INSTRUMENT ERROR: mktemp ์คํจ"; exit 1; }
|
|
72
|
+
trap 'rm -f "$_CAP_TMP"' EXIT INT TERM
|
|
56
73
|
printf '%s\n' "$ENTRIES" | while IFS= read -r e; do
|
|
57
74
|
[ -n "$e" ] || continue
|
|
58
75
|
if node -e 'const f=JSON.parse(process.argv[1]);process.exit(f.includes(process.argv[2])?0:1)' "$FILES_JSON" "$e"; then
|
|
@@ -60,14 +77,14 @@ printf '%s\n' "$ENTRIES" | while IFS= read -r e; do
|
|
|
60
77
|
else
|
|
61
78
|
echo " MISSING $e"
|
|
62
79
|
fi
|
|
63
|
-
done > "$
|
|
80
|
+
done > "$_CAP_TMP"
|
|
64
81
|
|
|
65
|
-
missing=$(grep -c '^ MISSING ' "$
|
|
82
|
+
missing=$(grep -c '^ MISSING ' "$_CAP_TMP" || true)
|
|
66
83
|
missing=$(( ${missing:-0} + 0 ))
|
|
67
|
-
shipped=$(grep -c '^ ok ' "$
|
|
84
|
+
shipped=$(grep -c '^ ok ' "$_CAP_TMP" || true)
|
|
68
85
|
shipped=$(( ${shipped:-0} + 0 ))
|
|
69
|
-
cat "$
|
|
70
|
-
rm -f "$
|
|
86
|
+
cat "$_CAP_TMP"
|
|
87
|
+
rm -f "$_CAP_TMP"
|
|
71
88
|
|
|
72
89
|
if [ "$missing" -eq 0 ]; then
|
|
73
90
|
ok "all $shipped capability entry point(s) are in package.json files[]"
|
|
@@ -118,6 +135,66 @@ else
|
|
|
118
135
|
bad "$dangling declared capability entry point(s) missing from disk โ npm would ship a broken files[] and the disk-side check alone stays green"
|
|
119
136
|
fi
|
|
120
137
|
|
|
138
|
+
# SIBLING DEPENDENCIES (added 2026-08-16 โ occurrence #4 of the class this file's header names).
|
|
139
|
+
# The two directions above both key on the ENTRY-POINT convention (`*_capability.sh`). That is
|
|
140
|
+
# structurally blind to the failure that actually happened this time: a shipped script called a
|
|
141
|
+
# NON-entry-point sibling that did not ship. `capability_registry_check.sh` shipped, its new M6 axis
|
|
142
|
+
# ran `${0%/*}/capability_effect_probe.sh`, and that probe was absent from files[] โ so on a consumer
|
|
143
|
+
# install M6 would hit its fail-closed branch and reject every registration, blaming a "missing probe"
|
|
144
|
+
# that exists in the repo.
|
|
145
|
+
#
|
|
146
|
+
# WHY `package_coverage_check.sh` IS BLIND TO IT โ and why the fix belongs here, not there: that
|
|
147
|
+
# checker's extraction regex requires a reference to START with a shipped top-level directory
|
|
148
|
+
# (`scripts|templates|bin|docs|knowledge|plugins|.claude`). A script naming its own sibling writes
|
|
149
|
+
# `${0%/*}/name.sh` or `$(dirname "$0")/name.sh` โ the path is BUILT AT RUNTIME and no literal
|
|
150
|
+
# `scripts/` appears. The reference-follower cannot see a path that does not textually exist.
|
|
151
|
+
#
|
|
152
|
+
# Scope kept narrow on purpose: only SELF-DIRECTORY forms. `$REPO_ROOT/scripts/x.sh` already contains
|
|
153
|
+
# the literal `scripts/x.sh` and is caught upstream; widening past that would duplicate that checker.
|
|
154
|
+
SIB_PAT='(\$\{0%/\*\}|\$\(dirname [^)]*\)|\$\{BASH_SOURCE[^}]*%/\*\})/[A-Za-z0-9_.-]+\.(sh|py|js)'
|
|
155
|
+
SHIPPED_SH=$(node -e '
|
|
156
|
+
const f=JSON.parse(process.argv[1]);
|
|
157
|
+
process.stdout.write(f.filter(p=>/^scripts\/.*\.sh$/.test(p)).join("\n"));
|
|
158
|
+
' "$FILES_JSON")
|
|
159
|
+
|
|
160
|
+
sib_refs=0; sib_missing=0
|
|
161
|
+
if [ -n "$SHIPPED_SH" ]; then
|
|
162
|
+
while IFS= read -r s; do
|
|
163
|
+
[ -n "$s" ] && [ -f "$s" ] || continue
|
|
164
|
+
# `grep -o` yields the whole matched expression; the sibling NAME is its last path segment.
|
|
165
|
+
# COMMENT LINES ARE STRIPPED FIRST, and that is not cosmetic: the finding's text asserts the
|
|
166
|
+
# callee is "called at runtime". A file whose PROSE names a sibling (this file's own header does)
|
|
167
|
+
# would be reported under a claim that is false about it โ the right defect attributed to the
|
|
168
|
+
# wrong caller. Caught during this lane's own known-pair calibration, where the positive arm
|
|
169
|
+
# named two callers and only one of them actually calls anything.
|
|
170
|
+
for ref in $(sed 's/^[[:space:]]*#.*//' "$s" | grep -oE "$SIB_PAT" 2>/dev/null | sed 's|.*/||' | sort -u); do
|
|
171
|
+
sib_refs=$((sib_refs+1))
|
|
172
|
+
# Only assert on siblings that EXIST in the repo. A reference to a name that is absent from
|
|
173
|
+
# disk too is a different defect (a dead call), and it belongs to the dangling check above โ
|
|
174
|
+
# claiming it here would report one defect as two.
|
|
175
|
+
[ -f "scripts/$ref" ] || continue
|
|
176
|
+
if node -e 'const f=JSON.parse(process.argv[1]);process.exit(f.includes(process.argv[2])?0:1)' \
|
|
177
|
+
"$FILES_JSON" "scripts/$ref"; then :; else
|
|
178
|
+
echo " SIBLING-MISSING scripts/$ref (called by $s at runtime, absent from files[])"
|
|
179
|
+
sib_missing=$((sib_missing+1))
|
|
180
|
+
fi
|
|
181
|
+
done
|
|
182
|
+
done <<EOF
|
|
183
|
+
$SHIPPED_SH
|
|
184
|
+
EOF
|
|
185
|
+
fi
|
|
186
|
+
|
|
187
|
+
# Discovery-zero is an instrument failure here for the same reason as above: this repo is KNOWN to
|
|
188
|
+
# contain at least one self-directory sibling call (that is why this block exists). Zero means the
|
|
189
|
+
# pattern stopped matching โ a silent scanner, not a clean repo.
|
|
190
|
+
if [ "$sib_refs" -eq 0 ]; then
|
|
191
|
+
bad "INSTRUMENT DEAD โ zero self-directory sibling references found across $(printf '%s\n' "$SHIPPED_SH" | grep -c .) shipped scripts; the pattern is no longer matching anything"
|
|
192
|
+
elif [ "$sib_missing" -eq 0 ]; then
|
|
193
|
+
ok "all $sib_refs runtime sibling dependenc(ies) of shipped scripts are themselves in files[]"
|
|
194
|
+
else
|
|
195
|
+
bad "$sib_missing runtime sibling dependenc(ies) absent from files[] โ the consumer gets a caller whose callee is missing"
|
|
196
|
+
fi
|
|
197
|
+
|
|
121
198
|
# CONTROL โ the check must be able to say NO. A checker that only ever prints ok is indistinguishable
|
|
122
199
|
# from a checker that is not looking; assert the negative arm on a name that cannot be in files[].
|
|
123
200
|
if node -e 'const f=JSON.parse(process.argv[1]);process.exit(f.includes(process.argv[2])?0:1)' \
|
|
@@ -578,6 +578,82 @@ A_N10=$(cap a_n10.cap "id: demo:a" "entry: bash $T/n_key_pass.sh" "verdict_chann
|
|
|
578
578
|
rc=0; bash "$RELAY" run --cap "$A_N10" --cap "$B" --task t > "$T/on10" 2>&1 || rc=$?
|
|
579
579
|
_t "N10 both ์ฑ๋์ **์ผ์น** ์ ์ ๊ฒฝ๋ก๊ฐ ์ค์ ๋ก ๋๋ค(๊ณผ์ฐจ๋จ ์๋)" 0 "$rc"
|
|
580
580
|
|
|
581
|
+
# โโ N11โN15 ๋
ธ๋๋ณ ํธ์ถ ์ธ์ ์ฑ๋ (`--cap-args`) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
582
|
+
# ๐ฅ ์ด ์ฑ๋์ด ์๋ ๋์ **ํธ์ถ ์์ ์ธ์๋ฅผ ์๊ตฌํ๋ ๋ฅ๋ ฅ์ relay ๋ฅผ ํต๊ณผํ ์ ์์๋ค**
|
|
583
|
+
# (์ค์ธก 2026-08-16, pmh-dev:merge-noop-check โ ํญ์ ARGSโHARNESS_ERRORโBLOCKED).
|
|
584
|
+
# fail-closed ๋ผ ๋ฐฉํฅ์ ์ณ์์ง๋ง ์ ํธ๊ฐ 0 ์ด์๊ณ , ๊ทธ๊ฑด ยซํธ์ถ ๊ฐ๋ฅยป ์ ๊ตฌ์กฐ์ ์ผ๋ก ๋ชป ๋ง๋ ๋ค.
|
|
585
|
+
# ๋ ์ธ์ ๋ค ๊ฐ์ง๋ฅผ ๋ฐ๋ก ๋จ์ธํ๋ค โ ๋๋ฌ ยท ๊ฒฐ๋ฐ ๋์ ยท fail-closed ยท **๋น์ฃผ์
์ปจํธ๋กค**.
|
|
586
|
+
mk n_echo_args.sh '#!/usr/bin/env bash
|
|
587
|
+
# ๋ฐ์ ์์น ์ธ์๋ฅผ ๊ทธ๋๋ก ์ฐ๊ณ , ์ฒซ ์ธ์๊ฐ "GO" ์ผ ๋๋ง ํต๊ณผํ๋ค.
|
|
588
|
+
echo "ARGS=[$*]"
|
|
589
|
+
[ "${1:-}" = "GO" ] && exit 0
|
|
590
|
+
exit 1'
|
|
591
|
+
ARGSCAP() { cap "$1" "id: demo:$2" "entry: bash $T/n_echo_args.sh" "verdict_channel: exit" \
|
|
592
|
+
"verdict_enum: 0=PASS 1=FAIL" "approval: auto" "reversibility: reversible" "residency: public" \
|
|
593
|
+
"degrade: fail-closed" "tier_floor: none" "writes: read-only" "judge: mechanical" \
|
|
594
|
+
"verdict_binding: FAIL"; }
|
|
595
|
+
|
|
596
|
+
# N11 ์ธ์๊ฐ ์ค์ ๋ก ์ง์
์ ์ **๋๋ฌํ๋ค** โ ์์ผ๋ฉด FAIL ์ด์ด์ผ ํ ๋
ธ๋๊ฐ ํต๊ณผํ๋ค
|
|
597
|
+
A_N11=$(ARGSCAP a_n11.cap a)
|
|
598
|
+
rc=0; bash "$RELAY" run --cap "$A_N11" --cap-args "GO" --cap "$B" --task t \
|
|
599
|
+
--record "$T/rec11" > "$T/on11" 2>&1 || rc=$?
|
|
600
|
+
_t "N11 --cap-args ๊ฐ ์ง์
์ ์ ์ค์ ๋ก ๋๋ฌํ๋ค" 0 "$rc"
|
|
601
|
+
# โ
๋จ์ธ ๋์์ relay ์ stdout ์ด ์๋๋ผ **๋
ธ๋ ์์ ์ ์ถ๋ ฅ**์ด๋ค. relay ๋ ๋
ธ๋ stdout ์
|
|
602
|
+
# ๊ธฐ๋ก ๋๋ ํฐ๋ฆฌ๋ก ๋ณด๋ด๋ฏ๋ก, relay ์ถ๋ ฅ์ ๋๊ณ grep ํ๋ฉด ๋ ยซ์์ยป ์ด ๋์ ๊ฑฐ์ง ์ ์์ด ๋๋ค
|
|
603
|
+
# (์ดํ์ด ๊ทธ๋ ๊ฒ ํ๋ ธ๋ค โ ๊ณ๊ธฐ๊ฐ ์๋๋ผ ๋จ์ธ ์์น๊ฐ ํ๋ฆฐ ๊ฒฝ์ฐ).
|
|
604
|
+
_tout "N11b ๋ฐ์ ์ธ์๋ฅผ ์ง์
์ ์ด ๊ทธ๋๋ก ๋ณธ๋ค" "ARGS=\[GO\]" "$T/rec11/node1.out"
|
|
605
|
+
|
|
606
|
+
# N12 ๐ฅ **๋น์ฃผ์
์ปจํธ๋กค** โ ๊ฐ์ capfile ์ ์ธ์๋ง ๋นผ๋ฉด FAIL ์ด์ด์ผ ํ๋ค.
|
|
607
|
+
# ์ด๊ฒ ์์ผ๋ฉด N11 ์ ยซ์ธ์์ ๋ฌด๊ดํ๊ฒ ๋ ํต๊ณผํ๋ ๊ณ๊ธฐยป ์ ๊ตฌ๋ถ๋์ง ์๋๋ค.
|
|
608
|
+
rc=0; bash "$RELAY" run --cap "$A_N11" --cap "$B" --task t \
|
|
609
|
+
--record "$T/rec12" > "$T/on12" 2>&1 || rc=$?
|
|
610
|
+
_t "N12 ์ธ์๋ฅผ ์ ์ฃผ๋ฉด ๊ฐ์ ๋
ธ๋๊ฐ ๋งํ๋ค(์ปจํธ๋กค โ ์ฑ๋์ด ์ค์ฌํ๋ค๋ ์ฆ๊ฑฐ)" 2 "$rc"
|
|
611
|
+
_tout "N12b ์ธ์ ์์ด ๋ถ๋ฅด๋ฉด ์ง์
์ ์ด ๋น ์ธ์๋ฅผ ๋ณธ๋ค" "ARGS=\[\]" "$T/rec12/node1.out"
|
|
612
|
+
|
|
613
|
+
# N13 ๊ฒฐ๋ฐ ๋์์ **๊ฐ์ฅ ์ต๊ทผ --cap** ์ด๋ค โ ์์น ์ธ๋ฑ์ค๋ก ์ง์ง์ผ๋ฉด ์กฐ์ฉํ ๋ค๋ฅธ ๋
ธ๋์ ๋ถ๋๋ค
|
|
614
|
+
A_N13=$(ARGSCAP a_n13.cap a)
|
|
615
|
+
rc=0; bash "$RELAY" run --cap "$B" --cap "$A_N13" --cap-args "GO" --task t > "$T/on13" 2>&1 || rc=$?
|
|
616
|
+
_t "N13 ์ธ์๊ฐ ยซ๊ฐ์ฅ ์ต๊ทผ --capยป ์ ๊ฒฐ๋ฐ๋๋ค(์ฒซ ๋
ธ๋๋ก ์์ง ์๋๋ค)" 0 "$rc"
|
|
617
|
+
|
|
618
|
+
# N14 `--cap` ์์ด ๋จผ์ ์ค๋ฉด fail-closed โ ์ด๋ ๋ถ์ผ์ง ๋ชจ๋ฅด๋ ์ธ์๋ฅผ ์กฐ์ฉํ ๋ฒ๋ฆฌ์ง ์๋๋ค
|
|
619
|
+
rc=0; bash "$RELAY" run --cap-args "GO" --cap "$A_N11" --cap "$B" --task t > "$T/on14" 2>&1 || rc=$?
|
|
620
|
+
_t "N14 --cap ์์ --cap-args ๋ fail-closed(๋ฌด์ ํ๊ธฐ ์๋)" 10 "$rc"
|
|
621
|
+
|
|
622
|
+
# N15 ์
ธ ๋ฉํ๋ฌธ์ ๊ฑฐ๋ถ โ ์ง์
์ ์ด ๋จ์ด๋ถํด๋ก ์คํ๋๋ฏ๋ก ํ๋ก๋ธ์ ๊ฐ์ ๊ท์น์ ์ด๋ค
|
|
623
|
+
rc=0; bash "$RELAY" run --cap "$A_N11" --cap-args 'GO; rm -rf /tmp/x' --cap "$B" --task t > "$T/on15" 2>&1 || rc=$?
|
|
624
|
+
_t "N15 --cap-args ์ ์
ธ ๋ฉํ๋ฌธ์๋ ๊ฑฐ๋ถ๋๋ค" 10 "$rc"
|
|
625
|
+
|
|
626
|
+
# โโ N16โN18 cross-family 3๊ฑด(2026-08-16) โ ์ ๋ถ ์ ์ฌํ ํ ์ต์ปค โโโโโโโโโโโโโโโโ
|
|
627
|
+
# ์
๋ค ใ์กฐ์ฉํ ์๋ชป๋๋ใ ํํ๋ค: ๊ฐ์ด ์ฌ๋ผ์ง๊ฑฐ๋, ๊ฒฐ๋ฐ์ด ์ฃฝ๊ฑฐ๋, ์ธ์ ๊ฒฝ๊ณ๊ฐ ๋ฐ๋๋ค.
|
|
628
|
+
A_N16=$(ARGSCAP a_n16.cap a)
|
|
629
|
+
rc=0; bash "$RELAY" run --cap "$A_N16" --cap-args "FIRST" --cap-args "GO" --cap "$B" --task t > "$T/on16" 2>&1 || rc=$?
|
|
630
|
+
_t "N16 ๊ฐ์ --cap ์ --cap-args ๋ ๋ฒ์ fail-closed(์ ๊ฐ ๋ฌด์ ํ๊ธฐ ๊ธ์ง)" 10 "$rc"
|
|
631
|
+
|
|
632
|
+
# N17 ๊ฒฐ๋ฐ ํ๋๊ทธ์์ ์ถฉ๋ โ `--cap-args --` ๋ก `--upstream-verdict` ๋ฅผ ์์น์ธ์๋ก ๋ฐ์ด๋ผ ์ ์์๋ค
|
|
633
|
+
A_N17=$(cap a_n17.cap "id: demo:a" "entry: bash $T/n_echo_args.sh" "upstream_argv: yes" \
|
|
634
|
+
"verdict_channel: exit" "verdict_enum: 0=PASS 1=FAIL" \
|
|
635
|
+
"approval: auto" "reversibility: reversible" "residency: public" "degrade: fail-closed" \
|
|
636
|
+
"tier_floor: none" "writes: read-only" "judge: mechanical" "verdict_binding: FAIL")
|
|
637
|
+
rc=0; bash "$RELAY" run --cap "$A_N17" --cap-args "GO" --cap "$B" --task t > "$T/on17" 2>&1 || rc=$?
|
|
638
|
+
_t "N17 upstream_argv ๋
ธ๋์ --cap-args ๋ฅผ ๋ถ์ด๋ฉด fail-closed(๊ฒฐ๋ฐ์ด ์กฐ์ฉํ ์ฃฝ์ง ์๋๋ค)" 10 "$rc"
|
|
639
|
+
# N17b ์ปจํธ๋กค โ upstream_argv ๋ฅผ **์ ์ธํ์ง ์์** ๋
ธ๋๋ ์ข
์ ๋๋ก ํต๊ณผํด์ผ ํ๋ค(๊ณผ์ฐจ๋จ ๋ฐฉ์ง)
|
|
640
|
+
rc=0; bash "$RELAY" run --cap "$A_N16" --cap-args "GO" --cap "$B" --task t > "$T/on17b" 2>&1 || rc=$?
|
|
641
|
+
_t "N17b ์ปจํธ๋กค โ upstream_argv ๋ฏธ์ ์ธ ๋
ธ๋๋ --cap-args ๋ฅผ ์ ์ ์์ฉ" 0 "$rc"
|
|
642
|
+
|
|
643
|
+
# N18 ๊ฐํ โ ์ดํ ๊ฐ๋๋ฅผ ํต๊ณผํด **ํ ์ธ์๊ฐ ๋ ์ธ์๋ก ์ชผ๊ฐ์ก๋ค**($'GO\nSECOND' โ ARGC=2)
|
|
644
|
+
rc=0; bash "$RELAY" run --cap "$A_N16" --cap-args "$(printf 'GO\nSECOND')" --cap "$B" --task t > "$T/on18" 2>&1 || rc=$?
|
|
645
|
+
_t "N18 --cap-args ์ ๊ฐํ์ ๊ฑฐ๋ถ๋๋ค(์ธ์ ๊ฒฝ๊ณ ๋ฌด์ ๋ณํ ์ฐจ๋จ)" 10 "$rc"
|
|
646
|
+
# N18b ์ปจํธ๋กค โ **์ ์ ๋ค์ค ์ธ์**(๊ณต๋ฐฑ ๊ตฌ๋ถ)๋ ๊ณ์ ํต๊ณผํด์ผ ํ๋ค. ์ ๊ทธ๋ฌ๋ฉด N18 ์
|
|
647
|
+
# ใ์ธ์๋ฅผ ์ฌ๋ฌ ๊ฐ ๋ชป ์ฃผ๋ ๊ณ๊ธฐใ์ ๊ตฌ๋ถ๋์ง ์๋๋ค.
|
|
648
|
+
A_N18=$(cap a_n18.cap "id: demo:a" "entry: bash $T/n_echo_args.sh" "verdict_channel: exit" \
|
|
649
|
+
"verdict_enum: 0=PASS 1=FAIL" "approval: auto" "reversibility: reversible" "residency: public" \
|
|
650
|
+
"degrade: fail-closed" "tier_floor: none" "writes: read-only" "judge: mechanical" \
|
|
651
|
+
"verdict_binding: FAIL")
|
|
652
|
+
rc=0; bash "$RELAY" run --cap "$A_N18" --cap-args "GO SECOND THIRD" --cap "$B" --task t \
|
|
653
|
+
--record "$T/rec18" > "$T/on18b" 2>&1 || rc=$?
|
|
654
|
+
_t "N18b ์ปจํธ๋กค โ ๊ณต๋ฐฑ ๊ตฌ๋ถ ๋ค์ค ์ธ์๋ ์ ์ ํต๊ณผ" 0 "$rc"
|
|
655
|
+
_tout "N18b2 ์ธ ์ธ์๊ฐ ๊ทธ๋๋ก ๋๋ฌํ๋ค" "ARGS=\[GO SECOND THIRD\]" "$T/rec18/node1.out"
|
|
656
|
+
|
|
581
657
|
printf '\nโโ relay_channel lanes: %d PASS / %d FAIL โโ\n' "$pass" "$fail"
|
|
582
658
|
[ "$fail" -eq 0 ] || exit 1
|
|
583
659
|
exit 0
|
|
@@ -284,8 +284,20 @@ else
|
|
|
284
284
|
psa_load "$REPO_ROOT/.claude/rules/.public-surface-patterns.defaults" \
|
|
285
285
|
"${PSA_PATTERNS:-$REPO_ROOT/.claude/rules/.public-surface-patterns}"
|
|
286
286
|
if [ "$PSA_OVERRIDE_PRESENT" -eq 0 ]; then
|
|
287
|
-
|
|
288
|
-
|
|
287
|
+
# 2026-08-16 weekly-audit residual โ operator decision: LOUDER WARNING, not fail-closed.
|
|
288
|
+
# A hard block here would fail every fresh clone's / CI's / worktree's first commit (the
|
|
289
|
+
# override is gitignored by construction), training PUBLIC_SURFACE_OK into a reflex โ the same
|
|
290
|
+
# override-habituation this repo has measured and warned against repeatedly. So the degrade
|
|
291
|
+
# direction stays PASS; what changed is that the old two-line notice was easy to scroll past in
|
|
292
|
+
# a green hook run. This is now impossible to miss, still non-blocking.
|
|
293
|
+
echo ""
|
|
294
|
+
echo " ๐ง๐ง๐ง CONFIDENTIALITY COVERAGE REDUCED โ READ BEFORE TRUSTING THIS PASS ๐ง๐ง๐ง"
|
|
295
|
+
echo " โ ๏ธ operator pattern override ABSENT โ only committed defaults are active."
|
|
296
|
+
echo " Company/employer-name and real-username token classes are UNSCANNED this run."
|
|
297
|
+
echo " A clean PASS below reflects the defaults-only pattern set, not the full one."
|
|
298
|
+
echo " Fix: populate .claude/rules/.public-surface-patterns (gitignored, one severity<TAB>regex per line)."
|
|
299
|
+
echo " ๐ง๐ง๐ง โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ ๐ง๐ง๐ง"
|
|
300
|
+
echo ""
|
|
289
301
|
fi
|
|
290
302
|
if [ "$PSA_DEFAULTS_OK" -eq 0 ] || [ "$PSA_BAD_ROWS" -gt 0 ] \
|
|
291
303
|
|| [ -z "$(printf '%s' "$PSA_STREAM" | grep -vE '^[[:space:]]*(#|$)' || true)" ]; then
|