Feature · Work

Specs

Write plans together and trace each requirement to its evidence.

Last changed

Generated from commit be57775 ·

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.

  • getRecordOverview

    Viewer

    Gets record overview.

    Types: Record<string, never> returns RecordOverview

  • listSpecs

    Viewer

    Lists specs.

    Types: { status?: SpecStatus[]; q?: string; limit?: number; cursor?: string } returns { items: SpecSummary[]; nextCursor: string | null }

  • searchRecord

    Viewer

    Searches record.

    Types: { q: string; kinds?: RecordHitKind[]; limit?: number } returns { hits: RecordHit[] }

  • listWorkItems

    Viewer

    Lists work items.

    Types: ListWorkItemsRequest returns PageResponse<WorkItemSummary>

  • createSpec

    Member

    With 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 }

  • listMembers

    Viewer

    Lists members.

    Types: EmptyRequest returns ListMembersResponse

  • listProjectDecisions

    Viewer

    Lists 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 …

  • markDecisionsRead

    Viewer

    Marks the decisions read.

    Types: Record<string, never> returns { unreadCount: number }

  • retireProjectDecision

    Member

    Retires the project decision.

    Types: { decisionId: string; reason: string } returns { decision: ProjectDecision }

  • getProjectDecision

    Viewer

    One decision with its whole supersession chain, oldest first.

    Types: { decisionId?: string; key?: string } returns { decision: ProjectDecision; chain: ProjectDecision[] }

  • recordProjectDecision

    Member

    Records a project decision.

    Types: { title: string; decision: string; reason: string; alternatives?: string[]; domain?: string; supersedes?: string } returns { decision: ProjectDecision }

  • getSpec

    Viewer

    By id or key; `revision` reads an older revision (its blocks; notes and trace stay current).

    Types: { specId?: string; key?: string; revision?: number } returns SpecDetail

  • auditSpec

    Member

    Runs the deterministic audit on the current revision. Findings that no longer apply resolve.

    Types: { specId: string } returns { audit: SpecAudit; findings: SpecNote[] }

  • setSpecStatus

    Member

    Sets spec status.

    Types: { specId: string; status: SpecStatus; expectedRevision: number; waiver?: string } returns SpecDetail

  • markSpecRead

    Viewer

    Marks the spec read.

    Types: { specId: string; revision: number } returns { lastReadRevision: number }

  • sendSpecNotes

    Member

    Sends 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 }

  • exportSpecMarkdown

    Viewer

    Exports the spec markdown.

    Types: { specId: string } returns { filename: string; markdown: string }

  • promoteSpecDecisions

    Member

    Records the spec's decision blocks in the decision log now (also happens on done).

    Types: { specId: string } returns { promoted: ProjectDecision[]; spec: SpecDetail }

  • reviseSpec

    Member

    The 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… returns SpecDetail

  • getSpecRevision

    Viewer

    Gets the spec revision.

    Types: { specId: string; revision: number } returns { revision: SpecRevisionSummary; blocks: SpecBlock[] }

  • unlinkSpecTicket

    Member

    Unlinks the spec ticket.

    Types: { specId: string; blockId: string; workItemId: string } returns SpecDetail

  • removeSpecEvidence

    Member

    Removes spec evidence.

    Types: { specId: string; evidenceId: string } returns SpecDetail

  • linkSpecTicket

    Member

    Links the spec ticket.

    Types: { specId: string; blockId: string; workItemId: string } returns SpecDetail

  • attachSpecEvidence

    Member

    Attaches spec evidence.

    Types: { specId: string; blockId: string; label: string; url?: string; verdict: TraceEvidence['verdict'] } returns SpecDetail

  • createSpecTickets

    Member

    One 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;…

  • resolveSpecNote

    Member

    Resolves the spec note.

    Types: { noteId: string; status: SpecNoteStatus; resolution?: string } returns { note: SpecNote }

  • addSpecNote

    Member

    Adds a spec note.

    Types: { specId: string; blockId?: string; kind: (typeof SPEC_HUMAN_NOTE_KINDS)[number]; body: string; quote?: string; parentI… returns { note: SpecNote }

Screens

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

Generated from code at commit be57775 ·

Turn the numbers into shipped work.

Agent runs these choices for you: a persistent AI worker with memory and rules, on your Claude and Codex subscriptions.