tiny-spec 1.2.0__tar.gz → 2.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/PKG-INFO +38 -39
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/README.md +37 -38
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/agents/tiny-spec-build-executor.md +2 -2
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/agents/tiny-spec-build-reviewer.md +2 -2
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/docs/eval/README.md +2 -2
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/examples/todo-cli/README.md +6 -4
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/pyproject.toml +1 -1
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/tiny-spec-adopt/SKILL.md +2 -2
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/tiny-spec-build/SKILL.md +28 -25
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/tiny-spec-create/SKILL.md +21 -21
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/tiny-spec-design/SKILL.md +3 -3
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/tiny-spec-plan/SKILL.md +32 -35
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/tiny-spec-run/SKILL.md +69 -65
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/tiny-spec-scope/SKILL.md +65 -64
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/tiny_spec/__init__.py +1 -1
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/.gitignore +0 -0
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/LICENSE +0 -0
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/tiny_spec/cli.py +0 -0
- {tiny_spec-1.2.0 → tiny_spec-2.0.0}/tiny_spec/manifest.json +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: tiny-spec
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: A tiny, opinionated take on spec-driven development.
|
|
5
5
|
Project-URL: Homepage, https://github.com/GrayMa77er/tiny-spec
|
|
6
6
|
Project-URL: Source, https://github.com/GrayMa77er/tiny-spec
|
|
@@ -71,13 +71,13 @@ committed.
|
|
|
71
71
|
That core is **three skills and two agents**. In front of it sit **two front doors** —
|
|
72
72
|
pick the one that matches where you're starting. Over the top sits **one router**,
|
|
73
73
|
`tiny-spec-run`, which drives the chain and, when you ask it to, works a whole list of
|
|
74
|
-
|
|
74
|
+
features through to merged code. No config file, no build step.
|
|
75
75
|
|
|
76
76
|
```
|
|
77
77
|
GREENFIELD BROWNFIELD
|
|
78
78
|
starting from an idea starting from a codebase
|
|
79
79
|
tiny-spec-scope tiny-spec-adopt
|
|
80
|
-
idea → Features
|
|
80
|
+
idea → Features real code → constitution
|
|
81
81
|
BREAKDOWN.md constitution.md
|
|
82
82
|
\ /
|
|
83
83
|
└───────────┬───────────┘
|
|
@@ -85,16 +85,16 @@ stories through to merged code. No config file, no build step.
|
|
|
85
85
|
tiny-spec-create → tiny-spec-plan → tiny-spec-build
|
|
86
86
|
intent design + tasks per-task loop
|
|
87
87
|
SPEC.md PLAN.md plan → implement
|
|
88
|
-
|
|
88
|
+
(+ ## Tasks) → review → commit
|
|
89
89
|
|
|
90
90
|
tiny-spec-run one router. Walks the chain and stops before build —
|
|
91
|
-
or, asked to, builds each
|
|
91
|
+
or, asked to, builds each feature and merges it.
|
|
92
92
|
tiny-spec-design optional. Wireframes → tokens + gradeable screens.
|
|
93
93
|
```
|
|
94
94
|
|
|
95
95
|
**Pick one front door, once per project.** Starting from an idea with no code yet? Run
|
|
96
96
|
`tiny-spec-scope` — it interviews the idea into a `BREAKDOWN.md`, a flat list of
|
|
97
|
-
Features
|
|
97
|
+
well-defined Features with draft acceptance criteria. Working in a codebase that already
|
|
98
98
|
exists? Run `tiny-spec-adopt` — it reads your repo and derives the constitution from
|
|
99
99
|
what's actually there: your real lint and test commands, your real layout, your real
|
|
100
100
|
conventions. Have a single known ticket in a project that's already set up? Skip both
|
|
@@ -110,7 +110,7 @@ receipt rather than the adjective:
|
|
|
110
110
|
|
|
111
111
|
| | skills / commands | agents | config | artifacts per feature |
|
|
112
112
|
|---|---|---|---|---|
|
|
113
|
-
| **tiny-spec** | **7** (3 core + 1 router + 3 optional) | **2** | **none** | **`SPEC` `PLAN
|
|
113
|
+
| **tiny-spec** | **7** (3 core + 1 router + 3 optional) | **2** | **none** | **`SPEC` `PLAN`** |
|
|
114
114
|
| [GitHub Spec Kit](https://github.com/github/spec-kit) | 10 | — | `specify init` | `spec` `plan` `tasks` `checklist` `constitution` `research` `data-model` `contracts/` `quickstart` |
|
|
115
115
|
| [OpenSpec](https://github.com/Fission-AI/OpenSpec) | 12 | — | `.openspec.yaml` | `proposal` `design` `tasks` `specs/` |
|
|
116
116
|
| [BMAD-METHOD](https://github.com/bmad-code-org/BMAD-METHOD) | 58 | 5 personas | 35 × `customize.toml` | `PRD` `architecture` `epics` `stories` `UX` `brief` `sprint-plan` |
|
|
@@ -197,7 +197,7 @@ uvx tiny-spec install
|
|
|
197
197
|
Restart Claude Code so it picks up the new skills, then run the flow in your project:
|
|
198
198
|
|
|
199
199
|
```
|
|
200
|
-
/tiny-spec-scope # starting from an idea: interview it into
|
|
200
|
+
/tiny-spec-scope # starting from an idea: interview it into features (BREAKDOWN.md)
|
|
201
201
|
/tiny-spec-adopt # starting from a codebase: derive the constitution from real code
|
|
202
202
|
/tiny-spec-create # capture intent and requirements (binds a ticket, optional)
|
|
203
203
|
/tiny-spec-plan # design it, harden the constitution, slice the task list
|
|
@@ -219,10 +219,10 @@ forward. It writes nothing itself, it only delegates. By default it **stops befo
|
|
|
219
219
|
Ask it to build and it goes all the way instead:
|
|
220
220
|
|
|
221
221
|
```
|
|
222
|
-
/tiny-spec-run build the backlog # per
|
|
222
|
+
/tiny-spec-run build the backlog # per feature: branch → plan → build → merge → next
|
|
223
223
|
```
|
|
224
224
|
|
|
225
|
-
It reads your `BREAKDOWN.md` (or a list you paste) and works the
|
|
225
|
+
It reads your `BREAKDOWN.md` (or a list you paste) and works the features one after
|
|
226
226
|
another, merging each finished branch into `main` locally before starting the next —
|
|
227
227
|
until it's done or reaches a **terminal state** it names out loud. See
|
|
228
228
|
[Working a whole list](#working-a-whole-list). Which of the two it does is decided from
|
|
@@ -262,8 +262,8 @@ or install one set at a time.
|
|
|
262
262
|
### See a finished run first
|
|
263
263
|
|
|
264
264
|
[`examples/todo-cli/`](examples/todo-cli/) is a real run of the flow on one small
|
|
265
|
-
ticket, committed verbatim — the `TICKET.md` that went in, the `SPEC.md`, `PLAN.md
|
|
266
|
-
|
|
265
|
+
ticket, committed verbatim — the `TICKET.md` that went in, the `SPEC.md`, `PLAN.md`
|
|
266
|
+
and `constitution.md` the suite wrote, and the code and tests it produced.
|
|
267
267
|
The tests pass; you can clone it and run the gate yourself.
|
|
268
268
|
|
|
269
269
|
## How it works
|
|
@@ -464,7 +464,7 @@ proved the same thing repeatedly and was the slowest part of the loop.
|
|
|
464
464
|
|
|
465
465
|
```mermaid
|
|
466
466
|
flowchart TB
|
|
467
|
-
SPEC[SPEC.md<br/>intent] --> PLAN[PLAN.md<br/>design] --> TASKS[
|
|
467
|
+
SPEC[SPEC.md<br/>intent] --> PLAN[PLAN.md<br/>design] --> TASKS[PLAN.md ## Tasks<br/>checklist]
|
|
468
468
|
|
|
469
469
|
TASKS -->|pause: set| H[Halt — paused<br/>task stays unchecked]
|
|
470
470
|
TASKS --> P[Plan task]
|
|
@@ -498,40 +498,39 @@ resumes from the checklist state.
|
|
|
498
498
|
### Working a whole list
|
|
499
499
|
|
|
500
500
|
Ask `/tiny-spec-run` to build — "build the backlog", "work through the breakdown",
|
|
501
|
-
"spec it out and build it" — and it takes a list of
|
|
502
|
-
Per
|
|
501
|
+
"spec it out and build it" — and it takes a list of features and works them in batches.
|
|
502
|
+
Per feature it does the same four moves:
|
|
503
503
|
|
|
504
504
|
```
|
|
505
505
|
cut a branch from main → walk the chain → tiny-spec-build → merge back to main
|
|
506
506
|
```
|
|
507
507
|
|
|
508
|
-
Each branch is cut **fresh from main**, so a later
|
|
508
|
+
Each branch is cut **fresh from main**, so a later feature sees the earlier ones already
|
|
509
509
|
merged — which is what makes an ordered list build correctly.
|
|
510
510
|
|
|
511
|
-
**Independent
|
|
511
|
+
**Independent features build at the same time.** A feature can declare what it must follow
|
|
512
512
|
with a `needs:` line in `BREAKDOWN.md`; everything with no unmet `needs:` forms a batch
|
|
513
|
-
and builds **concurrently, one git worktree per
|
|
513
|
+
and builds **concurrently, one git worktree per feature**, three at a time by default.
|
|
514
514
|
The batch merges, then the next one starts.
|
|
515
515
|
|
|
516
516
|
```
|
|
517
|
-
## Feature:
|
|
517
|
+
## Feature: expose both helpers on a CLI slug: cli
|
|
518
518
|
|
|
519
|
-
-
|
|
520
|
-
|
|
521
|
-
- needs: slugify, wordwrap
|
|
519
|
+
- AC: `textkit slugify "Hi There"` prints "hi-there"
|
|
520
|
+
- needs: slugify, wordwrap
|
|
522
521
|
```
|
|
523
522
|
|
|
524
|
-
Omit `needs:` when a
|
|
523
|
+
Omit `needs:` when a feature stands alone — that's the common case, and the field is meant
|
|
525
524
|
to be rare. A `needs:` you didn't need costs you parallelism forever; one you missed
|
|
526
525
|
costs a single merge conflict, which the run already catches and halts on. You can also
|
|
527
526
|
just name the set yourself at invocation ("build these three at once"), which overrides
|
|
528
|
-
the graph. A cycle, or a `needs:` naming a
|
|
527
|
+
the graph. A cycle, or a `needs:` naming a feature that isn't there, stops the run rather
|
|
529
528
|
than being guessed past.
|
|
530
529
|
|
|
531
|
-
**Tasks *inside* a
|
|
532
|
-
the last landed, so they stay strictly sequential. Parallelism is across
|
|
530
|
+
**Tasks *inside* a feature never run in parallel.** They share files and each one assumes
|
|
531
|
+
the last landed, so they stay strictly sequential. Parallelism is across features only.
|
|
533
532
|
|
|
534
|
-
**The list is `BREAKDOWN.md` by default** — its
|
|
533
|
+
**The list is `BREAKDOWN.md` by default** — its `## Feature:` entries, in file order,
|
|
535
534
|
each already carrying a `slug:` (the branch and directory name) and `AC:` lines. Paste
|
|
536
535
|
a list at invocation instead and that wins; but a bare feature name has no acceptance
|
|
537
536
|
criteria, so `tiny-spec-create` will interview you when it reaches it. That's the
|
|
@@ -541,26 +540,26 @@ honest trade: a breakdown runs unattended, a pasted list is supervised.
|
|
|
541
540
|
|
|
542
541
|
| | |
|
|
543
542
|
|---|---|
|
|
544
|
-
| `done` | every
|
|
543
|
+
| `done` | every feature built **and merged** |
|
|
545
544
|
| `blocked` | an upstream document is wrong — go fix the spec or the plan |
|
|
546
545
|
| `exhausted` | a task stayed red past two fix attempts |
|
|
547
546
|
| `paused` | it reached a `pause:` point |
|
|
548
547
|
| `fork` | a real either/or the plan doesn't answer |
|
|
549
|
-
| `conflict` | a
|
|
548
|
+
| `conflict` | a feature's branch wouldn't merge cleanly |
|
|
550
549
|
|
|
551
|
-
**Only `done` means the work is built** — and in a
|
|
552
|
-
Stopping at
|
|
550
|
+
**Only `done` means the work is built** — and in a feature run, that means *all* of them.
|
|
551
|
+
Stopping at feature 2 of 7 and reporting "done" is what autonomous loops get wrong most
|
|
553
552
|
often, so the state is always named alongside what merged and what's still untouched.
|
|
554
553
|
|
|
555
554
|
**A halt stops the lane it happened in, and ends the run after that batch.** Its siblings
|
|
556
555
|
were declared independent, so they finish and merge — killing working lanes because one
|
|
557
|
-
failed throws away good work. But the run does not start the next batch: later
|
|
556
|
+
failed throws away good work. But the run does not start the next batch: later features
|
|
558
557
|
usually assume the earlier ones landed, so skipping ahead past a failure just produces a
|
|
559
|
-
second, more confusing failure downstream. With more than one lane you get each
|
|
558
|
+
second, more confusing failure downstream. With more than one lane you get each feature's
|
|
560
559
|
own state, and the run's state is the worst of them — four green lanes and one `blocked`
|
|
561
560
|
is a `blocked` run.
|
|
562
561
|
|
|
563
|
-
**Pause points are technical, not per-
|
|
562
|
+
**Pause points are technical, not per-feature.** Any task can carry a `pause:` line, and
|
|
564
563
|
the build halts *before* running it:
|
|
565
564
|
|
|
566
565
|
```
|
|
@@ -572,7 +571,7 @@ the build halts *before* running it:
|
|
|
572
571
|
`tiny-spec-plan` proposes these for genuinely irreversible work — migrations,
|
|
573
572
|
destructive file operations, a new dependency, an auth boundary, a public API contract.
|
|
574
573
|
You can also give the run a standing policy up front ("halt before anything that touches
|
|
575
|
-
auth") and it gets applied as each
|
|
574
|
+
auth") and it gets applied as each feature's tasks are sliced.
|
|
576
575
|
|
|
577
576
|
**What it will not do to your repo.** It runs exactly seven git commands — `switch`,
|
|
578
577
|
`switch -c`, `merge --no-ff`, `merge --abort`, `worktree add`, `worktree list`, and
|
|
@@ -584,11 +583,11 @@ the merge alone and tells you the undo command rather than running it — and it
|
|
|
584
583
|
back the `git worktree remove` commands for the lanes instead of running those either,
|
|
585
584
|
since a halted lane's worktree is the tree you need to look at.
|
|
586
585
|
|
|
587
|
-
**Walk away and come back.** Progress isn't written down, it's derived: a
|
|
588
|
-
ticked `
|
|
586
|
+
**Walk away and come back.** Progress isn't written down, it's derived: a feature whose
|
|
587
|
+
ticked `## Tasks` is on `main` is done, a `.spec/<slug>/` with an unchecked task is in
|
|
589
588
|
progress, no directory means not started. Ask again tomorrow in a fresh session and it
|
|
590
589
|
picks up where it stopped. No run-state file, no lock, no budget to configure — the
|
|
591
|
-
|
|
590
|
+
feature list *is* the budget.
|
|
592
591
|
|
|
593
592
|
**It never fixes a blocker for you.** A blocker means one of your documents is wrong,
|
|
594
593
|
and a run allowed to rewrite the requirement its own task just failed would be grading
|
|
@@ -613,7 +612,7 @@ It is namespaced per ticket, with a shared spine at the root:
|
|
|
613
612
|
constitution.md project-wide, shared across tickets
|
|
614
613
|
memory.md operational lessons, shared across tickets
|
|
615
614
|
<ticket-id>/ one directory per ticket (PROJ-123/, gh-42/, …)
|
|
616
|
-
SPEC.md PLAN.md
|
|
615
|
+
SPEC.md PLAN.md decisions.md (PLAN.md ends in the ## Tasks checklist)
|
|
617
616
|
```
|
|
618
617
|
|
|
619
618
|
`BREAKDOWN.md` and `design/` sit at your project root rather than inside `.spec/`,
|
|
@@ -34,13 +34,13 @@ committed.
|
|
|
34
34
|
That core is **three skills and two agents**. In front of it sit **two front doors** —
|
|
35
35
|
pick the one that matches where you're starting. Over the top sits **one router**,
|
|
36
36
|
`tiny-spec-run`, which drives the chain and, when you ask it to, works a whole list of
|
|
37
|
-
|
|
37
|
+
features through to merged code. No config file, no build step.
|
|
38
38
|
|
|
39
39
|
```
|
|
40
40
|
GREENFIELD BROWNFIELD
|
|
41
41
|
starting from an idea starting from a codebase
|
|
42
42
|
tiny-spec-scope tiny-spec-adopt
|
|
43
|
-
idea → Features
|
|
43
|
+
idea → Features real code → constitution
|
|
44
44
|
BREAKDOWN.md constitution.md
|
|
45
45
|
\ /
|
|
46
46
|
└───────────┬───────────┘
|
|
@@ -48,16 +48,16 @@ stories through to merged code. No config file, no build step.
|
|
|
48
48
|
tiny-spec-create → tiny-spec-plan → tiny-spec-build
|
|
49
49
|
intent design + tasks per-task loop
|
|
50
50
|
SPEC.md PLAN.md plan → implement
|
|
51
|
-
|
|
51
|
+
(+ ## Tasks) → review → commit
|
|
52
52
|
|
|
53
53
|
tiny-spec-run one router. Walks the chain and stops before build —
|
|
54
|
-
or, asked to, builds each
|
|
54
|
+
or, asked to, builds each feature and merges it.
|
|
55
55
|
tiny-spec-design optional. Wireframes → tokens + gradeable screens.
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
**Pick one front door, once per project.** Starting from an idea with no code yet? Run
|
|
59
59
|
`tiny-spec-scope` — it interviews the idea into a `BREAKDOWN.md`, a flat list of
|
|
60
|
-
Features
|
|
60
|
+
well-defined Features with draft acceptance criteria. Working in a codebase that already
|
|
61
61
|
exists? Run `tiny-spec-adopt` — it reads your repo and derives the constitution from
|
|
62
62
|
what's actually there: your real lint and test commands, your real layout, your real
|
|
63
63
|
conventions. Have a single known ticket in a project that's already set up? Skip both
|
|
@@ -73,7 +73,7 @@ receipt rather than the adjective:
|
|
|
73
73
|
|
|
74
74
|
| | skills / commands | agents | config | artifacts per feature |
|
|
75
75
|
|---|---|---|---|---|
|
|
76
|
-
| **tiny-spec** | **7** (3 core + 1 router + 3 optional) | **2** | **none** | **`SPEC` `PLAN
|
|
76
|
+
| **tiny-spec** | **7** (3 core + 1 router + 3 optional) | **2** | **none** | **`SPEC` `PLAN`** |
|
|
77
77
|
| [GitHub Spec Kit](https://github.com/github/spec-kit) | 10 | — | `specify init` | `spec` `plan` `tasks` `checklist` `constitution` `research` `data-model` `contracts/` `quickstart` |
|
|
78
78
|
| [OpenSpec](https://github.com/Fission-AI/OpenSpec) | 12 | — | `.openspec.yaml` | `proposal` `design` `tasks` `specs/` |
|
|
79
79
|
| [BMAD-METHOD](https://github.com/bmad-code-org/BMAD-METHOD) | 58 | 5 personas | 35 × `customize.toml` | `PRD` `architecture` `epics` `stories` `UX` `brief` `sprint-plan` |
|
|
@@ -160,7 +160,7 @@ uvx tiny-spec install
|
|
|
160
160
|
Restart Claude Code so it picks up the new skills, then run the flow in your project:
|
|
161
161
|
|
|
162
162
|
```
|
|
163
|
-
/tiny-spec-scope # starting from an idea: interview it into
|
|
163
|
+
/tiny-spec-scope # starting from an idea: interview it into features (BREAKDOWN.md)
|
|
164
164
|
/tiny-spec-adopt # starting from a codebase: derive the constitution from real code
|
|
165
165
|
/tiny-spec-create # capture intent and requirements (binds a ticket, optional)
|
|
166
166
|
/tiny-spec-plan # design it, harden the constitution, slice the task list
|
|
@@ -182,10 +182,10 @@ forward. It writes nothing itself, it only delegates. By default it **stops befo
|
|
|
182
182
|
Ask it to build and it goes all the way instead:
|
|
183
183
|
|
|
184
184
|
```
|
|
185
|
-
/tiny-spec-run build the backlog # per
|
|
185
|
+
/tiny-spec-run build the backlog # per feature: branch → plan → build → merge → next
|
|
186
186
|
```
|
|
187
187
|
|
|
188
|
-
It reads your `BREAKDOWN.md` (or a list you paste) and works the
|
|
188
|
+
It reads your `BREAKDOWN.md` (or a list you paste) and works the features one after
|
|
189
189
|
another, merging each finished branch into `main` locally before starting the next —
|
|
190
190
|
until it's done or reaches a **terminal state** it names out loud. See
|
|
191
191
|
[Working a whole list](#working-a-whole-list). Which of the two it does is decided from
|
|
@@ -225,8 +225,8 @@ or install one set at a time.
|
|
|
225
225
|
### See a finished run first
|
|
226
226
|
|
|
227
227
|
[`examples/todo-cli/`](examples/todo-cli/) is a real run of the flow on one small
|
|
228
|
-
ticket, committed verbatim — the `TICKET.md` that went in, the `SPEC.md`, `PLAN.md
|
|
229
|
-
|
|
228
|
+
ticket, committed verbatim — the `TICKET.md` that went in, the `SPEC.md`, `PLAN.md`
|
|
229
|
+
and `constitution.md` the suite wrote, and the code and tests it produced.
|
|
230
230
|
The tests pass; you can clone it and run the gate yourself.
|
|
231
231
|
|
|
232
232
|
## How it works
|
|
@@ -427,7 +427,7 @@ proved the same thing repeatedly and was the slowest part of the loop.
|
|
|
427
427
|
|
|
428
428
|
```mermaid
|
|
429
429
|
flowchart TB
|
|
430
|
-
SPEC[SPEC.md<br/>intent] --> PLAN[PLAN.md<br/>design] --> TASKS[
|
|
430
|
+
SPEC[SPEC.md<br/>intent] --> PLAN[PLAN.md<br/>design] --> TASKS[PLAN.md ## Tasks<br/>checklist]
|
|
431
431
|
|
|
432
432
|
TASKS -->|pause: set| H[Halt — paused<br/>task stays unchecked]
|
|
433
433
|
TASKS --> P[Plan task]
|
|
@@ -461,40 +461,39 @@ resumes from the checklist state.
|
|
|
461
461
|
### Working a whole list
|
|
462
462
|
|
|
463
463
|
Ask `/tiny-spec-run` to build — "build the backlog", "work through the breakdown",
|
|
464
|
-
"spec it out and build it" — and it takes a list of
|
|
465
|
-
Per
|
|
464
|
+
"spec it out and build it" — and it takes a list of features and works them in batches.
|
|
465
|
+
Per feature it does the same four moves:
|
|
466
466
|
|
|
467
467
|
```
|
|
468
468
|
cut a branch from main → walk the chain → tiny-spec-build → merge back to main
|
|
469
469
|
```
|
|
470
470
|
|
|
471
|
-
Each branch is cut **fresh from main**, so a later
|
|
471
|
+
Each branch is cut **fresh from main**, so a later feature sees the earlier ones already
|
|
472
472
|
merged — which is what makes an ordered list build correctly.
|
|
473
473
|
|
|
474
|
-
**Independent
|
|
474
|
+
**Independent features build at the same time.** A feature can declare what it must follow
|
|
475
475
|
with a `needs:` line in `BREAKDOWN.md`; everything with no unmet `needs:` forms a batch
|
|
476
|
-
and builds **concurrently, one git worktree per
|
|
476
|
+
and builds **concurrently, one git worktree per feature**, three at a time by default.
|
|
477
477
|
The batch merges, then the next one starts.
|
|
478
478
|
|
|
479
479
|
```
|
|
480
|
-
## Feature:
|
|
480
|
+
## Feature: expose both helpers on a CLI slug: cli
|
|
481
481
|
|
|
482
|
-
-
|
|
483
|
-
|
|
484
|
-
- needs: slugify, wordwrap
|
|
482
|
+
- AC: `textkit slugify "Hi There"` prints "hi-there"
|
|
483
|
+
- needs: slugify, wordwrap
|
|
485
484
|
```
|
|
486
485
|
|
|
487
|
-
Omit `needs:` when a
|
|
486
|
+
Omit `needs:` when a feature stands alone — that's the common case, and the field is meant
|
|
488
487
|
to be rare. A `needs:` you didn't need costs you parallelism forever; one you missed
|
|
489
488
|
costs a single merge conflict, which the run already catches and halts on. You can also
|
|
490
489
|
just name the set yourself at invocation ("build these three at once"), which overrides
|
|
491
|
-
the graph. A cycle, or a `needs:` naming a
|
|
490
|
+
the graph. A cycle, or a `needs:` naming a feature that isn't there, stops the run rather
|
|
492
491
|
than being guessed past.
|
|
493
492
|
|
|
494
|
-
**Tasks *inside* a
|
|
495
|
-
the last landed, so they stay strictly sequential. Parallelism is across
|
|
493
|
+
**Tasks *inside* a feature never run in parallel.** They share files and each one assumes
|
|
494
|
+
the last landed, so they stay strictly sequential. Parallelism is across features only.
|
|
496
495
|
|
|
497
|
-
**The list is `BREAKDOWN.md` by default** — its
|
|
496
|
+
**The list is `BREAKDOWN.md` by default** — its `## Feature:` entries, in file order,
|
|
498
497
|
each already carrying a `slug:` (the branch and directory name) and `AC:` lines. Paste
|
|
499
498
|
a list at invocation instead and that wins; but a bare feature name has no acceptance
|
|
500
499
|
criteria, so `tiny-spec-create` will interview you when it reaches it. That's the
|
|
@@ -504,26 +503,26 @@ honest trade: a breakdown runs unattended, a pasted list is supervised.
|
|
|
504
503
|
|
|
505
504
|
| | |
|
|
506
505
|
|---|---|
|
|
507
|
-
| `done` | every
|
|
506
|
+
| `done` | every feature built **and merged** |
|
|
508
507
|
| `blocked` | an upstream document is wrong — go fix the spec or the plan |
|
|
509
508
|
| `exhausted` | a task stayed red past two fix attempts |
|
|
510
509
|
| `paused` | it reached a `pause:` point |
|
|
511
510
|
| `fork` | a real either/or the plan doesn't answer |
|
|
512
|
-
| `conflict` | a
|
|
511
|
+
| `conflict` | a feature's branch wouldn't merge cleanly |
|
|
513
512
|
|
|
514
|
-
**Only `done` means the work is built** — and in a
|
|
515
|
-
Stopping at
|
|
513
|
+
**Only `done` means the work is built** — and in a feature run, that means *all* of them.
|
|
514
|
+
Stopping at feature 2 of 7 and reporting "done" is what autonomous loops get wrong most
|
|
516
515
|
often, so the state is always named alongside what merged and what's still untouched.
|
|
517
516
|
|
|
518
517
|
**A halt stops the lane it happened in, and ends the run after that batch.** Its siblings
|
|
519
518
|
were declared independent, so they finish and merge — killing working lanes because one
|
|
520
|
-
failed throws away good work. But the run does not start the next batch: later
|
|
519
|
+
failed throws away good work. But the run does not start the next batch: later features
|
|
521
520
|
usually assume the earlier ones landed, so skipping ahead past a failure just produces a
|
|
522
|
-
second, more confusing failure downstream. With more than one lane you get each
|
|
521
|
+
second, more confusing failure downstream. With more than one lane you get each feature's
|
|
523
522
|
own state, and the run's state is the worst of them — four green lanes and one `blocked`
|
|
524
523
|
is a `blocked` run.
|
|
525
524
|
|
|
526
|
-
**Pause points are technical, not per-
|
|
525
|
+
**Pause points are technical, not per-feature.** Any task can carry a `pause:` line, and
|
|
527
526
|
the build halts *before* running it:
|
|
528
527
|
|
|
529
528
|
```
|
|
@@ -535,7 +534,7 @@ the build halts *before* running it:
|
|
|
535
534
|
`tiny-spec-plan` proposes these for genuinely irreversible work — migrations,
|
|
536
535
|
destructive file operations, a new dependency, an auth boundary, a public API contract.
|
|
537
536
|
You can also give the run a standing policy up front ("halt before anything that touches
|
|
538
|
-
auth") and it gets applied as each
|
|
537
|
+
auth") and it gets applied as each feature's tasks are sliced.
|
|
539
538
|
|
|
540
539
|
**What it will not do to your repo.** It runs exactly seven git commands — `switch`,
|
|
541
540
|
`switch -c`, `merge --no-ff`, `merge --abort`, `worktree add`, `worktree list`, and
|
|
@@ -547,11 +546,11 @@ the merge alone and tells you the undo command rather than running it — and it
|
|
|
547
546
|
back the `git worktree remove` commands for the lanes instead of running those either,
|
|
548
547
|
since a halted lane's worktree is the tree you need to look at.
|
|
549
548
|
|
|
550
|
-
**Walk away and come back.** Progress isn't written down, it's derived: a
|
|
551
|
-
ticked `
|
|
549
|
+
**Walk away and come back.** Progress isn't written down, it's derived: a feature whose
|
|
550
|
+
ticked `## Tasks` is on `main` is done, a `.spec/<slug>/` with an unchecked task is in
|
|
552
551
|
progress, no directory means not started. Ask again tomorrow in a fresh session and it
|
|
553
552
|
picks up where it stopped. No run-state file, no lock, no budget to configure — the
|
|
554
|
-
|
|
553
|
+
feature list *is* the budget.
|
|
555
554
|
|
|
556
555
|
**It never fixes a blocker for you.** A blocker means one of your documents is wrong,
|
|
557
556
|
and a run allowed to rewrite the requirement its own task just failed would be grading
|
|
@@ -576,7 +575,7 @@ It is namespaced per ticket, with a shared spine at the root:
|
|
|
576
575
|
constitution.md project-wide, shared across tickets
|
|
577
576
|
memory.md operational lessons, shared across tickets
|
|
578
577
|
<ticket-id>/ one directory per ticket (PROJ-123/, gh-42/, …)
|
|
579
|
-
SPEC.md PLAN.md
|
|
578
|
+
SPEC.md PLAN.md decisions.md (PLAN.md ends in the ## Tasks checklist)
|
|
580
579
|
```
|
|
581
580
|
|
|
582
581
|
`BREAKDOWN.md` and `design/` sit at your project root rather than inside `.spec/`,
|
|
@@ -17,9 +17,9 @@ Everything you need and nothing you don't:
|
|
|
17
17
|
|
|
18
18
|
- **the working directory** to operate in. Every path you read, write, or run a command
|
|
19
19
|
against resolves against it. It may be a **git worktree** rather than the main checkout
|
|
20
|
-
— a build can run several
|
|
20
|
+
— a build can run several features at once, each in its own worktree. **Never read or
|
|
21
21
|
write outside the directory you were given**, and never `cd` to a sibling worktree to
|
|
22
|
-
"check something": another
|
|
22
|
+
"check something": another feature is being built there right now, and what you find will
|
|
23
23
|
be wrong by the time you act on it;
|
|
24
24
|
- the **task id**, **description**, and **acceptance** (the outcome that proves it done);
|
|
25
25
|
- a **`files:` hint** — likely paths to touch (guidance, not a hard boundary);
|
|
@@ -15,8 +15,8 @@ back to `tiny-spec-build`; return data, not pleasantries.
|
|
|
15
15
|
|
|
16
16
|
- **the working directory** to operate in — every path and every gate command resolves
|
|
17
17
|
against it. It may be a **git worktree** rather than the main checkout, since a build
|
|
18
|
-
can run several
|
|
19
|
-
directory you were given**: a sibling worktree holds a different
|
|
18
|
+
can run several features at once. **Never read, write, or run a gate outside the
|
|
19
|
+
directory you were given**: a sibling worktree holds a different feature mid-build, and
|
|
20
20
|
measuring it would make your verdict meaningless;
|
|
21
21
|
- the **task id**, **description**, and **acceptance** (the outcome that must hold);
|
|
22
22
|
- the full **constitution** (`constitution.md`) — especially **Guiding invariants**,
|
|
@@ -87,10 +87,10 @@ Each case runs in a throwaway sandbox seeded with `IDEA.md` and the vendored ski
|
|
|
87
87
|
### What gets measured
|
|
88
88
|
|
|
89
89
|
- **structural conformance** (deterministic) — BREAKDOWN has Problem and
|
|
90
|
-
Goal & non-goals filled, a Decisions block, ≥1 Feature,
|
|
90
|
+
Goal & non-goals filled, a Decisions block, ≥1 Feature, each with a slug and ≥1 AC; the
|
|
91
91
|
planning skills left no `.spec/` behind.
|
|
92
92
|
- **hand-off integrity** (LLM judge) — **coverage** (every PRD capability lands in ≥1
|
|
93
|
-
|
|
93
|
+
feature, nothing dropped) and **no fabrication** (every feature traces to a capability,
|
|
94
94
|
nothing invented). These are the high-value signals; a case PASSes only if structural
|
|
95
95
|
conformance holds *and* the judge confirms both.
|
|
96
96
|
- **quality** (LLM judge, reported not gated) — atomicity / user-observable phrasing,
|
|
@@ -10,6 +10,9 @@ workflow generates before you run it on your own work.
|
|
|
10
10
|
> retouched to match the current artifact formats — a doctored example would defeat
|
|
11
11
|
> the point. Later versions add a `## Design` section to `SPEC.md` (unused here: this
|
|
12
12
|
> is a CLI with no design surface) and richer status flags. The shape is the same.
|
|
13
|
+
> One format move was applied after the fact: in 2.0 the checklist stopped being its
|
|
14
|
+
> own `tasks.md` and became `PLAN.md`'s `## Tasks` section, so the original `tasks.md`
|
|
15
|
+
> was moved there verbatim — same tasks, same ticks, no content edited.
|
|
13
16
|
|
|
14
17
|
## What's here
|
|
15
18
|
|
|
@@ -20,14 +23,13 @@ TICKET.md the input — a small "todo CLI" ask
|
|
|
20
23
|
definition of done, and the verification gate
|
|
21
24
|
todo-cli/
|
|
22
25
|
SPEC.md intent + REQ-1..REQ-9 (what "done" means)
|
|
23
|
-
PLAN.md the design
|
|
24
|
-
|
|
26
|
+
PLAN.md the design, how each requirement is covered, and
|
|
27
|
+
the ordered ## Tasks checklist, all ticked [x]
|
|
25
28
|
todo.py the produced CLI (stdlib only, 117 lines)
|
|
26
29
|
test_todo.py the produced end-to-end test (129 lines)
|
|
27
30
|
```
|
|
28
31
|
|
|
29
|
-
Read them in flow order: `TICKET.md` → `SPEC.md` → `PLAN.md` → `
|
|
30
|
-
`todo.py`. The `constitution.md` is the persistent context injected into every task.
|
|
32
|
+
Read them in flow order: `TICKET.md` → `SPEC.md` → `PLAN.md` → `todo.py`. The `constitution.md` is the persistent context injected into every task.
|
|
31
33
|
|
|
32
34
|
## It passes its own gate
|
|
33
35
|
|
|
@@ -15,7 +15,7 @@ there, then stops. It does **not** create a ticket dir, write a `SPEC.md`, switc
|
|
|
15
15
|
branches, or modify a single line of source.
|
|
16
16
|
|
|
17
17
|
**Starting from a blank page instead?** Use `tiny-spec-scope` — it interviews an idea
|
|
18
|
-
into
|
|
18
|
+
into features. The two are the suite's two front doors, and you generally want exactly
|
|
19
19
|
one of them.
|
|
20
20
|
|
|
21
21
|
## The one thing that matters most
|
|
@@ -182,7 +182,7 @@ Say plainly that inferred sections need review before the first build.
|
|
|
182
182
|
A constitution change invalidates work reviewed against the old one, so after applying
|
|
183
183
|
any accepted change:
|
|
184
184
|
|
|
185
|
-
For **each** ticket dir under `.spec/` whose `
|
|
185
|
+
For **each** ticket dir under `.spec/` whose `PLAN.md` has checked tasks, set it
|
|
186
186
|
`status: stale` and log a `decisions.md` entry in that ticket, creating the file if
|
|
187
187
|
absent:
|
|
188
188
|
|