create-pathfinder 3.0.0 → 4.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 -3
- package/CLAUDE.md +27 -18
- package/README.md +20 -3
- package/context/ai-interaction.md +19 -13
- package/context/coding-standards.md +11 -7
- package/package.json +2 -2
- package/roles/developer.md +2 -1
- package/roles/planner.md +8 -6
- package/roles/tester.md +1 -1
- package/skills/debug-issue/SKILL.md +4 -4
- package/skills/kickstart-pathfinder/SKILL.md +52 -7
- package/skills/quiz-me/SKILL.md +1 -1
- package/skills/reverse-engineer/SKILL.md +1 -1
- package/skills/role/SKILL.md +8 -2
- package/skills/setup-tracker/SKILL.md +38 -18
- package/skills/teach-feature/SKILL.md +1 -1
- package/skills/ticket/SKILL.md +64 -0
- package/skills/ticket/actions/complete.md +50 -0
- package/skills/ticket/actions/load.md +72 -0
- package/skills/ticket/actions/review.md +44 -0
- package/skills/ticket/actions/start.md +50 -0
- package/skills/ticket/store.md +72 -0
- package/skills/to-specs/SKILL.md +15 -5
- package/skills/to-tickets/SKILL.md +98 -0
- package/skills/whereami/SKILL.md +17 -15
- package/src/kit.mjs +26 -10
- package/templates/feature-spec.template.md +0 -7
- package/templates/ticket.template.md +42 -0
- package/skills/feature/SKILL.md +0 -56
- package/skills/feature/actions/complete.md +0 -22
- package/skills/feature/actions/load.md +0 -45
- package/skills/feature/actions/review.md +0 -32
- package/skills/feature/actions/start.md +0 -33
- package/skills/sync-tracker/SKILL.md +0 -81
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ticket
|
|
3
|
+
description: Run one action of the ticket delivery loop — load, start, review, or complete.
|
|
4
|
+
argument-hint: load|start|review|complete
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Ticket
|
|
8
|
+
|
|
9
|
+
The delivery loop, as one skill. The human names the action:
|
|
10
|
+
|
|
11
|
+
`/ticket load <ticket>`
|
|
12
|
+
`/ticket start`
|
|
13
|
+
`/ticket review`
|
|
14
|
+
`/ticket complete`
|
|
15
|
+
|
|
16
|
+
## Process
|
|
17
|
+
|
|
18
|
+
1. Take the action from the invocation.
|
|
19
|
+
If none was given, list the four actions below and stop.
|
|
20
|
+
If it is not one of the four, say so, list them, and stop.
|
|
21
|
+
2. Read only `skills/ticket/actions/<action>.md` and follow it exactly.
|
|
22
|
+
|
|
23
|
+
## Actions
|
|
24
|
+
|
|
25
|
+
- `load` — prepare one ticket for execution. Resolves the ticket store, reads
|
|
26
|
+
the ticket and its parent Feature spec, verifies every blocker, loads the
|
|
27
|
+
minimum context the ticket names, and writes the session's workspace state.
|
|
28
|
+
- `start` — implement the loaded ticket, restating the pre-implementation
|
|
29
|
+
summary before editing anything.
|
|
30
|
+
- `review` — verify implemented work against the ticket and its parent Feature,
|
|
31
|
+
and report findings. It changes no implementation and accepts nothing.
|
|
32
|
+
- `complete` — complete work the human has accepted, through the project's
|
|
33
|
+
delivery workflow and its durable records, then name the tickets that are now
|
|
34
|
+
ready.
|
|
35
|
+
|
|
36
|
+
## Lifecycle
|
|
37
|
+
|
|
38
|
+
A ticket's status holds the durable lifecycle state named in
|
|
39
|
+
`context/ai-interaction.md`. It lives in the ticket store — see
|
|
40
|
+
`skills/ticket/store.md`, which is where the store and ticket identity are
|
|
41
|
+
defined:
|
|
42
|
+
|
|
43
|
+
`Proposed` → `Ready` → `In Progress` → `Complete`
|
|
44
|
+
|
|
45
|
+
`Cancelled` and `Superseded` are terminal alternatives.
|
|
46
|
+
|
|
47
|
+
- `load` writes `Proposed` → `Ready`.
|
|
48
|
+
- `start` writes `Ready` → `In Progress`.
|
|
49
|
+
- `complete` writes `Complete`.
|
|
50
|
+
- `review` writes no status. Review is workflow activity, not lifecycle state.
|
|
51
|
+
|
|
52
|
+
The parent Feature's status is derived from its tickets, never maintained by
|
|
53
|
+
hand. `start` and `complete` are the only actions that write it, and each writes
|
|
54
|
+
it only as a consequence of the ticket transition it just made.
|
|
55
|
+
|
|
56
|
+
`context/current-ticket.md` is transient workspace state and records no status.
|
|
57
|
+
|
|
58
|
+
## Rules
|
|
59
|
+
|
|
60
|
+
- Run the one action the human named. Do not continue into the next one.
|
|
61
|
+
- Read only that action's file. The other three are not context for this work.
|
|
62
|
+
- One ticket at a time. A session that finishes a ticket stops there.
|
|
63
|
+
- Human authority is unchanged: approval, acceptance, merge, and release are
|
|
64
|
+
the human's, whichever action is running.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Ticket: Complete
|
|
2
|
+
|
|
3
|
+
Invoking this action is the human's acceptance of the ticket. Do not ask for
|
|
4
|
+
acceptance again.
|
|
5
|
+
|
|
6
|
+
## Assumed role
|
|
7
|
+
|
|
8
|
+
Unless the human explicitly activated a role, assume `developer` for this
|
|
9
|
+
invocation: read `roles/developer.md` and follow it. An explicit role overrides
|
|
10
|
+
this default. A role narrows responsibility and never grants human authority.
|
|
11
|
+
|
|
12
|
+
Acceptance of the ticket is not approval of the delivery steps below. Each one
|
|
13
|
+
that the project's documented workflow gates is still asked for.
|
|
14
|
+
|
|
15
|
+
1. Run the project's required final checks.
|
|
16
|
+
2. Follow the documented Git, merge, version, release, and deployment workflow.
|
|
17
|
+
Ask for approval where it requires it. If that workflow is undocumented or
|
|
18
|
+
`TBD`, stop and ask rather than choosing one.
|
|
19
|
+
3. Mark the ticket `Complete` in the store, closing it where the store has a
|
|
20
|
+
closed state. `skills/ticket/store.md` says how that store is written.
|
|
21
|
+
4. Derive the parent Feature's status: when every ticket of that Feature is
|
|
22
|
+
`Complete`, `Cancelled`, or `Superseded`, and at least one is `Complete`, the
|
|
23
|
+
Feature becomes `Complete`. Otherwise leave it exactly as it is. Read the
|
|
24
|
+
sibling tickets' status from the store for this and nothing else. The Feature
|
|
25
|
+
spec is in the repository, and its `## Status` is the only field to write.
|
|
26
|
+
5. Add a compact entry to `context/history.md` when the Feature completed at
|
|
27
|
+
step 4. A ticket that leaves its Feature unfinished is an increment, not a
|
|
28
|
+
completed outcome, and the durable record is per Feature.
|
|
29
|
+
Create the file from `templates/history.template.md` if it does not exist.
|
|
30
|
+
6. Clear or update `context/current-ticket.md`. Do nothing if it does not exist.
|
|
31
|
+
7. Report the tickets that are now ready — see Next below — and let the human
|
|
32
|
+
choose. Do not load one.
|
|
33
|
+
|
|
34
|
+
## Next
|
|
35
|
+
|
|
36
|
+
A ticket became ready when this completion satisfied its last blocker.
|
|
37
|
+
|
|
38
|
+
Read the sibling tickets' status and blockers from the store, and report every
|
|
39
|
+
ticket whose own status is `Proposed` or `Ready` and whose blockers are now all
|
|
40
|
+
`Complete`.
|
|
41
|
+
|
|
42
|
+
Report each by key and title. When none is ready, say so, and say whether that
|
|
43
|
+
is because the Feature is finished or because the remaining tickets are blocked
|
|
44
|
+
by something else.
|
|
45
|
+
|
|
46
|
+
Do not implement the next ticket, and do not decide which one it is.
|
|
47
|
+
|
|
48
|
+
Do not re-review accepted work unless final verification exposes a new problem.
|
|
49
|
+
|
|
50
|
+
Do not claim completion if required checks or delivery steps failed.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Ticket: Load
|
|
2
|
+
|
|
3
|
+
Prepare one ticket for execution.
|
|
4
|
+
|
|
5
|
+
## Assumed role
|
|
6
|
+
|
|
7
|
+
Unless the human explicitly activated a role, assume `developer` for this
|
|
8
|
+
invocation: read `roles/developer.md` and follow it. An explicit role overrides
|
|
9
|
+
this default. A role narrows responsibility and never grants human authority.
|
|
10
|
+
|
|
11
|
+
1. Resolve the ticket store. Read `skills/ticket/store.md` and follow it.
|
|
12
|
+
2. Select the ticket the human named, by key. If none was named, list the ready
|
|
13
|
+
tickets — see Readiness below — and stop.
|
|
14
|
+
3. Read the ticket.
|
|
15
|
+
4. Read its parent Feature spec, named under the ticket's `## Parent Feature`.
|
|
16
|
+
Read the Feature for its Goal, Requirements, Out of Scope, and Acceptance
|
|
17
|
+
Criteria. Do not read the other tickets of that Feature; the blocker check
|
|
18
|
+
below reads their status and nothing else.
|
|
19
|
+
5. Verify every blocker under `## Blocked by`, reading each blocker's status
|
|
20
|
+
from the store:
|
|
21
|
+
- A blocker that is `Complete` is satisfied.
|
|
22
|
+
- A blocker that is `Cancelled` or `Superseded` is not satisfied. Report it
|
|
23
|
+
and stop: an edge pointing at abandoned work is a planning question.
|
|
24
|
+
- Any other status blocks the load. Name the blocking ticket and stop.
|
|
25
|
+
- A named blocker that does not exist blocks the load. Report it by key.
|
|
26
|
+
Stop before writing anything. A blocked load must leave no trace.
|
|
27
|
+
6. Read only the files or context the ticket's `## Context` names.
|
|
28
|
+
7. Inspect the current Git state.
|
|
29
|
+
8. Stop if a required human decision blocks the work.
|
|
30
|
+
9. Record the approval in the ticket's `## Status`:
|
|
31
|
+
- `Proposed` becomes `Ready`. That is the only value this action writes.
|
|
32
|
+
- `Ready` or `In Progress` is left exactly as it is. Reloading a ticket
|
|
33
|
+
mid-work is normal and must not rewrite its state.
|
|
34
|
+
- `Complete`, `Cancelled`, or `Superseded` blocks the load. Report it and
|
|
35
|
+
stop. Reopening terminal work is the human's decision.
|
|
36
|
+
|
|
37
|
+
Do this only once steps 1-8 found no blocker, and before the next step, so a
|
|
38
|
+
blocked load never leaves a promoted ticket behind.
|
|
39
|
+
10. Create or update `context/current-ticket.md` — it does not ship, so the
|
|
40
|
+
first load writes it — with:
|
|
41
|
+
- ticket key, title, and where it is in the store
|
|
42
|
+
- parent Feature number, name, and spec path
|
|
43
|
+
- Git state
|
|
44
|
+
- blocker, if any
|
|
45
|
+
- next action
|
|
46
|
+
|
|
47
|
+
Do not record the lifecycle status here. This file is transient workspace
|
|
48
|
+
state belonging to one session on one machine; the ticket carries the
|
|
49
|
+
durable status.
|
|
50
|
+
11. Present a short readiness summary.
|
|
51
|
+
|
|
52
|
+
## Readiness
|
|
53
|
+
|
|
54
|
+
A ticket is ready when its own status is `Proposed` or `Ready`, and every ticket
|
|
55
|
+
under its `## Blocked by` is `Complete`.
|
|
56
|
+
|
|
57
|
+
Nothing else makes a ticket ready. File order, ticket number, and the order the
|
|
58
|
+
tickets were written are not dependencies.
|
|
59
|
+
|
|
60
|
+
Do not implement the ticket. That is `/ticket start`.
|
|
61
|
+
|
|
62
|
+
Do not load the parent Feature's other tickets, unrelated repository areas,
|
|
63
|
+
history, or roadmap by default.
|
|
64
|
+
|
|
65
|
+
Do not rewrite the ticket's substance — its Goal, Context, Changes,
|
|
66
|
+
Verification, Out of Scope, or Blocked by. `## Status` is the one field this
|
|
67
|
+
action maintains.
|
|
68
|
+
|
|
69
|
+
Do not copy the ticket into the repository. The store holds it, and
|
|
70
|
+
`context/current-ticket.md` records only which ticket this session is on.
|
|
71
|
+
|
|
72
|
+
Do not edit the parent Feature spec. `load` derives nothing.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Ticket: Review
|
|
2
|
+
|
|
3
|
+
Review the actual diff and behavior, not only the developer's summary.
|
|
4
|
+
|
|
5
|
+
## Assumed role
|
|
6
|
+
|
|
7
|
+
Unless the human explicitly activated a role, assume `tester` for this
|
|
8
|
+
invocation: read `roles/tester.md` and follow it. An explicit role overrides
|
|
9
|
+
this default. A role narrows responsibility and never grants human authority.
|
|
10
|
+
|
|
11
|
+
Read the ticket from the store, and its parent Feature spec from the
|
|
12
|
+
repository. The ticket says what this slice had
|
|
13
|
+
to do; the Feature says what the work as a whole is for.
|
|
14
|
+
|
|
15
|
+
## Check
|
|
16
|
+
|
|
17
|
+
- the ticket's `## Verification`, run rather than assumed
|
|
18
|
+
- the ticket's `## Changes`, and whether anything outside them was changed
|
|
19
|
+
- the parent Feature's acceptance criteria this ticket was supposed to advance
|
|
20
|
+
- regressions and important edge cases
|
|
21
|
+
- security/privacy when relevant
|
|
22
|
+
- accessibility, performance, compatibility, and operations when relevant
|
|
23
|
+
- tests and verification
|
|
24
|
+
- scope creep, including work that belongs to another ticket
|
|
25
|
+
- documentation accuracy
|
|
26
|
+
|
|
27
|
+
Use the project's quality priorities and existing standards where relevant.
|
|
28
|
+
|
|
29
|
+
## Output
|
|
30
|
+
|
|
31
|
+
Report:
|
|
32
|
+
|
|
33
|
+
- `PASS`, or findings by severity
|
|
34
|
+
- file/location and impact for each finding
|
|
35
|
+
- what was actually verified
|
|
36
|
+
- anything important that remains unverified
|
|
37
|
+
|
|
38
|
+
Do not modify the implementation unless the human explicitly asks.
|
|
39
|
+
|
|
40
|
+
Do not invent findings or treat passing tests as automatic acceptance.
|
|
41
|
+
|
|
42
|
+
Do not write the ticket's `## Status`, and do not touch the parent Feature's.
|
|
43
|
+
Review is workflow activity, not lifecycle state, and a reviewed ticket stays
|
|
44
|
+
`In Progress` until it is completed.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Ticket: Start
|
|
2
|
+
|
|
3
|
+
Implement the loaded ticket.
|
|
4
|
+
|
|
5
|
+
## Assumed role
|
|
6
|
+
|
|
7
|
+
Unless the human explicitly activated a role, assume `developer` for this
|
|
8
|
+
invocation: read `roles/developer.md` and follow it. An explicit role overrides
|
|
9
|
+
this default. A role narrows responsibility and never grants human authority.
|
|
10
|
+
|
|
11
|
+
1. Read `context/current-ticket.md` and, from the store, the ticket it names.
|
|
12
|
+
If neither exists, stop: an unloaded ticket is not approved for execution.
|
|
13
|
+
Run `/ticket load`.
|
|
14
|
+
2. Read only the context the ticket names.
|
|
15
|
+
3. Restate the pre-implementation summary the project's agent guide requires,
|
|
16
|
+
and wait for it to be answered where it names a human decision. Do not edit
|
|
17
|
+
any file before this step is done.
|
|
18
|
+
4. Record the ticket's status as `In Progress` in the store, before the first
|
|
19
|
+
file edit:
|
|
20
|
+
- `Ready` becomes `In Progress`. That is the only value this action writes to
|
|
21
|
+
the ticket.
|
|
22
|
+
- `In Progress` is left exactly as it is. Continuing a ticket across sessions
|
|
23
|
+
is normal and must not rewrite its state.
|
|
24
|
+
- Any other status stops the session. Report it. A ticket that was never
|
|
25
|
+
loaded is not approved for execution, and terminal work is the human's to
|
|
26
|
+
reopen.
|
|
27
|
+
5. Derive the parent Feature's status from that transition: a Feature whose
|
|
28
|
+
status is `Proposed` or `Ready` becomes `In Progress` when its first ticket
|
|
29
|
+
does. A Feature already `In Progress` is left alone. Write nothing else to
|
|
30
|
+
the Feature spec.
|
|
31
|
+
6. Implement the ticket's `## Changes`, and only those.
|
|
32
|
+
7. Make the smallest complete change.
|
|
33
|
+
8. Verify it as the ticket's `## Verification` says.
|
|
34
|
+
9. Keep the repository stable. The ticket is a slice that leaves the project
|
|
35
|
+
working, so a green build at the end is part of the work, not a later ticket.
|
|
36
|
+
10. Update `context/current-ticket.md` with the current state and next action.
|
|
37
|
+
Do not record the lifecycle status there; the ticket carries it.
|
|
38
|
+
|
|
39
|
+
## Rules
|
|
40
|
+
|
|
41
|
+
- Stay inside this ticket. Work that belongs to another ticket waits for it.
|
|
42
|
+
- Follow existing project conventions.
|
|
43
|
+
- Stop if implementation requires a human decision or material scope change.
|
|
44
|
+
- Do not silently add dependencies or adopt prototype code.
|
|
45
|
+
- Do not edit the parent Feature spec beyond the derived status above.
|
|
46
|
+
- Follow the project's approval and Git rules.
|
|
47
|
+
- Do not decide that your own work is accepted.
|
|
48
|
+
|
|
49
|
+
When the ticket is done, report what changed, what was verified, and anything
|
|
50
|
+
unresolved. Then stop. Picking up the next ticket is a new session.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Where tickets live
|
|
2
|
+
|
|
3
|
+
The one statement of the ticket store. `to-tickets` reads it before creating
|
|
4
|
+
tickets; the `ticket` actions read it before touching one. Neither restates it.
|
|
5
|
+
|
|
6
|
+
## The store is canonical
|
|
7
|
+
|
|
8
|
+
Tickets live in exactly one place: the store the project configured. There is
|
|
9
|
+
one ticket artifact and no copy of it anywhere else.
|
|
10
|
+
|
|
11
|
+
Local Markdown is a store, not a mirror of one. A project using GitHub Issues
|
|
12
|
+
has its tickets in GitHub and nothing under `context/tickets/`; a project using
|
|
13
|
+
local Markdown has them in `context/tickets/` and nowhere else.
|
|
14
|
+
|
|
15
|
+
Nothing publishes, projects, or synchronizes a ticket, because there is never a
|
|
16
|
+
second copy to reconcile.
|
|
17
|
+
|
|
18
|
+
## Resolving it
|
|
19
|
+
|
|
20
|
+
- No `context/tracker.md` — the store is local Markdown at `context/tickets/`.
|
|
21
|
+
That is the default store, not a fallback, and it needs no configuration, no
|
|
22
|
+
credentials, and no dependency.
|
|
23
|
+
- `context/tracker.md` exists — it names the store, how to reach it, and how a
|
|
24
|
+
ticket carries its key. Use what it names. If that store cannot be reached,
|
|
25
|
+
report it and stop; do not write tickets somewhere else.
|
|
26
|
+
|
|
27
|
+
## Identity
|
|
28
|
+
|
|
29
|
+
A ticket's key is `NN.TT` — its parent Feature's number, and the ticket number
|
|
30
|
+
within that Feature. Keys are never reused and never renumbered: blocker edges
|
|
31
|
+
are matched on them.
|
|
32
|
+
|
|
33
|
+
Where tickets are files, the key is the filename, `NN.TT-slug.md`, read from the
|
|
34
|
+
basename and nowhere else — never from the directory above it, the title inside
|
|
35
|
+
it, or the order the tickets happen to be read in.
|
|
36
|
+
|
|
37
|
+
Where they are not files, the key is carried the way `context/tracker.md` says,
|
|
38
|
+
and that is what a later run matches on. Titles are edited by humans and are
|
|
39
|
+
never the identity.
|
|
40
|
+
|
|
41
|
+
## Writing to it
|
|
42
|
+
|
|
43
|
+
- `to-tickets` creates the tickets.
|
|
44
|
+
- `/ticket load` and `/ticket start` record the status transitions the lifecycle
|
|
45
|
+
defines.
|
|
46
|
+
- `/ticket complete` marks the ticket complete, closing it where the store has a
|
|
47
|
+
closed state.
|
|
48
|
+
|
|
49
|
+
`templates/ticket.template.md` is the ticket's content in any store. Where the
|
|
50
|
+
store has a native field for something the template carries — a status, a
|
|
51
|
+
closed state, a blocked-by link — that field is where it lives, and the body
|
|
52
|
+
does not also carry it. Two copies of one ticket's status in one ticket drift
|
|
53
|
+
exactly as fast as two copies in two systems.
|
|
54
|
+
|
|
55
|
+
Match the store's own conventions when it has them — an issue's state, a label
|
|
56
|
+
the config names — rather than writing Pathfinder's vocabulary into a field that
|
|
57
|
+
does not mean it.
|
|
58
|
+
|
|
59
|
+
Ask for approval before the first write of a run that leaves this repository.
|
|
60
|
+
One approval covers the run. Writing a Markdown ticket inside the repository is
|
|
61
|
+
an ordinary file write and is not gated.
|
|
62
|
+
|
|
63
|
+
## What is not in the store
|
|
64
|
+
|
|
65
|
+
Feature specs. They stay in the repository, are read from there, and are the
|
|
66
|
+
planning source the tickets were sliced from.
|
|
67
|
+
|
|
68
|
+
## Changing stores
|
|
69
|
+
|
|
70
|
+
Moving a project from one store to another is a human migration, done
|
|
71
|
+
deliberately and once. Nothing here moves tickets between stores, and no skill
|
|
72
|
+
reads two stores at the same time.
|
package/skills/to-specs/SKILL.md
CHANGED
|
@@ -7,6 +7,12 @@ description: Turn approved direction into small, clear Feature specs.
|
|
|
7
7
|
|
|
8
8
|
Turn approved direction into the minimum Feature specs needed to implement it.
|
|
9
9
|
|
|
10
|
+
## Assumed role
|
|
11
|
+
|
|
12
|
+
Unless the human explicitly activated a role, assume `planner` for this
|
|
13
|
+
invocation: read `roles/planner.md` and follow it. An explicit role overrides
|
|
14
|
+
this default. A role narrows responsibility and never grants human authority.
|
|
15
|
+
|
|
10
16
|
## Process
|
|
11
17
|
|
|
12
18
|
1. Read the approved project context and relevant existing Features.
|
|
@@ -17,8 +23,11 @@ Turn approved direction into the minimum Feature specs needed to implement it.
|
|
|
17
23
|
`NN-feature-name.md` — see Naming below.
|
|
18
24
|
6. Fill only information that materially helps implementation and review.
|
|
19
25
|
7. Present the created Features and recommend which one to start first.
|
|
20
|
-
|
|
21
|
-
|
|
26
|
+
Recommend `to-tickets` on that Feature as the next action: a Feature is
|
|
27
|
+
planned work, and tickets are what a session executes.
|
|
28
|
+
8. Do not consult or write the ticket store. Feature specs stay in the
|
|
29
|
+
repository; `to-tickets` owns creating their executable tickets wherever the
|
|
30
|
+
project keeps them.
|
|
22
31
|
|
|
23
32
|
## Naming
|
|
24
33
|
|
|
@@ -27,8 +36,8 @@ A Feature spec is named `NN-feature-name.md` in the spec source, for example
|
|
|
27
36
|
|
|
28
37
|
`NN` is the Feature number: the next unused number in the spec source, counting
|
|
29
38
|
every spec already there whatever its status. Numbers are never reused and never
|
|
30
|
-
renumbered, because
|
|
31
|
-
renumbering would orphan
|
|
39
|
+
renumbered, because every ticket of that Feature carries the number in its own
|
|
40
|
+
key — `NN.TT` — and renumbering would orphan all of them.
|
|
32
41
|
|
|
33
42
|
The number lives in the filename and nowhere else. The Feature template carries
|
|
34
43
|
no number field, and nothing else in the spec records one.
|
|
@@ -46,7 +55,8 @@ Split only when separate outcomes:
|
|
|
46
55
|
|
|
47
56
|
Prefer fewer Features and fewer artifacts.
|
|
48
57
|
|
|
49
|
-
|
|
58
|
+
A Feature that is coherent but large is not two Features. It is one Feature
|
|
59
|
+
that `to-tickets` will slice into several tickets.
|
|
50
60
|
|
|
51
61
|
## Rules
|
|
52
62
|
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: to-tickets
|
|
3
|
+
description: Decompose one approved Feature spec into small, blocker-linked tickets.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# To Tickets
|
|
7
|
+
|
|
8
|
+
Turn one approved Feature into the tickets that execute it.
|
|
9
|
+
|
|
10
|
+
A Feature is the planning outcome. A ticket is the executable unit of work: one
|
|
11
|
+
vertical slice a fresh session can implement, verify, and hand back with the
|
|
12
|
+
project still working.
|
|
13
|
+
|
|
14
|
+
## Assumed role
|
|
15
|
+
|
|
16
|
+
Unless the human explicitly activated a role, assume `planner` for this
|
|
17
|
+
invocation: read `roles/planner.md` and follow it. An explicit role overrides
|
|
18
|
+
this default. A role narrows responsibility and never grants human authority.
|
|
19
|
+
|
|
20
|
+
## Process
|
|
21
|
+
|
|
22
|
+
1. Read the Feature spec named by the human. If none was named, list the specs
|
|
23
|
+
in the spec source and stop.
|
|
24
|
+
2. Stop if the Feature still carries an unresolved human decision or a `TBD`.
|
|
25
|
+
3. Read only the source the Feature's `## Context` names, and only enough of it
|
|
26
|
+
to size the work honestly.
|
|
27
|
+
4. Decide the slices. See Slicing below.
|
|
28
|
+
5. Resolve the ticket store. Read `skills/ticket/store.md` and follow it.
|
|
29
|
+
6. Create each ticket in that store, from `templates/ticket.template.md`, with
|
|
30
|
+
the key and title the store carries — see Identity below.
|
|
31
|
+
7. Record blockers as ticket keys under each ticket's `## Blocked by`. Verify
|
|
32
|
+
the edges form a directed acyclic graph before creating anything. A cycle is
|
|
33
|
+
a slicing mistake, not a ticket to write.
|
|
34
|
+
8. Present the tickets, the blocker graph, and which tickets are ready now.
|
|
35
|
+
|
|
36
|
+
## Identity
|
|
37
|
+
|
|
38
|
+
A ticket's key is `NN.TT`. `NN` is the parent Feature's number, taken from its
|
|
39
|
+
spec filename. `TT` is the next unused ticket number within that Feature,
|
|
40
|
+
counting every ticket already in the store whatever its status.
|
|
41
|
+
|
|
42
|
+
In the local Markdown store that key is the filename — `context/tickets/`
|
|
43
|
+
holds `NN.TT-slug.md`, for example `context/tickets/27.3-csv-download-endpoint.md`.
|
|
44
|
+
In another store it is carried the way `context/tracker.md` says. Either way,
|
|
45
|
+
`skills/ticket/store.md` is where identity is defined; read it there.
|
|
46
|
+
|
|
47
|
+
Keys are never reused and never renumbered, because blocker edges are matched on
|
|
48
|
+
them.
|
|
49
|
+
|
|
50
|
+
## Slicing
|
|
51
|
+
|
|
52
|
+
A ticket is a tracer bullet, not a layer.
|
|
53
|
+
|
|
54
|
+
Each one must:
|
|
55
|
+
|
|
56
|
+
- deliver an observable change, end to end, however thin
|
|
57
|
+
- leave the project working when it lands
|
|
58
|
+
- be implementable by one session that reads the ticket, its parent Feature, and
|
|
59
|
+
nothing else
|
|
60
|
+
- be verifiable by a command to run or a behavior to observe
|
|
61
|
+
|
|
62
|
+
Do not slice by layer, by file, or by phase. "Add the schema", "wire the UI",
|
|
63
|
+
and "write the tests" are three halves of one ticket.
|
|
64
|
+
|
|
65
|
+
Prefer fewer, larger tickets over many small dependent ones. Every blocker edge
|
|
66
|
+
is a session that has to wait.
|
|
67
|
+
|
|
68
|
+
Split when the work has genuinely separate outcomes, needs meaningfully
|
|
69
|
+
different context, or has a real dependency between its parts.
|
|
70
|
+
|
|
71
|
+
## Blockers
|
|
72
|
+
|
|
73
|
+
An edge means the later ticket cannot start until the earlier one is `Complete`.
|
|
74
|
+
|
|
75
|
+
- Name only real dependencies. Preferred order is not a blocker.
|
|
76
|
+
- Never write an edge to a ticket of another Feature that does not exist yet.
|
|
77
|
+
- Two tickets that only touch the same file are not blocked; they are a merge
|
|
78
|
+
the human resolves.
|
|
79
|
+
|
|
80
|
+
## Status
|
|
81
|
+
|
|
82
|
+
A ticket's `## Status` is its durable lifecycle state:
|
|
83
|
+
|
|
84
|
+
`Proposed` → `Ready` → `In Progress` → `Complete`
|
|
85
|
+
|
|
86
|
+
`Cancelled` and `Superseded` are terminal alternatives.
|
|
87
|
+
|
|
88
|
+
This skill writes `Proposed` and nothing else. Promotion belongs to the
|
|
89
|
+
execution loop.
|
|
90
|
+
|
|
91
|
+
## Rules
|
|
92
|
+
|
|
93
|
+
- Do not implement.
|
|
94
|
+
- Do not invent unresolved decisions or resolve a `TBD`.
|
|
95
|
+
- Do not plan beyond the Feature you were given.
|
|
96
|
+
- Do not rewrite the Feature spec. Report a Feature too vague to slice, and stop.
|
|
97
|
+
- Do not add metadata the ticket template does not carry.
|
|
98
|
+
- Do not scan unrelated repository areas.
|
package/skills/whereami/SKILL.md
CHANGED
|
@@ -12,16 +12,18 @@ action. It reports state. It never changes it.
|
|
|
12
12
|
|
|
13
13
|
## Process
|
|
14
14
|
|
|
15
|
-
1. Role: report
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
1. Role: report an explicit `/role` override when one is active; otherwise
|
|
16
|
+
report `none`. Lifecycle role assumptions apply only to their own invocation,
|
|
17
|
+
so a previous `ticket` or planning action does not persist a role for
|
|
18
|
+
`whereami`. Roles are never written to disk. Do not infer one from the
|
|
19
|
+
current ticket or search `roles/`.
|
|
20
|
+
2. Read `context/current-ticket.md` if it exists.
|
|
21
|
+
Take Ticket, Feature, and Next from it verbatim. The ticket key and the
|
|
22
|
+
Feature number are the ones recorded there, from their filenames.
|
|
21
23
|
If the file is missing or still holds template placeholders, report `none`.
|
|
22
24
|
3. Run `git status --short --branch` once.
|
|
23
25
|
Report the branch/ref, and `clean` or the count of changed paths.
|
|
24
|
-
4. Compare the Git section of `context/current-
|
|
26
|
+
4. Compare the Git section of `context/current-ticket.md` with step 3.
|
|
25
27
|
Report a drift line only if the recorded branch differs from the real one.
|
|
26
28
|
5. Context telemetry: report it only if this harness exposes it.
|
|
27
29
|
Otherwise `unavailable`. Do not estimate.
|
|
@@ -33,7 +35,7 @@ Exactly this shape, one line each:
|
|
|
33
35
|
```
|
|
34
36
|
Role: <role | none>
|
|
35
37
|
Feature: <## — name | none>
|
|
36
|
-
|
|
38
|
+
Ticket: <key and name | none>
|
|
37
39
|
Git: <branch/ref> — <clean | N changed>
|
|
38
40
|
Context: <telemetry | unavailable>
|
|
39
41
|
Next: <single next action | none>
|
|
@@ -42,7 +44,7 @@ Next: <single next action | none>
|
|
|
42
44
|
Add at most one line after it, and only when step 4 found drift:
|
|
43
45
|
|
|
44
46
|
```
|
|
45
|
-
Drift: current-
|
|
47
|
+
Drift: current-ticket.md records <branch>, working tree is on <branch>
|
|
46
48
|
```
|
|
47
49
|
|
|
48
50
|
Then stop.
|
|
@@ -50,8 +52,8 @@ Then stop.
|
|
|
50
52
|
## Rules
|
|
51
53
|
|
|
52
54
|
- Read only. No writes, no commits, no `git` command that mutates anything.
|
|
53
|
-
- Read at most one file: `context/current-
|
|
54
|
-
- Do not open the feature spec, history, roadmap,
|
|
55
|
+
- Read at most one file: `context/current-ticket.md`.
|
|
56
|
+
- Do not open the ticket, the feature spec, history, roadmap, or source.
|
|
55
57
|
- Report `none` or `unavailable` instead of inferring a missing value.
|
|
56
58
|
- Do not offer to fix drift, update state, or start the next action.
|
|
57
59
|
The human decides what happens after the snapshot.
|
|
@@ -63,7 +65,7 @@ Then stop.
|
|
|
63
65
|
```
|
|
64
66
|
Role: developer
|
|
65
67
|
Feature: 12 — export saved searches
|
|
66
|
-
|
|
68
|
+
Ticket: 12.2 — CSV writer
|
|
67
69
|
Git: feature/12-export-saved-searches — 3 changed
|
|
68
70
|
Context: unavailable
|
|
69
71
|
Next: Verify the CSV writer against the acceptance criteria
|
|
@@ -76,12 +78,12 @@ Do not do this:
|
|
|
76
78
|
```
|
|
77
79
|
Role: developer (inferred from recent commits)
|
|
78
80
|
Feature: 12 — export saved searches
|
|
79
|
-
|
|
81
|
+
Ticket: 12.3 — probably the download endpoint
|
|
80
82
|
Git: feature/12-export-saved-searches — 3 changed
|
|
81
83
|
Context: ~60% used
|
|
82
|
-
Next: I can update current-
|
|
84
|
+
Next: I can update current-ticket.md and start ticket 12.3 — want me to?
|
|
83
85
|
```
|
|
84
86
|
|
|
85
|
-
It guesses the role from history, invents a
|
|
87
|
+
It guesses the role from history, invents a ticket that was never written,
|
|
86
88
|
estimates telemetry it cannot see, and turns a status report into a proposal
|
|
87
89
|
to write state.
|
package/src/kit.mjs
CHANGED
|
@@ -57,24 +57,38 @@ export function isExcluded(basename) {
|
|
|
57
57
|
* real, hand-written files that live inside a copy-list directory and must
|
|
58
58
|
* still never reach a destination project.
|
|
59
59
|
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
60
|
+
* Every one of them would be actively wrong in somebody else's project,
|
|
61
|
+
* though not all for the same reason — see `context/history.md` below.
|
|
62
62
|
*
|
|
63
|
-
* `context/tracker.md` is the original case.
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* tracker it does not own, pointing at a spec directory it does not have, with
|
|
67
|
-
* the off switch already defeated on first install.
|
|
63
|
+
* `context/tracker.md` is the original case. Its absence selects the default
|
|
64
|
+
* local-Markdown ticket store, so shipping this repository's own copy would
|
|
65
|
+
* hand every new project a configuration naming a store it does not own.
|
|
68
66
|
*
|
|
69
|
-
* `context/current-
|
|
67
|
+
* `context/current-ticket.md` and `context/handoff.md` are transient session
|
|
70
68
|
* state, and they are here for the same reason one step further on: the kit
|
|
71
|
-
* stopped shipping a blank `current-
|
|
69
|
+
* stopped shipping a blank `current-ticket.md` stencil, because `/ticket load`
|
|
72
70
|
* writes the real one on first use and a placeholder is just a file a reader
|
|
73
71
|
* has to recognise as empty. Having stopped shipping the blank one, the thing
|
|
74
72
|
* to guard against is shipping a *filled-in* one — a destination project
|
|
75
|
-
* opening its first session to a note about whichever
|
|
73
|
+
* opening its first session to a note about whichever ticket a Pathfinder
|
|
76
74
|
* maintainer had loaded on the day of the release.
|
|
77
75
|
*
|
|
76
|
+
* `context/current-feature.md` is the same file under its former name. The
|
|
77
|
+
* delivery loop stopped writing it when tickets became the executable unit, and
|
|
78
|
+
* it stays on this list because a project installed before that change still
|
|
79
|
+
* has one sitting in `context/`, and an upgrade must not ship a maintainer's
|
|
80
|
+
* copy over it.
|
|
81
|
+
*
|
|
82
|
+
* `context/history.md` is the odd one out, and the reason this set now has two
|
|
83
|
+
* kinds in it. The others are transient or local session state, ignored by
|
|
84
|
+
* Git as well as excluded here. This one is durable project truth, tracked in
|
|
85
|
+
* version control exactly as `README.md` says a project should track it — it is
|
|
86
|
+
* simply *another project's* truth. A destination project gets its own, written
|
|
87
|
+
* by `/ticket complete` from `templates/history.template.md` on the day it
|
|
88
|
+
* first completes something, and that template must keep shipping. So the
|
|
89
|
+
* promise made about this path is the publication half only: never shipped, but
|
|
90
|
+
* emphatically tracked.
|
|
91
|
+
*
|
|
78
92
|
* `context` is a *directory* entry in the copy list, so anything placed beneath
|
|
79
93
|
* it ships by default. Making the invariant enforced rather than intended is
|
|
80
94
|
* the same move `check_no_junk_tracked` made: an ignore rule is advisory, one
|
|
@@ -86,8 +100,10 @@ export function isExcluded(basename) {
|
|
|
86
100
|
*/
|
|
87
101
|
const NEVER_SHIPS = new Set([
|
|
88
102
|
"context/tracker.md",
|
|
103
|
+
"context/current-ticket.md",
|
|
89
104
|
"context/current-feature.md",
|
|
90
105
|
"context/handoff.md",
|
|
106
|
+
"context/history.md",
|
|
91
107
|
]);
|
|
92
108
|
|
|
93
109
|
/**
|
|
@@ -26,13 +26,6 @@ Include only what materially helps someone implement this Feature.
|
|
|
26
26
|
|
|
27
27
|
- `[explicit exclusion]`
|
|
28
28
|
|
|
29
|
-
## Delivery Chunks
|
|
30
|
-
|
|
31
|
-
1. `[small, stable, verifiable increment]`
|
|
32
|
-
2. `[next increment, if needed]`
|
|
33
|
-
|
|
34
|
-
Use one chunk when the Feature is already small.
|
|
35
|
-
|
|
36
29
|
## Acceptance Criteria
|
|
37
30
|
|
|
38
31
|
- `[observable result proving the Feature works]`
|