46afea83c2
管道本來就是好的(install-harness 功能完整、冪等),**過時的是內容**:
harness skill(4066B)grep「意圖」「>>」= 0 命中,只講世界觀/別寫 Python
⇒ 新裝的封測者拿不到步驟 1 的核心教材(`>>` 意圖語法)。
■ 單一真相源:harness skill 改為建置期由 registry 複製
build-harness-skill.mjs=head + registry/skills/write_intent_workflow.md 正文 + tail。
選「建置期複製」的理由:npm files 只收 harness/,registry 不進套件;
symlink 在 npm pack 與 Windows 不可靠。產物 commit 進 repo(npm 裝的是產物、不跑 build)。
head/tail 是 harness 專屬(CLI 語境入口/acr 指令表/暴露同意/誠實鐵律),
install-harness 的 copyTree 跳過 .head/.tail,不鋪進使用者專案。
■ 其餘三件逐份對照現世代事實後更新(過時的直接刪,不留死代碼)
- CLAUDE.block.md:補 >> 意圖語法、not_found 兩條路、零件 vs recipe 分型、
腹語術紅線、金鑰只拿名字
- commands/arcrun.md:步驟改成「先寫意圖 → 丟去查 → 再寫 YAML」,補 acr search/validate
- hooks/arcrun-guard.sh:**正路提示改為指向 arcrun-mindset Skill +意圖語法**
(呼應「hook 沒提 skill 反而把 AI 導向 repo 文件」的教訓);
新增 code 節點腹語術提醒,settings.fragment 補 Write|Edit|MultiEdit matcher
■ 世代閘(防再度脫節)
check-harness-generation.mjs 檢查四件交付物的現世代指紋,缺指紋 exit 1,
掛進 npm run build(prepublishOnly 因此也擋)。
反向驗證:把 skill/CLAUDE.block 換回上一代 → 兩者都被擋下並逐條點名缺哪個指紋。
■ 驗收(考生 haiku/受測物=環境)
乾淨臨時目錄 acr install-harness → 四件鋪好;重跑冪等(全檔 md5 不變、
CLAUDE.md 66 行不變、hooks 條目 2 不變、arcrun 區塊仍 1 個)。
haiku 只讀該目錄的 CLAUDE.md+SKILL.md(明令禁讀 ~/.claude、禁上網;
兩份教材 md5 與大小均不同,可證非考本機那支)答十題
→ grade-step1.sh **10 / 10 通過**(判分器同時反向驗證仍會抓
ON_TRUE/ON_FAILURE/第一節點非 input)。
npm test 18/18、tsc 綠。
SDD:workflow-discovery/tasks.md 3.11
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
65 lines
3.3 KiB
JavaScript
65 lines
3.3 KiB
JavaScript
#!/usr/bin/env node
|
||
/**
|
||
* build-harness-skill.mjs — 由 registry/skills/ 組出 harness 的 arcrun-mindset SKILL.md
|
||
*
|
||
* 【為什麼是「建置期複製」而不是人工維護兩份】
|
||
* `registry/skills/write_intent_workflow.md` 是意圖語法的**單一真相源**——它同時是
|
||
* MCP `arcrun_get_skill()` 回給雲端 AI 的內容。harness 的 skill 若人工再抄一份,
|
||
* 兩份必然漂移(2026-07-31 實錄:harness 那份停在上一代,grep「意圖」「>>」= 0 命中,
|
||
* 只講世界觀,害新裝的用戶 AI 學不到 `>>`)。
|
||
*
|
||
* 作法:harness skill = 三段拼接
|
||
* SKILL.md.head ← harness 專屬(frontmatter/CLI 入口/三種東西的分型)
|
||
* registry 的 write_intent_workflow.md 正文 ← 單一真相源,只此一份被維護
|
||
* SKILL.md.tail ← harness 專屬(acr 指令表/暴露同意/誠實鐵律)
|
||
*
|
||
* 為什麼不用 symlink / npm 打包直接引用:npm `files` 只收 `harness/`,
|
||
* registry/ 不進套件;symlink 在 npm pack 與 Windows 上不可靠。建置期複製最單純。
|
||
*
|
||
* 產物 `SKILL.md` **有 commit 進 repo**(npm 套件裝的是它,不會跑 build),
|
||
* 由 check-harness-generation.mjs 驗證它與 registry 沒有漂移。
|
||
*/
|
||
import { readFileSync, writeFileSync } from 'node:fs';
|
||
import { fileURLToPath } from 'node:url';
|
||
import { dirname, join } from 'node:path';
|
||
|
||
const here = dirname(fileURLToPath(import.meta.url)); // cli/scripts
|
||
const repoRoot = join(here, '..', '..'); // repo 根
|
||
const skillDir = join(here, '..', 'harness', 'skills', 'arcrun-mindset');
|
||
const registrySkill = join(repoRoot, 'registry', 'skills', 'write_intent_workflow.md');
|
||
|
||
const head = readFileSync(join(skillDir, 'SKILL.md.head'), 'utf8').trimEnd();
|
||
const tail = readFileSync(join(skillDir, 'SKILL.md.tail'), 'utf8').trimEnd();
|
||
const body = readFileSync(registrySkill, 'utf8');
|
||
|
||
// 取 registry skill 的正文:去掉它自己的 H1 標題與「何時用這個 skill」那段
|
||
// (harness 的 head 已用 CLI 語境寫過入口),從第一個 `## 1.` 章節起收。
|
||
const idx = body.indexOf('## 1. 意圖工作流的語法');
|
||
if (idx < 0) {
|
||
console.error('❌ registry/skills/write_intent_workflow.md 找不到「## 1. 意圖工作流的語法」章節;');
|
||
console.error(' registry skill 結構變了 → 請同步更新 cli/scripts/build-harness-skill.mjs 的取段規則。');
|
||
process.exit(1);
|
||
}
|
||
const middle = body
|
||
.slice(idx)
|
||
// registry 版把 MCP 工具當預設介面;harness 裝在有 acr CLI 的專案 → 補上 CLI 等價指令
|
||
.replace(/`arcrun_get_workflow\(<name>\)`/g, '`acr logs <name>`(有 MCP 則 `arcrun_get_workflow(<name>)`)')
|
||
.replace(/`arcrun_list_components` \/ `arcrun_search_components`/g, '`acr parts` / `acr search`')
|
||
.replace(/下一步該讀哪支 skill:`arcrun_list_skills\(\)`/g, '下一步該讀哪支 skill(需 MCP):`arcrun_list_skills()`')
|
||
.trimEnd();
|
||
|
||
const out = [
|
||
head,
|
||
'',
|
||
'<!-- 以下正文由 registry/skills/write_intent_workflow.md 於建置期複製而來(單一真相源)。',
|
||
' 不要直接編輯本段——改 registry 那份,然後跑 `npm run build:harness`。 -->',
|
||
'',
|
||
middle,
|
||
'',
|
||
tail,
|
||
'',
|
||
].join('\n');
|
||
|
||
writeFileSync(join(skillDir, 'SKILL.md'), out, 'utf8');
|
||
console.log(`✓ harness skill 已由 registry 重建:${out.length} bytes`);
|