Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion examples/adversarial-implementation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,19 @@ Independent review summaries allow 1500 characters; detailed observations belong
in `findings`. The request states this bound alongside the exact revision and
clause IDs. Ordinary phase and API-foundation summaries retain their own bounds.

A joined reply containing only `{"status":"in_progress"}` gets one completion
turn in the same native conversation, with the same reviewer, resolved model,
effort and exact source revision. The workflow saves the original reply, checks
that the checkout is clean and reserves `completion/` before sending a prompt
with a five-minute deadline. A second progress reply, unavailable conversation,
failed turn or changed source holds the review. Unmarked prose and malformed
verdicts do not authorize a completion turn. Status and reconciliation read the
saved evidence without prompting; a later invocation never starts an unused or
interrupted completion turn.

The completion turn has its own allowance. If it returns a review whose only
defect is summary length, the original formatting allowance still applies.

An otherwise-valid joined review with only an oversized summary can consume the
work item's recorded `maxResponseCorrections` allowance. Each correction stays
in the selected reviewer conversation with the same resolved model and effort.
Expand All @@ -322,7 +335,7 @@ Use `--props-action reconcile` when the selected joined review has a saved
execution but no accepted receipt. Only the selection's attempt qualifies: the
original reviewer, or Astra after a retained transition from an eligible Fable
failure. It checks that attempt's assignment, joined execution, unchanged raw
reply, current schema, clauses and source before creating the missing receipt,
reply, any saved completion, current schema, clauses and source before creating the missing receipt,
and saves a raw reply the execution joined but never wrote. It never shortens text, changes a verdict, repeats
a model call or overwrites a contradictory receipt. Missing or uncertain execution
continues to hold. Status uses this same validation boundary to read receipts.
Expand Down
58 changes: 58 additions & 0 deletions examples/adversarial-implementation/components/Delivery/Finish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
description: 'Finish an incomplete review once in its original conversation, or read that saved turn. Use <Delivery.Finish delivery={delivery} revision={revision} reviewer={reviewer} catalog={catalog} attempt={attempt} dispatch={false} as="reply" />.'
props:
type: object
properties:
delivery: {type: object}
revision: {type: string, pattern: '^[0-9a-f]{40}$'}
reviewer: {type: object}
catalog: {type: object}
attempt: {type: string, pattern: '^/'}
dispatch: {type: boolean}
required: [delivery, revision, reviewer, catalog, attempt, dispatch]
additionalProperties: false
returns: {type: string}
---

The initial turn has returned an explicit progress reply. Reserve the one
completion turn before prompting. Its reply and source evidence stay separate
from the first turn and any later summary corrections.

<Delivery.Schema as="schemas" />
<If condition={props.catalog.state !== "selected" || typeof props.catalog.model !== "string" || !props.catalog.model}><Fail message="The progress reply has no retained selected model. Preserve it and hold." /></If>
<Let as="directory" value={props.attempt + "/completion"} />
<Let as="request" value={{schema:"delivery-review-completion.v1",revision:props.revision,reviewer:props.reviewer,model:props.catalog.model,original:props.attempt + "/raw.txt",timeout:"5m",responseSchema:schemas.review}} />
<Let as="sourceSchema" value={{type:"object",properties:{head:{const:props.revision},clean:{const:true}},required:["head","clean"]}} />
<If condition={props.dispatch}>
<Ticket.Checkout repository={props.delivery.repository} as="before" />
<If condition={before.head !== props.revision || !before.clean}><Fail message="Source changed before review completion. Preserve the first reply and hold." /></If>
<Let as="quoted" value={"'" + directory.replaceAll("'","'\"'\"'") + "'"} />
```bash exec as="reserved"
mkdir -- {quoted}
```
<If condition={reserved.exitCode !== 0}><Fail message="The review completion is already reserved or cannot be reserved. No prompt is repeated." /></If>
<Dir path={directory}><File path="request.json"><Json value={request} /></File><File path="source-before.json"><Json value={before} /></File></Dir>
<Delivery.Turn as="turn"><Agent name={props.reviewer.provider}><Session name={props.reviewer.session} model={props.catalog.model} effort={props.reviewer.effort ?? undefined}><Phase.Session directory={props.delivery.directory + "/sessions"} name={props.reviewer.session} requireExisting={true}><Prompt throwOnError={true} timeout={request.timeout}>
Continue your unfinished independent review of {props.revision} from this conversation. Finish only the checks still needed. Keep source unchanged, run checks in the foreground and join them before returning. Return the final verdict for the original acceptance clauses as one JSON object. If you cannot finish, report the concrete blocker in the verdict. This is the only completion turn.
<Json value={request.responseSchema} />
</Prompt></Phase.Session></Session></Agent></Delivery.Turn>
<Dir path={directory}><File path="outcome.json"><Json value={{reviewer:props.reviewer,catalog:props.catalog,turn}} /></File></Dir>
<If condition={turn.state !== "reply"}><Fail message={"Review completion failed: " + turn.failure + ". Preserve both turns and hold."} /></If>
<Dir path={directory}><File path="raw.txt">{turn.reply}</File></Dir>
<Ticket.Checkout repository={props.delivery.repository} as="after" />
<Dir path={directory}><File path="source-after.json"><Json value={after} /></File></Dir>
</If>
<Ticket.Text path={directory + "/request.json"} as="savedRequest" />
<Parse schema={{type:"object"}} as="packet">{savedRequest}</Parse>
<If condition={JSON.stringify(packet) !== JSON.stringify(request)}><Fail message="The saved completion request differs from the original review." /></If>
<Ticket.Text path={directory + "/outcome.json"} as="savedOutcome" />
<Parse schema={{type:"object"}} as="returned">{savedOutcome}</Parse>
<Ticket.Text path={directory + "/raw.txt"} as="reply" />
<If condition={JSON.stringify(returned.reviewer) !== JSON.stringify(props.reviewer) || JSON.stringify(returned.catalog) !== JSON.stringify(props.catalog) || returned.turn?.state !== "reply" || returned.turn.reply !== reply}><Fail message="The completion reply differs from its retained reviewer outcome." /></If>
<Ticket.Text path={directory + "/source-before.json"} as="beforeText" />
<Ticket.Text path={directory + "/source-after.json"} as="afterText" />
<Parse schema={sourceSchema} as="before">{beforeText}</Parse>
<Parse schema={sourceSchema} as="after">{afterText}</Parse>
<SafeParse schema={schemas.progress} as="progress">{reply}</SafeParse>
<If condition={progress.ok}><Fail message="The reviewer is still unfinished after its one completion turn. Preserve both replies and hold." /></If>
<Return value={reply} />
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ returns: {type: object}
Only the retained selection's attempt can supply the receipt: the original
reviewer, or its replacement after a retained transition from an eligible
failure. A joined reply that was never saved as `raw.txt` is completed from the
attempt's retained outcome.
attempt's retained outcome. If it was a progress reply, only the saved
completion turn can supply the review.

<Delivery.Schema as="schemas" />
<Delivery.Attempts delivery={props.delivery} revision={props.revision} as="read" />
Expand Down
29 changes: 18 additions & 11 deletions examples/adversarial-implementation/components/Delivery/Response.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
description: 'Shorten only an oversized independent-review summary, or validate its saved correction chain without prompting. Use <Delivery.Response delivery={delivery} revision={revision} reviewer={reviewer} attempt={attempt} raw={raw} dispatch={false} as="response" />.'
description: 'Finish a review after an explicit progress reply, repair an oversized summary, or validate the saved replies without prompting. Use <Delivery.Response delivery={delivery} revision={revision} reviewer={reviewer} attempt={attempt} raw={raw} dispatch={false} as="response" />.'
props:
type: object
properties:
Expand All @@ -14,32 +14,39 @@ props:
returns: {type: object}
---

The original review stays unchanged. Each extra call belongs to the same
reviewer, model and native conversation, and consumes the recorded response
allowance before dispatch. Reconciliation reads that chain and sends no prompt.
A progress reply can use one separate completion turn. Formatting corrections
start with the completed review and consume only the recorded formatting
allowance. Reconciliation reads both records and sends no prompt.

<Delivery.Schema as="schemas" />
<Ticket.Text path={props.attempt + "/assignment.json"} as="assignmentText" />
<Parse schema={{type:"object"}} as="assignment">{assignmentText}</Parse>
<Let as="limit" value={assignment.maxResponseCorrections ?? 0} />
<If condition={!Number.isInteger(limit) || limit < 0 || limit > 3 || limit !== (props.delivery.maxResponseCorrections ?? 0)}><Fail message="The review response allowance differs from its recorded assignment." /></If>
<Delivery.Validate text={props.raw} revision={props.revision} acceptance={props.delivery.policy.acceptance} as="checked" />
<Ticket.Text path={props.attempt + "/outcome.json"} as="outcomeText" />
<Parse schema={{type:"object"}} as="originalOutcome">{outcomeText}</Parse>
<Let as="catalog" value={originalOutcome.catalog} />
<If condition={originalOutcome.turn?.state !== "reply" || originalOutcome.turn.reply !== props.raw || JSON.stringify(originalOutcome.reviewer) !== JSON.stringify(props.reviewer)}><Fail message="The original review does not match its joined outcome." /></If>
<Let as="reviewRaw" value={props.raw} />
<Let as="initialRawPath" value={props.attempt + "/raw.txt"} />
<SafeParse schema={schemas.progress} as="progress">{props.raw}</SafeParse>
<If condition={progress.ok}>
<Delivery.Finish delivery={props.delivery} revision={props.revision} reviewer={props.reviewer} catalog={catalog} attempt={props.attempt} dispatch={props.dispatch} as="reviewRaw" />
<Let as="initialRawPath" value={props.attempt + "/completion/raw.txt"} />
</If>
<Delivery.Validate text={reviewRaw} revision={props.revision} acceptance={props.delivery.policy.acceptance} as="checked" />
<Let as="original" value={checked.result ?? null} />
<Let as="rawPath" value={props.attempt + "/raw.txt"} />
<Let as="rawPath" value={initialRawPath} />
<Let as="round" value={0} />
<If condition={!checked.ok && props.dispatch}>
<Dir path={props.attempt}><File path="response-rejection.json"><Json value={checked} /></File></Dir>
</If>
<Ticket.Text path={props.attempt + "/outcome.json"} as="outcomeText" />
<Parse schema={{type:"object"}} as="originalOutcome">{outcomeText}</Parse>
<Let as="catalog" value={originalOutcome.catalog} />
<If condition={originalOutcome.turn?.state !== "reply" || originalOutcome.turn.reply !== props.raw || JSON.stringify(originalOutcome.reviewer) !== JSON.stringify(props.reviewer)}><Fail message="The original review does not match its joined outcome." /></If>
<Loop max={3}>
<If condition={checked.ok || !checked.repairable || round >= limit}><Break /></If>
<Let as="round" value={round + 1} />
<Let as="directory" value={props.attempt + "/response-corrections/" + String(round).padStart(4,"0")} />
<Let as="repairSchema" value={{...schemas.review,properties:Object.fromEntries(Object.entries(schemas.review.properties).map(([key,value]) => [key,key === "summary" ? value : {const:original[key]}]))}} />
<Let as="packet" value={{schema:"delivery-summary-correction.v1",revision:props.revision,reviewer:props.reviewer,model:catalog.model,ordinal:round,remaining:limit-round,original:props.attempt + "/raw.txt",result:original,responseSchema:repairSchema}} />
<Let as="packet" value={{schema:"delivery-summary-correction.v1",revision:props.revision,reviewer:props.reviewer,model:catalog.model,ordinal:round,remaining:limit-round,original:initialRawPath,result:original,responseSchema:repairSchema}} />
<If condition={JSON.stringify(packet).length > 64000}><Fail message="The review correction packet exceeds 64000 characters; no prompt was sent." /></If>
<If condition={props.dispatch}>
<Ticket.Checkout repository={props.delivery.repository} as="before" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,19 @@ mkdir -- {quotedReplacement}
<Delivery.Reconcile delivery={props.delivery} revision={props.revision} publish={true} as="receipt" />
<Return value={receipt} />
<Else>
<If condition={read.selection.chain === "single"}><Fail message="Independent review did not return a joined result. Preserve this attempt and reconcile the original call; do not launch another reviewer." /></If>
<If condition={read.selection.chain === "single" && read.state.hold === null}>
<Let as="unfinished" value={false} />
<If condition={read.state.attempts[0]?.state === "held"}>
<Dir path={read.directory}><Glob include={["raw.txt"]} as="replies" /></Dir>
<If condition={replies.length !== 0}>
<Delivery.Schema as="schemas" />
<Ticket.Text path={read.directory + "/raw.txt"} as="raw" />
<SafeParse schema={schemas.progress} as="progress">{raw}</SafeParse>
<Let as="unfinished" value={progress.ok} />
</If>
</If>
<If condition={!unfinished}><Fail message="Independent review did not return a joined result. Preserve this attempt and reconcile the original call; do not launch another reviewer." /></If>
</If>
<Delivery.Hold delivery={props.delivery} revision={props.revision} as="held" />
<Return value={held} />
</Else>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ Original captured source text:

Keep summary within {schemas.review.properties.summary.maxLength} characters, including spaces and newlines. Put detailed observations in findings; do not compress the whole report into summary. Check revision against the assigned full SHA and acceptance against the recorded clause IDs before returning.

Return exactly one JSON object satisfying this schema. acceptance lists every clause ID actually examined. pass requires no blocking finding. The workflow supplies work, reviewer, attempt and completion metadata.
If you must end the turn before the verdict is ready, return exactly {JSON.stringify(schemas.progress.const)} on its own. The workflow can then give this same conversation one chance to finish.

Otherwise, return exactly one JSON object satisfying this schema. acceptance lists every clause ID actually examined. pass requires no blocking finding. The workflow supplies work, reviewer, attempt and completion metadata.
<Json value={schemas.review} />
</Let>
<If condition={instructions.length > 64000}><Fail message="The complete independent-review request exceeds 64000 characters. Prepare concise accepted inputs before dispatch." /></If>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ returns: {type: object}

<Let as="text" value={{type:"string",minLength:1}} />
<Let as="revision" value={{type:"string",pattern:"^[0-9a-f]{40}$"}} />
<Return value={{policy:{type:"object",properties:{repository:{type:"string",pattern:"^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$"},reviewer:{type:"object",properties:{provider:{enum:["claude","codex"]},model:text,effort:{type:["string","null"]},session:text},required:["provider","model","effort","session"],additionalProperties:false},acceptance:{type:"array",minItems:1,items:{type:"object",properties:{id:text,source:text,requirement:text},required:["id","source","requirement"],additionalProperties:false}}},required:["repository","reviewer","acceptance"],additionalProperties:false},review:{type:"object",properties:{revision,verdict:{enum:["pass","changes_required","blocked"]},summary:{type:"string",minLength:1,maxLength:1500},acceptance:{type:"array",items:{type:"string"},uniqueItems:true},findings:{type:"array",items:{type:"object",properties:{blocking:{type:"boolean"},description:text},required:["blocking","description"],additionalProperties:false}}},required:["revision","verdict","summary","acceptance","findings"],additionalProperties:false}}} />
<Return value={{progress:{const:{status:"in_progress"}},policy:{type:"object",properties:{repository:{type:"string",pattern:"^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$"},reviewer:{type:"object",properties:{provider:{enum:["claude","codex"]},model:text,effort:{type:["string","null"]},session:text},required:["provider","model","effort","session"],additionalProperties:false},acceptance:{type:"array",minItems:1,items:{type:"object",properties:{id:text,source:text,requirement:text},required:["id","source","requirement"],additionalProperties:false}}},required:["repository","reviewer","acceptance"],additionalProperties:false},review:{type:"object",properties:{revision,verdict:{enum:["pass","changes_required","blocked"]},summary:{type:"string",minLength:1,maxLength:1500},acceptance:{type:"array",items:{type:"string"},uniqueItems:true},findings:{type:"array",items:{type:"object",properties:{blocking:{type:"boolean"},description:text},required:["blocking","description"],additionalProperties:false}}},required:["revision","verdict","summary","acceptance","findings"],additionalProperties:false}}} />
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export const holdSchema = z.strictObject({
schema: z.literal("delivery-review-hold.v1"),
work: z.string().min(1),
revision: z.string().regex(/^[0-9a-f]{40}$/),
chain: z.enum(["fable-astra", "astra-final"]),
chain: selectionSchema.shape.chain,
summary: z.string().min(1),
unknown: z.string().min(1),
attempts: z.array(attemptSchema).min(1).max(2),
Expand Down
7 changes: 4 additions & 3 deletions examples/adversarial-implementation/delivery.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ props:
---

Read the original delivery record and perform only its computed next action.
A status read starts no agent. Review preserves every attempt and never repeats
one: an unavailable Fable reviewer is replaced once by Codex Astra, and a review
nobody could complete is held and asked about. Readiness permits no merge.
A status read starts no agent. An explicit progress reply gets one continuation
in the same conversation. An unavailable Fable reviewer is replaced once by
Codex Astra. The workflow preserves each attempt and asks about a review it
cannot complete. Readiness permits no merge.

<Ticket.Text path={props.record} as="recordText" />
<Parse schema={{type:"object",properties:{work:{type:"string"},repository:{type:"string",pattern:"^/"},directory:{type:"string",pattern:"^/"},policy:{type:"object"},required:{const:["independent-review","required-ci","main-health"]}},required:["work","repository","directory","policy","required"]}} as="delivery">{recordText}</Parse>
Expand Down
Loading
Loading