Skip to content

workspace.toml schema reference

Exact target entries, lifecycle collections, compatibility forms, and validation limits for the workspace index.

workspace.toml is the repository coordination index. It points to canonical artifacts, records lifecycle membership, stores minimal source provenance, and names hard dependencies. It is not a requirements document.

Use this reference when you need to answer: “How should this artifact be represented in workspace.toml, and is the entry safe to dispatch?” The result is either a valid target entry in one lifecycle collection or a non-dispatchable compatibility or reconciliation finding.

Input: A repository-relative canonical artifact path or a closed external locator, its artifact kind, minimal source provenance, a display summary, and any hard dependencies.

Output: A target entry that validates against the published workspace-entry schema, or a fail-closed finding that names the unsafe or legacy condition.

Reads: Consumers read workspace.toml and the referenced canonical artifacts needed to confirm lifecycle, provenance, plans, dependencies, and confinement.

Writes: Writers update lifecycle membership only after they have created or updated the canonical artifact. Requirements and acceptance decisions stay in that artifact, never in the workspace index.

Workspace entries stay terse: minimal source provenance, one short current or next-needed summary, and hard dependencies. They do not carry chronology, rationale, procedures, review transcripts, raw findings, copied source text, soft priority, or suggested order. If that context matters, write it to the canonical artifact first and index the pointer here.

Human decision: A person chooses the canonical artifact route, approves requirement-bearing artifacts, and decides how to migrate a legacy entry.

Repositories that enable tracker refresh also carry a global [authorization.refresh] role policy outside initiative entries. See Use work intake for the exact required keys and confirmation boundaries. The policy contains roles only; artifact authority, approver identities, decisions, conflicts, and receipts remain in the canonical artifact.

Comments, summary, list order, tracker object type, and profile hints are display context only. They must not decide routing, reconciliation, dependency satisfaction, dispatch, or which processor runs.

Section headers use TOML quoted dotted keys when an initiative id contains a hyphen:

["ini-001"]
name = "Workspace routing"
status = "active"
milestone = "M1"

Every target-state lifecycle entry is an inline table with four required fields plus a repository-relative path, a closed external locator, or both:

{ path = "docs/specs/self-service-reset/spec.md", kind = "spec", source = { mode = "repo-origin" }, summary = "Let a user reset access without support", needs = [] }
FieldTypeMeaning
pathstringOptional repository-relative canonical artifact path. At least one of path or locator is required.
surface_rolestringOptional semantic role. Required with locator.
locatortableOptional closed external locator with exactly kind = "external" and value.
kindstringintent, research, design, brief, spec, or defect.
sourcetableMinimal provenance used for display and reconciliation.
summarystringNon-empty display text. Non-semantic.
needsarrayTyped hard dependencies. Empty when unblocked by other artifacts.

Unknown fields fail the target contract. Requirements, acceptance criteria, field ownership maps, source-decision history, credentials, and raw source payloads do not belong in workspace.toml. Comments are not overflow storage; an entry that is materially updated now adopts the terse live-index form even when untouched legacy prose remains elsewhere.

ValueLimit
path and dependency paths1–1,000 characters
External locator.value3–1,000 characters
summary1–500 characters
needs0–50 records
source.ref1–1,000 characters when present
source.revision1–200 characters when present
source.coordination1–300 characters when present
Tracker profile id1–200 characters
Tracker profile version1–100 characters

path and local dependency paths are repository-relative POSIX-style paths. They must not be empty or absolute. Backslashes, control characters, empty segments, and . or .. segments are rejected.

The lexical check is not enough before reading or dispatching. Consumers must resolve the repository root and target path after symlinks, then verify the resolved target remains under the resolved root. A symlink that points outside the repository, a symlink loop, or an uncertain resolution fails closed even if its text path looks valid.

Use a semantic role when a workflow needs to identify what a destination means without fixing its filename or format. The accepted roles are:

  • delivery-brief, delivery-contract, current-product-truth
  • user-documentation, product-history, release-history
  • current-architecture, architecture-design, decision-record
  • operations, interface-contract, project-knowledge, runtime-coordination

A path entry may carry role and locator metadata without changing its lifecycle classification:

{ path = "docs/specs/example/spec.md", surface_role = "delivery-contract", locator = { kind = "external", value = "example-tracker:delivery/42" }, kind = "spec", source = { mode = "repo-origin" }, summary = "Delivery contract with external coordination", needs = [] }

A locator-only entry is also contract-valid:

{ surface_role = "delivery-contract", locator = { kind = "external", value = "example-tracker:delivery/42" }, kind = "spec", source = { mode = "tracker-origin", ref = "example-tracker:delivery/42", revision = "revision-7" }, summary = "Externally located delivery contract", needs = [] }

Locator-only entries are visible but non-dispatchable. The workspace reader returns configuration_mismatch before attempting a local artifact read. Semantic resolution itself is read-only: it does not create an artifact, register an entry, or change lifecycle membership.

An external locator uses a scheme-shaped opaque value such as example-tracker:delivery/42. Userinfo, query strings, fragments, whitespace, and control characters fail the contract. Consumers preserve the value as an external locator; they do not turn it into a local path, fetch it, or infer availability, writability, or authority from it.

source.mode is required and is either repo-origin or tracker-origin.

source = { mode = "repo-origin", parent = "docs/product/briefs/account-recovery.md" }
source = { mode = "tracker-origin", ref = "example-service://tickets/WORK-123", revision = "tracker-rev-42", tracker_profile = { id = "example-service/default", version = "2026-08" } }

Tracker-origin entries require both ref and revision. Optional fields are:

FieldMeaning
parentLocal parent artifact such as a brief or intent.
coordinationCross-repository coordination reference.
tracker_profileOptional profile hint with id and version.

ref is durable provenance, not a credential carrier. Userinfo (@), query strings, and fragments fail the contract; store a sanitized opaque source identifier instead.

Tracker profile and object vocabulary are hints. They cannot determine artifact kind, lifecycle membership, or processor.

needs is an array of typed hard dependencies. A local dependency names the required artifact kind and canonical local path:

needs = [
{ type = "local", kind = "design", path = "docs/product/design/workspace-routing.md" },
]

A local dependency on a delivery whose entry and artifact have been removed can carry a completion receipt on the citing edge:

needs = [
{ type = "local", kind = "design", path = "docs/product/design/account-recovery.md", receipt = { delivery_id = "account-recovery-42", outcome = "completed", completion_event = "release", evidence_ref = "commit:0123456789abcdef0123456789abcdef01234567" } },
]

The receipt requires exactly delivery_id, outcome, completion_event, and evidence_ref. A defect-kind need may not carry one.

A cross-repository dependency is satisfied only by a reviewed local receipt in the containing brief. The dependency pins the local brief path, receipt id, and accepted revision:

needs = [
{ type = "cross-repo", kind = "brief", path = "docs/product/briefs/account-recovery.md", containing_brief = "docs/product/briefs/account-recovery.md", receipt_id = "remote-prereq", accepted_revision = "remote-rev-9" },
]

When a cross-repository dependency names a containing brief, that local brief must contain exactly one fenced block whose info string is exactly toml coordination-receipts. The block is parsed as TOML; surrounding prose and other fenced blocks are inert.

Valid receipt block:

[[coordination_receipts]]
id = "remote-prereq"
remote_kind = "brief"
remote_ref = "example-service://projects/example-artifact"
accepted_revision = "remote-rev-9"
required_status = "Shipped"
reported_status = "Shipped"
reviewed_by = "Example Reviewer"
reviewed_at = "2026-08-10T00:00:00Z"
refresh_conflict = false

Representative invalid receipt block:

[[coordination_receipts]]
id = "remote-prereq"
remote_kind = "brief"
remote_ref = "example-service://projects/example-artifact"
accepted_revision = "remote-rev-8"
required_status = "Shipped"
reported_status = "Shipped"
reviewed_by = "Example Reviewer"
reviewed_at = "2026-08-10T00:00:00Z"
refresh_conflict = false

The invalid example fails because its accepted_revision does not match the dependency’s pinned revision. Recovery: replace it with a reviewed receipt matching the pinned dependency; the finding code is invalid_receipt.

Priority, affinity, rationale, and suggested order are not dependencies.

Membership is lifecycle state. A target entry appears in exactly one lifecycle collection.

CollectionValid artifactsMeaning
[backlog].openDraft artifacts and open defect contextsVisible, not dispatchable.
[backlog].closedRetained captures and closed defect contextsClosed defect resolution is fixed, declined, or superseded.
["ini-NNN".shaping_queue].backlogintent, research, designWaiting for shaping, research, or design processing.
["ini-NNN".shaping_queue].activeintent, research, designCurrently being processed outside implementation work.
["ini-NNN".brief_queue].draftbriefDraft brief; no child is Implementing or Shipped.
["ini-NNN".brief_queue].readybriefPassed the Ready gate; no child is Implementing or Shipped. May have zero child specs.
["ini-NNN".brief_queue].executingbriefOpen brief with at least one Implementing or Shipped child.
["ini-NNN".brief_queue].shippedbriefExplicitly closed successfully; the map is non-empty and every materialized child is Shipped.
["ini-NNN".brief_queue].withdrawnbriefExplicitly stopped before any child reached Implementing or Shipped.
["ini-NNN".brief_queue].cancelledbriefExplicitly stopped after at least one child reached Implementing or Shipped.
["ini-NNN".work].queuespecApproved spec with an existing sibling plan, waiting to be claimed.
["ini-NNN".work].activespecImplementing spec claimed by the build loop.
["ini-NNN".work].shippedspecShipped spec retained for dependency and history.

An initiative table is active only when status = "active". Paused and closed initiatives are visible but non-dispatchable.

workspace.toml is live coordination, not the artifact-retention unit. A pause may reference an overlay in an established compatible coordination surface, but does not change the spec’s Ready or Implementing status. workspace-status may project pause and closeout blockers from current state; it does not store a disposition, start a cooling clock, or remove context.

When close-work settles an initiative, it reconciles both shaping and build rooms, every child, obligation, dependency, and residual before proposing compaction. Settled membership may leave even when an RFC, release, or decision family remains retained as a semantic anchor. Do not replace removed membership with a narrative history. A dependency receipt belongs only in an already compatible coordination surface and contains exactly delivery ID, outcome, completion event, and evidence reference; workspace.toml may point at cooling state and never owns it.

[backlog]
open = [
{ path = "docs/product/intents/workspace-routing.md", kind = "intent", source = { mode = "repo-origin" }, summary = "Define deterministic workspace routing", needs = [] },
]
closed = []
["ini-001"]
name = "Workspace routing"
status = "active"
milestone = "M1"
["ini-001".brief_queue]
draft = []
ready = [
{ path = "docs/product/briefs/account-recovery.md", kind = "brief", source = { mode = "tracker-origin", ref = "example-service://projects/PROJ-123", revision = "tracker-rev-42" }, summary = "Make account recovery self-service", needs = [] },
]
executing = []
shipped = []
withdrawn = []
cancelled = []
["ini-001".work]
queue = [
{ path = "docs/specs/self-service-reset/spec.md", kind = "spec", source = { mode = "tracker-origin", ref = "example-service://projects/PROJ-123", revision = "tracker-rev-42", parent = "docs/product/briefs/account-recovery.md" }, summary = "Let a user reset access without support", needs = [] },
]
active = []
shipped = []
["ini-001".shaping_queue]
backlog = []
active = []

A Ready brief with zero child specs is valid and useful planning state. It is visible in workspace-status, but it is not dispatchable. Implementation begins only when a selected slice has a spec, its sibling plan, Approved status, and a target entry in work.queue.

Once a child reaches Implementing or Shipped, move the open brief to executing. This includes programmes whose currently materialized children are all Shipped while the next slice has not been materialized. Shipping every current row does not move the brief automatically. Shipped, Withdrawn, and Cancelled require explicit closeout, preserve child statuses, and use their matching collections.

Legacy four-state files need no immediate rewrite. Add empty withdrawn and cancelled lists when you next normalize the table, or add the relevant list when the first terminated brief is recorded. The historical scalar form of executing remains accepted; workspace-status keeps projecting it as a scalar while the other five states are lists.

Every refusal is visible as a stable code with a safe next action, plus an identifier. The identifier is a repository-relative path, except for unsupported_legacy, which carries a safe single-segment slug when the offending object has one so that each record stays attributable. Treat a finding identifier as a path only after confirming it is one.

CodeWhy blockedSafe action
invalid_workspaceTOML parse failure or invalid lifecycle collection shape.Correct workspace.toml, then rerun reconciliation.
invalid_entryMalformed target record, unknown field or kind, or failed schema conditional.Rewrite the entry to the accepted target contract.
legacy_entrySupported compatibility form; visible but never dispatchable.Materialize and register a canonical target entry.
unsupported_legacyLegacy-like form outside accepted compatibility fixtures.Route the item manually; do not infer a target entry.
invalid_artifact_pathUnsafe, noncanonical, or out-of-repository artifact-like path.Replace it with a confined canonical repository-relative path.
missing_artifactRegistered canonical artifact does not exist.Create and review the canonical artifact before dispatch.
unreadable_artifactA confined artifact cannot be read safely.Restore readable repository state, then rerun reconciliation.
missing_planA spec has no sibling plan.md.Create and approve the plan before dispatch.
unapproved_specQueue spec is not Approved.Complete the spec approval gate.
unregistered_workSupplied or active spec has no unique matching workspace membership.Register or reconcile the canonical entry explicitly.
duplicate_membershipOne artifact occurs more than once across lifecycle memberships.Remove the duplicate after choosing the authoritative membership.
impossible_transitionArtifact status and lifecycle membership cannot coexist.Correct the artifact or membership through a reviewed transition.
provenance_mismatchWorkspace source metadata disagrees with canonical artifact metadata.Resolve provenance in the canonical artifact and mirror it deliberately.
refresh_conflictTracker-origin refresh conflict remains unresolved.Resolve the conflict through the artifact’s authority workflow.
invalid_source_authorityTracker-origin source authority is missing, duplicated, malformed, or violates its closed contract.Correct the closed source-authority block, then rerun reconciliation.
source_authority_migration_requiredA legacy tracker-origin artifact has no closed source-authority record.Add the reviewed authority record before using refresh.
invalid_lifecycle_recordA docs/lifecycle/ record failed to load, was a symlink, or was not a regular file.Repair or remove that record; other records still cool.
cooling_state_unavailableThe cooled set could not be established at all: docs/lifecycle/ is unusable or escapes the root, or no cooling module resolved.Install close-work or repair docs/lifecycle/; no artifact is excluded this run.
unsatisfied_dependencyA known dependency lacks its kind-specific terminal state.Complete or explicitly revise the dependency.
missing_dependencyA dependency target cannot be resolved locally.Materialize or correct the dependency target.
dependency_cycleThe hard-dependency graph contains a cycle.Break the cycle through an explicit plan change.
invalid_receiptCross-repository receipt is incomplete, mismatched, or conflicted.Replace it with a reviewed receipt matching the pinned dependency.
invalid_completion_receiptA local completion receipt has the wrong fields, value types, grammar, or outcome.Replace it with a valid reviewed completion receipt for that dependency.
inactive_initiativeWork belongs to a paused or closed initiative.Reactivate the initiative explicitly or move the work through governance.
configuration_mismatchVersioned schema, adapter/profile, or routing identity is inconsistent, or a locator-only entry has no dispatch integration.Install or select a consistent versioned configuration, then rerun.

The shared intent artifact contains:

  • Status
  • Level
  • Outcome
  • Opportunity
  • Assumptions
  • Source

The default path is docs/product/intents/<slug>.md. A repository may relocate the parent through its configured core layout, but the resolved output must stay inside the repository so it can be indexed by workspace.toml.

A defect context captures already-intended behavior that is not currently true. It requires expected behavior, observed behavior, reproduction evidence or an error signature, source provenance, and a durable citation establishing the intended behavior. Closed defect contexts record exactly one resolution: fixed, declined, or superseded.

Defects stay in the repository-level backlog. They are routed to the bug-fix workflow, not directly to implementation queue dispatch.

During the compatibility window, readers may recognize these legacy shapes:

CollectionLegacy shape
Work arraysBare spec/<slug> strings only.
Shaping arraysBare shaping slugs, or { slug, type, needs } objects where type is shape, research, strategy, signal, or design.
Brief queue arraysBrief path strings such as docs/product/briefs/<slug>.md.
[backlog].openComment-rich inline objects with slug plus legacy fields such as needs, source, summary, or type.

The same shape in the wrong collection is invalid. A legacy entry is tagged as legacy, visible, and non-dispatchable. A missing artifact or plan stays non-dispatchable, and readers do not reconstruct requirements from comments. Migration requires a human to choose the canonical artifact route and write a target entry.

Repositories that apply or roll back legacy-entry migrations declare one closed global policy outside initiative tables:

[authorization.migration]
contract_version = "work-intake-migration-authorization.v1"
approver_roles = ["migration-approver"]

approver_roles is a non-empty unique subset of the public roles accepted by the confirmation contract: migration-approver, repository-maintainer, and security-approver. Unknown keys or roles fail closed.

Planning consumes a closed, human-authored selection and is read-only. It binds the canonical legacy finding ID, workspace fingerprint, source collection/index/exact-slice digest, selected five-field target entry and membership, owning processor, provenance, and positive privacy attestation. The agent may show candidates but must not author or edit that selection.

Apply creates .workspace-migrations.json at the repository root. The ledger stores repository identity and ordered operations with:

  • operation ID and immutable digest;
  • exact legacy TOML slice and original membership;
  • selected target entry and membership;
  • artifact path, confined fingerprint, and proof that it existed before apply;
  • pending, applied, rollback_pending, or rolled_back state;
  • consumed single-use confirmation receipts with opaque identifiers, action and operation binding, role digest, timestamp, and authorization source.

The ledger excludes requirements, raw tracker payloads, credentials, and raw role labels. It is written and synced before the workspace effect so an interrupted operation can recover. Rollback restores the exact legacy slice and never deletes the canonical artifact.

A shipped entry may be removed while a live needs edge references it when every such edge carries a valid completion receipt whose outcome is completed. No open parent may reference the entry, and closure evidence must be durable in the canonical artifacts. Compaction removes only the index entry. It never deletes the canonical artifact or its Git history.

Examples use TOML strings as raw UTF-8. Do not encode Unicode scalar values as JSON surrogate escapes in TOML examples. JSON fixture loading rejects non-standard NaN and infinity constants, and JSON emission must refuse non-finite values.