#!/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\(\)`/g, '`acr logs `(有 MCP 則 `arcrun_get_workflow()`)') .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, '', '', '', middle, '', tail, '', ].join('\n'); writeFileSync(join(skillDir, 'SKILL.md'), out, 'utf8'); console.log(`✓ harness skill 已由 registry 重建:${out.length} bytes`);