create-pathfinder 1.8.0 → 2.0.0
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.
- package/AGENTS.md +3 -1
- package/CLAUDE.md +20 -0
- package/README.md +383 -65
- package/context/ai-interaction.md +78 -39
- package/context/coding-standards.md +119 -60
- package/copy-list.json +1 -0
- package/package.json +2 -1
- package/roles/developer.md +37 -0
- package/roles/planner.md +38 -0
- package/roles/tester.md +40 -0
- package/skills/challenge-me/SKILL.md +11 -7
- package/skills/complete-feature/SKILL.md +16 -11
- package/skills/handoff/SKILL.md +24 -4
- package/skills/kickstart-pathfinder/SKILL.md +6 -1
- package/skills/learning-review/SKILL.md +9 -6
- package/skills/load-feature/SKILL.md +21 -11
- package/skills/prototype/SKILL.md +3 -1
- package/skills/quiz-me/SKILL.md +33 -7
- package/skills/review-feature/SKILL.md +19 -11
- package/skills/role/SKILL.md +33 -0
- package/skills/setup-tracker/SKILL.md +29 -61
- package/skills/start-feature/SKILL.md +19 -16
- package/skills/sync-tracker/SKILL.md +67 -106
- package/skills/teach-architecture/SKILL.md +6 -5
- package/skills/teach-feature/SKILL.md +11 -8
- package/skills/to-specs/SKILL.md +40 -28
- package/skills/whereami/SKILL.md +87 -0
- package/src/cli.mjs +2 -1
- package/src/install.mjs +5 -1
- package/src/kit.mjs +70 -1
- package/templates/CHANGELOG.template.md +2 -1
- package/templates/feature-spec.template.md +18 -80
- package/templates/history.template.md +12 -0
- package/templates/lesson.template.md +22 -51
- package/templates/project-overview.template.md +80 -145
- package/context/current-feature.md +0 -46
- package/context/features/example-feature-spec.md +0 -103
- package/context/history.md +0 -14
- package/context/learning/learner-profile.md +0 -35
- package/context/learning/lessons/.gitkeep +0 -0
- package/context/learning/progress.md +0 -28
- package/context/project-overview.md +0 -211
- package/templates/progress-entry.template.md +0 -23
- package/templates/tracker.template.md +0 -359
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
# Project Overview
|
|
2
|
-
|
|
3
|
-
> Describe the product, audience, intended feeling, and reason it should exist.
|
|
4
|
-
|
|
5
|
-
## Status
|
|
6
|
-
|
|
7
|
-
- Project: `[Project Name]`
|
|
8
|
-
- Stage: `[idea / prototype / MVP / production / maintenance]`
|
|
9
|
-
- Repo type: `[new / existing / application / library / service / monorepo / other]`
|
|
10
|
-
- Primary goal: `[success definition]`
|
|
11
|
-
- Prototype status: `[not required / recommended / in progress / approved / rejected / TBD]`
|
|
12
|
-
|
|
13
|
-
## Decision States
|
|
14
|
-
|
|
15
|
-
These four words describe a decision:
|
|
16
|
-
|
|
17
|
-
- `TBD` — human decision required
|
|
18
|
-
- `None` — intentionally excluded
|
|
19
|
-
- `N/A` — not applicable
|
|
20
|
-
- `Deferred` — intentionally postponed
|
|
21
|
-
|
|
22
|
-
## Record Status
|
|
23
|
-
|
|
24
|
-
A `Status` column describes the record, not the decision:
|
|
25
|
-
|
|
26
|
-
- `proposed` — written down, not yet approved by the human
|
|
27
|
-
- `accepted` — approved by the human
|
|
28
|
-
- `superseded` — replaced by a later decision, kept for history
|
|
29
|
-
|
|
30
|
-
The two answer different questions. `TBD` says nobody has decided yet. `proposed` says something was recorded for the human to approve. A recorded proposal is not an approved decision.
|
|
31
|
-
|
|
32
|
-
## Product Vision
|
|
33
|
-
|
|
34
|
-
- Problem:
|
|
35
|
-
- Primary user:
|
|
36
|
-
- First useful outcome:
|
|
37
|
-
- Distinctive quality:
|
|
38
|
-
- What this must avoid becoming:
|
|
39
|
-
|
|
40
|
-
## MVP Boundary
|
|
41
|
-
|
|
42
|
-
### In scope
|
|
43
|
-
|
|
44
|
-
- `[essential outcome]`
|
|
45
|
-
|
|
46
|
-
### Out of scope
|
|
47
|
-
|
|
48
|
-
- `[deferred outcome]`
|
|
49
|
-
|
|
50
|
-
### Success signals
|
|
51
|
-
|
|
52
|
-
- `[observable user, business, system, or learning signal]`
|
|
53
|
-
|
|
54
|
-
## Core Experience or System Flow
|
|
55
|
-
|
|
56
|
-
```text
|
|
57
|
-
starting state -> action/process -> useful result -> reason to return or continue
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## Requirements, Preferences, Constraints, and Open Decisions
|
|
61
|
-
|
|
62
|
-
| Type | Item | Notes |
|
|
63
|
-
| --- | --- | --- |
|
|
64
|
-
| Requirement | `[must be true]` | |
|
|
65
|
-
| Preference | `[desired but negotiable]` | |
|
|
66
|
-
| Constraint | `[limit or external obligation]` | |
|
|
67
|
-
| Open decision | `[TBD]` | |
|
|
68
|
-
|
|
69
|
-
## Recommended and Approved Technology
|
|
70
|
-
|
|
71
|
-
Recommended and approved choices both live here. `debate-me` and `kickstart-pathfinder` may record a choice before the human approves it; that row is marked `proposed` in `Status` and stays that way until it is `accepted`. Leave `Status` empty while the choice is still `TBD`.
|
|
72
|
-
|
|
73
|
-
| Layer | Choice | Reason | Status |
|
|
74
|
-
| --- | --- | --- | --- |
|
|
75
|
-
| Platform/runtime | `TBD` | | |
|
|
76
|
-
| Language(s) | `TBD` | | |
|
|
77
|
-
| UI/presentation | `TBD / N/A` | | |
|
|
78
|
-
| Backend/application layer | `TBD / None` | | |
|
|
79
|
-
| Data storage | `TBD / None` | | |
|
|
80
|
-
| Data access/ORM | `TBD / None` | | |
|
|
81
|
-
| Authentication | `TBD / None` | | |
|
|
82
|
-
| Authorization | `TBD / None` | | |
|
|
83
|
-
| API/integration style | `TBD / None` | | |
|
|
84
|
-
| State management | `TBD / N/A` | | |
|
|
85
|
-
| Testing | `TBD` | | |
|
|
86
|
-
| Build/package tooling | `TBD` | | |
|
|
87
|
-
| Deployment/runtime environment | `TBD` | | |
|
|
88
|
-
| Observability | `TBD / Deferred` | | |
|
|
89
|
-
| AI providers/models | `TBD / None` | | |
|
|
90
|
-
|
|
91
|
-
## Architecture
|
|
92
|
-
|
|
93
|
-
- Architecture style: `TBD`
|
|
94
|
-
- Repository shape: `TBD`
|
|
95
|
-
- Main boundaries/modules:
|
|
96
|
-
- Data/control flow:
|
|
97
|
-
- Important tradeoffs:
|
|
98
|
-
|
|
99
|
-
```text
|
|
100
|
-
[path or module] # purpose
|
|
101
|
-
[path or module] # purpose
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
## Prototype Direction
|
|
105
|
-
|
|
106
|
-
- Prototype needed: `[yes / no / TBD]`
|
|
107
|
-
- Type: `[experience / technical / diagram / mixed / N/A]`
|
|
108
|
-
- Assumption being validated:
|
|
109
|
-
- Output location:
|
|
110
|
-
- Review criteria:
|
|
111
|
-
- Approved direction:
|
|
112
|
-
- Elements explicitly not adopted into production:
|
|
113
|
-
|
|
114
|
-
## Delivery Workflow
|
|
115
|
-
|
|
116
|
-
| Area | Choice |
|
|
117
|
-
| --- | --- |
|
|
118
|
-
| Git workflow | `TBD` |
|
|
119
|
-
| Default/stable branch | `TBD` |
|
|
120
|
-
| Branch naming | `TBD / N/A` |
|
|
121
|
-
| Commit convention | `TBD / None` |
|
|
122
|
-
| Pull request policy | `TBD` |
|
|
123
|
-
| Merge strategy | `TBD` |
|
|
124
|
-
| CI/CD | `TBD / None` |
|
|
125
|
-
| Versioning | `TBD / None` |
|
|
126
|
-
| Changelog | `TBD / None` |
|
|
127
|
-
| Release process | `TBD / None` |
|
|
128
|
-
|
|
129
|
-
## Environments and Integrations
|
|
130
|
-
|
|
131
|
-
| Area | Choice | Notes |
|
|
132
|
-
| --- | --- | --- |
|
|
133
|
-
| Local development | `TBD` | |
|
|
134
|
-
| Preview/staging | `TBD / None` | |
|
|
135
|
-
| Production | `TBD / None` | |
|
|
136
|
-
| Environment configuration | `TBD` | |
|
|
137
|
-
| Secrets management | `TBD / N/A` | |
|
|
138
|
-
| External APIs/services | `TBD / None` | |
|
|
139
|
-
| Rate/cost limits | `TBD / N/A` | |
|
|
140
|
-
|
|
141
|
-
## Quality Priorities
|
|
142
|
-
|
|
143
|
-
Rank only what matters for this project.
|
|
144
|
-
|
|
145
|
-
1. `[priority]`
|
|
146
|
-
2. `[priority]`
|
|
147
|
-
3. `[priority]`
|
|
148
|
-
|
|
149
|
-
| Concern | Target or decision |
|
|
150
|
-
| --- | --- |
|
|
151
|
-
| Correctness/reliability | `TBD` |
|
|
152
|
-
| Security/privacy | `TBD / N/A` |
|
|
153
|
-
| Accessibility | `TBD / N/A` |
|
|
154
|
-
| Performance | `TBD / N/A` |
|
|
155
|
-
| Browser/platform support | `TBD / N/A` |
|
|
156
|
-
| Localization | `TBD / None` |
|
|
157
|
-
| Offline behavior | `TBD / N/A` |
|
|
158
|
-
|
|
159
|
-
## Core Domain Concepts
|
|
160
|
-
|
|
161
|
-
Describe durable concepts without assuming a language:
|
|
162
|
-
|
|
163
|
-
```text
|
|
164
|
-
Entity/Concept: Example
|
|
165
|
-
Required fields: id, name
|
|
166
|
-
Important states: draft, active, archived
|
|
167
|
-
Relationships: belongs to / contains / references
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
## Build, Test, and Run Commands
|
|
171
|
-
|
|
172
|
-
```text
|
|
173
|
-
install: TBD
|
|
174
|
-
run/dev: TBD
|
|
175
|
-
test: TBD
|
|
176
|
-
lint/static analysis: TBD
|
|
177
|
-
build/package: TBD
|
|
178
|
-
other verification: TBD
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
## Build Phases
|
|
182
|
-
|
|
183
|
-
| Phase | Goal | Visible or verifiable win |
|
|
184
|
-
| --- | --- | --- |
|
|
185
|
-
| 1 | Foundation | `[result]` |
|
|
186
|
-
| 2 | Core experience/system | `[result]` |
|
|
187
|
-
| 3 | Real data/integration | `[result]` |
|
|
188
|
-
| 4 | Quality and release readiness | `[result]` |
|
|
189
|
-
|
|
190
|
-
## Learning Goals
|
|
191
|
-
|
|
192
|
-
- What the human wants to understand:
|
|
193
|
-
- Preferred lesson format: `[HTML / MDX / Markdown / existing docs system / TBD]`
|
|
194
|
-
- Quiz preferences:
|
|
195
|
-
- Topics to emphasize:
|
|
196
|
-
- Topics to avoid over-explaining:
|
|
197
|
-
|
|
198
|
-
## Durable Decisions
|
|
199
|
-
|
|
200
|
-
| Date | Decision | Reason | Status |
|
|
201
|
-
| --- | --- | --- | --- |
|
|
202
|
-
| `[YYYY-MM-DD]` | `[decision]` | `[reason]` | `[proposed / accepted / superseded]` |
|
|
203
|
-
|
|
204
|
-
## Things To Avoid
|
|
205
|
-
|
|
206
|
-
- Building before critical decisions are understood.
|
|
207
|
-
- Treating recommendations as approval.
|
|
208
|
-
- Silently resolving `TBD` items.
|
|
209
|
-
- Turning prototype shortcuts into production defaults.
|
|
210
|
-
- Over-documenting temporary implementation detail.
|
|
211
|
-
- Creating feature specs too large for a focused LLM context window.
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
## Progress Update — [Date]
|
|
2
|
-
|
|
3
|
-
### Lesson
|
|
4
|
-
|
|
5
|
-
- Feature:
|
|
6
|
-
- Lesson file:
|
|
7
|
-
- Evidence reviewed:
|
|
8
|
-
|
|
9
|
-
### Concepts
|
|
10
|
-
|
|
11
|
-
| Concept | Previous | New | Evidence |
|
|
12
|
-
| --- | --- | --- | --- |
|
|
13
|
-
|
|
14
|
-
### Misconceptions or Gaps
|
|
15
|
-
|
|
16
|
-
- Gap:
|
|
17
|
-
- Correction:
|
|
18
|
-
- Recommended reinforcement:
|
|
19
|
-
|
|
20
|
-
### Next Review
|
|
21
|
-
|
|
22
|
-
- Topic:
|
|
23
|
-
- Suggested timing or trigger:
|
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
# Tracker
|
|
2
|
-
|
|
3
|
-
> Starting point for `context/tracker.md`. `setup-tracker` fills the placeholders
|
|
4
|
-
> and keeps **one** projection block, then deletes this blockquote.
|
|
5
|
-
>
|
|
6
|
-
> **The file's absence is the off switch.** Work Tracking is optional. A project
|
|
7
|
-
> with no `context/tracker.md` behaves exactly as it always has, and nothing in
|
|
8
|
-
> Pathfinder prompts for one. Do not ship this template's output unconfigured.
|
|
9
|
-
>
|
|
10
|
-
> **The backend-neutral model is everything between the two markers below** —
|
|
11
|
-
> from `pathfinder:model-start` down to `pathfinder:projection-boundary` — and it
|
|
12
|
-
> **must be byte-identical whichever projection is chosen.** Choosing a backend
|
|
13
|
-
> cuts below the projection boundary and nowhere else. Nothing inside the model
|
|
14
|
-
> may be *defined* in a backend's terms — an "issue number", a "label", a file
|
|
15
|
-
> path. Naming one in order to rule it out is not the same thing and is correct:
|
|
16
|
-
> "edges name keys, never tracker issue numbers" is the neutrality rule being
|
|
17
|
-
> stated, not a leak. The test is whether changing backend would change the
|
|
18
|
-
> sentence.
|
|
19
|
-
>
|
|
20
|
-
> The two paragraphs above the model marker are this project's own — the tracker
|
|
21
|
-
> it uses, and the rule that the repository wins. They are *not* claimed to be
|
|
22
|
-
> byte-identical across backends: the first one names the tracker and how an
|
|
23
|
-
> agent reaches it, so it necessarily differs.
|
|
24
|
-
|
|
25
|
-
This project tracks work in `[tracker name]`, at `[where it lives]`, reached by
|
|
26
|
-
`[how to reach it]`.
|
|
27
|
-
|
|
28
|
-
The repository is canonical. This tracker is a **one-way projection** of work
|
|
29
|
-
that already exists in `context/features/`. Never read status back out of the
|
|
30
|
-
tracker and into a spec. If the two disagree, the repository is right and the
|
|
31
|
-
tracker is stale.
|
|
32
|
-
|
|
33
|
-
<!-- pathfinder:model-start
|
|
34
|
-
Everything from here to the projection boundary is the backend-neutral model. It
|
|
35
|
-
is byte-identical in every configured project, whichever backend is chosen.
|
|
36
|
-
Nothing between the two markers may be defined in a backend's terms; naming one
|
|
37
|
-
to exclude it is correct and is not a leak.
|
|
38
|
-
-->
|
|
39
|
-
|
|
40
|
-
## What gets tracked
|
|
41
|
-
|
|
42
|
-
Only **approved feature specs**, from `to-specs` onward. Never track debate
|
|
43
|
-
notes, kickstart output, or prototypes. The one exception is a prototype that
|
|
44
|
-
gates a decision, which may be tracked as a single item phrased as the decision
|
|
45
|
-
it resolves, never as a deliverable.
|
|
46
|
-
|
|
47
|
-
## The work item
|
|
48
|
-
|
|
49
|
-
Every tracked thing is a **work item**. A work item has:
|
|
50
|
-
|
|
51
|
-
- a **key** — stable, assigned by Pathfinder, never by the tracker
|
|
52
|
-
- a **kind** — what sort of thing it is
|
|
53
|
-
- a **title** and a **body**
|
|
54
|
-
- zero or more **blocked-by** edges, naming other work items by key
|
|
55
|
-
- zero or more **tags**
|
|
56
|
-
- an ordered list of **chunks** (features only)
|
|
57
|
-
- a **parent** key (tickets only)
|
|
58
|
-
|
|
59
|
-
### Keys
|
|
60
|
-
|
|
61
|
-
A key looks like `pathfinder:<kind>/<id>`. For a feature spec, the id is the
|
|
62
|
-
spec's number: `context/features/06-docs-site-scaffold.md` is
|
|
63
|
-
`pathfinder:feature/06`.
|
|
64
|
-
|
|
65
|
-
Keys are how a work item is recognised on a later run. Record the key inside the
|
|
66
|
-
published item so it can be found again without keeping a local index. Put it in
|
|
67
|
-
a marker block that the tracker will not render to a human:
|
|
68
|
-
|
|
69
|
-
```text
|
|
70
|
-
<!-- pathfinder:work-item
|
|
71
|
-
key: pathfinder:feature/06
|
|
72
|
-
kind: feature
|
|
73
|
-
blocked-by: pathfinder:feature/03
|
|
74
|
-
tags: area:site, type:infra, agent:suitable
|
|
75
|
-
chunks-projection: checklist
|
|
76
|
-
-->
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
Match on the key alone. Never match on the title — titles are edited by humans
|
|
80
|
-
and a title match will create duplicates or overwrite the wrong item.
|
|
81
|
-
|
|
82
|
-
**The title is written once, when the item is created, and is never reconciled
|
|
83
|
-
afterwards.** It is human-owned from that point on. This is a decision, not an
|
|
84
|
-
oversight, and it follows from the rule above: humans edit titles, so a
|
|
85
|
-
projection that rewrote them would overwrite that edit on every run. Renaming
|
|
86
|
-
the spec changes the pointer to it in the body, not the title.
|
|
87
|
-
|
|
88
|
-
**Prose alone is not sufficient for identity.** This marker is the one
|
|
89
|
-
machine-stable token in an otherwise prose contract. Everything else here can be
|
|
90
|
-
reworded; this cannot be removed on the grounds that the config is "just prose".
|
|
91
|
-
Without it there is no way to recognise an item on a second run, and publishing
|
|
92
|
-
stops being idempotent.
|
|
93
|
-
|
|
94
|
-
### Kinds
|
|
95
|
-
|
|
96
|
-
Two kinds are defined.
|
|
97
|
-
|
|
98
|
-
- `feature` — one approved feature spec. One branch, one review, one merge.
|
|
99
|
-
- `ticket` — an independently assignable unit of execution inside a feature,
|
|
100
|
-
carrying its own blocked-by edges so that more than one agent can work a
|
|
101
|
-
feature at once. A ticket names its feature with `parent`.
|
|
102
|
-
|
|
103
|
-
**A ticket is not a delivery chunk.** Chunks are a planning device inside a spec;
|
|
104
|
-
tickets are units of execution. They may coincide, and they routinely will not: a
|
|
105
|
-
ticket may span several chunks, and a ticket may exist that belongs to no chunk
|
|
106
|
-
at all — a prefactor, or a decision that gates the rest. Nothing in this model
|
|
107
|
-
derives one from the other, and a projection that assumed `ticket == chunk` would
|
|
108
|
-
be wrong rather than simplified.
|
|
109
|
-
|
|
110
|
-
**Do not treat a chunk as permanently equal to a checkbox either.** Chunk
|
|
111
|
-
rendering is a *projection choice* named by `chunks-projection`, not a fact about
|
|
112
|
-
the model.
|
|
113
|
-
|
|
114
|
-
Feature and ticket are the **same work item**. They carry the same fields, the
|
|
115
|
-
same marker, the same edge semantics, the same tag model, and the same
|
|
116
|
-
idempotency rule. `chunks` is simply absent on a ticket, and `parent` is absent on
|
|
117
|
-
a feature — optional fields, not different shapes. **No rule anywhere may branch
|
|
118
|
-
on `kind`.**
|
|
119
|
-
|
|
120
|
-
### Parent
|
|
121
|
-
|
|
122
|
-
A ticket names the feature it belongs to with `parent`, a key. Parentage is
|
|
123
|
-
**not** a blocking edge and must never be rendered as one: a ticket is not
|
|
124
|
-
blocked by its feature. Rendering parentage as a blocker produces a graph that
|
|
125
|
-
never unblocks.
|
|
126
|
-
|
|
127
|
-
### Blocked-by edges
|
|
128
|
-
|
|
129
|
-
Edges name **keys**, never tracker issue numbers. Resolving a key to an issue
|
|
130
|
-
number is the projection's job, and the same edge must survive being pointed at a
|
|
131
|
-
different tracker.
|
|
132
|
-
|
|
133
|
-
An edge may name a work item that is **not in the set being published**. That is
|
|
134
|
-
normal — a feature can depend on one that was tracked earlier or not at all. Do
|
|
135
|
-
not drop such an edge and do not invent an item for it. Resolve it against the
|
|
136
|
-
tracker as a whole rather than against this run:
|
|
137
|
-
|
|
138
|
-
- if the key already has an item in the tracker, render that item's identifier,
|
|
139
|
-
exactly as an in-set edge is rendered;
|
|
140
|
-
- otherwise render the key and say plainly that it has no item here.
|
|
141
|
-
|
|
142
|
-
Being outside this run is not the same as being untracked, and an edge must not
|
|
143
|
-
claim it is.
|
|
144
|
-
|
|
145
|
-
Publish in dependency order, blockers first, so an edge can reference a real
|
|
146
|
-
identifier by the time it is written.
|
|
147
|
-
|
|
148
|
-
### Tags
|
|
149
|
-
|
|
150
|
-
A tag is `namespace:value`. The namespace says what kind of statement the tag is
|
|
151
|
-
making; the value is free text.
|
|
152
|
-
|
|
153
|
-
Namespaces in use here:
|
|
154
|
-
|
|
155
|
-
- `area` — the part of the system touched, e.g. `area:site`, `area:cli`
|
|
156
|
-
- `type` — the nature of the work, e.g. `type:infra`, `type:content`
|
|
157
|
-
- `priority` — only when the project actually uses one, e.g. `priority:now`
|
|
158
|
-
- `agent` — suitability for autonomous work, e.g. `agent:suitable`,
|
|
159
|
-
`agent:needs-human`
|
|
160
|
-
|
|
161
|
-
**Tags are backend-neutral.** The list above is the whole model. How a tag
|
|
162
|
-
becomes a label, a field, or a line of text is a projection concern.
|
|
163
|
-
|
|
164
|
-
**Respect what the tracker already has.** Before introducing any tag value,
|
|
165
|
-
list the values the tracker already carries. If one already means the same
|
|
166
|
-
thing, use it and record the mapping below rather than creating a
|
|
167
|
-
near-duplicate. Never invent a taxonomy the team did not ask for, and never
|
|
168
|
-
apply a tag that is not in the mapping table.
|
|
169
|
-
|
|
170
|
-
### From spec to work item
|
|
171
|
-
|
|
172
|
-
Every field above comes from the spec, and from nowhere else:
|
|
173
|
-
|
|
174
|
-
- **key** — `pathfinder:feature/<NN>`, from the spec's number.
|
|
175
|
-
- **kind** — `feature` for an approved feature spec.
|
|
176
|
-
- **title** — the spec's own title.
|
|
177
|
-
- **blocked-by** — the specs named under `## Dependencies`, each converted to
|
|
178
|
-
its key. A dependency that is not a feature spec — a decision, an external
|
|
179
|
-
system, `None` — produces no edge.
|
|
180
|
-
- **chunks** — the entries under `## Delivery Chunks`, in spec order.
|
|
181
|
-
- **tags** — **only** the values written in the spec's optional `## Tags`
|
|
182
|
-
section.
|
|
183
|
-
|
|
184
|
-
**Tags are never inferred.** Not from the title, not from the paths a spec
|
|
185
|
-
mentions, not from which part of the system it appears to touch. A spec with no
|
|
186
|
-
`## Tags` section has no tags, and an item published with none is correct and
|
|
187
|
-
expected — most projects never use them. Guessing a tag produces a taxonomy the
|
|
188
|
-
team did not choose, applied to work they did not classify, and it will look
|
|
189
|
-
authoritative on the board.
|
|
190
|
-
|
|
191
|
-
If a spec names a tag that this config's mapping table does not carry, **stop and
|
|
192
|
-
ask**. Do not apply it, and do not quietly drop it.
|
|
193
|
-
|
|
194
|
-
### Body composition
|
|
195
|
-
|
|
196
|
-
The body is a **pure function of the spec**. The same spec must produce the same
|
|
197
|
-
body on every run. This is not tidiness: re-publishing decides what to do by
|
|
198
|
-
comparing the body it would write now against the one already there, so a body
|
|
199
|
-
that varies between runs rewrites every item forever while appearing to work.
|
|
200
|
-
|
|
201
|
-
Compose it in this order, and **omit any section whose source is absent** rather
|
|
202
|
-
than emitting it empty:
|
|
203
|
-
|
|
204
|
-
1. a pointer to the spec this item projects
|
|
205
|
-
2. the blocked-by edges
|
|
206
|
-
3. the parent, on a ticket
|
|
207
|
-
4. the delivery chunks
|
|
208
|
-
5. the statement that the repository is canonical and that nothing here is read
|
|
209
|
-
back
|
|
210
|
-
6. the marker block, last
|
|
211
|
-
|
|
212
|
-
**Never include anything derived from the run rather than the spec** — no date,
|
|
213
|
-
no timestamp, no run counter, no tally of what changed, no note of who published
|
|
214
|
-
it. Each of those differs on the next run and each would make every item look
|
|
215
|
-
modified. Never re-wrap or re-summarise text taken from the spec: copy it the
|
|
216
|
-
same way every time, or the same spec produces two different bodies.
|
|
217
|
-
|
|
218
|
-
How each of these elements *renders* is a projection concern. The order, the
|
|
219
|
-
omission rule, and the absence of run-derived content are not.
|
|
220
|
-
|
|
221
|
-
<!-- pathfinder:projection-boundary
|
|
222
|
-
This marker closes the neutral model opened by `pathfinder:model-start`.
|
|
223
|
-
Everything below is one projection. Keep exactly one of the two blocks that
|
|
224
|
-
follow, and delete this marker, the model-start marker, and the block you did
|
|
225
|
-
not keep.
|
|
226
|
-
-->
|
|
227
|
-
|
|
228
|
-
## Projection to GitHub
|
|
229
|
-
|
|
230
|
-
*Keep this block for a GitHub Issues tracker; delete the local-files block below.*
|
|
231
|
-
|
|
232
|
-
- One work item → one issue.
|
|
233
|
-
- Title → the spec's title, prefixed with its number: `06 — Docs Site Scaffold`.
|
|
234
|
-
- The **spec pointer** → the first line of the body, naming the spec's path.
|
|
235
|
-
- The **repository-is-canonical statement** → a line near the end of the body,
|
|
236
|
-
before the marker, saying that nothing here is read back and that a ticked box
|
|
237
|
-
advances no state.
|
|
238
|
-
- The marker block goes at the **end** of the issue body.
|
|
239
|
-
- `blocked-by` → a `**Blocked by**` line naming each blocker as
|
|
240
|
-
`#<number> (<key>)`. A key with no issue in this repository renders as
|
|
241
|
-
`<key> — not tracked here`; a key that has one renders as `#<number> (<key>)`
|
|
242
|
-
whether or not it is part of the current run.
|
|
243
|
-
- `parent` → a `**Parent**` line naming the feature as `#<number> (<key>)`.
|
|
244
|
-
Never render parentage as a blocking edge.
|
|
245
|
-
- `chunks` under `chunks-projection: checklist` → a `## Delivery chunks` section
|
|
246
|
-
of `- [ ]` items in spec order. **A checked box means nothing to Pathfinder.**
|
|
247
|
-
The repository is canonical; a human ticking a box does not advance any state
|
|
248
|
-
and must never be read back.
|
|
249
|
-
- Tags → labels, via this mapping. Create a label only if nothing equivalent
|
|
250
|
-
exists. Replace the rows below with this project's own tags and the labels the
|
|
251
|
-
repository already carries.
|
|
252
|
-
|
|
253
|
-
| Tag | GitHub label | Colour |
|
|
254
|
-
|---|---|---|
|
|
255
|
-
| `area:site` | `area:site` | `1d76db` |
|
|
256
|
-
| `area:cli` | `area:cli` | `1d76db` |
|
|
257
|
-
| `type:infra` | `type:infra` | `5319e7` |
|
|
258
|
-
| `type:content` | `documentation` *(pre-existing — reused, not duplicated)* | `0075ca` |
|
|
259
|
-
| `agent:suitable` | `agent:suitable` | `0e8a16` |
|
|
260
|
-
| `agent:needs-human` | `agent:needs-human` | `d93f0b` |
|
|
261
|
-
|
|
262
|
-
### Publishing, and re-publishing
|
|
263
|
-
|
|
264
|
-
**Ask the human before the first write to this tracker in a session.** Creating
|
|
265
|
-
issues on a shared repository is outward-facing and is not covered by ordinary
|
|
266
|
-
file-edit approval.
|
|
267
|
-
|
|
268
|
-
Publishing is **idempotent**. Re-running must be safe and must be provably inert
|
|
269
|
-
when nothing changed:
|
|
270
|
-
|
|
271
|
-
1. Read every existing issue in the repository, open and closed, and index them
|
|
272
|
-
by the key in their marker block.
|
|
273
|
-
2. For each work item, if no issue carries its key, create one.
|
|
274
|
-
3. If an issue carries its key, compare the rendered body and the label set to
|
|
275
|
-
what would be published now. **If they are identical, do nothing at all** —
|
|
276
|
-
no edit, no comment, no label call. An unchanged item must produce zero
|
|
277
|
-
writes, not a write that happens to be a no-op.
|
|
278
|
-
|
|
279
|
-
**Compare normalized, never raw bytes.** A tracker is not obliged to hand a
|
|
280
|
-
body back exactly as it was sent, and APIs differ in whether they adjust
|
|
281
|
-
trailing whitespace. Where that happens, a naive byte comparison reports every
|
|
282
|
-
issue as changed on every run and rewrites all of them forever — which looks
|
|
283
|
-
like working sync and is not. Before comparing, strip trailing whitespace from
|
|
284
|
-
each line and collapse trailing blank lines at end of body, on **both** sides.
|
|
285
|
-
This costs nothing when the round-trip is exact, and is the difference between
|
|
286
|
-
inert and catastrophic when it is not. Compare label sets as sets, not as
|
|
287
|
-
ordered lists — the tracker does not preserve the order they were applied.
|
|
288
|
-
4. If they differ, edit that issue in place. Never close and recreate.
|
|
289
|
-
5. Never close an issue, never reopen one, and never touch an issue whose key is
|
|
290
|
-
absent from the current set — it belongs to work outside this run.
|
|
291
|
-
|
|
292
|
-
Report what was created, what was edited, and what was left alone.
|
|
293
|
-
|
|
294
|
-
## Projection to local files
|
|
295
|
-
|
|
296
|
-
*Keep this block for a local Markdown tracker; delete the GitHub block above.*
|
|
297
|
-
|
|
298
|
-
- One work item → one file, `.work/<NN>-<slug>.md`. On first publish the files
|
|
299
|
-
are numbered from `01` in dependency order, so blockers sort first.
|
|
300
|
-
|
|
301
|
-
**`<NN>` is presentation and ordering only. It is never identity** — a file is
|
|
302
|
-
recognised by the key inside it, and nothing may match on the prefix.
|
|
303
|
-
|
|
304
|
-
A new file takes the **next unused prefix**, not the position it would occupy
|
|
305
|
-
in dependency order. Existing files are **never renumbered**: renaming a file
|
|
306
|
-
is deleting one and creating another, and re-publishing must never do that —
|
|
307
|
-
it would rewrite unrelated files every time a blocker was inserted. So after a
|
|
308
|
-
dependency change the prefixes no longer sort into dependency order, and that
|
|
309
|
-
is expected. Read the current order from the `**Blocked by**` lines, which are
|
|
310
|
-
reconciled. The prefixes are not.
|
|
311
|
-
- Title → an `# ` heading, prefixed with its number: `06 — Docs Site Scaffold`.
|
|
312
|
-
- The **spec pointer** → the first line of the body, naming the spec's path.
|
|
313
|
-
- The **repository-is-canonical statement** → a line near the end of the file,
|
|
314
|
-
before the marker, saying that nothing here is read back and that a ticked box
|
|
315
|
-
advances no state.
|
|
316
|
-
- The marker block goes at the **end** of the file.
|
|
317
|
-
- `blocked-by` → a `**Blocked by**` line naming each blocker as
|
|
318
|
-
`<file> (<key>)`. A key with no file under `.work/` renders as
|
|
319
|
-
`<key> — not tracked here`; a key that has one renders as `<file> (<key>)`
|
|
320
|
-
whether or not it is part of the current run.
|
|
321
|
-
- `parent` → a `**Parent**` line naming the feature as `<file> (<key>)`.
|
|
322
|
-
Never render parentage as a blocking edge.
|
|
323
|
-
- `chunks` under `chunks-projection: checklist` → a `## Delivery chunks` section
|
|
324
|
-
of `- [ ]` items in spec order. **A checked box means nothing to Pathfinder.**
|
|
325
|
-
The repository is canonical; a human ticking a box does not advance any state
|
|
326
|
-
and must never be read back.
|
|
327
|
-
- Tags → a `**Tags**` line listing them verbatim, comma-separated, in the order
|
|
328
|
-
given. There is no label object to create, so the mapping is the identity
|
|
329
|
-
mapping and no colour applies. Replace the rows below with this project's own
|
|
330
|
-
tags.
|
|
331
|
-
|
|
332
|
-
| Tag | Local rendering |
|
|
333
|
-
|---|---|
|
|
334
|
-
| `area:site` | `area:site` |
|
|
335
|
-
| `area:cli` | `area:cli` |
|
|
336
|
-
| `type:infra` | `type:infra` |
|
|
337
|
-
| `type:content` | `type:content` |
|
|
338
|
-
| `agent:suitable` | `agent:suitable` |
|
|
339
|
-
| `agent:needs-human` | `agent:needs-human` |
|
|
340
|
-
|
|
341
|
-
### Publishing, and re-publishing
|
|
342
|
-
|
|
343
|
-
No approval is required to write under `.work/` — it is an ordinary file edit in
|
|
344
|
-
this repository and reaches nothing outside it.
|
|
345
|
-
|
|
346
|
-
Publishing is **idempotent**. Re-running must be safe and must be provably inert
|
|
347
|
-
when nothing changed:
|
|
348
|
-
|
|
349
|
-
1. Read every existing file under `.work/` and index them by the key in their
|
|
350
|
-
marker block.
|
|
351
|
-
2. For each work item, if no file carries its key, create one.
|
|
352
|
-
3. If a file carries its key, compare its full contents to what would be written
|
|
353
|
-
now. **If they are identical, do nothing at all** — do not rewrite the file
|
|
354
|
-
with the same bytes. An unchanged item must leave its mtime untouched.
|
|
355
|
-
4. If they differ, rewrite that file in place. Never delete and recreate.
|
|
356
|
-
5. Never delete a file, and never touch a file whose key is absent from the
|
|
357
|
-
current set — it belongs to work outside this run.
|
|
358
|
-
|
|
359
|
-
Report what was created, what was edited, and what was left alone.
|