> ## Documentation Index
> Fetch the complete documentation index at: https://docs.obversa.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Feature delivery

> Analyse, implement, test, review, approve: one brief to an approved change, with the reviewers able to send it back.

Hand a brief to a team and get back an approved change with the evidence
beside it. This file has a Claude seat write a requirements note, a Codex
seat implement it, runs the test with Node, has a Claude reviewer read the
result, and has a final Claude seat write the approval. The reviewer can
send the work back to the implementer, once.

```bash theme={null}
npm install @obversa/runtime @obversa/teams @obversa/engine-claude-cli @obversa/engine-codex
```

## The file

```ts theme={null}
import { ClaudeCliEngine } from '@obversa/engine-claude-cli';
import { CodexEngine } from '@obversa/engine-codex';
import { run } from '@obversa/runtime';
import { featureDelivery } from '@obversa/teams';

const workspace = process.cwd();
const analyse = {
  engine: new ClaudeCliEngine({
    defaultModel: 'claude-sonnet-4-5',
    permissionMode: 'bypassPermissions',
  }),
  identity: {
    adapter: 'claude-cli',
    provider: 'anthropic',
    modelFamily: 'claude',
    model: 'claude-sonnet-4-5',
  },
};
const implement = {
  engine: new CodexEngine({
    defaultModel: 'gpt-5.6-luna',
    permissionMode: 'bypassPermissions',
  }),
  identity: {
    adapter: 'codex',
    provider: 'openai',
    modelFamily: 'gpt',
    model: 'gpt-5.6-luna',
  },
};
const reviewer = {
  engine: new ClaudeCliEngine({
    defaultModel: 'claude-sonnet-4-5',
    permissionMode: 'bypassPermissions',
  }),
  identity: {
    adapter: 'claude-cli',
    provider: 'anthropic',
    modelFamily: 'claude',
    model: 'claude-sonnet-4-5',
  },
};
const approve = {
  engine: new ClaudeCliEngine({
    defaultModel: 'claude-sonnet-4-5',
    permissionMode: 'bypassPermissions',
  }),
  identity: {
    adapter: 'claude-cli',
    provider: 'anthropic',
    modelFamily: 'claude',
    model: 'claude-sonnet-4-5',
  },
};

const team = featureDelivery({
  brief: 'Deliver a pure triple(value) function in src/triple.mjs with a Node test in test/triple.test.mjs.',
  workspace,
  files: ['src/triple.mjs', 'test/triple.test.mjs'],
  test: { command: 'node', args: ['--test', 'test/triple.test.mjs'] },
  analyse,
  implement,
  reviewers: [{ name: 'correctness', seat: reviewer }],
  reviewThreshold: 1,
  approve,
});

const result = await run(team, { cwd: workspace });
console.log(JSON.stringify(result.outcome, null, 2));
```

## What a run printed

From one real run of this file.

```json theme={null}
{
  "status": "pass",
  "summary": "dag \"feature-delivery\": all 5 node(s) green",
  "data": {
    "analyse": {
      "status": "pass",
      "summary": "Requirements extracted from work brief and documented in team-output/brief.md. Identified 4 core requirements: pure triple(value) function, source location (src/triple.mjs), Node test implementation, and test location (test/triple.test.mjs)."
    },
    "implement": {
      "status": "pass",
      "summary": "Implemented pure triple(value) with finite-number validation and added Node tests for numeric and invalid inputs."
    },
    "test": {
      "status": "pass",
      "summary": "`node` exited 0"
    },
    "review": {
      "status": "pass",
      "summary": "Review panel: 1/1 reviewer(s) cleared.",
      "data": {
        "findings": [],
        "escalatedFindings": [],
        "errors": [],
        "results": [
          {
            "kind": "verdict",
            "name": "correctness",
            "met": true,
            "reason": "Implementation is correct. The triple function is pure, properly validates inputs, and correctly multiplies finite numbers by 3. Tests comprehensively verify both valid inputs and error cases."
          }
        ],
        "passed": 1,
        "required": 1,
        "severityCounts": {}
      }
    },
    "approve": {
      "status": "pass",
      "summary": "Implementation meets all requirements. The triple function is pure, correctly multiplies finite numbers by 3, properly validates inputs, and has comprehensive passing tests (2/2). Ready to ship."
    }
  }
}
```

The analyse step wrote `team-output/brief.md`:

```md theme={null}
# Work Brief Requirements

## Requirements

1. **Function Implementation**
   - Create a function named `triple`
   - Function accepts a `value` parameter
   - Function must be pure (deterministic, no side effects, same input always produces same output)

2. **Source File Location**
   - File path: `src/triple.mjs`

3. **Test Implementation**
   - Create a Node test for the `triple` function
   - Test must verify the function's behavior

4. **Test File Location**
   - File path: `test/triple.test.mjs`
```

The implementer wrote `src/triple.mjs`:

```js theme={null}
export function triple(value) {
  if (typeof value !== 'number' || !Number.isFinite(value)) {
    throw new TypeError('value must be a finite number');
  }

  return value * 3;
}
```

and `test/triple.test.mjs`:

```js theme={null}
import test from 'node:test';
import assert from 'node:assert/strict';
import { triple } from '../src/triple.mjs';

test('triple multiplies finite numbers by three', () => {
  assert.strictEqual(triple(4), 12);
  assert.strictEqual(triple(0), 0);
  assert.strictEqual(triple(-2.5), -7.5);
});

test('triple rejects values that are not finite numbers', () => {
  for (const value of [undefined, null, '4', {}, NaN, Infinity]) {
    assert.throws(() => triple(value), TypeError);
  }
});
```

The approve step wrote `team-output/approval.md`:

```md theme={null}
# Approval

**Status:** ✅ Ready to ship

## Summary

The `triple` function implementation meets all brief requirements and is ready for production:

- **Pure function**: Deterministic, no side effects, consistent output for same input
- **Correct behavior**: Multiplies finite numbers by 3 as specified
- **Robust validation**: Properly rejects non-finite and non-number inputs with TypeError
- **Comprehensive tests**: All tests pass (2/2), covering both valid cases and error handling

## Evidence

1. **Implementation correctness**: Function correctly returns `value * 3` for all finite numbers
2. **Test coverage**: Tests verify positive (4→12), zero (0→0), and negative (-2.5→-7.5) cases
3. **Error handling**: Validation correctly rejects undefined, null, strings, objects, NaN, and Infinity
4. **Review verification**: Correctness review passed with no findings
5. **Test execution**: All tests pass with 100% success rate

## Recommendation

**Ship immediately.** No changes required.
```

## The team's shape

| step      | does                                                                              | done when                                                         |
| --------- | --------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| analyse   | Turn the brief into a delivery note the later steps can read.                     | The delivery note is in the workspace and names each requirement. |
| implement | Build the change from the delivery note, taking the last review into account.     | The code and its test cover every requirement in the note.        |
| test      | Run the test command against the change.                                          | The test command exits 0.                                         |
| review    | Have the reviewers read the change and the test result and count the acceptances. | At least the threshold number of reviewers have accepted.         |
| approve   | Record that the change is ready to ship.                                          | An approval note is in the workspace.                             |

Each step needs the one before it. A review below `reviewThreshold` is a
revision request aimed at `implement`; the implementer runs again with the
findings, then the test and the review run again with it.

## Gotchas

* **The analyse step writes the note and nothing else.** The package
  compares the expected files before and after the analyse step, and fails
  it by name if the seat wrote or changed any of them, because a plan
  written after the code is not a plan. Files that were already in the
  workspace before the run are left alone.
* **The implementer and every reviewer are different model families.** The
  analyse and approve seats are free to share a family with either.
* **The approval is a file, not a status.** `team-output/approval.md` is
  what the approve step must leave behind, and the step fails when it is
  missing or empty.
* **A writing seat can write anywhere the process can.** The files above
  start their Claude and Codex seats with permission prompts off, which is
  what lets a model write files. Run them in a directory you are willing
  to let a model change, and give a reviewing seat a read-only mode if its
  plugin has one.

## Source

The file is `examples/teams/feature-delivery.ts`. The
[teams package page](/packages/teams) lists every input.
