flowchart TB
subgraph Stage1 [Stage 1: PRD]
direction TB
P1[prd-plan] --> P2[prd-check]
P2 -->|FAIL| P1
P2 -->|PASS| P3[prd-render]
P3 --> P4[prd-slice]
end
subgraph Stage2 [Stage 2: Scaffold]
direction TB
S1[scaffold-plan] --> S2[scaffold-check]
S2 -->|FAIL| S1
S2 -->|PASS| S3[scaffold]
end
subgraph Stage3 [Stage 3: Split]
direction TB
SP1[split-plan] -->|PASS| SP3[split]
SP3 --> SP4[split-check1]
SP4 -->|FAIL| SP1
SP4 -->|PASS| SP5[split-check2]
SP5 -->|FAIL| SP1
SP5 -->|PASS| SP6[split-checkout]
end
subgraph Stage4 [Stage 4: Story]
direction TB
ST1[story-check] -->|PASS| ST2[story-pack]
ST2 --> ST3[story]
end
Stage1 --> Stage2
Stage2 --> Stage3
Stage3 --> Stage4
SP6 -->|FAIL| SP3
| Concept | Description |
|---|---|
| JSON as Single Source of Truth | docs/*.json is the only source of truth; docs/*.md are generated views (do not manually edit after generation) |
| Gates/IDs Handled by Scripts | Model only writes "confirmed facts"; *.id can be null, continuity/uniqueness/append-only enforced by scripts |
| Low-Noise Slicing | Subsequent bundles only read slice index + files referenced by index, avoiding full file reads |
| Low-Noise Diagnostic Artifacts | Each * check writes a current snapshot (docs/*-replan-pack.json + docs/diagnostics/*.md, overwritten on rerun). On FAIL it also writes a preserved snapshot: docs/*-replan-pack.last-fail.json + docs/diagnostics/*.last-fail.md. |
Key Execution Conventions:
- All commands run from project root
- Recommended to open new window for each stage (avoid context pollution)
- Workflow triggered via
textumskill routing; script stages run the correspondinguv run ... textum ...commands (you may also run them for debugging) - User interaction point:
prd-planonly - WARN is non-blocking by default: Ignore WARN when the goal is to keep moving; use
--strictto upgrade WARN to FAIL for strict gates
Command Output Pattern:
- Script commands have low-noise stdout: prints
PASS|FAIL, optional one-lineFAIL/WARNitems (loc/problem/expected/impact/fix), optionalwrote:/entry:, then final linenext:
Plan Phase Behavior:
prd-planmay ask questions or write backscaffold-planandsplit-plando not ask questions and instead write from confirmed artifacts (docs/prd-pack.json.workflow_preferences,docs/prd-slices/*) + deterministic heuristics, or emit blockers to return toPRD Plan
Goal: Requirements clarification → Gate validation → Generate acceptance view → Slice
| Step | Skill | Description |
|---|---|---|
| 1 | prd-plan |
Interactive clarification, write "confirmed facts" to docs/prd-pack.json (auto-init on first run) |
| 2 | prd-check |
Gate validation + auto-assign IDs; writes diagnostic artifacts; FAIL → return to step 1 |
| 3 | prd-render |
Generate docs/PRD.md (manual acceptance; if not as expected → return to step 1) |
| 4 | prd-slice |
Generate docs/prd-slices/ (required for subsequent Split Plan) |
Recommendation (reduce avoidable loops):
- Before leaving
prd-planasREADY, fill the minimal access model:roles[]+permission_matrix.operations[](even for single-user apps; otherwiseprd-checkmayFAILand bounce back)
Goal: Technical decisions → Gate validation → Generate global context
| Step | Skill | Description |
|---|---|---|
| 1 | scaffold-plan |
No-conversation planning; write "confirmed technical decisions" to docs/scaffold-pack.json from confirmed docs/prd-pack.json.workflow_preferences (auto-init on first run) |
| 2 | scaffold-check |
Gate validation + auto-populate extracted/source; writes diagnostic artifacts; FAIL → return to step 1 |
| 3 | scaffold |
Generate docs/GLOBAL-CONTEXT.md (manual acceptance; if not as expected → return to step 1) |
Prerequisites:
docs/prd-slices/index.jsonexists (PRD Slice completed)docs/scaffold-pack.jsonavailable (Scaffold Check passed)
Goal: Story split planning → Gate validation → Generate Story source of truth → Consistency validation → Export dependency graph
| Step | Skill | Description |
|---|---|---|
| 1 | split-plan |
No-conversation planning + built-in READY gate; heuristics: story count derived from PRD complexity (modules/FP/API), deps-first, P0 early; write docs/split-plan-pack.json; iterate via replan packs until PASS |
| 2 | split |
Generate docs/stories/story-###-<slug>.json |
| 3 | split-check1 |
Structure gate + generate handoff index docs/split-check-index-pack.json; threshold defaults to WARN (non-blocking; ok to ignore; --strict upgrades to FAIL); writes diagnostic artifacts; FAIL → return to step 1 (may additionally write docs/split-replan-pack.json) |
| 4 | split-check2 |
Reference consistency + completeness gate (story_count must match actual file count); writes diagnostic artifacts; FAIL → return to step 1 |
| 5 | split-checkout |
Export dependency graph docs/story-mermaid.md (for manual order inspection) |
Prerequisites:
docs/prd-pack.jsonavailable (PRD Check passed)docs/stories/story-###-<slug>.jsonexists (Split Generate completed)docs/scaffold-pack.jsoncontainsextracted.modules_index(Scaffold Check passed)
Goal: Single Story gate → Generate execution bundle → Implement code
| Step | Skill | Input | Description |
|---|---|---|---|
| 1 | story-check |
n (Story number) |
Single Story gate; writes diagnostic artifacts; FAIL → route by next: |
| 2 | story-pack |
n |
Generate low-noise execution bundle docs/story-exec/story-###-<slug>/index.json; writes diagnostic artifacts; FAIL → route by next: |
| 3 | story |
n |
Read-only execution bundle + minimal on-demand repo code reads; only implement this Story's feature_points and api_endpoints |
| 4 | story-full-exec |
1/2/3 |
Batch execution (in order, no rollback) |
story-check / story-pack follow the next: <stage> directive in output on FAIL (fail-fast routing).
Default Behavior:
- Default
--fix=true: Some gate/render/slice commands may write back todocs/*-pack.json(only normalize/ID, populatesource/extractednon-business fields); only outputswrote: ...when actually writing
Diagnostic Artifacts:
* checkcommands writedocs/*-replan-pack.json+docs/diagnostics/*.md(current snapshot; overwritten on rerun)- On
FAILthey also writedocs/*-replan-pack.last-fail.json+docs/diagnostics/*.last-fail.md(preserved)
WARN vs FAIL:
- WARN is non-blocking by default: treat as "optimization suggestions" when the goal is to keep moving
- Use
--strictto upgrade WARN to FAIL for strict gates (currently mainly for Split gate)
Plan Phase Details:
prd-plan: Interactive, may ask questions or write backscaffold-plan/split-plan: No-conversation, write from confirmed artifacts + deterministic heuristics, or emit blockers to return toPRD Plan
| Stage | Source of Truth | Views/Slices |
|---|---|---|
| PRD | docs/prd-pack.json |
docs/PRD.md, docs/prd-slices/ |
| Scaffold | docs/scaffold-pack.json |
docs/GLOBAL-CONTEXT.md |
| Split | docs/split-plan-pack.json, docs/stories/story-###-<slug>.json |
docs/split-check-index-pack.json, docs/split-replan-pack.json, docs/story-mermaid.md |
| Story | — | docs/story-exec/story-###-<slug>/index.json |
| Checks | — | docs/*-replan-pack.json, docs/diagnostics/*.md, docs/*-replan-pack.last-fail.json, docs/diagnostics/*.last-fail.md |
Dependencies isolated in
$SCRIPTS_PATH/.venv, does not pollute project.Codex environment:
SCRIPTS_PATH=.codex/skills/textum/scriptsClaude Code environment:
SCRIPTS_PATH=.claude/skills/textum/scripts
uv sync --project $SCRIPTS_PATH # First time/dependency updates
uv run --project $SCRIPTS_PATH textum <cmd> # Execute commandSee Appendix D for specific <cmd> options.
Entry point:
$SCRIPTS_PATH/textum/textum_cli.py
| Skill | CLI Command | Main Implementation |
|---|---|---|
prd-plan |
textum prd init |
textum/prd/prd_pack.py, textum/prd/prd_pack_validate.py |
prd-check |
textum prd check |
textum/prd/prd_pack_validate.py |
prd-render |
textum prd render |
textum/prd/prd_render.py |
prd-slice |
textum prd slice |
textum/prd/prd_slices.py, textum/prd/prd_slices_generate.py |
scaffold-plan |
textum scaffold init |
textum/scaffold/scaffold_pack.py |
scaffold-check |
textum scaffold check |
textum/scaffold/scaffold_pack_validate.py |
scaffold |
textum scaffold render |
textum/scaffold/scaffold_render.py |
split-plan |
textum split plan init/check |
textum/split/split_plan_pack.py, textum/split/split_plan_pack_validate.py |
split |
textum split generate |
textum/split/split_story_generate.py |
split-check1 |
textum split check1 |
textum/split/split_check_index_generate.py, textum/split/split_check_index_pack.py |
split-check2 |
textum split check2 |
textum/split/split_check_refs.py |
split-checkout |
textum split checkout |
textum/split/split_checkout.py |
story-check |
textum story check --n <n> |
textum/story/story_check.py, textum/story/story_check_utils.py, textum/story/story_check_validate_*.py |
story-pack |
textum story pack --n <n> |
textum/story/story_exec_pack.py, textum/story/story_exec_pack_validate.py |
story / story-full-exec |
— | prompt-only (no script) |
Utility commands (non-skill; for atomic writes in Plan phase, avoiding full file reordering):
textum prd patch {set|append|delete}(implementation:textum/textum_cli_prd_patch.py,textum/textum_json_patch.py)