#!/usr/bin/env node
/**
 * check-harness-generation.mjs — 世代閘：harness 內容脫節就讓 build/publish 失敗
 *
 * 【為什麼要這道閘】
 * 2026-07-31 實錄：`acr install-harness` 的管道一直是好的，但它鋪出去的**內容停在上一代**——
 * harness skill grep「意圖」「>>」= 0 命中，只講世界觀。管道綠燈、交付物過時，
 * 沒有任何機械檢查會抱怨 ⇒ 世代脫節可以無聲存在好幾個月。
 *
 * 這道閘檢查四件交付物的「現世代指紋」。缺指紋 = exit 1，擋掉 build 與 npm publish。
 * 指紋要挑「上一代絕不會有、現世代一定有」的字串，不是隨便的關鍵字。
 */
import { readFileSync, existsSync, statSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
import { execFileSync } from 'node:child_process';

const here = dirname(fileURLToPath(import.meta.url));
const harness = join(here, '..', 'harness');
const repoRoot = join(here, '..', '..');

/** @type {{file: string, must: [string, string][], mustNot?: [string,string][]}[]} */
const CHECKS = [
  {
    file: 'skills/arcrun-mindset/SKILL.md',
    must: [
      ['>>', '意圖語法（`A >> 邊 >> B`）——步驟 1 的核心教材'],
      ['ON_SUCCESS', '合法邊之一'],
      ['對每個', 'FOREACH 邊（十題裡有四題要用）'],
      ['input', '第一個節點固定是 input'],
      ['not_found', '現世代查詢狀態（舊版寫 missing／假 found）'],
      ['腹語術', '缺件不准改寫成 code 的紅線'],
      ['recipe', '零件 vs recipe 分型'],
      // 條件邊自 2026-08-01 起引擎已支援（cypher-executor/src/graph-executor.ts
      // case 'ON_TRUE'/'ON_FALSE'/'ON_BRANCH'，31 個測試全過）。教材該教會怎麼用，
      // 不是教「不存在」——這條 must 同時防「哪天又被改回舊世代說法」的回歸。
      ['ON_TRUE', '條件邊（配 if_control）自 2026-08-01 起引擎已支援，教材須教會用法'],
    ],
    mustNot: [
      // ON_FAILURE 才是真的不存在（VALID_EDGE_TYPES 只有 ON_FAIL，見
      // cypher-executor/src/lib/constants.ts）。只准出現在「教它不存在」的脈絡。
      // 2026-08-10 修正：這道閘原本擋的是 ON_TRUE——但 ON_TRUE/ON_FALSE/ON_BRANCH
      // 已是引擎現世代能力，正確教材反而被這道閘擋下，是閘的判準過時了，不是教材寫錯。
      ['ON_FAILURE', '引擎沒有這種邊（只有 ON_FAIL）；教材不該把它教成可用的邊', /不要寫|不存在|沒有這種|❌|非法/],
    ],
  },
  {
    file: 'CLAUDE.block.md',
    must: [
      ['>>', '意圖語法要在 CLAUDE.md 就先亮相'],
      ['not_found', '缺件兩條路的觸發點'],
    ],
  },
  {
    file: 'commands/arcrun.md',
    must: [
      ['>>', '/arcrun 的第一步就該是寫意圖'],
      ['acr search', '現世代的跨類搜尋指令'],
    ],
  },
  {
    file: 'hooks/arcrun-guard.sh',
    must: [
      ['arcrun-mindset', 'hook 被擋下時要把 AI 導向 skill，而不是叫它去翻 repo 文件'],
      ['>>', 'hook 的正路提示要提到意圖語法'],
    ],
  },
];

let fail = 0;
const say = (s) => console.log(s);

say('\n  世代閘：檢查 harness 交付物是否為現世代內容\n');

for (const c of CHECKS) {
  const p = join(harness, c.file);
  if (!existsSync(p)) {
    say(`  ❌ ${c.file} — 檔案不存在`);
    fail++;
    continue;
  }
  const text = readFileSync(p, 'utf8');
  const missing = c.must.filter(([needle]) => !text.includes(needle));
  const badNot = (c.mustNot ?? []).filter(([needle, , allowIfNear]) => {
    if (!text.includes(needle)) return false;
    if (!allowIfNear) return true;
    // 允許「在教『不要用』的脈絡裡」出現：看該字串所在行是否有豁免詞
    return !text
      .split('\n')
      .filter((l) => l.includes(needle))
      .every((l) => allowIfNear.test(l));
  });

  if (missing.length === 0 && badNot.length === 0) {
    say(`  ✓ ${c.file}`);
  } else {
    fail++;
    say(`  ❌ ${c.file}`);
    for (const [needle, why] of missing) say(`       缺指紋「${needle}」— ${why}`);
    for (const [needle, why] of badNot) say(`       不該出現「${needle}」— ${why}`);
  }
}

// harness skill 必須是由 registry 重建的最新版（防「改了 registry 忘了重跑 build」）
const skillPath = join(harness, 'skills', 'arcrun-mindset', 'SKILL.md');
const registrySkill = join(repoRoot, 'registry', 'skills', 'write_intent_workflow.md');
if (existsSync(skillPath) && existsSync(registrySkill)) {
  try {
    execFileSync(process.execPath, [join(here, 'build-harness-skill.mjs')], { stdio: 'pipe' });
    const rebuilt = readFileSync(skillPath, 'utf8');
    const before = statSync(skillPath); // 重建後內容即為期望值
    void before;
    // 重建是冪等的：若重建後與 git 中的版本不同，git diff 會在 CI 顯示；
    // 這裡直接比對「重建結果是否含 registry 當前的關鍵段落」
    const reg = readFileSync(registrySkill, 'utf8');
    const marker = reg.includes('## 7. 常犯的錯') ? '## 7. 常犯的錯' : null;
    if (marker && !rebuilt.includes(marker)) {
      say(`  ❌ harness skill 與 registry 漂移：registry 有「${marker}」但重建產物沒有`);
      fail++;
    } else {
      say('  ✓ harness skill 與 registry/skills/write_intent_workflow.md 同步');
    }
  } catch (e) {
    say(`  ❌ 無法由 registry 重建 harness skill：${e.message}`);
    fail++;
  }
}

say('');
if (fail) {
  say(`  🔴 世代閘擋下（${fail} 項）。harness 交付的內容落後於現世代。`);
  say('     修法：改 registry/skills/write_intent_workflow.md（單一真相源）或對應的');
  say('     cli/harness/ 檔案，然後跑 `npm run build:harness` 重建，再跑本檢查。\n');
  process.exit(1);
}
say('  ✅ 世代閘通過：四件交付物都帶現世代指紋\n');
