import type { LlmClient } from "./llm.js"; /** * Strip the brand header, cost footer, and HTML cost marker out of a * model-emitted markdown body. The calling code adds those around the * output; if the model copies them from prior-turn context, we'd * post duplicates. Cheap regex; safe to no-op when patterns absent. * * Visible for tests. */ export declare function stripModelEmittedDuplicates(body: string): string; import type { ForgeAdapter, Spec } from "@slowcook-ai/core"; export declare const LABEL_CHANGE_OF_MIND = "change-of-mind"; export declare const LABEL_BLOCKED_CONTRADICTION = "blocked-contradiction"; export declare const LABEL_BLOCKED_OVERLAP = "blocked-overlap"; export declare const LABEL_SPEC_SUBMITTED = "spec-submitted"; export declare const LABEL_SPEC_READY = "spec-ready"; export declare const LABEL_NEEDS_REFINEMENT = "needs-refinement"; /** * cli α.44 — applied to an issue when refine has posted a multifurcation * proposal. While present, future refine runs skip the multifurcation * step (the PM is still deciding whether to file the split). PM removes * the label after acting on the proposal. */ export declare const LABEL_MULTIFURCATION_PROPOSED = "slowcook-multifurcation-proposed"; /** * Branded header prepended to every clarifying-question comment so reviewers * can tell at a glance that the comment is agent-authored, even though GitHub * shows the author as "github-actions[bot]". The prefix `### slowcook ·` is * load-bearing — the consumer workflow filters comments starting with it to * avoid re-triggering the agent on its own output. Do not change this literal * without updating rewo's slowcook-refine.yml `if:` condition in lockstep. */ export declare const BRAND_HEADER = "### slowcook \u00B7 refinement agent \uD83C\uDF72\n\n"; export interface RefineContext { issueNumber: number; repoRoot: string; forge: ForgeAdapter; llm: LlmClient; /** Model id for refinement (heavy reasoning). */ refineModel: string; /** Model id for relationship analysis (cheaper). */ relationshipModel: string; /** slowcook CLI version string for the spec's refined_by field. */ cliVersion: string; /** Base branch for PRs (default: "main"). */ baseBranch: string; /** Current UTC time (injectable for tests). */ now: Date; } export type RefineOutcome = { kind: "questions-posted"; commentId: number; } | { kind: "spec-emitted"; specPath: string; prUrl: string; prNumber: number; } | { kind: "overlap-flagged"; conflicting_ids: string[]; } | { kind: "follow-up-noted"; related_ids: string[]; } | { kind: "contradiction-blocked"; conflicting_ids: string[]; } | { kind: "change-of-mind-accepted"; supersedes: string[]; } | { kind: "multifurcation-proposed"; commentId: number; subIssueCount: number; } | { kind: "noop"; reason: string; }; export declare function runRefinement(ctx: RefineContext): Promise; interface ParseContext { storyId: string; issueNumber: number; createdAt: string; cliVersion: string; supersedes: string[]; /** 0.19.0-α.29 — passed through so synthesizeProposalsFromSpec can detect * multi-app vs single-app shape and emit correct route file paths. */ repoRoot?: string; } export type AgentOutput = { kind: "questions"; markdown: string; } | { kind: "spec"; spec: Spec; }; export declare function parseAgentOutput(raw: string, ctx: ParseContext): AgentOutput; export interface ResubmitContext { prNumber: number; /** * 0.11.10+ — when refine was triggered by a `pull_request_review_comment` * event, this is the id of the triggering inline comment. Agent will * post its response as a threaded reply to that comment. Null when the * trigger was an `issue_comment` or `pull_request_review` event. */ reviewCommentId: number | null; repoRoot: string; forge: ForgeAdapter; llm: LlmClient; refineModel: string; cliVersion: string; baseBranch: string; now: Date; } export type ResubmitOutcome = { kind: "resubmitted"; specPath: string; branch: string; } | { /** * 0.11.11+ — /refine was processed on an already-merged spec PR; * amendment went onto a fresh follow-up branch and a new PR was * opened. Refine still responds to the original comment so the PM * sees the handoff without leaving the merged-PR thread. */ kind: "follow-up-opened"; specPath: string; branch: string; followUpPrNumber: number; followUpPrUrl: string; } | { kind: "noop"; reason: string; }; /** * Amend a spec on its existing PR branch based on PR review comments. * * Flow: * 1. Detect story id from current branch * 2. Load current spec YAML from disk * 3. Fetch PR comments — filter to PM replies since the most recent * spec-author commit (agent's own edits don't count as feedback) * 4. Call LLM in amendment mode: old spec + feedback → new spec * 5. Parse emitted YAML, run through spec-body synth + proposals validator * 6. Write updated spec, stage, commit, force-push, post summary comment * * Kept intentionally narrow: no relationship analysis (spec already * exists), no supersede logic (that's refine-proper's job on a new * story), no test manifest changes. */ export declare function runResubmitRefinement(ctx: ResubmitContext): Promise; export {}; //# sourceMappingURL=agent.d.ts.map