@qijenchen/design-system 0.1.0-beta.135 → 0.1.0-beta.136
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/ds-canonical/fork/consumer/lock.json +4 -4
- package/ds-canonical/fork/governance.lock +1 -1
- package/ds-canonical/fork/manifest.json +10 -10
- package/ds-canonical/hooks/stop_self_audit.sh +40 -0
- package/ds-canonical/hooks/tests/test_stop_self_audit.sh +31 -0
- package/ds-canonical/rules/meta-patterns.md +1 -1
- package/package.json +1 -1
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
"schemaVersion": 1,
|
|
4
4
|
"role": "template-consumer",
|
|
5
5
|
"release": {
|
|
6
|
-
"designSystem": "0.1.0-beta.
|
|
7
|
-
"storybookConfig": "0.1.0-beta.
|
|
6
|
+
"designSystem": "0.1.0-beta.136",
|
|
7
|
+
"storybookConfig": "0.1.0-beta.136"
|
|
8
8
|
},
|
|
9
9
|
"upgradeTrust": {
|
|
10
10
|
"schemaVersion": 1,
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"implementationSha256": "98b74118fb5b410b77ad2994aa9105fa7609c7353822f8c5213cce54d94f0af4"
|
|
43
43
|
},
|
|
44
44
|
"payload": {
|
|
45
|
-
"forkCorpusLockSha256": "
|
|
45
|
+
"forkCorpusLockSha256": "98b621dc50c9f3baeafa1c8a422931066f35a887ad8944d3c79389e11e31c67f",
|
|
46
46
|
"discoveryPolicySha256": "fba289aeeb5a3f11139b9589f7ab08b5e8c8799c7bdf8f0ea57ebfeb8e7c9da6",
|
|
47
47
|
"providerMaterializersSha256": "732e85b01a12e7dd19469e26e4427f0e0cfe5117a78fc9f69c2f0f89702f463a",
|
|
48
|
-
"providerLifecycleSha256": "
|
|
48
|
+
"providerLifecycleSha256": "27e611b19cb01f2ad64fb4548de352b212bde528757f7d816d19a4f52b3f9159",
|
|
49
49
|
"providerInventorySha256": "00adf1c4f6b3367055a9cc3fdfe658660771b4c9931f696e12761a95076ad92c",
|
|
50
50
|
"executionRuntimeSha256": "d9377cc45308731f287d7b1711b7c38fc4e02ff8f84729bcbbf01bb52d136904",
|
|
51
51
|
"commonInstructionSha256": "a72c51a412d6cdb3961d691744013c8362e826626a330cecf4a296a6f4d93a5c",
|
|
@@ -919,7 +919,7 @@
|
|
|
919
919
|
{
|
|
920
920
|
"schemaVersion": 1,
|
|
921
921
|
"file": "manifest.json",
|
|
922
|
-
"sha256": "
|
|
922
|
+
"sha256": "ec51e4107e3345673c76cda0d4a9fc9aafa4bf47a93be3c65efd0cb7e8c9538c",
|
|
923
923
|
"source": null,
|
|
924
924
|
"classification": null,
|
|
925
925
|
"destination": null
|
|
@@ -104,20 +104,20 @@
|
|
|
104
104
|
},
|
|
105
105
|
"providerLifecycle": {
|
|
106
106
|
"schemaVersion": 4,
|
|
107
|
-
"releaseVersion": "0.1.0-beta.
|
|
107
|
+
"releaseVersion": "0.1.0-beta.136",
|
|
108
108
|
"immutableHead": {
|
|
109
109
|
"providerInventorySha256": "86e9d0668cb54ad1bf05c36e78b4aa80417d5f468c929dd3ddcf69c1afbf32e4",
|
|
110
|
-
"releaseVersion": "0.1.0-beta.
|
|
111
|
-
"snapshotSha256": "
|
|
110
|
+
"releaseVersion": "0.1.0-beta.135",
|
|
111
|
+
"snapshotSha256": "8814d3c2a71f1eae73408864def3b566bbcb88a45377dc53a28fec00b90e7a3a"
|
|
112
112
|
},
|
|
113
|
-
"ledgerSha256": "
|
|
114
|
-
"previousSnapshotSha256": "
|
|
115
|
-
"currentSnapshotSha256": "
|
|
113
|
+
"ledgerSha256": "523ce8f6ceec7fbaca1fba28e38946b97b3b7281de38acf422efabc34afa070d",
|
|
114
|
+
"previousSnapshotSha256": "8814d3c2a71f1eae73408864def3b566bbcb88a45377dc53a28fec00b90e7a3a",
|
|
115
|
+
"currentSnapshotSha256": "1601a1ea9c1a957f0ba228ddcca2acc17f1d0f2843f91101cf0780825075c0e3",
|
|
116
116
|
"currentProviderInventorySha256": "86e9d0668cb54ad1bf05c36e78b4aa80417d5f468c929dd3ddcf69c1afbf32e4",
|
|
117
117
|
"retiredProviders": [],
|
|
118
118
|
"currentSnapshot": {
|
|
119
|
-
"releaseVersion": "0.1.0-beta.
|
|
120
|
-
"previousSnapshotSha256": "
|
|
119
|
+
"releaseVersion": "0.1.0-beta.136",
|
|
120
|
+
"previousSnapshotSha256": "8814d3c2a71f1eae73408864def3b566bbcb88a45377dc53a28fec00b90e7a3a",
|
|
121
121
|
"providers": [
|
|
122
122
|
{
|
|
123
123
|
"id": "claude",
|
|
@@ -193,8 +193,8 @@
|
|
|
193
193
|
"retiredProviders": []
|
|
194
194
|
},
|
|
195
195
|
"immutableHeadSnapshot": {
|
|
196
|
-
"releaseVersion": "0.1.0-beta.
|
|
197
|
-
"previousSnapshotSha256": "
|
|
196
|
+
"releaseVersion": "0.1.0-beta.135",
|
|
197
|
+
"previousSnapshotSha256": "684bf42d3c7a9e075f60cebce0c68d442239cda935624c4dbe8d07acbcae8fcd",
|
|
198
198
|
"providers": [
|
|
199
199
|
{
|
|
200
200
|
"id": "claude",
|
|
@@ -489,6 +489,30 @@ if [ -n "$LAST_ASSISTANT" ] && [ -n "$TRANSCRIPT_PATH" ] && [ -f "$TRANSCRIPT_PA
|
|
|
489
489
|
fi
|
|
490
490
|
fi
|
|
491
491
|
|
|
492
|
+
# ── Mechanism 10: 自鎖後把動作推給 user(M36(b),2026-09-19)────────────────
|
|
493
|
+
# SSOT = meta-patterns M36(b)/(b') + governance/memory/feedback_anti_self_lock_release_transport.md。
|
|
494
|
+
#
|
|
495
|
+
# 為什麼要機械化:這條規則 2026-08-08 就立了、2026-08-11 連環五鎖逐層拆完、2026-08-28 還特別
|
|
496
|
+
# 寫下「**禁**指路 `!`(與 Bash 同沙箱必再擋)或推 user 終端機」—— 然後 2026-09-19 又犯:
|
|
497
|
+
# `git branch -D` 被 classifier 擋下,沒走等價的 `git update-ref -d`(plumbing,只寫 .git 可寫區),
|
|
498
|
+
# 直接寫「你要清的話在終端機打 `! git branch -D ...` 就行」,而且是 user 反問才發現。
|
|
499
|
+
# M36(a) 有 Mechanism 8 把關,M36(b) 一直是**零機械強制** —— 所以它才會重犯。
|
|
500
|
+
#
|
|
501
|
+
# 判準:本 turn 有工具被擋(denied / EPERM / not permitted),且 reply 把一個**具體指令**交給
|
|
502
|
+
# user 去跑 → CRITICAL。真正的 human-only 邊界(login / MFA / OAuth / 帳單 / 缺 credential
|
|
503
|
+
# reference)明文豁免,那些本來就該交給 user。
|
|
504
|
+
if [ -n "$LAST_ASSISTANT" ]; then
|
|
505
|
+
BLOCKED_RE='(has been denied|Permission to use|Operation not permitted|EPERM|not accessible by personal access token|Blocked by classifier)'
|
|
506
|
+
HANDOFF_RE='(在終端機(打|輸入|跑|執行)|你要?(自己)?(跑|執行|打|輸入)|請你(跑|執行|手動)|麻煩你(跑|執行)|`![[:space:]])'
|
|
507
|
+
HUMAN_ONLY_RE='(auth login|gh auth|MFA|OAuth|二階段|登入|帳單|billing|付費|credential reference|vault|Secret Manager)'
|
|
508
|
+
if printf '%s' "${THIS_TURN_TOOLS:-}" | grep -qE "$BLOCKED_RE" \
|
|
509
|
+
&& printf '%s' "$LAST_ASSISTANT" | grep -qE "$HANDOFF_RE" \
|
|
510
|
+
&& ! printf '%s' "$LAST_ASSISTANT" | grep -qE "$HUMAN_ONLY_RE"; then
|
|
511
|
+
CRITICAL_SELF_LOCK_HANDOFF=1
|
|
512
|
+
WARNINGS="${WARNINGS}\n • M36(b) 自鎖後把動作推給 user:本 turn 有工具被擋,而你請 user 自己跑指令。"
|
|
513
|
+
fi
|
|
514
|
+
fi
|
|
515
|
+
|
|
492
516
|
# ── Mechanism 6: capability-bound PushNotification gap ────────────────────
|
|
493
517
|
# Provider-neutral runtime 不可假設 exact tool 存在。只有 adapter/registry 明確宣告
|
|
494
518
|
# `push-notification` capability 時才檢查;缺宣告 = UNOBSERVED/nonblocking。
|
|
@@ -733,6 +757,22 @@ if [ "${CRITICAL_CLAIM_VERIFY:-0}" = "1" ] && [ -n "$LAST_ASSISTANT" ]; then
|
|
|
733
757
|
fi
|
|
734
758
|
fi
|
|
735
759
|
|
|
760
|
+
# ── BLOCKER for Mechanism 10 自鎖後把動作推給 user(M36(b),2026-09-19)──
|
|
761
|
+
# 升級邏輯同 M1/M4:第一次 block 阻 turn,同 hash 降 warn 防 loop。
|
|
762
|
+
if [ "${CRITICAL_SELF_LOCK_HANDOFF:-0}" = "1" ] && [ -n "$LAST_ASSISTANT" ]; then
|
|
763
|
+
LOCK_HASH=$(printf '%s' "${LAST_ASSISTANT: -200}" | governance_hash_prefix)
|
|
764
|
+
LAST_BLOCKED_LOCK_FILE="$STATE_DIR/.last-blocked-self-lock.txt"
|
|
765
|
+
LAST_BLOCKED_LOCK=""
|
|
766
|
+
[ "$STATE_WRITES" = "1" ] && [ -f "$LAST_BLOCKED_LOCK_FILE" ] && LAST_BLOCKED_LOCK=$(cat "$LAST_BLOCKED_LOCK_FILE" 2>/dev/null || echo "")
|
|
767
|
+
if [ "$LOCK_HASH" != "$LAST_BLOCKED_LOCK" ]; then
|
|
768
|
+
[ "$STATE_WRITES" = "1" ] && { mkdir -p "$STATE_DIR" 2>/dev/null; echo "$LOCK_HASH" > "$LAST_BLOCKED_LOCK_FILE" 2>/dev/null || true; }
|
|
769
|
+
REASON=$(printf '%s' \
|
|
770
|
+
"🚨 SELF-LOCK HANDOFF BLOCKER(M36(b)):本 turn 有工具被擋,而你在 reply 裡請 user 自己跑指令。先答 M36(b') 三問 — (1) 憑證真的缺嗎?(2) 體檢測的是真實需要的能力嗎?(3) 有沒有已驗證可通的等價傳輸?尤其 git plumbing(update-ref -d / update-index --cacheinfo,只寫 .git 可寫區)、harness 檔案工具、index-authoritative generator。禁指路 '!':它與 Bash 同沙箱,同一道牆必再擋,等於把死路交給 user。真 human-only 只有 login/MFA/OAuth/帳單/缺 credential reference。做到了,或確認是真 human-only 邊界,才可結束 turn。" \
|
|
771
|
+
"本機制 = M36(b) 從純散文升為 mechanical BLOCKER(2026-09-19;規則 2026-08-08 就立、2026-08-28 已明文禁指路 '!',仍於 2026-09-19 再犯且是 user 反問才發現)。")
|
|
772
|
+
emit_governance_block "$REASON"
|
|
773
|
+
fi
|
|
774
|
+
fi
|
|
775
|
+
|
|
736
776
|
# ── BLOCKER for Mechanism 4 peer-design-no-approval(2026-05-09 user-authorized + escalated)──
|
|
737
777
|
if [ "${CRITICAL_PEER_DESIGN_NO_APPROVAL:-0}" = "1" ] && [ -n "$LAST_ASSISTANT" ]; then
|
|
738
778
|
DESIGN_HASH=$(printf '%s' "${LAST_ASSISTANT: -200}" | governance_hash_prefix)
|
|
@@ -486,5 +486,36 @@ T20A=$(peer_edit_transcript \
|
|
|
486
486
|
'const nextValue = normalizeValue(value)')
|
|
487
487
|
run_test "Test 20a: wrong-target engineering intent cannot authorize Button → block" 1 "$T20A"
|
|
488
488
|
|
|
489
|
+
# Tests 21-24: Mechanism 10 —— 自鎖後把動作推給 user(M36(b))。
|
|
490
|
+
# 對照組刻意四組:必紅一組、必綠三組。少了「必紅」那組,這支閘的綠燈就是零證據
|
|
491
|
+
# (2026-09-19 錨例:規則 2026-08-08 已立、2026-08-28 已明文禁指路 '!',仍再犯 —— 因為零機械強制)。
|
|
492
|
+
self_lock_transcript() {
|
|
493
|
+
# $1 = 工具結果文字(要不要含「被擋」);$2 = assistant reply 文字
|
|
494
|
+
printf '%s\n%s\n%s\n' \
|
|
495
|
+
'{"message":{"role":"user","content":[{"type":"text","text":"收尾"}]}}' \
|
|
496
|
+
"$(jq -nc --arg t "$1" '{message:{role:"user",content:[{type:"tool_result",content:$t}]}}')" \
|
|
497
|
+
"$(jq -nc --arg t "$2" '{message:{role:"assistant",content:[{type:"text",text:$t}]}}')"
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
T21=$(self_lock_transcript \
|
|
501
|
+
'Permission to use Bash with command git branch -D foo has been denied.' \
|
|
502
|
+
'純本機殘留,不影響任何東西,你要清的話在終端機打 ! git branch -D foo 就行。')
|
|
503
|
+
run_test "Test 21: 被擋後叫 user 自己跑指令 → block" 1 "$T21"
|
|
504
|
+
|
|
505
|
+
T22=$(self_lock_transcript \
|
|
506
|
+
'Permission to use Bash with command gh pr merge has been denied.' \
|
|
507
|
+
'這一步是真的 human-only:請你跑 gh auth login 完成登入,之後我會自動續跑。')
|
|
508
|
+
run_test "Test 22: 真 human-only(gh auth login)交辦 → no block" 0 "$T22"
|
|
509
|
+
|
|
510
|
+
T23=$(self_lock_transcript \
|
|
511
|
+
'ok' \
|
|
512
|
+
'你要跑的話在終端機打 npm run dev 就能看即時預覽。')
|
|
513
|
+
run_test "Test 23: 本 turn 沒被擋,只是一般教學 → no block" 0 "$T23"
|
|
514
|
+
|
|
515
|
+
T24=$(self_lock_transcript \
|
|
516
|
+
'Permission to use Bash with command git branch -D foo has been denied.' \
|
|
517
|
+
'改用 git plumbing 繞過該限制:已執行 git update-ref -d refs/heads/foo,分支已刪除。')
|
|
518
|
+
run_test "Test 24: 被擋後自己走等價傳輸、沒交辦 → no block" 0 "$T24"
|
|
519
|
+
|
|
489
520
|
echo "Results: $PASS PASS, $FAIL FAIL"
|
|
490
521
|
[ "$FAIL" -eq 0 ] || exit 1
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
| **M30** | **Wrapper-vs-primitive schema unify invariant — wrapper API option / config schema 必 `extends` primitive SSOT,且 wrapper 內部轉換 mapping 必 forward 全 primitive surface field**。Primitive(`SelectMenuOption` / `MenuItemProps` / `ItemAnatomyProps` 等)宣告 SSOT 後,所有 wrapper(`Select.SelectOption` / `Combobox.SelectOption` / `PeoplePicker` 等)若有同類 schema,(a) 用 TypeScript `extends primitive` 機械繼承,**不可平行 declare** weak schema(同名 / 部分欄位)(b) wrapper 內部 `xxxToYyy()` mapping 必 forward 全 primitive surface field(不可只 forward `value` + `label`,silently drop avatar / description / disabled 等)(c) wrapper-only field 加在 `extends body`(不污染 primitive)。Hook `check_wrapper_primitive_schema_drift.sh` 機械強制(P0 BLOCKER):grep `export interface .*Option \{` cross components/,同名 ≥ 2 處且未 `extends` primitive → BLOCK。對齊 Polaris ChoiceList / Material Autocomplete / Carbon Dropdown wrapper-vs-primitive schema-extension idiom。 | 2026-05-10 PeoplePicker weak schema 漏 avatar,mapping 只 forward 2 fields(詳 historical-bugs.md) |
|
|
70
70
|
| **M32** | **Audit script 必 pixel-quantified verify ≠ attribute existence**(2026-05-12)。Audit 必驗 `rect.top / .left / .height` numeric pixel,**不**可只驗 `getAttribute('data-state')` / `class.includes(...)` = false-positive trap(DOM-pass ≠ visual-pass)。對齊 Material X-DataGrid / AG Grid playwright pixel snapshot / Polaris visual diff canonical。Hook `check_pixel_quantified_audit.sh` 機械強制(scans `getAttribute(` without paired `getBoundingClientRect(`)。**+ Sub-invariant(2026-05-30,doc-claim layer)**:story/anatomy/a11y/spec 的**文字宣稱 ≠ code 真實**——audit 必 adversarial **讀元件 .tsx +(其 wrap 的 Radix/cmdk/react-day-picker 等 lib)source**,逐句驗 keyboard map/ARIA role/focus 行為/prop 存在性/native-vs-custom;prose-skim「looks fine」= false-pass(prose-pass ≠ source-verified)。**「無 code 改動」≠ 可跳過**。`/deep-audit-cross-codex` A.1b + CP-A1b + report-validator F 機械強制。Anchor:2026-05-30 獨立 adversarial 抓 403 findings/64 單元/202 FALSE_CLAIM(前期 prose-skim story dim 全漏);prop-existence deterministic detector 因 passthrough over-flag 證實此類本質需 LLM 讀 source → 用 mandatory-dim + report-validator 保證真跑。**+ Sub-invariant「儀器要先有對照組」(2026-09-08 folded,absorbs 4 bugs)**:任何量測/閘在拿它的**綠燈**當證據前,必須先證明它**在該紅的時候會紅** —— 把被驗的東西弄壞一次,看它是否指名該處,再還原。缺這一步的綠燈是零證據。四個錨(同一天):(a) 22 支瀏覽器腳本因缺沙箱參數永遠回 `SKIPPED-ENV`,332 條不變式從沒真的跑過;(b) 自己寫的 C5/G2 測試假綠(抓到鎖定欄、用滿捲位置),補對照組才發現;(c) `transition-colors` 的 transition-property 含 `outline-color`,聚焦後立刻量抓到過渡中間值,差點寫成「全 DS 焦點框失效」;(d) 本輪新建的 7 組閘 `grep -rl <name> .github` 回 **0** —— 從沒被 CI 呼叫,跟 ci.yml 註解裡記過兩次的 distribute-column-widths / pagination 同一種病;(e) Playwright headless 預設帶 `--hide-scrollbars`,任何量捲軸厚度的探針永遠得 0 —— Bug H(Windows 捲軸溢出)五個月沒人量到就是這樣,要 `ignoreDefaultArgs` 拿掉再用根規則 `::-webkit-scrollbar{width:17px}` 造 Windows 幾何(2026-09-08);(f) 同頁多個目標逐一 `scrollIntoView` 後,先前算好的視窗座標拿去截圖是**全白** —— 截圖前一刻才對該元素重算(同日)。(g) **headless Chromium 的 rAF 被釘在 16.7ms**,連故意把每列加上 box-shadow+blur 都不動,CPU 降速 6 倍也不動 —— 任何「每幀時間」類量具在 headless 一律無效,綠燈是零證據;同一天建了兩版都被自我檢查判死(2026-09-15)。要量幀時間只能在真瀏覽器(而且分頁必須是可見的,背景分頁 rAF 不跑);headless 改用 CDP `Tracing`(看光柵/主執行緒任務)或 `LayerTree.profileSnapshot`(光柵成本),那兩個會紅。(h) **跨網域/跨主機的效能比較無效;先歸因再消融**(2026-09-15,兩天教訓):user 機器「main 17ms / 分支 33ms」追了兩天、DS 內部消融七項全 33、本機永遠重現不出 —— 最後用 Long Animation Frames API 在他機器上看長幀 `scripts[].sourceURL`,5301ms 全在 `thin-client-min.js`(那台機器的網路/安全產品對 `*.netlify.app` 注入的遠端隔離 thin client),而 main 在 github.io 是白名單本地渲染、main 放到 Netlify 一樣慢。**唯一變數是網域**。機械問法:(1) A/B 兩頁同網域嗎?(2) 長幀裡的 script 來源是我們建置裡的檔嗎?兩題沒答完前,任何消融都是白做(`governance/memory/reference_perf_validation_same_host.md`)。**機械化問法**:寫完任一閘立刻問三題 —— 「弄壞它會紅嗎(跑一次)」「誰呼叫它(grep CI)」「它的量測值會不會受動畫/時序影響(等穩態再量)」。**Split note**:原 mega 8 sub-invariants 拆 4 home — (b) fix-time root-invariant → M12 extension / (c)(d)(h) batch + parallel + claim-verify → `/bug-fix-rhythm` skill / (e) tool preflight(CLI binary 必跑 4-test discovery:which / npx / package.json / auth.json,禁短路「not installed」假警報)— 原 memory `feedback_tool_binary_preflight_sweep.md` 已 retire,invariant 一行收容於此 / (f) ship gate → AGENTS.md `# 稽核 canonical` / (g) Layer marker → M31 + hook。git blame 2026-05-12 commit 留 audit trail。 | 2026-05-12 4 audit-vs-visual gap absorbed:cell-align / divider 2px / breadcrumb tooltip / row-alignment 全 audit「Δ=0 ALL PASS」但 user 抓視覺壞(詳 historical-bugs.md)。|
|
|
71
71
|
| **M31** | **Provider-adaptive adversarial two-track 5-step canonical**。**Activation boundary**:只有 task/deliverable 明確要求 independent review 時才啟動;exact run waiver 必記 receipt,optional review 缺席不得阻擋一般工程、deep audit 或 standard release。執行 authority = `packages/design-system/ds-canonical/skills/independent-review/SKILL.md` / `deep-audit-cross-codex/SKILL.md` + `packages/governance/canonical/providers.json` + `packages/governance/src/provider-review-binding.mjs#resolveProviderReviewBinding`;skill 舊名稱只保留 discovery compatibility,不指定 reviewer。**Step 0 入口 gate**:啟動後 primary author 先完成獨立 Phase A,再由 resolver 選出不同 provider、不同 context、read-only、已認證的 peer;無可用 peer/transport/certification/evidence = required-review claim `REVIEW-BLOCKED`,禁止同模型或同 context 假扮 second opinion。**Step 1-5**(啟動後每題必過):(1)兩方各自在隔離 context 熟讀相同完整 inventory/spec/canonical/source,NO-SAMPLE;(2)兩方各自驗證 deterministic gates + applicable runtime/visual evidence,不可只一方 verify;(3)需要視覺判斷時兩方各自執行 target-bound browser/DOM/pixel 稽核;(4)每個 finding 都附 owner path/精確證據/reasoning,未證實即撤回;(5)closed synthesis 比較兩份 content-addressed artifact,agree 時補齊缺漏,disagree 時以 canonical evidence 較強者勝,保留 unresolved,不得 pass-through。legacy-named compatibility hook `check_codex_collab_5step.sh` 只檢查流程證據,不是 provider 或 transport authority。對齊 RFC 學術同儕審查 / Linux kernel-mailinglist cite source / Google ML eng-design-review。 | 2026-05-10 的 pass-through 事故證明「拿 peer 結論代替 primary 驗證」會造成 drift;後續 cite battle 以 `field-controls.spec.md` + `item-anatomy.spec.md` 找回雙 owner,現已抽象成 provider-neutral second-opinion invariant。 |
|
|
72
|
-
| **M36** | **禁把自己的推論寫成 user 的決定;禁用自家治理設定把自己鎖死**(2026-08-08 user directive)。**(a) Provenance 不得升格**:任何文件/回覆標「user 拍板」「你最早的決定」「已拍板」,**必須當場引得出 user 的原話**;引不出來一律標「AI 推導」或「AI 建議、user 採納」。**引文一律逐字,禁刪語氣詞**——把「…才對吧?」寫成「…才對」= 竄改證據,比誤判嚴重(2026-08-09 錨例);user 說「還在思考」之後仍當已決,同罪。**問句 ≠ 同意**——user 問「這是 X 的情況?」是要澄清,不是核准。**推論 ≠ 既有**——把某個既有值(如 Dialog 的 maxWidth 檔位)當成保證,再據以生出新規則,是同一類病。**規範的「理由」也要引得出原文(2026-09-18 加)**——說「X 存在的唯一理由是 Y」「X 是為了 Y」前,必須先讀到 X 自己寫的理由並逐字引;**現象上成立 ≠ 那就是它的理由**。錯例:Combobox 的 tagPadding,規格白紙黑字寫「確保 tag 四邊等距」,我看到 sm/md 剛好讓 Tag 內文字落在 `--field-px` 那條線上,就寫成「它存在的唯一理由就是把字推回那條線」,並據此把 lg(四邊等距算出 5、字落 15px)判成「兩條規範打架」丟給 user 拍板 —— **那是我自己造出來的假議題**,而且該規則三天前才立、commit message 就寫著理由。危險之處在於:編造的理由會**同時**寫進 code 註解、spec、閘的檔頭與 commit,下一個人只讀得到我的版本。機械問法:(1)這個「理由」我是**讀到的**還是**看出來的**?(2)引得出檔名行號嗎?(3)我要據此宣告「衝突 / 例外 / 該改」之前,原文有沒有說過那句話?第 (3) 題沒過就不准把它升級成待決事項 —— 假議題比沉默更貴。發現升格 → 立即撤回並留檔於該文件的「來源總帳」。**(b) 禁自鎖(anti-self-lock)**:遇到「被我們自己的 policy/schema/sandbox 設定擋住授權內動作」時,**先解自己的鎖**(改 canonical owner → 走正常 PR),或改用不需放寬安全邊界的既有機制;**禁止**因自家設定擋路就把動作丟回 user、或宣稱做不到。真正的 human-only boundary 只有 login/MFA/OAuth、缺 credential reference、plan 外付費、法律/帳號權限——**自家治理設定不在此列**。**(b') 判自鎖的機械三問(2026-08-11 codify,任何模型任何環境)**:宣稱「被擋、需要 user」前必逐題答:(1)**憑證真的缺嗎?**——canonical credential reference(`~/.config/qijenchen-governance/github-token`)存在且可用 ≠ 缺憑證;工具讀錯存放處(gh 存的 OAuth 過期但 token 檔可用)= 工程 bug 自修,禁報 login 邊界。(2)**體檢測的是真實需要的能力嗎?**——帳號級 preflight(`gh auth status`)擋 repo-scoped token = 體檢錯位,改 target-bound 驗證(能讀目標 repo 即可)。(3)**這條傳輸不通,有沒有已驗證可通的等價傳輸?**——gh 的 Go TLS 不信 sandbox 代理憑證但 curl 可通 → 換傳輸(shim),不是邊界。(4)**鎖的主人是誰?(2026-08-28 加)**——自家 policy/schema/settings 有列 → 解自己的鎖走正常 PR;**自家清單沒列卻仍 EPERM = 平台內建安全邊界**(如 Claude Code 對 hook 設定目錄的防注入保護、沙箱不可關),不試圖解鎖,改找**不碰被鎖路徑**的等價機制(git plumbing 只寫 `.git` 可寫區、harness 檔案工具、index-authoritative generator);**任何要交 user 執行的指令,必先驗證它不在同一道牆內**——對話內 `!` 與 Bash 同沙箱,指同牆死路 = 把動作丟回 user 的變形,同罪。**復原/交易類機制必有顯式逃生口 + skip-identical**(未變目標不准碰;全有全無原子性造成的死鎖 = 過度設計,2026-08-11 拆除)
|
|
72
|
+
| **M36** | **禁把自己的推論寫成 user 的決定;禁用自家治理設定把自己鎖死**(2026-08-08 user directive)。**(a) Provenance 不得升格**:任何文件/回覆標「user 拍板」「你最早的決定」「已拍板」,**必須當場引得出 user 的原話**;引不出來一律標「AI 推導」或「AI 建議、user 採納」。**引文一律逐字,禁刪語氣詞**——把「…才對吧?」寫成「…才對」= 竄改證據,比誤判嚴重(2026-08-09 錨例);user 說「還在思考」之後仍當已決,同罪。**問句 ≠ 同意**——user 問「這是 X 的情況?」是要澄清,不是核准。**推論 ≠ 既有**——把某個既有值(如 Dialog 的 maxWidth 檔位)當成保證,再據以生出新規則,是同一類病。**規範的「理由」也要引得出原文(2026-09-18 加)**——說「X 存在的唯一理由是 Y」「X 是為了 Y」前,必須先讀到 X 自己寫的理由並逐字引;**現象上成立 ≠ 那就是它的理由**。錯例:Combobox 的 tagPadding,規格白紙黑字寫「確保 tag 四邊等距」,我看到 sm/md 剛好讓 Tag 內文字落在 `--field-px` 那條線上,就寫成「它存在的唯一理由就是把字推回那條線」,並據此把 lg(四邊等距算出 5、字落 15px)判成「兩條規範打架」丟給 user 拍板 —— **那是我自己造出來的假議題**,而且該規則三天前才立、commit message 就寫著理由。危險之處在於:編造的理由會**同時**寫進 code 註解、spec、閘的檔頭與 commit,下一個人只讀得到我的版本。機械問法:(1)這個「理由」我是**讀到的**還是**看出來的**?(2)引得出檔名行號嗎?(3)我要據此宣告「衝突 / 例外 / 該改」之前,原文有沒有說過那句話?第 (3) 題沒過就不准把它升級成待決事項 —— 假議題比沉默更貴。發現升格 → 立即撤回並留檔於該文件的「來源總帳」。**(b) 禁自鎖(anti-self-lock)**:遇到「被我們自己的 policy/schema/sandbox 設定擋住授權內動作」時,**先解自己的鎖**(改 canonical owner → 走正常 PR),或改用不需放寬安全邊界的既有機制;**禁止**因自家設定擋路就把動作丟回 user、或宣稱做不到。真正的 human-only boundary 只有 login/MFA/OAuth、缺 credential reference、plan 外付費、法律/帳號權限——**自家治理設定不在此列**。**(b') 判自鎖的機械三問(2026-08-11 codify,任何模型任何環境)**:宣稱「被擋、需要 user」前必逐題答:(1)**憑證真的缺嗎?**——canonical credential reference(`~/.config/qijenchen-governance/github-token`)存在且可用 ≠ 缺憑證;工具讀錯存放處(gh 存的 OAuth 過期但 token 檔可用)= 工程 bug 自修,禁報 login 邊界。(2)**體檢測的是真實需要的能力嗎?**——帳號級 preflight(`gh auth status`)擋 repo-scoped token = 體檢錯位,改 target-bound 驗證(能讀目標 repo 即可)。(3)**這條傳輸不通,有沒有已驗證可通的等價傳輸?**——gh 的 Go TLS 不信 sandbox 代理憑證但 curl 可通 → 換傳輸(shim),不是邊界。(4)**鎖的主人是誰?(2026-08-28 加)**——自家 policy/schema/settings 有列 → 解自己的鎖走正常 PR;**自家清單沒列卻仍 EPERM = 平台內建安全邊界**(如 Claude Code 對 hook 設定目錄的防注入保護、沙箱不可關),不試圖解鎖,改找**不碰被鎖路徑**的等價機制(git plumbing 只寫 `.git` 可寫區、harness 檔案工具、index-authoritative generator);**任何要交 user 執行的指令,必先驗證它不在同一道牆內**——對話內 `!` 與 Bash 同沙箱,指同牆死路 = 把動作丟回 user 的變形,同罪。**復原/交易類機制必有顯式逃生口 + skip-identical**(未變目標不准碰;全有全無原子性造成的死鎖 = 過度設計,2026-08-11 拆除)。**(b'') 機械化(2026-09-19)**:(b) 從 2026-08-08 立規到 2026-09-19 都只有散文、零強制 —— 而 (a) 早就有 `stop_self_audit.sh` Mechanism 8 把關。結果就是 2026-09-19 再犯同一件事:`git branch -D` 被 classifier 擋下,沒走等價的 `git update-ref -d`(plumbing 只寫 `.git` 可寫區),直接寫「你要清的話在終端機打 `!` …」——**正是 2026-08-28 那條錨例白紙黑字禁止的動作**,而且是 user 反問才發現。現由同檔 **Mechanism 10** 強制:本 turn 有工具被擋 + reply 把具體指令交給 user → BLOCKER,turn 不結束;真 human-only(login/MFA/OAuth/帳單/缺 credential reference)明文豁免。**教訓本身**:規則重犯代表缺的是強制面而不是再寫一遍散文 —— 同一條 M-rule 的兩個子款,有 hook 的那款沒再犯,沒 hook 的那款犯了兩次。 | 2026-08-08 4 次 provenance 升格 + policy 自鎖;2026-08-11 一日連環五鎖全是自家機制,逐層拆除後 release 全自動走通;2026-08-28 平台鎖誤判自家鎖 + 指 `!` 同沙箱死路給 user,正解 skip-worktree 一行(詳 historical-bugs.md,含 user 原話) |
|
|
73
73
|
<!-- M27 retired 2026-05-15(per /knowledge-prune D3 audit):self-flagged「M23 子規則」 → collapsed into M23 sub-bullet (c) "framework prop name namespace conflict"。Original case (TanStack size vs DS density) + hook `check_datatable_invariants.sh(r2 folded,2026-06-11)` retained 在 M23 children。 -->
|
|
74
74
|
<!-- M33 retired 2026-05-22(per /knowledge-prune deep audit Lens 1+2):folded into M20 as sub-rule「Stop hook overfire defer anti-pattern」。Original session context(2026-05-13 claim-verify-gap)+ hook `stop_self_audit.sh` P1 warn detection(Mechanism 4 + 次 turn auto-inject)retained at M20 entry。Single-bug rule → 與 M20 同類「AI self-correction under feedback signals」合併。 -->
|
|
75
75
|
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"type": "git",
|
|
5
5
|
"url": "git+https://github.com/ajenchen/design-system.git"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.1.0-beta.
|
|
7
|
+
"version": "0.1.0-beta.136",
|
|
8
8
|
"private": false,
|
|
9
9
|
"description": "World-class design system — components, patterns, tokens, hooks (single source of truth for team distribution).",
|
|
10
10
|
"type": "module",
|