create-pathfinder 1.8.0 → 2.1.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.
Files changed (45) hide show
  1. package/AGENTS.md +3 -1
  2. package/CLAUDE.md +20 -0
  3. package/README.md +383 -65
  4. package/context/ai-interaction.md +78 -39
  5. package/context/coding-standards.md +119 -60
  6. package/copy-list.json +1 -0
  7. package/package.json +2 -1
  8. package/roles/developer.md +37 -0
  9. package/roles/planner.md +38 -0
  10. package/roles/tester.md +40 -0
  11. package/skills/challenge-me/SKILL.md +11 -7
  12. package/skills/complete-feature/SKILL.md +16 -11
  13. package/skills/handoff/SKILL.md +24 -4
  14. package/skills/kickstart-pathfinder/SKILL.md +6 -1
  15. package/skills/learning-review/SKILL.md +9 -6
  16. package/skills/load-feature/SKILL.md +40 -10
  17. package/skills/prototype/SKILL.md +3 -1
  18. package/skills/quiz-me/SKILL.md +33 -7
  19. package/skills/review-feature/SKILL.md +19 -11
  20. package/skills/role/SKILL.md +33 -0
  21. package/skills/setup-tracker/SKILL.md +29 -61
  22. package/skills/start-feature/SKILL.md +19 -16
  23. package/skills/sync-tracker/SKILL.md +67 -106
  24. package/skills/teach-architecture/SKILL.md +6 -5
  25. package/skills/teach-feature/SKILL.md +11 -8
  26. package/skills/to-specs/SKILL.md +40 -28
  27. package/skills/whereami/SKILL.md +87 -0
  28. package/src/cli.mjs +67 -96
  29. package/src/install.mjs +5 -1
  30. package/src/kit.mjs +70 -1
  31. package/src/outcome.mjs +147 -0
  32. package/templates/CHANGELOG.template.md +2 -1
  33. package/templates/feature-spec.template.md +18 -80
  34. package/templates/history.template.md +12 -0
  35. package/templates/lesson.template.md +22 -51
  36. package/templates/project-overview.template.md +80 -145
  37. package/context/current-feature.md +0 -46
  38. package/context/features/example-feature-spec.md +0 -103
  39. package/context/history.md +0 -14
  40. package/context/learning/learner-profile.md +0 -35
  41. package/context/learning/lessons/.gitkeep +0 -0
  42. package/context/learning/progress.md +0 -28
  43. package/context/project-overview.md +0 -211
  44. package/templates/progress-entry.template.md +0 -23
  45. 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.