Skip to main content

Increment Metadata Reference

Every SpecWeave increment has a metadata.json file at .specweave/increments/{id}/metadata.json. This is the source of truth for increment state, configuration, and external tool links.


Required Fields

FieldTypeDescription
idstringIncrement identifier (e.g., "0532-fix-hook-timeout")
statusstringCurrent lifecycle state (see Status Lifecycle below)
typestringIncrement classification (see Types below)
createdISO 8601Creation timestamp
lastActivityISO 8601Last activity timestamp

Optional Fields

FieldTypeDefaultDescription
prioritystring"P1"Priority: P0, P1, P2, P3, critical, high, medium, low
testModestring"TDD"Testing mode: TDD, test-after, test-first, manual, none
coverageTargetnumber90Test coverage target (0-100, 0 = disabled)
feature_idstringnullFeature ID (derived from increment number)
epic_idstringnullEpic ID if part of an epic
projectstringProject identifier (for umbrella/workspace repos)
skipLivingDocsSyncbooleanfalseSkip living docs sync for this increment

Status Lifecycle

Status Values

StatusWIP CountedDescription
planningNoSpec/plan/tasks being created
activeYesCurrently being worked on
backlogNoPlanned but not ready
pausedYesTemporarily blocked
ready_for_reviewYesAll tasks complete, awaiting review
completedNoApproved via sw:done
abandonedNoWork abandoned

Critical Gates

  • active → ready_for_review: Auto-transitions when all tasks marked complete
  • ready_for_review → completed: Only via explicit sw:done with quality gates
  • Direct active → completed: Not allowed — prevents auto-completion bugs

Increment Types

TypeWIP LimitAuto-AbandonDescription
feature2New functionality
bugunlimitedBug fix requiring RCA
hotfixunlimitedCritical production fix, bypasses all limits
change-request2Business/stakeholder changes
refactor1Technical debt reduction
experimentunlimited14 daysPOC/spike, auto-abandons after threshold

Lifecycle Timestamps

These fields are set automatically when status transitions occur:

FieldSet When
backlogAtStatus → backlog
backlogReasonStatus = backlog
pausedAtStatus → paused
pausedReasonStatus = paused
abandonedAtStatus → abandoned
abandonedReasonStatus = abandoned
readyForReviewAtAll tasks complete (auto)
approvedAtsw:done completes

The externalLinks object tracks references to external tools. Each provider has its own schema.

GitHub

{
"externalLinks": {
"github": {
"issues": {
"US-001": {
"issueNumber": 1573,
"issueUrl": "https://github.com/org/repo/issues/1573",
"status": "active"
}
},
"milestone": 243,
"syncedAt": "2026-03-15T16:49:06.925Z"
}
}
}

JIRA

{
"externalLinks": {
"jira": {
"epicKey": "PROJ-220",
"epicUrl": "https://domain.atlassian.net/browse/PROJ-220",
"projectKey": "PROJ",
"domain": "domain.atlassian.net",
"syncedAt": "2026-03-15T17:04:28.435Z"
}
}
}

Azure DevOps

{
"externalLinks": {
"ado": {
"featureId": "1366",
"featureUrl": "https://dev.azure.com/org/project/_workitems/edit/1366",
"organization": "MyOrg",
"project": "MyProject",
"syncedAt": "2026-03-15T17:04:30.186Z"
}
}
}

Sync Target

Controls which sync profile handles this increment (v1.0.31+):

{
"syncTarget": {
"profileId": "github-main",
"provider": "github",
"derivedFrom": "project-mapping",
"setAt": "2026-03-15T08:52:13.086Z",
"sourceProjectId": "frontend-app"
}
}

derivedFrom values: user-selection, project-mapping, default-profile, first-profile-fallback, auto-detected


PR References

Track pull requests linked to this increment (v1.0.437+):

{
"prRefs": [{
"branch": "sw/0520-feature-branch",
"prNumber": 42,
"prUrl": "https://github.com/org/repo/pull/42",
"repoSlug": "org/repo",
"state": "open",
"createdAt": "2026-03-12T10:00:00Z"
}]
}

Complete Example

{
"id": "0532-fix-hook-timeout-errors",
"status": "completed",
"type": "bug",
"priority": "P1",
"created": "2026-03-15T08:52:13.086Z",
"lastActivity": "2026-03-15T17:04:20.194Z",
"testMode": "TDD",
"coverageTarget": 90,
"feature_id": null,
"epic_id": null,
"project": "specweave",
"externalLinks": {
"github": {
"issues": {
"US-001": {
"issueNumber": 1573,
"issueUrl": "https://github.com/anton-abyzov/specweave/issues/1573",
"status": "active"
}
},
"milestone": 243,
"syncedAt": "2026-03-15T16:49:06.925Z"
},
"jira": {
"epicKey": "SWE2E-220",
"epicUrl": "https://antonabyzov.atlassian.net/browse/SWE2E-220",
"projectKey": "SWE2E",
"domain": "antonabyzov.atlassian.net",
"syncedAt": "2026-03-15T17:04:28.435Z"
}
},
"syncTarget": {
"profileId": "github-main",
"provider": "github",
"derivedFrom": "project-mapping",
"setAt": "2026-03-15T08:52:13.086Z"
},
"readyForReviewAt": "2026-03-15T17:04:20.147Z",
"approvedAt": "2026-03-15T17:04:20.194Z"
}