Skip to content

feat(symphony): factory autonomous SDLC workflow pack (ENG-2921)#1127

Draft
hari (harivansh-afk) wants to merge 1 commit into
mainfrom
factory-workflow
Draft

feat(symphony): factory autonomous SDLC workflow pack (ENG-2921)#1127
hari (harivansh-afk) wants to merge 1 commit into
mainfrom
factory-workflow

Conversation

@harivansh-afk

@harivansh-afk hari (harivansh-afk) commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

What

A Symphony pack implementing the autonomous agent workflow from ENG-2921: five agent roles plus an escalate escape hatch that take an idea from conception to a green, auto-merged PR on ix.

Idea generator / Cleaner  --(factory:scope-needed)-->  Researcher -> Worker <-> Reviewer -> merge
        (cron feeders)                                        (one Symphony run per issue)

How it works

  • Two cron feeders (idea-generator, cleaner) scan ix + prior art and file deduped Linear issues labelled factory:scope-needed.
  • task-pipeline triggers per issue on that label: Researcher scopes -> Worker implements on a branch + opens a PR -> bounded Reviewer/Worker correction loop -> auto-merge when build is green.
  • Loops on an acyclic runtime: Symphony has no backward edges and a when body holds exactly one statement, so the Worker<->Reviewer loop is an unrolled, flat when-cascade ordered by data deps. MAX_ROUNDS = 3 is a structural convergence cap (no review4 exists). Open-ended macro arrows are cross-run via Linear labels.
  • Merge reuses the existing ix-playbook-agent bot path (squash via merge queue; main auto-deploys), inheriting its .github/**/CODEOWNERS guardrails.

Validation

All three .sym were run through the real parser + interpreter + materializer (pure Elixir, no hex deps):

file result
cleaner.sym OK - 1 agent node
idea-generator.sym OK - 1 agent node
task-pipeline.sym OK - 8 nodes (1 agent + 7 lazy gates)

The 1 agent + 7 gates shape confirms the lazy forward cascade and that envelope validation passes.

Scope / notes

  • No symphony runtime changes - pure pack + config. Activate with SYMPHONY_PACK_DIR=packages/symphony/workflows/factory.
  • Design doc: packages/symphony/docs/factory-workflow.md.
  • Verify on first boot (documented in the pack README): agent JSON output parsing into ${node.field}, tool names (linear_graphql, web_search), and widening the ix-side ix-playbook-agent auto-merge scope from playbook-only to code.

Closes ENG-2921.

Note

Add autonomous SDLC factory Symphony workflow pack for ix

Macroscope summarized a478e81.

A Symphony pack implementing the agent workflow from ENG-2921: five agent
roles (idea-generator, cleaner, researcher, worker, reviewer) plus an escalate
escape hatch that take an idea to a green, auto-merged PR on ix.

- Two cron feeders (idea-generator, cleaner) file deduped Linear issues.
- task-pipeline runs per issue on the factory:scope-needed label: scope ->
  implement -> bounded review/fix cascade -> auto-merge. The Worker<->Reviewer
  loop is an unrolled, flat when-cascade (Symphony is acyclic); MAX_ROUNDS=3 is
  the structural convergence cap.
- Reuses the ix-playbook-agent bot path for PRs + auto-merge.
- Pure pack + config; no runtime changes. All three .sym validated through the
  real parser + interpreter + materializer.
@harivansh-afk hari (harivansh-afk) marked this pull request as draft June 16, 2026 19:21

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review found issues in this pull request.

Verdict: patch is incorrect
Confidence: 0.91

The factory pack is not runnable as added: skills with partials fail to load, agent nodes lack a placement/cwd, the workflow depends on unsupported structured agent outputs, and skipped conditional branches can deadlock. Additional delegate/tool paths also cannot work with the current runtime wiring.

  • P1 packages/symphony/workflows/factory/skills/researcher.md:29 Move partials under the skills directory
  • P1 packages/symphony/workflows/factory/workflows/task-pipeline.sym:13 Set a real placement for agent nodes
  • P1 packages/symphony/workflows/factory/_partials/decision-contract.md:3 Do not gate on final-message JSON until it is parsed
  • P1 packages/symphony/workflows/factory/workflows/task-pipeline.sym:21 Flattened gates can deadlock on skipped branches
  • P2 packages/symphony/workflows/factory/skills/worker.md:10 Delegate cannot retrigger while the current run is active
  • P2 packages/symphony/workflows/factory/skills/idea-generator.md:1 Declared tools are not available to these agents

Comment on lines +29 to +31
{{partial:ix-validation}}

{{partial:decision-contract}}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Move partials under the skills directory

These skills include {{partial:...}}, but Symphony resolves partials relative to the skill file's directory as skills/_partials/<name>.md. This PR added the partials at workflows/factory/_partials, so the loader will return {:missing_partial, ...} for each referenced partial and the catalog will not publish the skill; prompt: skill "researcher" then fails at runtime. Move the shared partials under skills/_partials or update the loader to support this pack-level location.

Comment on lines +13 to +18
scope <- agent {
engine: codex
model: "gpt-5.3-codex"
effort: high
permissions: read_only
prompt: skill "researcher"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Set a real placement for agent nodes

This agent omits location, so the envelope defaults to :local. The runtime only acquires a checkout/cwd for :host or :ixvm; for :local/:room, workspace_cwd returns :error and RoomEngineClient fails the turn with :missing_cwd. The same omission appears on the other new agents, so the factory workflows fail before any prompt runs unless each agent declares a real placement or local cwd support is added.

Comment on lines +3 to +6
End your turn by emitting EXACTLY ONE fenced JSON object as the final block of
your message. Nothing after it. Downstream `when` gates read its fields, so the
keys and types must match what your role declares. Booleans must be real JSON
booleans, not strings.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Do not gate on final-message JSON until it is parsed

The contract assumes the agent's fenced JSON becomes node output fields, but the current synchronous engine response persisted by Symphony contains only thread/event/cost metadata and drops message text. As a result ${scope.scoped}, ${impl.completed}, and reviewer fields are absent even when the model emits the requested JSON, so the Worker/review gates cannot make decisions from agent output. Add fail-closed parsing of the final JSON into node output, or use a mechanism that already produces structured output, before relying on these fields.

Comment on lines +21 to +34
# Worker: implement the scoped plan on a branch and open a PR (only if scoped).
impl <- when ${scope.scoped} {
agent {
engine: codex
model: "gpt-5.3-codex"
effort: high
permissions: workspace_write
prompt: skill "worker" { plan: ${scope.plan}, affected: ${scope.affected_crates} }
}
}

# Review round 1 (only if the Worker completed and opened a PR).
review1 <- when ${impl.completed} {
agent {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Flattened gates can deadlock on skipped branches

After a closed when, the bound name is not added to the interpreter environment. If scope.scoped is false, impl is never bound but the next top-level statement still evaluates when ${impl.completed}; that becomes a gate placeholder with no dependency, which placeholders never run or retire, so the run deadlocks instead of ending as denied/skipped. The same pattern repeats for later review rounds after an approval. Keep later rounds inside the gate that creates their inputs, or emit explicit false/default outputs for skipped branches.

Comment on lines +10 to +15
1. Read the `plan`. If you disagree with it (wrong, unsafe, or it needs more
research), you are allowed to **deny** or **delegate** - do not build
something you think is wrong. Comment your reasoning on the issue.
- deny -> label `factory:denied`.
- delegate -> label `factory:scope-needed` again with a comment on what the
Researcher must resolve.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Delegate cannot retrigger while the current run is active

The delegate path re-applies the same factory:scope-needed trigger label from inside the current Linear-triggered run. The Linear webhook controller dedupes events for issues that already have an active pending/running run, so that label update is ignored; when this run exits there is no second webhook to start Researcher. Delegate needs to enqueue after the current run is no longer active, use a distinct handoff path, or invoke Researcher within the current workflow.

Comment on lines +1 to +23
---
description: Propose one high-value improvement or feature idea for ix and file it as a Linear issue, deduped against existing work.
tools: [linear_graphql, web_search]
---

You are the Idea Generator in an autonomous SDLC factory for the **ix** repo
(custom rust-vmm VMM, ix-server RPC, two isolated regions, IPv6-as-identity).

Goal: produce **one** concrete, valuable idea per run and file it as a Linear
issue. Quality over quantity. One good idea beats three vague ones.

Steps:
1. Inspect the checked-out ix workspace. Look for: missing capabilities, rough
edges, places competitors/prior art do better. Use web search for prior art
and competitor features when it sharpens the idea.
2. **Dedup before filing.** Query Linear for open AND closed issues with similar
titles/scope (use `linear_graphql`). If the idea already exists or was
already rejected, DO NOT file it - return `created: false` and stop.
3. If it is genuinely new, create a Linear issue:
- Clear problem statement (what + why, from a user/system perspective).
- A short solution sketch.
- Label it `factory:scope-needed` (this is what triggers the pipeline).
- Team: Engineering. Priority: your best judgment.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Declared tools are not available to these agents

This feeder requires web_search and linear_graphql to dedupe and create Linear issues, but in the current engine path skill frontmatter is only loaded with the prompt metadata; RoomEngineClient submits tools: [] unless run options explicitly supply tools, and the runtime never derives that from skill.tools. These agents therefore cannot perform their primary action even with LINEAR_API_KEY configured. Wire skill.tools into the turn request or avoid depending on these tool names.

@github-actions

Copy link
Copy Markdown
Contributor

Blast radius

24 of 1462 checks would rebuild between base 33458d6 and head ba6817c.

pie showData title Rebuilt checks by category
  "image" : 15
  "rust" : 2
  "site" : 2
  "agent" : 1
  "blast" : 1
  "eval" : 1
  "lint" : 1
  "symphony" : 1
Loading
flowchart LR
  c0["ix-mcp"]
  c1["blast-radius-test"]
  c2["agent-context"]
  c3["lint"]
  c4["site-test"]
  c5["site-case-tests"]
  c0 --> k0["agent-context"]
  c0 --> k2["eval"]
  c0 --> k3["image-development-base"]
  c0 --> k4["image-kernel-dev"]
  c0 --> k5["image-minecraft"]
Loading
changed checks (24)
  • agent-context
  • blast-radius-test
  • eval
  • image-development-base
  • image-kernel-dev
  • image-minecraft
  • image-minecraft-bedrock
  • image-minecraft-status
  • image-minecraft_1.21.11-fabric
  • image-minecraft_1.21.11-paper
  • image-minecraft_26.1.2-fabric
  • image-minecraft_26.1.2-paper
  • image-minecraft_26w17a-fabric
  • image-minestom
  • image-neovim-ci
  • image-remote-desktop
  • image-symphony-codex
  • image-test-cluster-bootstrap
  • lint
  • rust-mcp.evalSmoke
  • rust-mcp.requirementsSmoke
  • site-case-tests
  • site-test
  • symphony-elixir

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant