From d39e9b9534aef17b6150c2acd08c34120c24bc77 Mon Sep 17 00:00:00 2001 From: tinqs-limited Date: Wed, 3 Jun 2026 02:37:00 +0100 Subject: [PATCH] merge: combine pi-flow-native-brain + pi-ci-integrator into one post MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Single public-facing post that tells the complete Pi autonomy story: - Part 1: Retiring the hardcoded supervisor (1,050 lines deleted) replaced by composable oracle-backed pi-flows with 5 gates (build, test, behaviour, feel, visual) - Part 2: The CI integrator — agents that watch CI, read failure logs, and fix their own broken builds (tinqs-ci extension) - Combined stack: flow engine → gates → sub-agents → CI loop - SVG gate pipeline + deletion bar diagrams preserved via build.js passthrough - Removed old separate pi-ci-integrator post; pi-flow-native-brain is now a proper .md source (replaces hand-authored HTML) --- README.md | 2 + index.html | 14 +- pi-ci-integrator.html | 331 ---------------------------------- pi-flow-native-brain.html | 124 ++++++++++--- posts/pi-ci-integrator.md | 103 ----------- posts/pi-flow-native-brain.md | 259 ++++++++++++++++++++++++++ 6 files changed, 363 insertions(+), 470 deletions(-) delete mode 100644 pi-ci-integrator.html delete mode 100644 posts/pi-ci-integrator.md create mode 100644 posts/pi-flow-native-brain.md diff --git a/README.md b/README.md index cbcb65d..309b999 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ We're building Tinqs Studio while using it to make our own game --- a survival c - [Streaming a 12km Archipelago in Godot 4](posts/godot-optimisation.md) (2026-05-22) - [AI Art at Scale: Using fal.ai Flux for Game Asset Generation](posts/fal-image-generation.md) (2026-05-25) - [Tinqs Studio Is an Agent Harness for Game Dev](posts/agent-harness.md) (2026-05-25) +- [Pi's Flow-Native Brain: Retiring the Supervisor, Teaching Agents to Fix Their Own Builds](posts/pi-flow-native-brain.md) (2026-06-03) +- [Our Blog Just Got a Visual Upgrade — Here's How We Did It](posts/blog-visual-upgrade.md) (2026-06-03) ## Skills diff --git a/index.html b/index.html index 9c86bff..54e4393 100644 --- a/index.html +++ b/index.html @@ -128,6 +128,13 @@ Read → + + 3 June 2026 +

Pi's Flow-Native Brain: Retiring the Supervisor, Teaching Agents to Fix Their Own Builds

+

Two changes made Pi genuinely autonomous: we deleted the hardcoded supervisor and replaced it with composable oracle-backed flows, and we taught agents to watch CI, read failure logs, and fix their own broken builds.

+ Read → +
+ 26 May 2026

Building a Cloud Agent Harness with DeepSeek V4 and Pi

@@ -163,13 +170,6 @@ Read →
- - 25 May 2026 -

Pi as CI Integrator: Agents That Fix Their Own Builds

-

Most coding agents stop at git push. Our Pi fork watches CI, reads failure logs, and fixes its own code until the pipeline goes green.

- Read → -
- 25 May 2026

A Pre-Commit Agent That Guards Your Secrets for $0.001

diff --git a/pi-ci-integrator.html b/pi-ci-integrator.html deleted file mode 100644 index 8096fc5..0000000 --- a/pi-ci-integrator.html +++ /dev/null @@ -1,331 +0,0 @@ - - - - - - - Pi as CI Integrator: Agents That Fix Their Own Builds — Tinqs Blog - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- Games - Technology - About - Blog - Contact - Press -
- - -
- ← All Posts - -

Pi as CI Integrator: Agents That Fix Their Own Builds

-

Most coding agents have a dirty secret: they don't care if the code compiles. They write, they push, they walk away. The human discovers the broken build an hour later. We built a Pi extension that closes the loop — agents that watch CI, read failure logs, and fix their own mistakes.

- -
-

The Gap

-

Every agent demo looks the same. The AI writes code, commits, pushes. The presenter says "and now we have a pull request!" Cut. End of demo.

-

What happens next? The CI pipeline runs. Tests fail. Linting screams. The build breaks because someone forgot an import. A human opens the PR, reads the red badge, clicks into the logs, finds the error, fixes it, pushes again. The agent did 90% of the work but left the last 10% — the most tedious part — for a person.

-

We wanted agents that finish the job.

-

The tinqs-ci Extension

-

Our Pi fork has a tinqs-ci extension — a single TypeScript file, about 200 lines — that gives the agent three tools:

-
    -
  • ci_status — checks the current pipeline state for a branch (pending, running, success, failure)
  • -
  • ci_logs — fetches the full build log from the most recent failed run
  • -
  • ci_wait — polls the pipeline every 15 seconds until it finishes, then returns the result
  • -
-

These are Gitea Actions API calls under the hood. The agent authenticates with the same PAT it uses for git push. No extra credentials, no special CI service account.

-

The Loop

-

Here's what a Pi task looks like end to end:

-
Agent receives task brief
-  → reads codebase, plans approach
-  → writes code
-  → runs local tests (bash tool)
-  → commits and pushes branch
-  → calls ci_wait
-  → CI passes → opens PR via Gitea API
-  → CI fails → calls ci_logs
-  → reads error output
-  → fixes the issue
-  → pushes again
-  → calls ci_wait again
-  → repeats until green (max 3 retries)
-

The key is that ci_logs returns the raw build output — compiler errors, test failures, lint violations — as plain text in the agent's context. DeepSeek V4 is surprisingly good at reading build logs. It parses a Go compiler error, identifies the file and line, and fixes it. It reads a test assertion failure, understands what the test expected, and corrects the implementation.

-

Three retries is the hard limit. If the agent can't fix it in three rounds, it opens the PR anyway with a comment explaining what failed and why. A human takes over from there. In practice, most failures resolve on the first retry — it's usually a missing import or a type mismatch.

-

What This Actually Looks Like

-

A real run from last week. The task: add a health check endpoint to a Go service.

-
    -
  • Turn 1: Agent reads the codebase, writes the handler and test, pushes. CI fails — the test imports a package that doesn't exist on the runner.
  • -
  • Turn 2: Agent reads ci_logs, sees the go: module not found error, adds the missing go.mod replace directive, pushes. CI passes.
  • -
  • Turn 3: Agent opens PR with passing checks.
  • -
-

Total time: 4 minutes. Total cost: $0.06. No human touched the keyboard.

-

Without the CI extension, this would have been a PR with a red badge and a Slack message saying "hey, the agent's PR is broken again." Someone would have context-switched, opened the logs, seen the trivial error, fixed it, and lost 20 minutes of flow state.

-

Why This Matters More Than You Think

-

CI integration isn't a feature. It's the difference between an agent that helps and an agent that creates work.

-

An agent that pushes broken code is worse than no agent at all. It creates a false sense of progress — "the PR is up!" — while actually adding a task to someone's plate. Every broken PR is an interruption. Every interruption costs 15 minutes of context-switching.

-

An agent that watches CI and fixes its own builds is genuinely autonomous. You submit a task, you walk away, you come back to a green PR ready for review. The agent handled the mechanical iteration that a human would have done anyway — the fix-push-wait-check cycle that eats hours of developer time every week.

-

The Guardrail Problem

-

Letting an agent retry its own builds sounds dangerous. What if it enters an infinite loop? What if it starts making increasingly wild changes to get the build to pass?

-

Three safeguards:

-

Retry limit. Three attempts maximum. After that, the agent stops and reports. This is a hard limit in the orchestrator, not a suggestion to the model.

-

Diff budget. Each retry can only touch files that were already in the original changeset. The agent can't "fix" a build failure by rewriting the test suite or disabling the linter. If the fix requires touching new files, it fails and escalates.

-

Hallucination detection. The guardrail extension monitors every turn. If the agent claims "the build passed" without having called ci_status or ci_wait, it gets corrected. Agents are not allowed to guess the CI result.

-

The Numbers

-

Over three weeks of running the orchestrator:

-
    -
  • 87 tasks completed end-to-end
  • -
  • 23 tasks needed at least one CI retry (26%)
  • -
  • 19 of those 23 resolved on the first retry
  • -
  • 4 tasks hit the retry limit and escalated to a human
  • -
  • 0 tasks produced a merged PR that later broke something else
  • -
-

The 26% retry rate tells you how often agents push code that doesn't build on the first try. That's not a bad number — it's the same rate you'd see from a junior developer. The difference is the agent fixes it in 30 seconds instead of 20 minutes.

-
-

The CI extension is part of our Pi fork, which runs inside Tinqs Studio — a Gitea-based platform for game development with built-in AI agents. The whole thing is MIT licensed.

- -
- - -
- - - - - - - - diff --git a/pi-flow-native-brain.html b/pi-flow-native-brain.html index c48b256..a12fb10 100644 --- a/pi-flow-native-brain.html +++ b/pi-flow-native-brain.html @@ -4,27 +4,27 @@ - Retiring the Supervisor: Pi's Flow-Native Brain — Tinqs Blog - + Pi's Flow-Native Brain: Retiring the Supervisor, Teaching Agents to Fix Their Own Builds — Tinqs Blog + - - + + - - + + @@ -218,11 +218,13 @@
← All Posts -

Retiring the Supervisor: Pi's Flow-Native Brain

-

The supervisor was 1,050 lines of TypeScript spread across 15 files — a hardcoded orchestration loop that ran contract-gated, verify-heavy sessions over isolated Pi processes. Today we deleted it. What replaced it is simpler, more flexible, and already passing real builds.

+

Pi's Flow-Native Brain: Retiring the Supervisor, Teaching Agents to Fix Their Own Builds

+

Two changes this week made Pi genuinely autonomous. First, we deleted 1,050 lines of hardcoded supervisor logic and replaced it with a flow-native brain — oracle-backed gates that agents compose dynamically. Second, we closed the loop: agents now watch CI, read failure logs, and fix their own broken builds until the pipeline goes green.

-

What the Supervisor Did

+
+

Part 1: Retiring the Supervisor

+

What the Supervisor Did

The .pi/supervisor/ directory was the orchestration brain Pi left to us. For every task, it ran a fixed loop:

1. Contract gate — skip-to-human if "done" wasn't programmatically verifiable

2. TDAID phase A — a test-writer agent writes RED tests, never implementation

@@ -230,11 +232,11 @@

4. Verification gate — run the build, check tests, pass or fail with a report

It worked. It caught broken builds before they hit CI. It enforced the discipline of "define done before you start." But it had a structural problem: the loop was hardcoded. Every decision tree, every gate, every retry policy was baked into TypeScript. To change the workflow, you changed code. To add a new gate — vision QA, linting, asset validation — you added more code to the same monolithic loop.

The supervisor was doing what pi-flows was designed to do, but from the wrong side of the architecture. Flows composes agents, gates, and decision points into pipelines. The supervisor reimplemented that logic in a single file. It was fighting the framework.

-

What Replaced It

+

What Replaced It

The verify-heavy brain now runs as a pi-flows flow — a pipeline of oracle-backed gates orchestrated by the flow engine, visualized in FlowDashboard, and composable by agents themselves.

The core pieces:

    -
  • Oracle-backed gates. The verify_build tool (.pi/extensions/tinqs-verify.ts) is the canonical gate. It compiles the game and sim, runs tests, and returns a structured PASS/FAIL verdict with file:line errors. Agents route through it; the gate decides whether to proceed.
  • +
  • Oracle-backed gates. The verify_build tool is the canonical gate. It compiles the game and sim, runs tests, and returns a structured PASS/FAIL verdict with file:line errors. Agents route through it; the gate decides whether to proceed.
  • Agent-loop-decision Reflexion. Instead of a fixed two-phase TDAID loop, agents self-reflect on build failures. The flow engine gives them the failure report; they decide whether to fix and retry or escalate.
  • Role-split agents. G1 build, G2 tests, G3 behaviour (drives the live game), G4 feel (measured game-feel) and G5 visual (animation) are separate sub-agents, each with its own toolset and context, composed by the flow.
@@ -267,16 +269,16 @@ G5 · Visual - all green ⇒ done · any fail ⇒ report + all green ⇒ done · any fail ⇒ report - Judge — honest verdict + Judge — honest verdict - Reflexion · fix & retry ≤ 3 + Reflexion · fix & retry ≤ 3
A real in-game failure loops back to implement with the gate evidence (bounded to three tries); anything green — or skipped because no live instance is running — falls through to a single honest judge.

It started as three gates — build, test, vision. Gates are cheap to add, so it grew: a feature now also passes a live-game behaviour probe and a measured feel check before the judge signs off. Critically, the flow is not fixed. Agents can add gates, reorder steps, or branch on conditions. The flow engine handles orchestration; the agents handle decisions.

-

What We Deleted

+

What We Deleted

The commit removes 1,050 lines across 15 files:

  • runner.ts (115 lines) — the main orchestration loop
  • @@ -290,29 +292,92 @@
- Net change: −750 lines, + a composable pipeline + Net change: −750 lines, + a composable pipeline Deleted - supervisor/ — 1,050 lines · 15 files + supervisor/ — 1,050 lines · 15 files Kept - verify_build — ~300 lines · 1 oracle + verify_build — ~300 lines · 1 oracle
The whole orchestration loop was deleted; only the build oracle survived — and it became the gate that powers the flow.

None of this was bad code. It was just the wrong layer. Flows gives us all of this — orchestration, state, gates, retry policy, event routing — as a framework primitive. We were maintaining a parallel implementation of something the framework already provided.

The durable asset we kept: verify_build, the build oracle. It's now reused as the gate tool that powers the flow pipeline.

-

The Bug That Took a Day to Find

+

The Bug That Took a Day to Find

Moving to flows exposed a subtle problem. Flow sub-agents run in their own extension stack — the main session's extensions don't reach them. The build-verifier and test-runner agents declared verify_build in their frontmatter, but the tool was never actually in their toolset.

-

The symptom was confusing: the agents would report "oracle not available" and route to fail/report, silently skipping the test gate entirely. The build would pass, tests would never run, and the pipeline would report success. A false green.

+

The symptom was confusing: agents reported "oracle not available" and routed to fail/report, silently skipping the test gate entirely. A false green — the build passed, tests never ran, and the pipeline reported success.

The fix was a single pattern: emit flow:register-tool with the full tool definition at extension activation, and re-announce on flow:rediscover. The flow engine collects these into getExtensionTools() and hands them to every sub-agent that declares the tool. Three lines of orchestration, a day of debugging.

Verified live: game-check now routes context → build → build-gate(pass) → tests → tests-gate(pass) → vision. Every gate fires. No false greens.

-

Why This Architecture Wins

+

Why This Architecture Wins

Composability. Agents can add gates without touching framework code. Want a linting gate? Add a sub-agent with a linter tool. Want a security scan? Same pattern. The flow engine handles routing; you just declare the gate.

Reusability. The verify_build oracle that powered the old supervisor now powers the flow gates. Same tool, same interface, different orchestration. No rewrite needed.

Observability. FlowDashboard visualizes the entire pipeline. You can see which gates passed, which failed, and where the agent decided to retry. The old supervisor logged to stdout.

Self-modification. Agents can read the flow graph, understand where they are in the pipeline, and decide what to do next. The supervisor's decision tree was opaque to the agents it was supervising. Flows makes the pipeline itself part of the agent's context.

-

The Stack Today

+
+

Part 2: Agents That Fix Their Own Builds

+

Most coding agents have a dirty secret: they don't care if the code compiles. They write, they push, they walk away. The human discovers the broken build an hour later. The flow-native brain handles verification inside the pipeline — but what about after push? What about CI?

+

The Gap

+

Every agent demo looks the same. The AI writes code, commits, pushes. The presenter says "and now we have a pull request!" Cut. End of demo.

+

What happens next? The CI pipeline runs. Tests fail. Linting screams. The build breaks because someone forgot an import. A human opens the PR, reads the red badge, clicks into the logs, finds the error, fixes it, pushes again. The agent did 90% of the work but left the last 10% — the most tedious part — for a person.

+

We wanted agents that finish the job.

+

The tinqs-ci Extension

+

Our Pi fork has a tinqs-ci extension — a single TypeScript file, about 200 lines — that gives the agent three tools:

+
    +
  • ci_status — checks the current pipeline state for a branch (pending, running, success, failure)
  • +
  • ci_logs — fetches the full build log from the most recent failed run
  • +
  • ci_wait — polls the pipeline every 15 seconds until it finishes, then returns the result
  • +
+

These are Gitea Actions API calls under the hood. The agent authenticates with the same PAT it uses for git push. No extra credentials, no special CI service account.

+

The Loop

+

Here's what a Pi task looks like end to end:

+
Agent receives task brief
+  → reads codebase, plans approach
+  → writes code
+  → runs local tests (bash tool)
+  → commits and pushes branch
+  → calls ci_wait
+  → CI passes → opens PR via Gitea API
+  → CI fails → calls ci_logs
+  → reads error output
+  → fixes the issue
+  → pushes again
+  → calls ci_wait again
+  → repeats until green (max 3 retries)
+

The key is that ci_logs returns the raw build output — compiler errors, test failures, lint violations — as plain text in the agent's context. DeepSeek V4 is surprisingly good at reading build logs. It parses a Go compiler error, identifies the file and line, and fixes it. It reads a test assertion failure, understands what the test expected, and corrects the implementation.

+

Three retries is the hard limit. If the agent can't fix it in three rounds, it opens the PR anyway with a comment explaining what failed and why. A human takes over from there. In practice, most failures resolve on the first retry — it's usually a missing import or a type mismatch.

+

A Real Run

+

Last week. The task: add a health check endpoint to a Go service.

+
    +
  • Turn 1: Agent reads the codebase, writes the handler and test, pushes. CI fails — the test imports a package that doesn't exist on the runner.
  • +
  • Turn 2: Agent reads ci_logs, sees the go: module not found error, adds the missing go.mod replace directive, pushes. CI passes.
  • +
  • Turn 3: Agent opens PR with passing checks.
  • +
+

Total time: 4 minutes. Total cost: $0.06. No human touched the keyboard.

+

Without the CI extension, this would have been a PR with a red badge and a Slack message saying "hey, the agent's PR is broken again." Someone would have context-switched, opened the logs, seen the trivial error, fixed it, and lost 20 minutes of flow state.

+

Why This Matters More Than You Think

+

CI integration isn't a feature. It's the difference between an agent that helps and an agent that creates work.

+

An agent that pushes broken code is worse than no agent at all. It creates a false sense of progress — "the PR is up!" — while actually adding a task to someone's plate. Every broken PR is an interruption. Every interruption costs 15 minutes of context-switching.

+

An agent that watches CI and fixes its own builds is genuinely autonomous. You submit a task, you walk away, you come back to a green PR ready for review. The agent handled the mechanical iteration that a human would have done anyway — the fix-push-wait-check cycle that eats hours of developer time every week.

+

The Guardrail Problem

+

Letting an agent retry its own builds sounds dangerous. What if it enters an infinite loop? What if it starts making increasingly wild changes to get the build to pass?

+

Three safeguards:

+

Retry limit. Three attempts maximum. After that, the agent stops and reports. This is a hard limit in the orchestrator, not a suggestion to the model.

+

Diff budget. Each retry can only touch files that were already in the original changeset. The agent can't "fix" a build failure by rewriting the test suite or disabling the linter. If the fix requires touching new files, it fails and escalates.

+

Hallucination detection. The guardrail extension monitors every turn. If the agent claims "the build passed" without having called ci_status or ci_wait, it gets corrected. Agents are not allowed to guess the CI result.

+

The Numbers

+

Over three weeks of running the orchestrator:

+
    +
  • 87 tasks completed end-to-end
  • +
  • 23 tasks needed at least one CI retry (26%)
  • +
  • 19 of those 23 resolved on the first retry
  • +
  • 4 tasks hit the retry limit and escalated to a human
  • +
  • 0 tasks produced a merged PR that later broke something else
  • +
+

The 26% retry rate tells you how often agents push code that doesn't build on the first try. That's not a bad number — it's the same rate you'd see from a junior developer. The difference is the agent fixes it in 30 seconds instead of 20 minutes.

+
+

Putting It Together: The Stack

+

The flow-native brain and the CI integrator are two sides of the same coin. The flow handles pre-push verification — did the code compile? do the tests pass? does the game behave correctly? The CI integrator handles post-push verification — did the CI pipeline agree? did anything break on the runner that didn't break locally?

@@ -324,14 +389,15 @@ - - - + + + +
Flow enginepi-flows orchestratorComposes agents, gates and decision points
Gatesverify_build oracleCompiles, tests, returns PASS/FAIL with file:line errors
Sub-agentsG1 build · G2 tests · G3 behaviour · G4 feel · G5 visualRole-split, each with its own toolset
DecisionAgent-loop ReflexionSelf-reflect on failures, retry (≤3) or escalate
VisualizationFlowDashboardReal-time pipeline state at localhost:33634
Sub-agentsG1 build · G2 tests · G3 behaviour · G4 feel · G5 visualRole-split, each with its own toolset
CI looptinqs-ci extensionci_status, ci_logs, ci_wait — polls Gitea Actions, reads logs, retries
DecisionAgent-loop ReflexionSelf-reflect on failures, retry (≤3) or escalate
VisualizationFlowDashboardReal-time pipeline state

-

The old supervisor was 1,050 lines of code that did one thing well: verify that agent output compiled and passed tests. The new flow-native brain does the same thing with less code, more flexibility, and a bug we'll never hit again. Sometimes the best commit is a deletion.

-

The flow-native brain runs on our Pi fork inside Tinqs Studio. The verify_build extension is ~300 lines of TypeScript, MIT licensed, and reusable in any Pi project.

+

The old supervisor was 1,050 lines of code that did one thing well: verify that agent output compiled and passed tests. The new system does the same thing with less code, more flexibility, composable gates, live CI integration, and a bug we'll never hit again. Sometimes the best commit is a deletion. Sometimes it's two.

+

The flow-native brain and CI extension run on our Pi fork inside Tinqs Studio. The verify_build extension is ~300 lines of TypeScript, the tinqs-ci extension is ~200 lines — both MIT licensed and reusable in any Pi project.

diff --git a/posts/pi-ci-integrator.md b/posts/pi-ci-integrator.md deleted file mode 100644 index b75b4af..0000000 --- a/posts/pi-ci-integrator.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: "Pi as CI Integrator: Agents That Fix Their Own Builds" -slug: pi-ci-integrator -date: "2026-05-25" -description: "Most coding agents stop at git push. Our Pi fork watches CI, reads failure logs, and fixes its own code until the pipeline goes green." -og_description: "Coding agents that watch CI and fix their own builds." -og_image: "https://www.tinqs.com/img/og-cover.jpg" -excerpt: "Most coding agents stop at git push. Our Pi fork watches CI, reads failure logs, and fixes its own code until the pipeline goes green." -author: "Ozan Bozkurt" -author_initials: "OB" -author_role: "CTO & Developer, Tinqs" ---- -Most coding agents have a dirty secret: they don't care if the code compiles. They write, they push, they walk away. The human discovers the broken build an hour later. We built a Pi extension that closes the loop --- agents that watch CI, read failure logs, and fix their own mistakes. - -## The Gap - -Every agent demo looks the same. The AI writes code, commits, pushes. The presenter says "and now we have a pull request!" Cut. End of demo. - -What happens next? The CI pipeline runs. Tests fail. Linting screams. The build breaks because someone forgot an import. A human opens the PR, reads the red badge, clicks into the logs, finds the error, fixes it, pushes again. The agent did 90% of the work but left the last 10% --- the most tedious part --- for a person. - -We wanted agents that finish the job. - -## The tinqs-ci Extension - -Our [Pi fork](https://tinqs.com/tinqs/pi) has a `tinqs-ci` extension --- a single TypeScript file, about 200 lines --- that gives the agent three tools: - -- **ci_status** --- checks the current pipeline state for a branch (pending, running, success, failure) -- **ci_logs** --- fetches the full build log from the most recent failed run -- **ci_wait** --- polls the pipeline every 15 seconds until it finishes, then returns the result - -These are Gitea Actions API calls under the hood. The agent authenticates with the same PAT it uses for git push. No extra credentials, no special CI service account. - -## The Loop - -Here's what a Pi task looks like end to end: - -``` -Agent receives task brief - → reads codebase, plans approach - → writes code - → runs local tests (bash tool) - → commits and pushes branch - → calls ci_wait - → CI passes → opens PR via Gitea API - → CI fails → calls ci_logs - → reads error output - → fixes the issue - → pushes again - → calls ci_wait again - → repeats until green (max 3 retries) -``` - -The key is that `ci_logs` returns the raw build output --- compiler errors, test failures, lint violations --- as plain text in the agent's context. DeepSeek V4 is surprisingly good at reading build logs. It parses a Go compiler error, identifies the file and line, and fixes it. It reads a test assertion failure, understands what the test expected, and corrects the implementation. - -Three retries is the hard limit. If the agent can't fix it in three rounds, it opens the PR anyway with a comment explaining what failed and why. A human takes over from there. In practice, most failures resolve on the first retry --- it's usually a missing import or a type mismatch. - -## What This Actually Looks Like - -A real run from last week. The task: add a health check endpoint to a Go service. - -- **Turn 1:** Agent reads the codebase, writes the handler and test, pushes. CI fails --- the test imports a package that doesn't exist on the runner. -- **Turn 2:** Agent reads `ci_logs`, sees the `go: module not found` error, adds the missing `go.mod` replace directive, pushes. CI passes. -- **Turn 3:** Agent opens PR with passing checks. - -Total time: 4 minutes. Total cost: $0.06. No human touched the keyboard. - -Without the CI extension, this would have been a PR with a red badge and a Slack message saying "hey, the agent's PR is broken again." Someone would have context-switched, opened the logs, seen the trivial error, fixed it, and lost 20 minutes of flow state. - -## Why This Matters More Than You Think - -CI integration isn't a feature. It's the difference between an agent that helps and an agent that creates work. - -An agent that pushes broken code is worse than no agent at all. It creates a false sense of progress --- "the PR is up!" --- while actually adding a task to someone's plate. Every broken PR is an interruption. Every interruption costs 15 minutes of context-switching. - -An agent that watches CI and fixes its own builds is genuinely autonomous. You submit a task, you walk away, you come back to a green PR ready for review. The agent handled the mechanical iteration that a human would have done anyway --- the fix-push-wait-check cycle that eats hours of developer time every week. - -## The Guardrail Problem - -Letting an agent retry its own builds sounds dangerous. What if it enters an infinite loop? What if it starts making increasingly wild changes to get the build to pass? - -Three safeguards: - -**Retry limit.** Three attempts maximum. After that, the agent stops and reports. This is a hard limit in the orchestrator, not a suggestion to the model. - -**Diff budget.** Each retry can only touch files that were already in the original changeset. The agent can't "fix" a build failure by rewriting the test suite or disabling the linter. If the fix requires touching new files, it fails and escalates. - -**Hallucination detection.** The guardrail extension monitors every turn. If the agent claims "the build passed" without having called `ci_status` or `ci_wait`, it gets corrected. Agents are not allowed to guess the CI result. - -## The Numbers - -Over three weeks of running the orchestrator: - -- **87 tasks** completed end-to-end -- **23 tasks** needed at least one CI retry (26%) -- **19 of those 23** resolved on the first retry -- **4 tasks** hit the retry limit and escalated to a human -- **0 tasks** produced a merged PR that later broke something else - -The 26% retry rate tells you how often agents push code that doesn't build on the first try. That's not a bad number --- it's the same rate you'd see from a junior developer. The difference is the agent fixes it in 30 seconds instead of 20 minutes. - ---- - -*The CI extension is part of our [Pi fork](https://tinqs.com/tinqs/pi), which runs inside [Tinqs Studio](https://tinqs.com) --- a Gitea-based platform for game development with built-in AI agents. The whole thing is MIT licensed.* diff --git a/posts/pi-flow-native-brain.md b/posts/pi-flow-native-brain.md new file mode 100644 index 0000000..4a554e1 --- /dev/null +++ b/posts/pi-flow-native-brain.md @@ -0,0 +1,259 @@ +--- +title: "Pi's Flow-Native Brain: Retiring the Supervisor, Teaching Agents to Fix Their Own Builds" +slug: pi-flow-native-brain +date: "2026-06-03" +description: "We deleted 1,050 lines of hardcoded supervisor logic, replaced it with oracle-backed pi-flows, and gave agents the tools to watch CI and fix their own broken builds." +og_description: "Pi's supervisor is gone — replaced by oracle-backed flows and CI-integrating agents that fix their own builds." +og_image: "https://www.tinqs.com/img/og-cover.jpg" +excerpt: "Two changes made Pi genuinely autonomous: we deleted the hardcoded supervisor and replaced it with composable oracle-backed flows, and we taught agents to watch CI, read failure logs, and fix their own broken builds." +author: "Ozan Bozkurt" +author_initials: "OB" +author_role: "CTO & Developer, Tinqs" +--- +Two changes this week made Pi genuinely autonomous. First, we deleted 1,050 lines of hardcoded supervisor logic and replaced it with a flow-native brain — oracle-backed gates that agents compose dynamically. Second, we closed the loop: agents now watch CI, read failure logs, and fix their own broken builds until the pipeline goes green. + +--- + +## Part 1: Retiring the Supervisor + +### What the Supervisor Did + +The `.pi/supervisor/` directory was the orchestration brain Pi left to us. For every task, it ran a fixed loop: + +1. **Contract gate** — skip-to-human if "done" wasn't programmatically verifiable +2. **TDAID phase A** — a test-writer agent writes RED tests, never implementation +3. **TDAID phase B** — a code-writer agent makes them green; on failure, a Reflexion follow-up retries (capped) +4. **Verification gate** — run the build, check tests, pass or fail with a report + +It worked. It caught broken builds before they hit CI. It enforced the discipline of "define done before you start." But it had a structural problem: the loop was **hardcoded**. Every decision tree, every gate, every retry policy was baked into TypeScript. To change the workflow, you changed code. To add a new gate — vision QA, linting, asset validation — you added more code to the same monolithic loop. + +The supervisor was doing what `pi-flows` was designed to do, but from the wrong side of the architecture. Flows composes agents, gates, and decision points into pipelines. The supervisor reimplemented that logic in a single file. It was fighting the framework. + +### What Replaced It + +The verify-heavy brain now runs **as a pi-flows flow** — a pipeline of oracle-backed gates orchestrated by the flow engine, visualized in FlowDashboard, and composable by agents themselves. + +The core pieces: + +- **Oracle-backed gates.** The `verify_build` tool is the canonical gate. It compiles the game and sim, runs tests, and returns a structured PASS/FAIL verdict with file:line errors. Agents route through it; the gate decides whether to proceed. +- **Agent-loop-decision Reflexion.** Instead of a fixed two-phase TDAID loop, agents self-reflect on build failures. The flow engine gives them the failure report; they decide whether to fix and retry or escalate. +- **Role-split agents.** G1 build, G2 tests, G3 behaviour (drives the live game), G4 feel (measured game-feel) and G5 visual (animation) are separate sub-agents, each with its own toolset and context, composed by the flow. + +The result is a pipeline that flows naturally — a plan, an implementation, then a ladder of oracle-backed gates: + + +
+ + + + + + + Context + + Plan + + Implement + + + + VERIFY-HEAVY GATES — most compute is spent checking, not writing + + G1 · Build + + G2 · Tests + + G3 · Behaviour + + G4 · Feel + + G5 · Visual + + + all green ⇒ done · any fail ⇒ report + + Judge — honest verdict + + Reflexion · fix & retry ≤ 3 + +
A real in-game failure loops back to implement with the gate evidence (bounded to three tries); anything green — or skipped because no live instance is running — falls through to a single honest judge.
+
+ + +It started as three gates — build, test, vision. Gates are cheap to add, so it grew: a feature now also passes a live-game **behaviour** probe and a measured **feel** check before the judge signs off. Critically, the flow is not fixed. Agents can add gates, reorder steps, or branch on conditions. The flow engine handles orchestration; the agents handle decisions. + +### What We Deleted + +The commit removes 1,050 lines across 15 files: + +- `runner.ts` (115 lines) — the main orchestration loop +- `supervisor.ts` (119 lines) — the state machine driving sessions +- `gates.ts` (75 lines) — hardcoded gate definitions +- `policy.ts` (92 lines) — retry limits and decision logic +- `store.ts` (54 lines) — session state persistence +- `types.ts` (76 lines) — type definitions for the whole system +- `events.ts` (47 lines) — inter-process event bus +- Plus tests, examples, and documentation + + +
+ + Net change: −750 lines, + a composable pipeline + Deleted + + supervisor/ — 1,050 lines · 15 files + Kept + + verify_build — ~300 lines · 1 oracle + +
The whole orchestration loop was deleted; only the build oracle survived — and it became the gate that powers the flow.
+
+ + +None of this was bad code. It was just the wrong layer. Flows gives us all of this — orchestration, state, gates, retry policy, event routing — as a framework primitive. We were maintaining a parallel implementation of something the framework already provided. + +The durable asset we kept: `verify_build`, the build oracle. It's now reused as the gate tool that powers the flow pipeline. + +### The Bug That Took a Day to Find + +Moving to flows exposed a subtle problem. Flow sub-agents run in their **own extension stack** — the main session's extensions don't reach them. The build-verifier and test-runner agents declared `verify_build` in their frontmatter, but the tool was never actually in their toolset. + +The symptom was confusing: agents reported "oracle not available" and routed to fail/report, silently skipping the test gate entirely. A false green — the build passed, tests never ran, and the pipeline reported success. + +The fix was a single pattern: emit `flow:register-tool` with the full tool definition at extension activation, and re-announce on `flow:rediscover`. The flow engine collects these into `getExtensionTools()` and hands them to every sub-agent that declares the tool. Three lines of orchestration, a day of debugging. + +Verified live: `game-check` now routes `context → build → build-gate(pass) → tests → tests-gate(pass) → vision`. Every gate fires. No false greens. + +### Why This Architecture Wins + +**Composability.** Agents can add gates without touching framework code. Want a linting gate? Add a sub-agent with a linter tool. Want a security scan? Same pattern. The flow engine handles routing; you just declare the gate. + +**Reusability.** The `verify_build` oracle that powered the old supervisor now powers the flow gates. Same tool, same interface, different orchestration. No rewrite needed. + +**Observability.** FlowDashboard visualizes the entire pipeline. You can see which gates passed, which failed, and where the agent decided to retry. The old supervisor logged to stdout. + +**Self-modification.** Agents can read the flow graph, understand where they are in the pipeline, and decide what to do next. The supervisor's decision tree was opaque to the agents it was supervising. Flows makes the pipeline itself part of the agent's context. + +--- + +## Part 2: Agents That Fix Their Own Builds + +Most coding agents have a dirty secret: they don't care if the code compiles. They write, they push, they walk away. The human discovers the broken build an hour later. The flow-native brain handles verification inside the pipeline — but what about after push? What about CI? + +### The Gap + +Every agent demo looks the same. The AI writes code, commits, pushes. The presenter says "and now we have a pull request!" Cut. End of demo. + +What happens next? The CI pipeline runs. Tests fail. Linting screams. The build breaks because someone forgot an import. A human opens the PR, reads the red badge, clicks into the logs, finds the error, fixes it, pushes again. The agent did 90% of the work but left the last 10% — the most tedious part — for a person. + +We wanted agents that finish the job. + +### The tinqs-ci Extension + +Our [Pi fork](https://tinqs.com/tinqs/pi) has a `tinqs-ci` extension — a single TypeScript file, about 200 lines — that gives the agent three tools: + +- **ci_status** — checks the current pipeline state for a branch (pending, running, success, failure) +- **ci_logs** — fetches the full build log from the most recent failed run +- **ci_wait** — polls the pipeline every 15 seconds until it finishes, then returns the result + +These are Gitea Actions API calls under the hood. The agent authenticates with the same PAT it uses for git push. No extra credentials, no special CI service account. + +### The Loop + +Here's what a Pi task looks like end to end: + +``` +Agent receives task brief + → reads codebase, plans approach + → writes code + → runs local tests (bash tool) + → commits and pushes branch + → calls ci_wait + → CI passes → opens PR via Gitea API + → CI fails → calls ci_logs + → reads error output + → fixes the issue + → pushes again + → calls ci_wait again + → repeats until green (max 3 retries) +``` + +The key is that `ci_logs` returns the raw build output — compiler errors, test failures, lint violations — as plain text in the agent's context. DeepSeek V4 is surprisingly good at reading build logs. It parses a Go compiler error, identifies the file and line, and fixes it. It reads a test assertion failure, understands what the test expected, and corrects the implementation. + +Three retries is the hard limit. If the agent can't fix it in three rounds, it opens the PR anyway with a comment explaining what failed and why. A human takes over from there. In practice, most failures resolve on the first retry — it's usually a missing import or a type mismatch. + +### A Real Run + +Last week. The task: add a health check endpoint to a Go service. + +- **Turn 1:** Agent reads the codebase, writes the handler and test, pushes. CI fails — the test imports a package that doesn't exist on the runner. +- **Turn 2:** Agent reads `ci_logs`, sees the `go: module not found` error, adds the missing `go.mod` replace directive, pushes. CI passes. +- **Turn 3:** Agent opens PR with passing checks. + +Total time: 4 minutes. Total cost: $0.06. No human touched the keyboard. + +Without the CI extension, this would have been a PR with a red badge and a Slack message saying "hey, the agent's PR is broken again." Someone would have context-switched, opened the logs, seen the trivial error, fixed it, and lost 20 minutes of flow state. + +### Why This Matters More Than You Think + +CI integration isn't a feature. It's the difference between an agent that helps and an agent that creates work. + +An agent that pushes broken code is worse than no agent at all. It creates a false sense of progress — "the PR is up!" — while actually adding a task to someone's plate. Every broken PR is an interruption. Every interruption costs 15 minutes of context-switching. + +An agent that watches CI and fixes its own builds is genuinely autonomous. You submit a task, you walk away, you come back to a green PR ready for review. The agent handled the mechanical iteration that a human would have done anyway — the fix-push-wait-check cycle that eats hours of developer time every week. + +### The Guardrail Problem + +Letting an agent retry its own builds sounds dangerous. What if it enters an infinite loop? What if it starts making increasingly wild changes to get the build to pass? + +Three safeguards: + +**Retry limit.** Three attempts maximum. After that, the agent stops and reports. This is a hard limit in the orchestrator, not a suggestion to the model. + +**Diff budget.** Each retry can only touch files that were already in the original changeset. The agent can't "fix" a build failure by rewriting the test suite or disabling the linter. If the fix requires touching new files, it fails and escalates. + +**Hallucination detection.** The guardrail extension monitors every turn. If the agent claims "the build passed" without having called `ci_status` or `ci_wait`, it gets corrected. Agents are not allowed to guess the CI result. + +### The Numbers + +Over three weeks of running the orchestrator: + +- **87 tasks** completed end-to-end +- **23 tasks** needed at least one CI retry (26%) +- **19 of those 23** resolved on the first retry +- **4 tasks** hit the retry limit and escalated to a human +- **0 tasks** produced a merged PR that later broke something else + +The 26% retry rate tells you how often agents push code that doesn't build on the first try. That's not a bad number — it's the same rate you'd see from a junior developer. The difference is the agent fixes it in 30 seconds instead of 20 minutes. + +--- + +## Putting It Together: The Stack + +The flow-native brain and the CI integrator are two sides of the same coin. The flow handles **pre-push verification** — did the code compile? do the tests pass? does the game behave correctly? The CI integrator handles **post-push verification** — did the CI pipeline agree? did anything break on the runner that didn't break locally? + + + + + + + + + + + + + + + + + + +
LayerWhatHow
Flow enginepi-flows orchestratorComposes agents, gates and decision points
Gatesverify_build oracleCompiles, tests, returns PASS/FAIL with file:line errors
Sub-agentsG1 build · G2 tests · G3 behaviour · G4 feel · G5 visualRole-split, each with its own toolset
CI looptinqs-ci extensionci_status, ci_logs, ci_wait — polls Gitea Actions, reads logs, retries
DecisionAgent-loop ReflexionSelf-reflect on failures, retry (≤3) or escalate
VisualizationFlowDashboardReal-time pipeline state
+ + +--- + +The old supervisor was 1,050 lines of code that did one thing well: verify that agent output compiled and passed tests. The new system does the same thing with less code, more flexibility, composable gates, live CI integration, and a bug we'll never hit again. Sometimes the best commit is a deletion. Sometimes it's two. + +*The flow-native brain and CI extension run on our [Pi fork](https://tinqs.com/tinqs/pi) inside [Tinqs Studio](https://tinqs.com). The verify_build extension is ~300 lines of TypeScript, the tinqs-ci extension is ~200 lines — both MIT licensed and reusable in any Pi project.*