Feature · Work
Specs
Write plans together and trace each requirement to its evidence.
How it works
What a spec is
A spec, for example SPEC-7, is a list of blocks. A block is a goal, context, requirement, decision, question, risk or approach. Each block keeps a reference, for example R3, for life.
Statuses
Draft, Ready, Building, Done and Archived. Marking a spec Ready needs a clear audit of the current revision, or a written waiver. A waiver shows as "Waived, not passed".
Notes
Anyone can add a comment, question or objection on a block. Send to agent sends all open notes to the work item's worker in one message. The worker answers with one new revision.
The audit
A fixed set of rules checks the current revision and pins each finding to its block. The audit checks structure. It does not judge whether the plan is wise.
Tickets and the trace
Each requirement can become a ticket: a child work item that cites the block. The trace shows each requirement's tickets, checks and evidence, and a verdict: unplanned, planned, in progress, failing or proven.
The decision log
Decisions keeps accepted, superseded and retired decisions, for example DEC-12, each with its reason and the alternatives. Select Record decision to add one. A new spec starts from the decisions that apply.
Who can write
Members and above can write specs and record decisions. Revisions never overwrite each other: a save on an old revision is refused.
Limits
Build notes are not raised from code changes by themselves.
From the help article Specs and the decision log, checked against the product on .
What you can do
The operations this feature's screens call. Each one is POST /api/<name>, and the badge says who may call it.
ViewergetRecordOverviewGets record overview.
Types:
Record<string, never>returnsRecordOverview
ViewerlistSpecsLists specs.
Types:
{ status?: SpecStatus[]; q?: string; limit?: number; cursor?: string }returns{ items: SpecSummary[]; nextCursor: string | null }
ViewersearchRecordSearches record.
Types:
{ q: string; kinds?: RecordHitKind[]; limit?: number }returns{ hits: RecordHit[] }
ViewerlistWorkItemsLists work items.
Types:
ListWorkItemsRequestreturnsPageResponse<WorkItemSummary>
MembercreateSpecWith a work item and no blocks it starts from the item: objective, requirements, plan approach, risks, open questions and recorded decisions. One spec per work item.
Types:
{ title?: string; workItemId?: string; blocks?: SpecBlockInput[]; draftWithAgent?: boolean }returns{ spec: SpecDetail; agentAsked: boolean; reason: string | null }
ViewerlistMembersLists members.
Types:
EmptyRequestreturnsListMembersResponse
ViewerlistProjectDecisionsLists project decisions.
Types:
{ q?: string; domain?: string; status?: ProjectDecisionStatus[]; limit?: number; cursor?: string }returns{ items: ProjectDecision[]; domains: Array<{ domain: string; count: number }>; unreadCount: number; nextCursor: string …
ViewermarkDecisionsReadMarks the decisions read.
Types:
Record<string, never>returns{ unreadCount: number }
MemberretireProjectDecisionRetires the project decision.
Types:
{ decisionId: string; reason: string }returns{ decision: ProjectDecision }
ViewergetProjectDecisionOne decision with its whole supersession chain, oldest first.
Types:
{ decisionId?: string; key?: string }returns{ decision: ProjectDecision; chain: ProjectDecision[] }
MemberrecordProjectDecisionRecords a project decision.
Types:
{ title: string; decision: string; reason: string; alternatives?: string[]; domain?: string; supersedes?: string }returns{ decision: ProjectDecision }
ViewergetSpecBy id or key; `revision` reads an older revision (its blocks; notes and trace stay current).
Types:
{ specId?: string; key?: string; revision?: number }returnsSpecDetail
MemberauditSpecRuns the deterministic audit on the current revision. Findings that no longer apply resolve.
Types:
{ specId: string }returns{ audit: SpecAudit; findings: SpecNote[] }
MembersetSpecStatusSets spec status.
Types:
{ specId: string; status: SpecStatus; expectedRevision: number; waiver?: string }returnsSpecDetail
ViewermarkSpecReadMarks the spec read.
Types:
{ specId: string; revision: number }returns{ lastReadRevision: number }
MembersendSpecNotesSends every unsent open note from people to the spec's agent in one message, for one revision.
Types:
{ specId: string }returns{ sent: number; agentAsked: boolean; reason: string | null }
ViewerexportSpecMarkdownExports the spec markdown.
Types:
{ specId: string }returns{ filename: string; markdown: string }
MemberpromoteSpecDecisionsRecords the spec's decision blocks in the decision log now (also happens on done).
Types:
{ specId: string }returns{ promoted: ProjectDecision[]; spec: SpecDetail }
MemberreviseSpecThe whole block list, replacing the current one; refused unless `expectedRevision` is current.
Types:
{ specId: string; expectedRevision: number; blocks: SpecBlockInput[]; title?: string; summary?: string; answers?: strin…returnsSpecDetail
ViewergetSpecRevisionGets the spec revision.
Types:
{ specId: string; revision: number }returns{ revision: SpecRevisionSummary; blocks: SpecBlock[] }
MemberunlinkSpecTicketUnlinks the spec ticket.
Types:
{ specId: string; blockId: string; workItemId: string }returnsSpecDetail
MemberremoveSpecEvidenceRemoves spec evidence.
Types:
{ specId: string; evidenceId: string }returnsSpecDetail
MemberlinkSpecTicketLinks the spec ticket.
Types:
{ specId: string; blockId: string; workItemId: string }returnsSpecDetail
MemberattachSpecEvidenceAttaches spec evidence.
Types:
{ specId: string; blockId: string; label: string; url?: string; verdict: TraceEvidence['verdict'] }returnsSpecDetail
MembercreateSpecTicketsOne child work item per requirement block without a ticket (or the given blocks).
Types:
{ specId: string; blockIds?: string[]; ownerWorkerId?: string }returns{ created: Array<{ blockId: string; ref: string; ticket: TraceTicket }>; skipped: Array<{ blockId: string; ref: string;…
MemberresolveSpecNoteResolves the spec note.
Types:
{ noteId: string; status: SpecNoteStatus; resolution?: string }returns{ note: SpecNote }
MemberaddSpecNoteAdds a spec note.
Types:
{ specId: string; blockId?: string; kind: (typeof SPEC_HUMAN_NOTE_KINDS)[number]; body: string; quote?: string; parentI…returns{ note: SpecNote }
Screens
/specs/specs/decisions/specs/:key
What it records
The feature writes these events to the audit log, the permanent record of what happened.
- Project decision recorded
- Project decision retired
- Project decision superseded
- Spec audited
- Spec created
- Spec note added
- Spec note resolved
- Spec revised
- Spec status changed
- Spec tickets created
- Spec trace changed