/**
 * V0 dormancy — negative tests.
 *
 * V1 keeps V0's psychographic machinery (5D dimensions + 8 archetypes + signal map)
 * in code but explicitly does not surface it in default-mode skill output. This test
 * enforces the maintenance boundary: if these strings ever appear in a generated
 * tier-≥2 SKILL.md's normal (default-mode) content, V0 machinery has leaked.
 *
 * Exceptions (explicitly allowed): SKILL.md files for skills that legitimately discuss
 * V0 machinery:
 *   - plan-tune/ — the conversational inspection skill for /plan-tune
 *   - office-hours/ — sets the declared profile
 * For these, V0 vocabulary is load-bearing and must appear.
 *
 * All other tier-≥2 skills: 5D dim names + archetype names must NOT appear.
 */
import { describe, test, expect } from 'bun:test';
import * as fs from 'fs';
import * as path from 'path';

const ROOT = path.resolve(import.meta.dir, '..');

const FORBIDDEN_5D_DIMS = [
  'scope_appetite',
  'risk_tolerance',
  'detail_preference',
  'architecture_care',
  // `autonomy` is too common a word to forbid in arbitrary skill output.
];

const FORBIDDEN_ARCHETYPE_NAMES = [
  'Cathedral Builder',
  'Ship-It Pragmatist',
  'Deep Craft',
  'Taste Maker',
  'Solo Operator',
  // `Consultant`, `Wedge Hunter`, `Builder-Coach` — some may appear in prose
  // naturally; check the strictly-V0-unique phrases first.
];

// Skills that legitimately reference V0 psychographic vocabulary.
const ALLOWED_SKILLS_WITH_V0_VOCAB = new Set([
  'plan-tune',
  'office-hours',
]);

function discoverTier2PlusSkillMds(): Array<{ skillName: string; mdPath: string }> {
  const entries = fs.readdirSync(ROOT, { withFileTypes: true });
  const results: Array<{ skillName: string; mdPath: string }> = [];
  for (const e of entries) {
    if (!e.isDirectory()) continue;
    if (e.name.startsWith('.') || e.name === 'node_modules' || e.name === 'test') continue;
    const mdPath = path.join(ROOT, e.name, 'SKILL.md');
    const tmplPath = path.join(ROOT, e.name, 'SKILL.md.tmpl');
    if (!fs.existsSync(mdPath) || !fs.existsSync(tmplPath)) continue;
    // Check tier via frontmatter. Every template that resolves {{PREAMBLE}}
    // must declare preamble-tier (the generator throws otherwise), so a
    // missing declaration means the template has no preamble at all — scan it
    // anyway (the vocabulary check is content-wide and cheap).
    const tmpl = fs.readFileSync(tmplPath, 'utf-8');
    const tierMatch = tmpl.match(/preamble-tier:\s*(\d+)/);
    if (tierMatch && parseInt(tierMatch[1], 10) < 2) continue;
    results.push({ skillName: e.name, mdPath });
  }
  return results;
}

describe('V0 dormancy in default-mode skill output', () => {
  const skills = discoverTier2PlusSkillMds();

  for (const { skillName, mdPath } of skills) {
    if (ALLOWED_SKILLS_WITH_V0_VOCAB.has(skillName)) continue;

    test(`${skillName}/SKILL.md contains no V0 psychographic dimension names`, () => {
      const content = fs.readFileSync(mdPath, 'utf-8');
      for (const dim of FORBIDDEN_5D_DIMS) {
        expect(content).not.toContain(dim);
      }
    });

    test(`${skillName}/SKILL.md contains no V0 archetype names`, () => {
      const content = fs.readFileSync(mdPath, 'utf-8');
      for (const archetype of FORBIDDEN_ARCHETYPE_NAMES) {
        expect(content).not.toContain(archetype);
      }
    });
  }

  test('at least 5 tier-≥2 skills were checked (sanity)', () => {
    expect(skills.length).toBeGreaterThanOrEqual(5);
  });
});
