mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-10-08 03:10:26 +00:00
refactor(types): remove stage status compatibility
This commit is contained in:
parent
ba529c23f9
commit
d65c1fa635
72 changed files with 552 additions and 549 deletions
|
|
@ -51,7 +51,7 @@ export function emptyStateCopy(kind: EmptyKind): string {
|
|||
/// The full RunStatus enum (per fabro-types/src/status.rs) is:
|
||||
/// submitted, queued, starting, running, blocked, paused, removing,
|
||||
/// succeeded, failed, dead, archived
|
||||
/// partial_success is a stage status, not a run status.
|
||||
/// partially_succeeded is a stage outcome, not a run status.
|
||||
export function deriveEmptyKind(args: {
|
||||
runStatus: string | undefined;
|
||||
totalChanged: number;
|
||||
|
|
|
|||
|
|
@ -16,16 +16,16 @@
|
|||
|
||||
| Path | Direct dependency | Why it still exists | Required remediation track |
|
||||
| --- | --- | --- | --- |
|
||||
| `lib/crates/fabro-cli/src/commands/pr/create.rs` | `outcome::StageStatus`, `pull_request::maybe_open_pull_request` | CLI still reconstructs store state and runs PR creation logic from the workflow pipeline directly. | Replace with a server API, or extract PR orchestration into a non-engine shared service crate plus API. |
|
||||
| `lib/crates/fabro-cli/src/commands/pr/create.rs` | `StageOutcome`, `pull_request::maybe_open_pull_request` | CLI still reconstructs store state and runs PR creation logic from the workflow pipeline directly. | Replace with a server API, or extract PR orchestration into a non-engine shared service crate plus API. |
|
||||
| `lib/crates/fabro-cli/src/commands/run/runner.rs` | `artifact_snapshot::CapturedArtifactInfo`, `artifact_upload::{ArtifactSink, StageArtifactUploader}`, `event::{Emitter, RunEventSink}`, `operations::{self, StartServices}`, `run_control::RunControlState`, `runtime_store::{RunStoreBackend, RunStoreHandle}` | Hidden worker subprocess path still lives inside the CLI crate and embeds the workflow engine directly. | Re-home worker/runtime code outside the user CLI surface, ideally into a dedicated worker crate or binary. |
|
||||
| `lib/crates/fabro-cli/src/manifest_builder.rs` | `git::{GitSyncStatus, head_sha, sync_status}` | Manifest submission still relies on git helper logic that happens to live in `fabro_workflow`. | Extract git-sync inspection helpers into a non-workflow shared crate/module. |
|
||||
| `lib/crates/fabro-cli/src/server_client.rs` | `artifact_snapshot::CapturedArtifactInfo` | The upload client reuses a workflow-owned artifact snapshot DTO. | Extract shared artifact snapshot DTOs into `fabro-store`, `fabro-types`, or a dedicated shared crate. |
|
||||
| `lib/crates/fabro-cli/src/commands/runs/inspect.rs` | `run_status::RunStatus` | CLI output types still depend on engine-owned run status enums. | Extract shared status types into `fabro-types` or switch to API-generated/public store types. |
|
||||
| `lib/crates/fabro-cli/src/commands/runs/list.rs` | `run_status::RunStatus` | List rendering still depends on engine-owned run status enums. | Extract shared status types into `fabro-types` or switch to API-generated/public store types. |
|
||||
| `lib/crates/fabro-cli/src/commands/run/attach.rs` | `outcome::StageStatus`, `run_status::RunStatus` | Attach/replay logic still formats engine-owned terminal status types directly. | Extract shared run/conclusion status types into `fabro-types`. |
|
||||
| `lib/crates/fabro-cli/src/commands/run/output.rs` | `outcome::StageStatus`, `records::Conclusion` | Human-readable completion output still consumes workflow-owned conclusion/status records. | Extract shared conclusion/status DTOs into `fabro-types` or `fabro-store`. |
|
||||
| `lib/crates/fabro-cli/src/commands/run/attach.rs` | `StageOutcome`, `run_status::RunStatus` | Attach/replay logic still formats engine-owned terminal status types directly. | Extract shared run/conclusion status types into `fabro-types`. |
|
||||
| `lib/crates/fabro-cli/src/commands/run/output.rs` | `StageOutcome`, `records::Conclusion` | Human-readable completion output still consumes workflow-owned conclusion/status records. | Extract shared conclusion/status DTOs into `fabro-types` or `fabro-store`. |
|
||||
| `lib/crates/fabro-cli/src/commands/run/wait.rs` | `records::Conclusion`, `run_status::RunStatus` | Wait output still depends on workflow-owned status/conclusion records. | Extract shared conclusion/status DTOs into `fabro-types` or `fabro-store`. |
|
||||
| `lib/crates/fabro-cli/src/commands/run/run_progress/stage_display.rs` | `outcome::{StageStatus, format_cost}` | Progress UI still depends on workflow-owned stage status and cost-formatting helper code. | Extract shared stage status types into `fabro-types` and move formatting helpers into `fabro-util`. |
|
||||
| `lib/crates/fabro-cli/src/commands/run/run_progress/stage_display.rs` | `StageOutcome`, `format_cost` | Progress UI still depends on shared stage outcome and workflow-owned cost-formatting helper code. | Move formatting helpers into `fabro-util`. |
|
||||
| `lib/crates/fabro-cli/src/commands/run/run_progress/info_display.rs` | `event::RunNoticeLevel` | Progress UI still formats workflow-owned notice levels directly. | Extract shared notice/event enums into `fabro-types`. |
|
||||
| `lib/crates/fabro-cli/src/commands/run/run_progress/event.rs` | `event::RunNoticeLevel` | Progress event translation still depends on workflow-owned notice levels. | Extract shared notice/event enums into `fabro-types`. |
|
||||
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
| Path | Direct dependency | Why it still exists | Suggested handling |
|
||||
| --- | --- | --- | --- |
|
||||
| `lib/crates/fabro-cli/src/commands/dump.rs` test module | `event::{Event, append_event}` | Unit tests synthesize workflow events directly. | Low priority; keep until a lighter-weight event fixture helper exists. |
|
||||
| `lib/crates/fabro-cli/src/commands/run/wait.rs` test module | `outcome::StageStatus`, `records::Conclusion`, `run_status::RunStatusRecord` | Output tests construct workflow-owned records directly. | Replace with shared fixture builders once status/conclusion DTOs move out. |
|
||||
| `lib/crates/fabro-cli/src/commands/run/wait.rs` test module | `StageOutcome`, `records::Conclusion`, `run_status::RunStatusRecord` | Output tests construct workflow-owned records directly. | Replace with shared fixture builders once conclusion DTOs move out. |
|
||||
| `lib/crates/fabro-cli/src/commands/run/run_progress/mod.rs` test module | `event::{Event, RunNoticeLevel, to_run_event, to_run_event_at}`, `outcome::billed_model_usage_from_llm` | Progress tests build engine events directly. | Replace with shared event fixture helpers after event DTO extraction. |
|
||||
| `lib/crates/fabro-cli/src/commands/run/run_progress/event.rs` test module | `event::{Event, to_run_event}` | Event rendering tests depend on engine event constructors. | Replace with shared event fixture helpers after event DTO extraction. |
|
||||
| `lib/crates/fabro-cli/src/commands/run/runner.rs` test module | `artifact_upload::StageArtifactUploader` | Worker tests still reach into workflow upload internals. | Keep with worker re-home work; not worth separating first. |
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ Emitted when the workflow run finishes successfully (or with partial success).
|
|||
"properties": {
|
||||
"duration_ms": 45000,
|
||||
"artifact_count": 3,
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"total_cost": 0.15,
|
||||
"final_git_commit_sha": "def456...",
|
||||
"usage": {
|
||||
|
|
@ -143,7 +143,7 @@ Emitted when the workflow run finishes successfully (or with partial success).
|
|||
|----------|------|-------------|
|
||||
| `duration_ms` | number | Total run duration in milliseconds |
|
||||
| `artifact_count` | number | Number of artifacts produced |
|
||||
| `status` | string | Final status (`"success"`, `"fail"`, `"partial_success"`) |
|
||||
| `status` | string | Final stage outcome (`"succeeded"`, `"failed"`, `"partially_succeeded"`, `"skipped"`) |
|
||||
| `total_cost` | number? | Aggregate cost in USD |
|
||||
| `final_git_commit_sha` | string? | Final HEAD SHA |
|
||||
| `usage` | object? | Aggregate token usage |
|
||||
|
|
@ -327,7 +327,7 @@ Emitted when a workflow node finishes execution.
|
|||
"properties": {
|
||||
"index": 1,
|
||||
"duration_ms": 8000,
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"preferred_label": "tests_pass",
|
||||
"suggested_next_ids": ["review"],
|
||||
"usage": {
|
||||
|
|
@ -362,7 +362,7 @@ Emitted when a workflow node finishes execution.
|
|||
|----------|------|-------------|
|
||||
| `index` | number | Stage execution order index |
|
||||
| `duration_ms` | number | Stage duration in milliseconds |
|
||||
| `status` | string | `"success"`, `"fail"`, `"skipped"`, `"partial_success"`, `"retry"` |
|
||||
| `status` | string | `"succeeded"`, `"failed"`, `"skipped"`, `"partially_succeeded"` |
|
||||
| `preferred_label` | string? | Edge label hint for routing |
|
||||
| `suggested_next_ids` | string[] | Suggested successor node ids |
|
||||
| `usage` | object? | Token usage for this stage |
|
||||
|
|
@ -522,7 +522,7 @@ Emitted when a parallel branch finishes.
|
|||
"properties": {
|
||||
"index": 0,
|
||||
"duration_ms": 5000,
|
||||
"status": "success"
|
||||
"status": "succeeded"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -640,7 +640,7 @@ Emitted after a checkpoint is saved.
|
|||
"node_id": "code",
|
||||
"node_label": "code",
|
||||
"properties": {
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"git_commit_sha": "abc123...",
|
||||
"diff": "diff --git a/src/lib.rs b/src/lib.rs\n..."
|
||||
}
|
||||
|
|
@ -821,7 +821,7 @@ Emitted when the engine selects the next edge to traverse.
|
|||
"reason": "condition",
|
||||
"preferred_label": "tests_pass",
|
||||
"suggested_next_ids": ["review"],
|
||||
"stage_status": "success",
|
||||
"stage_status": "succeeded",
|
||||
"is_jump": false
|
||||
}
|
||||
}
|
||||
|
|
@ -1490,7 +1490,7 @@ Emitted when the agent fails over to a different LLM provider/model.
|
|||
"node_label": "pipeline",
|
||||
"properties": {
|
||||
"steps_executed": 4,
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"duration_ms": 25000
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ Agent and prompt nodes can influence which edge is taken after they complete by
|
|||
|
||||
| Field | Effect |
|
||||
|---|---|
|
||||
| `outcome` | Sets the node status: `success`, `fail`, `partial_success`, `retry`, or `skipped` |
|
||||
| `failure_reason` | When `outcome` is `fail`, provides a structured failure message |
|
||||
| `outcome` | Sets the node outcome: `succeeded`, `failed`, `partially_succeeded`, or `skipped` |
|
||||
| `failure_reason` | When `outcome` is `failed`, provides a structured failure message |
|
||||
| `preferred_next_label` | Matched against edge labels to select the next node |
|
||||
| `suggested_next_ids` | Ordered list of preferred target node IDs |
|
||||
| `context_updates` | Key-value pairs merged into the run context |
|
||||
|
|
@ -110,7 +110,7 @@ The tracked paths are stored as `files_touched` on the stage outcome:
|
|||
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"files_touched": ["src/main.rs", "tests/api_test.rs", "README.md"]
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -5635,7 +5635,7 @@ components:
|
|||
properties:
|
||||
force:
|
||||
type: boolean
|
||||
description: Create the pull request even if the run did not finish with success or partial_success.
|
||||
description: Create the pull request even if the run did not finish with succeeded or partially_succeeded.
|
||||
example: false
|
||||
model:
|
||||
type: ["string", "null"]
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ The engine walks the graph starting from the start node. For each node it:
|
|||
|
||||
1. **Resolves context** — Assembles the node's input from prior stage outputs, run context, and the workflow goal. The [fidelity](/workflows/stages-and-nodes#agent) setting controls how much prior context is included.
|
||||
2. **Dispatches to a handler** — Each [node type](/workflows/stages-and-nodes) has a handler: the agent handler runs an LLM tool loop, the command handler runs a shell script, the human handler waits for input, and so on.
|
||||
3. **Collects the outcome** — The handler returns a [status](/execution/outcomes) (`success`, `fail`, `partial_success`, `retry`, or `skipped`), optional routing directives, and any context updates.
|
||||
3. **Collects the outcome** — The handler returns a [stage outcome](/execution/outcomes) (`succeeded`, `failed`, `partially_succeeded`, or `skipped`), optional routing directives, and any context updates.
|
||||
4. **Selects the next edge** — Fabro evaluates outgoing edges using conditions, labels, and weights to pick the next node. See [Transitions](/workflows/transitions).
|
||||
5. **Checkpoints** — After each stage, Fabro writes a checkpoint so the run can be resumed if interrupted.
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ The engine sets several keys automatically. These are prefixed with `internal.`
|
|||
| `internal.thread_id` | Thread ID for shared-conversation nodes (or null) |
|
||||
| `internal.node_visit_count` | How many times the current node has been visited |
|
||||
| `internal.retry_count.{node_id}` | Number of retry attempts used by a node |
|
||||
| `outcome` | Status of the last completed stage (`success`, `fail`, etc.) |
|
||||
| `outcome` | Status of the last completed stage (`succeeded`, `failed`, etc.) |
|
||||
| `failure_class` | Classification of the last failure (if any) |
|
||||
| `failure_signature` | Deduplication signature for the last failure |
|
||||
| `preferred_label` | Label selected by a human gate or agent routing directive |
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ The engine resolves retry configuration in this order:
|
|||
|
||||
Not all errors trigger a node retry. The handler's `should_retry` check must return true — generally, only errors classified as transient are retried. Deterministic errors (auth failures, bad config) fail immediately without consuming retry attempts.
|
||||
|
||||
When a handler returns a `Retry` status instead of `Fail`, retries always proceed (if attempts remain). If retries are exhausted and the node has `allow_partial=true`, the outcome is promoted to `PartialSuccess` instead of failing. See [Node Outcomes — Retry loop](/execution/outcomes#retry-loop) for a detailed flow diagram.
|
||||
When a handler reports a retryable failure, retries always proceed if attempts remain. If retries are exhausted and the node has `allow_partial=true`, the outcome is promoted to `partially_succeeded` instead of `failed`. See [Node Outcomes — Retry loop](/execution/outcomes#retry-loop) for a detailed flow diagram.
|
||||
|
||||
## Model fallbacks
|
||||
|
||||
|
|
@ -234,7 +234,7 @@ Loop restart edges also have their own separate circuit breaker (`restart_failur
|
|||
|
||||
## Goal gates
|
||||
|
||||
Goal gates are quality checkpoints that are enforced when the workflow reaches an exit node. A node marked with `goal_gate=true` must have completed with `success` or `partial_success` — otherwise the run cannot finish. See [Node Outcomes — Goal gate interaction](/execution/outcomes#goal-gate-interaction) for how `partial_success` and `allow_partial` interact with goal gates.
|
||||
Goal gates are quality checkpoints that are enforced when the workflow reaches an exit node. A node marked with `goal_gate=true` must have completed with `succeeded` or `partially_succeeded` — otherwise the run cannot finish. See [Node Outcomes — Goal gate interaction](/execution/outcomes#goal-gate-interaction) for how `partially_succeeded` and `allow_partial` interact with goal gates.
|
||||
|
||||
```dot
|
||||
verify [shape=box, goal_gate="true"]
|
||||
|
|
|
|||
|
|
@ -1,40 +1,39 @@
|
|||
---
|
||||
title: "Node Outcomes"
|
||||
description: "The five stage statuses and the attributes that control them"
|
||||
description: "The four stage outcomes and the attributes that control them"
|
||||
---
|
||||
|
||||
Every node execution produces an **outcome** containing a status that drives edge routing, retry logic, and goal gate checks. This page defines the five statuses and the attributes that influence them.
|
||||
Every node execution produces an **outcome** that drives edge routing, retry logic, and goal gate checks. This page defines the four externally visible outcomes and the attributes that influence them.
|
||||
|
||||
## The five statuses
|
||||
## The four outcomes
|
||||
|
||||
| Status | Meaning |
|
||||
| Outcome | Meaning |
|
||||
|---|---|
|
||||
| `success` | The handler completed normally |
|
||||
| `fail` | The handler encountered an unrecoverable error |
|
||||
| `partial_success` | The handler did not fully succeed but produced usable results — typically from retries exhausted with `allow_partial=true` |
|
||||
| `retry` | The handler wants to re-execute — consumed by the [retry loop](#retry-loop) and never appears in edge conditions |
|
||||
| `succeeded` | The handler completed normally |
|
||||
| `failed` | The handler encountered an unrecoverable error |
|
||||
| `partially_succeeded` | The handler did not fully succeed but produced usable results — typically from retries exhausted with `allow_partial=true` |
|
||||
| `skipped` | The node was not executed (e.g. a branch not taken in a parallel fan-out) |
|
||||
|
||||
<Note>
|
||||
`retry` is internal to the engine. It triggers re-execution inside the retry loop and is never visible in edge `condition` expressions. The four externally-visible statuses are `success`, `fail`, `partial_success`, and `skipped`.
|
||||
Retry intent is internal to the engine. It triggers re-execution inside the retry loop and is never visible in edge `condition` expressions. Retryable failures emit `stage.retrying` events while the node is still active, then finish as one of the four outcomes above.
|
||||
</Note>
|
||||
|
||||
## How handlers produce statuses
|
||||
## How handlers produce outcomes
|
||||
|
||||
Each node type has its own rules for which statuses it can return:
|
||||
Each node type has its own rules for which outcomes it can return:
|
||||
|
||||
| Handler | Produces | Conditions |
|
||||
|---|---|---|
|
||||
| **Command** | `success`, `fail` | `success` when exit code is 0; `fail` otherwise |
|
||||
| **Agent / Prompt** | `success`, `fail`, `partial_success`, `retry`, `skipped` | Defaults to `success`. The LLM can set any status via a [routing directive](/agents/outputs#routing-directives) JSON object in its response. Backend errors produce `retry` (if retryable) or `fail`. |
|
||||
| **Parallel** | `success`, `partial_success`, `fail` | Depends on the `join_policy`. `wait_all`: `success` if no failures, `partial_success` if some branches failed. `first_success`: `success` if threshold met, else `fail`. |
|
||||
| **Human** | `success` | Always succeeds — the user's selection becomes a routing signal via `preferred_label` |
|
||||
| **Conditional** | `success` | Always succeeds — routing is handled by the engine's edge selection |
|
||||
| **Start / Exit / Wait** | `success` | Always succeed |
|
||||
| **Command** | `succeeded`, `failed` | `succeeded` when exit code is 0; `failed` otherwise |
|
||||
| **Agent / Prompt** | `succeeded`, `failed`, `partially_succeeded`, `skipped` | Defaults to `succeeded`. The LLM can set any outcome via a [routing directive](/agents/outputs#routing-directives) JSON object in its response. Backend errors request retry when retryable or finish as `failed`. |
|
||||
| **Parallel** | `succeeded`, `partially_succeeded`, `failed` | Depends on the `join_policy`. `wait_all`: `succeeded` if no failures, `partially_succeeded` if some branches failed. `first_success`: `succeeded` if threshold met, else `failed`. |
|
||||
| **Human** | `succeeded` | Always succeeds — the user's selection becomes a routing signal via `preferred_label` |
|
||||
| **Conditional** | `succeeded` | Always succeeds — routing is handled by the engine's edge selection |
|
||||
| **Start / Exit / Wait** | `succeeded` | Always succeed |
|
||||
|
||||
## Retry loop
|
||||
|
||||
When a handler returns `retry` status, the engine enters the retry loop. If retry attempts remain (per the node's [retry policy](/execution/failures#retry-policies)), the handler re-executes after a backoff delay. If attempts are exhausted, the final status depends on `allow_partial`:
|
||||
When a handler returns a retryable failure, the engine enters the retry loop. If retry attempts remain (per the node's [retry policy](/execution/failures#retry-policies)), the handler re-executes after a backoff delay. If attempts are exhausted, the final outcome depends on `allow_partial`:
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
|
|
@ -42,10 +41,10 @@ When a handler returns `retry` status, the engine enters the retry loop. If retr
|
|||
└──────┬──────┘
|
||||
│
|
||||
▼
|
||||
┌──────────┐ success/fail/
|
||||
│ Status? │───partial_success/───▶ Done (use as-is)
|
||||
└────┬─────┘ skipped
|
||||
│ retry
|
||||
┌──────────┐ succeeded / failed /
|
||||
│Outcome? │─── partially_succeeded / skipped ──▶ Done (use as-is)
|
||||
└────┬─────┘
|
||||
│ retryable failure
|
||||
▼
|
||||
┌──────────────┐ yes ┌──────────────┐
|
||||
│ Attempts │─────────▶│ Backoff + │──┐
|
||||
|
|
@ -58,15 +57,14 @@ When a handler returns `retry` status, the engine enters the retry loop. If retr
|
|||
└──────┬───┬───┘ │ "Run handler")
|
||||
yes │ │ no │
|
||||
▼ ▼
|
||||
partial_ fail
|
||||
success
|
||||
partially_succeeded failed
|
||||
```
|
||||
|
||||
Handler errors follow the same loop: retryable errors (transient infrastructure) re-execute if attempts remain; non-retryable errors (authentication, bad config) fail immediately without consuming retry attempts.
|
||||
|
||||
## `allow_partial`
|
||||
|
||||
When `allow_partial=true` and the retry loop exhausts all attempts on a `retry` status, the outcome is promoted to `partial_success` instead of `fail`. This lets the workflow continue past nodes that could not fully succeed.
|
||||
When `allow_partial=true` and the retry loop exhausts all attempts on a retryable failure, the outcome is promoted to `partially_succeeded` instead of `failed`. This lets the workflow continue past nodes that could not fully succeed.
|
||||
|
||||
| Attribute | Type | Default |
|
||||
|---|---|---|
|
||||
|
|
@ -81,13 +79,13 @@ implement [
|
|||
]
|
||||
```
|
||||
|
||||
In this example, if the agent returns `retry` and all 5 standard-policy attempts are used, the node finishes with `partial_success` rather than failing the run.
|
||||
In this example, if the agent returns a retryable failure and all 5 standard-policy attempts are used, the node finishes with `partially_succeeded` rather than failing the run.
|
||||
|
||||
See [Retry policies](/execution/failures#retry-policies) for the available presets and backoff settings.
|
||||
|
||||
## `auto_status`
|
||||
|
||||
When `auto_status=true`, any non-`success` and non-`skipped` status is silently overridden to `success` after the handler completes. This is applied after the retry loop, so retries still happen normally — only the final outcome is overridden.
|
||||
When `auto_status=true`, any non-`succeeded` and non-`skipped` outcome is silently overridden to `succeeded` after the handler completes. This is applied after the retry loop, so retries still happen normally — only the final outcome is overridden.
|
||||
|
||||
| Attribute | Type | Default |
|
||||
|---|---|---|
|
||||
|
|
@ -106,9 +104,9 @@ Use `auto_status` for nodes whose failure should never block the workflow — op
|
|||
|
||||
## Goal gate interaction
|
||||
|
||||
Nodes marked with `goal_gate=true` are checked when the workflow reaches the exit node. A goal gate is satisfied if its last outcome was `success` **or** `partial_success`. Any other status (`fail`, `skipped`) causes the workflow to fail, even though execution reached the exit.
|
||||
Nodes marked with `goal_gate=true` are checked when the workflow reaches the exit node. A goal gate is satisfied if its last outcome was `succeeded` **or** `partially_succeeded`. Any other outcome (`failed`, `skipped`) causes the workflow to fail, even though execution reached the exit.
|
||||
|
||||
This means `allow_partial=true` on a goal gate node lets the gate pass even if the node exhausted its retries — the promoted `partial_success` counts as passing.
|
||||
This means `allow_partial=true` on a goal gate node lets the gate pass even if the node exhausted its retries — the promoted `partially_succeeded` outcome counts as passing.
|
||||
|
||||
See [Goal gates](/execution/failures#goal-gates) for retry target resolution and failure behavior.
|
||||
|
||||
|
|
|
|||
|
|
@ -591,7 +591,7 @@ fabro pr create [OPTIONS] <RUN_ID>
|
|||
|
||||
| Option | Description |
|
||||
| --- | --- |
|
||||
| `-f, --force` | Create PR even if the run status is not success/partial_success |
|
||||
| `-f, --force` | Create PR even if the run status is not succeeded/partially_succeeded |
|
||||
| `--model <model>` | LLM model for generating PR description |
|
||||
| `--server <server>` | Fabro server target: http(s) URL or absolute Unix socket path |
|
||||
|
||||
|
|
|
|||
|
|
@ -189,9 +189,9 @@ Start nodes can also be identified by ID (`start` or `Start`). Exit nodes can be
|
|||
| `retry_policy` | String | Named preset: `none`, `standard`, `aggressive`, `linear`, `patient` |
|
||||
| `retry_target` | String | Node ID to jump to on retry |
|
||||
| `fallback_retry_target` | String | Fallback node ID if primary `retry_target` is unreachable |
|
||||
| `goal_gate` | Boolean | When `true`, workflow fails if this node didn't finish with `success` or `partial_success`. See [Node Outcomes](/execution/outcomes#goal-gate-interaction). |
|
||||
| `auto_status` | Boolean | When `true`, overrides any non-`success`/non-`skipped` status to `success` after the handler completes. See [Node Outcomes](/execution/outcomes#auto_status). |
|
||||
| `allow_partial` | Boolean | When `true` and retries are exhausted on a `retry` status, promotes the outcome to `partial_success` instead of `fail`. Default `false`. See [Node Outcomes](/execution/outcomes#allow_partial). |
|
||||
| `goal_gate` | Boolean | When `true`, workflow fails if this node didn't finish with `succeeded` or `partially_succeeded`. See [Node Outcomes](/execution/outcomes#goal-gate-interaction). |
|
||||
| `auto_status` | Boolean | When `true`, overrides any non-`succeeded`/non-`skipped` outcome to `succeeded` after the handler completes. See [Node Outcomes](/execution/outcomes#auto_status). |
|
||||
| `allow_partial` | Boolean | When `true` and retries are exhausted on a retry-requesting failure, promotes the outcome to `partially_succeeded` instead of `failed`. Default `false`. See [Node Outcomes](/execution/outcomes#allow_partial). |
|
||||
| `selection` | String | Edge tiebreaking strategy: `deterministic` (default) or `random` (weighted-random). Cannot be combined with conditional edges. |
|
||||
|
||||
### Agent and prompt nodes
|
||||
|
|
@ -271,7 +271,7 @@ Op ::= '=' | '!=' | '>' | '<' | '>=' | '<='
|
|||
|
||||
| Key | Resolves to |
|
||||
|---|---|
|
||||
| `outcome` | Stage status: `success`, `fail`, `partial_success`, or `skipped`. See [Node Outcomes](/execution/outcomes#outcome-in-edge-conditions). |
|
||||
| `outcome` | Stage outcome: `succeeded`, `failed`, `partially_succeeded`, or `skipped`. See [Node Outcomes](/execution/outcomes#outcome-in-edge-conditions). |
|
||||
| `preferred_label` | Label selected by a human gate or LLM routing directive |
|
||||
| `context.KEY` | Value from the run context |
|
||||
| `KEY` | Shorthand for context lookup (without the `context.` prefix) |
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ After each node finishes, Fabro must decide which edge to follow to the next nod
|
|||
|
||||
## How transitions work
|
||||
|
||||
When a node completes, it produces an **outcome** with a [status](/execution/outcomes) (`success`, `fail`, `partial_success`, or `skipped`) and optional signals like a preferred label or suggested next node. Fabro evaluates the outgoing edges in a fixed priority order:
|
||||
When a node completes, it produces an **outcome** with a [stage outcome](/execution/outcomes) (`succeeded`, `failed`, `partially_succeeded`, or `skipped`) and optional signals like a preferred label or suggested next node. Fabro evaluates the outgoing edges in a fixed priority order:
|
||||
|
||||
1. **Condition match** — Edges with a `condition` attribute are evaluated first. If one or more conditions match, the edge with the highest `weight` wins (lexical tiebreak on target node ID).
|
||||
2. **Preferred label** — If the node's outcome includes a preferred label (e.g. from a human gate selection), the edge whose `label` matches is chosen.
|
||||
|
|
@ -37,7 +37,7 @@ gate -> implement [label="Fix", condition="outcome=failed"]
|
|||
|
||||
| Key | Resolves to |
|
||||
|---|---|
|
||||
| `outcome` | The stage status: `success`, `fail`, `partial_success`, or `skipped`. See [Node Outcomes](/execution/outcomes). |
|
||||
| `outcome` | The stage outcome: `succeeded`, `failed`, `partially_succeeded`, or `skipped`. See [Node Outcomes](/execution/outcomes). |
|
||||
| `preferred_label` | The label selected by a human gate |
|
||||
| `context.KEY` | A value from the run context (e.g. `context.tests_passed`) |
|
||||
| `KEY` | Shorthand for context lookup (without the `context.` prefix) |
|
||||
|
|
|
|||
|
|
@ -767,7 +767,7 @@ pub(crate) struct PrCreateArgs {
|
|||
/// LLM model for generating PR description
|
||||
#[arg(long)]
|
||||
pub(crate) model: Option<String>,
|
||||
/// Create PR even if the run status is not success/partial_success
|
||||
/// Create PR even if the run status is not succeeded/partially_succeeded
|
||||
#[arg(short, long)]
|
||||
pub(crate) force: bool,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ const ATTACH_PREMATURE_EOF_MESSAGE: &str = "Attach stream ended before terminal
|
|||
|
||||
/// Attach to a running (or finished) workflow run, rendering progress live.
|
||||
///
|
||||
/// Returns exit code 0 for success/partial_success, 1 otherwise.
|
||||
/// Returns exit code 0 for succeeded/partially_succeeded, 1 otherwise.
|
||||
#[cfg(test)]
|
||||
pub(crate) async fn attach_run(
|
||||
run_dir: &Path,
|
||||
|
|
@ -455,7 +455,7 @@ fn state_exit_code(state: &server_client::RunProjection) -> Option<ExitCode> {
|
|||
fn event_exit_code(event: &EventEnvelope) -> Option<ExitCode> {
|
||||
match &event.event.body {
|
||||
EventBody::RunCompleted(props) => Some(
|
||||
if props.status == "success" || props.status == "partial_success" {
|
||||
if props.status == "succeeded" || props.status == "partially_succeeded" {
|
||||
ExitCode::from(0)
|
||||
} else {
|
||||
ExitCode::from(1)
|
||||
|
|
|
|||
|
|
@ -374,11 +374,11 @@ fn format_event_pretty_value(envelope: &serde_json::Value, styles: &Styles) -> O
|
|||
let duration = format_duration_ms(prop_field(envelope, "duration_ms"));
|
||||
let status_str = match prop_str_field(envelope, "status") {
|
||||
Some(status) if !status.is_empty() => status,
|
||||
_ => "success",
|
||||
_ => "succeeded",
|
||||
};
|
||||
let status_upper = status_str.to_uppercase();
|
||||
let status_style = match status_str {
|
||||
"success" | "partial_success" => &styles.bold_green,
|
||||
"succeeded" | "partially_succeeded" => &styles.bold_green,
|
||||
_ => &styles.bold_red,
|
||||
};
|
||||
let cost = format_cost(
|
||||
|
|
@ -386,13 +386,17 @@ fn format_event_pretty_value(envelope: &serde_json::Value, styles: &Styles) -> O
|
|||
.or_else(|| prop_field(envelope, "total_cost")),
|
||||
);
|
||||
|
||||
let mut lines = vec![format!(
|
||||
"{} {} {} {}",
|
||||
let mut summary = format!(
|
||||
"{} {} {}",
|
||||
styles.dim.apply_to(&ts),
|
||||
status_style.apply_to(format!("\u{2713} {status_upper}")),
|
||||
styles.bold.apply_to(&duration),
|
||||
styles.dim.apply_to(&cost),
|
||||
)];
|
||||
);
|
||||
if !cost.is_empty() {
|
||||
write!(summary, " {}", styles.dim.apply_to(&cost)).expect("write to string");
|
||||
}
|
||||
|
||||
let mut lines = vec![summary];
|
||||
|
||||
if let Some(billing) =
|
||||
prop_field(envelope, "billing").or_else(|| prop_field(envelope, "usage"))
|
||||
|
|
@ -968,7 +972,7 @@ mod tests {
|
|||
#[test]
|
||||
fn pretty_stage_completed() {
|
||||
let styles = no_color_styles();
|
||||
let line = r#"{"ts":"2026-01-01T14:23:15Z","event":"stage.completed","node_label":"plan","properties":{"duration_ms":8000,"status":"success","usage":{"cost":0.12,"input_tokens":10000,"output_tokens":5200}}}"#;
|
||||
let line = r#"{"ts":"2026-01-01T14:23:15Z","event":"stage.completed","node_label":"plan","properties":{"duration_ms":8000,"status":"succeeded","usage":{"cost":0.12,"input_tokens":10000,"output_tokens":5200}}}"#;
|
||||
let result = format_event_pretty(line, &styles).unwrap();
|
||||
assert!(result.contains("plan"), "got: {result}");
|
||||
assert!(result.contains("$0.12"), "got: {result}");
|
||||
|
|
@ -1047,9 +1051,9 @@ mod tests {
|
|||
#[test]
|
||||
fn pretty_workflow_run_completed() {
|
||||
let styles = no_color_styles();
|
||||
let line = r#"{"ts":"2026-01-01T14:23:32Z","run_id":"abc123","event":"run.completed","properties":{"duration_ms":25000,"status":"success","total_usd_micros":570000,"billing":{"input_tokens":5000,"output_tokens":2000,"total_tokens":7000,"cache_read_tokens":3000,"cache_write_tokens":500,"reasoning_tokens":800}}}"#;
|
||||
let line = r#"{"ts":"2026-01-01T14:23:32Z","run_id":"abc123","event":"run.completed","properties":{"duration_ms":25000,"status":"succeeded","total_usd_micros":570000,"billing":{"input_tokens":5000,"output_tokens":2000,"total_tokens":7000,"cache_read_tokens":3000,"cache_write_tokens":500,"reasoning_tokens":800}}}"#;
|
||||
let result = format_event_pretty(line, &styles).unwrap();
|
||||
assert!(result.contains("SUCCESS"), "got: {result}");
|
||||
assert!(result.contains("SUCCEEDED"), "got: {result}");
|
||||
assert!(result.contains("25s"), "got: {result}");
|
||||
assert!(result.contains("$0.57"), "got: {result}");
|
||||
assert!(result.contains("7.0k toks"), "got: {result}");
|
||||
|
|
@ -1063,7 +1067,7 @@ mod tests {
|
|||
let styles = no_color_styles();
|
||||
let line = r#"{"ts":"2026-01-01T14:23:32Z","run_id":"abc123","event":"run.completed","properties":{"duration_ms":25000,"total_cost":0.57}}"#;
|
||||
let result = format_event_pretty(line, &styles).unwrap();
|
||||
assert!(result.contains("SUCCESS"), "got: {result}");
|
||||
assert!(result.contains("SUCCEEDED"), "got: {result}");
|
||||
assert!(result.contains("25s"), "got: {result}");
|
||||
assert!(result.contains("$0.57"), "got: {result}");
|
||||
assert!(!result.contains("Tokens:"), "got: {result}");
|
||||
|
|
@ -1072,7 +1076,7 @@ mod tests {
|
|||
#[test]
|
||||
fn pretty_workflow_run_completed_fail_status() {
|
||||
let styles = no_color_styles();
|
||||
let line = r#"{"ts":"2026-01-01T14:23:32Z","event":"run.completed","properties":{"duration_ms":25000,"status":"fail"}}"#;
|
||||
let line = r#"{"ts":"2026-01-01T14:23:32Z","event":"run.completed","properties":{"duration_ms":25000,"status":"failed"}}"#;
|
||||
let result = format_event_pretty(line, &styles).unwrap();
|
||||
assert!(result.contains("FAIL"), "got: {result}");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -509,7 +509,7 @@ mod tests {
|
|||
reason: "condition".into(),
|
||||
preferred_label: None,
|
||||
suggested_next_ids: Vec::new(),
|
||||
stage_status: "success".into(),
|
||||
stage_status: "succeeded".into(),
|
||||
is_jump: false,
|
||||
});
|
||||
|
||||
|
|
@ -532,7 +532,7 @@ mod tests {
|
|||
name: "Plan".into(),
|
||||
index: 0,
|
||||
duration_ms: 5000,
|
||||
status: "success".into(),
|
||||
status: "succeeded".into(),
|
||||
preferred_label: None,
|
||||
suggested_next_ids: Vec::new(),
|
||||
billing: None,
|
||||
|
|
|
|||
|
|
@ -552,7 +552,7 @@ mod tests {
|
|||
name: name.into(),
|
||||
index: 0,
|
||||
duration_ms: 5000,
|
||||
status: "success".into(),
|
||||
status: "succeeded".into(),
|
||||
preferred_label: None,
|
||||
suggested_next_ids: Vec::new(),
|
||||
billing: Some(billed_model_usage_from_llm(
|
||||
|
|
@ -616,7 +616,7 @@ mod tests {
|
|||
branch: "security".into(),
|
||||
index: 0,
|
||||
duration_ms: 2000,
|
||||
status: "success".into(),
|
||||
status: "succeeded".into(),
|
||||
head_sha: None,
|
||||
});
|
||||
let stage = &ui.stage.active_stages["fork1"];
|
||||
|
|
@ -717,7 +717,7 @@ mod tests {
|
|||
reason: "condition".into(),
|
||||
preferred_label: None,
|
||||
suggested_next_ids: Vec::new(),
|
||||
stage_status: "success".into(),
|
||||
stage_status: "succeeded".into(),
|
||||
is_jump: false,
|
||||
},
|
||||
Event::StageRetrying {
|
||||
|
|
@ -912,7 +912,7 @@ mod tests {
|
|||
reason: "condition".into(),
|
||||
preferred_label: None,
|
||||
suggested_next_ids: Vec::new(),
|
||||
stage_status: "success".into(),
|
||||
stage_status: "succeeded".into(),
|
||||
is_jump: false,
|
||||
});
|
||||
emit(&mut ui, Event::StageRetrying {
|
||||
|
|
@ -1117,7 +1117,7 @@ mod tests {
|
|||
branch: "security".into(),
|
||||
index: 0,
|
||||
duration_ms: 500,
|
||||
status: "success".into(),
|
||||
status: "succeeded".into(),
|
||||
head_sha: None,
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ impl StageDisplay {
|
|||
return;
|
||||
};
|
||||
|
||||
let succeeded = matches!(status, "success" | "partial_success");
|
||||
let succeeded = matches!(status, "succeeded" | "partially_succeeded");
|
||||
entry.status = if succeeded {
|
||||
ToolCallStatus::Succeeded
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -698,7 +698,7 @@ mod tests {
|
|||
worker_title_phase_for_event(&EventBody::RunCompleted(RunCompletedProps {
|
||||
duration_ms: 10,
|
||||
artifact_count: 0,
|
||||
status: "success".to_string(),
|
||||
status: "succeeded".to_string(),
|
||||
reason: SuccessReason::Completed,
|
||||
total_usd_micros: None,
|
||||
final_git_commit_sha: None,
|
||||
|
|
|
|||
|
|
@ -806,7 +806,7 @@ fn attach_json_errors_without_prompting_for_human_input() {
|
|||
"node_visits": {
|
||||
"start": 1
|
||||
},
|
||||
"status": "success"
|
||||
"status": "succeeded"
|
||||
},
|
||||
"run_id": "[ULID]",
|
||||
"stage_id": "start@1",
|
||||
|
|
@ -824,7 +824,7 @@ fn attach_json_errors_without_prompting_for_human_input() {
|
|||
"from_node": "start",
|
||||
"is_jump": false,
|
||||
"reason": "unconditional",
|
||||
"stage_status": "success",
|
||||
"stage_status": "succeeded",
|
||||
"to_node": "approve"
|
||||
},
|
||||
"run_id": "[ULID]",
|
||||
|
|
@ -860,14 +860,14 @@ fn attach_json_errors_without_prompting_for_human_input() {
|
|||
"next_node_id": "approve",
|
||||
"node_outcomes": {
|
||||
"start": {
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"usage": null
|
||||
}
|
||||
},
|
||||
"node_visits": {
|
||||
"start": 1
|
||||
},
|
||||
"status": "success"
|
||||
"status": "succeeded"
|
||||
},
|
||||
"run_id": "[ULID]",
|
||||
"stage_id": "start@1",
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ fn inspect_completed_run_shows_run_start_conclusion_checkpoint() {
|
|||
"has_start_time": true
|
||||
},
|
||||
"conclusion": {
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"duration_ms": "[DURATION_MS]",
|
||||
"stage_count": null
|
||||
},
|
||||
|
|
@ -263,7 +263,7 @@ fn inspect_completed_run_reads_store_without_disk_metadata_files() {
|
|||
"has_start_time": true
|
||||
},
|
||||
"conclusion": {
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"duration_ms": "[DURATION_MS]",
|
||||
"stage_count": null
|
||||
},
|
||||
|
|
@ -322,7 +322,7 @@ fn inspect_git_backed_run_exposes_checkpoint_and_sandbox_state() {
|
|||
"base_sha": "[SHA]"
|
||||
},
|
||||
"conclusion": {
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"duration_ms": "[DURATION_MS]",
|
||||
"final_git_commit_sha": "[SHA]",
|
||||
"stage_count": null
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ fn logs_pretty_formats_small_run() {
|
|||
[CLOCK] → exit unconditional
|
||||
[CLOCK] ▶ Exit
|
||||
[CLOCK] ✓ Exit [DURATION]
|
||||
[CLOCK] ✓ SUCCESS [DURATION]
|
||||
[CLOCK] ✓ SUCCEEDED [DURATION]
|
||||
----- stderr -----
|
||||
");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ fn help() {
|
|||
--server <SERVER> Fabro server target: http(s) URL or absolute Unix socket path [env: FABRO_SERVER=]
|
||||
--debug Enable DEBUG-level logging (default is INFO) [env: FABRO_DEBUG=]
|
||||
--model <MODEL> LLM model for generating PR description
|
||||
-f, --force Create PR even if the run status is not success/partial_success
|
||||
-f, --force Create PR even if the run status is not succeeded/partially_succeeded
|
||||
--no-upgrade-check Disable automatic upgrade check [env: FABRO_NO_UPGRADE_CHECK=true]
|
||||
--quiet Suppress non-essential output [env: FABRO_QUIET=]
|
||||
--verbose Enable verbose output [env: FABRO_VERBOSE=]
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ fn remote_run_state_response() -> serde_json::Value {
|
|||
"checkpoints": [],
|
||||
"conclusion": {
|
||||
"timestamp": "2026-04-05T12:00:01Z",
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"duration_ms": 12,
|
||||
"stages": [],
|
||||
"billing": null,
|
||||
|
|
@ -77,7 +77,7 @@ fn run_completed_event(run_id: &str) -> serde_json::Value {
|
|||
"properties": {
|
||||
"duration_ms": 12,
|
||||
"artifact_count": 0,
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"reason": "completed"
|
||||
}
|
||||
})
|
||||
|
|
@ -703,7 +703,7 @@ fn dry_run_simple() {
|
|||
|
||||
=== Run Result ===
|
||||
Run: [ULID]
|
||||
Status: SUCCESS
|
||||
Status: SUCCEEDED
|
||||
Duration: [DURATION]
|
||||
|
||||
=== Output ===
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ fn assert_worker_succeeded(run_dir: &std::path::Path, stdout: &[u8]) {
|
|||
let events = stored_worker_events(run_dir);
|
||||
assert!(events.iter().any(|event| matches!(
|
||||
&event.body,
|
||||
EventBody::RunCompleted(props) if props.status == "success"
|
||||
EventBody::RunCompleted(props) if props.status == "succeeded"
|
||||
)));
|
||||
}
|
||||
|
||||
|
|
@ -656,7 +656,7 @@ digraph Test {
|
|||
"run_dir": null,
|
||||
"start_time": "[TIMESTAMP]",
|
||||
"conclusion_timestamp": "[TIMESTAMP]",
|
||||
"conclusion_status": "success"
|
||||
"conclusion_status": "succeeded"
|
||||
}
|
||||
"#);
|
||||
|
||||
|
|
|
|||
|
|
@ -1042,7 +1042,7 @@ async fn append_seeded_simple_completion_events(
|
|||
serde_json::json!({
|
||||
"duration_ms": 123,
|
||||
"artifact_count": 0,
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"reason": "completed",
|
||||
"total_usd_micros": null,
|
||||
"final_git_commit_sha": null,
|
||||
|
|
@ -1157,7 +1157,14 @@ async fn append_seeded_git_completion_events(
|
|||
&run.run_id,
|
||||
Some("start"),
|
||||
"checkpoint.completed",
|
||||
checkpoint_properties("success", "start", &["start"], Some("step_one"), None, None),
|
||||
checkpoint_properties(
|
||||
"succeeded",
|
||||
"start",
|
||||
&["start"],
|
||||
Some("step_one"),
|
||||
None,
|
||||
None,
|
||||
),
|
||||
)
|
||||
.await;
|
||||
append_run_event(
|
||||
|
|
@ -1201,7 +1208,7 @@ async fn append_seeded_git_completion_events(
|
|||
serde_json::json!({
|
||||
"duration_ms": 456,
|
||||
"artifact_count": 0,
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"reason": "completed",
|
||||
"total_usd_micros": null,
|
||||
"final_git_commit_sha": step_two_sha,
|
||||
|
|
@ -1262,7 +1269,7 @@ async fn append_seeded_git_noop_events(
|
|||
serde_json::json!({
|
||||
"duration_ms": 123,
|
||||
"artifact_count": 0,
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"reason": "completed",
|
||||
"total_usd_micros": null,
|
||||
"final_git_commit_sha": base_sha,
|
||||
|
|
@ -1322,7 +1329,7 @@ async fn append_seeded_artifact_run_events(
|
|||
serde_json::json!({
|
||||
"duration_ms": 123,
|
||||
"artifact_count": 6,
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"reason": "completed",
|
||||
"total_usd_micros": null,
|
||||
"final_git_commit_sha": null,
|
||||
|
|
@ -1415,7 +1422,7 @@ async fn append_seeded_edge(
|
|||
"reason": "unconditional",
|
||||
"preferred_label": null,
|
||||
"suggested_next_ids": [],
|
||||
"stage_status": "success",
|
||||
"stage_status": "succeeded",
|
||||
"is_jump": false,
|
||||
}),
|
||||
)
|
||||
|
|
@ -1470,7 +1477,7 @@ fn stage_completed_properties(index: usize, response: Option<&str>) -> serde_jso
|
|||
serde_json::json!({
|
||||
"index": index,
|
||||
"duration_ms": 1,
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"preferred_label": null,
|
||||
"suggested_next_ids": [],
|
||||
"billing": null,
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ fn run_sse_body(run_id: &str) -> String {
|
|||
"properties": {
|
||||
"duration_ms": 12,
|
||||
"artifact_count": 0,
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"reason": "completed"
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ fn scenario_agent_linear(sandbox: &str) {
|
|||
|
||||
let run_dir = find_run_dir(&context);
|
||||
let conclusion = read_conclusion(&run_dir);
|
||||
assert_eq!(conclusion["status"].as_str(), Some("success"));
|
||||
assert_eq!(conclusion["status"].as_str(), Some("succeeded"));
|
||||
|
||||
let nodes = completed_nodes(&run_dir);
|
||||
assert!(
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ fn scenario_command_agent_mixed(sandbox: &str) {
|
|||
|
||||
let run_dir = find_run_dir(&context);
|
||||
let conclusion = read_conclusion(&run_dir);
|
||||
assert_eq!(conclusion["status"].as_str(), Some("success"));
|
||||
assert_eq!(conclusion["status"].as_str(), Some("succeeded"));
|
||||
|
||||
let nodes = completed_nodes(&run_dir);
|
||||
assert!(
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ fn scenario_command_pipeline(sandbox: &str) {
|
|||
let conclusion = read_conclusion(&run_dir);
|
||||
assert_eq!(
|
||||
conclusion["status"].as_str(),
|
||||
Some("success"),
|
||||
"conclusion status should be success"
|
||||
Some("succeeded"),
|
||||
"conclusion status should be succeeded"
|
||||
);
|
||||
|
||||
let nodes = completed_nodes(&run_dir);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ fn scenario_conditional_branching(sandbox: &str) {
|
|||
|
||||
let run_dir = find_run_dir(&context);
|
||||
let conclusion = read_conclusion(&run_dir);
|
||||
assert_eq!(conclusion["status"].as_str(), Some("success"));
|
||||
assert_eq!(conclusion["status"].as_str(), Some("succeeded"));
|
||||
|
||||
let nodes = completed_nodes(&run_dir);
|
||||
assert!(
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ fn dry_run_branching() {
|
|||
|
||||
=== Run Result ===
|
||||
Run: [ULID]
|
||||
Status: SUCCESS
|
||||
Status: SUCCEEDED
|
||||
Duration: [DURATION]
|
||||
|
||||
=== Output ===
|
||||
|
|
@ -63,7 +63,7 @@ fn dry_run_conditions() {
|
|||
|
||||
=== Run Result ===
|
||||
Run: [ULID]
|
||||
Status: SUCCESS
|
||||
Status: SUCCEEDED
|
||||
Duration: [DURATION]
|
||||
|
||||
=== Output ===
|
||||
|
|
@ -97,7 +97,7 @@ fn dry_run_parallel() {
|
|||
|
||||
=== Run Result ===
|
||||
Run: [ULID]
|
||||
Status: SUCCESS
|
||||
Status: SUCCEEDED
|
||||
Duration: [DURATION]
|
||||
|
||||
=== Output ===
|
||||
|
|
@ -131,7 +131,7 @@ fn dry_run_styled() {
|
|||
|
||||
=== Run Result ===
|
||||
Run: [ULID]
|
||||
Status: SUCCESS
|
||||
Status: SUCCEEDED
|
||||
Duration: [DURATION]
|
||||
|
||||
=== Output ===
|
||||
|
|
@ -163,7 +163,7 @@ fn dry_run_legacy_tool() {
|
|||
|
||||
=== Run Result ===
|
||||
Run: [ULID]
|
||||
Status: SUCCESS
|
||||
Status: SUCCEEDED
|
||||
Duration: [DURATION]
|
||||
");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ fn scenario_full_stack(sandbox: &str) {
|
|||
let conclusion = read_conclusion(&run_dir);
|
||||
assert_eq!(
|
||||
conclusion["status"].as_str(),
|
||||
Some("success"),
|
||||
Some("succeeded"),
|
||||
"conclusion: {conclusion}"
|
||||
);
|
||||
assert!(
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ model = "{model}"
|
|||
run_success_output(cmd).await;
|
||||
}
|
||||
|
||||
assert_eq!(conclusion_status(&context), "success");
|
||||
assert_eq!(conclusion_status(&context), "succeeded");
|
||||
}
|
||||
|
||||
#[fabro_macros::e2e_test(twin, live("ANTHROPIC_API_KEY"))]
|
||||
|
|
@ -230,7 +230,7 @@ max_tool_rounds = 1
|
|||
run_success_output(cmd).await;
|
||||
}
|
||||
|
||||
assert_eq!(conclusion_status(&context), "success");
|
||||
assert_eq!(conclusion_status(&context), "succeeded");
|
||||
}
|
||||
|
||||
#[fabro_macros::e2e_test(twin, live("ANTHROPIC_API_KEY"))]
|
||||
|
|
@ -287,7 +287,7 @@ max_tool_rounds = 5
|
|||
run_success_output(cmd).await;
|
||||
}
|
||||
|
||||
assert_eq!(conclusion_status(&context), "success");
|
||||
assert_eq!(conclusion_status(&context), "succeeded");
|
||||
}
|
||||
|
||||
#[fabro_macros::e2e_test(twin, live("ANTHROPIC_API_KEY"))]
|
||||
|
|
@ -346,5 +346,5 @@ async fn arc_e2e_with_real_llm() {
|
|||
"Hello from LLM",
|
||||
"workflow should create the expected file"
|
||||
);
|
||||
assert_eq!(conclusion_status(&context), "success");
|
||||
assert_eq!(conclusion_status(&context), "succeeded");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ fn scenario_human_gate(sandbox: &str) {
|
|||
|
||||
let run_dir = find_run_dir(&context);
|
||||
let conclusion = read_conclusion(&run_dir);
|
||||
assert_eq!(conclusion["status"].as_str(), Some("success"));
|
||||
assert_eq!(conclusion["status"].as_str(), Some("succeeded"));
|
||||
|
||||
let nodes = completed_nodes(&run_dir);
|
||||
assert!(
|
||||
|
|
|
|||
|
|
@ -443,7 +443,7 @@ mod tests {
|
|||
use crate::context::Context;
|
||||
use crate::error::HandlerErrorDetail;
|
||||
use crate::lifecycle::RunLifecycle;
|
||||
use crate::outcome::{StageOutcome, StageStatus};
|
||||
use crate::outcome::StageOutcome;
|
||||
use crate::retry::{BackoffPolicy, RetryPolicy};
|
||||
use crate::test_fixtures::*;
|
||||
|
||||
|
|
@ -470,7 +470,7 @@ mod tests {
|
|||
let result = run_linear(&["start", "work", "end"], Arc::new(AlwaysSucceedHandler))
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Success);
|
||||
assert_eq!(result.status, StageOutcome::Succeeded);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -514,7 +514,7 @@ mod tests {
|
|||
let g = TestGraph::new(
|
||||
vec![
|
||||
TestNode::new("work"),
|
||||
TestNode::terminal("end").with_goal_gate("work", StageStatus::Success),
|
||||
TestNode::terminal("end").with_goal_gate("work", StageOutcome::Succeeded),
|
||||
],
|
||||
vec![TestEdge::new("work", "end")],
|
||||
"work",
|
||||
|
|
@ -524,7 +524,7 @@ mod tests {
|
|||
ExecutorBuilder::new(Arc::new(AlwaysSucceedHandler) as Arc<dyn NodeHandler<TestGraph>>)
|
||||
.build();
|
||||
let (result, _) = executor.run(&g, state).await.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Success);
|
||||
assert_eq!(result.status, StageOutcome::Succeeded);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -535,7 +535,7 @@ mod tests {
|
|||
let g = TestGraph::new(
|
||||
vec![
|
||||
TestNode::new("work"),
|
||||
TestNode::terminal("end").with_goal_gate("work", StageStatus::Success),
|
||||
TestNode::terminal("end").with_goal_gate("work", StageOutcome::Succeeded),
|
||||
],
|
||||
vec![TestEdge::new("work", "end")],
|
||||
"work",
|
||||
|
|
@ -550,7 +550,7 @@ mod tests {
|
|||
let executor =
|
||||
ExecutorBuilder::new(handler.clone() as Arc<dyn NodeHandler<TestGraph>>).build();
|
||||
let (result, _) = executor.run(&g, state).await.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Success);
|
||||
assert_eq!(result.status, StageOutcome::Succeeded);
|
||||
assert_eq!(handler.calls(), 2);
|
||||
}
|
||||
|
||||
|
|
@ -559,7 +559,7 @@ mod tests {
|
|||
let g = TestGraph::new(
|
||||
vec![
|
||||
TestNode::new("work"),
|
||||
TestNode::terminal("end").with_goal_gate("work", StageStatus::Success),
|
||||
TestNode::terminal("end").with_goal_gate("work", StageOutcome::Succeeded),
|
||||
],
|
||||
vec![TestEdge::new("work", "end")],
|
||||
"work",
|
||||
|
|
@ -571,7 +571,9 @@ mod tests {
|
|||
)
|
||||
.build();
|
||||
let (result, _) = executor.run(&g, state).await.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Fail);
|
||||
assert_eq!(result.status, StageOutcome::Failed {
|
||||
retry_requested: false,
|
||||
});
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -726,7 +728,7 @@ mod tests {
|
|||
.build();
|
||||
let (result, _) = executor.run(&g, state).await.unwrap();
|
||||
// Ends at "bad" terminal with success (goal gates pass since no gates defined)
|
||||
assert_eq!(result.status, StageStatus::Success);
|
||||
assert_eq!(result.status, StageOutcome::Succeeded);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -748,7 +750,7 @@ mod tests {
|
|||
ExecutorBuilder::new(Arc::new(AlwaysSucceedHandler) as Arc<dyn NodeHandler<TestGraph>>)
|
||||
.build();
|
||||
let (result, _) = executor.run(&g, state).await.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Success);
|
||||
assert_eq!(result.status, StageOutcome::Succeeded);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -781,7 +783,7 @@ mod tests {
|
|||
let executor =
|
||||
ExecutorBuilder::new(Arc::new(JumpHandler) as Arc<dyn NodeHandler<TestGraph>>).build();
|
||||
let (result, _) = executor.run(&g, state).await.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Success);
|
||||
assert_eq!(result.status, StageOutcome::Succeeded);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -817,7 +819,7 @@ mod tests {
|
|||
.max_node_visits(5)
|
||||
.build();
|
||||
let (result, _) = executor.run(&g, state).await.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Success);
|
||||
assert_eq!(result.status, StageOutcome::Succeeded);
|
||||
assert_eq!(handler.calls(), 4);
|
||||
}
|
||||
|
||||
|
|
@ -881,7 +883,9 @@ mod tests {
|
|||
)
|
||||
.build();
|
||||
let (result, _) = executor.run(&g, state).await.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Fail);
|
||||
assert_eq!(result.status, StageOutcome::Failed {
|
||||
retry_requested: false,
|
||||
});
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -893,7 +897,7 @@ mod tests {
|
|||
ExecutorBuilder::new(Arc::new(AlwaysSucceedHandler) as Arc<dyn NodeHandler<TestGraph>>)
|
||||
.build();
|
||||
let (result, _) = executor.run(&g, state).await.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Success);
|
||||
assert_eq!(result.status, StageOutcome::Succeeded);
|
||||
}
|
||||
|
||||
// ---- Step 11: Cancellation ----
|
||||
|
|
@ -1003,7 +1007,7 @@ mod tests {
|
|||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Success);
|
||||
assert_eq!(result.status, StageOutcome::Succeeded);
|
||||
assert_eq!(handler.calls(), 3);
|
||||
}
|
||||
|
||||
|
|
@ -1041,7 +1045,7 @@ mod tests {
|
|||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Success);
|
||||
assert_eq!(result.status, StageOutcome::Succeeded);
|
||||
assert_eq!(handler.calls(), 3);
|
||||
}
|
||||
|
||||
|
|
@ -1119,20 +1123,20 @@ mod tests {
|
|||
}
|
||||
fn on_retries_exhausted(&self, _n: &TestNode, _last: Outcome) -> Outcome {
|
||||
Outcome {
|
||||
status: StageStatus::PartialSuccess,
|
||||
status: StageOutcome::PartiallySucceeded,
|
||||
notes: Some("exhausted".into()),
|
||||
..Outcome::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
// No outgoing edges from "start" so PartialSuccess becomes the run result
|
||||
// No outgoing edges from "start" so PartiallySucceeded becomes the run result.
|
||||
let g = TestGraph::new(vec![TestNode::new("start")], vec![], "start");
|
||||
let state = ExecutionState::new(&g).unwrap();
|
||||
let executor =
|
||||
ExecutorBuilder::new(Arc::new(ExhaustedHandler) as Arc<dyn NodeHandler<TestGraph>>)
|
||||
.build();
|
||||
let (result, _) = executor.run(&g, state).await.unwrap();
|
||||
assert_eq!(result.status, StageStatus::PartialSuccess);
|
||||
assert_eq!(result.status, StageOutcome::PartiallySucceeded);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -1303,7 +1307,7 @@ mod tests {
|
|||
.lifecycle(Box::new(SkipOnSecondAttempt(call_count_clone)))
|
||||
.build();
|
||||
let (result, _) = executor.run(&g, state).await.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Success); // overall run succeeds via terminal
|
||||
assert_eq!(result.status, StageOutcome::Succeeded); // overall run succeeds via terminal
|
||||
assert_eq!(handler.calls(), 1); // handler only called once
|
||||
assert_eq!(call_count.load(Ordering::Relaxed), 2); // before_attempt called twice
|
||||
}
|
||||
|
|
@ -1338,7 +1342,7 @@ mod tests {
|
|||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Success);
|
||||
assert_eq!(result.status, StageOutcome::Succeeded);
|
||||
// Should have slept ~5s for the retry backoff
|
||||
assert!(start.elapsed() >= Duration::from_secs(4));
|
||||
}
|
||||
|
|
@ -1372,7 +1376,7 @@ mod tests {
|
|||
.lifecycle(Box::new(SkipFirst(Mutex::new(false))))
|
||||
.build();
|
||||
let (result, _) = executor.run(&g, state).await.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Success);
|
||||
assert_eq!(result.status, StageOutcome::Succeeded);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -1451,7 +1455,7 @@ mod tests {
|
|||
.lifecycle(Box::new(Redirector))
|
||||
.build();
|
||||
let (result, _) = executor.run(&g, state).await.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Success);
|
||||
assert_eq!(result.status, StageOutcome::Succeeded);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -1777,7 +1781,7 @@ mod tests {
|
|||
let g2 = TestGraph::new(
|
||||
vec![
|
||||
TestNode::new("work"),
|
||||
TestNode::terminal("end").with_goal_gate("work", StageStatus::Success),
|
||||
TestNode::terminal("end").with_goal_gate("work", StageOutcome::Succeeded),
|
||||
],
|
||||
vec![TestEdge::new("work", "end")],
|
||||
"work",
|
||||
|
|
@ -1926,7 +1930,7 @@ mod tests {
|
|||
let g = TestGraph::new(
|
||||
vec![
|
||||
TestNode::new("work"),
|
||||
TestNode::terminal("end").with_goal_gate("work", StageStatus::Success),
|
||||
TestNode::terminal("end").with_goal_gate("work", StageOutcome::Succeeded),
|
||||
],
|
||||
vec![TestEdge::new("work", "end")],
|
||||
"work",
|
||||
|
|
@ -1937,7 +1941,7 @@ mod tests {
|
|||
let executor =
|
||||
ExecutorBuilder::new(handler.clone() as Arc<dyn NodeHandler<TestGraph>>).build();
|
||||
let (result, _) = executor.run(&g, state).await.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Success);
|
||||
assert_eq!(result.status, StageOutcome::Succeeded);
|
||||
assert_eq!(handler.calls(), 2);
|
||||
}
|
||||
|
||||
|
|
@ -1968,7 +1972,7 @@ mod tests {
|
|||
.max_node_visits(5)
|
||||
.build();
|
||||
let (result, _) = executor.run(&g, state).await.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Success);
|
||||
assert_eq!(result.status, StageOutcome::Succeeded);
|
||||
assert_eq!(handler.calls(), 2);
|
||||
}
|
||||
|
||||
|
|
@ -1993,7 +1997,7 @@ mod tests {
|
|||
let g = TestGraph::new(
|
||||
vec![
|
||||
TestNode::new("work"),
|
||||
TestNode::terminal("end").with_goal_gate("work", StageStatus::Success),
|
||||
TestNode::terminal("end").with_goal_gate("work", StageOutcome::Succeeded),
|
||||
],
|
||||
vec![TestEdge::new("work", "end")],
|
||||
"work",
|
||||
|
|
@ -2008,7 +2012,9 @@ mod tests {
|
|||
.build();
|
||||
|
||||
let (result, _) = executor.run(&g, state).await.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Fail);
|
||||
assert_eq!(result.status, StageOutcome::Failed {
|
||||
retry_requested: false,
|
||||
});
|
||||
assert_eq!(
|
||||
result
|
||||
.failure
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ pub use lifecycle::{
|
|||
};
|
||||
pub use outcome::{
|
||||
FailureCategory, FailureDetail, NodeResult, NodeResultExt, Outcome, OutcomeMeta, StageOutcome,
|
||||
StageState, StageStatus,
|
||||
StageState,
|
||||
};
|
||||
pub use retry::{BackoffPolicy, RetryPolicy};
|
||||
pub use stall::{ActivityMonitor, StallGuard, StallWatchdog};
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ use std::time::Duration;
|
|||
|
||||
pub use fabro_types::outcome::{
|
||||
FailureCategory, FailureDetail, NodeResult, Outcome, OutcomeMeta, StageOutcome, StageState,
|
||||
StageStatus,
|
||||
};
|
||||
|
||||
use crate::error::Error;
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ mod tests {
|
|||
use serde_json::json;
|
||||
|
||||
use super::*;
|
||||
use crate::outcome::{Outcome, StageStatus};
|
||||
use crate::outcome::{Outcome, StageOutcome};
|
||||
use crate::test_fixtures::linear_graph;
|
||||
|
||||
#[test]
|
||||
|
|
@ -115,7 +115,7 @@ mod tests {
|
|||
state.record("start", &result);
|
||||
|
||||
assert_eq!(state.completed_nodes, vec!["start"]);
|
||||
assert_eq!(state.node_outcomes["start"].status, StageStatus::Success);
|
||||
assert_eq!(state.node_outcomes["start"].status, StageOutcome::Succeeded);
|
||||
assert_eq!(state.node_retries["start"], 1); // 2 attempts - 1
|
||||
assert_eq!(state.stage_index, 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use crate::context::Context;
|
|||
use crate::error::{Error, HandlerErrorDetail, Result};
|
||||
use crate::graph::{EdgeSelection, EdgeSpec, Graph, NodeSpec};
|
||||
use crate::handler::NodeHandler;
|
||||
use crate::outcome::{Outcome, StageStatus};
|
||||
use crate::outcome::{Outcome, StageOutcome};
|
||||
use crate::retry::RetryPolicy;
|
||||
|
||||
// ---- Test node ----
|
||||
|
|
@ -18,7 +18,7 @@ pub struct TestNode {
|
|||
pub id: String,
|
||||
pub terminal: bool,
|
||||
pub max_visits: Option<usize>,
|
||||
pub goal_gate: Option<(String, StageStatus)>,
|
||||
pub goal_gate: Option<(String, StageOutcome)>,
|
||||
}
|
||||
|
||||
impl TestNode {
|
||||
|
|
@ -47,7 +47,7 @@ impl TestNode {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_goal_gate(mut self, node_id: &str, required_status: StageStatus) -> Self {
|
||||
pub fn with_goal_gate(mut self, node_id: &str, required_status: StageOutcome) -> Self {
|
||||
self.goal_gate = Some((node_id.to_string(), required_status));
|
||||
self
|
||||
}
|
||||
|
|
@ -525,7 +525,7 @@ mod tests {
|
|||
let g = TestGraph::new(
|
||||
vec![
|
||||
TestNode::new("work"),
|
||||
TestNode::terminal("end").with_goal_gate("work", StageStatus::Success),
|
||||
TestNode::terminal("end").with_goal_gate("work", StageOutcome::Succeeded),
|
||||
],
|
||||
vec![TestEdge::new("work", "end")],
|
||||
"work",
|
||||
|
|
@ -540,7 +540,7 @@ mod tests {
|
|||
let g = TestGraph::new(
|
||||
vec![
|
||||
TestNode::new("work"),
|
||||
TestNode::terminal("end").with_goal_gate("work", StageStatus::Success),
|
||||
TestNode::terminal("end").with_goal_gate("work", StageOutcome::Succeeded),
|
||||
],
|
||||
vec![TestEdge::new("work", "end")],
|
||||
"work",
|
||||
|
|
@ -564,7 +564,7 @@ mod tests {
|
|||
let node = g.get_node("start").unwrap();
|
||||
let ctx = Context::new();
|
||||
let result = h.execute(&node, &ctx, &g).await.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Success);
|
||||
assert_eq!(result.status, StageOutcome::Succeeded);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -574,7 +574,9 @@ mod tests {
|
|||
let node = g.get_node("start").unwrap();
|
||||
let ctx = Context::new();
|
||||
let result = h.execute(&node, &ctx, &g).await.unwrap();
|
||||
assert_eq!(result.status, StageStatus::Fail);
|
||||
assert_eq!(result.status, StageOutcome::Failed {
|
||||
retry_requested: false,
|
||||
});
|
||||
assert_eq!(result.failure.unwrap().message, "boom");
|
||||
}
|
||||
|
||||
|
|
@ -586,16 +588,18 @@ mod tests {
|
|||
let ctx = Context::new();
|
||||
|
||||
let r1 = h.execute(&node, &ctx, &g).await.unwrap();
|
||||
assert_eq!(r1.status, StageStatus::Fail);
|
||||
assert_eq!(r1.status, StageOutcome::Failed {
|
||||
retry_requested: false,
|
||||
});
|
||||
assert_eq!(h.calls(), 1);
|
||||
|
||||
let r2 = h.execute(&node, &ctx, &g).await.unwrap();
|
||||
assert_eq!(r2.status, StageStatus::Success);
|
||||
assert_eq!(r2.status, StageOutcome::Succeeded);
|
||||
assert_eq!(h.calls(), 2);
|
||||
|
||||
// Past end of outcomes list → default success
|
||||
let r3 = h.execute(&node, &ctx, &g).await.unwrap();
|
||||
assert_eq!(r3.status, StageStatus::Success);
|
||||
assert_eq!(r3.status, StageOutcome::Succeeded);
|
||||
assert_eq!(h.calls(), 3);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -479,7 +479,7 @@ mod tests {
|
|||
use chrono::{TimeZone, Utc};
|
||||
use fabro_agent::LocalSandbox;
|
||||
use fabro_store::{NodeState, StageId};
|
||||
use fabro_types::{NodeStatusRecord, StageStatus};
|
||||
use fabro_types::{NodeStatusRecord, StageOutcome};
|
||||
use tokio::fs;
|
||||
|
||||
use super::*;
|
||||
|
|
@ -558,7 +558,7 @@ mod tests {
|
|||
prompt: Some("plan".to_string()),
|
||||
response: Some("done".to_string()),
|
||||
status: Some(NodeStatusRecord {
|
||||
status: StageStatus::Success,
|
||||
status: StageOutcome::Succeeded,
|
||||
notes: Some("ok".to_string()),
|
||||
failure_reason: None,
|
||||
timestamp: Utc
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use fabro_types::run_event::{
|
|||
use fabro_types::{
|
||||
BilledModelUsage, Checkpoint, Conclusion, EventBody, FailureSignature, InterviewQuestionRecord,
|
||||
NodeStatusRecord, Outcome, PendingInterviewRecord, PullRequestRecord, RunControlAction, RunId,
|
||||
RunProjection, RunSpec, RunStatus, RunSummary, SandboxRecord, StageStatus, StartRecord,
|
||||
RunProjection, RunSpec, RunStatus, RunSummary, SandboxRecord, StageOutcome, StartRecord,
|
||||
TerminalStatus,
|
||||
};
|
||||
use fabro_util::error::render_with_causes;
|
||||
|
|
@ -302,7 +302,9 @@ impl RunProjectionReducer for RunProjection {
|
|||
let failure_reason = props.failure.as_ref().map(|detail| detail.message.clone());
|
||||
let node = self.node_mut(node_id, visit);
|
||||
node.status = Some(NodeStatusRecord {
|
||||
status: StageStatus::Fail,
|
||||
status: StageOutcome::Failed {
|
||||
retry_requested: false,
|
||||
},
|
||||
notes: None,
|
||||
failure_reason,
|
||||
timestamp: ts,
|
||||
|
|
@ -448,7 +450,7 @@ fn conclusion_from_completed(
|
|||
) -> Result<Conclusion> {
|
||||
Ok(Conclusion {
|
||||
timestamp,
|
||||
status: StageStatus::from_str(&props.status)
|
||||
status: StageOutcome::from_str(&props.status)
|
||||
.map_err(|err| Error::InvalidEvent(format!("invalid completed stage status: {err}")))?,
|
||||
duration_ms: props.duration_ms,
|
||||
failure_reason: None,
|
||||
|
|
@ -462,7 +464,9 @@ fn conclusion_from_completed(
|
|||
fn conclusion_from_failed(props: &RunFailedProps, timestamp: DateTime<Utc>) -> Conclusion {
|
||||
Conclusion {
|
||||
timestamp,
|
||||
status: StageStatus::Fail,
|
||||
status: StageOutcome::Failed {
|
||||
retry_requested: false,
|
||||
},
|
||||
duration_ms: props.duration_ms,
|
||||
failure_reason: Some(render_with_causes(&props.error, &props.causes)),
|
||||
final_git_commit_sha: props.git_commit_sha.clone(),
|
||||
|
|
@ -485,7 +489,7 @@ fn stage_visit(
|
|||
|
||||
fn stage_outcome_from_props(props: &StageCompletedProps) -> Outcome<Option<BilledModelUsage>> {
|
||||
Outcome {
|
||||
status: props.status.clone(),
|
||||
status: props.status,
|
||||
preferred_label: props.preferred_label.clone(),
|
||||
suggested_next_ids: props.suggested_next_ids.clone(),
|
||||
context_updates: props
|
||||
|
|
@ -508,7 +512,7 @@ fn node_status_from_outcome(
|
|||
timestamp: DateTime<Utc>,
|
||||
) -> NodeStatusRecord {
|
||||
NodeStatusRecord {
|
||||
status: outcome.status.clone(),
|
||||
status: outcome.status,
|
||||
notes: outcome.notes.clone(),
|
||||
failure_reason: outcome
|
||||
.failure
|
||||
|
|
@ -1118,7 +1122,7 @@ mod tests {
|
|||
EventBody::RunCompleted(RunCompletedProps {
|
||||
duration_ms: 10,
|
||||
artifact_count: 0,
|
||||
status: "success".to_string(),
|
||||
status: "succeeded".to_string(),
|
||||
reason: SuccessReason::Completed,
|
||||
total_usd_micros: None,
|
||||
final_git_commit_sha: None,
|
||||
|
|
@ -1181,7 +1185,7 @@ mod tests {
|
|||
EventBody::RunCompleted(RunCompletedProps {
|
||||
duration_ms: 10,
|
||||
artifact_count: 0,
|
||||
status: "success".to_string(),
|
||||
status: "succeeded".to_string(),
|
||||
reason: SuccessReason::PartialSuccess,
|
||||
total_usd_micros: None,
|
||||
final_git_commit_sha: None,
|
||||
|
|
@ -1311,7 +1315,7 @@ mod tests {
|
|||
EventBody::RunCompleted(RunCompletedProps {
|
||||
duration_ms: 10,
|
||||
artifact_count: 0,
|
||||
status: "success".to_string(),
|
||||
status: "succeeded".to_string(),
|
||||
reason: SuccessReason::Completed,
|
||||
total_usd_micros: None,
|
||||
final_git_commit_sha: None,
|
||||
|
|
|
|||
|
|
@ -421,7 +421,7 @@ mod tests {
|
|||
&serde_json::json!({
|
||||
"duration_ms": 3210,
|
||||
"artifact_count": 1,
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"reason": "completed",
|
||||
"total_cost": 1.25,
|
||||
}),
|
||||
|
|
@ -625,7 +625,7 @@ mod tests {
|
|||
&serde_json::json!({
|
||||
"duration_ms": 3210,
|
||||
"artifact_count": 1,
|
||||
"status": "success",
|
||||
"status": "succeeded",
|
||||
"reason": "completed",
|
||||
"total_cost": 1.25,
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use fabro_store::{NodeState, RunProjection, SerializableProjection, StageId};
|
|||
use fabro_types::graph::Graph;
|
||||
use fabro_types::run::RunSpec;
|
||||
use fabro_types::{
|
||||
Checkpoint, NodeStatusRecord, RunStatus, SandboxRecord, StageStatus, StartRecord,
|
||||
Checkpoint, NodeStatusRecord, RunStatus, SandboxRecord, StageOutcome, StartRecord,
|
||||
TerminalStatus, WorkflowSettings, fixtures,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
|
@ -81,7 +81,7 @@ fn serializable_projection_round_trips_and_trims_bulky_node_fields() {
|
|||
prompt: Some("plan the work".to_string()),
|
||||
response: Some("done".to_string()),
|
||||
status: Some(NodeStatusRecord {
|
||||
status: StageStatus::Success,
|
||||
status: StageOutcome::Succeeded,
|
||||
notes: Some("ok".to_string()),
|
||||
failure_reason: None,
|
||||
timestamp: Utc
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ pub use interview::{InterviewQuestionRecord, QuestionType};
|
|||
pub use node_status::NodeStatusRecord;
|
||||
pub use outcome::{
|
||||
FailureCategory, FailureDetail, NodeResult, Outcome, OutcomeMeta, StageOutcome, StageState,
|
||||
StageStatus,
|
||||
};
|
||||
pub use pull_request::{
|
||||
PullRequestDetail, PullRequestGithubDetail, PullRequestRecord, PullRequestRef, PullRequestUser,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::fmt;
|
|||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::de::{DeserializeOwned, Error as DeError};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde_json::Value;
|
||||
use strum::{Display, EnumString, IntoStaticStr};
|
||||
|
|
@ -87,7 +87,7 @@ impl<'de> Deserialize<'de> for StageOutcome {
|
|||
D: Deserializer<'de>,
|
||||
{
|
||||
let value = String::deserialize(deserializer)?;
|
||||
value.parse().map_err(serde::de::Error::custom)
|
||||
value.parse().map_err(DeError::custom)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -142,23 +142,6 @@ impl From<StageOutcome> for StageState {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(
|
||||
non_upper_case_globals,
|
||||
reason = "Temporary compatibility constants allow the staged refactor to compile between phase commits."
|
||||
)]
|
||||
impl StageOutcome {
|
||||
pub const Success: Self = Self::Succeeded;
|
||||
pub const Fail: Self = Self::Failed {
|
||||
retry_requested: false,
|
||||
};
|
||||
pub const PartialSuccess: Self = Self::PartiallySucceeded;
|
||||
pub const Retry: Self = Self::Failed {
|
||||
retry_requested: true,
|
||||
};
|
||||
}
|
||||
|
||||
pub type StageStatus = StageOutcome;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum FailureCategory {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ A DOT-based pipeline runner for multi-stage AI workflows. Define workflows as Gr
|
|||
- **Node** -- A workflow step. Graphviz shapes map to handler types (e.g., `Mdiamond` = start, `Msquare` = exit, `box` = agent, `tab` = prompt, `diamond` = conditional, `hexagon` = human gate, `component` = parallel).
|
||||
- **Edge** -- A connection between nodes with optional `condition`, `label`, `weight`, and `fidelity` attributes that control routing.
|
||||
- **Handler** -- An async trait implementation that executes a node and returns an `Outcome`. Built-in handlers include `StartHandler`, `ExitHandler`, `AgentHandler`, `PromptHandler`, `ConditionalHandler`, `HumanHandler`, `ParallelHandler`, `FanInHandler`, `CommandHandler`, and `SubWorkflowHandler`.
|
||||
- **Outcome** -- The result of executing a handler, carrying a `StageStatus` (Success, Fail, PartialSuccess, Retry, Skipped), optional routing hints (`preferred_label`, `suggested_next_ids`), and context updates.
|
||||
- **Outcome** -- The result of executing a handler, carrying a `StageOutcome` (Success, Fail, PartialSuccess, Retry, Skipped), optional routing hints (`preferred_label`, `suggested_next_ids`), and context updates.
|
||||
- **Context** -- A thread-safe key-value store shared across pipeline stages, supporting snapshots and isolated cloning for parallel branches.
|
||||
- **Interviewer** -- A trait for human-in-the-loop interactions. Implementations include `AutoApproveInterviewer`, `QueueInterviewer`, `CallbackInterviewer`, `ConsoleInterviewer`, and `RecordingInterviewer`.
|
||||
- **Checkpoint** -- A serializable snapshot of execution state (completed nodes, context values) for crash recovery and resume.
|
||||
|
|
|
|||
|
|
@ -302,7 +302,7 @@ impl Handler for SubWorkflowHandler {
|
|||
);
|
||||
|
||||
let mut outcome = Outcome {
|
||||
status: child_outcome.status.clone(),
|
||||
status: child_outcome.status,
|
||||
notes: Some(format!("Child completed at cycle {cycle}")),
|
||||
context_updates: diff,
|
||||
..Outcome::success()
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ pub fn classify_engine_result(
|
|||
) -> (StageOutcome, Option<String>, RunStatus) {
|
||||
match engine_result {
|
||||
Ok(outcome) => {
|
||||
let status = outcome.status.clone();
|
||||
let status = outcome.status;
|
||||
let failure_reason = outcome.failure_reason().map(String::from);
|
||||
let run_status = match status {
|
||||
StageOutcome::Succeeded | StageOutcome::Skipped => RunStatus::Succeeded {
|
||||
|
|
@ -359,7 +359,7 @@ pub(crate) fn build_terminal_event(
|
|||
StageOutcome::Failed {
|
||||
retry_requested: false,
|
||||
},
|
||||
|o| o.status.clone(),
|
||||
|o| o.status,
|
||||
);
|
||||
|
||||
if outcome_status == StageOutcome::Succeeded
|
||||
|
|
@ -456,7 +456,7 @@ pub async fn finalize(retroed: Retroed, options: &FinalizeOptions) -> Result<Con
|
|||
let conclusion = build_conclusion_from_parts(
|
||||
checkpoint.as_ref(),
|
||||
&stage_durations,
|
||||
final_status.clone(),
|
||||
final_status,
|
||||
failure_reason,
|
||||
duration_ms,
|
||||
options.last_git_sha.clone(),
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
*/
|
||||
export interface CreateRunPullRequestRequest {
|
||||
/**
|
||||
* Create the pull request even if the run did not finish with success or partial_success.
|
||||
* Create the pull request even if the run did not finish with succeeded or partially_succeeded.
|
||||
*/
|
||||
'force': boolean;
|
||||
/**
|
||||
|
|
@ -27,4 +27,3 @@ export interface CreateRunPullRequestRequest {
|
|||
*/
|
||||
'model'?: string | null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ digraph Workflow {
|
|||
node_type="stack.steer", label="Review Consensus", shape="box", style="rounded,filled",
|
||||
is_codergen="true", model="gpt-5.2-codex",
|
||||
max_agent_turns="6", timeout="300",
|
||||
llm_prompt="Reach consensus.\n\nRead .ai/review_*.md\nWrite to .ai/review_consensus.md\n\noutcome=yes if PASS, outcome=retry if FAIL. Set preferred_next_label to \"\" (empty) or to \"yes\"/\"retry\"; do not use \"No\"."
|
||||
llm_prompt="Reach consensus.\n\nRead .ai/review_*.md\nWrite to .ai/review_consensus.md\n\noutcome=succeeded if PASS, outcome=failed if FAIL. Set preferred_next_label to \"\" (empty) or to \"yes\"/\"retry\"; do not use \"No\"."
|
||||
];
|
||||
|
||||
Postmortem [
|
||||
|
|
@ -150,7 +150,7 @@ digraph Workflow {
|
|||
ReviewGemini -> ReviewConsensus;
|
||||
ReviewGPT -> ReviewConsensus;
|
||||
ReviewOpus -> ReviewConsensus;
|
||||
ReviewConsensus -> Exit [condition="outcome=yes"];
|
||||
ReviewConsensus -> Exit [condition="outcome=succeeded"];
|
||||
ReviewConsensus -> Postmortem;
|
||||
Postmortem -> PlanGemini [loop_restart="true"];
|
||||
Postmortem -> PlanGPT [loop_restart="true"];
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ Create:
|
|||
|
||||
Run: go build ./...
|
||||
|
||||
Write status.json: outcome=success if project builds, outcome=fail with error otherwise."
|
||||
Write status.json: outcome=succeeded if project builds, outcome=failed with error otherwise."
|
||||
]
|
||||
|
||||
verify_setup [
|
||||
|
|
@ -45,7 +45,7 @@ Run:
|
|||
3. Check that go.mod exists with correct module path
|
||||
|
||||
Write results to .ai/verify_setup.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_setup [shape=diamond, label="Setup OK?"]
|
||||
|
|
@ -69,7 +69,7 @@ Add comprehensive godoc comments. Include validation methods where appropriate.
|
|||
|
||||
Run: go build ./... && go test ./pkg/dttf/...
|
||||
|
||||
Write status.json: outcome=success if builds and tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if builds and tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_types [
|
||||
|
|
@ -85,7 +85,7 @@ Run:
|
|||
4. Check that all types from section 7 are present
|
||||
|
||||
Write results to .ai/verify_types.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_types [shape=diamond, label="Types OK?"]
|
||||
|
|
@ -112,7 +112,7 @@ Create tests in pkg/dttf/loader_test.go with sample PNGs.
|
|||
|
||||
Run: go test ./pkg/dttf/... -run TestLoad
|
||||
|
||||
Write status.json: outcome=success if tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_loader [
|
||||
|
|
@ -128,7 +128,7 @@ Run:
|
|||
4. Verify font.json defaults are applied
|
||||
|
||||
Write results to .ai/verify_loader.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_loader [shape=diamond, label="Loader OK?"]
|
||||
|
|
@ -151,7 +151,7 @@ Create tests with synthetic images and known thresholds.
|
|||
|
||||
Run: go test ./pkg/dttf/... -run TestImage
|
||||
|
||||
Write status.json: outcome=success if tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_imageproc [
|
||||
|
|
@ -166,7 +166,7 @@ Run:
|
|||
3. Check threshold produces binary output
|
||||
|
||||
Write results to .ai/verify_imageproc.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_imageproc [shape=diamond, label="ImageProc OK?"]
|
||||
|
|
@ -191,7 +191,7 @@ Create tests with simple shapes (square, circle, letter O with counter).
|
|||
|
||||
Run: go test ./pkg/dttf/tracer/... -run TestDecompose
|
||||
|
||||
Write status.json: outcome=success if tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_tracer_phase1 [
|
||||
|
|
@ -206,7 +206,7 @@ Run:
|
|||
3. Verify closed paths return to origin
|
||||
|
||||
Write results to .ai/verify_tracer_phase1.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_tracer_phase1 [shape=diamond, label="Phase1 OK?"]
|
||||
|
|
@ -230,7 +230,7 @@ Create tests comparing input/output vertex counts.
|
|||
|
||||
Run: go test ./pkg/dttf/tracer/... -run TestPolygon
|
||||
|
||||
Write status.json: outcome=success if tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_tracer_phase2 [
|
||||
|
|
@ -245,7 +245,7 @@ Run:
|
|||
3. Verify shape is preserved
|
||||
|
||||
Write results to .ai/verify_tracer_phase2.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_tracer_phase2 [shape=diamond, label="Phase2 OK?"]
|
||||
|
|
@ -270,7 +270,7 @@ Create tests with known curves.
|
|||
|
||||
Run: go test ./pkg/dttf/tracer/... -run TestBezier
|
||||
|
||||
Write status.json: outcome=success if tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_tracer_phase3 [
|
||||
|
|
@ -285,7 +285,7 @@ Run:
|
|||
3. Verify curves are quadratic (TrueType format)
|
||||
|
||||
Write results to .ai/verify_tracer_phase3.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_tracer_phase3 [shape=diamond, label="Phase3 OK?"]
|
||||
|
|
@ -310,7 +310,7 @@ Create tests validating each constraint.
|
|||
|
||||
Run: go test ./pkg/dttf/tracer/... -run TestOptimize
|
||||
|
||||
Write status.json: outcome=success if tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_tracer_phase4 [
|
||||
|
|
@ -326,7 +326,7 @@ Run:
|
|||
4. Check point count cap
|
||||
|
||||
Write results to .ai/verify_tracer_phase4.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_tracer_phase4 [shape=diamond, label="Phase4 OK?"]
|
||||
|
|
@ -348,7 +348,7 @@ Create tests with known transformations.
|
|||
|
||||
Run: go test ./pkg/dttf/tracer/... -run TestCoordinates
|
||||
|
||||
Write status.json: outcome=success if tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_coordinates [
|
||||
|
|
@ -363,7 +363,7 @@ Run:
|
|||
3. Verify integer output
|
||||
|
||||
Write results to .ai/verify_coordinates.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_coordinates [shape=diamond, label="Coords OK?"]
|
||||
|
|
@ -387,7 +387,7 @@ Create integration tests.
|
|||
|
||||
Run: go test ./pkg/dttf/... -run TestTrace
|
||||
|
||||
Write status.json: outcome=success if tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_tracer_main [
|
||||
|
|
@ -402,7 +402,7 @@ Run:
|
|||
3. Verify all phases are called
|
||||
|
||||
Write results to .ai/verify_tracer_main.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_tracer_main [shape=diamond, label="Tracer OK?"]
|
||||
|
|
@ -424,7 +424,7 @@ Create tests with known glyph shapes.
|
|||
|
||||
Run: go test ./pkg/dttf/... -run TestMetrics
|
||||
|
||||
Write status.json: outcome=success if tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_metrics [
|
||||
|
|
@ -439,7 +439,7 @@ Run:
|
|||
3. Verify sidebearing calculations
|
||||
|
||||
Write results to .ai/verify_metrics.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_metrics [shape=diamond, label="Metrics OK?"]
|
||||
|
|
@ -471,7 +471,7 @@ Create tests validating table structure.
|
|||
|
||||
Run: go test ./pkg/dttf/ttf/... -v
|
||||
|
||||
Write status.json: outcome=success if tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_tables [
|
||||
|
|
@ -486,7 +486,7 @@ Run:
|
|||
3. Verify checksums are computed correctly
|
||||
|
||||
Write results to .ai/verify_tables.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_tables [shape=diamond, label="Tables OK?"]
|
||||
|
|
@ -509,7 +509,7 @@ Implement in pkg/dttf/assembler.go:
|
|||
|
||||
Run: go test ./pkg/dttf/... -run TestAssemble
|
||||
|
||||
Write status.json: outcome=success if tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_assembler [
|
||||
|
|
@ -524,7 +524,7 @@ Run:
|
|||
3. Verify offset calculations
|
||||
|
||||
Write results to .ai/verify_assembler.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_assembler [shape=diamond, label="Assembler OK?"]
|
||||
|
|
@ -546,7 +546,7 @@ Create tests writing to temp files.
|
|||
|
||||
Run: go test ./pkg/dttf/... -run TestWrite
|
||||
|
||||
Write status.json: outcome=success if tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_writer [
|
||||
|
|
@ -561,7 +561,7 @@ Run:
|
|||
3. Verify checksum calculation
|
||||
|
||||
Write results to .ai/verify_writer.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_writer [shape=diamond, label="Writer OK?"]
|
||||
|
|
@ -582,7 +582,7 @@ Create end-to-end test with sample input directory.
|
|||
|
||||
Run: go test ./pkg/dttf/... -run TestBuild
|
||||
|
||||
Write status.json: outcome=success if tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_pipeline [
|
||||
|
|
@ -597,7 +597,7 @@ Run:
|
|||
3. Verify parallelization works
|
||||
|
||||
Write results to .ai/verify_pipeline.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_pipeline [shape=diamond, label="Pipeline OK?"]
|
||||
|
|
@ -622,7 +622,7 @@ Create tests with valid and invalid fonts.
|
|||
|
||||
Run: go test ./pkg/dttf/... -run TestValidate
|
||||
|
||||
Write status.json: outcome=success if tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_validator [
|
||||
|
|
@ -637,7 +637,7 @@ Run:
|
|||
3. Check that invalid fonts fail appropriately
|
||||
|
||||
Write results to .ai/verify_validator.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_validator [shape=diamond, label="Validator OK?"]
|
||||
|
|
@ -662,7 +662,7 @@ Create tests with a simple font.
|
|||
|
||||
Run: go test ./pkg/dttf/... -run TestRasterize
|
||||
|
||||
Write status.json: outcome=success if tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_rasterizer [
|
||||
|
|
@ -677,7 +677,7 @@ Run:
|
|||
3. Verify font.json is written
|
||||
|
||||
Write results to .ai/verify_rasterizer.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_rasterizer [shape=diamond, label="Rasterizer OK?"]
|
||||
|
|
@ -699,7 +699,7 @@ Create tests with identical/different images.
|
|||
|
||||
Run: go test ./pkg/dttf/quality/... -run TestSSIM
|
||||
|
||||
Write status.json: outcome=success if tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_ssim [
|
||||
|
|
@ -714,7 +714,7 @@ Run:
|
|||
3. Check different images return < 1.0
|
||||
|
||||
Write results to .ai/verify_ssim.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_ssim [shape=diamond, label="SSIM OK?"]
|
||||
|
|
@ -738,7 +738,7 @@ Create tests with a known font.
|
|||
|
||||
Run: go test ./pkg/dttf/test/... -run TestHarness
|
||||
|
||||
Write status.json: outcome=success if tests pass, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if tests pass, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_test_harness [
|
||||
|
|
@ -753,7 +753,7 @@ Run:
|
|||
3. Verify SSIM scores are computed
|
||||
|
||||
Write results to .ai/verify_test_harness.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_test_harness [shape=diamond, label="Harness OK?"]
|
||||
|
|
@ -774,7 +774,7 @@ Update cmd/dttf/main.go to register command.
|
|||
|
||||
Run: go build ./cmd/dttf && ./cmd/dttf build --help
|
||||
|
||||
Write status.json: outcome=success if help displays, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if help displays, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_cli_build [
|
||||
|
|
@ -789,7 +789,7 @@ Run:
|
|||
3. Check all flags are present
|
||||
|
||||
Write results to .ai/verify_cli_build.md.
|
||||
Write status.json: outcome=success if help works, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if help works, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_cli_build [shape=diamond, label="CLI Build OK?"]
|
||||
|
|
@ -810,7 +810,7 @@ Update cmd/dttf/main.go to register command.
|
|||
|
||||
Run: go build ./cmd/dttf && ./cmd/dttf rasterize --help
|
||||
|
||||
Write status.json: outcome=success if help displays, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if help displays, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_cli_rasterize [
|
||||
|
|
@ -825,7 +825,7 @@ Run:
|
|||
3. Check all flags are present
|
||||
|
||||
Write results to .ai/verify_cli_rasterize.md.
|
||||
Write status.json: outcome=success if help works, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if help works, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_cli_rasterize [shape=diamond, label="CLI Rasterize OK?"]
|
||||
|
|
@ -846,7 +846,7 @@ Update cmd/dttf/main.go to register command.
|
|||
|
||||
Run: go build ./cmd/dttf && ./cmd/dttf validate --help
|
||||
|
||||
Write status.json: outcome=success if help displays, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if help displays, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_cli_validate [
|
||||
|
|
@ -860,7 +860,7 @@ Run:
|
|||
2. ./cmd/dttf validate --help
|
||||
|
||||
Write results to .ai/verify_cli_validate.md.
|
||||
Write status.json: outcome=success if help works, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if help works, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_cli_validate [shape=diamond, label="CLI Validate OK?"]
|
||||
|
|
@ -882,7 +882,7 @@ Update cmd/dttf/main.go to register command.
|
|||
|
||||
Run: go build ./cmd/dttf && ./cmd/dttf test --help
|
||||
|
||||
Write status.json: outcome=success if help displays, outcome=fail otherwise."
|
||||
Write status.json: outcome=succeeded if help displays, outcome=failed otherwise."
|
||||
]
|
||||
|
||||
verify_cli_test [
|
||||
|
|
@ -897,7 +897,7 @@ Run:
|
|||
3. Check all flags are present
|
||||
|
||||
Write results to .ai/verify_cli_test.md.
|
||||
Write status.json: outcome=success if help works, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if help works, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_cli_test [shape=diamond, label="CLI Test OK?"]
|
||||
|
|
@ -923,7 +923,7 @@ This is an end-to-end test of the full pipeline.
|
|||
|
||||
Run: go test ./test/... -v -timeout 5m
|
||||
|
||||
Write status.json: outcome=success if all steps pass and SSIM > 0.90, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all steps pass and SSIM > 0.90, outcome=failed with details."
|
||||
]
|
||||
|
||||
verify_integration [
|
||||
|
|
@ -939,7 +939,7 @@ Run:
|
|||
4. Check SSIM threshold met
|
||||
|
||||
Write results to .ai/verify_integration.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_integration [shape=diamond, label="Integration OK?"]
|
||||
|
|
@ -967,109 +967,109 @@ Run:
|
|||
3. go vet ./...
|
||||
|
||||
Write a review report to .ai/review.md.
|
||||
Write status.json: outcome=success if complete and correct, outcome=fail with missing/broken items."
|
||||
Write status.json: outcome=succeeded if complete and correct, outcome=failed with missing/broken items."
|
||||
]
|
||||
|
||||
check_review [shape=diamond, label="Review OK?"]
|
||||
|
||||
// Flow
|
||||
start -> impl_setup -> verify_setup -> check_setup
|
||||
check_setup -> impl_types [condition="outcome=success"]
|
||||
check_setup -> impl_setup [condition="outcome=fail", label="retry"]
|
||||
check_setup -> impl_types [condition="outcome=succeeded"]
|
||||
check_setup -> impl_setup [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_types -> verify_types -> check_types
|
||||
check_types -> impl_loader [condition="outcome=success"]
|
||||
check_types -> impl_types [condition="outcome=fail", label="retry"]
|
||||
check_types -> impl_loader [condition="outcome=succeeded"]
|
||||
check_types -> impl_types [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_loader -> verify_loader -> check_loader
|
||||
check_loader -> impl_imageproc [condition="outcome=success"]
|
||||
check_loader -> impl_loader [condition="outcome=fail", label="retry"]
|
||||
check_loader -> impl_imageproc [condition="outcome=succeeded"]
|
||||
check_loader -> impl_loader [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_imageproc -> verify_imageproc -> check_imageproc
|
||||
check_imageproc -> impl_tracer_phase1 [condition="outcome=success"]
|
||||
check_imageproc -> impl_imageproc [condition="outcome=fail", label="retry"]
|
||||
check_imageproc -> impl_tracer_phase1 [condition="outcome=succeeded"]
|
||||
check_imageproc -> impl_imageproc [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_tracer_phase1 -> verify_tracer_phase1 -> check_tracer_phase1
|
||||
check_tracer_phase1 -> impl_tracer_phase2 [condition="outcome=success"]
|
||||
check_tracer_phase1 -> impl_tracer_phase1 [condition="outcome=fail", label="retry"]
|
||||
check_tracer_phase1 -> impl_tracer_phase2 [condition="outcome=succeeded"]
|
||||
check_tracer_phase1 -> impl_tracer_phase1 [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_tracer_phase2 -> verify_tracer_phase2 -> check_tracer_phase2
|
||||
check_tracer_phase2 -> impl_tracer_phase3 [condition="outcome=success"]
|
||||
check_tracer_phase2 -> impl_tracer_phase2 [condition="outcome=fail", label="retry"]
|
||||
check_tracer_phase2 -> impl_tracer_phase3 [condition="outcome=succeeded"]
|
||||
check_tracer_phase2 -> impl_tracer_phase2 [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_tracer_phase3 -> verify_tracer_phase3 -> check_tracer_phase3
|
||||
check_tracer_phase3 -> impl_tracer_phase4 [condition="outcome=success"]
|
||||
check_tracer_phase3 -> impl_tracer_phase3 [condition="outcome=fail", label="retry"]
|
||||
check_tracer_phase3 -> impl_tracer_phase4 [condition="outcome=succeeded"]
|
||||
check_tracer_phase3 -> impl_tracer_phase3 [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_tracer_phase4 -> verify_tracer_phase4 -> check_tracer_phase4
|
||||
check_tracer_phase4 -> impl_coordinates [condition="outcome=success"]
|
||||
check_tracer_phase4 -> impl_tracer_phase4 [condition="outcome=fail", label="retry"]
|
||||
check_tracer_phase4 -> impl_coordinates [condition="outcome=succeeded"]
|
||||
check_tracer_phase4 -> impl_tracer_phase4 [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_coordinates -> verify_coordinates -> check_coordinates
|
||||
check_coordinates -> impl_tracer_main [condition="outcome=success"]
|
||||
check_coordinates -> impl_coordinates [condition="outcome=fail", label="retry"]
|
||||
check_coordinates -> impl_tracer_main [condition="outcome=succeeded"]
|
||||
check_coordinates -> impl_coordinates [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_tracer_main -> verify_tracer_main -> check_tracer_main
|
||||
check_tracer_main -> impl_metrics [condition="outcome=success"]
|
||||
check_tracer_main -> impl_tracer_main [condition="outcome=fail", label="retry"]
|
||||
check_tracer_main -> impl_metrics [condition="outcome=succeeded"]
|
||||
check_tracer_main -> impl_tracer_main [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_metrics -> verify_metrics -> check_metrics
|
||||
check_metrics -> impl_tables [condition="outcome=success"]
|
||||
check_metrics -> impl_metrics [condition="outcome=fail", label="retry"]
|
||||
check_metrics -> impl_tables [condition="outcome=succeeded"]
|
||||
check_metrics -> impl_metrics [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_tables -> verify_tables -> check_tables
|
||||
check_tables -> impl_assembler [condition="outcome=success"]
|
||||
check_tables -> impl_tables [condition="outcome=fail", label="retry"]
|
||||
check_tables -> impl_assembler [condition="outcome=succeeded"]
|
||||
check_tables -> impl_tables [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_assembler -> verify_assembler -> check_assembler
|
||||
check_assembler -> impl_writer [condition="outcome=success"]
|
||||
check_assembler -> impl_assembler [condition="outcome=fail", label="retry"]
|
||||
check_assembler -> impl_writer [condition="outcome=succeeded"]
|
||||
check_assembler -> impl_assembler [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_writer -> verify_writer -> check_writer
|
||||
check_writer -> impl_pipeline [condition="outcome=success"]
|
||||
check_writer -> impl_writer [condition="outcome=fail", label="retry"]
|
||||
check_writer -> impl_pipeline [condition="outcome=succeeded"]
|
||||
check_writer -> impl_writer [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_pipeline -> verify_pipeline -> check_pipeline
|
||||
check_pipeline -> impl_validator [condition="outcome=success"]
|
||||
check_pipeline -> impl_pipeline [condition="outcome=fail", label="retry"]
|
||||
check_pipeline -> impl_validator [condition="outcome=succeeded"]
|
||||
check_pipeline -> impl_pipeline [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_validator -> verify_validator -> check_validator
|
||||
check_validator -> impl_rasterizer [condition="outcome=success"]
|
||||
check_validator -> impl_validator [condition="outcome=fail", label="retry"]
|
||||
check_validator -> impl_rasterizer [condition="outcome=succeeded"]
|
||||
check_validator -> impl_validator [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_rasterizer -> verify_rasterizer -> check_rasterizer
|
||||
check_rasterizer -> impl_ssim [condition="outcome=success"]
|
||||
check_rasterizer -> impl_rasterizer [condition="outcome=fail", label="retry"]
|
||||
check_rasterizer -> impl_ssim [condition="outcome=succeeded"]
|
||||
check_rasterizer -> impl_rasterizer [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_ssim -> verify_ssim -> check_ssim
|
||||
check_ssim -> impl_test_harness [condition="outcome=success"]
|
||||
check_ssim -> impl_ssim [condition="outcome=fail", label="retry"]
|
||||
check_ssim -> impl_test_harness [condition="outcome=succeeded"]
|
||||
check_ssim -> impl_ssim [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_test_harness -> verify_test_harness -> check_test_harness
|
||||
check_test_harness -> impl_cli_build [condition="outcome=success"]
|
||||
check_test_harness -> impl_test_harness [condition="outcome=fail", label="retry"]
|
||||
check_test_harness -> impl_cli_build [condition="outcome=succeeded"]
|
||||
check_test_harness -> impl_test_harness [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_cli_build -> verify_cli_build -> check_cli_build
|
||||
check_cli_build -> impl_cli_rasterize [condition="outcome=success"]
|
||||
check_cli_build -> impl_cli_build [condition="outcome=fail", label="retry"]
|
||||
check_cli_build -> impl_cli_rasterize [condition="outcome=succeeded"]
|
||||
check_cli_build -> impl_cli_build [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_cli_rasterize -> verify_cli_rasterize -> check_cli_rasterize
|
||||
check_cli_rasterize -> impl_cli_validate [condition="outcome=success"]
|
||||
check_cli_rasterize -> impl_cli_rasterize [condition="outcome=fail", label="retry"]
|
||||
check_cli_rasterize -> impl_cli_validate [condition="outcome=succeeded"]
|
||||
check_cli_rasterize -> impl_cli_rasterize [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_cli_validate -> verify_cli_validate -> check_cli_validate
|
||||
check_cli_validate -> impl_cli_test [condition="outcome=success"]
|
||||
check_cli_validate -> impl_cli_validate [condition="outcome=fail", label="retry"]
|
||||
check_cli_validate -> impl_cli_test [condition="outcome=succeeded"]
|
||||
check_cli_validate -> impl_cli_validate [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_cli_test -> verify_cli_test -> check_cli_test
|
||||
check_cli_test -> impl_integration [condition="outcome=success"]
|
||||
check_cli_test -> impl_cli_test [condition="outcome=fail", label="retry"]
|
||||
check_cli_test -> impl_integration [condition="outcome=succeeded"]
|
||||
check_cli_test -> impl_cli_test [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_integration -> verify_integration -> check_integration
|
||||
check_integration -> review [condition="outcome=success"]
|
||||
check_integration -> impl_integration [condition="outcome=fail", label="retry"]
|
||||
check_integration -> review [condition="outcome=succeeded"]
|
||||
check_integration -> impl_integration [condition="outcome=failed", label="retry"]
|
||||
|
||||
review -> check_review
|
||||
check_review -> exit [condition="outcome=success"]
|
||||
check_review -> impl_setup [condition="outcome=fail", label="fix from start"]
|
||||
check_review -> exit [condition="outcome=succeeded"]
|
||||
check_review -> impl_setup [condition="outcome=failed", label="fix from start"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ Expand this into a detailed spec covering:
|
|||
|
||||
Write the expanded spec to .ai/spec.md.
|
||||
|
||||
Write status.json: outcome=success"
|
||||
Write status.json: outcome=succeeded"
|
||||
]
|
||||
|
||||
// Phase 2: Project setup
|
||||
|
|
@ -56,7 +56,7 @@ Create the Go project structure:
|
|||
|
||||
Run: go build ./...
|
||||
|
||||
Write status.json: outcome=success if the project builds, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if the project builds, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_setup [
|
||||
|
|
@ -75,7 +75,7 @@ Check that:
|
|||
- pkg/ directories are created
|
||||
|
||||
Write results to .ai/verify_setup.md.
|
||||
Write status.json: outcome=success if all checks pass, outcome=fail with details otherwise."
|
||||
Write status.json: outcome=succeeded if all checks pass, outcome=failed with details otherwise."
|
||||
]
|
||||
|
||||
check_setup [shape=diamond, label="Setup OK?"]
|
||||
|
|
@ -104,7 +104,7 @@ Include comprehensive documentation for all exported types.
|
|||
|
||||
Run: go build ./...
|
||||
|
||||
Write status.json: outcome=success if builds, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if builds, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_types [
|
||||
|
|
@ -124,7 +124,7 @@ Check that:
|
|||
- No compilation errors
|
||||
|
||||
Write results to .ai/verify_types.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details otherwise."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details otherwise."
|
||||
]
|
||||
|
||||
check_types [shape=diamond, label="Types OK?"]
|
||||
|
|
@ -158,7 +158,7 @@ Read: pkg/crawler/types.go for interfaces.
|
|||
|
||||
Run: go test ./pkg/robotstxt/...
|
||||
|
||||
Write status.json: outcome=success if all tests pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all tests pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_robotstxt [
|
||||
|
|
@ -176,7 +176,7 @@ Check test coverage:
|
|||
4. go test ./pkg/robotstxt/... -cover
|
||||
|
||||
Write results to .ai/verify_robotstxt.md.
|
||||
Write status.json: outcome=success if all pass and coverage > 70%, outcome=fail with details otherwise."
|
||||
Write status.json: outcome=succeeded if all pass and coverage > 70%, outcome=failed with details otherwise."
|
||||
]
|
||||
|
||||
check_robotstxt [shape=diamond, label="Robots.txt OK?"]
|
||||
|
|
@ -206,7 +206,7 @@ Read: pkg/crawler/types.go for types.
|
|||
|
||||
Run: go test ./pkg/checker/...
|
||||
|
||||
Write status.json: outcome=success if all tests pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all tests pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_checker [
|
||||
|
|
@ -225,7 +225,7 @@ Check:
|
|||
- No race conditions: go test ./pkg/checker/... -race
|
||||
|
||||
Write results to .ai/verify_checker.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details otherwise."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details otherwise."
|
||||
]
|
||||
|
||||
check_checker [shape=diamond, label="Checker OK?"]
|
||||
|
|
@ -255,7 +255,7 @@ Read: pkg/crawler/types.go for types.
|
|||
|
||||
Run: go test ./pkg/crawler/...
|
||||
|
||||
Write status.json: outcome=success if all tests pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all tests pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_extractor [
|
||||
|
|
@ -275,7 +275,7 @@ Check:
|
|||
- Non-http schemes are filtered
|
||||
|
||||
Write results to .ai/verify_extractor.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details otherwise."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details otherwise."
|
||||
]
|
||||
|
||||
check_extractor [shape=diamond, label="Extractor OK?"]
|
||||
|
|
@ -319,7 +319,7 @@ Read: pkg/crawler/types.go, pkg/crawler/extractor.go, pkg/robotstxt/, pkg/checke
|
|||
|
||||
Run: go test ./pkg/crawler/...
|
||||
|
||||
Write status.json: outcome=success if all tests pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all tests pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_crawler [
|
||||
|
|
@ -341,7 +341,7 @@ Check:
|
|||
- No race conditions
|
||||
|
||||
Write results to .ai/verify_crawler.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details otherwise."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details otherwise."
|
||||
]
|
||||
|
||||
check_crawler [shape=diamond, label="Crawler OK?"]
|
||||
|
|
@ -377,7 +377,7 @@ Read: pkg/report/types.go for types.
|
|||
|
||||
Run: go test ./pkg/report/...
|
||||
|
||||
Write status.json: outcome=success if all tests pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all tests pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_report [
|
||||
|
|
@ -397,7 +397,7 @@ Check:
|
|||
- All test cases pass
|
||||
|
||||
Write results to .ai/verify_report.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details otherwise."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details otherwise."
|
||||
]
|
||||
|
||||
check_report [shape=diamond, label="Report OK?"]
|
||||
|
|
@ -430,7 +430,7 @@ Read: all pkg/ directories for integration.
|
|||
|
||||
Run: go build ./cmd/linkcheck
|
||||
|
||||
Write status.json: outcome=success if builds, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if builds, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_cli [
|
||||
|
|
@ -454,7 +454,7 @@ Check:
|
|||
- Exit codes are correct
|
||||
|
||||
Write results to .ai/verify_cli.md.
|
||||
Write status.json: outcome=success if all manual tests pass, outcome=fail with details otherwise."
|
||||
Write status.json: outcome=succeeded if all manual tests pass, outcome=failed with details otherwise."
|
||||
]
|
||||
|
||||
check_cli [shape=diamond, label="CLI OK?"]
|
||||
|
|
@ -479,7 +479,7 @@ Create integration tests in test/:
|
|||
|
||||
Run: go test ./test/...
|
||||
|
||||
Write status.json: outcome=success if integration tests pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if integration tests pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_integration [
|
||||
|
|
@ -500,7 +500,7 @@ Check:
|
|||
- Project builds cleanly
|
||||
|
||||
Write results to .ai/verify_integration.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with details otherwise."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with details otherwise."
|
||||
]
|
||||
|
||||
check_integration [shape=diamond, label="Integration OK?"]
|
||||
|
|
@ -543,7 +543,7 @@ Perform final review of the complete linkcheck implementation:
|
|||
- go build ./...
|
||||
|
||||
Write detailed review to .ai/final_review.md.
|
||||
Write status.json: outcome=success if complete and working, outcome=fail with specific issues that need fixing."
|
||||
Write status.json: outcome=succeeded if complete and working, outcome=failed with specific issues that need fixing."
|
||||
]
|
||||
|
||||
check_review [shape=diamond, label="Review OK?"]
|
||||
|
|
@ -551,42 +551,42 @@ Write status.json: outcome=success if complete and working, outcome=fail with sp
|
|||
// Graph flow
|
||||
start -> expand_spec -> impl_setup -> verify_setup -> check_setup
|
||||
|
||||
check_setup -> impl_types [condition="outcome=success"]
|
||||
check_setup -> impl_setup [condition="outcome=fail", label="retry"]
|
||||
check_setup -> impl_types [condition="outcome=succeeded"]
|
||||
check_setup -> impl_setup [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_types -> verify_types -> check_types
|
||||
check_types -> impl_robotstxt [condition="outcome=success"]
|
||||
check_types -> impl_types [condition="outcome=fail", label="retry"]
|
||||
check_types -> impl_robotstxt [condition="outcome=succeeded"]
|
||||
check_types -> impl_types [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_robotstxt -> verify_robotstxt -> check_robotstxt
|
||||
check_robotstxt -> impl_checker [condition="outcome=success"]
|
||||
check_robotstxt -> impl_robotstxt [condition="outcome=fail", label="retry"]
|
||||
check_robotstxt -> impl_checker [condition="outcome=succeeded"]
|
||||
check_robotstxt -> impl_robotstxt [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_checker -> verify_checker -> check_checker
|
||||
check_checker -> impl_extractor [condition="outcome=success"]
|
||||
check_checker -> impl_checker [condition="outcome=fail", label="retry"]
|
||||
check_checker -> impl_extractor [condition="outcome=succeeded"]
|
||||
check_checker -> impl_checker [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_extractor -> verify_extractor -> check_extractor
|
||||
check_extractor -> impl_crawler [condition="outcome=success"]
|
||||
check_extractor -> impl_extractor [condition="outcome=fail", label="retry"]
|
||||
check_extractor -> impl_crawler [condition="outcome=succeeded"]
|
||||
check_extractor -> impl_extractor [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_crawler -> verify_crawler -> check_crawler
|
||||
check_crawler -> impl_report [condition="outcome=success"]
|
||||
check_crawler -> impl_crawler [condition="outcome=fail", label="retry"]
|
||||
check_crawler -> impl_report [condition="outcome=succeeded"]
|
||||
check_crawler -> impl_crawler [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_report -> verify_report -> check_report
|
||||
check_report -> impl_cli [condition="outcome=success"]
|
||||
check_report -> impl_report [condition="outcome=fail", label="retry"]
|
||||
check_report -> impl_cli [condition="outcome=succeeded"]
|
||||
check_report -> impl_report [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_cli -> verify_cli -> check_cli
|
||||
check_cli -> impl_integration [condition="outcome=success"]
|
||||
check_cli -> impl_cli [condition="outcome=fail", label="retry"]
|
||||
check_cli -> impl_integration [condition="outcome=succeeded"]
|
||||
check_cli -> impl_cli [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_integration -> verify_integration -> check_integration
|
||||
check_integration -> review [condition="outcome=success"]
|
||||
check_integration -> impl_integration [condition="outcome=fail", label="retry"]
|
||||
check_integration -> review [condition="outcome=succeeded"]
|
||||
check_integration -> impl_integration [condition="outcome=failed", label="retry"]
|
||||
|
||||
review -> check_review
|
||||
check_review -> exit [condition="outcome=success"]
|
||||
check_review -> impl_cli [condition="outcome=fail", label="fix"]
|
||||
check_review -> exit [condition="outcome=succeeded"]
|
||||
check_review -> impl_cli [condition="outcome=failed", label="fix"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ Create:
|
|||
|
||||
Run: go build ./...
|
||||
|
||||
Write status.json: outcome=success if project builds, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if project builds, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_setup [
|
||||
|
|
@ -46,7 +46,7 @@ Run:
|
|||
3. Check that all required directories exist
|
||||
|
||||
Write results to .ai/verify_setup.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_setup [shape=diamond, label="Setup OK?"]
|
||||
|
|
@ -77,7 +77,7 @@ Acceptance:
|
|||
- go build ./...
|
||||
- go test ./pkg/game/
|
||||
|
||||
Write status.json: outcome=success if all criteria pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all criteria pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_core_types [
|
||||
|
|
@ -93,7 +93,7 @@ Run:
|
|||
4. Check test coverage: go test -cover ./pkg/game/
|
||||
|
||||
Write results to .ai/verify_core_types.md.
|
||||
Write status.json: outcome=success if ALL pass and coverage >70%, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass and coverage >70%, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_core_types [shape=diamond, label="Types OK?"]
|
||||
|
|
@ -140,7 +140,7 @@ Acceptance:
|
|||
- go build ./...
|
||||
- go test ./pkg/game/ -v (all tests pass)
|
||||
|
||||
Write status.json: outcome=success if all criteria pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all criteria pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_game_logic [
|
||||
|
|
@ -156,7 +156,7 @@ Run:
|
|||
4. go test -cover ./pkg/game/ (check for >80% coverage)
|
||||
|
||||
Write results to .ai/verify_game_logic.md.
|
||||
Write status.json: outcome=success if ALL pass with good coverage, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass with good coverage, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_game_logic [shape=diamond, label="Logic OK?"]
|
||||
|
|
@ -194,7 +194,7 @@ Acceptance:
|
|||
- go build ./...
|
||||
- go test ./pkg/ui/
|
||||
|
||||
Write status.json: outcome=success if all criteria pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all criteria pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_ui_render [
|
||||
|
|
@ -210,7 +210,7 @@ Run:
|
|||
4. Check that bubbletea dependency is properly added to go.mod
|
||||
|
||||
Write results to .ai/verify_ui_render.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_ui_render [shape=diamond, label="Render OK?"]
|
||||
|
|
@ -255,7 +255,7 @@ Acceptance:
|
|||
- Binary runs and displays game (manual check)
|
||||
- All keyboard controls work (manual check)
|
||||
|
||||
Write status.json: outcome=success if builds and runs, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if builds and runs, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_ui_input [
|
||||
|
|
@ -272,7 +272,7 @@ Run:
|
|||
5. Check that binary exists at ./cmd/solitaire/solitaire
|
||||
|
||||
Write results to .ai/verify_ui_input.md.
|
||||
Write status.json: outcome=success if ALL pass and binary exists, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass and binary exists, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_ui_input [shape=diamond, label="Input OK?"]
|
||||
|
|
@ -312,7 +312,7 @@ Acceptance:
|
|||
- go test ./pkg/storage/
|
||||
- Manual test: save game, quit, restart with --load
|
||||
|
||||
Write status.json: outcome=success if all criteria pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all criteria pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_persistence [
|
||||
|
|
@ -328,7 +328,7 @@ Run:
|
|||
4. go test ./... (all tests)
|
||||
|
||||
Write results to .ai/verify_persistence.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_persistence [shape=diamond, label="Persist OK?"]
|
||||
|
|
@ -368,7 +368,7 @@ Acceptance:
|
|||
- All keyboard commands work
|
||||
- Game is winnable
|
||||
|
||||
Write status.json: outcome=success if all criteria pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all criteria pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_integration [
|
||||
|
|
@ -387,7 +387,7 @@ Run:
|
|||
7. Verify README exists and has instructions
|
||||
|
||||
Write results to .ai/verify_integration.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_integration [shape=diamond, label="Integration OK?"]
|
||||
|
|
@ -425,7 +425,7 @@ Verify:
|
|||
Run full test suite and manual gameplay check.
|
||||
|
||||
Write comprehensive review to .ai/final_review.md.
|
||||
Write status.json: outcome=success if COMPLETE per spec, outcome=fail with specific missing items."
|
||||
Write status.json: outcome=succeeded if COMPLETE per spec, outcome=failed with specific missing items."
|
||||
]
|
||||
|
||||
check_review [shape=diamond, label="Review OK?"]
|
||||
|
|
@ -434,40 +434,40 @@ Write status.json: outcome=success if COMPLETE per spec, outcome=fail with speci
|
|||
start -> impl_setup
|
||||
impl_setup -> verify_setup
|
||||
verify_setup -> check_setup
|
||||
check_setup -> impl_core_types [condition="outcome=success"]
|
||||
check_setup -> impl_setup [condition="outcome=fail", label="retry"]
|
||||
check_setup -> impl_core_types [condition="outcome=succeeded"]
|
||||
check_setup -> impl_setup [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_core_types -> verify_core_types
|
||||
verify_core_types -> check_core_types
|
||||
check_core_types -> impl_game_logic [condition="outcome=success"]
|
||||
check_core_types -> impl_core_types [condition="outcome=fail", label="retry"]
|
||||
check_core_types -> impl_game_logic [condition="outcome=succeeded"]
|
||||
check_core_types -> impl_core_types [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_game_logic -> verify_game_logic
|
||||
verify_game_logic -> check_game_logic
|
||||
check_game_logic -> impl_ui_render [condition="outcome=success"]
|
||||
check_game_logic -> impl_game_logic [condition="outcome=fail", label="retry"]
|
||||
check_game_logic -> impl_ui_render [condition="outcome=succeeded"]
|
||||
check_game_logic -> impl_game_logic [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_ui_render -> verify_ui_render
|
||||
verify_ui_render -> check_ui_render
|
||||
check_ui_render -> impl_ui_input [condition="outcome=success"]
|
||||
check_ui_render -> impl_ui_render [condition="outcome=fail", label="retry"]
|
||||
check_ui_render -> impl_ui_input [condition="outcome=succeeded"]
|
||||
check_ui_render -> impl_ui_render [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_ui_input -> verify_ui_input
|
||||
verify_ui_input -> check_ui_input
|
||||
check_ui_input -> impl_persistence [condition="outcome=success"]
|
||||
check_ui_input -> impl_ui_input [condition="outcome=fail", label="retry"]
|
||||
check_ui_input -> impl_persistence [condition="outcome=succeeded"]
|
||||
check_ui_input -> impl_ui_input [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_persistence -> verify_persistence
|
||||
verify_persistence -> check_persistence
|
||||
check_persistence -> impl_integration [condition="outcome=success"]
|
||||
check_persistence -> impl_persistence [condition="outcome=fail", label="retry"]
|
||||
check_persistence -> impl_integration [condition="outcome=succeeded"]
|
||||
check_persistence -> impl_persistence [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_integration -> verify_integration
|
||||
verify_integration -> check_integration
|
||||
check_integration -> review [condition="outcome=success"]
|
||||
check_integration -> impl_integration [condition="outcome=fail", label="retry"]
|
||||
check_integration -> review [condition="outcome=succeeded"]
|
||||
check_integration -> impl_integration [condition="outcome=failed", label="retry"]
|
||||
|
||||
review -> check_review
|
||||
check_review -> exit [condition="outcome=success"]
|
||||
check_review -> impl_integration [condition="outcome=fail", label="fix"]
|
||||
check_review -> exit [condition="outcome=succeeded"]
|
||||
check_review -> impl_integration [condition="outcome=failed", label="fix"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ Create Go project structure:
|
|||
|
||||
Run: go build ./...
|
||||
|
||||
Write status.json: outcome=success if builds, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if builds, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_setup [
|
||||
|
|
@ -45,7 +45,7 @@ Run:
|
|||
3. Check that pkg/dttf/types.go exists and contains all required types from specs/dttf-v1.md section 7.1
|
||||
|
||||
Write results to .ai/verify_setup.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_setup [shape=diamond, label="Setup OK?"]
|
||||
|
|
@ -71,7 +71,7 @@ Acceptance:
|
|||
- go build ./...
|
||||
- go test ./pkg/dttf/... -v
|
||||
|
||||
Write status.json: outcome=success if all pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_loader [
|
||||
|
|
@ -85,7 +85,7 @@ Run:
|
|||
3. go test ./pkg/dttf/... -v -run Loader
|
||||
|
||||
Write results to .ai/verify_loader.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_loader [shape=diamond, label="Loader OK?"]
|
||||
|
|
@ -115,7 +115,7 @@ Acceptance:
|
|||
- go build ./...
|
||||
- go test ./pkg/dttf/... -v -run Tracer
|
||||
|
||||
Write status.json: outcome=success if all pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_tracer [
|
||||
|
|
@ -131,7 +131,7 @@ Run:
|
|||
5. Verify winding direction enforcement (section 3.2 Phase 4)
|
||||
|
||||
Write results to .ai/verify_tracer.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_tracer [shape=diamond, label="Tracer OK?"]
|
||||
|
|
@ -155,7 +155,7 @@ Acceptance:
|
|||
- go build ./...
|
||||
- go test ./pkg/dttf/... -v -run Metrics
|
||||
|
||||
Write status.json: outcome=success if all pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_metrics [
|
||||
|
|
@ -169,7 +169,7 @@ Run:
|
|||
3. go test ./pkg/dttf/... -v -run Metrics
|
||||
|
||||
Write results to .ai/verify_metrics.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_metrics [shape=diamond, label="Metrics OK?"]
|
||||
|
|
@ -199,7 +199,7 @@ Acceptance:
|
|||
- go build ./...
|
||||
- go test ./pkg/dttf/... -v -run Tables
|
||||
|
||||
Write status.json: outcome=success if all pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_tables [
|
||||
|
|
@ -215,7 +215,7 @@ Run:
|
|||
5. Verify checksums are computed correctly
|
||||
|
||||
Write results to .ai/verify_tables.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_tables [shape=diamond, label="Tables OK?"]
|
||||
|
|
@ -246,7 +246,7 @@ Acceptance:
|
|||
- go build ./...
|
||||
- go test ./pkg/dttf/... -v
|
||||
|
||||
Write status.json: outcome=success if all pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_writer [
|
||||
|
|
@ -261,7 +261,7 @@ Run:
|
|||
4. go test ./pkg/dttf/... -v -run Build
|
||||
|
||||
Write results to .ai/verify_writer.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_writer [shape=diamond, label="Writer OK?"]
|
||||
|
|
@ -288,7 +288,7 @@ Acceptance:
|
|||
- go build ./...
|
||||
- go test ./pkg/dttf/... -v -run Validator
|
||||
|
||||
Write status.json: outcome=success if all pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_validator [
|
||||
|
|
@ -302,7 +302,7 @@ Run:
|
|||
3. go test ./pkg/dttf/... -v -run Validator
|
||||
|
||||
Write results to .ai/verify_validator.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_validator [shape=diamond, label="Validator OK?"]
|
||||
|
|
@ -329,7 +329,7 @@ Acceptance:
|
|||
- go build ./...
|
||||
- go test ./pkg/dttf/... -v -run Rasterizer
|
||||
|
||||
Write status.json: outcome=success if all pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_rasterizer [
|
||||
|
|
@ -343,7 +343,7 @@ Run:
|
|||
3. go test ./pkg/dttf/... -v -run Rasterizer
|
||||
|
||||
Write results to .ai/verify_rasterizer.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_rasterizer [shape=diamond, label="Rasterizer OK?"]
|
||||
|
|
@ -369,7 +369,7 @@ Acceptance:
|
|||
- ./cmd/dttf/dttf --help
|
||||
- Test each command with --help
|
||||
|
||||
Write status.json: outcome=success if all commands work, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all commands work, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_cli [
|
||||
|
|
@ -387,7 +387,7 @@ Run:
|
|||
7. ./cmd/dttf/dttf test --help
|
||||
|
||||
Write results to .ai/verify_cli.md.
|
||||
Write status.json: outcome=success if ALL commands exist and show help, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL commands exist and show help, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_cli [shape=diamond, label="CLI OK?"]
|
||||
|
|
@ -420,7 +420,7 @@ Acceptance:
|
|||
- go test ./pkg/dttf/... -v -run TestHarness
|
||||
- dttf test --help shows correct options
|
||||
|
||||
Write status.json: outcome=success if all pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_test_harness [
|
||||
|
|
@ -436,7 +436,7 @@ Run:
|
|||
5. Verify reference font download works
|
||||
|
||||
Write results to .ai/verify_test_harness.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_test_harness [shape=diamond, label="Test Harness OK?"]
|
||||
|
|
@ -463,7 +463,7 @@ Acceptance:
|
|||
- Output font is valid
|
||||
- SSIM > 0.90 (acceptable threshold from section 5.2)
|
||||
|
||||
Write status.json: outcome=success if all criteria pass, outcome=fail with failure_reason and specific metrics otherwise."
|
||||
Write status.json: outcome=succeeded if all criteria pass, outcome=failed with failure_reason and specific metrics otherwise."
|
||||
]
|
||||
|
||||
verify_integration [
|
||||
|
|
@ -478,7 +478,7 @@ Run:
|
|||
4. go test ./... (full test suite)
|
||||
|
||||
Write results to .ai/verify_integration.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_integration [shape=diamond, label="Integration OK?"]
|
||||
|
|
@ -513,57 +513,57 @@ Run:
|
|||
- dttf test --reference-dir <test-fonts>/ if available
|
||||
|
||||
Write comprehensive review to .ai/final_review.md.
|
||||
Write status.json: outcome=success if complete and spec-compliant, outcome=fail with specific missing/incorrect features otherwise."
|
||||
Write status.json: outcome=succeeded if complete and spec-compliant, outcome=failed with specific missing/incorrect features otherwise."
|
||||
]
|
||||
|
||||
check_review [shape=diamond, label="Review OK?"]
|
||||
|
||||
// Flow
|
||||
start -> impl_setup -> verify_setup -> check_setup
|
||||
check_setup -> impl_loader [condition="outcome=success"]
|
||||
check_setup -> impl_setup [condition="outcome=fail", label="retry"]
|
||||
check_setup -> impl_loader [condition="outcome=succeeded"]
|
||||
check_setup -> impl_setup [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_loader -> verify_loader -> check_loader
|
||||
check_loader -> impl_tracer [condition="outcome=success"]
|
||||
check_loader -> impl_loader [condition="outcome=fail", label="retry"]
|
||||
check_loader -> impl_tracer [condition="outcome=succeeded"]
|
||||
check_loader -> impl_loader [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_tracer -> verify_tracer -> check_tracer
|
||||
check_tracer -> impl_metrics [condition="outcome=success"]
|
||||
check_tracer -> impl_tracer [condition="outcome=fail", label="retry"]
|
||||
check_tracer -> impl_metrics [condition="outcome=succeeded"]
|
||||
check_tracer -> impl_tracer [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_metrics -> verify_metrics -> check_metrics
|
||||
check_metrics -> impl_tables [condition="outcome=success"]
|
||||
check_metrics -> impl_metrics [condition="outcome=fail", label="retry"]
|
||||
check_metrics -> impl_tables [condition="outcome=succeeded"]
|
||||
check_metrics -> impl_metrics [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_tables -> verify_tables -> check_tables
|
||||
check_tables -> impl_writer [condition="outcome=success"]
|
||||
check_tables -> impl_tables [condition="outcome=fail", label="retry"]
|
||||
check_tables -> impl_writer [condition="outcome=succeeded"]
|
||||
check_tables -> impl_tables [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_writer -> verify_writer -> check_writer
|
||||
check_writer -> impl_validator [condition="outcome=success"]
|
||||
check_writer -> impl_writer [condition="outcome=fail", label="retry"]
|
||||
check_writer -> impl_validator [condition="outcome=succeeded"]
|
||||
check_writer -> impl_writer [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_validator -> verify_validator -> check_validator
|
||||
check_validator -> impl_rasterizer [condition="outcome=success"]
|
||||
check_validator -> impl_validator [condition="outcome=fail", label="retry"]
|
||||
check_validator -> impl_rasterizer [condition="outcome=succeeded"]
|
||||
check_validator -> impl_validator [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_rasterizer -> verify_rasterizer -> check_rasterizer
|
||||
check_rasterizer -> impl_cli [condition="outcome=success"]
|
||||
check_rasterizer -> impl_rasterizer [condition="outcome=fail", label="retry"]
|
||||
check_rasterizer -> impl_cli [condition="outcome=succeeded"]
|
||||
check_rasterizer -> impl_rasterizer [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_cli -> verify_cli -> check_cli
|
||||
check_cli -> impl_test_harness [condition="outcome=success"]
|
||||
check_cli -> impl_cli [condition="outcome=fail", label="retry"]
|
||||
check_cli -> impl_test_harness [condition="outcome=succeeded"]
|
||||
check_cli -> impl_cli [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_test_harness -> verify_test_harness -> check_test_harness
|
||||
check_test_harness -> impl_integration [condition="outcome=success"]
|
||||
check_test_harness -> impl_test_harness [condition="outcome=fail", label="retry"]
|
||||
check_test_harness -> impl_integration [condition="outcome=succeeded"]
|
||||
check_test_harness -> impl_test_harness [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_integration -> verify_integration -> check_integration
|
||||
check_integration -> review [condition="outcome=success"]
|
||||
check_integration -> impl_integration [condition="outcome=fail", label="retry"]
|
||||
check_integration -> review [condition="outcome=succeeded"]
|
||||
check_integration -> impl_integration [condition="outcome=failed", label="retry"]
|
||||
|
||||
review -> check_review
|
||||
check_review -> exit [condition="outcome=success"]
|
||||
check_review -> impl_integration [condition="outcome=fail", label="fix"]
|
||||
check_review -> exit [condition="outcome=succeeded"]
|
||||
check_review -> impl_integration [condition="outcome=failed", label="fix"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ Expand into a detailed spec covering:
|
|||
|
||||
Write the spec to .ai/spec.md.
|
||||
|
||||
Write status.json: outcome=success"
|
||||
Write status.json: outcome=succeeded"
|
||||
]
|
||||
|
||||
// Project setup
|
||||
|
|
@ -56,7 +56,7 @@ Acceptance:
|
|||
- `go build ./...` must pass
|
||||
- Directory structure matches spec
|
||||
|
||||
Write status.json: outcome=success if all pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_setup [
|
||||
|
|
@ -72,7 +72,7 @@ Run:
|
|||
5. Check that pkg/ subdirectories exist
|
||||
|
||||
Write results to .ai/verify_setup.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_setup [shape=diamond, label="Setup OK?"]
|
||||
|
|
@ -104,7 +104,7 @@ Acceptance:
|
|||
- `go build ./...` must pass
|
||||
- `go test ./pkg/crawler/...` must pass with all tests
|
||||
|
||||
Write status.json: outcome=success if all criteria pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all criteria pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_crawler [
|
||||
|
|
@ -120,7 +120,7 @@ Run:
|
|||
5. Check that tests cover FetchPage and ExtractLinks
|
||||
|
||||
Write results to .ai/verify_crawler.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_crawler [shape=diamond, label="Crawler OK?"]
|
||||
|
|
@ -148,7 +148,7 @@ Acceptance:
|
|||
- `go build ./...` must pass
|
||||
- `go test ./pkg/robots/...` must pass
|
||||
|
||||
Write status.json: outcome=success if all criteria pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all criteria pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_robots [
|
||||
|
|
@ -163,7 +163,7 @@ Run:
|
|||
4. Check that pkg/robots/robots.go exists
|
||||
|
||||
Write results to .ai/verify_robots.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_robots [shape=diamond, label="Robots OK?"]
|
||||
|
|
@ -194,7 +194,7 @@ Acceptance:
|
|||
- `go build ./...` must pass
|
||||
- `go test ./pkg/checker/...` must pass
|
||||
|
||||
Write status.json: outcome=success if all criteria pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all criteria pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_checker [
|
||||
|
|
@ -209,7 +209,7 @@ Run:
|
|||
4. Check that pkg/checker/checker.go exists
|
||||
|
||||
Write results to .ai/verify_checker.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_checker [shape=diamond, label="Checker OK?"]
|
||||
|
|
@ -238,7 +238,7 @@ Acceptance:
|
|||
- `go build ./...` must pass
|
||||
- `go test ./pkg/formatter/...` must pass
|
||||
|
||||
Write status.json: outcome=success if all criteria pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all criteria pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_formatter [
|
||||
|
|
@ -253,7 +253,7 @@ Run:
|
|||
4. Check that both text.go and json.go exist
|
||||
|
||||
Write results to .ai/verify_formatter.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_formatter [shape=diamond, label="Formatter OK?"]
|
||||
|
|
@ -278,7 +278,7 @@ Acceptance:
|
|||
- `./linkcheck --help` shows usage
|
||||
- `./linkcheck https://example.com` runs without error
|
||||
|
||||
Write status.json: outcome=success if all criteria pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all criteria pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_cli [
|
||||
|
|
@ -293,7 +293,7 @@ Run:
|
|||
4. Check that main.go wires all packages together
|
||||
|
||||
Write results to .ai/verify_cli.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_cli [shape=diamond, label="CLI OK?"]
|
||||
|
|
@ -318,7 +318,7 @@ Acceptance:
|
|||
- `go test ./...` must pass (all tests)
|
||||
- Integration test validates end-to-end functionality
|
||||
|
||||
Write status.json: outcome=success if all criteria pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all criteria pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_integration [
|
||||
|
|
@ -332,7 +332,7 @@ Run:
|
|||
3. Check that integration test covers depth, format, robots.txt
|
||||
|
||||
Write results to .ai/verify_integration.md.
|
||||
Write status.json: outcome=success if ALL pass, outcome=fail with details."
|
||||
Write status.json: outcome=succeeded if ALL pass, outcome=failed with details."
|
||||
]
|
||||
|
||||
check_integration [shape=diamond, label="Integration OK?"]
|
||||
|
|
@ -360,41 +360,41 @@ Run:
|
|||
3. Manual test: `./linkcheck https://example.com --depth 1 --format json`
|
||||
|
||||
Write review to .ai/final_review.md.
|
||||
Write status.json: outcome=success if complete and correct, outcome=fail with what's missing or broken."
|
||||
Write status.json: outcome=succeeded if complete and correct, outcome=failed with what's missing or broken."
|
||||
]
|
||||
|
||||
check_review [shape=diamond, label="Review OK?"]
|
||||
|
||||
// Flow
|
||||
start -> expand_spec -> impl_setup -> verify_setup -> check_setup
|
||||
check_setup -> impl_crawler [condition="outcome=success"]
|
||||
check_setup -> impl_setup [condition="outcome=fail", label="retry"]
|
||||
check_setup -> impl_crawler [condition="outcome=succeeded"]
|
||||
check_setup -> impl_setup [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_crawler -> verify_crawler -> check_crawler
|
||||
check_crawler -> impl_robots [condition="outcome=success"]
|
||||
check_crawler -> impl_crawler [condition="outcome=fail", label="retry"]
|
||||
check_crawler -> impl_robots [condition="outcome=succeeded"]
|
||||
check_crawler -> impl_crawler [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_robots -> verify_robots -> check_robots
|
||||
check_robots -> impl_checker [condition="outcome=success"]
|
||||
check_robots -> impl_robots [condition="outcome=fail", label="retry"]
|
||||
check_robots -> impl_checker [condition="outcome=succeeded"]
|
||||
check_robots -> impl_robots [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_checker -> verify_checker -> check_checker
|
||||
check_checker -> impl_formatter [condition="outcome=success"]
|
||||
check_checker -> impl_checker [condition="outcome=fail", label="retry"]
|
||||
check_checker -> impl_formatter [condition="outcome=succeeded"]
|
||||
check_checker -> impl_checker [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_formatter -> verify_formatter -> check_formatter
|
||||
check_formatter -> impl_cli [condition="outcome=success"]
|
||||
check_formatter -> impl_formatter [condition="outcome=fail", label="retry"]
|
||||
check_formatter -> impl_cli [condition="outcome=succeeded"]
|
||||
check_formatter -> impl_formatter [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_cli -> verify_cli -> check_cli
|
||||
check_cli -> impl_integration [condition="outcome=success"]
|
||||
check_cli -> impl_cli [condition="outcome=fail", label="retry"]
|
||||
check_cli -> impl_integration [condition="outcome=succeeded"]
|
||||
check_cli -> impl_cli [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_integration -> verify_integration -> check_integration
|
||||
check_integration -> review [condition="outcome=success"]
|
||||
check_integration -> impl_integration [condition="outcome=fail", label="retry"]
|
||||
check_integration -> review [condition="outcome=succeeded"]
|
||||
check_integration -> impl_integration [condition="outcome=failed", label="retry"]
|
||||
|
||||
review -> check_review
|
||||
check_review -> exit [condition="outcome=success"]
|
||||
check_review -> impl_integration [condition="outcome=fail", label="fix"]
|
||||
check_review -> exit [condition="outcome=succeeded"]
|
||||
check_review -> impl_integration [condition="outcome=failed", label="fix"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ Expand into a detailed spec covering:
|
|||
|
||||
Write the spec to .ai/spec.md.
|
||||
|
||||
Write status.json: outcome=success"
|
||||
Write status.json: outcome=succeeded"
|
||||
]
|
||||
|
||||
// Project setup
|
||||
|
|
@ -50,7 +50,7 @@ Run the appropriate build command:
|
|||
- Go: go build ./...
|
||||
- Rust: cargo build
|
||||
|
||||
Write status.json: outcome=success if project structure is created and builds, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if project structure is created and builds, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_setup [
|
||||
|
|
@ -68,7 +68,7 @@ Run:
|
|||
4. Verify no syntax errors
|
||||
|
||||
Write results to .ai/verify_setup.md.
|
||||
Write status.json: outcome=success if ALL checks pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if ALL checks pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
check_setup [shape=diamond, label="Setup OK?"]
|
||||
|
|
@ -93,7 +93,7 @@ Run appropriate test command:
|
|||
- Go: go test ./...
|
||||
- Rust: cargo test
|
||||
|
||||
Write status.json: outcome=success if all tests pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all tests pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_data_structures [
|
||||
|
|
@ -114,7 +114,7 @@ Run:
|
|||
4. Verify basic operations work (create deck, shuffle, deal)
|
||||
|
||||
Write results to .ai/verify_data_structures.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with failure_reason."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason."
|
||||
]
|
||||
|
||||
check_data_structures [shape=diamond, label="Data structures OK?"]
|
||||
|
|
@ -146,7 +146,7 @@ Run tests for the chosen language ONLY (do not run other language commands):
|
|||
- Go: go test ./... -v
|
||||
- Rust: cargo test -- --nocapture
|
||||
|
||||
Write status.json: outcome=success if all tests pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all tests pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_game_logic [
|
||||
|
|
@ -168,7 +168,7 @@ Run:
|
|||
5. Test undo functionality
|
||||
|
||||
Write results to .ai/verify_game_logic.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with failure_reason."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason."
|
||||
]
|
||||
|
||||
check_game_logic [shape=diamond, label="Game logic OK?"]
|
||||
|
|
@ -203,7 +203,7 @@ Run for the chosen language ONLY (do not run other language commands):
|
|||
- Go: go build ./... && go test ./...
|
||||
- Rust: cargo build && cargo test
|
||||
|
||||
Write status.json: outcome=success if builds and tests pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if builds and tests pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_terminal_ui [
|
||||
|
|
@ -225,7 +225,7 @@ Run:
|
|||
5. Test that rendering doesn't crash with empty game state
|
||||
|
||||
Write results to .ai/verify_terminal_ui.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with failure_reason."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason."
|
||||
]
|
||||
|
||||
check_terminal_ui [shape=diamond, label="Terminal UI OK?"]
|
||||
|
|
@ -256,7 +256,7 @@ IMPORTANT: Run for the chosen language ONLY (do not run other language commands)
|
|||
- Go: go build ./cmd/solitaire && go test ./...
|
||||
- Rust: cargo build --release && cargo test
|
||||
|
||||
Write status.json: outcome=success if game runs and all tests pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if game runs and all tests pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_integration [
|
||||
|
|
@ -278,7 +278,7 @@ Run:
|
|||
5. Test that game starts without errors
|
||||
|
||||
Write results to .ai/verify_integration.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with failure_reason."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason."
|
||||
]
|
||||
|
||||
check_integration [shape=diamond, label="Integration OK?"]
|
||||
|
|
@ -314,33 +314,33 @@ Write detailed review to .ai/final_review.md including:
|
|||
- Any issues found
|
||||
- Compliance with spec
|
||||
|
||||
Write status.json: outcome=success if the game is complete and playable per spec, outcome=fail with what's missing or broken."
|
||||
Write status.json: outcome=succeeded if the game is complete and playable per spec, outcome=failed with what's missing or broken."
|
||||
]
|
||||
|
||||
check_review [shape=diamond, label="Review OK?"]
|
||||
|
||||
// Flow
|
||||
start -> expand_spec -> impl_setup -> verify_setup -> check_setup
|
||||
check_setup -> impl_data_structures [condition="outcome=success"]
|
||||
check_setup -> impl_setup [condition="outcome=fail", label="retry"]
|
||||
check_setup -> impl_data_structures [condition="outcome=succeeded"]
|
||||
check_setup -> impl_setup [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_data_structures -> verify_data_structures -> check_data_structures
|
||||
check_data_structures -> impl_game_logic [condition="outcome=success"]
|
||||
check_data_structures -> impl_data_structures [condition="outcome=fail", label="retry"]
|
||||
check_data_structures -> impl_game_logic [condition="outcome=succeeded"]
|
||||
check_data_structures -> impl_data_structures [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_game_logic -> verify_game_logic -> check_game_logic
|
||||
check_game_logic -> impl_terminal_ui [condition="outcome=success"]
|
||||
check_game_logic -> impl_game_logic [condition="outcome=fail", label="retry"]
|
||||
check_game_logic -> impl_terminal_ui [condition="outcome=succeeded"]
|
||||
check_game_logic -> impl_game_logic [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_terminal_ui -> verify_terminal_ui -> check_terminal_ui
|
||||
check_terminal_ui -> impl_integration [condition="outcome=success"]
|
||||
check_terminal_ui -> impl_terminal_ui [condition="outcome=fail", label="retry"]
|
||||
check_terminal_ui -> impl_integration [condition="outcome=succeeded"]
|
||||
check_terminal_ui -> impl_terminal_ui [condition="outcome=failed", label="retry"]
|
||||
|
||||
impl_integration -> verify_integration -> check_integration
|
||||
check_integration -> review [condition="outcome=success"]
|
||||
check_integration -> impl_integration [condition="outcome=fail", label="retry"]
|
||||
check_integration -> review [condition="outcome=succeeded"]
|
||||
check_integration -> impl_integration [condition="outcome=failed", label="retry"]
|
||||
|
||||
review -> check_review
|
||||
check_review -> exit [condition="outcome=success"]
|
||||
check_review -> impl_terminal_ui [condition="outcome=fail", label="fix"]
|
||||
check_review -> exit [condition="outcome=succeeded"]
|
||||
check_review -> impl_terminal_ui [condition="outcome=failed", label="fix"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -309,9 +309,9 @@ digraph reference_template {
|
|||
|
||||
// Linear start: toolchain gate -> spec -> DoD check
|
||||
start -> check_toolchain
|
||||
check_toolchain -> expand_spec [condition="outcome=success"]
|
||||
check_toolchain -> check_toolchain [condition="outcome=fail && context.failure_class=transient_infra", loop_restart=true]
|
||||
check_toolchain -> postmortem [condition="outcome=fail && context.failure_class!=transient_infra"]
|
||||
check_toolchain -> expand_spec [condition="outcome=succeeded"]
|
||||
check_toolchain -> check_toolchain [condition="outcome=failed && context.failure_class=transient_infra", loop_restart=true]
|
||||
check_toolchain -> postmortem [condition="outcome=failed && context.failure_class!=transient_infra"]
|
||||
check_toolchain -> postmortem
|
||||
expand_spec -> check_dod
|
||||
|
||||
|
|
@ -340,42 +340,42 @@ digraph reference_template {
|
|||
|
||||
// Verify/check inner loop (tool gates first, semantic review last)
|
||||
implement -> check_implement
|
||||
check_implement -> fix_fmt [condition="outcome=success"]
|
||||
check_implement -> fix_fmt [condition="outcome=succeeded"]
|
||||
fix_fmt -> verify_fmt
|
||||
check_implement -> implement [condition="outcome=fail && context.failure_class=transient_infra", loop_restart=true]
|
||||
check_implement -> postmortem [condition="outcome=fail && context.failure_class!=transient_infra"]
|
||||
check_implement -> implement [condition="outcome=failed && context.failure_class=transient_infra", loop_restart=true]
|
||||
check_implement -> postmortem [condition="outcome=failed && context.failure_class!=transient_infra"]
|
||||
check_implement -> postmortem
|
||||
verify_fmt -> check_fmt
|
||||
check_fmt -> verify_build [condition="outcome=success"]
|
||||
check_fmt -> implement [condition="outcome=fail && context.failure_class=transient_infra", loop_restart=true]
|
||||
check_fmt -> postmortem [condition="outcome=fail && context.failure_class!=transient_infra"]
|
||||
check_fmt -> verify_build [condition="outcome=succeeded"]
|
||||
check_fmt -> implement [condition="outcome=failed && context.failure_class=transient_infra", loop_restart=true]
|
||||
check_fmt -> postmortem [condition="outcome=failed && context.failure_class!=transient_infra"]
|
||||
check_fmt -> postmortem
|
||||
|
||||
verify_build -> check_build
|
||||
check_build -> verify_test [condition="outcome=success"]
|
||||
check_build -> implement [condition="outcome=fail && context.failure_class=transient_infra", loop_restart=true]
|
||||
check_build -> postmortem [condition="outcome=fail && context.failure_class!=transient_infra"]
|
||||
check_build -> verify_test [condition="outcome=succeeded"]
|
||||
check_build -> implement [condition="outcome=failed && context.failure_class=transient_infra", loop_restart=true]
|
||||
check_build -> postmortem [condition="outcome=failed && context.failure_class!=transient_infra"]
|
||||
check_build -> postmortem
|
||||
|
||||
verify_test -> check_test
|
||||
check_test -> verify_artifacts [condition="outcome=success"]
|
||||
check_test -> implement [condition="outcome=fail && context.failure_class=transient_infra", loop_restart=true]
|
||||
check_test -> postmortem [condition="outcome=fail && context.failure_class!=transient_infra"]
|
||||
check_test -> verify_artifacts [condition="outcome=succeeded"]
|
||||
check_test -> implement [condition="outcome=failed && context.failure_class=transient_infra", loop_restart=true]
|
||||
check_test -> postmortem [condition="outcome=failed && context.failure_class!=transient_infra"]
|
||||
check_test -> postmortem
|
||||
|
||||
verify_artifacts -> check_artifacts
|
||||
check_artifacts -> verify_fidelity [condition="outcome=success"]
|
||||
check_artifacts -> implement [condition="outcome=fail && context.failure_class=transient_infra", loop_restart=true]
|
||||
check_artifacts -> postmortem [condition="outcome=fail && context.failure_class!=transient_infra"]
|
||||
check_artifacts -> verify_fidelity [condition="outcome=succeeded"]
|
||||
check_artifacts -> implement [condition="outcome=failed && context.failure_class=transient_infra", loop_restart=true]
|
||||
check_artifacts -> postmortem [condition="outcome=failed && context.failure_class!=transient_infra"]
|
||||
check_artifacts -> postmortem
|
||||
|
||||
verify_fidelity -> check_impl
|
||||
check_impl -> review_fanout [condition="outcome=success"]
|
||||
check_impl -> review_fanout [condition="outcome=succeeded"]
|
||||
review_fanout -> review_a
|
||||
review_fanout -> review_b
|
||||
review_fanout -> review_c
|
||||
check_impl -> implement [condition="outcome=fail && context.failure_class=transient_infra", loop_restart=true]
|
||||
check_impl -> postmortem [condition="outcome=fail && context.failure_class!=transient_infra"]
|
||||
check_impl -> implement [condition="outcome=failed && context.failure_class=transient_infra", loop_restart=true]
|
||||
check_impl -> postmortem [condition="outcome=failed && context.failure_class!=transient_infra"]
|
||||
check_impl -> postmortem
|
||||
|
||||
// Review fan-in -> consensus
|
||||
|
|
@ -384,11 +384,11 @@ digraph reference_template {
|
|||
review_c -> review_consensus
|
||||
|
||||
// Consensus routing: success -> exit, anything else -> postmortem
|
||||
review_consensus -> exit [condition="outcome=success"]
|
||||
review_consensus -> exit [condition="outcome=succeeded"]
|
||||
review_consensus -> postmortem
|
||||
|
||||
// Domain-routed recovery: classify failure and choose the right re-entry
|
||||
postmortem -> check_toolchain [condition="outcome=fail && context.failure_class=transient_infra"]
|
||||
postmortem -> check_toolchain [condition="outcome=failed && context.failure_class=transient_infra"]
|
||||
postmortem -> implement [condition="outcome=impl_repair"]
|
||||
postmortem -> plan_fanout [condition="outcome=needs_replan"]
|
||||
postmortem -> check_toolchain [condition="outcome=needs_toolchain"]
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ digraph Workflow {
|
|||
|
||||
FinalizeAndUpdateLedger [allow_partial="false", color="#94a3b8", fillcolor="white", fontname="Helvetica", fontsize="12", is_codergen="true", label="6) Finalize & update ledger", model="gpt-5.2-codex", llm_prompt="**Finalize implementation and update ledger in one step.**\\n\\n1. Synthesize the port plan from .ai/semport_plan_sonnet.md and implementation results into .ai/semport_implementation_summary.md. List which upstream commits were processed, what changes were made (with file:line references), and the disposition ('implemented').\\n\\n2. Update the ledger using:\\n```\\npython3 semport/ledger.py update <shortsha> implemented\\npython3 semport/ledger.py sort\\n```\\n\\n3. Verify with `python3 semport/ledger.py stats` to see progress.\\n\\n4. **Commit all changes** (implementation + ledger update) with a clear message:\\n ```\\n git add -A\\n git commit -m \"semport: implement <shortsha> - <brief description of what was ported>\"\\n ```\\n Example: `git commit -m \"semport: implement a776d80 - nest handoff history by default\"`\\n\\nKeep our goal $goal in mind. Then loop back to process the next commit.", margin="0.1,0.08", max_agent_turns="8", node_type="stack.observe", penwidth="1.2", reasoning_effort="high", shape="box", style="rounded,filled", timeout="1200"];
|
||||
|
||||
TestValidate [allow_partial="true", color="#94a3b8", fillcolor="white", fontname="Helvetica", fontsize="12", is_codergen="true", label="5) Test/Validate changes", model="gpt-5.2-codex", llm_prompt="Keeping our goal in mind: $goal. From repo root, validate that all ported changes work correctly. Run relevant tests (go test ./...), ensure compilation succeeds, and verify the ported functionality matches the upstream semantic intent (not necessarily syntax). Write validation results to .ai/semport_validation_report_NN.md. Use outcome=yes if all tests pass and changes are semantically correct; otherwise use outcome=retry with concrete failure details.", margin="0.1,0.08", max_agent_turns="8", node_type="stack.steer", penwidth="1.2", reasoning_effort="high", shape="box", style="rounded,filled", timeout="1800"];
|
||||
TestValidate [allow_partial="true", color="#94a3b8", fillcolor="white", fontname="Helvetica", fontsize="12", is_codergen="true", label="5) Test/Validate changes", model="gpt-5.2-codex", llm_prompt="Keeping our goal in mind: $goal. From repo root, validate that all ported changes work correctly. Run relevant tests (go test ./...), ensure compilation succeeds, and verify the ported functionality matches the upstream semantic intent (not necessarily syntax). Write validation results to .ai/semport_validation_report_NN.md. Use outcome=succeeded if all tests pass and changes are semantically correct; otherwise use outcome=failed with concrete failure details.", margin="0.1,0.08", max_agent_turns="8", node_type="stack.steer", penwidth="1.2", reasoning_effort="high", shape="box", style="rounded,filled", timeout="1800"];
|
||||
|
||||
AnalyzeFailureSonnet [allow_partial="false", color="#94a3b8", fillcolor="white", fontname="Helvetica", fontsize="12", is_codergen="true", label="6a) Analyze failure (sonnet)", model="gpt-5.2-codex", llm_prompt="When tests or validation fail, inspect .ai/semport_validation_report_*.md, logs, diffs, and error messages. Write .ai/semport_failure_sonnet.md summarizing root causes, impacted files (with line references), and what needs to be fixed. Clearly note where failure artifacts are located. Keep our goal $goal in mind and be subjective.", margin="0.1,0.08", max_agent_turns="8", node_type="stack.observe", penwidth="1.2", reasoning_effort="high", shape="box", style="rounded,filled", timeout="1200"];
|
||||
|
||||
|
|
@ -23,8 +23,8 @@ digraph Workflow {
|
|||
Start -> FetchUpstreamSonnet;
|
||||
AnalyzeFailureSonnet -> FinalizeAndUpdateLedger;
|
||||
FinalizePlanGPT -> ImplementPort;
|
||||
TestValidate -> FinalizeAndUpdateLedger [condition="outcome=yes", label="pass"];
|
||||
TestValidate -> AnalyzeFailureSonnet [condition="outcome=retry", label="fail"];
|
||||
TestValidate -> FinalizeAndUpdateLedger [condition="outcome=succeeded", label="pass"];
|
||||
TestValidate -> AnalyzeFailureSonnet [condition="outcome=failed", label="fail"];
|
||||
FetchUpstreamSonnet -> AnalyzePlanSonnet [condition="outcome=process", label="process"];
|
||||
FetchUpstreamSonnet -> Exit [condition="outcome=done", label="done"];
|
||||
ImplementPort -> TestValidate;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ Expand into a detailed spec covering:
|
|||
|
||||
Write the spec to .ai/spec.md.
|
||||
|
||||
Write status.json: outcome=success"
|
||||
Write status.json: outcome=succeeded"
|
||||
]
|
||||
|
||||
// Project setup
|
||||
|
|
@ -50,7 +50,7 @@ Run the appropriate build command:
|
|||
- Go: go build ./...
|
||||
- Rust: cargo build
|
||||
|
||||
Write status.json: outcome=success if project structure is created and builds, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if project structure is created and builds, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_setup [
|
||||
|
|
@ -68,7 +68,7 @@ Run:
|
|||
4. Verify no syntax errors
|
||||
|
||||
Write results to .ai/verify_setup.md.
|
||||
Write status.json: outcome=success if ALL checks pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if ALL checks pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
check_setup [shape=diamond, label="Setup OK?"]
|
||||
|
|
@ -93,7 +93,7 @@ Run appropriate test command:
|
|||
- Go: go test ./...
|
||||
- Rust: cargo test
|
||||
|
||||
Write status.json: outcome=success if all tests pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all tests pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_data_structures [
|
||||
|
|
@ -114,7 +114,7 @@ Run:
|
|||
4. Verify basic operations work (create deck, shuffle, deal)
|
||||
|
||||
Write results to .ai/verify_data_structures.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with failure_reason."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason."
|
||||
]
|
||||
|
||||
check_data_structures [shape=diamond, label="Data structures OK?"]
|
||||
|
|
@ -146,7 +146,7 @@ Run tests for the chosen language ONLY (do not run other language commands):
|
|||
- Go: go test ./... -v
|
||||
- Rust: cargo test -- --nocapture
|
||||
|
||||
Write status.json: outcome=success if all tests pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if all tests pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_game_logic [
|
||||
|
|
@ -168,7 +168,7 @@ Run:
|
|||
5. Test undo functionality
|
||||
|
||||
Write results to .ai/verify_game_logic.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with failure_reason."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason."
|
||||
]
|
||||
|
||||
check_game_logic [shape=diamond, label="Game logic OK?"]
|
||||
|
|
@ -203,7 +203,7 @@ Run for the chosen language ONLY (do not run other language commands):
|
|||
- Go: go build ./... && go test ./...
|
||||
- Rust: cargo build && cargo test
|
||||
|
||||
Write status.json: outcome=success if builds and tests pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if builds and tests pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_terminal_ui [
|
||||
|
|
@ -225,7 +225,7 @@ Run:
|
|||
5. Test that rendering doesn't crash with empty game state
|
||||
|
||||
Write results to .ai/verify_terminal_ui.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with failure_reason."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason."
|
||||
]
|
||||
|
||||
check_terminal_ui [shape=diamond, label="Terminal UI OK?"]
|
||||
|
|
@ -256,7 +256,7 @@ IMPORTANT: Run for the chosen language ONLY (do not run other language commands)
|
|||
- Go: go build ./cmd/solitaire && go test ./...
|
||||
- Rust: cargo build --release && cargo test
|
||||
|
||||
Write status.json: outcome=success if game runs and all tests pass, outcome=fail with failure_reason otherwise."
|
||||
Write status.json: outcome=succeeded if game runs and all tests pass, outcome=failed with failure_reason otherwise."
|
||||
]
|
||||
|
||||
verify_integration [
|
||||
|
|
@ -278,7 +278,7 @@ Run:
|
|||
5. Test that game starts without errors
|
||||
|
||||
Write results to .ai/verify_integration.md.
|
||||
Write status.json: outcome=success if all pass, outcome=fail with failure_reason."
|
||||
Write status.json: outcome=succeeded if all pass, outcome=failed with failure_reason."
|
||||
]
|
||||
|
||||
check_integration [shape=diamond, label="Integration OK?"]
|
||||
|
|
@ -314,39 +314,39 @@ Write detailed review to .ai/final_review.md including:
|
|||
- Any issues found
|
||||
- Compliance with spec
|
||||
|
||||
Write status.json: outcome=success if the game is complete and playable per spec, outcome=fail with what's missing or broken."
|
||||
Write status.json: outcome=succeeded if the game is complete and playable per spec, outcome=failed with what's missing or broken."
|
||||
]
|
||||
|
||||
check_review [shape=diamond, label="Review OK?"]
|
||||
|
||||
// Flow
|
||||
start -> expand_spec -> impl_setup -> verify_setup -> check_setup
|
||||
check_setup -> impl_data_structures [condition="outcome=success"]
|
||||
check_setup -> impl_setup [condition="outcome=fail", label="retry"]
|
||||
check_setup -> impl_data_structures [condition="outcome=succeeded"]
|
||||
check_setup -> impl_setup [condition="outcome=failed", label="retry"]
|
||||
check_setup -> impl_setup [label="fallback"]
|
||||
|
||||
impl_data_structures -> verify_data_structures -> check_data_structures
|
||||
check_data_structures -> impl_game_logic [condition="outcome=success"]
|
||||
check_data_structures -> impl_data_structures [condition="outcome=fail", label="retry"]
|
||||
check_data_structures -> impl_game_logic [condition="outcome=succeeded"]
|
||||
check_data_structures -> impl_data_structures [condition="outcome=failed", label="retry"]
|
||||
check_data_structures -> impl_data_structures [label="fallback"]
|
||||
|
||||
impl_game_logic -> verify_game_logic -> check_game_logic
|
||||
check_game_logic -> impl_terminal_ui [condition="outcome=success"]
|
||||
check_game_logic -> impl_game_logic [condition="outcome=fail", label="retry"]
|
||||
check_game_logic -> impl_terminal_ui [condition="outcome=succeeded"]
|
||||
check_game_logic -> impl_game_logic [condition="outcome=failed", label="retry"]
|
||||
check_game_logic -> impl_game_logic [label="fallback"]
|
||||
|
||||
impl_terminal_ui -> verify_terminal_ui -> check_terminal_ui
|
||||
check_terminal_ui -> impl_integration [condition="outcome=success"]
|
||||
check_terminal_ui -> impl_terminal_ui [condition="outcome=fail", label="retry"]
|
||||
check_terminal_ui -> impl_integration [condition="outcome=succeeded"]
|
||||
check_terminal_ui -> impl_terminal_ui [condition="outcome=failed", label="retry"]
|
||||
check_terminal_ui -> impl_terminal_ui [label="fallback"]
|
||||
|
||||
impl_integration -> verify_integration -> check_integration
|
||||
check_integration -> review [condition="outcome=success"]
|
||||
check_integration -> impl_integration [condition="outcome=fail", label="retry"]
|
||||
check_integration -> review [condition="outcome=succeeded"]
|
||||
check_integration -> impl_integration [condition="outcome=failed", label="retry"]
|
||||
check_integration -> impl_integration [label="fallback"]
|
||||
|
||||
review -> check_review
|
||||
check_review -> exit [condition="outcome=success"]
|
||||
check_review -> impl_terminal_ui [condition="outcome=fail", label="fix"]
|
||||
check_review -> exit [condition="outcome=succeeded"]
|
||||
check_review -> impl_terminal_ui [condition="outcome=failed", label="fix"]
|
||||
check_review -> impl_terminal_ui [label="fallback"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,6 @@ digraph Branch {
|
|||
gate [shape=diamond, label="Tests passing?"]
|
||||
|
||||
start -> plan -> implement -> validate -> gate
|
||||
gate -> exit [label="Yes", condition="outcome=success"]
|
||||
gate -> exit [label="Yes", condition="outcome=succeeded"]
|
||||
gate -> implement [label="No"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ digraph Conditions {
|
|||
path_b [label="Path B"]
|
||||
|
||||
start -> decide
|
||||
decide -> path_a [condition="outcome=success && context.mode=fast"]
|
||||
decide -> path_a [condition="outcome=succeeded && context.mode=fast"]
|
||||
decide -> path_b
|
||||
path_a -> exit
|
||||
path_b -> exit
|
||||
|
|
|
|||
|
|
@ -521,9 +521,9 @@ Respond with exactly one of:\n\
|
|||
|
||||
// Bootstrap
|
||||
start -> check_toolchain
|
||||
check_toolchain -> expand_spec [condition="outcome=success"]
|
||||
check_toolchain -> check_toolchain [condition="outcome=fail && context.failure_class=transient_infra", loop_restart=true]
|
||||
check_toolchain -> postmortem [condition="outcome=fail && context.failure_class!=transient_infra"]
|
||||
check_toolchain -> expand_spec [condition="outcome=succeeded"]
|
||||
check_toolchain -> check_toolchain [condition="outcome=failed && context.failure_class=transient_infra", loop_restart=true]
|
||||
check_toolchain -> postmortem [condition="outcome=failed && context.failure_class!=transient_infra"]
|
||||
check_toolchain -> postmortem
|
||||
|
||||
expand_spec -> plan_fanout
|
||||
|
|
@ -541,23 +541,23 @@ Respond with exactly one of:\n\
|
|||
// Verify chain — failures go directly back to implement (errors logged to .workflow/verify_errors.log)
|
||||
fix_fmt -> verify_fmt
|
||||
verify_fmt -> gate_fmt
|
||||
gate_fmt -> verify_build [condition="outcome=success"]
|
||||
gate_fmt -> verify_build [condition="outcome=succeeded"]
|
||||
gate_fmt -> implement
|
||||
|
||||
verify_build -> gate_build
|
||||
gate_build -> verify_test [condition="outcome=success"]
|
||||
gate_build -> verify_test [condition="outcome=succeeded"]
|
||||
gate_build -> implement
|
||||
|
||||
verify_test -> gate_test
|
||||
gate_test -> verify_browser [condition="outcome=success"]
|
||||
gate_test -> verify_browser [condition="outcome=succeeded"]
|
||||
gate_test -> implement
|
||||
|
||||
verify_browser -> gate_browser
|
||||
gate_browser -> verify_artifacts [condition="outcome=success"]
|
||||
gate_browser -> verify_artifacts [condition="outcome=succeeded"]
|
||||
gate_browser -> implement
|
||||
|
||||
verify_artifacts -> gate_artifacts
|
||||
gate_artifacts -> verify_fidelity [condition="outcome=success"]
|
||||
gate_artifacts -> verify_fidelity [condition="outcome=succeeded"]
|
||||
gate_artifacts -> implement
|
||||
|
||||
verify_fidelity -> gate_fidelity
|
||||
|
|
|
|||
|
|
@ -581,7 +581,7 @@ Otherwise set preferred_next_label to \"more_work_needed\"."
|
|||
review_codex -> fix_codex [label="Fallback"]
|
||||
|
||||
/* Phase 6: Build */
|
||||
build_check -> final_audit_opus [label="Build OK", condition="outcome=success"]
|
||||
build_check -> final_audit_opus [label="Build OK", condition="outcome=succeeded"]
|
||||
build_check -> build_fix [label="Build failed"]
|
||||
build_fix -> build_check
|
||||
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ Otherwise set preferred_next_label to \"more_work_needed\"."
|
|||
fix_batch -> build_check
|
||||
|
||||
/* Build check outcomes */
|
||||
build_check -> final_audit [label="Build OK", condition="outcome=success"]
|
||||
build_check -> final_audit [label="Build OK", condition="outcome=succeeded"]
|
||||
build_check -> build_fix [label="Build failed"]
|
||||
|
||||
/* Build fix loops back to build check */
|
||||
|
|
|
|||
|
|
@ -34,13 +34,13 @@ digraph NLSpecConformance {
|
|||
// Wiring
|
||||
start -> plan -> implement -> test_quick -> gate_quick
|
||||
|
||||
gate_quick -> test_full [label="Pass", condition="outcome=success"]
|
||||
gate_quick -> test_full [label="Pass", condition="outcome=succeeded"]
|
||||
gate_quick -> fix [label="Fix"]
|
||||
|
||||
fix -> test_quick
|
||||
|
||||
test_full -> gate_full
|
||||
|
||||
gate_full -> exit [label="Pass", condition="outcome=success"]
|
||||
gate_full -> exit [label="Pass", condition="outcome=succeeded"]
|
||||
gate_full -> fix [label="Fix"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ digraph SemanticPort {
|
|||
|
||||
plan -> implement -> validate -> gate
|
||||
|
||||
gate -> finalize [label="Pass", condition="outcome=success"]
|
||||
gate -> finalize [label="Pass", condition="outcome=succeeded"]
|
||||
gate -> fix [label="Fail"]
|
||||
|
||||
fix -> validate
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ digraph ImplementFeature {
|
|||
|
||||
implement -> test -> validate -> gate
|
||||
|
||||
gate -> review [label="Pass", condition="outcome=success"]
|
||||
gate -> review [label="Pass", condition="outcome=succeeded"]
|
||||
gate -> implement [label="Fix"]
|
||||
|
||||
review -> exit
|
||||
|
|
|
|||
|
|
@ -11,6 +11,6 @@ digraph BranchLoop {
|
|||
gate [shape=diamond, label="Tests passing?"]
|
||||
|
||||
start -> plan -> implement -> validate -> gate
|
||||
gate -> exit [label="Pass", condition="outcome=success"]
|
||||
gate -> exit [label="Pass", condition="outcome=succeeded"]
|
||||
gate -> implement [label="Fix"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,6 @@ digraph ImplementAndTest {
|
|||
gate [shape=diamond, label="Tests passing?"]
|
||||
|
||||
start -> implement -> validate -> gate
|
||||
gate -> exit [label="Pass", condition="outcome=success"]
|
||||
gate -> exit [label="Pass", condition="outcome=succeeded"]
|
||||
gate -> implement [label="Fix", max_visits=5]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ digraph AllNodeTypes {
|
|||
approve -> spec [label="[A] Approve"]
|
||||
approve -> plan [label="[R] Revise"]
|
||||
spec -> implement -> test -> gate
|
||||
gate -> fork [label="Pass", condition="outcome=success"]
|
||||
gate -> fork [label="Pass", condition="outcome=succeeded"]
|
||||
gate -> cooldown [label="Fix"]
|
||||
cooldown -> implement
|
||||
fork -> security
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ digraph TransitionPatterns {
|
|||
review -> implement [label="Fix"]
|
||||
review -> gate [label="Approve"]
|
||||
review -> gate [weight=-1]
|
||||
gate -> fast_path [condition="outcome=success"]
|
||||
gate -> fast_path [condition="outcome=succeeded"]
|
||||
gate -> slow_path
|
||||
fast_path -> preferred [weight=10]
|
||||
fast_path -> exit [weight=1]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue