Files
orquestra/docs/context-handoff.md
rikrdo 634525fa21 feat: Orquestra - sequential orchestration runtime
- Context isolation: fresh Pi process per stage (run_stage.py)
- Gate enforcement: blocks close without approved gates
- Auto commit/push on feature close (close_feature.py)
- Write restrictions: only allowed directories (ALLOWED_WRITE_DIRS)
- Pi extension: orquestra-status with /orquestra-stage command
- Documentation: context-handoff.md, updated README
- Scripts: agent_status.py, verify.sh, install.sh updated
2026-08-17 07:39:03 +02:00

277 lines
7.0 KiB
Markdown

# Context Handoff in Orquestra
Orquestra keeps agents focused by making context explicit. Agents do not pass a whole chat history to the next agent. They pass durable artifacts on disk, and each new stage reads only the files declared for that stage.
## Quick path
1. The current agent writes its result to `work/artifacts/<feature_id>/`.
2. From the active Pi session, `/orquestra-stage <stage> [feature_id]` calls `scripts/run_stage.py`.
3. `run_stage.py` starts a fresh Pi process.
4. The new agent receives only the `input` paths declared in `harness/workflow.stages.yml`.
5. The new agent writes its own output artifact.
6. `scripts/agent_status.py` and `scripts/verify.sh` enforce stage order and gates.
7. When the `close` stage completes, `scripts/close_feature.py <feature_id>` runs automatically to validate gates, update the backlog, commit and push if a remote repo is configured.
## Mental model
```text
Agent A
reads its stage inputs
writes one durable artifact
work/artifacts/F-001/agent-a-output
run_stage.py starts a fresh Pi process
Agent B
reads only declared inputs, including Agent A's artifact if relevant
writes its own artifact
```
The agents “talk” through files, not through memory-heavy chat context.
## Why fresh processes matter
A single long Pi session naturally accumulates chat, tool output, false starts, and old assumptions. That causes two problems:
| Problem | Orquestra answer |
|---|---|
| The next agent gets distracted by old context | Start the next stage with `--no-session --no-context-files` |
| Token usage grows until compaction | Each stage starts with a small prompt and declared files |
| Claims become hard to verify | Only artifacts on disk count as handoff evidence |
| Agents can skip gates in chat | `agent_status.py` validates stage owner and prerequisites |
## What a stage receives
Each stage receives three kinds of context:
1. **Harness rules** — always read first.
- `AGENTS.md`
- `harness/agents.matrix.yml`
- `harness/workflow.stages.yml`
- `harness/contracts/handoff.md`
2. **Declared stage inputs** — from `harness/workflow.stages.yml`.
3. **Selected Engram memory** — only when the agent performs a narrow search for a concrete need.
The full previous chat is not valid input.
## Example: design to build
`architect` receives product/spec context:
```yaml
- name: design
owner: architect
input:
- work/current.md
- spec/product.md
- spec/tech.md
- spec/acceptance.md
output:
- work/artifacts/<feature_id>/architect.md
```
It writes:
```text
work/artifacts/F-001/architect.md
```
Then `implementer` starts fresh from the active Pi session:
```text
/orquestra-stage build F-001
```
Equivalent shell form:
```bash
python3 scripts/run_stage.py build --feature-id F-001
```
The generated prompt gives it only:
```yaml
- name: build
owner: implementer
input:
- work/current.md
- spec/product.md
- spec/tech.md
- spec/acceptance.md
- work/artifacts/<feature_id>/architect.md
output:
- work/artifacts/<feature_id>/implementer.md
```
So the implementer knows the design result, but not the architect's full chat.
## Example: build to review
The implementer writes evidence:
```text
work/artifacts/F-001/implementer.md
```
A minimal implementer artifact should answer:
```markdown
# Implementer Evidence
## Changed files
- project/app.py
- tests/test_app.py
## What changed
- Added ticket creation validation.
## Checks
- `python3 -m unittest discover -s tests -v` passed.
## Notes for reviewer
- Main behavior lives in `project/app.py:create_ticket`.
```
Then reviewer starts fresh:
```text
/orquestra-stage review_gate F-001
```
Reviewer input is only:
```yaml
input:
- work/current.md
- spec/acceptance.md
- work/artifacts/<feature_id>/implementer.md
```
Reviewer does not need the architect's whole reasoning unless the workflow explicitly declares it. If reviewer needs more, it blocks and asks for a specific artifact/path.
## Example: security and QA reuse only relevant context
Security does not need all acceptance prose plus every design note. It needs the implementation evidence and review result:
```yaml
- name: security_gate
owner: security
input:
- work/current.md
- work/artifacts/<feature_id>/implementer.md
- work/artifacts/<feature_id>/reviewer.json
```
QA needs acceptance criteria and approved gate context:
```yaml
- name: qa_gate
owner: qa
input:
- work/current.md
- spec/acceptance.md
- work/artifacts/<feature_id>/implementer.md
- work/artifacts/<feature_id>/reviewer.json
- work/artifacts/<feature_id>/security.json
```
That is the core rule: give each agent the smallest context that lets it do its job.
## Anti-cheating controls
```text
run_stage.py
├─ starts fresh Pi process
├─ disables previous session/context files
└─ injects only declared input/output paths
agent_status.py
├─ validates stage owner
├─ requires feature_id for real stages
├─ rejects gated stages when prerequisite artifacts are missing
└─ keeps visible runtime status
orquestra-status extension
├─ blocks writes outside allowed directories: project/, tests/, work/, backlog/, spec/, harness/, scripts/, platforms/, docs/
├─ blocks product/test writes outside implementer build stage
└─ blocks product code in repository root
verify.sh
├─ validates harness structure
├─ validates backlog/runtime JSON
├─ validates Engram availability
└─ rejects done features without approved gate artifacts
```
Chat-only claims do not pass any gate. The agent must write evidence to disk.
## What Engram is for
Engram is durable memory for reusable facts, not a replacement for stage artifacts.
Each stage must save to Engram only when it produced durable knowledge.
Use Engram for:
- stable project decisions,
- bug fixes,
- non-obvious discoveries,
- reusable conventions or patterns,
- configuration changes,
- repeated gotchas,
- environment facts,
- lessons learned across features.
Do not use Engram for:
- replacing `implementer.md`,
- hiding gate evidence,
- routine progress,
- command output dumps,
- artifact summaries,
- passing huge summaries to every stage,
- bypassing declared workflow inputs.
A good Engram lookup is narrow:
```text
Search: "orquestra project root product files rule"
Use result only if it affects this stage.
```
A bad lookup is broad:
```text
Search: "everything about this project"
```
## Updating an installed project safely
From the Orquestra source checkout:
```bash
/path/to/orquestra/scripts/install.sh /path/to/project
cd /path/to/project
./scripts/verify.sh
```
The installer updates harness-owned files and preserves project-owned progress files when they already exist:
```text
backlog/features.json
spec/*
work/current.md
work/history.md
work/runtime-status.json
project/*
work/artifacts/*
```
That means an existing project can adopt fresh-stage handoff without losing its current feature state.