Work model
Authoritative reference for the work-management model and its manifest. Consult this
before answering a question about the model, before hand-editing any work file, and
before adding a project fact anywhere other than the manifest.
Resolve configuration first
Read references/config-resolution.md and follow it. Project facts come from
<paths.work>/project.yml and nowhere else. Report a missing manifest rather than
guessing paths.
That document also defines the two roots — the VCS root where .git lives, and the
project root where this project's world begins — and the path-resolution and VCS-scoping
rules that follow from telling them apart. Read that section before resolving any path or
running any git command; on a repository holding one project the two roots coincide and
nothing changes, but the assumption that they always coincide is wrong on a monorepo.
The supported schema is model_version: 5. The compatibility gate in
references/config-resolution.md is checked before any other field, by every command. A stale
manifest is a stop with a pointer to /work-init --upgrade, never an auto-migration.
references/schema-history.md holds every earlier era, the keys that identify it, and its
transition forward. Consult it when asked what changed between versions, or when a manifest does
not match its own declaration — model_version: 2 covers four distinct shapes, so those files
must be identified by their keys rather than their declaration.
The model
Read references/model.md for the full model: the four files, the request and work item
field schemas, all three status vocabularies, spike rules, the active release lifecycle,
and the pruning rules.
Answer questions about statuses, fields, and lifecycle from that document rather than
from general project-management knowledge. The vocabularies are deliberately specific —
blocked versus deferred, and abandoned versus cancelled, both carry precise
meanings that a plausible-sounding paraphrase will get wrong.
The dividing line
When something looks like it needs recording, decide where it belongs:
| The fact is... |
It belongs in |
| true of this project only (paths, boundary, stack, agents, release mechanics, test policy) |
the manifest, project.yml |
| true of the model on every project (statuses, field schemas, lifecycle) |
references/model.md — do not edit per project |
| a change to the manifest schema itself |
references/schema-history.md, plus a model_version bump |
| a piece of work someone wants done |
requests.md, via the work-capture skill |
| refined, actionable, ready for an implementer |
backlog.yml, via /work-plan |
| the current delivery scope |
active-release.md, via /work-plan |
| a durable record of something shipped |
the changelog, git history, tags, tests, code |
If a command or an agent file would have to change to record a project fact, that is the
signal the fact belongs in the manifest instead.
Validating conformance
When asked to check the work files, or before a planning session on a project last
touched by hand, verify:
- Structure —
requests.md has the legend and the four H2 sections in order; each
request is an H3 with Key: value lines, no bullets or nested headings.
- Vocabulary — every
Type: appears in <taxonomy.request_types>; every work item
type appears in <taxonomy.work_types>; every Priority: in
<taxonomy.priorities>; every status is valid for its plane.
- Field names — requests use
Work items: (not Derived work items:).
- Paired fields —
blocked carries Blocked on: / blocked_on; deferred does
not; done and partially-done carry Done in: / done_in.
- Provenance — every work item sets exactly one of
source_request /
source_release, the other being null. Both set is a contradiction and a hard finding.
source_release holds a release version, never a request ID. Neither set is legacy
rather than invalid — source_release is newer than most backlogs — so report it as a
backfill to do on next touch, not as a failure.
- Review pressure —
Reviewed: / reviewed is a single integer with one accompanying
line, not a list. A request accumulating a dated paragraph per planning session has drifted
from the model: the count is stored, the history is the commit history, and only a material
change is appended to Notes:.
- Completion values — every entry in
Done in: / done_in is a release version or
SPIKE: <ITEM-ID>. Free text such as a bare date is drift: a spike bumps no version, so
it records the marker instead.
- Referential integrity — every ID in
Work items: exists in backlog.yml; every
non-null source_request exists in requests.md; every name in suggested_agents exists in
<agents> and not in <inactive_agents>; every dependencies entry resolves.
- Ownership — compute effective ownership as
owns minus excludes, expanding globs and
treating a parent path as covering its children. No path may then belong to two agents.
This is a hard failure, not a warning: overlapping ownership generates two contradictory
scope tables that each tell the other agent to keep out, and the deadlock is hard to trace
back to its cause. A carve-out must be declared on both sides — excluded by one agent,
owned by another — never left to a most-specific-path-wins convention, because nothing
downstream enforces one. A path excluded by one agent and owned by none is a gap. Confirm
every owns, excludes, and reads path resolves against the tree; a typo produces an
agent that owns nothing, or hands a path back to the wrong owner.
- Boundary coherence — resolve every path field against the project root per
references/config-resolution.md, then confirm each one exists. A path that resolved
correctly under the old repository-root rule and is now missing is the signature of a
manifest that kept an apps/toolA/ prefix it no longer needs; say so rather than reporting
five unrelated missing files. Where <scope.root> is set, confirm it names a directory that
exists and sits inside the repository, and that every leading-slash path in any agent's
owns also appears in <scope.writes_outside> — an owned path outside the boundary that
nothing has authorised is a write the boundary will refuse at the moment it is attempted.
Confirm each <scope.writes_outside> entry resolves and sits outside <scope.root>; an
entry that is already inside the boundary is redundant and reads as a permission that was
needed once.
- Tag coherence — where
<scope.root> is set and <version.tag_template> is null, flag
it: the project is claiming the repository's global v1.2.3 and will collide with the next
member to reach that number. Where the template is set and
<release.pipeline.definition> names a file with trigger: tag-push, read that file and
confirm its tag filter actually matches what the template renders. A workflow watching v*
does not fire on toolA/v1.2.3, and that combination ships a release that builds nothing.
- Stage coherence — check
<vcs.stages> against the validity table in
references/config-resolution.md, and report every failure at once rather than the first.
The rules that catch real misconfigurations: commit: human with any later stage set to
agent (nothing downstream works without commits); merge and pull_request both active;
either active without branch; pull_request without push; tag: none with
<version.file> null, which leaves the version nowhere to live. Also flag interleaved
ownership — an agent stage between two human ones — not as an error but as a session
that will stall mid-flight, which the human should know before a release rather than during
one.
- Version-control coherence — if
<vcs.system> is none, then
<version.file> must be set, because a tag is not available to hold the version — and
<version.tag_template> is inert, since there are no tags to name;
<paths.changelog> should be set, because it is the only remaining narrative record; and
every stage in <vcs.stages> must be none, since there is no repository to act on. If
<vcs.system> is git, confirm a repository actually exists — a manifest claiming git on
a directory with no repository will make every release hand off to steps the user cannot
perform. Test with git rev-parse --show-toplevel, not by looking for a .git directory
beside the manifest: on a monorepo member .git is legitimately several levels above, and
a bare directory check reports no repository on a project that has one.
- Hygiene — flag if
done items older than the most recent few releases are still
present, which means pruning has lapsed. Suggest /work-prune.
- Schema —
model_version matches the supported version, and the file's shape agrees with
its own declaration. A mismatch either way is a stop; the fix is /work-init --upgrade, which
migrates the manifest and regenerates the agents in one pass.
Report findings as a list with a recommended fix for each. Do not silently repair
vocabulary drift: if requests.md uses a type the manifest does not list, the manifest
may be wrong rather than the data. Ask which is authoritative.
Related commands
/work-init sets a project up, and /work-init --upgrade brings an older manifest to the
current schema before regenerating agents — it runs the /work-migrate procedure itself, which
also stays callable on its own when you want that edit reviewed separately. /work-ingest
backfills intake from a PRD or other existing material. /work-plan
refines and proposes scope. /work-release delivers. /work-spike runs investigations.
/work-crunch runs those three on a loop under a permissions contract agreed up front.
/work-review-deferred re-triages parked items. /work-prune trims completed history. The
work-capture skill handles quick intake.
On a project adopting the model with work already recorded elsewhere, the order is
/work-init then /work-ingest then /work-plan. Ingesting before the manifest exists has no
vocabulary to validate against; refining before ingesting means refining an empty file.
1---2name: work-model3description: Explains and enforces the project-agnostic Request -> Work item -> Active release -> Done work-management model, including the manifest schema at docs/work/project.yml, the exact file formats for requests.md / backlog.yml / active-release.md, all valid statuses, and the configuration-resolution protocol every command follows. Use when someone asks how the work management model works, what a status means, whether something is blocked or deferred, what fields a request or work item takes, how to configure project.yml, what belongs in the manifest versus a command, or when validating that requests.md and backlog.yml conform to the model. Also use before hand-editing any of the work files, so the edit matches the required structure rather than drifting from it.4---56# Work model78Authoritative reference for the work-management model and its manifest. Consult this9before answering a question about the model, before hand-editing any work file, and10before adding a project fact anywhere other than the manifest.1112## Resolve configuration first1314Read `references/config-resolution.md` and follow it. Project facts come from15`<paths.work>/project.yml` and nowhere else. Report a missing manifest rather than16guessing paths.1718That document also defines **the two roots** — the VCS root where `.git` lives, and the19project root where this project's world begins — and the path-resolution and VCS-scoping20rules that follow from telling them apart. Read that section before resolving any path or21running any git command; on a repository holding one project the two roots coincide and22nothing changes, but the assumption that they always coincide is wrong on a monorepo.2324**The supported schema is `model_version: 5`.** The compatibility gate in25`references/config-resolution.md` is checked before any other field, by every command. A stale26manifest is a stop with a pointer to `/work-init --upgrade`, never an auto-migration.2728`references/schema-history.md` holds every earlier era, the keys that identify it, and its29transition forward. Consult it when asked what changed between versions, or when a manifest does30not match its own declaration — `model_version: 2` covers four distinct shapes, so those files31must be identified by their keys rather than their declaration.3233## The model3435Read `references/model.md` for the full model: the four files, the request and work item36field schemas, all three status vocabularies, spike rules, the active release lifecycle,37and the pruning rules.3839Answer questions about statuses, fields, and lifecycle from that document rather than40from general project-management knowledge. The vocabularies are deliberately specific —41`blocked` versus `deferred`, and `abandoned` versus `cancelled`, both carry precise42meanings that a plausible-sounding paraphrase will get wrong.4344## The dividing line4546When something looks like it needs recording, decide where it belongs:4748| The fact is... | It belongs in |49|---|---|50| true of this project only (paths, boundary, stack, agents, release mechanics, test policy) | the manifest, `project.yml` |51| true of the model on every project (statuses, field schemas, lifecycle) | `references/model.md` — do not edit per project |52| a change to the manifest schema itself | `references/schema-history.md`, plus a `model_version` bump |53| a piece of work someone wants done | `requests.md`, via the `work-capture` skill |54| refined, actionable, ready for an implementer | `backlog.yml`, via `/work-plan` |55| the current delivery scope | `active-release.md`, via `/work-plan` |56| a durable record of something shipped | the changelog, git history, tags, tests, code |5758If a command or an agent file would have to change to record a project fact, that is the59signal the fact belongs in the manifest instead.6061## Validating conformance6263When asked to check the work files, or before a planning session on a project last64touched by hand, verify:6566- **Structure** — `requests.md` has the legend and the four H2 sections in order; each67 request is an H3 with `Key: value` lines, no bullets or nested headings.68- **Vocabulary** — every `Type:` appears in `<taxonomy.request_types>`; every work item69 `type` appears in `<taxonomy.work_types>`; every `Priority:` in70 `<taxonomy.priorities>`; every status is valid for its plane.71- **Field names** — requests use `Work items:` (not `Derived work items:`).72- **Paired fields** — `blocked` carries `Blocked on:` / `blocked_on`; `deferred` does73 not; `done` and `partially-done` carry `Done in:` / `done_in`.74- **Provenance** — every work item sets **exactly one** of `source_request` /75 `source_release`, the other being null. Both set is a contradiction and a hard finding.76 `source_release` holds a release version, never a request ID. Neither set is legacy77 rather than invalid — `source_release` is newer than most backlogs — so report it as a78 backfill to do on next touch, not as a failure.79- **Review pressure** — `Reviewed:` / `reviewed` is a single integer with one accompanying80 line, not a list. A request accumulating a dated paragraph per planning session has drifted81 from the model: the count is stored, the history is the commit history, and only a material82 change is appended to `Notes:`.83- **Completion values** — every entry in `Done in:` / `done_in` is a release version or84 `SPIKE: <ITEM-ID>`. Free text such as a bare date is drift: a spike bumps no version, so85 it records the marker instead.86- **Referential integrity** — every ID in `Work items:` exists in `backlog.yml`; every87 non-null `source_request` exists in `requests.md`; every name in `suggested_agents` exists in88 `<agents>` and not in `<inactive_agents>`; every `dependencies` entry resolves.89- **Ownership** — compute effective ownership as `owns` minus `excludes`, expanding globs and90 treating a parent path as covering its children. No path may then belong to two agents.91 This is a hard failure, not a warning: overlapping ownership generates two contradictory92 scope tables that each tell the other agent to keep out, and the deadlock is hard to trace93 back to its cause. A carve-out must be declared on both sides — excluded by one agent,94 owned by another — never left to a most-specific-path-wins convention, because nothing95 downstream enforces one. A path excluded by one agent and owned by none is a gap. Confirm96 every `owns`, `excludes`, and `reads` path resolves against the tree; a typo produces an97 agent that owns nothing, or hands a path back to the wrong owner.98- **Boundary coherence** — resolve every path field against the project root per99 `references/config-resolution.md`, then confirm each one exists. A path that resolved100 correctly under the old repository-root rule and is now missing is the signature of a101 manifest that kept an `apps/toolA/` prefix it no longer needs; say so rather than reporting102 five unrelated missing files. Where `<scope.root>` is set, confirm it names a directory that103 exists and sits inside the repository, and that every leading-slash path in any agent's104 `owns` also appears in `<scope.writes_outside>` — an owned path outside the boundary that105 nothing has authorised is a write the boundary will refuse at the moment it is attempted.106 Confirm each `<scope.writes_outside>` entry resolves and sits outside `<scope.root>`; an107 entry that is already inside the boundary is redundant and reads as a permission that was108 needed once.109- **Tag coherence** — where `<scope.root>` is set and `<version.tag_template>` is null, flag110 it: the project is claiming the repository's global `v1.2.3` and will collide with the next111 member to reach that number. Where the template is set and112 `<release.pipeline.definition>` names a file with `trigger: tag-push`, read that file and113 confirm its tag filter actually matches what the template renders. A workflow watching `v*`114 does not fire on `toolA/v1.2.3`, and that combination ships a release that builds nothing.115- **Stage coherence** — check `<vcs.stages>` against the validity table in116 `references/config-resolution.md`, and report every failure at once rather than the first.117 The rules that catch real misconfigurations: `commit: human` with any later stage set to118 `agent` (nothing downstream works without commits); `merge` and `pull_request` both active;119 either active without `branch`; `pull_request` without `push`; `tag: none` with120 `<version.file>` null, which leaves the version nowhere to live. Also flag interleaved121 ownership — an `agent` stage between two `human` ones — not as an error but as a session122 that will stall mid-flight, which the human should know before a release rather than during123 one.124- **Version-control coherence** — if `<vcs.system>` is `none`, then125 `<version.file>` must be set, because a tag is not available to hold the version — and126 `<version.tag_template>` is inert, since there are no tags to name;127 `<paths.changelog>` should be set, because it is the only remaining narrative record; and128 every stage in `<vcs.stages>` must be `none`, since there is no repository to act on. If129 `<vcs.system>` is `git`, confirm a repository actually exists — a manifest claiming git on130 a directory with no repository will make every release hand off to steps the user cannot131 perform. Test with `git rev-parse --show-toplevel`, not by looking for a `.git` directory132 beside the manifest: on a monorepo member `.git` is legitimately several levels above, and133 a bare directory check reports no repository on a project that has one.134- **Hygiene** — flag if `done` items older than the most recent few releases are still135 present, which means pruning has lapsed. Suggest `/work-prune`.136- **Schema** — `model_version` matches the supported version, *and* the file's shape agrees with137 its own declaration. A mismatch either way is a stop; the fix is `/work-init --upgrade`, which138 migrates the manifest and regenerates the agents in one pass.139140Report findings as a list with a recommended fix for each. Do not silently repair141vocabulary drift: if `requests.md` uses a type the manifest does not list, the manifest142may be wrong rather than the data. Ask which is authoritative.143144## Related commands145146`/work-init` sets a project up, and `/work-init --upgrade` brings an older manifest to the147current schema before regenerating agents — it runs the `/work-migrate` procedure itself, which148also stays callable on its own when you want that edit reviewed separately. `/work-ingest`149backfills intake from a PRD or other existing material. `/work-plan`150refines and proposes scope. `/work-release` delivers. `/work-spike` runs investigations.151`/work-crunch` runs those three on a loop under a permissions contract agreed up front.152`/work-review-deferred` re-triages parked items. `/work-prune` trims completed history. The153`work-capture` skill handles quick intake.154155On a project adopting the model with work already recorded elsewhere, the order is156`/work-init` then `/work-ingest` then `/work-plan`. Ingesting before the manifest exists has no157vocabulary to validate against; refining before ingesting means refining an empty file.