nikos 0.0.1 → 0.0.2

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 CHANGED
@@ -8,13 +8,21 @@
8
8
  spec-driven development for AI coding agents
9
9
  ```
10
10
 
11
- Your story map, plans and acceptance criteria live in your repo as plain
12
- files and executable Cucumber features, and the agent can't call a story done
13
- until its scenarios pass.
11
+ AI coding agents are quick to say "done". nikOS makes them prove it. Your
12
+ story map, plans and acceptance criteria live in your repo as plain files,
13
+ each criterion is a Cucumber scenario that runs as a test, and a story can't
14
+ be marked done until its scenarios pass. Your agent follows a named playbook
15
+ for each request instead of improvising, and every decision is written down
16
+ where the next person (or agent) can find it.
14
17
 
15
- > Early work in progress. Start with [the intent/ format](docs/format.md).
18
+ > Early work in progress. Open source, MIT licensed.
16
19
 
17
- ## Install
20
+ ## Try it in 10 minutes
21
+
22
+ [docs/quickstart.md](docs/quickstart.md) takes an empty repo to one passing
23
+ scenario, with every command and the output you should see.
24
+
25
+ ## Install in your agent tool
18
26
 
19
27
  | Tool | Command |
20
28
  | --- | --- |
@@ -23,11 +31,78 @@ until its scenarios pass.
23
31
  | Cursor | Add `https://github.com/nikovijay/NikOS` as a plugin marketplace |
24
32
 
25
33
  Then ask your agent to plan or build a story: the `nikos-mode` skill takes it
26
- from there. Details and the formats each tool expects: [docs/install.md](docs/install.md).
34
+ from there. The skills run the `nikos` command through `npx`, so there's
35
+ nothing else to install. More in [docs/install.md](docs/install.md).
36
+
37
+ ## The loop
38
+
39
+ ```bash
40
+ npx -y nikos init # create intent/ with a starter story
41
+ # write the story's scenarios in intent/features/
42
+ npx -y nikos verify setup # add a Cucumber runner for your stack
43
+ npx -y nikos verify TC-1 # run the story: it fails until it's built
44
+ # build it, then
45
+ npx -y nikos state set TC-1 done # refused unless its scenarios pass
46
+ ```
47
+
48
+ With an agent, you only write the request ("add a story for X and build
49
+ it"); the playbooks run these steps and stop at each point that needs you.
50
+
51
+ ## What lives in your repo
52
+
53
+ ```text
54
+ intent/
55
+ ├── constitution.md who it's for, the problem, what proves it works
56
+ ├── storymap.yaml activities, releases, and the order to build stories in
57
+ ├── state.yaml each story's status: todo, in_progress, needs_rework, done
58
+ ├── decisions.md why things are the way they are, append-only
59
+ ├── features/ one .feature file per story; its scenarios are the criteria
60
+ │ └── <activity>/<story>.feature
61
+ ├── plans/ how each story will be built, versioned: <story>.v<N>.md
62
+ └── bets/ time-boxed bets and the stories that test them
63
+ ```
64
+
65
+ Every file is plain text you can read, review and diff. The full format:
66
+ [docs/format.md](docs/format.md). A worked example:
67
+ [examples/hello-todo](examples/hello-todo/intent).
68
+
69
+ ## Commands
70
+
71
+ | Command | What it does |
72
+ | --- | --- |
73
+ | `nikos init` | Create `intent/` in this repo |
74
+ | `nikos validate` | Check `intent/` is well formed |
75
+ | `nikos clear <id>` | Check a story is ready to build |
76
+ | `nikos plan new <id>` | Start the next version of a story's plan |
77
+ | `nikos verify setup` | Add a Cucumber runner for this repo's stack |
78
+ | `nikos verify [id]` | Run a story's scenarios, or all of them |
79
+ | `nikos state set <id> <status>` | Move a story; done only if its scenarios pass |
80
+ | `nikos next` | Print the next story to build |
81
+ | `nikos show <id>` | Summarise a story: feature, status, plan, bets, decisions |
82
+ | `nikos decide "<title>"` | Append a decision to `decisions.md` |
83
+ | `nikos decisions "<q>"` | Quote the decisions about a topic or story |
84
+ | `nikos bet new <id>` | Write a time-boxed bet card linked to its stories |
85
+
86
+ ## Working with a team: intentdocs
87
+
88
+ When you want a visual story map, reviews and a team around the same specs,
89
+ [intentdocs](https://www.intentdocs.com) reads the same `intent/` folder:
90
+
91
+ ```bash
92
+ npx intentdocs push # upload intent/ and link this repo
93
+ npx intentdocs pull # bring web edits back, shown as diffs first
94
+ ```
95
+
96
+ The repo stays the source of truth for specs and plans; intentdocs runs the
97
+ build and acceptance steps. What maps to what:
98
+ [docs/intentdocs-mapping.md](docs/intentdocs-mapping.md).
99
+
100
+ ## Links
27
101
 
28
102
  - Home: https://nikos.tools
29
- - Format spec: [docs/format.md](docs/format.md)
30
- - Mapping to intentdocs: [docs/intentdocs-mapping.md](docs/intentdocs-mapping.md)
31
- - Worked example: [examples/hello-todo](examples/hello-todo/intent)
103
+ - Quickstart: [docs/quickstart.md](docs/quickstart.md)
104
+ - Install: [docs/install.md](docs/install.md)
105
+ - Format: [docs/format.md](docs/format.md)
106
+ - Writing stories as features: [docs/gherkin.md](docs/gherkin.md)
32
107
 
33
108
  MIT licensed.
@@ -1,4 +1,4 @@
1
- import { copyFileSync, existsSync, mkdirSync } from "node:fs";
1
+ import { copyFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
2
2
  import { dirname, join, relative } from "node:path";
3
3
  import { spawnSync } from "node:child_process";
4
4
  import { fileURLToPath } from "node:url";
@@ -12,6 +12,8 @@ const INSTALL = {
12
12
  ts: "npm install --save-dev @cucumber/cucumber@^12 tsx",
13
13
  python: "pip install behave",
14
14
  };
15
+ /** A step only the untouched example story has. */
16
+ const EXAMPLE_STEP = "When I do the one thing this product is for";
15
17
  const CONFIG = { js: "cucumber.mjs", ts: "cucumber.mjs", python: "behave.ini" };
16
18
  function stackOrThrow(root) {
17
19
  const stack = detectStack(root);
@@ -25,8 +27,10 @@ export function setupVerify(root) {
25
27
  const src = join(templateDir, stack === "python" ? "python" : stack);
26
28
  const created = [];
27
29
  const skipped = [];
28
- // Step stubs are for the example story `nikos init` creates; skip them once it's gone.
29
- const hasExample = existsSync(join(root, "intent/features/getting-started/first-story.feature"));
30
+ // Step stubs are for the example story `nikos init` creates; skip them once
31
+ // it's gone or rewritten into a real story, whose steps they wouldn't match.
32
+ const example = join(root, "intent/features/getting-started/first-story.feature");
33
+ const hasExample = existsSync(example) && readFileSync(example, "utf8").includes(EXAMPLE_STEP);
30
34
  for (const file of walk(src)) {
31
35
  const rel = relative(src, file);
32
36
  if (!hasExample && /first[-_]story/.test(rel))
@@ -0,0 +1,153 @@
1
+ # Quickstart: your first passing scenario in 10 minutes
2
+
3
+ You'll make a tiny tip calculator in an empty repo and finish with one story
4
+ whose acceptance criterion runs as a test and passes. You need Node 20 or
5
+ later and npm. Nothing is installed globally: every `nikos` command runs
6
+ through `npx`.
7
+
8
+ ## 1. Make a repo (1 minute)
9
+
10
+ ```bash
11
+ mkdir tip-calculator && cd tip-calculator
12
+ git init
13
+ npm init -y
14
+ npm pkg set type=module
15
+ ```
16
+
17
+ ## 2. Create the intent/ folder (1 minute)
18
+
19
+ ```bash
20
+ npx -y nikos init --name "Tip Calculator" --key TC
21
+ ```
22
+
23
+ You should see:
24
+
25
+ ```text
26
+ Created intent/ (6 files)
27
+ ✓ intent/ is valid — 1 story, 1 release
28
+
29
+ Next: fill in intent/constitution.md, then write your first story in intent/features/.
30
+ ```
31
+
32
+ `intent/` now holds your story map, a state file, a decision log and one
33
+ starter story, TC-1. [docs/format.md](format.md) explains each file.
34
+
35
+ ## 3. Write the story (2 minutes)
36
+
37
+ Replace the starter story with a real one. Save this as
38
+ **`intent/features/getting-started/first-story.feature`**:
39
+
40
+ ```gherkin
41
+ @TC-1 @release-1 @must @activity-getting-started
42
+ Feature: Add a tip to the bill
43
+
44
+ As a diner
45
+ I want to add a tip to my bill
46
+ So that I know what to pay
47
+
48
+ @AC1 @must
49
+ Scenario: AC1 — A 20% tip on a 50 bill
50
+ Given a bill of 50
51
+ When I add a 20% tip
52
+ Then the total is 60.00
53
+ ```
54
+
55
+ The scenario is the acceptance criterion: TC-1 isn't done until it passes.
56
+ Check the folder is still well formed, and start the story:
57
+
58
+ ```bash
59
+ npx -y nikos validate
60
+ npx -y nikos state set TC-1 in_progress
61
+ ```
62
+
63
+ ```text
64
+ ✓ intent/ is valid — 1 story, 1 release
65
+ TC-1: todo → in_progress
66
+ ```
67
+
68
+ ## 4. Set up the runner (2 minutes)
69
+
70
+ ```bash
71
+ npx -y nikos verify setup
72
+ npm install --save-dev @cucumber/cucumber@^12
73
+ ```
74
+
75
+ `verify setup` notices this is a JavaScript repo and adds `cucumber.mjs`,
76
+ which runs every story in `intent/` as a test. Now run TC-1:
77
+
78
+ ```bash
79
+ npx -y nikos verify TC-1
80
+ ```
81
+
82
+ It fails, and says why: none of the three steps has any code behind it yet.
83
+
84
+ ```text
85
+ 1 scenario (1 undefined)
86
+ 3 steps (3 undefined)
87
+ ```
88
+
89
+ ## 5. Make it pass (3 minutes)
90
+
91
+ Write the code. Save this as **`tip.js`**:
92
+
93
+ ```js
94
+ export function totalWithTip(bill, percent) {
95
+ return (bill * (1 + percent / 100)).toFixed(2);
96
+ }
97
+ ```
98
+
99
+ Connect each step to the code. Save this as **`test/steps/tip.steps.mjs`**:
100
+
101
+ ```js
102
+ import { Given, When, Then } from "@cucumber/cucumber";
103
+ import assert from "node:assert/strict";
104
+ import { totalWithTip } from "../../tip.js";
105
+
106
+ Given("a bill of {int}", function (bill) {
107
+ this.bill = bill;
108
+ });
109
+
110
+ When("I add a {int}% tip", function (percent) {
111
+ this.total = totalWithTip(this.bill, percent);
112
+ });
113
+
114
+ Then("the total is {float}", function (expected) {
115
+ assert.equal(this.total, expected.toFixed(2));
116
+ });
117
+ ```
118
+
119
+ Run it again:
120
+
121
+ ```bash
122
+ npx -y nikos verify TC-1
123
+ ```
124
+
125
+ ```text
126
+ 1 scenario (1 passed)
127
+ 3 steps (3 passed)
128
+ ```
129
+
130
+ ## 6. Call it done (1 minute)
131
+
132
+ ```bash
133
+ npx -y nikos state set TC-1 done
134
+ ```
135
+
136
+ ```text
137
+ TC-1: in_progress → done
138
+ ```
139
+
140
+ `state set … done` runs the scenarios first and refuses if any fail, so a
141
+ story can't be marked done on the agent's word alone.
142
+
143
+ That's the whole loop: write the story, run it, make it pass, mark it done.
144
+
145
+ ## Next: let your agent do it
146
+
147
+ Install nikOS in your agent tool ([docs/install.md](install.md)), then ask:
148
+
149
+ > Add a story for splitting the bill between people, and build it.
150
+
151
+ The `nikos-mode` skill picks the right playbook: it writes the story,
152
+ checks it, plans it, builds it, and stops at "done" only when the new
153
+ scenario passes.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nikos",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "nikOS \u2014 an open-source agent skill stack for spec-driven development. Specs, plans and Cucumber features live in your repo.",
5
5
  "license": "MIT",
6
6
  "author": "Niko Vijay",