From 502b0a337d2aaaf3ffbbceb392795a2ea499e350 Mon Sep 17 00:00:00 2001 From: poetry by <2638986+btomaj@users.noreply.github.com> Date: Thu, 26 Mar 2026 21:27:57 +1100 Subject: [PATCH 1/8] Correct inconsistency in Transform interface --- attractor-spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attractor-spec.md b/attractor-spec.md index aaaa969..4c030f1 100644 --- a/attractor-spec.md +++ b/attractor-spec.md @@ -1888,7 +1888,7 @@ This section defines how to validate that an implementation of this spec is comp ### 11.11 Transforms and Extensibility - [ ] AST transforms can modify the Graph between parsing and validation -- [ ] Transform interface: `transform(graph) -> graph` +- [ ] Transform interface: `apply(graph) -> Graph` - [ ] Built-in variable expansion transform replaces `$goal` in prompts - [ ] Custom transforms can be registered and run in order - [ ] HTTP server mode (if implemented): POST /run starts pipeline, GET /status checks state, POST /answer submits human input From 6490ad497e2638e7d0fe080aa6fa1e0e3f08defd Mon Sep 17 00:00:00 2001 From: poetry by <2638986+btomaj@users.noreply.github.com> Date: Thu, 26 Mar 2026 21:53:14 +1100 Subject: [PATCH 2/8] Correct inconsistency in orphan node validation --- attractor-spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attractor-spec.md b/attractor-spec.md index 4c030f1..26d31f6 100644 --- a/attractor-spec.md +++ b/attractor-spec.md @@ -1904,7 +1904,7 @@ Run this validation matrix -- each cell must pass: | Parse multi-line node attributes | [ ] | | Validate: missing start node -> error | [ ] | | Validate: missing exit node -> error | [ ] | -| Validate: orphan node -> warning | [ ] | +| Validate: orphan node -> error | [ ] | | Execute a linear 3-node pipeline end-to-end | [ ] | | Execute with conditional branching (success/fail paths) | [ ] | | Execute with retry on failure (max_retries=2) | [ ] | From 600bbf919c6ee9971cbec5fa090108e21bbd11b8 Mon Sep 17 00:00:00 2001 From: poetry by <2638986+btomaj@users.noreply.github.com> Date: Fri, 27 Mar 2026 09:18:33 +1100 Subject: [PATCH 3/8] Correct inconsistency in core execution loop --- attractor-spec.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/attractor-spec.md b/attractor-spec.md index 26d31f6..f944ad9 100644 --- a/attractor-spec.md +++ b/attractor-spec.md @@ -337,16 +337,18 @@ PARSE -> TRANSFORM -> VALIDATE -> INITIALIZE -> EXECUTE -> FINALIZE The following pseudocode defines the execution engine's traversal algorithm. This is the heart of the system. ``` -FUNCTION run(graph, config): - context = new Context() +FUNCTION run(graph, context=new Context(), start_at=None): mirror_graph_attributes(graph, context) checkpoint = new Checkpoint() completed_nodes = [] node_outcomes = {} - - current_node = find_start_node(graph) - -- Resolves by: (1) shape=Mdiamond, (2) id="start" or "Start" - -- Raises error if not found + + IF start_at is not NONE: + current_node = graph.nodes[start_at] + ELSE: + current_node = find_start_node(graph) + -- Resolves by: (1) shape=Mdiamond, (2) id="start" or "Start" + -- Raises error if not found WHILE true: node = graph.nodes[current_node.id] @@ -394,8 +396,7 @@ FUNCTION run(graph, config): -- Step 7: Handle loop_restart IF next_edge has loop_restart=true: - restart_run(graph, config, start_at=next_edge.target) - RETURN + RETURN run(graph, context, start_at=next_edge.target) -- Step 8: Advance to next node current_node = graph.nodes[next_edge.to_node] @@ -1958,8 +1959,7 @@ lint_results = validate(graph) ASSERT no error-severity results in lint_results -- 3. Execute with LLM callback -context = Context() -outcome = run_pipeline(graph, context, llm_callback = real_llm_callback) +outcome = run(graph) -- 4. Verify ASSERT outcome.status == "success" From e109d089c3b6b7fa0545492728338e355e85f5fb Mon Sep 17 00:00:00 2001 From: poetry by <2638986+btomaj@users.noreply.github.com> Date: Fri, 27 Mar 2026 12:15:13 +1100 Subject: [PATCH 4/8] Correct inconsistency in Outcome interface --- attractor-spec.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/attractor-spec.md b/attractor-spec.md index f944ad9..baeaee5 100644 --- a/attractor-spec.md +++ b/attractor-spec.md @@ -1962,8 +1962,7 @@ ASSERT no error-severity results in lint_results outcome = run(graph) -- 4. Verify -ASSERT outcome.status == "success" -ASSERT "implement" in outcome.completed_nodes +ASSERT outcome.status == SUCCESS ASSERT artifacts_exist(logs_root, "plan", ["prompt.md", "response.md", "status.json"]) ASSERT artifacts_exist(logs_root, "implement", ["prompt.md", "response.md", "status.json"]) ASSERT artifacts_exist(logs_root, "review", ["prompt.md", "response.md", "status.json"]) From 5fcba66c5ae8db1ce2545b5a4390b10f3785d1b5 Mon Sep 17 00:00:00 2001 From: poetry by <2638986+btomaj@users.noreply.github.com> Date: Fri, 27 Mar 2026 15:48:48 +1100 Subject: [PATCH 5/8] Correct inconsistency in implied Edge shape --- attractor-spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attractor-spec.md b/attractor-spec.md index baeaee5..df19c8b 100644 --- a/attractor-spec.md +++ b/attractor-spec.md @@ -396,7 +396,7 @@ FUNCTION run(graph, context=new Context(), start_at=None): -- Step 7: Handle loop_restart IF next_edge has loop_restart=true: - RETURN run(graph, context, start_at=next_edge.target) + RETURN run(graph, context, start_at=next_edge.to_node) -- Step 8: Advance to next node current_node = graph.nodes[next_edge.to_node] From c7c4d1ed0106d89497faa0edfe585399cab42e4e Mon Sep 17 00:00:00 2001 From: poetry by <2638986+btomaj@users.noreply.github.com> Date: Fri, 27 Mar 2026 21:33:39 +1100 Subject: [PATCH 6/8] loop_restart is complete restart --- attractor-spec.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/attractor-spec.md b/attractor-spec.md index df19c8b..9d0e404 100644 --- a/attractor-spec.md +++ b/attractor-spec.md @@ -337,7 +337,7 @@ PARSE -> TRANSFORM -> VALIDATE -> INITIALIZE -> EXECUTE -> FINALIZE The following pseudocode defines the execution engine's traversal algorithm. This is the heart of the system. ``` -FUNCTION run(graph, context=new Context(), start_at=None): +FUNCTION run(graph, context, start_at=None): mirror_graph_attributes(graph, context) checkpoint = new Checkpoint() completed_nodes = [] @@ -396,6 +396,7 @@ FUNCTION run(graph, context=new Context(), start_at=None): -- Step 7: Handle loop_restart IF next_edge has loop_restart=true: + context = new Context() RETURN run(graph, context, start_at=next_edge.to_node) -- Step 8: Advance to next node @@ -1959,7 +1960,8 @@ lint_results = validate(graph) ASSERT no error-severity results in lint_results -- 3. Execute with LLM callback -outcome = run(graph) +context = new Context() +outcome = run(graph, context) -- 4. Verify ASSERT outcome.status == SUCCESS From eeb93b42e69f04da0e955525459bdc49fd95a5da Mon Sep 17 00:00:00 2001 From: poetry by <2638986+btomaj@users.noreply.github.com> Date: Sat, 28 Mar 2026 20:53:23 +1100 Subject: [PATCH 7/8] Correct inconsistency with retry logic --- attractor-spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attractor-spec.md b/attractor-spec.md index 9d0e404..a077c59 100644 --- a/attractor-spec.md +++ b/attractor-spec.md @@ -1832,7 +1832,7 @@ This section defines how to validate that an implementation of this spec is comp ### 11.5 Retry Logic -- [ ] Nodes with `max_retries > 0` are retried on RETRY or FAIL outcomes +- [ ] Nodes with `max_retries > 0` are retried on RETRY outcomes - [ ] Retry count is tracked per-node and respects the configured limit - [ ] Backoff between retries works (constant, linear, or exponential as configured) - [ ] Jitter is applied to backoff delays when configured From 083333e7fcd80570e49002dc86a34ac7378097fc Mon Sep 17 00:00:00 2001 From: poetry by <2638986+btomaj@users.noreply.github.com> Date: Sat, 28 Mar 2026 21:10:58 +1100 Subject: [PATCH 8/8] Correct inconsistency in wait.human handler return Outcome --- attractor-spec.md | 1 + 1 file changed, 1 insertion(+) diff --git a/attractor-spec.md b/attractor-spec.md index a077c59..2320076 100644 --- a/attractor-spec.md +++ b/attractor-spec.md @@ -770,6 +770,7 @@ WaitForHumanHandler: -- 6. Record in context and return RETURN Outcome( status=SUCCESS, + preferred_label=selected.label suggested_next_ids=[selected.to], context_updates={ "human.gate.selected": selected.key,