@pikku/skills 0.12.49 → 0.12.51

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/skills",
3
- "version": "0.12.49",
3
+ "version": "0.12.51",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/pikkujs/pikku.git",
@@ -126,5 +126,5 @@ on their tracker is a public post.
126
126
  ## Then
127
127
 
128
128
  Go back to the mode you were building in (`pikku-build`). The addon is a
129
- dependency of the app, not the app: plan milestones around what the user wants
129
+ dependency of the app, not the app: plan changes around what the user wants
130
130
  to do with the API, and reach the operations through `ref()`.
@@ -1,16 +1,15 @@
1
1
  ---
2
2
  name: pikku-architect
3
3
  description: >-
4
- Use to turn one settled milestone note into the technical plan the build is measured against —
4
+ Use to turn one claimed changeset into the technical plan its build is measured against —
5
5
  the tables, functions, wires, roles, scopes, screens and scenarios it owes, split into passes and
6
- written through `pikku knowledge plan set`. The plan is the denominator
7
- `pikku knowledge plan progress` divides by, so it is written BEFORE any of the milestone's code
8
- exists and never edited afterwards to match what got built. TRIGGER when: a milestone note is settled and the next step is
9
- planning it, the user asks to plan or architect a milestone, `pikku knowledge plan progress` says
10
- a milestone has no plan, or pikku-build's App mode reaches a milestone with nothing planned. DO
11
- NOT TRIGGER when: the milestone notes themselves are still being written (use pikku-knowledge),
12
- the plan already exists and the job is to build it (use pikku-build), or the ask is a one-off
13
- edit to a working app.
6
+ written through `pikku knowledge plan set <changeset>`. The plan is the denominator
7
+ `pikku knowledge plan progress` divides by, so it is written BEFORE any of the changeset's code
8
+ exists and never edited afterwards to match what got built. TRIGGER when: `pikku changes
9
+ claim` says a changeset needs a plan, `changes done` or `pikku changes next` refuses one for having no
10
+ plan, or the user asks to plan or architect a changeset. DO NOT TRIGGER when: the knowledge notes
11
+ themselves are still being written (use pikku-knowledge), the plan already exists and the job is
12
+ to build it (use pikku-changes), or the changeset was claimed with no plan needed.
14
13
  installGroups: [core]
15
14
  agent:
16
15
  tools: read, write, edit, bash, grep
@@ -21,45 +20,51 @@ agent:
21
20
  verify:
22
21
  - id: knowledge-consistent
23
22
  command: pikku knowledge validate
24
- - id: plan-accepted
25
- command: pikku knowledge next --require dispatch,idle
26
23
 
27
24
  ---
28
25
 
29
- # Plan one milestone
26
+ # Plan one changeset
30
27
 
31
- A milestone note says what the app must DO and how it must feel for the person using it. It
32
- deliberately does not say how. This is where how gets decided, once, in writing, before any of
28
+ A changeset's changes say what the app must DO, in the words of the person who filed them, and the
29
+ knowledge notes say what the app is. Neither says how. This is where how gets decided, once, in writing, before any of
33
30
  it is built.
34
31
 
35
32
  **Why the plan comes first and stays fixed.** A builder who plans after seeing its own work can
36
33
  build a fraction, plan only that fraction, and certify itself complete — `pikku knowledge plan
37
34
  progress` then divides by a denominator chosen after the answer. The defence is the ORDER: the plan
38
- is written against the note, in its own turn, before a single migration for it exists, and is never
35
+ is written against the changes, in its own turn, before a single migration for it exists, and is never
39
36
  edited afterwards. An item that will not land is deferred with its reason through `plan defer`,
40
37
  not rewritten out of the plan. The same agent plans and then builds; nothing hands off.
41
38
 
42
- **One milestone, one plan, then build it.** Do not plan the next milestone "while you are here" —
43
- the notes after this one are still allowed to change, and a plan written against a note that later
44
- moves is worse than no plan.
39
+ **One changeset, one plan, then build it.** Do not plan another changeset "while you are here" —
40
+ its changes are still allowed to move, and a plan written against work that later moves is worse
41
+ than no plan.
42
+
43
+ **When a changeset needs one.** `changes claim` decides: a changeset that creates or alters a table,
44
+ or one with many changes, is planned; anything else is put to the configured judge, and a judge that
45
+ fails says plan. The claim prints which, and why. `changes done` then refuses the first change of a
46
+ planned changeset until its plan reads, and the last until the plan's first pass exists; `pikku changes next`
47
+ will not merge it without the plan on its branch.
45
48
 
46
49
  ---
47
50
 
48
51
  ## Write nothing by hand
49
52
 
50
- The plan reaches disk through `pikku knowledge plan set <milestone> <file>` and nowhere else. It
53
+ The plan reaches disk through `pikku knowledge plan set <changeset> <file>` and nowhere else —
54
+ `knowledge/plans/<changeset>.plan.json`, where `<changeset>` is the group id the claim printed.
55
+ Commit it on the changeset's branch, before the first change, so it merges with the code it
56
+ describes. It
51
57
  validates first and names the field that is wrong if it refuses; a plan file written with an editor
52
58
  is a plan nothing checked, and the place that discovers that is a finished build.
53
59
 
54
- It is also written ONCE. `plan set` refuses a milestone that already has a plan: the plan is the
60
+ It is also written ONCE. `plan set` refuses a changeset that already has a plan: the plan is the
55
61
  order the build is measured against, and an order that can be rewritten measures nothing. The one
56
- way down from a written plan is `pikku knowledge plan defer <milestone> <item> --reason <why>`,
62
+ way down from a written plan is `pikku knowledge plan defer <changeset> <item> --reason <why>`,
57
63
  which records what was left out and why.
58
64
 
59
65
  It is JSON rather than a note on purpose. Everything else under `knowledge/` is prose a human
60
66
  reads; this one is consumed field-by-field, and a markdown parser is one more place a misspelt
61
- heading silently passes. It cannot live INSIDE the milestone note either: that note is frozen once
62
- its status leaves `proposed`, so rewriting it would change what the builder was told.
67
+ heading silently passes.
63
68
 
64
69
  ## Send it. Do not go looking.
65
70
 
@@ -87,38 +92,41 @@ pikku meta context --json # what the app already declares
87
92
  pikku knowledge plan schema # the only spec for what you are about to write
88
93
  ```
89
94
 
90
- Then read, in the tree: the milestone's own note in full, every note it names on `entities:` and
91
- `requires:`, the decisions that constrain it, and the migrations already in `db/sqlite/` — those
92
- say whether your tables are new or an alter.
95
+ Then read the changeset's changes in full (`pikku changes show <n>` for each), every
96
+ knowledge note they touch — the entity notes, and the note a change's `Knowledge:` line names — the
97
+ decisions that constrain them, and the migrations already in `db/sqlite/`: those say whether your
98
+ tables are new or an alter.
93
99
 
94
- **Do not re-interview.** If the note leaves something genuinely undecided, plan the reading that
95
- builds LESS. A smaller milestone that ships is worth more than a complete one that does not, and
96
- what you leave out is named in `covers` for the next milestone to pick up.
100
+ **Do not re-interview.** If a change leaves something that alters the schema or a screen genuinely
101
+ undecided, `pikku changes ask` on it and plan the rest; otherwise plan the reading that
102
+ builds LESS. A smaller changeset that ships is worth more than a complete one that does not, and
103
+ what you leave out is named in `covers` for the next changeset to pick up.
97
104
 
98
105
  ### 2. Decide the passes
99
106
 
100
- A pass is a slice of the milestone that stands up on its own. **Pass 1 is a walking skeleton**: it
107
+ A pass is a slice of the changeset that stands up on its own. **Pass 1 is a walking skeleton**: it
101
108
  reaches a real screen, with real functions behind it, proved by a real browser scenario. Everything
102
109
  else waits behind it.
103
110
 
104
111
  This is enforced, not advisory — `plan set` refuses a plan whose pass 1 has no `ui` item, no
105
112
  `functions` item, or a pass-1 route with nothing proving it works. The reason is the failure it was
106
- written against: a milestone that built four unwired functions and no page, and reported itself
113
+ written against: a changeset that built four unwired functions and no page, and reported itself
107
114
  finished. A build that runs out of time in pass 2 has shipped something; one that runs out of time
108
115
  having built pass 1 across four half-finished layers has shipped nothing.
109
116
 
110
117
  **Only pass 1 blocks.** `pikku knowledge plan progress` reports a later pass under `deferred` and
111
118
  never refuses on it. That is what stops plan size from being fatal — but it is not licence to plan
112
- a milestone nobody could finish. The question that decides a plan's size is not "what does this
119
+ a changeset nobody could finish. The question that decides a plan's size is not "what does this
113
120
  note imply" but **"could a build finish all of this if pass 1 took twice as long as I expect"** — if
114
- not, it is two milestones. Plan the first, and say in `covers` what you left behind.
121
+ not, it is two changesets. Plan the first, and say in `covers` what you left behind.
115
122
 
116
- **A screen is what pass 1 reaches only when the milestone IS an app.** The note's `surface:` says
117
- which it is — absent means an app, and `cli`, `mcp`, `agent` and `backend` are the others. On those,
123
+ **A screen is what pass 1 reaches only when the changeset reaches people through an app.** The
124
+ plan's `surface` says which — `app` by default, and `cli`, `mcp`, `agent` and `backend` are the
125
+ others. On those,
118
126
  `ui` is legitimately `n/a` (with its reason, like any slot), and pass 1 proves itself one level
119
127
  down: a pass-1 function that is actually wired, and a `scenarios.backend` item carrying that
120
- function's name in its `fn` field. The obligation never lifts, it only moves — read the surface off
121
- the note before you decide the passes.
128
+ function's name in its `fn` field. The obligation never lifts, it only moves — decide the surface
129
+ before you decide the passes.
122
130
 
123
131
  ### 3. Say what each slot is, or say why it is nothing
124
132
 
@@ -133,7 +141,7 @@ app is the same kind of person" and "nobody thought about roles" must not look a
133
141
  ### 4. Write it
134
142
 
135
143
  ```sh
136
- pikku knowledge plan set <milestone> /tmp/plan.json
144
+ pikku knowledge plan set <changeset> /tmp/plan.json
137
145
  ```
138
146
 
139
147
  Write the JSON to a file first — the command takes a path, not inline JSON, which is what keeps an
@@ -144,7 +152,7 @@ not read.
144
152
  Then confirm what the builder will be handed:
145
153
 
146
154
  ```sh
147
- pikku knowledge plan show <milestone> --for-build
155
+ pikku knowledge plan show <changeset> --for-build
148
156
  ```
149
157
 
150
158
  ---
@@ -156,19 +164,19 @@ inventories every function, wire, scope, role, workflow, agent and scenario. Not
156
164
  duplicates that — only what codegen cannot infer: **why a thing exists, which pass it belongs to,
157
165
  and which knowledge note it discharges.**
158
166
 
159
- ### `covers` — which notes this milestone discharges
167
+ ### `covers` — which notes this changeset discharges
160
168
 
161
169
  Every plan claims at least one knowledge note: `note` (its path under `knowledge/`), `hash` (what
162
170
  that note's body hashes to right now) and `complete`.
163
171
 
164
- `complete: false` is the honest answer for a note whose claims span several milestones — claim the
165
- whole of a note only when this milestone genuinely leaves nothing of it unbuilt, because a note
172
+ `complete: false` is the honest answer for a note whose claims span several changesets — claim the
173
+ whole of a note only when this changeset genuinely leaves nothing of it unbuilt, because a note
166
174
  marked complete is a note nobody looks at again.
167
175
 
168
176
  **You do not have to compute the hash.** Write anything twelve characters long and send the plan:
169
177
  `plan set` refuses a hash that is not the note's current one and names the correct one, so one
170
178
  round trip gets you every hash in the plan. That refusal is the point of the field — a hash that
171
- was never right makes the note read as edited-since from the moment the milestone ships, and it
179
+ was never right makes the note read as edited-since from the moment the changeset ships, and it
172
180
  drops back into a backlog nobody planned.
173
181
 
174
182
  ### `model` — tables, and what their columns HOLD
@@ -197,7 +205,7 @@ parallel lists are two lists that drift.
197
205
  and the client calls it by name, so for nearly every function there is nothing to decide — leave the
198
206
  field out. A `wire` is for the exceptions: its own HTTP path via `wireHTTP` (a webhook, a payment
199
207
  callback, a public URL another system posts to), a queue job, a channel, a scheduled task, or a
200
- workflow entry point. Those last two are not alternate URLs — they are what the milestone IS, and a
208
+ workflow entry point. Those last two are not alternate URLs — they are what the changeset IS, and a
201
209
  plan that omits them ships a `status` column nothing advances or a job nobody runs.
202
210
 
203
211
  A wire is also a constraint on the function's SHAPE, not only an address for it. `wireScheduler`
@@ -221,7 +229,7 @@ permission scenario naming it in `fn`** — a rule with no failing case is a cla
221
229
  A scope depends ONLY on the session: "may this kind of user do this at all" — `admin:invoices:void`,
222
230
  `billing`. It is declared with `wireScope` and granted in `mapSession`, so every name here has to
223
231
  end up in pikku's generated scope meta. One that cannot be declared is one the build can never
224
- finish, and `plan progress` refuses the milestone for as long as it stands.
232
+ finish, and `plan progress` refuses the changeset for as long as it stands.
225
233
 
226
234
  Ownership is not a scope. "Only the owner of the house may read it" depends on the row being asked
227
235
  for, and a scope never sees the row — that is the function's `permission` sentence and lives nowhere
@@ -240,7 +248,7 @@ reach two, and never give a slug to someone who never signs in: a guest checking
240
248
  slug as the seller they buy from, on that app's public routes outside `/app`. Once there is more
241
249
  than one app, every `ui` item carries its `app` too.
242
250
 
243
- Adding the second frontend is the BUILD's job, at the milestone that first needs it —
251
+ Adding the second frontend is the BUILD's job, at the changeset that first needs it —
244
252
  pikku-build's multi-app reference. Your part is recording which app each person is in.
245
253
 
246
254
  ### `ui` — routes, and what is on them
@@ -254,7 +262,7 @@ counts — an unlinked browser scenario reads as a route nobody proved, and the
254
262
 
255
263
  `backend`, `browser`, `permission`, each its own slot. Keyed rather than tagged so that a plan with
256
264
  four backend scenarios and no browser scenario fails on its SHAPE — a flat list lets that through,
257
- and that is exactly the milestone that builds an API and ships no screen.
265
+ and that is exactly the changeset that builds an API and ships no screen.
258
266
 
259
267
  **Every scenario needs `name`: the `pikkuScenario` export it becomes** (`saveEntryScenario`).
260
268
  `feature` and `scenario` are prose for a reader, and prose cannot be matched against codegen.
@@ -262,7 +270,7 @@ and that is exactly the milestone that builds an API and ships no screen.
262
270
  cannot see.
263
271
 
264
272
  Permission scenarios default to pass 2 — they harden a journey that has to exist before they can
265
- cover it — so a role × resource cross product there costs the milestone nothing.
273
+ cover it — so a role × resource cross product there costs the changeset nothing.
266
274
 
267
275
  ---
268
276
 
@@ -270,10 +278,10 @@ cover it — so a role × resource cross product there costs the milestone nothi
270
278
 
271
279
  `plan set` catches the mechanical failures — a missing slot, a bad hash, a pass 1 with no `ui` item.
272
280
  Read your draft back against these six questions, which it cannot ask. Each has cost a real
273
- milestone; **[references/plan-defects.md](references/plan-defects.md)** carries the case behind every
281
+ changeset; **[references/plan-defects.md](references/plan-defects.md)** carries the case behind every
274
282
  one, and is worth opening for any question you cannot answer with a flat yes.
275
283
 
276
- 1. **Is this a plan for THIS note?** Every entity the note names appears in a function or a table.
284
+ 1. **Is this a plan for THESE changes?** Every entity the changes and their notes name appears in a function or a table.
277
285
  2. **Does pass 1 slice, and does the model fit inside it?** Not "pass 1: the data model, pass 2: the
278
286
  API" — and `model` holds only the tables pass 1 or 2 actually migrates, because the model slot has
279
287
  no passes and a later table is a PROBLEM from the first day.
@@ -283,7 +291,7 @@ one, and is worth opening for any question you cannot answer with a flat yes.
283
291
  4. **Does something produce every state and field the plan reads?** For each clause of a description,
284
292
  each screen the opening paragraph names, each field you filter or badge on, and each state a
285
293
  scenario waits in — name the function that gets the world there. A producer you are reusing is
286
- checked against code that already exists; a producer this milestone is adding is checked against
294
+ checked against code that already exists; a producer this changeset is adding is checked against
287
295
  the plan that adds it. What is never allowed is a state with no named producer at all.
288
296
  5. **Can two sentences in the plan both be true?** Write a state machine out once as a table in
289
297
  `model`, name who sets and reads every clock in it, and say whether saving a child collection
@@ -295,7 +303,8 @@ one, and is worth opening for any question you cannot answer with a flat yes.
295
303
 
296
304
  ## When you are done
297
305
 
298
- The accepted `plan set` is the end of planning. Go straight on to the build in `pikku-build` §6:
299
- read the plan with `plan show --for-build`, build it, and close the milestone only when
300
- `pikku knowledge plan progress` is clean. What you wrote is what you are measured against, so do
301
- not touch it once the first migration is open.
306
+ The accepted `plan set` is the end of planning. Commit the plan file on the changeset's branch, then
307
+ go straight on to the build in `pikku-changes`: read the plan with `plan show --for-build`, build it
308
+ one commit per change, and mark the last change done only when `pikku knowledge plan progress` is
309
+ clean — `changes done` checks the same thing and refuses until it is. What you wrote is what you are
310
+ measured against, so do not touch it once the first migration is open.
@@ -1,7 +1,7 @@
1
1
  # What makes a plan wrong
2
2
 
3
3
  `plan set` catches the mechanical failures — a missing slot, a bad hash, a pass 1 with no `ui`
4
- item. These are the ones it cannot, each carried back from a milestone that shipped it. They are
4
+ item. These are the ones it cannot, each carried back from a changeset that shipped it. They are
5
5
  grouped by the question that finds them, and the fastest way to use this file is to read the six
6
6
  questions and only open the group that worries you.
7
7
 
@@ -27,11 +27,11 @@ questions and only open the group that worries you.
27
27
  screens" is three passes of nothing working.
28
28
 
29
29
  **Put in `model` only the tables pass 1 — or at worst pass 2 — actually migrates.** The model
30
- slot has no passes: every item is checked from the moment the milestone starts, so a table whose
30
+ slot has no passes: every item is checked from the moment the changeset starts, so a table whose
31
31
  migration belongs to pass 3 is a PROBLEM from pass 1, and `plan progress` refuses on a problem
32
- rather than deferring it. A milestone that finishes pass 1 green then cannot be closed, and every
32
+ rather than deferring it. A changeset that finishes pass 1 green then cannot be closed, and every
33
33
  fix is outside the build's hands. When a later pass needs its own tables, that is the signal it is
34
- a second milestone — say so in `covers`.
34
+ a second changeset — say so in `covers`.
35
35
 
36
36
  ---
37
37
 
@@ -46,7 +46,7 @@ scenario cannot perform. Signed-out is a BROWSER fact.
46
46
  `saveEntry` returns 200 proves the wire. The one worth planning is the one where a person writes
47
47
  something, comes back, and it is still there. A browser scenario that opens a page and asserts it
48
48
  is still on it proves the route loads and nothing else — `plan progress` names it a problem and
49
- refuses the milestone.
49
+ refuses the changeset.
50
50
 
51
51
  **Write summary and dashboard scenarios as deltas.** The suite runs against a live database nobody
52
52
  resets, so "the payment-failed count is zero, then one" is a claim about every run that came
@@ -63,7 +63,7 @@ same way you read it against the functions.
63
63
  **Write every refusal as "X, which is `<state>`, is refused because `<rule>`" — then check that
64
64
  state against the rule you wrote in the same plan.** A refusal claims two things at once: that the
65
65
  rule shuts, and that the described situation reaches the shut state. One plan asked for "a paused
66
- licence is refused the academy" in the same milestone whose gate admitted `active_until_expired`,
66
+ licence is refused the academy" in the same changeset whose gate admitted `active_until_expired`,
67
67
  which is exactly what pausing inside the paid period produces. The scenario could only ever have
68
68
  asserted a bug.
69
69
 
@@ -77,7 +77,7 @@ decision that nothing records.
77
77
  **Every clause of a `feature` or `scenario` description has to be performed by a function** — one
78
78
  in this plan, or one already in the meta. Write "when the distributor is removed its companies
79
79
  fall back to the direct catalog" with no function that removes a distributor and `plan set`
80
- accepts it, `plan progress` passes, and the milestone ships a sentence nothing proves. Read each
80
+ accepts it, `plan progress` passes, and the changeset ships a sentence nothing proves. Read each
81
81
  description back asking *which function does this*, and cut the half you cannot name.
82
82
 
83
83
  **Where a scenario calls the same function twice, check it for a per-period guard first.** A
@@ -86,9 +86,9 @@ cannot be performed in a single run however correct the code is. One planned "sh
86
86
  second lesson and is nudged about the third" against a function that refuses a second completion
87
87
  the same calendar day.
88
88
 
89
- **Every screen the milestone's opening paragraph names is either a `ui` item or a sentence to
89
+ **Every screen the changeset's changes name is either a `ui` item or a sentence to
90
90
  cut.** This trap is easier to miss in the summary prose than in the scenarios: a screen named
91
- there and carried by no `ui` item is invisible to `plan progress`, so the milestone closes green
91
+ there and carried by no `ui` item is invisible to `plan progress`, so the changeset closes green
92
92
  with a sentence of itself unbuilt. One promised "the interval control on the admin product form"
93
93
  for a form that does not exist anywhere in the app.
94
94
 
@@ -99,7 +99,7 @@ mark a product's countries, cannot be proven without amending the plan mid-build
99
99
  **Every state a scenario waits in needs the function that leaves the world like that — checked
100
100
  against the code ALREADY built.** Three failure shapes, in rising order of cost:
101
101
 
102
- - *Stale*: a staff queue of "paid orders with no invoice yet", where an earlier milestone had
102
+ - *Stale*: a staff queue of "paid orders with no invoice yet", where an earlier changeset had
103
103
  moved invoicing to checkout. No order a customer could place was ever in that state; three
104
104
  scenarios passed once against old rows, then failed.
105
105
  - *Unreachable*: staff asked to "capture the payment on an authorised order" when no function in
@@ -108,13 +108,13 @@ against the code ALREADY built.** Three failure shapes, in rising order of cost:
108
108
  - *Wrong person*: a distributor salon owner planned to buy from a catalogue that is scoped by
109
109
  distributor and does not show her the product. Actors are not interchangeable.
110
110
 
111
- **A `model` slot saying "this milestone adds no table" has to be true of the DATA the scenarios
111
+ **A `model` slot saying "this changeset adds no table" has to be true of the DATA the scenarios
112
112
  read, not only of the entities they name.** One promised a checkout priced by delivery country — a
113
113
  shipping rate per country, a VAT rate per country — against an `n/a` model, while the only shipping
114
114
  table in the tree (an addon's) carries no country column at all. The builder then chooses between
115
115
  altering someone else's table and amending the plan, with neither choice recorded. Wherever a
116
116
  description prices, rates or tiers something BY a dimension, say in `model` where that lookup lives:
117
- a table this milestone adds, a column on one that exists, or config-as-code — and if it is config,
117
+ a table this changeset adds, a column on one that exists, or config-as-code — and if it is config,
118
118
  say so and why, exactly as for seed data.
119
119
 
120
120
  ---
@@ -125,7 +125,7 @@ A plan is read one field at a time, so a contradiction between two descriptions
125
125
  check `plan set` makes and is discovered mid-build, with the code already written one of the two
126
126
  ways.
127
127
 
128
- **Where the milestone has a state machine — anything with more than two states and a clock — write
128
+ **Where the changeset has a state machine — anything with more than two states and a clock — write
129
129
  the transitions out once, in the model slot, as the table they are.** Every scenario description
130
130
  then quotes that table instead of restating it from memory. One plan said a cancel on a paid-up
131
131
  licence lands in `canceled` in one scenario and `active_until_expired` in the next.
@@ -142,7 +142,7 @@ you look next: either the same reasoning applies to them, or the plan says why i
142
142
 
143
143
  **Wherever a function writes a set under a parent, say whether a save REPLACES that set or ADDS to
144
144
  it.** A product's variants, an order's lines, a company's members: the two produce identical tables
145
- and identical scenarios, and differ only on the second save. Left unsaid, one milestone shipped an
145
+ and identical scenarios, and differ only on the second save. Left unsaid, one changeset shipped an
146
146
  input schema that could not carry a variant's id, so every save re-added the variants it was given
147
147
  to update — 1, 2, 4, 8, and by the nineteenth save 262,144 rows, with the suite green throughout.
148
148
  Say it in the model slot in the same breath as `onDelete`: that field settles what happens when the
@@ -4,7 +4,7 @@ description: >-
4
4
  Use to build on Pikku — turning a fresh scaffold into a working app (quick spike, real product,
5
5
  or a showcase that exercises every surface), adding a feature to an app that already exists, and
6
6
  the one-off cleanup right after a template is cloned. Covers the knowledge base, personas and
7
- roles, milestone planning, the scenario that proves each one, theming, multi-app layouts and
7
+ roles, filing the work as changes and planning each changeset, the scenario that proves each one, theming, multi-app layouts and
8
8
  deploying. TRIGGER when: the user asks for an app to be built on Pikku, a freshly scaffolded
9
9
  project needs turning into a product, the user asks to add a feature or wire up a new endpoint
10
10
  in a working app, or a template was just cloned or scaffolded. DO NOT TRIGGER when: the user
@@ -36,7 +36,7 @@ agent:
36
36
  | A real product, meant to be picked up by someone else | `references/app.md` — the default |
37
37
  | A spike, a throwaway demo, an idea nobody has committed to | `references/quick.md` |
38
38
  | A showcase meant to exercise every Pikku surface | `references/platform.md`, which is a delta on top of `references/app.md` |
39
- | A feature added to an app that already has its knowledge base and milestones | `references/feature.md` |
39
+ | A feature added to an app that already has its knowledge base | `references/feature.md` |
40
40
 
41
41
  **App is the default.** A small or toy-sounding app does not make it Quick;
42
42
  only an explicit signal of speed or throwaway-ness does. Platform is not "App
@@ -79,14 +79,14 @@ Say it at once, in one line, and start: this is the obvious first move, not a
79
79
  question for the user. Generate the whole spec, however large.
80
80
 
81
81
  Neither is the app. When the conversion compiles, come back here and carry on
82
- in the mode the request calls for — App by default — planning milestones around
82
+ in the mode the request calls for — App by default — planning changesets around
83
83
  what the user wants to do with the API or the workflow, and reaching the
84
84
  generated functions through `ref()`.
85
85
 
86
86
  ## What holds in every mode
87
87
 
88
88
  - **The branch and the diff are the contract.** A reviewer sees real, compiled,
89
- working code: apply is a merge, reject is a `git branch -D`. The milestone's
89
+ working code: apply is a merge, reject is a `git branch -D`. The changeset's
90
90
  plan is your own denominator, measured by `pikku knowledge plan progress` —
91
91
  never something a reviewer is handed instead of the code.
92
92
  - **Discover before editing, and there are two questions, not one.** What THIS
@@ -102,7 +102,7 @@ generated functions through `ref()`.
102
102
  - **`capabilities.<type>` reports what this app USES, not what pikku offers.**
103
103
  A `false` there is "no wire of this type is declared yet", so the rule below
104
104
  about not introducing one is about not widening an app's surface on a whim —
105
- it is not a statement that the surface is unavailable. When a milestone's plan
105
+ it is not a statement that the surface is unavailable. When a changeset's plan
106
106
  calls for a scheduled task and `capabilities.scheduler` is `false`, check
107
107
  `pikku doc` for the door before concluding you cannot build it.
108
108
  - **`metaLocale` in `pikku.config.json` is the language of authored meta** —
@@ -116,7 +116,7 @@ generated functions through `ref()`.
116
116
  because codegen refuses before it gets there. Delete those contracts' entries
117
117
  from `versions.pikku.json` and re-run; they are re-recorded. Fix the real
118
118
  diagnostic first, or you will chase the echo instead. Deleting is right only
119
- for a contract first recorded INSIDE the milestone you are building — nothing
119
+ for a contract first recorded INSIDE the changeset you are building — nothing
120
120
  has consumed it, so there is no version to keep. A contract that shipped and
121
121
  then genuinely changed shape gets `version: N+1` on its `pikkuFunc({...})`
122
122
  followed by `pikku versions update`; delete its entry and you erase a version
@@ -130,10 +130,11 @@ generated functions through `ref()`.
130
130
  `addressLine1`, so a value saved through the query builder comes back missing
131
131
  with no error anywhere. Follow the columns already in `db/sqlite/`
132
132
  (`address_line1`), and check a new one round-trips before building on it.
133
- - **A milestone is planned before it is built, and the plan then stays fixed.**
134
- The plan — tables, functions, wires, roles, scopes, screens, scenarios, in
135
- passes — is written through `pikku knowledge plan set` (how: `pikku-architect`)
136
- in its own turn before any of that milestone's code exists, and
133
+ - **A changeset that needs a plan is planned before it is built, and the plan
134
+ then stays fixed.** `changes claim` says whether it needs one. The plan —
135
+ tables, functions, wires, roles, scopes, screens, scenarios, in passes — is
136
+ written through `pikku knowledge plan set <changeset>` (how: `pikku-architect`)
137
+ in its own turn before any of that changeset's code exists, and
137
138
  `pikku knowledge plan progress` measures the build against it from the
138
139
  generated meta. You plan it and you build it; what you never do is edit the
139
140
  plan afterwards to match what you built — that is grading yourself.
@@ -205,17 +206,17 @@ listed here.
205
206
 
206
207
  ## What NOT to do
207
208
 
208
- - **Do not skip ahead in App mode.** Knowledge, then people, then milestones,
209
- then one milestone at a time — planned, built, proven by a scenario, and
210
- closed against its plan before the next starts. The order is the method.
211
- - **Do not close a milestone your plan says is unfinished.** Build the missing
209
+ - **Do not skip ahead in App mode.** Knowledge, then people, then changes,
210
+ then one changeset at a time — planned, built, proven by a scenario, and
211
+ closed against its plan before it merges. The order is the method.
212
+ - **Do not close a changeset your plan says is unfinished.** Build the missing
212
213
  item, or defer it with a reason through `pikku knowledge plan defer`. Never
213
214
  edit the plan to match what you built, and never drop an item silently.
214
215
  - **Do not let a Quick build be mistaken for a real one.** It skips
215
- `knowledge/`, milestone planning, design direction and refusal scenarios — say
216
+ `knowledge/`, changesets and plans, design direction and refusal scenarios — say
216
217
  so out loud to the user when you finish, and point at the way out.
217
218
  - **Do not introduce a wire of a type whose `capabilities.<type>` is `false`**
218
- unless the user asked for it — and an approved milestone plan counts as them
219
+ unless the user asked for it — and an approved changeset plan counts as them
219
220
  asking. A plan the user signed off on authorizes the wires it names, so build
220
221
  them and flip the capability, rather than refusing planned work because the
221
222
  flag still reads `false` from before the plan.