feat: add typed inter-agent communication schema

Replace freetext signals (RFR, LGTM, VERDICT: PASS) with YAML
frontmatter envelopes routed by a `signal` field. New message-schema
skill defines 12 message types covering worker submissions, review/audit
verdicts, triage/plan results, research results, and orchestrator
commands. All agents load the skill; qa-checklist enforces compliance;
orchestrate routes by envelope signal.
This commit is contained in:
Bryan Ramos 2026-04-02 07:38:02 -04:00
parent d2fdcbc731
commit 341f500396
14 changed files with 476 additions and 39 deletions

View file

@ -0,0 +1,309 @@
---
name: message-schema
description: Typed envelope schema for all inter-agent communication. Defines message types, required fields, and signal routing contracts.
when_to_use: Automatically loaded by all agents and the orchestrator via skills frontmatter. Reference when producing or consuming agent output.
---
Every agent output and orchestrator dispatch uses a **YAML frontmatter envelope** followed by a **markdown body**. The envelope contains routing metadata; the body contains human-readable content.
```
---
type: <message_type>
signal: <routing_signal>
# ... type-specific fields
---
[markdown body]
```
The `signal` field is the orchestrator's primary routing key. It determines the next action without parsing prose.
---
## Signals
### Agent → Orchestrator
| Signal | Meaning | Emitted by |
|--------|---------|------------|
| `rfr` | Work complete, ready for review | worker, debugger, documenter |
| `pass` | Review/audit passed cleanly | reviewer, auditor |
| `pass_with_notes` | Passed with non-blocking findings | reviewer, auditor |
| `fail` | Review/audit failed, needs rework | reviewer, auditor |
| `triage_complete` | Triage done, research questions identified (or none) | architect |
| `plan_complete` | Plan written to file | architect |
| `research_complete` | Research question answered | researcher |
| `blocked` | Cannot proceed, needs orchestrator intervention | any agent |
| `escalate` | Beyond agent scope, needs user decision | any agent |
### Orchestrator → Agent
| Signal | Meaning | Sent to |
|--------|---------|---------|
| `execute` | Perform this task | worker, debugger, documenter, architect |
| `revise` | Fix listed issues and resubmit | worker, debugger, documenter |
| `lgtm` | Approved, commit now | worker, debugger, documenter |
| `research` | Answer this research question | researcher |
| `plan` | Produce architecture and wave decomposition | architect |
---
## Agent → Orchestrator Message Types
### worker_submission
Emitted by: worker, debugger, documenter
```yaml
---
type: worker_submission
signal: rfr | blocked | escalate
files_changed:
- path/to/file1
- path/to/file2
ac_coverage:
AC1: pass | fail | partial | na
AC2: pass | fail | partial | na
qa_check: pass | fail
---
```
Required: `type`, `signal`, `files_changed`, `qa_check`
Optional: `ac_coverage` (omit when no AC provided in assignment)
Body: `## Result` section with implementation details, then `## Self-Assessment` with per-criterion notes and known limitations.
### review_verdict
Emitted by: reviewer
```yaml
---
type: review_verdict
signal: pass | pass_with_notes | fail
critical_count: 0
moderate_count: 2
minor_count: 1
ac_coverage:
AC1: pass | fail
AC2: pass | fail
---
```
Required: `type`, `signal`, `critical_count`, `ac_coverage`
Optional: `moderate_count`, `minor_count`
**Hard rule:** `critical_count > 0` requires `signal: fail`.
Body: Findings by severity (CRITICAL / MODERATE / MINOR), then AC Coverage details, then one-line summary.
### audit_verdict
Emitted by: auditor
```yaml
---
type: audit_verdict
signal: pass | pass_with_notes | fail
security_findings:
critical: 0
high: 0
medium: 0
low: 0
build_status: pass | fail | skipped
test_status: pass | fail | partial | skipped
typecheck_status: pass | fail | skipped
---
```
Required: `type`, `signal`, `security_findings`, `build_status`, `test_status`
Optional: `typecheck_status`
**Hard rule:** `security_findings.critical > 0` or `build_status: fail` or `test_status: fail` requires `signal: fail`.
Body: Security findings by severity (or CLEAN), then Runtime section with tested/passed/failed.
### triage_result
Emitted by: architect (Phase 1)
```yaml
---
type: triage_result
signal: triage_complete
tier: 0 | 1 | 2 | 3
research_needed: true | false
research_count: 3
---
```
Required: `type`, `signal`, `tier`, `research_needed`
Optional: `research_count` (present when `research_needed: true`)
**Routing:** `research_needed: false` means the orchestrator skips research and resumes architect directly for Phase 2.
Body: Triage section (Tier, Problem, Constraints, Success criteria, Out of scope), then Research Questions if any.
### plan_result
Emitted by: architect (Phase 2)
```yaml
---
type: plan_result
signal: plan_complete | blocked
plan_file: .claude/plans/kebab-case-title.md
format: brief | full
wave_count: 3
step_count: 7
risk_tags:
- security
- data-mutation
has_blockers: false
---
```
Required: `type`, `signal`, `plan_file`, `wave_count`, `risk_tags`
Optional: `format`, `step_count`, `has_blockers`
**Routing:** `has_blockers: true` triggers user escalation before worker dispatch.
Body: One-paragraph summary of what the plan covers.
### research_result
Emitted by: researcher
```yaml
---
type: research_result
signal: research_complete
topic: "brief topic identifier"
verified: true | false
has_gotchas: true | false
---
```
Required: `type`, `signal`, `topic`, `verified`
Optional: `has_gotchas`
**Routing:** `verified: false` flags unverified assumptions to the architect before planning.
Body: Answer, Verified Facts with sources, Version Constraints, Gotchas, Unverified claims.
---
## Orchestrator → Agent Message Types
### task_assignment
Sent to: worker, debugger, documenter
```yaml
---
type: task_assignment
signal: execute
task: "short task title"
plan_file: .claude/plans/kebab-case-title.md
wave: 1
step: 2
---
```
Required: `type`, `signal`
Optional: `task`, `plan_file`, `wave`, `step` (Tier 0 tasks may lack plan context)
Body: Task spec, Acceptance Criteria, Context (interface contracts, constraints, out-of-scope), Files to modify/read.
### revision_request
Sent to: worker, debugger, documenter
```yaml
---
type: revision_request
signal: revise
iteration: 2
max_iterations: 5
fix_severity: critical | critical+moderate | all
---
```
Required: `type`, `signal`, `iteration`
Optional: `max_iterations`, `fix_severity`
`fix_severity` maps to iteration: 1-3 = `all`, 4-5 = `critical`.
Body: Issues to fix (from reviewer and/or auditor), grouped by source, with guidance.
### approval
Sent to: worker, debugger, documenter
```yaml
---
type: approval
signal: lgtm
---
```
Required: `type`, `signal`. Pure control signal — commit using conventional commit format.
### triage_request
Sent to: architect (Phase 1)
```yaml
---
type: triage_request
signal: execute
---
```
Required: `type`, `signal`
Body: Raw user request and any relevant project context.
### architecture_request
Sent to: architect (Phase 2, resume)
```yaml
---
type: architecture_request
signal: plan
---
```
Required: `type`, `signal`
Body: Assembled `## Research Context` block from all researchers, or "No research needed — proceed."
### research_request
Sent to: researcher
```yaml
---
type: research_request
signal: research
topic: "brief topic identifier"
---
```
Required: `type`, `signal`, `topic`
Body: Specific question, why it matters (what decision it gates), where to look, relevant project context.
---
## Schema Compliance
Before returning output, verify:
1. Output starts with a valid YAML frontmatter envelope (`---` delimiters)
2. `type` matches your message type
3. `signal` uses a valid enum value for your direction (agent→orch or orch→agent)
4. All required fields for your message type are present
5. Enum fields use exact values from this schema (no variations like "PASS" vs "pass")
6. Hard rules are satisfied (e.g., `critical_count > 0` implies `signal: fail`)

View file

@ -108,12 +108,17 @@ After each wave, spawn `reviewer` and `auditor` in a single response. They run i
Both receive: worker output, plan file path, acceptance criteria list, risk tags.
Collect both verdicts before deciding whether to advance to the next wave or send back for fixes.
**Routing by envelope:** Read the `signal` field from each reviewer/auditor envelope:
- `signal: pass` → advance to next wave
- `signal: pass_with_notes` → advance, surface notes in final delivery
- `signal: fail` → check `critical_count` / `security_findings` and send worker to fix
Do not advance until both verdicts are collected.
### Step 7 — Feedback loop on issues
1. Resume the worker with reviewer findings and instruction to fix
2. On resubmission, spawn reviewer again (new instance — stateless)
1. Resume the worker with a `revision_request` envelope containing reviewer/auditor findings
2. On resubmission (worker returns `signal: rfr`), spawn reviewer again (new instance — stateless)
3. Repeat
**Severity-aware decisions:**
@ -201,21 +206,28 @@ Spawning agents sequentially when they could run in parallel is a protocol viola
### Git flow
Workers signal `RFR` when done. You control commits:
- `LGTM` → worker commits
- Mark a step `- [x]` in the plan file **only when every worker assigned to that step has received LGTM**
- `REVISE` → worker fixes and resubmits with `RFR`
Workers return `signal: rfr` when done. You control commits:
- Send `signal: lgtm` → worker commits
- Mark a step `- [x]` in the plan file **only when every worker assigned to that step has received `signal: lgtm`**
- Send `signal: revise` → worker fixes and resubmits with `signal: rfr`
- Merge worktree branches after individual validation
- On Tier 2+: merge each worker's branch after validation, resolve conflicts if branches overlap
Only the orchestrator updates the plan file. Workers must not modify `.claude/plans/`.
### Review signals
### Message schema
| Signal | Direction | Meaning |
All agent communication uses typed YAML frontmatter envelopes defined in the `message-schema` skill. The `signal` field is your primary routing key.
| Envelope signal | Direction | Your action |
|---|---|---|
| `RFR` | worker → orchestrator | Ready for review |
| `LGTM` | orchestrator → worker | Approved, commit your changes |
| `REVISE` | orchestrator → worker | Fix the listed issues and resubmit |
| `VERDICT: PASS / PASS WITH NOTES / FAIL` | reviewer → orchestrator | Review result |
| `VERDICT: PASS / PARTIAL / FAIL` | auditor → orchestrator | Runtime validation result |
| `signal: rfr` | worker → you | Dispatch to reviewer (+ auditor if risk tags match) |
| `signal: pass` | reviewer/auditor → you | Advance to next wave |
| `signal: pass_with_notes` | reviewer/auditor → you | Advance, surface notes in delivery |
| `signal: fail` | reviewer/auditor → you | Send `revision_request` to worker |
| `signal: triage_complete` | architect → you | Check `research_needed`, spawn researchers or resume architect |
| `signal: plan_complete` | architect → you | Read plan file, begin wave dispatch |
| `signal: research_complete` | researcher → you | Collect, assemble into Research Context |
| `signal: blocked` / `signal: escalate` | any → you | Investigate or escalate to user |
When dispatching agents, use the orchestrator→agent envelope types (`task_assignment`, `revision_request`, `approval`, `triage_request`, `architecture_request`, `research_request`) from the message-schema skill.

View file

@ -39,9 +39,17 @@ Before returning your output, validate against every item below. If you find a v
- If you stated something as fact, can you back it up? Challenge your own claims.
- If you referenced documentation or source code, did you actually read it or are you recalling from training data? When it matters, verify.
### Schema compliance
- Does your output start with a valid YAML frontmatter envelope (`---` delimiters)?
- Does the `type` field match your message type?
- Does the `signal` field use a valid enum value from the message-schema skill?
- Are all required fields for your message type present?
- Are hard rules satisfied (e.g., `critical_count > 0` requires `signal: fail`)?
## After validation
Set `qa_check: pass` or `qa_check: fail` in your frontmatter envelope. This replaces the old `QA self-check` prose line.
In your Self-Assessment section, include:
- `QA self-check: [pass/fail]` — did your output survive the checklist?
- If fail: what you found and fixed before submission
- If qa_check is fail: what you found and fixed before submission
- If anything remains unverifiable, flag it explicitly as `Unverified: [claim]`

View file

@ -5,15 +5,28 @@ description: Standard output format, feedback handling, and operational procedur
## Output format
Return using this structure. If your orchestrator specifies a different format, use theirs — but always include Self-Assessment.
Wrap your output in a `worker_submission` envelope per the message-schema skill:
```yaml
---
type: worker_submission
signal: rfr | blocked | escalate
files_changed:
- path/to/file1
- path/to/file2
ac_coverage:
AC1: pass | fail | partial | na
AC2: pass | fail | partial | na
qa_check: pass | fail
---
```
Then the markdown body:
```
## Result
[Your deliverable here]
## Files Changed
[List files modified/created, or "N/A" if not a code task]
## Self-Assessment
- Acceptance criteria met: [yes/no per criterion, one line each]
- Known limitations: [any, or "none"]
@ -37,11 +50,11 @@ Before returning your output, run the `qa-checklist` skill against your work. Fi
## Commits
Do not commit until your orchestrator sends `LGTM`. End your output with `RFR` to signal you're ready for review.
Do not commit until your orchestrator sends `signal: lgtm`. Your output envelope's `signal: rfr` replaces the old freetext `RFR` — the envelope IS the signal.
- `RFR` — you → orchestrator: work complete, ready for review
- `LGTM` — orchestrator → you: approved, commit now
- `REVISE` — orchestrator → you: needs fixes (issues attached)
- `signal: rfr` — you → orchestrator: work complete, ready for review
- `signal: lgtm` — orchestrator → you: approved, commit now
- `signal: revise` — orchestrator → you: needs fixes (issues attached)
When you receive `LGTM`:
- Commit using conventional commit format per project conventions