Skip to content
Foundry
Esc
↑↓navigate↵open⌘Jpreview
On this page

Revise the candidate

Carry findings into another attempt without losing the issue history.

A revision is another attempt on the same issue. It keeps the plan, branch, original base, and earlier evidence. The new request must explain which findings or review comments to address.

Before requesting another attempt, reproduce the findings and decide which ones warrant changes. Record accepted findings, rejected suggestions with reasons, and unresolved questions. Pass the accepted request to the implementer with the original scope. Do not turn every reviewer preference into a new requirement. The review lead owns this synthesis; the command below records the supplied note without judging it.

Create .foundry/marbles/_factory/revise.ts:

Complete revise.ts
import { step } from "@foundry.sh/marbles";
import { z } from "zod";
import {
  issueInput,
  maxAttempts,
  recordEvent,
  recordSchema,
  requireRecord,
} from "./record";

export const revisionInput = issueInput.extend({ note: z.string().min(1) });
export const revise = step("factory-revision-request")
  .input(revisionInput)
  .output(recordSchema)
  .do(async ({ input, run }) => {
    const work = await requireRecord(input.issue);
    if (
      !(
        work.change &&
        work.plan &&
        ["needs-changes", "declined", "pr-open"].includes(work.status)
      )
    ) {
      throw new Error(
        "Revise a reviewed candidate. Reconcile blocked work before continuing."
      );
    }
    if (work.attempts >= maxAttempts) {
      throw new Error("Attempt limit reached. Record a handoff for a person.");
    }
    return recordEvent(
      {
        ...work,
        decision: undefined,
        status: "planned",
        verification: undefined,
      },
      run.id,
      "revision requested",
      input.note
    );
  });

Replace factory.ts with this final implementation-and-review workflow:

import { workflow } from "@foundry.sh/marbles";
import { implement } from "./_factory/implement";
import { intake } from "./_factory/intake";
import { plan } from "./_factory/plan";
import { issueInput } from "./_factory/record";
import { revise, revisionInput } from "./_factory/revise";
import { verify } from "./_factory/verify";

workflow("factory")
  .input(issueInput)
  .do(({ input }) =>
    verify({ work: implement({ work: plan({ work: intake({}, input) }) }) })
  );

workflow("factory-revise")
  .input(revisionInput)
  .do(({ input }) => verify({ work: implement({ work: revise({}, input) }) }));
marbles roll factory-revise --input '{"issue":42,"note":"Address the failed setup check and the reviewer finding about the test command."}'

The new implementation starts from the previous candidate and uses the same branch. Its explanation and test results get another entry in the work log. The original implementation remains visible.

Stop when progress stalls

The sample allows three implementation attempts, including the first. At that limit, hand the issue to a person with the latest commit, failed checks, unresolved findings, and proposed next action. Retrying an infrastructure failure is a separate decision from asking for another code revision.

Blocked work needs inspection. A crash may have committed a change before recording it. Resolve that mismatch before restarting a stage. A changed requirement or branch base also needs a new plan and fresh verification; do not carry an old approval onto the new commit.

Next: Approve and deliver.

Was this page helpful?