Skip to content

Content blocks (11)

Eleven block kinds covering the descriptive content of a typical feature. Two carry Layer 2 (criterion, fixture); the rest are descriptive.

Rich-text body. The only block that allows TipTap or Markdown.

{
"id": "desc_overview_a1b2",
"kind": "description",
"name": "Feature overview",
"body": "## Overview\n\nThis feature lets users …"
}

EARS-structured acceptance criterion.

{
"id": "cri_initial_load_h31a",
"kind": "criterion",
"name": "Initial load shows empty state when no habits",
"pattern": "WHEN",
"actor": "user",
"trigger": "opens the habits screen",
"system_response": "the app shows the empty state message",
"behavior": {
"before_after": {
"state_diff": { "habits": { "before": [], "after": [] } },
"api_calls": [
{ "method": "GET", "endpoint": "/api/habits", "response": [] }
]
}
}
}

pattern is one of WHEN / IF / WHILE / WHERE / UBIQUITOUS. See Authoring → EARS criteria.

Executable work item.

{
"id": "tsk_implement_create_h14a",
"kind": "task",
"title": "Implement Create habit endpoint",
"complexity": "M",
"depends_on": [],
"status": "in_progress"
}

complexity is one of XS / S / M / L. status is one of idea / in_progress / done / blocked.

Severity + STRIDE category + mitigation. Replaces v0.1’s generic constraint.

{
"id": "rsk_rate_limit_a1b2",
"kind": "risk",
"name": "Rate-limit abuse on Create",
"severity": "medium",
"stride": "DoS",
"mitigation": "Apply 30 req/min per-IP throttle on POST /api/habits"
}

Living scenario data linked to one or more criterion (RFC-0010).

{
"id": "fix_streak_at_4_z9z9",
"kind": "fixture",
"purpose": "Habits with one habit at streak=4",
"linked_criteria": ["cri_streak_increments_b2c2"],
"behavior": {
"shape": "scenario",
"before": { "habits": [{ "id": "h1", "name": "Read", "streak": 4 }] },
"after": { "habits": [{ "id": "h1", "name": "Read", "streak": 5 }] },
"api_calls": [
{ "method": "POST", "endpoint": "/api/habits/h1/checkin",
"response": { "streak": 5 } }
]
}
}

Free-form commentary with audience.

{
"id": "nte_implementation_note_a1b2",
"kind": "note",
"body": "Consider denormalising streak count for read perf.",
"audience": "engineer"
}

audience is one of engineer / pm / designer / all.

ADR-style decision record.

{
"id": "dec_pg_vs_sqlite_a1b2",
"kind": "decision",
"question": "Which DB for v1?",
"options": ["Postgres", "SQLite"],
"chosen": "Postgres",
"rationale": "Multi-user from day one; SQLite migration cost > prep cost."
}

Cross-tier reference.

{
"id": "dep_lemon_squeezy_a1b2",
"kind": "dependency",
"target_atom_id": "ven_lemon_squeezy_b2c2",
"relation": "depends_on"
}

Declarative human-facing must-hold rule. Distinct from rule (which is engine-executable).

{
"id": "inv_streak_monotonic_a1b2",
"kind": "invariant",
"rule_id": "streak_monotonic",
"statement": "A habit's streak counter never decreases except via explicit reset.",
"scope": "Habit entity"
}

Explicit non-goals.

{
"id": "oos_social_features_a1b2",
"kind": "out_of_scope",
"items": ["Friends list", "Public streak leaderboard", "Comments"],
"reason": "v1 focuses on solo habit tracking. Social may come in v2."
}

Step-by-step short flow inline.

{
"id": "seq_signup_flow_a1b2",
"kind": "sequence",
"steps": [
{ "actor": "user", "action": "enters email + password" },
{ "actor": "system", "action": "sends magic link" },
{ "actor": "user", "action": "clicks magic link" },
{ "actor": "system", "action": "creates session" }
]
}

For multi-screen UI flows, prefer ui_view with behavior.screens over a sequence atom.