"use strict";
// src/test_flow_run_cli.ts
// Smoke test for the v1.9.0 `openlife flow` CLI surface and
// `openlife project-mode` commands. Exercises the runtime path without
// requiring an LLM or external CI.
//
// Covers:
//  1. listFlows() returns all 12 expected workflows from bundled source
//  2. findFlow(id) resolves a known workflow
//  3. dryRunFlow(id) produces a phase plan with > 0 steps
//  4. ProjectMetadata read/write roundtrip
//  5. detectMode + recommendWorkflow produce sane defaults
//  6. project mode persistence file shape is valid JSON
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
const fs = __importStar(require("fs"));
const os = __importStar(require("os"));
const path = __importStar(require("path"));
const CommandFlowRunner_1 = require("./cli/CommandFlowRunner");
const ProjectMetadata_1 = require("./orchestrator/ProjectMetadata");
let passed = 0;
let failed = 0;
function check(name, cond, detail) {
    if (cond) {
        passed++;
        console.log(`  ✓ ${name}`);
    }
    else {
        failed++;
        console.error(`  ✗ ${name}${detail ? ` — ${detail}` : ''}`);
    }
}
const REPO_ROOT = path.resolve(__dirname, '..');
// ── 1. listFlows ───────────────────────────────────────────────────────
console.log('\n[1] CommandFlowRunner.listFlows()');
const flows = (0, CommandFlowRunner_1.listFlows)(REPO_ROOT);
check('at least 12 workflows surfaced', flows.length >= 12, `got ${flows.length}`);
const flowIds = new Set(flows.map(f => f.id));
for (const expected of ['greenfield-fullstack', 'greenfield-service', 'greenfield-ui',
    'brownfield-blueprint', 'brownfield-fullstack', 'brownfield-service',
    'brownfield-ui', 'story-development-cycle', 'qa-loop',
    'spec-pipeline', 'epic-orchestration', 'continuous-deployment']) {
    check(`flow "${expected}" listed`, flowIds.has(expected));
}
// Every entry has the right shape
for (const f of flows.slice(0, 3)) {
    check(`flow "${f.id}" has type`, !!f.type);
    check(`flow "${f.id}" has steps > 0`, f.steps > 0, `steps=${f.steps}`);
}
// ── 2. findFlow ────────────────────────────────────────────────────────
console.log('\n[2] CommandFlowRunner.findFlow()');
const greenfieldFs = (0, CommandFlowRunner_1.findFlow)('greenfield-fullstack', REPO_ROOT);
check('findFlow("greenfield-fullstack") returns a workflow', greenfieldFs !== null);
check('found workflow has correct id', greenfieldFs?.workflow.id === 'greenfield-fullstack');
check('source is bundled when running from repo', greenfieldFs?.source === 'bundled' || greenfieldFs?.source === 'local');
const notFound = (0, CommandFlowRunner_1.findFlow)('definitely-does-not-exist', REPO_ROOT);
check('findFlow returns null for unknown id', notFound === null);
// ── 3. dryRunFlow ──────────────────────────────────────────────────────
console.log('\n[3] CommandFlowRunner.dryRunFlow()');
const summary = (0, CommandFlowRunner_1.dryRunFlow)('greenfield-service', REPO_ROOT);
check('dryRunFlow("greenfield-service") returns summary', summary !== null);
if (summary) {
    check('summary has id', summary.id === 'greenfield-service');
    check('summary has > 5 steps', summary.steps.length > 5, `got ${summary.steps.length}`);
    check('summary has at least one phase marker', summary.steps.some(s => s.phase !== undefined));
    check('summary has at least one executable step', summary.steps.some(s => s.id !== undefined));
    const rendered = (0, CommandFlowRunner_1.renderDryRun)(summary);
    check('renderDryRun produces > 5 lines', rendered.length > 5);
}
// ── 4. ProjectMetadata roundtrip ───────────────────────────────────────
console.log('\n[4] ProjectMetadata read/write roundtrip');
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'openlife-method-test-'));
try {
    const meta = (0, ProjectMetadata_1.buildMetadata)('greenfield', tmpRoot, 'test-run-note');
    const fp = (0, ProjectMetadata_1.writeProjectMetadata)(meta, tmpRoot);
    check('writeProjectMetadata returns path', fp.endsWith('project.json'));
    check('file was actually written', fs.existsSync(fp));
    const readBack = (0, ProjectMetadata_1.readProjectMetadata)(tmpRoot);
    check('readProjectMetadata returns metadata', readBack !== null);
    check('read mode matches written mode', readBack?.mode === 'greenfield');
    check('read createdAt is ISO string', /\d{4}-\d{2}-\d{2}T/.test(readBack?.createdAt || ''));
    check('read recommendedWorkflow is non-empty', !!readBack?.recommendedWorkflow);
    check('read notes preserved', readBack?.notes === 'test-run-note');
    // Round-trip with brownfield
    const meta2 = (0, ProjectMetadata_1.buildMetadata)('brownfield', tmpRoot);
    (0, ProjectMetadata_1.writeProjectMetadata)(meta2, tmpRoot);
    const readBack2 = (0, ProjectMetadata_1.readProjectMetadata)(tmpRoot);
    check('brownfield mode roundtrips', readBack2?.mode === 'brownfield');
    check('brownfield recommends discovery', readBack2?.recommendedWorkflow === 'brownfield-blueprint');
}
finally {
    fs.rmSync(tmpRoot, { recursive: true, force: true });
}
// ── 5. detectMode + recommendWorkflow ──────────────────────────────────
console.log('\n[5] Heuristic detection');
// Empty tmpdir → greenfield
const emptyDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openlife-empty-'));
try {
    const mode = (0, ProjectMetadata_1.detectMode)(emptyDir);
    check('empty dir → greenfield', mode === 'greenfield');
    const rec = (0, ProjectMetadata_1.recommendWorkflow)(mode, []);
    check('greenfield + no stack → greenfield-fullstack', rec === 'greenfield-fullstack');
}
finally {
    fs.rmSync(emptyDir, { recursive: true, force: true });
}
// Tmp with package.json but no git → still greenfield
const pkgDir = fs.mkdtempSync(path.join(os.tmpdir(), 'openlife-pkg-'));
try {
    fs.writeFileSync(path.join(pkgDir, 'package.json'), JSON.stringify({ name: 'x', dependencies: { react: '*' } }));
    const stack = (0, ProjectMetadata_1.detectStack)(pkgDir);
    check('detectStack finds node', stack.includes('node'));
    check('detectStack finds react', stack.includes('react'));
    const rec = (0, ProjectMetadata_1.recommendWorkflow)('greenfield', stack);
    check('greenfield + react → greenfield-ui (no server)', rec === 'greenfield-ui');
}
finally {
    fs.rmSync(pkgDir, { recursive: true, force: true });
}
// Brownfield always recommends discovery
const rec3 = (0, ProjectMetadata_1.recommendWorkflow)('brownfield', ['node', 'typescript', 'react']);
check('brownfield → discovery regardless of stack', rec3 === 'brownfield-blueprint');
// ── 6. JSON file shape ─────────────────────────────────────────────────
console.log('\n[6] project.json shape');
const tmpRoot2 = fs.mkdtempSync(path.join(os.tmpdir(), 'openlife-shape-'));
try {
    const meta = (0, ProjectMetadata_1.buildMetadata)('greenfield', tmpRoot2);
    (0, ProjectMetadata_1.writeProjectMetadata)(meta, tmpRoot2);
    const raw = fs.readFileSync((0, ProjectMetadata_1.projectMetadataPath)(tmpRoot2), 'utf-8');
    let parsed = {};
    try {
        parsed = JSON.parse(raw);
    }
    catch { /* shape check below catches it */ }
    check('file is valid JSON', !!parsed.mode);
    check('has createdAt', typeof parsed.createdAt === 'string');
    check('has updatedAt', typeof parsed.updatedAt === 'string');
    check('has detectedStack array', Array.isArray(parsed.detectedStack));
    check('has recommendedWorkflow string', typeof parsed.recommendedWorkflow === 'string');
}
finally {
    fs.rmSync(tmpRoot2, { recursive: true, force: true });
}
// ── Done ───────────────────────────────────────────────────────────────
console.log('');
console.log(`Results: ${passed} passed, ${failed} failed`);
if (failed > 0) {
    console.error('TEST_FLOW_RUN_CLI_FAIL');
    process.exit(1);
}
console.log('TEST_FLOW_RUN_CLI_OK');
