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

# Mapping a Process to Substrate Groups, Fields, and Gates

> How to translate workflow stages, per-item metadata, and exit criteria into Substrate groups, field_schema entries, and boolean gate fields.

Before you write a single JSON key, list the stages your team actually uses, the things each work item tracks, and the criteria that must be true before something moves forward. That list is the board. The mapping below turns each element into the right Substrate construct.

## 1. Stages Become Groups

Each workflow stage is one group. Order them with `position` (0, 1, 2, …) — that is left-to-right flow on the board.

```json theme={null}
{
  "id": "spec",
  "name": "Spec",
  "description": "The problem, goals, and acceptance criteria.",
  "position": 0,
  "color": null,
  "version": 1,
  "archived_at": null
}
```

<Tip>
  Ids are referenced by policies and by every task — pick short, stable, human-readable ones. A rename later is a migration.
</Tip>

## 2. Metadata Becomes field\_schema.task

Every distinct thing a work item tracks becomes a field entry under `field_schema.task`:

```json theme={null}
"field_schema": {
  "task": {
    "priority":      { "type": "enum", "values": ["low", "med", "high"] },
    "spec_doc":      { "type": "string" },
    "acceptance":    { "type": "markdown" },
    "spec_approved": { "type": "boolean" },
    "tests_passing": { "type": "boolean" }
  },
  "comments": {}
}
```

Add a boolean gate field for each exit criterion you will enforce. If a criterion must be signed off by a person, mark that field `"human_only": true` — write tools will refuse to set it, making the human's approval the only path forward.

To change one field on an existing board without resending the whole schema, use `update_board`'s `field_schema_patch`.

## 3. The Mapping Recipe

| In the process                   | Becomes                                               |
| -------------------------------- | ----------------------------------------------------- |
| Workflow stages                  | `groups`, ordered by `position`                       |
| What each item tracks            | `field_schema.task` entries                           |
| Stage exit criteria / hard gates | `transition_guard` with `require` on a gate field     |
| Definition of done               | `"*"` → `done` `transition_guard` requiring key flags |
| Conventions and reminders        | `agent_responsibility` with `when` matching stage     |

## 4. A Worked Shape

A three-stage board with one real gate — from Spec to Build only when `plan_approved` is set:

```json theme={null}
{
  "id": "delivery",
  "name": "Delivery",
  "description": "Spec → Build → Done.",
  "field_schema": {
    "task": { "plan_approved": { "type": "boolean" } },
    "comments": {}
  },
  "groups": [
    { "id": "spec",  "name": "Spec",  "description": "", "position": 0, "color": null, "version": 1, "archived_at": null },
    { "id": "build", "name": "Build", "description": "", "position": 1, "color": null, "version": 1, "archived_at": null },
    { "id": "done",  "name": "Done",  "description": "", "position": 2, "color": null, "version": 1, "archived_at": null }
  ],
  "policies": [
    {
      "id": "gate-build",
      "name": "No build without an approved plan",
      "description": "Spec → Build requires plan_approved.",
      "type": "transition_guard",
      "definition": {
        "from_group": "spec",
        "to_group": "build",
        "require": [{ "field": "task.plan_approved", "op": "eq", "value": true }],
        "on_failure_message": "Set plan_approved once the plan is signed off."
      },
      "priority": 0,
      "enabled": true,
      "version": 1,
      "created_by_agent": "you",
      "created_at": "2026-01-01T00:00:00.000Z",
      "updated_at": "2026-01-01T00:00:00.000Z",
      "archived_at": null
    }
  ],
  "version": 1,
  "created_at": "2026-01-01T00:00:00.000Z",
  "updated_at": "2026-01-01T00:00:00.000Z",
  "archived_at": null
}
```

Once you have this shape, move on to writing the full policy DSL and validating that the rails fire.

***

<CardGroup cols={2}>
  <Card title="Write Policies" icon="shield" href="/authoring/write-policies">
    The full DSL for transition guards and agent responsibilities.
  </Card>

  <Card title="Validate Gates" icon="circle-check" href="/authoring/validate-gates">
    Prove your guards actually fire before relying on them.
  </Card>
</CardGroup>
