Skip to content

feat: squads-as-workflows — published workflows, board-as-bus, mute-to-user#23

Open
0xthc wants to merge 1 commit into
mainfrom
squads-as-workflows
Open

feat: squads-as-workflows — published workflows, board-as-bus, mute-to-user#23
0xthc wants to merge 1 commit into
mainfrom
squads-as-workflows

Conversation

@0xthc
Copy link
Copy Markdown

@0xthc 0xthc commented Jun 1, 2026

What & why

Companion to basalt-ai/infrastructure#530. Establishes the squad-side contract for the squads-as-workflows architecture: squads become fire-and-forget units that publish outcome-typed workflows and communicate with the cofounder only through the company task board (one voice out to the user).

Design doc / RFC: docs/workflows-architecture.md.

Changes

Workflow catalog contract

  • manifest.workflows[] {id, summary, inputs, outcome, agent} — added to manifest.schema.json, scripts/validate.mjs (id format, required fields, agent must be a declared agent id, no dup ids, unknown-field rejection), and documented in docs/bundle-reference.md.

Board-as-bus in the template

  • HEARTBEAT.md: reconcile assigned tickets first (board is the source of truth — push + pull, controller-style), self-cert or needs_input, never message the user.
  • SOUL.md: mute-to-user inviolable — the board is the only channel; self-certify reversible outcomes (correction = cofounder reopens, not an up-front gate).
  • docs/how-squads-work.md + bundle-reference.md: the bus, reconcile loop, crons-through-the-board (cron output files kind: routine/digest tickets with no notify_channel), and self-managed crons.

New pilot — github-triage-squad

  • triage-agent + 3 workflows (github.triage_issue / sweep_open_issues / weekly_report), a P0–P3 criticality rubric skill, a labeling skill, and crons that file routine/digest tickets. Read-mostly, so a low-blast-radius first proof of the loop.

Verification

  • node scripts/validate.mjs → all 7 bundles valid (existing squads untouched; workflows[] is additive/backward-compatible).
  • Negative-tested every workflow error class (bad id, empty summary, missing outcome, undeclared agent, unknown field, dup id) → non-zero exit.
  • The authoritative marketplace validator (apps/marketplace/src/services/manifest.ts, in #530) mirrors the same rule with +4 tests.

🤖 Generated with Claude Code

…o-user

Squads become fire-and-forget units that publish outcome-typed workflows and
communicate with the cofounder only through the company task board.

- manifest workflows[] {id,summary,inputs,outcome,agent} — schema + validator
  (agent must be declared; id/summary/outcome required), bundle-reference docs
- HEARTBEAT template: reconcile assigned tickets first (board is source of
  truth; push + pull), self-cert or needs_input, never message the user
- SOUL template: mute-to-user inviolable — the board is the only channel
- crons-through-the-board: cron output files kind:routine/digest tickets with
  no notify_channel (lands on the board without paging the user)
- new pilot: github-triage-squad (P0-P3 issue triage, 3 workflows, daily sweep
  + weekly report crons)
- RFC: docs/workflows-architecture.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 1, 2026 22:22
@0xthc
Copy link
Copy Markdown
Author

0xthc commented Jun 1, 2026

Companion infra PR (tasks plugin, squad-store catalog, marketplace validator, cofounder context slimming): basalt-ai/infrastructure#530

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR establishes the squad-side contract for a “squads-as-workflows” architecture, where squads publish outcome-typed workflows and communicate with the cofounder exclusively via the company task board (board-as-bus, mute-to-user).

Changes:

  • Adds manifest.workflows[] to the bundle contract, with schema + validator enforcement and documentation.
  • Updates the template agent SOUL.md/HEARTBEAT.md and docs to formalize “board is source of truth”, reconcile loop, self-certification, and mute-to-user.
  • Introduces a new pilot bundle github-triage-squad with a triage agent, three workflows, skills, and scheduled crons that file routine/digest tickets.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
template/agents/example-agent/SOUL.md Updates agent operating principles and escalation/boundaries for board-as-bus + mute-to-user.
template/agents/example-agent/HEARTBEAT.md Adds reconcile-first wake procedure and ticket-based workflow execution guidance.
squads/github-triage-squad/SQUAD.md New squad catalog card describing the triage squad and its workflows.
squads/github-triage-squad/ONBOARD.md New onboarding script for connecting GitHub and seeding an initial sweep ticket.
squads/github-triage-squad/manifest.json New squad manifest including published workflows and required permissions/secrets.
squads/github-triage-squad/crons/jobs.json New daily/weekly cron jobs that run workflows and file routine/digest tickets.
squads/github-triage-squad/agents/triage-agent/* New triage agent identity/soul/heartbeat + skills (rubric + labeling mechanics).
scripts/validate.mjs Validates manifest.workflows[] and enforces workflow id/fields/agent membership.
manifest.schema.json Extends JSON schema to include workflows[] contract.
docs/workflows-architecture.md Adds RFC/design doc for the new architecture and rollout phases.
docs/how-squads-work.md Documents board-as-bus communication and self-certification behavior.
docs/bundle-reference.md Documents the new workflows[] contract and cron-through-the-board pattern.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +77 to +80
Escalation is the exception, not the rhythm. You escalate **on the ticket** —
`add_task_comment` + `update_task_status(needs_input)` for an intent question,
`fail_task` for a hard blocker. Never by messaging the user. Escalate **only**
when:
Comment on lines +111 to 114
- **DM the co-founder out of band.** All squad↔co-founder communication is on the
ticket (`complete_task`, `add_task_comment`, `needs_input`) — auditable, never a side channel.
- Solicit or accept secrets in chat — always use the vault (`vault_request`).
- Make financial transactions or commit the company to spend.
- Modify other agents' workspaces. Read-only across siblings.
Comment on lines +36 to +38
- **A `todo` ticket assigned to you?** That's a dispatched job — claim it:
`update_task_status(id, "in_progress")`, then `get_task(id)` to read the full
brief from `context` (it names the **workflow** to run + its inputs).
Comment on lines +55 to +59
- **Blocked on intent only the cofounder has** (which target? what tone? is this
spend OK?)? Do **not** guess and do **not** message the user. Post the question
with `add_task_comment(id, "<your question>")`, then
`update_task_status(id, "needs_input", blocked_on: "<short>")`. The cofounder
answers on the thread and flips you back to `in_progress`.
Comment on lines +97 to +99
- On completion: `complete_task` with the outcome (self-cert).
- On a clarification need: `add_task_comment` + `update_task_status(needs_input)`.
- On a hard blocker: `fail_task` with the reason; log it.
Comment on lines +34 to +35
- `create_task({ assigned_to: "triage-agent", priority: "today", title: "Initial triage sweep — <repo>", context: "Run the github.sweep_open_issues workflow for <repo>. Classify every untriaged open issue P0–P3, label it, post + file each assessment, then file the sweep digest as a routine ticket. Report the headline numbers and any P0/P1 back on this ticket.", notify_channel: <your Slack channel id>, notify_session_key: <your sessionKey> })`
- Then `sessions_spawn` Triage on it (runtime: subagent, mode: run) and `update_task_status(id, "in_progress")`.
Comment on lines +23 to +25
- **A `todo` ticket assigned to you?** Claim it: `update_task_status(id, "in_progress")`, then
`get_task(id)` to read the brief — it names the workflow (`github.triage_issue`,
`github.sweep_open_issues`, or `github.weekly_report`) and its inputs (`repo`, `issue_number`).
Comment on lines +39 to +41
- **Severity genuinely ambiguous?** `add_task_comment(id, "<specific question>")` then
`update_task_status(id, "needs_input", blocked_on: "<short>")`. Do **not** guess a P-level
and do **not** message the user.
"id": "weekly-report",
"name": "Weekly issue-health report — Triage",
"enabled": true,
"schedule": { "kind": "cron", "expr": "0 10 * * MON", "tz": "America/Los_Angeles" },
Comment thread scripts/validate.mjs
Comment on lines +185 to +187
if (w.inputs !== undefined && !isObject(w.inputs)) {
err(`${at}.inputs`, "must be an object mapping input name → type/description when present");
}
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.

2 participants