Primitives
The project-memory entity model — the shape of a WorkItem, a DecisionRecord, an Artifact, and the rest of the durable record.
processkit provides a compact set of process primitives as universal
building blocks. The v2 direction keeps durable project facts in the
entity layer and moves workflow definitions, schedules, runtime model
data, and lifecycle implementation details to narrower surfaces.
In the v1 release line, apiVersion remains
processkit.projectious.work/v2. The product release version and entity API
version are independent. Create and transition canonical entities through MCP
management tools rather than hand-editing them.
Shipped v2 entity schemas
| Primitive | Purpose | Prefix |
|---|
| WorkItem | Unit of work (task, story, bug, epic, spike, chore) | BACK |
| LogEntry | Immutable record of something that happened | LOG |
| DecisionRecord | A choice with rationale (ADR pattern) | DEC |
| Migration | Pending/in-progress/applied transition between upstream versions | MIG |
| Artifact | Completed deliverable (document, dataset, build, URL) | ART |
| Note | Zettelkasten capture layer (fleeting, insight, reference) | NOTE |
| Actor | Person or agent (humans, AI, services) | ACTOR |
| Role | Named set of responsibilities | ROLE |
| Binding | Scoped/temporal relationship between two entities (generalized RoleBinding) | BIND |
| Scope | Bounded container (sprint, milestone, project, quarter, release) | SCOPE |
| Category | Classification axis with defined values | CAT |
| Gate | Validation checkpoint | GATE |
| Constraint | Rule or limit the project must respect | CONST |
| Context | Ambient knowledge and environment | CTX |
| Discussion | Multi-turn exploratory conversation | DISC |
| TeamMember | Persistent participant with persona, agent card, and memory tiers | TEAMMEMBER |
Demoted legacy surfaces
Metric, Model, Process, Schedule, and StateMachine are not
first-class shipped entity surfaces in the SmoothTiger/SmoothRiver v2
direction. Metric and policy definitions become artifact-backed
specifications; readings and events are LogEntries or external time
series. Model data belongs to model-recommender roster/configuration
surfaces. Processes are represented by process-instance WorkItems with
definition Artifacts. Schedules are represented by time-window Bindings.
State machines remain validation machinery, not author-facing workflow
records.
Layered relationships
Primitives depend on each other through the skill hierarchy:
Layer 0: index (infrastructure), id (infrastructure), LogEntry (event-log)
Layer 1: Actor (actor-profile), Role (role-management), TeamMember
Layer 2: WorkItem, DecisionRecord, Scope, Category, Binding, CrossReference
Layer 3: Gate, Constraint, Migration, workflow/projection skills
Layer 4: Discussion, metrics-management, Owner profile (owner-profiling), Context grooming
Lower layers never depend on higher layers. The management skill for a
primitive follows the same layer (e.g. workitem-management is Layer 2 and
depends on event-log at Layer 0 and actor-profile at Layer 1).
Cross-references vs Bindings
Rule: if a relationship has scope, time, or its own attributes → use a
Binding entity. Otherwise → use a cross-reference field in frontmatter.
| Situation | Use |
|---|
| “A blocks B” | cross-ref |
| “Alice is a developer” (globally) | cross-ref |
| “Alice is tech lead on project X for 2026” | Binding |
| “Security gate applies to release process on main” | Binding |
See Primitives → Relationships
for details.
Schema coverage
The current schema tree includes these authoritative YAML schema files under
src/context/schemas/
.
The schemas define the spec fields, required vs optional, and enum
constraints. MCP servers validate against the schema on every write call —
schema errors surface as structured tool errors rather than silent bad data.
Installer or CI validation can check the same file contracts without
starting a full agent session. MCP write tools perform the authoritative
write-path validation.
Next
1 - Entity File Format
Every processkit primitive entity is stored as a Markdown file with a
YAML frontmatter block. The format is inspired by Kubernetes objects —
stable, versioned, and easy to parse.
Canonical shape
---
apiVersion: processkit.projectious.work/v1 # required — schema version
kind: WorkItem # required — primitive type
metadata: # required
id: BACK-calm-fox
created: 2026-04-06T10:30:00Z
updated: 2026-04-06T11:15:00Z
labels:
priority: high
spec: # required — entity-specific
title: "Add a release audit check"
state: in-progress
assignee: ACTOR-alice
---
# Body — freeform Markdown
Human-readable description, acceptance criteria, notes, history.
The four top-level keys
| Key | Required | Purpose |
|---|
apiVersion | yes | Schema version. Always processkit.projectious.work/v1 at v0.x. |
kind | yes | Primitive type. Determines which schema validates spec. |
metadata | yes | Identity, timestamps, labels. Cross-cutting fields. |
spec | yes | Entity-specific fields. Validated by primitive schema. |
| Field | Required | Type | Notes |
|---|
id | yes | string | Unique identifier. Format configurable (see below). |
created | yes | ISO 8601 datetime | UTC. Never edited after creation. |
updated | no | ISO 8601 datetime | Set on modification. |
labels | no | map[string]string | Arbitrary key-value tags. Used by queries and filters. |
Configurable per project through installer or processkit settings:
id_format | id_slug | Example |
|---|
word | false | BACK-calm-fox |
word | true | BACK-calm-fox-add-lint |
uuid | false | BACK-550e8400-e29b-41d4 |
uuid | true | BACK-550e8400-add-lint |
The prefix (BACK-, LOG-, DEC-, …) is determined by the primitive
kind and is not configurable. See
Reference → ID Formats
for details.
apiVersion policy
apiVersion follows the Kubernetes convention: <group>/<version>, where
the group is a reverse-DNS name anchored on the owning organization. For
processkit the group is processkit.projectious.work, making processkit
a subcomponent of the projectious.work organization. This prevents
name collisions if other organizations fork or publish compatible
primitives under their own domains.
See Reference → apiVersion Policy
for
the evolution rules.
Authoritative source
The authoritative specification is
src/context/schemas/
in the processkit repo. This page is a condensed overview; the shipped
schema files define the authoritative spec contracts for each kind.
2 - State Machines
Primitives with lifecycle (WorkItem, DecisionRecord, Scope, Discussion)
are governed by state machines. processkit ships default machines that
projects can override.
WorkItem default
backlog → in-progress → review → done
↓ ↑
blocked ↑
↓ ↑
backlog ←
(any state) → cancelled (terminal)
Source: src/context/state-machines/workitem.yaml
.
DecisionRecord default
proposed → accepted → superseded (terminal)
↓
rejected (terminal)
Source: src/context/state-machines/decisionrecord.yaml
.
Overriding a default
Projects override a default by placing a same-named file in their own
context/state-machines/ directory. The index MCP server (v0.3.0) and any
validator prefer the project file over the processkit default.
Overrides must:
- Keep the same
initial state (or migrate existing data). - Not remove states that existing entities are currently in.
- Add new transitions only from states that already exist.
See the state-machine-management skill
for details.
Multiple machines for one kind
You can ship multiple state machines for the same primitive kind by using
distinct names. Entities opt into a specific machine via
spec.state_machine: <name>. Useful when the same kind has fundamentally
different lifecycles (e.g. a WorkItem with bug-lifecycle vs
story-lifecycle).
3 - Relationships
processkit expresses relationships between entities two ways:
- Cross-references — lightweight fields in frontmatter
- Bindings — first-class entities with their own files
Pick the right one based on what the relationship needs.
The rule
If a relationship has scope, time, or its own attributes → Binding.
Otherwise → cross-reference.
Cross-reference examples
# In a WorkItem
spec:
blocks: [BACK-swift-oak]
blocked_by: [BACK-calm-fox]
related_decisions: [DEC-023]
parent: BACK-epic-lint
Conventional field names:
| Field | Meaning |
|---|
parent | This entity is a child of another |
children | This entity has sub-items |
blocks | This entity blocks others until resolved |
blocked_by | This entity is blocked by others |
related_workitems | Typed relationship to WorkItems |
related_decisions | Typed relationship to DecisionRecords |
supersedes | This entity replaces an older one |
superseded_by | This entity has been replaced |
implements | This entity implements a decision |
See the cross-reference-management skill
for the full list and conventions.
Binding examples
---
apiVersion: processkit.projectious.work/v1
kind: Binding
metadata:
id: BIND-bright-falcon
created: 2026-04-06T00:00:00Z
spec:
type: role-assignment
subject: ACTOR-alice
target: ROLE-tech-lead
scope: SCOPE-project-x
valid_from: 2026-01-01
valid_until: 2026-12-31
---
Conventional binding types:
| type | subject kind | target kind |
|---|
role-assignment | Actor | Role |
work-assignment | WorkItem | Actor |
workitem-gate | WorkItem | Gate |
scope-gate | Scope | Gate |
time-window | any | any |
budget-application | Artifact | WorkItem/Scope |
Legacy process-gate, process-scope, and schedule-scope Bindings
are v1 migration inputs only. New v2 relationships should target the
concrete WorkItem, Scope, Artifact, or Gate being governed.
See the binding-management skill
for the full spec.
Why Binding was generalized from RoleBinding
DISC-002 §11 analyzes the decision to generalize the 18th primitive from
RoleBinding to Binding. The short version: the indirection pattern applies
to at least 7 relationship types across processkit, and one generalized
primitive is cleaner than multiplying specific bindings. See
DEC-023
in the aibox repo.
4 - WorkItem
A unit of work — task, story, bug, epic, spike, or chore. The primary
work-tracking primitive in processkit.
| |
|---|
| ID prefix | BACK |
| State machine | workitem |
| MCP server | workitem-management |
| Skill | workitem-management (Layer 2) |
State machine
backlog → in-progress → review → done
↕
blocked
All states can transition to cancelled. done and cancelled are
terminal.
Fields
Required
| Field | Type | Description |
|---|
title | string (1–200) | Short, actionable title |
state | string | Current state |
Optional
| Field | Type | Description |
|---|
description | string | Long-form description, acceptance criteria |
type | enum | task · story · bug · epic · spike · chore (default: task) |
priority | enum | critical · high · medium · low |
assignee | ACTOR-* | Responsible actor |
parent | BACK-* | Parent work item (for subtasks / epics) |
children | BACK-*[] | Child work item IDs |
blocks | BACK-*[] | Items this one blocks |
blocked_by | BACK-*[] | Items blocking this one |
related_decisions | DEC-*[] | Decisions that motivated or govern this item |
scope | string | Scope ID (sprint, milestone, release) |
estimate | object | Freeform effort estimate |
started_at | datetime | Set automatically on first in-progress transition |
completed_at | datetime | Set automatically on done or cancelled |
Example
---
apiVersion: processkit.projectious.work/v1
kind: WorkItem
metadata:
id: BACK-20260411_0900-BoldVale-fts5-full-text-search
created: '2026-04-11T09:00:00Z'
spec:
title: Add FTS5 full-text search to SQLite index
state: backlog
type: story
priority: medium
description: |
Implement FTS5 trigram tokeniser in index.py so agents can search
entity body text, not just frontmatter fields.
related_decisions:
- DEC-20260409_1200-SwiftPeak-sqlite-for-index
---
Notes
- All state transitions are auto-logged via
event-log — no manual log
call needed. - Use
parent / children to model epics and subtasks; keep the epic
type epic and subtask types task or story. scope is a free string; bind to a Scope entity via binding-management
when you need richer scope tracking (dates, goals, state).- Query by state, type, priority, or assignee via
query_workitems.
5 - LogEntry
An immutable, append-only record of something that happened. The audit
trail primitive — never updated or deleted after creation.
| |
|---|
| ID prefix | LOG |
| State machine | none (immutable) |
| MCP server | event-log |
| Skill | event-log (Layer 0) |
Fields
Required
| Field | Type | Description |
|---|
event_type | string | Machine-readable event type (e.g. workitem.created, gate.passed) |
actor | string | ID of actor who caused the event |
timestamp | datetime | When the event occurred (ISO 8601 UTC) |
Optional
| Field | Type | Description |
|---|
subject | string | ID of the entity the event concerns |
subject_kind | string | Kind of subject entity (fast filtering) |
summary | string | One-line human-readable summary |
details | object | Event-specific structured payload |
correlation_id | string | Links related events (e.g. a workflow run) |
Example
---
apiVersion: processkit.projectious.work/v1
kind: LogEntry
metadata:
id: LOG-20260411_0901-SteadyWren-workitem-transitioned
created: '2026-04-11T09:01:00Z'
spec:
event_type: workitem.transitioned
actor: ACTOR-claude
timestamp: '2026-04-11T09:01:00Z'
subject: BACK-20260411_0900-BoldVale-fts5-full-text-search
subject_kind: WorkItem
summary: WorkItem transitioned from backlog to in-progress
details:
from_state: backlog
to_state: in-progress
---
Auto-logging
Entity-mutating MCP servers (create_*, transition_*, link_*) append a
LogEntry automatically — callers do not need to call log_event separately.
Manual calls to log_event are for events that have no MCP server: deploying
a build, running a meeting, making a phone call, completing a manual step in a
process.
Event type conventions
Use dot-separated entity.verb naming:
| Pattern | Examples |
|---|
<kind>.created | workitem.created, decision.created |
<kind>.transitioned | workitem.transitioned, scope.transitioned |
<kind>.linked | workitem.linked, decision.linked |
gate.passed / gate.failed / gate.waived | gate evaluation results |
metric.recorded | individual metric reading |
constraint.violated | constraint breach |
session.handover | end-of-session handover written |
Notes
- LogEntries are never updated or deleted. If an event was logged in
error, log a corrective entry explaining the error.
query_events and recent_events support filtering by subject, actor,
event_type, and date range.- Logs are date-sharded:
context/logs/{year}/{month}/.
6 - DecisionRecord
A significant choice — architectural, product, or process — recorded with
its context, rationale, and alternatives. The ADR (Architecture Decision
Record) pattern as a first-class entity.
| |
|---|
| ID prefix | DEC |
| State machine | decisionrecord |
| MCP server | decision-record |
| Skill | decision-record (Layer 2) |
State machine
proposed → accepted → superseded
↘ rejected
accepted, rejected, and superseded are terminal.
Fields
Required
| Field | Type | Description |
|---|
title | string (1–200) | Short declarative title |
state | string | Current state |
decision | string | The chosen option, stated clearly |
Optional
| Field | Type | Description |
|---|
context | string | Situation that prompted the decision |
rationale | string | Why this option was chosen |
alternatives | object[] | Each with option (required) and rejected_because (optional) |
consequences | string | Known or expected downstream effects |
deciders | ACTOR-*[] | People / agents who made the decision |
supersedes | DEC-* | Prior decision this replaces |
superseded_by | DEC-* | Later decision that replaces this one |
related_workitems | BACK-*[] | Work items that motivated or implement this decision |
decided_at | datetime | When the decision was finalised |
Example
---
apiVersion: processkit.projectious.work/v1
kind: DecisionRecord
metadata:
id: DEC-20260411_0902-SwiftPeak-sqlite-for-index
created: '2026-04-11T09:02:00Z'
spec:
title: Use SQLite as the entity index store
state: accepted
decision: Use SQLite with WAL mode as the backing store for the index.
context: |
We need a queryable index over all context/ entities that agents can
use without doing filesystem walks.
rationale: |
SQLite is zero-config, ships as a Python built-in, and supports
full-text search via FTS5. No external service needed.
alternatives:
- option: PostgreSQL
rejected_because: Requires a running service; too heavy for local dev.
- option: DuckDB
rejected_because: No built-in full-text search; adds a dependency.
decided_at: '2026-04-09T12:00:00Z'
---
Notes
- Use
supersede_decision to create a clean supersession chain when a
decision changes — the old record stays as history, the new one links
back via supersedes. - Link decisions to work items with
link_decision_to_workitem to make
the “why was this built?” trail queryable. proposed is the right starting state for decisions that need
stakeholder sign-off before being acted on.
7 - Artifact
A completed deliverable — document, dataset, build, diagram, URL,
runbook, slide deck, or any other produced output. A catalogue record,
not a work-tracking entity.
| |
|---|
| ID prefix | ART |
| State machine | none |
| MCP server | artifact-management |
| Skill | artifact-management (Layer 2) |
Two usage patterns
Self-hosted — the content lives in the entity file’s Markdown body.
location is omitted or used as an optional secondary pointer.
Pointer — the content lives externally (Figma, Google Drive, S3, a
git path). location is required; the body may be empty or contain a
summary.
Fields
Required
| Field | Type | Description |
|---|
name | string | Human-readable name |
kind | enum | document · design · dataset · build · slides · video · spec · diagram · url · other |
Optional
| Field | Type | Description |
|---|
location | string | Path, URL, repo ref, or storage identifier |
format | string | File format or MIME type (pdf, png, application/json, …) |
version | string | Version identifier |
checksum | string | Hash for integrity verification |
owner | ACTOR-* | Actor responsible for this artifact |
produced_by | string | Entity that produced it (workitem, process, decision ID) |
produced_at | datetime | When the artifact was produced |
tags | string[] | Freeform tags for retrieval |
Examples
Self-hosted (document body in the file)
---
apiVersion: processkit.projectious.work/v1
kind: Artifact
metadata:
id: ART-20260411_0903-BrightVale-deploy-runbook
created: '2026-04-11T09:03:00Z'
spec:
name: Deploy Runbook — v0.12.0
kind: document
tags: [runbook, deploy, v0.12.0]
produced_at: '2026-04-11T09:03:00Z'
---
## Steps
1. Run smoke tests: `uv run scripts/smoke-test-servers.py`
2. Stamp provenance: `bash scripts/stamp-provenance.sh vX.Y.Z`
...
Pointer (external file)
---
apiVersion: processkit.projectious.work/v1
kind: Artifact
metadata:
id: ART-20260411_0904-NeatDawn-brand-design-system
created: '2026-04-11T09:04:00Z'
spec:
name: Brand Design System
kind: design
location: https://www.figma.com/file/abc123/brand-design-system
format: figma
owner: ACTOR-design-team
tags: [brand, design-system]
---
Notes
- Artifact has no state machine — it is a catalogue record, not a
work-tracking entity. Use WorkItem to track the work that produces it.
query_artifacts supports filtering by kind, tags, and title
substring.- For long-lived reference documents that agents should read, prefer
the
context-management skill; for point-in-time deliverables,
use Artifact.
8 - Note
A Zettelkasten capture layer for ideas, observations, and references.
Notes exist on a spectrum from raw capture (fleeting) to permanent
knowledge (insight).
| |
|---|
| ID prefix | NOTE |
| State machine | note |
| MCP server | note-management |
| Skill | note-management (Layer 2) |
State machine
fleeting → insight
↘ promoted (promoted to another entity kind)
↘ archived
insight, promoted, and archived are terminal.
Note types (Luhmann/Ahrens taxonomy)
| Type | Description |
|---|
fleeting | Quick capture, not yet refined — review within a week |
insight | Permanent note — self-contained conclusion, part of knowledge base |
reference | Literature note — pointer to an external source with summary |
question | Open question — may promote to WorkItem (spike) or Discussion |
Fields
Required
| Field | Type | Description |
|---|
title | string (1–120) | Self-contained claim or question — not a topic label |
body | string | The note content |
type | enum | fleeting · insight · reference · question |
state | string | Current state |
Optional
| Field | Type | Description |
|---|
tags | string[] | Freeform tags for discoverability |
source | string | For reference notes: URL, book title, or conversation |
promotes_to | object | {kind, id} — target entity when promoted |
review_due | date | When the note should be reviewed |
inbox | object | Hook-inbox status and routing metadata |
links | object[] | Typed edges to other Notes (see below) |
Hook inbox
The note-management MCP server can capture external or
agent-generated interrupts as Notes with spec.inbox. Inbox items move
through captured, claimed, completed, or failed, with an
injection_mode of interrupt, ambient, or next-cycle.
Hook adapters may use the filesystem hand-off directories
tasks/inbox/, tasks/claimed/, tasks/done/, and tasks/failed/.
Use prepare_hook_inbox_dirs to create that layout, then
capture_inbox_item, claim_inbox_item, complete_inbox_item, and
fail_inbox_item to keep the canonical Note state in processkit.
Links — typed Zettelkasten edges
Each entry in links has:
| Field | Type | Description |
|---|
target | NOTE-* | The linked note |
relation | enum | See table below |
context | string (≥10 chars) | One sentence explaining why the connection matters |
| Relation | Meaning |
|---|
elaborates | This note expands on the target |
contradicts | This note disagrees with the target |
supports | This note provides evidence for the target |
is-example-of | This note is a concrete case of the target’s claim |
see-also | Related but not directly argumentative |
refines | This note sharpens or corrects the target |
sourced-from | This note draws its content from the target |
Example
---
apiVersion: processkit.projectious.work/v1
kind: Note
metadata:
id: NOTE-20260411_0905-ClearDawn-fts5-trigram
created: '2026-04-11T09:05:00Z'
spec:
title: FTS5 trigram tokeniser matches substrings without pre-tokenisation
body: |
SQLite's FTS5 with the trigram tokeniser splits text into overlapping
3-character sequences. This lets you search for partial words
(e.g. "Crow" matches "StoutCrow") without needing a dedicated
tokenisation pass. Ideal for entity ID word-pair search.
type: insight
state: insight
tags: [sqlite, fts5, search]
links:
- target: NOTE-20260411_0906-BrightWave-search-ux
relation: supports
context: >
Trigram matching is what makes the search UX feel instant —
users type partial word-pairs and get matches immediately.
---
Notes
- Title discipline matters: a good Note title is a self-contained
claim or question —
"FTS5 trigram tokeniser matches substrings" not
"FTS5 notes". The title alone should convey the idea. - Tags group notes by topic; links build arguments. Use both.
- A
question note that remains unanswered after a week should become
a Discussion or WorkItem spike.
9 - Actor
A participant in the project — human, AI agent, or automated service.
Actors are assigned to WorkItems, named in DecisionRecords, and bound
to Roles.
| |
|---|
| ID prefix | ACTOR |
| State machine | none |
| MCP server | actor-profile |
| Skill | actor-profile (Layer 1) |
Fields
Required
| Field | Type | Description |
|---|
type | enum | human · ai-agent · service |
name | string (1–200) | Display name (for AI agents: model name + version) |
Optional
| Field | Type | Description |
|---|
email | email | Humans only |
handle | string | GitHub handle, Slack user, etc. |
expertise | string[] | Tags used by assignment-suggestion logic |
roles | ROLE-*[] | Shortcut for unscoped role assignment |
preferences | object | Freeform (commit style, timezone, review style, …) |
active | boolean | false = actor has left, no new work assigned (default: true) |
joined_at | datetime | When actor became part of the project |
left_at | datetime | When actor stopped |
Example
---
apiVersion: processkit.projectious.work/v1
kind: Actor
metadata:
id: ACTOR-20260411_0906-SteadyWren-claude
created: '2026-04-11T09:06:00Z'
spec:
type: ai-agent
name: Claude Sonnet 4.6
handle: claude
expertise: [python, typescript, processkit, documentation]
active: true
preferences:
commit_style: conventional-commits
timezone: UTC
---
Notes
- Roles are descriptive, not restrictive — processkit does not enforce
RBAC. Use
roles for assignment-suggestion only. - Use
deactivate_actor (not manual editing) to mark an actor as
active: false; it keeps the index consistent. - For scoped or time-bounded role assignments, use a Binding instead
of the
roles shortcut field.
10 - Role
A named set of responsibilities. Roles are descriptive — they document
who is expected to do what, but do not enforce access control.
| |
|---|
| ID prefix | ROLE |
| State machine | none |
| MCP server | role-management |
| Skill | role-management (Layer 1) |
Fields
Required
| Field | Type | Description |
|---|
name | string (1–100) | Kebab-case identifier matching the metadata.id suffix |
description | string | One-sentence purpose statement |
Optional
| Field | Type | Description |
|---|
responsibilities | string[] | Imperative bullet points — concrete, not vague |
skills_required | string[] | Skill IDs or names (advisory, not enforced) |
default_scope | enum | project · sprint · permanent — assumed scope when binding without an explicit one |
supersedes | ROLE-* | Role ID this one replaces |
Example
---
apiVersion: processkit.projectious.work/v1
kind: Role
metadata:
id: ROLE-20260411_0907-ClearOak-tech-lead
created: '2026-04-11T09:07:00Z'
spec:
name: tech-lead
description: Owns technical direction and architecture decisions.
responsibilities:
- Review and approve architectural decisions (DEC)
- Unblock teammates on technical questions within 24 hours
- Run weekly engineering sync
skills_required: [software-architecture, code-review, decision-record]
default_scope: project
---
Notes
- Roles describe responsibilities, not permissions. processkit does not
enforce RBAC.
- A global, unscoped assignment can use the Actor’s
roles field
directly. For a scoped or time-bounded assignment (“Alice is tech lead
on Project X for Q2”), create a Binding instead. link_role_to_actor creates the shortcut entry on the Actor entity.
11 - Binding
A scoped or time-bounded relationship between two entities — the
junction-table pattern promoted to a first-class primitive. Use when a
relationship has scope, time, or its own attributes; use a frontmatter
cross-reference field otherwise.
| |
|---|
| ID prefix | BIND |
| State machine | none |
| MCP server | binding-management |
| Skill | binding-management (Layer 2) |
When to use a Binding vs a cross-reference
| Situation | Use |
|---|
| “A blocks B” | frontmatter blocks: [BACK-...] |
| “Alice is a developer” (globally) | Actor’s roles: [ROLE-...] |
| “Alice is tech lead on Project X for Q2 2026” | Binding |
| “Security gate applies to this release WorkItem on main” | Binding |
| “Sprint 7 scopes these work items for Apr 1-14” | Binding |
Fields
Required
| Field | Type | Description |
|---|
type | string | Freeform binding type (see conventions below) |
subject | string | Entity on the “from” side |
target | string | Entity on the “to” side |
Optional
| Field | Type | Description |
|---|
subject_kind | string | Primitive kind of subject |
target_kind | string | Primitive kind of target |
scope | SCOPE-* | Scope within which the binding applies |
valid_from | string | When binding starts (date or ISO 8601 datetime) |
valid_until | string | When binding stops |
conditions | object | Freeform constraints attached to binding |
description | string | One-line human-readable summary |
Type conventions
| Type | Meaning |
|---|
role-assignment | Actor → Role (scoped) |
work-assignment | Actor → WorkItem (assigned to sprint/scope) |
workitem-gate | WorkItem → Gate (this gate guards this run or task) |
scope-gate | Scope → Gate (this gate applies within this scope) |
time-window | Entity → Artifact/Scope (time or recurrence contract) |
budget-application | Artifact → WorkItem/Scope (cost policy applies here) |
constraint-scope | Constraint → Scope (constraint applies in this scope) |
category-assignment | Entity → Category value |
Process and Schedule are not v2 Binding endpoints. Legacy
process-gate, process-scope, and schedule-scope records should be
migrated to concrete WorkItem, Scope, Artifact, Gate, or time-window
relationships.
Example
---
apiVersion: processkit.projectious.work/v1
kind: Binding
metadata:
id: BIND-20260411_0908-WarmOak-alice-techlead-q2
created: '2026-04-11T09:08:00Z'
spec:
type: role-assignment
subject: ACTOR-20260411_0906-alice
target: ROLE-20260411_0907-ClearOak-tech-lead
scope: SCOPE-20260410_q2-2026
valid_from: '2026-04-01'
valid_until: '2026-06-30'
description: Alice is tech lead on the processkit project for Q2 2026
---
Notes
end_binding closes a binding by setting valid_until to the current
datetime — use this rather than deleting the entity.resolve_bindings_for returns all active bindings for a given subject,
useful for “who is currently assigned to what” queries.
12 - Scope
A bounded container for work — sprint, milestone, quarter, release, or
project. Scopes give WorkItems, Processes, and Constraints a shared
time and goal boundary.
| |
|---|
| ID prefix | SCOPE |
| State machine | scope |
| MCP server | scope-management |
| Skill | scope-management (Layer 2) |
State machine
planned → active → completed
↘ cancelled
completed and cancelled are terminal.
Fields
Required
| Field | Type | Description |
|---|
name | string (1–200) | Human-readable name |
kind | enum | sprint · milestone · quarter · project · release · other |
state | string | Current state |
Optional
| Field | Type | Description |
|---|
starts_at | date | Start date |
ends_at | date | End date |
goals | string[] | Concrete, testable outcomes |
description | string | Longer context |
parent | SCOPE-* | Parent scope (a quarter contains sprints) |
related_decisions | DEC-*[] | Planning or retro decisions for this scope |
Example
---
apiVersion: processkit.projectious.work/v1
kind: Scope
metadata:
id: SCOPE-20260411_0909-BrightElm-sprint-7
created: '2026-04-11T09:09:00Z'
spec:
name: Sprint 7 — WildButter docs push
kind: sprint
state: active
starts_at: '2026-04-11'
ends_at: '2026-04-25'
goals:
- All primitive reference pages published
- Hugo and Docsy local build green
- First public deploy complete
parent: SCOPE-20260410_q2-2026
---
Notes
- Attach WorkItems to a Scope via a
scope field on the WorkItem, or
via a work-assignment Binding when richer tracking is needed. - Scope hierarchy (quarter → sprint) is modelled via the
parent field. transition_scope to active when work begins; to completed when
the scope closes — this timestamps the lifecycle automatically.
13 - Discussion
A structured, multi-turn conversation exploring an open question.
Discussions capture the back-and-forth of deliberation and produce
(or fail to produce) DecisionRecords as outcomes.
| |
|---|
| ID prefix | DISC |
| State machine | discussion |
| MCP server | discussion-management |
| Skill | discussion-management (Layer 4) |
State machine
active → resolved
↘ closed (no outcome)
resolved and closed are terminal.
Fields
Required
| Field | Type | Description |
|---|
question | string | The driving question — one crisp sentence |
state | string | Current state |
Optional
| Field | Type | Description |
|---|
participants | ACTOR-*[] | Actors participating |
related | DISC-*[] | Related discussion IDs |
outcomes | DEC-*[] | DecisionRecord IDs produced by this discussion |
opened_at | datetime | When the discussion started |
closed_at | datetime | When it was marked resolved or closed |
Example
---
apiVersion: processkit.projectious.work/v1
kind: Discussion
metadata:
id: DISC-20260411_0910-ClearWave-primitive-page-format
created: '2026-04-11T09:10:00Z'
spec:
question: What format should per-primitive reference pages follow?
state: resolved
participants: [ACTOR-claude, ACTOR-20260411_0906-owner]
outcomes: [DEC-20260411_0911-SwiftMeadow-primitive-page-format]
opened_at: '2026-04-11T09:10:00Z'
closed_at: '2026-04-11T09:30:00Z'
---
Notes
- Use
add_outcome to attach a DecisionRecord after it has been created
with record_decision. Both tools auto-log. - Discussions are the audit trail behind decisions — if a decision was
reached after deliberation, the Discussion captures the reasoning path.
- Transition to
resolved when a Decision was reached; to closed when
the question was abandoned or became moot. - The Markdown body (below the YAML frontmatter) is the space for the
discussion thread — arguments, evidence, proposals, objections.
14 - Gate
A validation checkpoint in a process. Gates define what must be true
before work can proceed. Evaluation results are LogEntries —
gate.passed, gate.failed, or gate.waived.
| |
|---|
| ID prefix | GATE |
| State machine | none |
| MCP server | gate-management |
| Skill | gate-management (Layer 3) |
Fields
Required
| Field | Type | Description |
|---|
name | string (1–100) | Short kebab-case identifier |
description | string | What this gate checks (one sentence) |
kind | enum | manual · automated · hybrid |
validator | string | Prose description of the check (one–two sentences) |
Optional
| Field | Type | Description |
|---|
validator_command | string | CLI command for automated/hybrid gates |
required_roles | ROLE-*[] | Roles authorised to sign off |
blocking | boolean | true = work cannot proceed without passing (default: true) |
evidence_required | boolean | true = gate.passed log must include artifact reference (default: false) |
Example
---
apiVersion: processkit.projectious.work/v1
kind: Gate
metadata:
id: GATE-20260411_0912-SteadyArch-smoke-tests-green
created: '2026-04-11T09:12:00Z'
spec:
name: smoke-tests-green
description: All MCP server smoke tests must pass before tagging a release.
kind: automated
validator: Run `uv run scripts/smoke-test-servers.py` — exit 0 required.
validator_command: uv run scripts/smoke-test-servers.py
blocking: true
evidence_required: false
---
Notes
- Gates define what to check; the evaluation happens externally (by an
agent, CI, or human). Log the result with
log_event using
event_type: gate.passed, gate.failed, or gate.waived. evaluate_gate runs the validator_command (if set) and logs the
result in one call.- Advisory gates (
blocking: false) surface warnings without halting
the process. - Attach gates to concrete v2 surfaces via
workitem-gate or
scope-gate Bindings. Legacy process-gate Bindings are migration-only.
15 - Migration
A pending, in-progress, or applied transition between two upstream
processkit versions. Migrations are generated by aibox sync and
represent the delta an agent must apply to bring the project’s
context/ up to date.
| |
|---|
| ID prefix | MIG |
| State machine | migration |
| MCP server | migration-management |
| Skill | migration-management (Layer 3) |
State machine
pending → in-progress → applied
↘ rejected
applied and rejected are terminal.
Fields
Required
| Field | Type | Description |
|---|
source | string | Upstream source identifier (processkit, processkit-acme, …) |
from_version | string | Version migrating FROM (semver tag) |
to_version | string | Version migrating TO (semver tag) |
state | string | Current state |
Optional
| Field | Type | Description |
|---|
source_url | string | Git URL of upstream (for re-fetch if needed) |
generated_by | string | What generated this (aibox sync, user, …) |
generated_at | datetime | When the migration document was written |
summary | string | One-line summary for listings |
affected_files | object[] | Files touched — each with path, classification, and optional group |
affected_groups | string[] | Logical groups affected (unit of auto-update) |
plan | string | Project-specific migration plan drafted by agent |
progress_notes | object[] | Append-only notes: {timestamp, note, actor} |
applied_at | datetime | When migration reached applied |
applied_by | string | Actor ID that finalised the migration |
rejected_reason | string | If rejected, why |
source_api_version | string | API version before a v2 conversion |
target_api_version | string | API version after a v2 conversion |
source_processkit_version | string | processkit version before conversion |
target_processkit_version | string | processkit version after conversion |
apply_mode | string | Migration apply mode (one-shot, etc.) |
The migration-management MCP server manages migration state
transitions and provides migrate_context_to_v2(dry_run=true) for the
breaking v2 API conversion path.
affected_files classification values
| Value | Meaning |
|---|
changed-upstream-only | Upstream changed it; project did not — safe to auto-apply |
changed-locally-only | Project customised it; upstream did not — no action needed |
conflict | Both sides changed it — requires manual resolution |
new-upstream | New file added upstream — agent should install it |
removed-upstream | File removed upstream — agent should confirm removal |
Example
---
apiVersion: processkit.projectious.work/v1
kind: Migration
metadata:
id: MIG-20260411_0913-BrightHaven-v0-11-1-to-v0-12-0
created: '2026-04-11T09:13:00Z'
spec:
source: processkit
from_version: v0.11.1
to_version: v0.12.0
state: applied
summary: Add artifact-management skill and MCP server
applied_at: '2026-04-11T06:40:00Z'
applied_by: ACTOR-claude
---
Notes
- Migrations live under
context/migrations/pending/ until applied,
then move to context/migrations/applied/. aibox sync generates migrations automatically by diffing
PROVENANCE.toml across versions.conflict files require human review — the agent drafts options in
the plan field but should not apply them unilaterally.- See Reference → Migration
for the full
migration model.
16 - Schedule
Legacy v1 time-based trigger or recurring cadence. In the
SmoothTiger/SmoothRiver v2 direction, processkit no longer presents
Schedule as a first-class shipped entity surface. Use
Binding(type=time-window) with conditions.recurrence_rule for the
durable contract; an external runner still performs execution.
| |
|---|
| ID prefix | SCHED (legacy v1) |
| State machine | none |
| MCP server | none |
| Skill | schedule-management (legacy authoring guidance) |
v2 replacement
Use the binding-management server’s create_time_window path for
time windows. pk-doctor’s v2_contracts check requires
Binding(type=time-window) records to include
conditions.recurrence_rule.
Fields
Required
| Field | Type | Description |
|---|
name | string | Kebab-case identifier |
description | string | Human-readable summary |
cadence | enum | daily · weekly · monthly · quarterly · adhoc · custom |
Optional
| Field | Type | Description |
|---|
cron | string | Standard cron expression for machine scheduling |
timezone | string | IANA timezone name (e.g. Europe/Berlin) |
triggers | object[] | What this schedule fires (processes, reminders, events) |
active | boolean | false = suspended (default: true) |
last_run | datetime | Advisory — set by whoever runs the schedule |
next_run | datetime | Advisory — set by runner |
Example
---
apiVersion: processkit.projectious.work/v1
kind: Schedule
metadata:
id: SCHED-20260411_0915-CalmGlen-weekly-standup
created: '2026-04-11T09:15:00Z'
spec:
name: weekly-standup
description: Fire the standup-context skill every Monday morning.
cadence: weekly
cron: "0 9 * * 1"
timezone: Europe/London
triggers:
- kind: skill
skill: standup-context
active: true
---
Notes
- Legacy v1 Schedule records are documentation for migration only. In
v2, an external runner reads
Binding(type=time-window) records and
fires the target at the right time. last_run and next_run are advisory fields set by the runner — not
enforced by processkit on legacy records.- Scope a recurring cadence by binding the governed WorkItem, Artifact,
or Scope through
type: time-window; do not create new
schedule-scope Bindings.
17 - Constraint
An explicit rule or limit the project must respect — budget ceiling,
latency SLO, regulatory requirement, team capacity cap. Violations
are LogEntries; constraints themselves do not change when violated.
| |
|---|
| ID prefix | CONST |
| State machine | none |
| MCP server | none |
| Skill | constraint-management (Layer 3) |
Fields
Required
| Field | Type | Description |
|---|
name | string | Kebab-case identifier |
description | string | One-sentence statement of the constraint |
kind | enum | budget · slo · regulatory · capacity · dependency · policy · other |
severity | enum | hard · soft · advisory |
Optional
| Field | Type | Description |
|---|
measurement | string | How to determine if the constraint is met |
target | string | Threshold or boundary value |
source | string | Where the constraint comes from (contract, regulation, decision) |
active | boolean | false = no longer in effect (default: true) |
related_decisions | DEC-*[] | Decisions that established or relaxed the constraint |
Severity levels
| Level | Meaning |
|---|
hard | Cannot violate — work stops until resolved |
soft | Flagged and tracked; can be overridden with justification |
advisory | Informational — violation noted but no process impact |
Example
---
apiVersion: processkit.projectious.work/v1
kind: Constraint
metadata:
id: CONST-20260411_0916-SteadyMoss-api-latency-slo
created: '2026-04-11T09:16:00Z'
spec:
name: api-latency-slo
description: MCP tool round-trip p99 latency must stay below 200ms.
kind: slo
severity: hard
target: "< 200ms p99"
measurement: |
Measured via the observability pipeline from tool-call dispatch to
server response. Alert fires if exceeded for 5 minutes.
source: Customer SLA — contract clause 4.2
related_decisions:
- DEC-20260409_latency-slo-accepted
---
Notes
- Constraint violations are logged via
log_event with
event_type: constraint.violated — the Constraint entity itself is
not modified. - A
hard constraint violation should surface as a blocked WorkItem or
an urgent Discussion. - Bind a Constraint to a Scope via a
constraint-scope Binding to make
it scope-specific rather than project-wide. - Set
active: false when a constraint is no longer in effect (SLA
renegotiated, regulatory exemption granted).
18 - Category
A classification axis with a closed set of allowed values — priority
levels, bug severity tiers, product areas. Use Category when the valid
values are defined and enforced; use freeform labels for open-ended
tagging.
| |
|---|
| ID prefix | CAT |
| State machine | none |
| MCP server | none |
| Skill | category-management (Layer 2) |
Fields
Required
| Field | Type | Description |
|---|
name | string (1–100) | Category name (kebab-case) |
description | string | What this axis classifies |
axis | string | Label key used on entities (e.g. priority, severity) |
values | object[] | Allowed values — each with name (required), description, deprecated, children (optional) |
Optional
| Field | Type | Description |
|---|
applies_to | string[] | Primitive kinds this applies to; empty = applies anywhere |
default | string | Default value when unspecified |
multi | boolean | true = entity can carry multiple values (default: false) |
Example
---
apiVersion: processkit.projectious.work/v1
kind: Category
metadata:
id: CAT-20260411_0917-BrightFern-workitem-priority
created: '2026-04-11T09:17:00Z'
spec:
name: workitem-priority
description: Business priority for work items.
axis: priority
applies_to: [WorkItem]
default: medium
values:
- name: critical
description: Blocks a release or customer. Drop everything.
- name: high
description: Important this sprint. Do before medium items.
- name: medium
description: Normal priority. Default.
- name: low
description: Nice to have. Defer if sprint is full.
---
Notes
- Categories complement the
type and priority fields already on
WorkItem — use Category when you need a custom classification axis
beyond the built-in enums. deprecated: true on a value signals it should no longer be used on
new entities, but keeps old entities valid.- Hierarchical value sets use the
children field to model tree-shaped
taxonomies (e.g. product area → sub-area).
19 - CrossReference
A lightweight, frontmatter-embedded relationship between two entities.
CrossReference is not a file — it is a convention for fields in the
spec block of any entity.
| |
|---|
| ID prefix | — (not a file entity) |
| State machine | — |
| MCP server | index-management (for querying) |
| Skill | cross-reference-management (Layer 2) |
When to use a CrossReference vs a Binding
Use a CrossReference when the relationship is:
- Simple — no scope, no time bounds, no attributes of its own
- Directional — one entity points at another
Use a Binding when the relationship has scope, time, or its own
attributes.
| Situation | Use |
|---|
| “WorkItem A blocks WorkItem B” | CrossReference (blocks field) |
| “Decision D governs WorkItem W” | CrossReference (related_decisions) |
| “Alice is tech lead for Q2” | Binding (scoped + time-bounded) |
Conventional field names
processkit standardises these field names across entity kinds:
| Field | Pattern | Meaning |
|---|
parent | BACK-* / SCOPE-* | Hierarchy parent |
children | BACK-*[] | Hierarchy children |
blocks | BACK-*[] | This item blocks these items |
blocked_by | BACK-*[] | These items block this one |
supersedes | DEC-* | This decision replaces an older one |
superseded_by | DEC-* | This decision was replaced by a newer one |
related_decisions | DEC-*[] | Decisions that govern or motivated this item |
related_workitems | BACK-*[] | WorkItems that motivated or implement a decision |
outcomes | DEC-*[] | DecisionRecords produced by a Discussion |
produces_to | object | For Note promotion: {kind, id} |
Example
# WorkItem with CrossReferences in spec
spec:
title: Implement FTS5 search
state: in-progress
parent: BACK-epic-search-improvements
blocks:
- BACK-search-ux-polish
blocked_by:
- BACK-index-schema-locked
related_decisions:
- DEC-sqlite-for-index
Notes
- CrossReferences are queryable via
query_entities and search_entities
in the index-management MCP server — the SQLite index tracks these
relationships. - There is no separate CrossReference entity file. The relationship lives
in the referring entity’s frontmatter.
- When you find yourself wanting attributes on a cross-reference (e.g. “this
relationship is valid from April to June”), that is the signal to promote
it to a Binding.
20 - Context
A structured narrative document for long-lived ambient knowledge —
owner identity, working style, team relationships, grooming reports,
situational briefings. The value lives in the Markdown body.
| |
|---|
| ID prefix | CTX (or custom, e.g. OWNER) |
| State machine | none |
| MCP server | none |
| Skill | context-grooming (Layer 4) |
Fields
Required
| Field | Type | Description |
|---|
description | string | One-sentence summary of what this document holds |
Optional
| Field | Type | Description |
|---|
purpose | string | Why the document exists — when an agent should read it |
scope | string | Where the context applies (project, owner, team, sprint) |
tags | string[] | Freeform tags for retrieval |
sensitive | boolean | true = body contains sensitive information (default: false) |
Example
---
apiVersion: processkit.projectious.work/v1
kind: Context
metadata:
id: OWNER-identity
created: '2026-04-09T00:00:00Z'
spec:
description: Owner identity, working style, and preferences for AI agents.
purpose: |
Read at session start to calibrate communication style and technical
depth. Load before any substantive work begins.
scope: owner
sensitive: false
---
## Identity
Name: ...
Role: ...
Timezone: ...
## Working style
...
Notes
- Context entities use the Markdown body (below the YAML frontmatter)
for their primary content. The
spec block is metadata only. - Custom ID prefixes (e.g.
OWNER-identity, CTX-team-norms) are
idiomatic — the CTX- prefix is the default but not required. - Sensitive context (
sensitive: true) should live under
context/**/private/ to be excluded from git tracking and the
docs-site build. - Context grooming (
context-grooming skill) prunes stale Context
documents periodically — documents that have not been read or updated
for a long time are candidates for archiving.
21 - Process
Legacy v1 declarative workflow definition. In the
SmoothTiger/SmoothRiver v2 direction, processkit no longer presents
Process as a first-class shipped entity surface. Use a
process-instance WorkItem for a concrete run and an Artifact for the
reusable process definition.
| |
|---|
| ID prefix | PROC (legacy v1) |
| State machine | none |
| MCP server | none |
| Skill | process-management (legacy authoring guidance) |
v2 replacement
Use:
WorkItem with spec.type: process-instance for a workflow run.Artifact with spec.kind describing the reusable process
definition.Gate and Binding records for policies that apply to the run.
pk-doctor’s v2_contracts check flags v2 process-instance WorkItems
that do not point at a process definition.
Fields
Required
| Field | Type | Description |
|---|
name | string | Kebab-case identifier |
description | string | One-sentence summary |
steps | object[] | Ordered list of steps (see below) |
definition_of_done | string | Acceptance criterion for the whole process |
Optional
| Field | Type | Description |
|---|
triggers | string[] | Event types that kick off the process |
roles | string[] | Role names involved |
parallel | boolean | true = steps run in parallel (default: false) |
retryable | boolean | true = process can re-run on failure (default: true) |
Step fields
| Field | Type | Description |
|---|
name | string | Required — step identifier |
role | string | Role responsible for this step |
description | string | What the step does |
uses_skill | string | Skill ID the agent invokes |
inputs | string[] | Inputs expected at this step |
outputs | string[] | Outputs produced |
gates | GATE-*[] | Gates that must pass before proceeding |
on_failure | enum | halt · retry · skip · escalate |
Example
---
apiVersion: processkit.projectious.work/v1
kind: Process
metadata:
id: PROC-20260411_0918-SureElm-code-review
created: '2026-04-11T09:18:00Z'
spec:
name: code-review
description: Review a pull request before merge.
triggers: [pr.opened, pr.review-requested]
roles: [developer, reviewer]
steps:
- name: author-self-check
role: developer
uses_skill: code-review
- name: peer-review
role: reviewer
uses_skill: code-review
gates: [GATE-no-blocking-comments]
- name: merge
role: developer
gates: [GATE-ci-passed, GATE-code-review-passed]
definition_of_done: PR merged with approval and CI green.
---
Notes
- processkit does not execute processes. The agent (or human) walks
the steps and logs progress via
log_event. - Gate references in steps are pointers to Gate entities — create the
Gate first, then reference its ID.
- Formal process definitions (
bug-fix, code-review,
feature-development, release) are planned as shipped YAML files
in a future release.
22 - StateMachine
Legacy v1 state/transition graph entity. In the SmoothTiger/SmoothRiver
v2 direction, processkit no longer presents StateMachine as a
first-class shipped entity surface. State machines still exist as
validation machinery used by MCP servers, but users should not model
new workflow records as StateMachine entities.
| |
|---|
| ID prefix | SM (legacy v1) |
| State machine | none (meta-primitive) |
| MCP server | none |
| Skill | state-machine-management (legacy authoring guidance) |
v2 replacement
Use the owning MCP server for lifecycle transitions. It loads the
appropriate implementation contract and returns structured errors for
invalid transitions. Project workflows should be expressed with
WorkItems, Artifacts, Gates, and Bindings rather than new
StateMachine records.
Fields
Required
| Field | Type | Description |
|---|
description | string | What this state machine governs |
initial | string | Starting state for new entities |
states | object | Map of state name → {description, transitions[]} |
Optional
| Field | Type | Description |
|---|
terminal | string[] | States with no outgoing transitions |
Transition fields (within each state)
| Field | Type | Description |
|---|
to | string | Target state |
guard | string | Prose description of when this transition is allowed |
on_enter | string | Side effect description when entering target state |
required_role | string | Role required to make this transition |
Default state machines shipped by processkit
| Primitive | States |
|---|
| WorkItem | backlog → in-progress → review → done (+ blocked, cancelled) |
| DecisionRecord | proposed → accepted / rejected → superseded |
| Migration | pending → in-progress → applied / rejected |
| Scope | planned → active → completed / cancelled |
| Discussion | active → resolved / closed |
| Note | fleeting → insight / promoted / archived |
Example — custom state machine
---
apiVersion: processkit.projectious.work/v1
kind: StateMachine
metadata:
id: SM-20260411_0919-ClearRidge-rfc-lifecycle
created: '2026-04-11T09:19:00Z'
spec:
description: RFC lifecycle for architecture proposals.
initial: draft
terminal: [accepted, withdrawn]
states:
draft:
description: Being written — not ready for review.
transitions:
- to: in-review
guard: Author marks RFC ready.
in-review:
description: Open for comments from stakeholders.
transitions:
- to: accepted
required_role: tech-lead
- to: draft
guard: Major revision needed.
- to: withdrawn
guard: Author withdraws.
accepted:
description: Accepted — implementation may proceed.
withdrawn:
description: RFC withdrawn by author.
---
Notes
- Legacy state machine definitions may exist in
context/state-machines/
during v1 migration, but they are not first-class v2 entities. - MCP servers load the state machine for a given
kind and enforce
valid transitions — invalid transition attempts return a structured error. - For v2, change lifecycle behavior in the owning MCP server or a
reviewed implementation contract, then migrate affected records
explicitly. Do not create new StateMachine records.