/**
 * Core types for the code conductor.
 *
 * The conductor is a DETERMINISTIC orchestrator: code decides the order, the
 * fan-out, and the fold. Each `agent` step dispatches one Han persona as a
 * bounded single-task worker (see dispatch.ts) — the model never sequences
 * itself, which is the failure mode that sinks loose self-orchestration on
 * weak local models. `code` steps run pure TS (fold / synthesis / transform).
 */

/** The original input to a flow run (e.g. { question, repoPath? }). */
export type FlowInput = Record<string, unknown>;

export interface StepContext {
  /** the original flow input, verbatim */
  readonly input: FlowInput;
  /** completed step results, keyed by step id (full output, no truncation) */
  readonly results: Readonly<Record<string, string>>;
}

export type StepKind = 'agent' | 'code';

export interface Step {
  /** unique id within the flow; other steps depend on it by this id */
  id: string;
  kind: StepKind;
  /** ids that must complete (or skip) before this step runs */
  deps?: string[];
  /** for kind:'agent' — the persona file name under conductor/agents (no .md) */
  agent?: string;
  /**
   * For kind:'agent', returns the worker PROMPT (task + any prior outputs).
   * For kind:'code', returns the step RESULT directly (the fold/transform).
   */
  run: (ctx: StepContext) => string | Promise<string>;
  /** optional guard — when it returns false the step is skipped (e.g. no repo) */
  when?: (ctx: StepContext) => boolean;
}

export interface Flow {
  name: string;
  description: string;
  steps: Step[];
  /** assemble the final artifact from all step results */
  render: (ctx: StepContext) => string;
  /** optional output filename for the artifact, derived from input */
  output?: (ctx: StepContext) => string;
}

export interface RunResult {
  results: Record<string, string>;
  artifact: string;
  outputPath?: string;
}

import type { Contract } from './contracts.js';

/** Han's sizing bands — select how many angles fan out. */
export type Band = 'small' | 'medium' | 'large';

/** One parallel discovery/analysis angle in a spine (a fan-out worker). */
export interface Angle {
  /** step id (also the section label in the report) */
  id: string;
  /** persona dispatched for this angle */
  agent: string;
  /** human label for the report heading */
  label: string;
  /** smallest band at which this angle runs (default 'small') */
  minBand?: Band;
  /** extra guard, e.g. only when a repo was given */
  when?: (ctx: StepContext) => boolean;
  /** build the worker task prompt */
  task: (ctx: StepContext) => string;
}

/**
 * A Han-style skill as data. The factory (spine.ts) turns this into a Flow:
 * angles fan out in parallel → code fold → optional synthesizer agent →
 * adversarial gate → render. This is the shape ~most Han skills share
 * (research, investigate, architectural-analysis, gap-analysis, security…);
 * skills with a genuinely different shape (e.g. code-review's per-finding
 * verify pipeline) get a bespoke Flow instead.
 */
export interface Spine {
  name: string;
  description: string;
  /** the parallel angles (fan-out) */
  angles: Angle[];
  /** optional agent that synthesises the folded angles (e.g. software-architect) */
  synthesizer?: { agent: string; label: string; task: (ctx: StepContext) => string };
  /** the adversarial gate; defaults to adversarial-validator if omitted */
  validator?: { agent: string; label: string; task: (ctx: StepContext) => string };
  /**
   * Han rule contracts injected into every worker brief and the validator
   * charter. Defaults to ['evidence']. Add 'yagni' for flows that PRODUCE a
   * committable artifact (plans, specs, standards, ADRs, runbooks, tests).
   */
  contracts?: Contract[];
}

