import { type AgentRunner } from "./agent-runner.js"; import { type ExecutionFitClassification } from "./execution-fit.js"; import { type WorkstreamScope } from "./author-brief.js"; import { type DependencyEdge, type UnmetRequirement } from "./reconcile-dependencies.js"; /** * Author one spec per workstream, each in its own clean agent. * * Authoring every spec in a single session degrades the later ones: workstream * eight is written in a window already carrying one through seven. Spawning a * fresh agent per workstream removes that, but a flat fan-out replaces it with * a worse problem — two dependent workstreams authored in isolation disagree * about the interface between them, and nobody notices until build. * * So the fan-out walks dependency *levels*. Independent workstreams author * concurrently; a workstream that depends on another waits and receives that * one's finished spec. The edge is directional, so there is nothing to * negotiate: the producer decided, and the consumer conforms. * * Discovery is separate from conformance. Every brief carries the full * roster — id, name, and scope of every workstream in the program — because * an author that cannot see a workstream exists will not merely omit the * dependency, it will reimplement that workstream's work. Knowing a node * exists costs a few lines; conforming to it costs its whole spec, and is * only paid for declared dependencies. */ export interface AuthorDeclaration { /** Every workstream this spec consumes output from, as the author saw it. */ dependencies: string[]; /** Dependencies whose full spec the author needed and did not have. */ needs: string[]; /** Requirements no workstream in the roster provides: a coverage gap. */ unmet: string[]; /** Structural reasons this scope cannot be an independently green checkpoint. */ replan: string[]; /** Typed file actions used to render the canonical Files Touched section. */ filesTouched?: Array<{ path: string; action: "NEW" | "MODIFY" | "DELETE"; note?: string; }>; } export interface AuthorWorkstreamOutcome { id: string; status: "authored" | "skipped" | "failed"; reason?: string; summary?: string; declaration: AuthorDeclaration; /** Size of the composed brief; telemetry for context budgeting. */ promptBytes?: number; /** Direct dependencies cut to their roster entry to fit the budget. */ demoted?: string[]; /** Which reconciliation pass authored this; 2 or more means re-authored. */ pass?: number; executionFit?: { classification: ExecutionFitClassification; workingSetTokens: number; lowerBoundTokens: number; upperBoundTokens: number; }; } /** What one reconciliation pass merged, and what it sent back for a re-run. */ export interface ReconciliationRecord { pass: number; added: DependencyEdge[]; unknown: DependencyEdge[]; reauthored: string[]; } export type AuthorOutcome = "COMPLETE" | "FAILED" | "PLANNED" | "ABORTED" | "REQUIRES_REPLAN"; export interface AuthorProgramResult { programId: string; result: AuthorOutcome; reason?: string; /** The resolved authoring agent, when configured. */ agent?: string; /** Workstream IDs grouped into the levels they author in. */ levels: string[][]; outcomes: AuthorWorkstreamOutcome[]; reconciliation: ReconciliationRecord[]; /** Cycles the merged graph would contain; set on REQUIRES_REPLAN. */ cycles?: string[][]; /** Requirements no workstream provides; set on REQUIRES_REPLAN. */ unmet?: UnmetRequirement[]; /** Non-atomic scopes or unsafe migration ordering reported by authors. */ replan?: Array<{ workstreamId: string; reason: string; }>; eventsPath?: string; replanReport?: string; /** Canonical plan/spec artifacts read or written by this run. */ artifactPaths?: string[]; /** Artifacts hidden by the repository's ignore rules. */ ignoredArtifacts?: string[]; } export interface AuthorProgramOptions { cwd: string; programId: string; /** Author only these workstreams; used to re-author after reconciliation. */ only?: string[]; /** Re-author specs that already exist. */ force?: boolean; dryRun?: boolean; agentRunner?: AgentRunner; now?: () => Date; onProgress?: (line: string) => void; } interface ManifestWorkstream { id: string; name: string; taskFile: string; status: string; dependencies: string[]; scope?: { summary?: string; includes?: string[]; excludes?: string[]; }; } /** * The manifest's scope for a workstream, or undefined when it has none. The * summary is what makes a roster entry useful; a workstream carrying only * includes and excludes is treated as unscoped. */ export declare function readScope(raw: ManifestWorkstream["scope"]): WorkstreamScope | undefined; /** * Parse the author's structured tail. Anything that does not fit the contract * is dropped rather than guessed at: a malformed declaration must not invent * a dependency edge that later gets written into the manifest. */ export declare function parseDeclaration(output: string): AuthorDeclaration; /** * Drop the largest unpinned dependency specs until the rest fit the budget. * Largest first keeps the most specs in the brief. Specs explicitly requested * through `needs` are pinned on the reconciliation pass: retrying without the * requested input would be an expensive no-op. */ export declare function fitDependencySpecs(specs: Array<{ id: string; path: string; content: string; }>, budget: number, pinnedIds?: ReadonlySet): { kept: Array<{ id: string; path: string; content: string; }>; demoted: string[]; pinnedOverBudget?: { ids: string[]; chars: number; budget: number; }; }; export declare function authorWorkstreams(options: AuthorProgramOptions): Promise; export {}; //# sourceMappingURL=author-workstreams.d.ts.map