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.
- package/README.md +5 -4
- package/dist/cli.js +25 -5
- package/dist/commands/init.js +8 -1
- package/dist/commands/map.js +272 -0
- package/dist/commands/release.js +203 -0
- package/dist/commands/show.js +7 -7
- package/dist/commands/step.js +59 -0
- package/dist/commands/story.js +9 -3
- package/dist/commands/validate.js +46 -31
- package/dist/lib/bets.js +25 -0
- package/dist/lib/frontmatter.js +8 -0
- package/dist/lib/project.js +37 -0
- package/dist/lint/gherkin.js +2 -2
- package/dist/planning/bets.js +73 -0
- package/dist/planning/cli.js +152 -0
- package/dist/planning/delivery.js +20 -0
- package/dist/planning/krs.js +73 -0
- package/dist/planning/model.js +164 -0
- package/dist/planning/server.js +336 -0
- package/dist/planning/ui.js +452 -0
- package/dist/planning/upstream.js +175 -0
- package/docs/format.md +51 -55
- package/docs/gherkin.md +2 -1
- package/docs/install.md +12 -5
- package/docs/planning.md +124 -0
- package/package.json +2 -1
- package/schemas/planning/bet.schema.json +42 -0
- package/schemas/planning/kr.schema.json +35 -0
- package/schemas/planning/plan.schema.json +28 -0
- package/schemas/storymap.schema.json +94 -11
- package/skills/nikos-mode/playbooks/idea-to-blueprint.md +1 -1
- package/skills/nikos-mode/playbooks/index.md +1 -1
- package/skills/nikos-mode/playbooks/planning.md +11 -0
- package/skills/nikos-mode/principles/index.md +0 -2
- package/dist/commands/bet.js +0 -97
- package/docs/intentdocs-mapping.md +0 -117
- package/schemas/bet.schema.json +0 -23
- 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),
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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/<bet-id>.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
|
|
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
|
-
|
|
82
|
-
|
|
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
|
package/docs/planning.md
ADDED
|
@@ -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/<kr-id>.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/<bet-id>.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/<name>.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.
|
|
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": [
|
|
6
|
+
"required": [
|
|
7
|
+
"format_version",
|
|
8
|
+
"project",
|
|
9
|
+
"key",
|
|
10
|
+
"activities",
|
|
11
|
+
"releases"
|
|
12
|
+
],
|
|
7
13
|
"additionalProperties": false,
|
|
8
14
|
"properties": {
|
|
9
|
-
"format_version": {
|
|
10
|
-
|
|
11
|
-
|
|
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": [
|
|
31
|
+
"required": [
|
|
32
|
+
"id",
|
|
33
|
+
"title"
|
|
34
|
+
],
|
|
18
35
|
"additionalProperties": false,
|
|
19
36
|
"properties": {
|
|
20
|
-
"id": {
|
|
21
|
-
|
|
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": [
|
|
74
|
+
"required": [
|
|
75
|
+
"number",
|
|
76
|
+
"title",
|
|
77
|
+
"stories"
|
|
78
|
+
],
|
|
31
79
|
"additionalProperties": false,
|
|
32
80
|
"properties": {
|
|
33
|
-
"number": {
|
|
34
|
-
|
|
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": {
|
|
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,
|
|
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
|
-
|
|
|
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. |
|