nikos 0.0.7 → 0.1.1

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 (38) hide show
  1. package/README.md +5 -4
  2. package/dist/cli.js +25 -5
  3. package/dist/commands/init.js +8 -1
  4. package/dist/commands/map.js +272 -0
  5. package/dist/commands/release.js +203 -0
  6. package/dist/commands/show.js +7 -7
  7. package/dist/commands/step.js +59 -0
  8. package/dist/commands/story.js +9 -3
  9. package/dist/commands/validate.js +46 -31
  10. package/dist/lib/bets.js +25 -0
  11. package/dist/lib/frontmatter.js +8 -0
  12. package/dist/lib/project.js +37 -0
  13. package/dist/lint/gherkin.js +2 -2
  14. package/dist/planning/bets.js +73 -0
  15. package/dist/planning/cli.js +152 -0
  16. package/dist/planning/delivery.js +20 -0
  17. package/dist/planning/krs.js +73 -0
  18. package/dist/planning/model.js +164 -0
  19. package/dist/planning/server.js +336 -0
  20. package/dist/planning/ui.js +452 -0
  21. package/dist/planning/upstream.js +175 -0
  22. package/docs/format.md +51 -55
  23. package/docs/gherkin.md +2 -1
  24. package/docs/install.md +12 -5
  25. package/docs/planning.md +124 -0
  26. package/package.json +2 -1
  27. package/schemas/planning/bet.schema.json +42 -0
  28. package/schemas/planning/kr.schema.json +35 -0
  29. package/schemas/planning/plan.schema.json +28 -0
  30. package/schemas/storymap.schema.json +94 -11
  31. package/skills/nikos-mode/playbooks/idea-to-blueprint.md +1 -1
  32. package/skills/nikos-mode/playbooks/index.md +1 -1
  33. package/skills/nikos-mode/playbooks/planning.md +11 -0
  34. package/skills/nikos-mode/principles/index.md +0 -2
  35. package/dist/commands/bet.js +0 -97
  36. package/docs/intentdocs-mapping.md +0 -117
  37. package/schemas/bet.schema.json +0 -23
  38. package/skills/nikos-mode/playbooks/bet.md +0 -14
package/docs/format.md CHANGED
@@ -19,8 +19,6 @@ intent/
19
19
  state.yaml status, blockers and the run queue
20
20
  outreach/ optional, drafts from the validate playbook
21
21
  <date>-<channel>.md
22
- bets/ optional, time-boxed bets (see Bets)
23
- <bet-id>.md
24
22
  ```
25
23
 
26
24
  Two rules hold across every file:
@@ -79,8 +77,8 @@ five vision sections come first, in order, and aren't empty.
79
77
 
80
78
  ## storymap.yaml
81
79
 
82
- **Purpose:** the shape of the product: activities (columns), releases (rows)
83
- and the order stories should be built in. It is an index; the stories
80
+ **Purpose:** the shape of the product: activities and their steps (columns),
81
+ releases (rows) and the order stories should be built in. It is an index; the stories
84
82
  themselves live in feature files.
85
83
 
86
84
  **Path:** `intent/storymap.yaml`
@@ -94,9 +92,15 @@ key: HT # story id prefix: HT-1, HT-2 …
94
92
  activities:
95
93
  - id: tasks # slug, matches the features/<activity>/ folder
96
94
  title: Manage tasks
95
+ steps: # optional: the steps a person takes in this activity
96
+ - id: capture # slug, unique across the map; a story tags it @step-capture
97
+ title: Capture a task
98
+ - id: focus
99
+ title: Focus on today
97
100
  releases:
98
101
  - number: 1
99
102
  title: MVP
103
+ goal: Capture tasks and see only today's top three. # optional, one line
100
104
  stories: [HT-1, HT-2] # build order within the release
101
105
  - number: 2
102
106
  title: Enhancements
@@ -108,10 +112,49 @@ Rules:
108
112
  - Every story id appears in exactly one release.
109
113
  - Every story id has exactly one feature file and one `state.yaml` entry.
110
114
  - Release numbers start at 1 and have no gaps.
115
+ - Step ids are unique across the map. A story's `@step-<id>` must name a step
116
+ of its own activity. A story with no step sits under the activity's first
117
+ step on the map.
118
+ - A story's `@release-N` tag should match the release that lists it;
119
+ `nikos validate` warns when they differ.
111
120
 
112
- Add a story with `nikos story add "<title>" --activity <id>`. It takes the
113
- next free id, adds it to the last release (or `--release <n>`), gives it a
114
- `todo` entry in `state.yaml` and writes a starter feature file to fill in.
121
+ ### Bet links (optional)
122
+
123
+ A release can name the bets it delivers, and a single story can override its
124
+ release's list. The bets themselves live outside `intent/`, in `planning/`
125
+ (the Planning pack, see [planning.md](planning.md)).
126
+
127
+ ```yaml
128
+ releases:
129
+ - number: 1
130
+ title: MVP
131
+ bets: [fewer-missed-tasks] # a bet in planning/bets/
132
+ stories: [HT-1, HT-2]
133
+ story_bets:
134
+ HT-2: [acme/company-plan#focus-mode] # this story serves another repo's bet
135
+ ```
136
+
137
+ - A bet id must have a `planning/bets/<id>.md` in the same repo.
138
+ - `owner/repo#id` names another repo's bet. `nikos validate` checks its form
139
+ only and never fetches it.
140
+ - A story's `story_bets` entry replaces its release's `bets` for that story.
141
+
142
+ Add a story with `nikos story add "<title>" --activity <id> [--step <id>]`.
143
+ It takes the next free id, adds it to the last release (or `--release <n>`),
144
+ gives it a `todo` entry in `state.yaml` and writes a starter feature file to
145
+ fill in.
146
+
147
+ The map's shape has commands too, so nobody has to hand-edit the YAML. Each
148
+ keeps comments and leaves the rest of the file as it was:
149
+
150
+ | Command | What it does |
151
+ | --- | --- |
152
+ | `nikos step add "<title>" --activity <id>` | Add a step under an activity (`--id` to choose its id) |
153
+ | `nikos release add "<title>" [--goal "<goal>"]` | Add the next numbered release, with no stories yet (titles must be unique) |
154
+ | `nikos release rename <n> ["<title>"] [--goal "<goal>"]` | Change a release's title or goal (`--goal ""` removes it) |
155
+ | `nikos release move <story-id> <n>` | Move a story to the end of another release and retag its feature |
156
+ | `nikos release reorder <n> <position>` | Move a release, renumber them all from 1 and retag every moved story |
157
+ | `nikos release remove <n>` | Remove a release with no stories or bets, renumber the rest and retag their stories |
115
158
 
116
159
  ---
117
160
 
@@ -129,7 +172,7 @@ story; each acceptance criterion is a `Scenario` (or `Scenario Outline`)
129
172
  titled with its label. Full rules are in [gherkin.md](gherkin.md).
130
173
 
131
174
  ```gherkin
132
- @HT-1 @release-1 @must @activity-tasks
175
+ @HT-1 @release-1 @must @activity-tasks @step-capture
133
176
  Feature: Add a task
134
177
 
135
178
  As a busy person
@@ -172,8 +215,6 @@ summary: One to three plain sentences on the approach.
172
215
  Notes for the agent.
173
216
  ```
174
217
 
175
- These fields match intentdocs plans one to one (see the mapping doc).
176
-
177
218
  Start a new version with `nikos plan new <story-id>`. It writes the next
178
219
  `v<N>` from a template, sets `supersedes`, and refuses to overwrite an
179
220
  existing file.
@@ -250,51 +291,6 @@ founder sends it, never the agent.
250
291
 
251
292
  ---
252
293
 
253
- ## bets/&lt;bet-id&gt;.md (optional)
254
-
255
- **Purpose:** a time-boxed bet that a set of stories will move a measure.
256
-
257
- **Path:** `intent/bets/<bet-id>.md`, where `<bet-id>` is lowercase words
258
- joined by hyphens.
259
-
260
- **Format:** Markdown with YAML front matter, then free-form notes. Create one
261
- with `nikos bet new`; the bet playbook frames and closes it.
262
-
263
- ```markdown
264
- ---
265
- id: faster-reorder
266
- hypothesis: We believe drag to reorder will make people plan their day in the app because they reorder on paper today.
267
- key_result: Share of daily users who reorder at least once
268
- expected_uplift: from 10% to 30%
269
- time_box: 2026-12-01
270
- blockers: []
271
- stories: [HT-3]
272
- status: open
273
- ---
274
-
275
- ## Why we think so
276
- The evidence behind the hypothesis.
277
-
278
- ## Outcome
279
- Filled in when the time box ends.
280
- ```
281
-
282
- | Field | Required | Meaning |
283
- | --- | --- | --- |
284
- | `id` | yes | Matches the file name |
285
- | `hypothesis` | yes | What you believe and why |
286
- | `key_result` | yes | The one measure that says whether it worked |
287
- | `expected_uplift` | yes | How far you expect it to move, from what to what |
288
- | `time_box` | yes | End date, `YYYY-MM-DD` |
289
- | `blockers` | yes | What stands in the way; `[]` if nothing |
290
- | `stories` | yes | At least one story id; each must be in `storymap.yaml` |
291
- | `status` | yes | `open \| won \| lost \| killed` |
292
-
293
- `nikos validate` checks every field against `schemas/bet.schema.json`, that
294
- the id matches the file name, and that every linked story exists.
295
-
296
- ---
297
-
298
294
  ## Versioning this format
299
295
 
300
296
  `format_version` in `storymap.yaml` and `state.yaml` is the version of this
package/docs/gherkin.md CHANGED
@@ -8,7 +8,7 @@ and the test: each acceptance criterion is a scenario that Cucumber can run.
8
8
  ## The shape of a story
9
9
 
10
10
  ```gherkin
11
- @HT-1 @release-1 @must @activity-tasks @effort-S
11
+ @HT-1 @release-1 @must @activity-tasks @step-capture @effort-S
12
12
  Feature: Add a task
13
13
 
14
14
  As a busy person
@@ -54,6 +54,7 @@ criterion's priority).
54
54
  | `@release-N` | release the story is in | yes |
55
55
  | `@must` / `@should` / `@could` | story priority | yes |
56
56
  | `@activity-<id>` | activity, matching the folder name | no |
57
+ | `@step-<id>` | step within that activity, from `storymap.yaml` | no |
57
58
  | `@effort-XS` … `@effort-XL` | size estimate | no |
58
59
 
59
60
  Anything else is a warning, so you notice typos.
package/docs/install.md CHANGED
@@ -59,6 +59,7 @@ marketplaces list it.
59
59
  | Pack | Folder | Claude Code |
60
60
  | --- | --- | --- |
61
61
  | Video | `tools/video/` | `/plugin install nikos-video@nikos` |
62
+ | Planning | `tools/planning/` | `/plugin install nikos-planning@nikos` |
62
63
 
63
64
  In Codex and Cursor, install the pack from the same marketplace as nikOS.
64
65
  nikOS's router hands requests to an installed pack's skill, and gives the
@@ -72,14 +73,20 @@ it anyway: `npm install -g nikos`.
72
73
 
73
74
  ## Formats checked
74
75
 
75
- Plugin formats change often. These were read on 2026-11-04 (no page showed a
76
- version):
76
+ Plugin formats change often. These were read on 2026-11-04, and the display
77
+ name fields again on 2026-11-05 (no page showed a version):
77
78
 
78
79
  - Claude Code: https://code.claude.com/docs/en/plugins-reference and
79
80
  https://code.claude.com/docs/en/plugins/marketplace-reference. Checked with
80
- `claude plugin validate .` on Claude Code 2.1.318.
81
- - Cursor: https://cursor.com/docs/reference/plugins
82
- - Codex: https://developers.openai.com/plugins/build/plugins
81
+ `claude plugin validate .` on Claude Code 2.1.318. `displayName` is the
82
+ name shown in the UI. A marketplace entry's `displayName` wins over the
83
+ plugin's. The marketplace `name` stays the install id (`nikos@nikos`).
84
+ - Cursor: https://cursor.com/docs/reference/plugins. That page does not list
85
+ `displayName`. `.cursor-plugin/plugin.json` still sets it so a listing can
86
+ show nikOS, and `name` stays the kebab-case id.
87
+ - Codex: https://developers.openai.com/plugins/build/plugins. The plugin
88
+ title is `interface.displayName` in `.codex-plugin/plugin.json`. The
89
+ marketplace title is the same field on `.agents/plugins/marketplace.json`.
83
90
 
84
91
  All three find skills as `skills/<name>/SKILL.md` at the plugin root.
85
92
  `test/install.test.ts` checks the manifests agree with each other and with
@@ -0,0 +1,124 @@
1
+ # The planning/ format
2
+
3
+ The Planning pack keeps objectives, key results and bets in a `planning/`
4
+ folder at the repo root, next to `intent/`. Planning sets direction; the
5
+ story map in `intent/` handles delivery. Everything is plain text and only
6
+ changes when you (or your agent, with your yes) change it.
7
+
8
+ ```
9
+ planning/
10
+ plan.yaml period, level, pillars and objectives
11
+ krs/<kr-id>.yaml key results and their check-ins
12
+ bets/<bet-id>.md bet cards
13
+ upstream.yaml optional: plans in other repos this one works toward
14
+ upstream.lock written by `nikos planning sync`
15
+ views/<name>.html optional: custom dashboard views
16
+ ```
17
+
18
+ `nikos planning validate` checks every file against `schemas/planning/`.
19
+
20
+ ## plan.yaml
21
+
22
+ **Purpose:** the planning context: the period, the level being planned
23
+ (company, department, group or team), its strategic pillars and objectives.
24
+
25
+ ```yaml
26
+ period: Q1 2027
27
+ level: team
28
+ pillars: [Retention]
29
+ objectives:
30
+ - id: keep-plants-alive
31
+ title: People keep their plants alive
32
+ aligns_to: acme/company-plan#plants-alive # optional
33
+ ```
34
+
35
+ ## krs/&lt;kr-id&gt;.yaml
36
+
37
+ **Purpose:** one key result, with dated check-ins that are only ever added to.
38
+
39
+ ```yaml
40
+ id: reminders-acted-on
41
+ title: Reminders acted on the same day
42
+ objective: keep-plants-alive
43
+ owner: Reminders team
44
+ unit: "%"
45
+ baseline: 41
46
+ target: 60
47
+ original_target: 60 # kept when the target is revised
48
+ by: 2027-03-31
49
+ aligns_to: acme/company-plan#kr-2 # optional, another repo's key result
50
+ stale_after_days: 14 # optional, default 14
51
+ checkins:
52
+ - date: 2027-01-20
53
+ value: 44
54
+ note: First week of the new reminder time.
55
+ evidence: https://analytics.example.com/reminders
56
+ ```
57
+
58
+ Add one with `nikos planning kr new`, check in with `nikos planning checkin`,
59
+ and revise a target with `nikos planning kr target` (the original stays).
60
+
61
+ ## bets/&lt;bet-id&gt;.md
62
+
63
+ **Purpose:** a bet: what we believe, the key results it should move, when we
64
+ review it, and every review decision since.
65
+
66
+ ```markdown
67
+ ---
68
+ id: reminders-that-stick
69
+ owner: Reminders team
70
+ team: Reminders
71
+ hypothesis: We believe reminders at each plant's real watering time get acted on the same day.
72
+ krs:
73
+ primary: reminders-acted-on
74
+ also: [acme/company-plan#kr-2]
75
+ starts: 2027-01-06
76
+ review_on: 2027-02-14
77
+ deadline: 2027-03-31 # optional: only a hard deadline
78
+ confidence: medium # low | medium | high
79
+ dependencies: [Push notifications (Platform team)]
80
+ outcome: open # open | awaiting evidence | won | lost | stopped
81
+ reviews:
82
+ - date: 2027-02-17
83
+ decision: continue # continue | change | stop | complete
84
+ reason: 55% against 60%. Keep going; review again 3 Mar.
85
+ ---
86
+
87
+ ## Why we think so
88
+ 41% of reminders are acted on the same day; most misses arrive at night.
89
+ ```
90
+
91
+ - A bet card has no `stories` field. The story map names the bets each
92
+ release delivers (`bets:` on a release, `story_bets:` for one story; see
93
+ [format.md](format.md)).
94
+ - `krs` may be empty for maintenance or risk-reduction work.
95
+ - Delivery (Shipped, Building, Not started) is worked out from the stories
96
+ that deliver the bet. The outcome only changes at a review: stop sets
97
+ `stopped`; complete sets `won` or `lost` from the key result evidence.
98
+
99
+ Write one with `nikos planning bet new`; review it with
100
+ `nikos planning bet review`.
101
+
102
+ ## upstream.yaml and upstream.lock
103
+
104
+ **Purpose:** the plans in other repos this one works toward, read without
105
+ ever writing to them.
106
+
107
+ ```yaml
108
+ - repo: acme/company-plan
109
+ ref: main
110
+ # url: https://git.example.com/acme/company-plan.git (optional; defaults to GitHub)
111
+ ```
112
+
113
+ `nikos planning sync` clones each into `.nikos/upstream/<owner>/<repo>/`
114
+ (gitignored; sync adds it to `.gitignore`) and writes the commit it read to
115
+ `upstream.lock`. A repo it can't reach is reported as unresolved and planning
116
+ carries on. `nikos planning sync --check` says whether an upstream has moved
117
+ past its locked commit. This repo only stores references like
118
+ `owner/repo#id`, never upstream content.
119
+
120
+ ## views/&lt;name&gt;.html
121
+
122
+ **Purpose:** a custom dashboard view, served by `nikos planning serve` at
123
+ `/views/<name>`. It reads and writes only through the view contract in the
124
+ pack's dashboard playbook.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nikos",
3
- "version": "0.0.7",
3
+ "version": "0.1.1",
4
4
  "description": "Spec-driven development for AI coding agents: story maps, Gherkin acceptance criteria and a done gate for Claude Code, Codex and Cursor",
5
5
  "license": "MIT",
6
6
  "author": "Niko Vijay",
@@ -24,6 +24,7 @@
24
24
  "docs"
25
25
  ],
26
26
  "scripts": {
27
+ "prebuild": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
27
28
  "build": "tsc -p tsconfig.json",
28
29
  "prepublishOnly": "npm run build && npm test",
29
30
  "test": "vitest run",
@@ -0,0 +1,42 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://nikos.tools/schemas/planning/bet.schema.json",
4
+ "title": "nikOS Planning bet card front matter",
5
+ "type": "object",
6
+ "required": ["id", "owner", "hypothesis", "krs", "review_on", "confidence", "dependencies", "outcome", "reviews"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "id": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" },
10
+ "owner": { "type": "string", "minLength": 1 },
11
+ "team": { "type": "string", "minLength": 1 },
12
+ "hypothesis": { "type": "string", "minLength": 1 },
13
+ "krs": {
14
+ "type": "object",
15
+ "additionalProperties": false,
16
+ "properties": {
17
+ "primary": { "type": "string", "minLength": 1 },
18
+ "also": { "type": "array", "uniqueItems": true, "items": { "type": "string", "minLength": 1 } }
19
+ }
20
+ },
21
+ "starts": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
22
+ "review_on": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
23
+ "deadline": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
24
+ "confidence": { "enum": ["low", "medium", "high"] },
25
+ "dependencies": { "type": "array", "items": { "type": "string", "minLength": 1 } },
26
+ "outcome": { "enum": ["open", "awaiting evidence", "won", "lost", "stopped"] },
27
+ "reviews": {
28
+ "type": "array",
29
+ "items": {
30
+ "type": "object",
31
+ "required": ["date", "decision", "reason"],
32
+ "additionalProperties": false,
33
+ "properties": {
34
+ "date": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
35
+ "decision": { "enum": ["continue", "change", "stop", "complete"] },
36
+ "reason": { "type": "string", "minLength": 1 },
37
+ "outcome": { "enum": ["won", "lost", "stopped"] }
38
+ }
39
+ }
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://nikos.tools/schemas/planning/kr.schema.json",
4
+ "title": "nikOS Planning key result",
5
+ "type": "object",
6
+ "required": ["id", "title", "owner", "baseline", "target", "original_target", "by", "checkins"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "id": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" },
10
+ "title": { "type": "string", "minLength": 1 },
11
+ "objective": { "type": "string", "minLength": 1 },
12
+ "owner": { "type": "string", "minLength": 1 },
13
+ "unit": { "type": "string" },
14
+ "baseline": { "type": "number" },
15
+ "target": { "type": "number" },
16
+ "original_target": { "type": "number" },
17
+ "by": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
18
+ "aligns_to": { "type": "string", "pattern": "^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+#[a-z0-9]+(-[a-z0-9]+)*$" },
19
+ "stale_after_days": { "type": "integer", "minimum": 1 },
20
+ "checkins": {
21
+ "type": "array",
22
+ "items": {
23
+ "type": "object",
24
+ "required": ["date", "value"],
25
+ "additionalProperties": false,
26
+ "properties": {
27
+ "date": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
28
+ "value": { "type": "number" },
29
+ "note": { "type": "string" },
30
+ "evidence": { "type": "string" }
31
+ }
32
+ }
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://nikos.tools/schemas/planning/plan.schema.json",
4
+ "title": "nikOS Planning context",
5
+ "type": "object",
6
+ "required": ["period", "level", "pillars"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "name": { "type": "string", "minLength": 1 },
10
+ "period": { "type": "string", "minLength": 1 },
11
+ "level": { "enum": ["company", "department", "group", "team"] },
12
+ "pillars": { "type": "array", "items": { "type": "string", "minLength": 1 } },
13
+ "objectives": {
14
+ "type": "array",
15
+ "items": {
16
+ "type": "object",
17
+ "required": ["id", "title"],
18
+ "additionalProperties": false,
19
+ "properties": {
20
+ "id": { "type": "string", "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$" },
21
+ "title": { "type": "string", "minLength": 1 },
22
+ "owner": { "type": "string" },
23
+ "aligns_to": { "type": "string" }
24
+ }
25
+ }
26
+ }
27
+ }
28
+ }
@@ -3,22 +3,66 @@
3
3
  "$id": "https://nikos.tools/schemas/storymap.schema.json",
4
4
  "title": "nikOS story map",
5
5
  "type": "object",
6
- "required": ["format_version", "project", "key", "activities", "releases"],
6
+ "required": [
7
+ "format_version",
8
+ "project",
9
+ "key",
10
+ "activities",
11
+ "releases"
12
+ ],
7
13
  "additionalProperties": false,
8
14
  "properties": {
9
- "format_version": { "const": 1 },
10
- "project": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$" },
11
- "key": { "type": "string", "pattern": "^[A-Z][A-Z0-9]{0,9}$" },
15
+ "format_version": {
16
+ "const": 1
17
+ },
18
+ "project": {
19
+ "type": "string",
20
+ "pattern": "^[a-z0-9][a-z0-9-]*$"
21
+ },
22
+ "key": {
23
+ "type": "string",
24
+ "pattern": "^[A-Z][A-Z0-9]{0,9}$"
25
+ },
12
26
  "activities": {
13
27
  "type": "array",
14
28
  "minItems": 1,
15
29
  "items": {
16
30
  "type": "object",
17
- "required": ["id", "title"],
31
+ "required": [
32
+ "id",
33
+ "title"
34
+ ],
18
35
  "additionalProperties": false,
19
36
  "properties": {
20
- "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$" },
21
- "title": { "type": "string", "minLength": 1 }
37
+ "id": {
38
+ "type": "string",
39
+ "pattern": "^[a-z0-9][a-z0-9-]*$"
40
+ },
41
+ "title": {
42
+ "type": "string",
43
+ "minLength": 1
44
+ },
45
+ "steps": {
46
+ "type": "array",
47
+ "items": {
48
+ "type": "object",
49
+ "required": [
50
+ "id",
51
+ "title"
52
+ ],
53
+ "additionalProperties": false,
54
+ "properties": {
55
+ "id": {
56
+ "type": "string",
57
+ "pattern": "^[a-z0-9][a-z0-9-]*$"
58
+ },
59
+ "title": {
60
+ "type": "string",
61
+ "minLength": 1
62
+ }
63
+ }
64
+ }
65
+ }
22
66
  }
23
67
  }
24
68
  },
@@ -27,17 +71,56 @@
27
71
  "minItems": 1,
28
72
  "items": {
29
73
  "type": "object",
30
- "required": ["number", "title", "stories"],
74
+ "required": [
75
+ "number",
76
+ "title",
77
+ "stories"
78
+ ],
31
79
  "additionalProperties": false,
32
80
  "properties": {
33
- "number": { "type": "integer", "minimum": 1 },
34
- "title": { "type": "string", "minLength": 1 },
81
+ "number": {
82
+ "type": "integer",
83
+ "minimum": 1
84
+ },
85
+ "title": {
86
+ "type": "string",
87
+ "minLength": 1
88
+ },
89
+ "goal": {
90
+ "type": "string",
91
+ "minLength": 1
92
+ },
35
93
  "stories": {
36
94
  "type": "array",
37
- "items": { "type": "string", "pattern": "^[A-Z][A-Z0-9]{0,9}-[0-9]+$" }
95
+ "items": {
96
+ "type": "string",
97
+ "pattern": "^[A-Z][A-Z0-9]{0,9}-[0-9]+$"
98
+ }
99
+ },
100
+ "bets": {
101
+ "type": "array",
102
+ "items": {
103
+ "type": "string",
104
+ "minLength": 1
105
+ },
106
+ "uniqueItems": true
38
107
  }
39
108
  }
40
109
  }
110
+ },
111
+ "story_bets": {
112
+ "type": "object",
113
+ "propertyNames": {
114
+ "pattern": "^[A-Z][A-Z0-9]{0,9}-[0-9]+$"
115
+ },
116
+ "additionalProperties": {
117
+ "type": "array",
118
+ "items": {
119
+ "type": "string",
120
+ "minLength": 1
121
+ },
122
+ "uniqueItems": true
123
+ }
41
124
  }
42
125
  }
43
126
  }
@@ -8,7 +8,7 @@ decides; you ask, propose and write it down.
8
8
  2. If the repo has no `intent/` folder, run `nikos init --name "<product name>"`, then put the one-sentence idea in the `idea:` line at the top of `intent/constitution.md`.
9
9
  3. Ask the five vision questions one at a time (Users, Problem, Switch, First, Proof), wait for each answer, and write it into its section of `intent/constitution.md`. If an answer contradicts the idea or an earlier answer, point it out and ask which one wins.
10
10
  4. Write a `## Jobs to be done` section ("When …, I want to …, so I can …") and a `## Founding hypothesis` section ("We believe <users> will <behaviour> because <reason>. We'll know we're right when <the Proof measure>."), then confirm both with the person.
11
- 5. Propose activities and releases, with the First answer as release 1, and write them into `intent/storymap.yaml` once the person agrees.
11
+ 5. Propose activities, the steps a person takes in each, and releases with a one-line goal, with the First answer as release 1. Once the person agrees, write them into `intent/storymap.yaml` (`nikos step add` and `nikos release add` do this without hand-editing).
12
12
  6. Write each story as `intent/features/<activity>/<story-slug>.feature`: tag it with its id, release and priority, put "As a … / I want … / So that …" under `Feature:`, and make each acceptance criterion a Scenario tagged and titled with its label (`@AC1`). Add each story to `intent/state.yaml` as `todo`, and remove the example story and its `getting-started` activity that `nikos init` created.
13
13
  7. Check every story with the clear skill. For each failed check, propose the fix to the person and change the spec only once they agree.
14
14
  8. Record every choice you made on the person's behalf (anything their answers didn't settle) with `nikos decide "<title>" --why "<why>" --category product`.
@@ -8,7 +8,7 @@ first match. Packs add rows here as they ship new playbooks.
8
8
  | idea-to-blueprint | `idea-to-blueprint.md` | The person has a new product idea, or wants to start a project from scratch and there is no story map yet. |
9
9
  | video | `video.md` | The person asks for a video: an explainer, product tour, demo, launch or social clip, or to edit or re-render one. Needs the Video pack. |
10
10
  | validate | `validate.md` | The person wants to test or validate an idea with real people, or draft outreach, a post or a demo script for it. |
11
- | bet | `bet.md` | The person wants to frame work as a bet, set a key result or time box for some stories, or close a bet and call its outcome. |
11
+ | planning | `planning.md` | The person wants to plan a period, set OKRs or key results, frame or review a bet, check in on key results, or see a planning dashboard. Needs the Planning pack. |
12
12
  | build-a-story | `build-a-story.md` | The person asks to build, do or pick up the next story, or a story by its id. |
13
13
  | answer | `answer.md` | The person asks a question about the product, a story, a plan or a decision, and nothing in the repo needs to change. |
14
14
  | change | `change.md` | The person asks to add, fix, change or remove something in the repo: code, tests, docs or specs. |
@@ -0,0 +1,11 @@
1
+ # planning
2
+
3
+ Plan a period, frame or review a bet, check in on key results or open the
4
+ planning dashboard. The work is done by the `nikos-planning` skill, which
5
+ ships in the Planning pack, not in nikOS itself. This playbook checks the
6
+ pack is there and hands over to it.
7
+
8
+ 1. Check the Planning pack is installed: the `nikos-planning` skill is in your skills list. If it isn't, tell the person to install it (Claude Code: `/plugin install nikos-planning@nikos`; Codex and Cursor: install `nikos-planning` from the nikOS marketplace), say planning can't run until they do, and stop.
9
+ 2. Hand over to the `nikos-planning` skill: say which of its playbooks matches the request, and run every step of it in order.
10
+ 3. Bets are linked from the story map, not the other way round: when a release or story delivers a bet, it's named in `intent/storymap.yaml` (`bets:` on the release, or `story_bets:`), and `nikos validate` checks the link.
11
+ 4. Report every step with its evidence or its skip reason.
@@ -9,6 +9,4 @@ every request.
9
9
  | **Criteria are the loss function.** The acceptance criteria decide done, not the agent's opinion. | You're judging whether work is finished. |
10
10
  | **Demos, not memos.** Show it working (a passing scenario, a command and its output) rather than describing it. | You're reporting progress or claiming done. |
11
11
  | **Specs stay implementation-agnostic.** Features and criteria describe behaviour, never code, tables or libraries. | You're writing or editing a `.feature` file or story text. |
12
- | **Bets are time boxes.** Work is framed as a bet with an end date; when time's up, decide to ship, extend or kill. | You're scoping a chunk of work or it's running long. |
13
- | **Bets are grounded in evidence.** A bet cites what we saw (user quotes, numbers, results), not what we hope. | You're writing a hypothesis or a key result. |
14
12
  | **The founder signs off outreach.** Nothing is sent to real people without the founder's explicit yes. | You've drafted a message, post or email to anyone outside the repo. |