# Workspace artifact schema

Feature truth: `.devrites/work/<slug>/`, discovered by `state.md`; remnants/archives
inactive. Spec's `README.md` is optional. Use canonical filenames. Both released
cursors read; no `schema` requires `devrites-engine migrate <slug>`.
`$rite-upgrade`: audit only, no path/alias/format migration.

## Contents

- [Slug identity](#slug-identity)
- [Required by phase](#required-by-phase)
- [What each file owns](#what-each-file-owns)
- [Candidate manifest and bindings](#candidate-manifest-and-bindings)
- [Anchored notes](#anchored-notes)
- [Native readiness ownership](#native-readiness-ownership)
- [Canonical slice grammar](#canonical-slice-grammar)
- [Read next by phase](#read-next-by-phase)
- [Do not duplicate](#do-not-duplicate)
- [ID contract](#id-contract)

## Slug identity

New slugs derive from the objective: lowercase ASCII kebab-case matching
`[a-z0-9]+(?:-[a-z0-9]+)*`, at most 64 characters. Shorten at word boundaries.
After the final shortening or suffix step, trim boundary hyphens; reject empty results.

Before creation, compare a matching workspace's `brief.md` objective: reuse only the
same feature. Otherwise append the smallest unused suffix (`-2`, `-3`, ...), keeping
the trimmed base within 64 characters. Never overwrite a workspace by slug alone;
accept safe legacy basenames. Ordinary phases never rename them.

## Required by phase

| Phase | Required artifacts |
| --- | --- |
| frame | `state.md` |
| spec | `brief.md`, `spec.md`, `state.md`, `decisions.md`, `assumptions.md`, `questions.md` |
| clarify | spec artifacts plus `decision-coverage.md` |
| temper | clarified spec artifacts plus `strategy.md` when temper runs |
| define/plan | clarified spec artifacts plus `architecture.md`, `plan.md`, `tasks.md`, `traceability.md` |
| vet/build/converge | plan artifacts plus `eng-review.md`, `test-plan.md`, `gates.md`; Build creates and maintains `touched-files.md` after its first green slice |
| prove/polish/review | vetted plan artifacts plus `evidence.md`, `touched-files.md` |
| seal/ship/done | proof artifacts plus `review.md`, `seal.md`; Ship writes `ship.md` |
| conditional | `checklists/<domain>.md` per spec-covered domain (Spec writes; Define gates on it); `flows.md` when diagrams clarify; `visual/` HTML+`.outline.md` companions when a richer reviewable visual earns it (optional; never readiness-required); `design-brief.md` and `browser-evidence.md` for UI; `devex.md` when a developer-facing surface is in scope; `drift.md` for drift; `polish-report.md` for polish; `handoff.md` only when requested; `references.md` + `references/` when references exist; `investigation-map.md` for pressure-test; `dogfood.md` for dogfood; `windows.md` when the diff introduces deferral markers (waiver ledger for `check windows`); `packets/` for by-reference dispatch packets and admitted accounts (≤ 64 KiB each; older closed rounds may be deleted; never transcripts); `history/` for verbatim relocated checkpoint narrative (append-only, never a read-next); `readiness-inputs.json` as the advisory per-input drift baseline written by `check drift --record` after Vet's binding (never a gate input; regenerated, not hand-edited); `diff-scope-baseline.json` as the pre-dispatch dirty-path fingerprint snapshot written by `check diff-scope --snapshot` and read by `--baseline` (engine-written, never hand-edited); `tree-baseline.json` as the root-edit tripwire baseline `dispatch` writes and `dispatch open`/`next`/`check candidate` read (engine-written, never hand-edited); `notes.md` for anchored notes bound to verbatim code quotes (engine-regraded; non-exact anchors block seal) |

## What each file owns

| File | Job | Budget |
| --- | --- | --- |
| `README.md` | map: phase/status/next action, artifacts/read-next, blocking gates, last update | 120 lines |
| `brief.md` | user request, objective, non-goals, success definition | 80 lines |
| `spec.md` | product WHAT/WHY, requirements, acceptance criteria, edge cases, measurable success, scope boundaries | 260 lines |
| `decision-coverage.md` | topology-first coverage matrix, assumption audit, residual uncertainty, and typed clarity verdict | 200 lines |
| `strategy.md` | temper verdict, scope mode/deltas, pre-mortem risks, deferred ambition | 180 lines |
| `architecture.md` | owning layer, integration points, data/API/events, dependencies, risks, affected boundaries | 180 lines |
| `flows.md` | useful Mermaid sequence/state/data/lifecycle diagrams with why-it-matters text and related IDs | 160 lines |
| `visual/<name>.html` | optional portable human-viewable visualization; pair with sibling `.outline.md`; self-contained preferred | 400 lines (advisory; not gate-checked) |
| `visual/<name>.outline.md` | required machine dual-read companion for the sibling HTML; outline wins on conflict; never a candidate path | 200 lines (advisory; not gate-checked) |
| `visual/README.md` | optional index of visuals in the workspace | 80 lines (advisory; not gate-checked) |
| `decisions.md` | ADR-style `DEC-###` log: status, context, options, decision, consequences, related IDs; optional `Files:`/`Tags:` fields make entries queryable by path or theme; Build's `## Carry-forward constraints` lines (rule, source slice, evidence, `Files:`) | 200 lines |
| `roadmap.md` | optional sequence authority (below); headerless maps stay legacy | — |
| `assumptions.md` | assumptions with confidence, owner, validation status | 160 lines |
| `questions.md` | current `q-YYYY-MM-DD-NNN` (or released `Q-###`) open/resolved questions, gate, answer, impact | 180 lines |
| `plan.md` | technical approach, slice strategy, canonical shared-contract proof, validation strategy, rollback | 220 lines |
| `tasks.md` | `SLICE-###` vertical slices with AC IDs, likely files, tests/proof, mode/gate, dependencies, done condition | 280 lines |
| `traceability.md` | matrix: AC/REQ ID, slice IDs, test/proof, evidence ID, touched files, status | 220 lines |
| `eng-review.md` | vetted scope/architecture/quality/performance, failure modes, preflight, stable-input binding, `## Deferred findings` (late rows: severity · site · role · kind · round) for Review | 240 lines |
| `test-plan.md` | executable proof commands, preflight/provenance contract, acceptance and interaction coverage | 260 lines |
| `gates.md` | machine-checked acceptance ledger: one gate per required outcome — runnable `CHECK`/`EXPECT`/`CWD` or manual `EVIDENCE`; engine-bound evidence, `ABANDON:` handoffs | 200 lines |
| `state.md` | compact cursor table/key-values; no narrative log | 120 lines |
| `evidence.md` | `EVID-###` command/action, result, timestamp if available, related AC/slice IDs, limitation; behavioral rows add selector, runner counts (collected/ran/passed/failed/skipped), and `attempt n; first: <result>`, with output and exit from one execution | 280 lines |
| `browser-evidence.md` | UI route/viewports/screenshots/console/network/interactions and Visual Verdict | 220 lines |
| `drift.md` | `DRIFT-###` spec/plan drift and resolution | 160 lines |
| `touched-files.md` | sole candidate manifest plus a concern-ordered `## Review trail` of `path:line` stops for human review and Build's deferred late findings (severity · site · role · round) that `$rite-review` must close | 160 lines |
| `design-brief.md` | UI design direction, states, interaction model | 160 lines |
| `handoff.md` | resume objective/last slice/next action/blockers/read-next; sections hold content or `Nothing yet`; unevidenced recollections: `Not tried yet`, never results | 120 lines |
| `polish-report.md` | polish axis deltas, re-verification lines, residual subjective preferences | 200 lines |
| `ship.md` | ship preflight, disclosed Git plan, commit/push/tag/PR record | 120 lines |
| `review.md` | reconciled Review verdict: `## Spec` and `## Code review` accounts, triggered frontend/security/performance accounts or `Not-applicable` lines, deferred-finding labels/actions, drift | 240 lines |
| `seal.md` | seal preflight, exact reviewer roster accounts, GO/NO-GO verdict and disclosures | 200 lines |
| `ai-spec.md` | model/RAG/agent/eval/LLM-output scope for AI surfaces | 160 lines |
| `windows.md` | deferral/bar-lowering waiver ledger: one `- path | marker | reason` row per introduced marker; `check windows` fails on unwaived hits | 120 lines |
| `notes.md` | `NOTE-###` anchored notes — rationale/warnings bound to a verbatim quote in one repository file; `note check` regrades anchors and drift blocks seal | 160 lines |

For visual pairs load only matching [playbooks](visual-playbooks/index.md); use
the [required outline headings](visual-playbooks/outline-template.md).

Canonical `roadmap.md`: either header claims explicit authority; require both
`Sequence root: <actual-anchor-slug>` and `Decision: DEC-NNN`, identifying one
`## DEC-NNN` in owner-local `decisions.md`. One related live/archive owner, one
`Position`/`Workspace` table: contiguous from 1, unique valid slugs matching all
related positions/exact successors; no unenrolled nodes. Valid authority supersedes
history for scheduling; preserve historical bytes. Headerless maps remain legacy.
Partial/malformed headers, multiple owners, invalid root/decision/table, symlink
or unreadable maps fail closed, no fallback. Native normalization records approved
actual identities, preserves history. Engine identity checks grant no semantic
approval, independence, Build or Ship readiness.

## Candidate manifest and bindings

`touched-files.md` contains exactly one `## Touched files` heading and exactly
one authoritative `## Candidate manifest` heading. The first describes scope
without repeating candidate paths; the manifest is the sole authority for candidate scope.

The manifest body is exactly either `No project files.` or this table with one
or more rows:

```markdown
| State | File | Slice | Reason |
| --- | --- | --- | --- |
| present | `path/to/file` | SLICE-001 | Observable reason |
```

Rows are sorted by File: they must already be strictly sorted by normalized
`File`, and readers reject rather than reorder them. `State` is exactly
`present` or `deleted`; `File` is a unique
project-relative UTF-8 path wrapped in one backtick pair; `Slice` and `Reason`
are nonempty. Paths must also be unique under case folding. Every component
rejects Windows-reserved characters and device names (including names with an
extension) plus a trailing dot or space. `## Review trail` may cite
concern-ordered `path:line` review stops, but it cannot define or expand
candidate scope; only manifest rows do.

The public candidate limits are a 1 MiB manifest, 4,096 rows, a 4,096-byte
path, 64 MiB per present file, and 256 MiB across all present files.

A release milestone's union manifest is produced by `devrites-engine state
merge-manifest <release-slug>` — it walks the recorded `sequence_parent` chain,
folds every predecessor manifest, and resolves a path collision in favor of the
later sequence position; a hand-assembled union is not authoritative. When the
workspace cursor declares `sequence_role: release`, `check candidate` and
`check seal` require the manifest to cover the whole recorded chain.

Workspace and audit artifacts are not candidate paths, including all
`.devrites/work/<slug>/visual/`. Durable owners include `.devrites/specs/**`,
`DESIGN.md`, and `docs/adr/**`, plus `.devrites/principles.md`. Under `.devrites`,
only those spec/principles owners qualify; all other siblings (`ACTIVE`, `AFK`,
`CHECKPOINT`, `archive/**`, `work/**`) fail closed. Engine owns malformed path, type,
and size rejection; phases never reinterpret a rejected manifest.

`evidence.md`, `review.md`, and `seal.md` each contain exactly one unindented standalone
binding line; `browser-evidence.md` does too when that file exists:

```text
Candidate SHA-256: <64 lowercase hex>
```

Old unfinished workspaces refresh the manifest and rerun real proof. They never
synthesize a historical pass or use a legacy fallback.

The worktree digest is deterministic but is not an atomic filesystem snapshot
against a malicious concurrent same-size rewrite. Ship's exact Git-index scope,
byte, binding, and secret checks own the final freeze immediately before commit.

Only structural `Budget override: <=N lines; <reason>` outside fences permits N
lines/N×400 bytes, N ≤ 2× budget. Reason-only overrides count as none. Budgets:
400 bytes/line (`state.md`: 120 lines/48 KiB); long lines cannot evade them.
`orient`: `artifact_budgets` (lines/bytes/over/override), `bulk_files` (non-canonical
files >64 KiB). Writers check limits before returning; no local script assumed.

`check readiness`/`check seal`/`state append` block present budgeted artifacts
(optional/`drift.md` included) at ≥1.5× lines or bytes without covering override.
Report exact measurement and remedies: lossless relocation (`$rite-plan revise`),
split (`$rite-plan course-correct`), bounded override. Past 2×: relocation/split
only; below 1.5×: advisory in `orient`.
Proof ledgers (`evidence.md`, `browser-evidence.md`, `touched-files.md`) alone may
grow unbounded, always advisory; manifest limits still apply. Read standalone
binding, `EVID-###`/section index (`grep -n`), then candidate AC/slice bodies.
Inspect no-in-scope-ID entries as anomalies. Whole-file reads require `orient`
within budget; Seal checks literal `AC-###` completeness, reader judges quality.

Slice/AC count and cursor history never justify durable overrides. Decomposition
overflow (`tasks.md`/`plan.md`/`traceability.md`) requires a
[feature-sequence split](../../rite-plan/reference/slicing.md#feature-ceiling-split-an-epic-never-override-the-budget).
Move `state.md` narrative verbatim to append-only `history/<file>-<YYYYMMDD>.md`;
leave a one-line pointer; history never enters phase read-next. Legacy reason-only
overrides cannot clear gates: `$rite-upgrade` routes relocation/split; new writers
never override these reasons. Use
[dispatch packets](standards/context-hygiene.md#dispatch-packets)
for byte checks/lossless retrieval. Overrides neither rewrite nor require loading protected history.

## Anchored notes

`notes.md` carries agent-authored knowledge bound to code it describes — a rationale,
warning, or review stop that must not silently drift when the code moves or changes.
Write it only through `devrites-engine note add <slug> <subject> <quote> <title>
[body]`: the engine assigns `NOTE-###` IDs, stores the subject path and verbatim
`quote`, and keeps the file parseable. One note per fact; quote the smallest
contiguous run that identifies the anchor (identifiers, literals, signatures —
whitespace is normalized, other edits stale it).

`note list` and `note check` regrade every anchor: `exact` (quote found in subject),
`moved` (quote lives in exactly one other file — `note check --repair` rewrites the
subject), `stale`/`ambiguous`/`lost` otherwise. Dependency and workspace trees
(`node_modules`, `.devrites`, vendor, build output) never count as relocation.
`check seal` refuses malformed notes and non-exact anchors; fix or `note rm` them,
never attest past them.

## Native readiness ownership

`decision-coverage.md` owns topology; `test-plan.md`, executable proof; `eng-review.md`,
reviewer verdicts, `Implementation readiness`, and `Readiness inputs SHA-256`. Root
re-reads their IDs/meaning. The digest binds bytes, never semantic correctness.
Readiness checks structure/binding; Seal rechecks both.

Proof commands must be repository-portable: no host wrappers, user-specific absolute paths,
or temporary proof trees. Evidence records the executed command. Optional `visual/`
artifacts never inflate readiness: they are not readiness inputs and do not substitute
for `decision-coverage.md`, `eng-review.md`, or `test-plan.md`.

## Canonical slice grammar

Every producer of `tasks.md` uses this field set. `Dependencies` is slice
ordering; package and service requirements belong in `External dependencies`.

<!-- canonical-slice:start -->
```markdown
## SLICE-001 <observable capability>
Goal: <single observable capability>
Satisfies: AC-001[, AC-002]
Acceptance criteria: <binary criteria this slice closes>
Complexity: <1..5> — <reason>
Mode: <AFK | HITL>
Gate: <advisory | validating | blocking | escalating>
SLA: <15m | 4h | 24h | none>
Checkpoint: <question + why it needs unavailable pre-code evidence or action-time approval | none>
Dependencies: <SLICE-### (via <interface it consumes>) list | none>
depends_on: [<SLICE-### IDs>]
Workspace dependencies: <none | comma-separated <workspace-slug>/SLICE-### producer refs>
Consumes / Produces: <interfaces read and exposed>
Known-Gotchas: <ordering hazards and framework footguns | none>
Prior-slice learnings: <constraints learned earlier | none>
Files likely touched: <real paths>
Writer allowlist: <exact project-relative files the wright may edit (a superset of Files likely touched)>
Tests/proof: <exact command + cwd + expected signal + prerequisites/provenance inputs>
Browser proof required: <yes | no>
Frontend craft required: <yes | no>
Design brief states: <UI states/interaction | none>
Visual acceptance: <state × viewport × input target | none>
Fullstack (FE+BE): <yes | no>
External dependencies: <libraries/services | none>
Existing to reuse / extend: <components/utilities/patterns | none>
Rollback notes: <reversal path>
Evidence required: <evidence $rite-prove must capture>
Edge/Prohibition coverage: <EDGE/PROH IDs | none>
Done condition: <checkable, exhaustive completion criterion>
```
<!-- canonical-slice:end -->

`depends_on` is the machine-readable mirror of `Dependencies`; keep the sets
identical and cycle-free. Each dependency names what crosses it (`check task-graph` advises).
`Workspace dependencies` records cross-workspace producer prerequisites, separate
from local `Dependencies`/`depends_on`. Define/Plan writes it after native interface,
assumption, runtime-resource and proof-independence review; Vet approves the current
bound declaration. `none` is explicit, not inferred from paths or local edges.
Only durably BUILT/integrated producer checkpoints satisfy refs, including valid
archived predecessors; unknown/malformed refs or cycles withhold unsafe work.
Missing field on a legacy future plan requires narrow Plan/Vet repair before
early admission, not rejection of existing local/standalone execution. The global
controller procedure lives only in [`parallel-workspaces.md`](parallel-workspaces.md).
Define and `$rite-plan` repair write `Prior-slice learnings`, folding Build's
`decisions.md` carry-forward constraints; Build never edits `tasks.md`. `Gate`, `SLA`, and `Checkpoint` are required for HITL
slices; use `none` when they do not apply. Complexity above 3 triggers reslicing
unless the stated reason makes the boundary irreducible. A Writer allowlist of 12+
files prints an engine `ADVISORY size:` line (`check task-graph`, `check slice`;
never blocking): split it acceptance-preserving, or add `Size rationale:` naming
the inseparable capability; `ADVISORY hub:` takes a seam slice or `Serial rationale:`.

## Read next by phase

Run `devrites-engine next <slug>` at phase entry for the minimal remaining path
(current phase, open questions, missing artifacts, next `/rite-*` command), then
read the phase row below — or hand `devrites-engine context --skills-root .agents/skills <slug> --phase <p>`
to the engine and read the bundle it emits.

| Phase | Read |
| --- | --- |
| spec | `README.md`, `brief.md`, `spec.md`, `references.md`, `questions.md` |
| clarify | `README.md`, `state.md`, `brief.md`, `spec.md`, `decisions.md`, `assumptions.md`, `questions.md` |
| temper | `spec.md`, `decision-coverage.md`, `decisions.md`, `assumptions.md`, `design-brief.md` |
| define | `README.md`, `state.md`, `spec.md`, `decision-coverage.md`, `architecture.md`, `decisions.md`, `assumptions.md` |
| vet | `state.md`, `spec.md`, `decision-coverage.md`, `README.md`, `traceability.md`, `plan.md`, `tasks.md`, `architecture.md`, `decisions.md` |
| build | `devrites-engine orient <slug>` first; then `state.md`, `eng-review.md` (Build readback + `## Deferred findings`), the selected slice and its `depends_on` via `devrites-engine observe slice <slug> <SLICE-ID>`, the `test-plan.md` and `traceability.md` rows that slice's AC IDs name, open `questions.md` gates, and `touched-files.md` when present. Load whole `tasks.md`/`plan.md`/`architecture.md`/`decision-coverage.md` only when `orient` shows them within budget or the slice cites a section by ID |
| prove | `traceability.md`, `touched-files.md`; each built slice's `Tests/proof` and `Evidence required` via `observe slice`; `evidence.md`/`browser-evidence.md` via the bounded advisory read above |
| review/seal | `README.md`, `traceability.md`, `spec.md`, `decisions.md`, `drift.md`, `touched-files.md`; `evidence.md`/`browser-evidence.md` via the bounded advisory read above |
| handoff | `README.md`, `state.md`, `handoff.md`, then the linked source artifacts |

## Do not duplicate

- Do not make `spec.md` carry deep architecture; link to `architecture.md`/`flows.md`.
- Do not copy acceptance criteria into `plan.md`; reference `AC-###`.
- Do not copy full proof into `handoff.md`; link to `evidence.md`.
- Do not make `state.md` an append-only log; keep only the current cursor. A
  checkpoint entry is at most three lines: what changed, the canonical record path or
  DEC/EVID ID, and the next action. Digests, packet hashes, and finding narratives
  belong to the record they identify, not the cursor.
- Give each normative fact one owner and stable ID; reference rather than copy it.
  Required schema mirrors remain required. Derive counts/mirrors or mechanically
  check equality using available tools, never invented commands. Repair stale
  derived values and assess consumer impact; they are not new policy decisions.
- Do not create optional files before their phase; absence is meaningful. Do not
  treat `visual/` as required for readiness; emit HTML+outline only when a writer
  earns a richer visual, and keep Mermaid in `flows.md` when that is enough.

## ID contract

Use stable IDs: `REQ-001`, `AC-001`, `EDGE-001`, `PROH-001`, `SLICE-001`,
`DEC-001`, `ASM-001`, `DRIFT-001`, `EVID-001`. Current queued questions use
`q-YYYY-MM-DD-NNN`; released table registers may retain `Q-001`. IDs are
append-only identities, not display positions:

- Allocate the next unused numeric suffix for that prefix after scanning its
  owning artifact. For a dated question ID, scan the current date's suffixes.
  Never fill a gap; every deleted or retired ID remains consumed.
- Never renumber an ID, reuse it, or transfer it to a different meaning. Reordering
  sections or rows does not change IDs.
- A wording edit that preserves the obligation keeps its ID. A materially different
  meaning gets a new ID; record the relationship in `decisions.md` or `drift.md`
  before updating downstream references.
- Re-read the owning artifact immediately before an append when another writer may
  have changed it; recompute rather than reserving an ID from stale state.

Old `AC1` and `Slice 1` forms are legacy and should not be generated for new
workspaces. Preserve released legacy forms unless an explicit upgrade owns the
migration; never renumber them incidentally.

