nikos 0.0.0-stage → 0.0.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 (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +32 -2
  3. package/dist/cli.js +60 -0
  4. package/dist/commands/bet.js +97 -0
  5. package/dist/commands/clear.js +100 -0
  6. package/dist/commands/decide.js +60 -0
  7. package/dist/commands/decisions.js +71 -0
  8. package/dist/commands/init.js +72 -0
  9. package/dist/commands/next.js +35 -0
  10. package/dist/commands/plan.js +64 -0
  11. package/dist/commands/show.js +82 -0
  12. package/dist/commands/state.js +104 -0
  13. package/dist/commands/validate.js +206 -0
  14. package/dist/commands/verify.js +95 -0
  15. package/dist/lib/project.js +42 -0
  16. package/dist/lint/constitution.js +40 -0
  17. package/dist/lint/gherkin.js +99 -0
  18. package/dist/lint/portable.js +66 -0
  19. package/dist/verify/detect.js +21 -0
  20. package/docs/format.md +296 -0
  21. package/docs/gherkin.md +81 -0
  22. package/docs/install.md +72 -0
  23. package/docs/intentdocs-mapping.md +117 -0
  24. package/package.json +44 -4
  25. package/schemas/bet.schema.json +23 -0
  26. package/schemas/state.schema.json +34 -0
  27. package/schemas/storymap.schema.json +43 -0
  28. package/skills/clear/SKILL.md +55 -0
  29. package/skills/clear-review/SKILL.md +45 -0
  30. package/skills/decisions/SKILL.md +45 -0
  31. package/skills/intent/SKILL.md +39 -0
  32. package/skills/nikos-mode/SKILL.md +61 -0
  33. package/skills/nikos-mode/playbooks/answer.md +9 -0
  34. package/skills/nikos-mode/playbooks/bet.md +14 -0
  35. package/skills/nikos-mode/playbooks/build-a-story.md +14 -0
  36. package/skills/nikos-mode/playbooks/change.md +12 -0
  37. package/skills/nikos-mode/playbooks/idea-to-blueprint.md +16 -0
  38. package/skills/nikos-mode/playbooks/index.md +13 -0
  39. package/skills/nikos-mode/playbooks/validate.md +17 -0
  40. package/skills/nikos-mode/principles/index.md +14 -0
  41. package/skills/verify/SKILL.md +49 -0
  42. package/templates/intent/constitution.md +19 -0
  43. package/templates/intent/decisions.md +12 -0
  44. package/templates/intent/features/getting-started/first-story.feature +12 -0
  45. package/templates/intent/plans/.gitkeep +0 -0
  46. package/templates/intent/state.yaml +4 -0
  47. package/templates/intent/storymap.yaml +10 -0
  48. package/templates/plan.md +13 -0
  49. package/templates/verify/js/cucumber.mjs +6 -0
  50. package/templates/verify/js/test/steps/first-story.steps.mjs +16 -0
  51. package/templates/verify/python/behave.ini +4 -0
  52. package/templates/verify/python/steps/first_story_steps.py +19 -0
  53. package/templates/verify/ts/cucumber.mjs +6 -0
  54. package/templates/verify/ts/test/steps/first-story.steps.ts +16 -0
@@ -0,0 +1,66 @@
1
+ import { readdirSync, readFileSync, statSync } from "node:fs";
2
+ import { join, relative } from "node:path";
3
+ import { parse } from "yaml";
4
+ /** The only frontmatter keys every harness (Claude Code, Cursor, Codex) understands. */
5
+ const ALLOWED_KEYS = ["name", "description"];
6
+ /** Tool names that exist in one harness only. A portable skill describes the action instead. */
7
+ const HARNESS_TOOLS = [
8
+ "TodoWrite", "TodoRead", "TaskCreate", "TaskUpdate", "TaskList", "AskUserQuestion",
9
+ "EnterPlanMode", "ExitPlanMode", "NotebookEdit", "SlashCommand", "todo_write", "update_plan",
10
+ "apply_patch", "$ARGUMENTS", "allowed-tools",
11
+ ];
12
+ /** Lint one SKILL.md (or a file it links to) for harness-specific features. */
13
+ export function lintSkill(text, { isEntry = true } = {}) {
14
+ const issues = [];
15
+ let body = text;
16
+ if (isEntry) {
17
+ const m = /^---\n([\s\S]*?)\n---\n/.exec(text);
18
+ if (!m) {
19
+ issues.push({ level: "error", message: "has no frontmatter", hint: "start with ---, name: and description:, then ---" });
20
+ }
21
+ else {
22
+ body = text.slice(m[0].length);
23
+ let meta = {};
24
+ try {
25
+ meta = parse(m[1]) ?? {};
26
+ }
27
+ catch (err) {
28
+ issues.push({ level: "error", message: `frontmatter isn't valid YAML: ${err.message.split("\n")[0]}` });
29
+ }
30
+ for (const key of Object.keys(meta)) {
31
+ if (!ALLOWED_KEYS.includes(key)) {
32
+ issues.push({ level: "error", message: `frontmatter key '${key}' isn't portable`, hint: "use only name and description" });
33
+ }
34
+ }
35
+ for (const key of ALLOWED_KEYS) {
36
+ if (typeof meta[key] !== "string" || !meta[key].trim()) {
37
+ issues.push({ level: "error", message: `frontmatter is missing '${key}'` });
38
+ }
39
+ }
40
+ }
41
+ }
42
+ for (const tool of HARNESS_TOOLS) {
43
+ if (body.includes(tool)) {
44
+ issues.push({ level: "error", message: `names the harness-only tool '${tool}'`, hint: "describe the action (\"your task list\") instead" });
45
+ }
46
+ }
47
+ return issues;
48
+ }
49
+ /** Lint every Markdown file under a skills/ folder. SKILL.md files are entry points and need frontmatter. */
50
+ export function lintSkills(dir) {
51
+ const issues = [];
52
+ const walk = (d) => {
53
+ for (const name of readdirSync(d)) {
54
+ const path = join(d, name);
55
+ if (statSync(path).isDirectory())
56
+ walk(path);
57
+ else if (name.endsWith(".md")) {
58
+ const file = relative(dir, path);
59
+ for (const i of lintSkill(readFileSync(path, "utf8"), { isEntry: name === "SKILL.md" }))
60
+ issues.push({ ...i, file });
61
+ }
62
+ }
63
+ };
64
+ walk(dir);
65
+ return issues;
66
+ }
@@ -0,0 +1,21 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ const PYTHON_MARKERS = ["pyproject.toml", "requirements.txt", "setup.py", "setup.cfg", "Pipfile"];
4
+ /** Pick the Cucumber runner's stack from the files at the repo root. Undefined means ask the person. */
5
+ export function detectStack(root) {
6
+ const pkgPath = join(root, "package.json");
7
+ if (existsSync(pkgPath)) {
8
+ let pkg = {};
9
+ try {
10
+ pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
11
+ }
12
+ catch {
13
+ // An unreadable package.json is still a JS project.
14
+ }
15
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
16
+ return existsSync(join(root, "tsconfig.json")) || "typescript" in deps ? "ts" : "js";
17
+ }
18
+ if (PYTHON_MARKERS.some((f) => existsSync(join(root, f))))
19
+ return "python";
20
+ return undefined;
21
+ }
package/docs/format.md ADDED
@@ -0,0 +1,296 @@
1
+ # The intent/ format
2
+
3
+ Format version: **1**
4
+
5
+ nikOS keeps a project's intent — what it's for, what to build, how it's going —
6
+ in an `intent/` folder at the root of the repo. Everything is plain text, so
7
+ agents, humans, git and code review all see the same thing.
8
+
9
+ ```
10
+ intent/
11
+ constitution.md the project's vision
12
+ storymap.yaml activities, releases and story order
13
+ features/
14
+ <activity>/
15
+ <story-slug>.feature one story, its criteria as scenarios
16
+ plans/
17
+ <story-id>.v<N>.md versioned implementation plans
18
+ decisions.md append-only decision log
19
+ state.yaml status, blockers and the run queue
20
+ outreach/ optional, drafts from the validate playbook
21
+ <date>-<channel>.md
22
+ bets/ optional, time-boxed bets (see Bets)
23
+ <bet-id>.md
24
+ ```
25
+
26
+ Two rules hold across every file:
27
+
28
+ 1. **Specs describe intent, not implementation.** Feature files and the
29
+ constitution say what and why. File paths, frameworks and code belong in
30
+ plans and decisions.
31
+ 2. **Changing state never edits a spec.** Status, owners, blockers and dates
32
+ live in `state.yaml`, so a spec's diff only changes when the intent does.
33
+
34
+ Every file below is listed with its **purpose**, **path** and **format**.
35
+
36
+ ---
37
+
38
+ ## constitution.md
39
+
40
+ **Purpose:** the project's vision, answered once and refined as you learn.
41
+ Every story should trace back to it.
42
+
43
+ **Path:** `intent/constitution.md`
44
+
45
+ **Format:** Markdown with YAML front matter and exactly these five `##`
46
+ sections, in this order:
47
+
48
+ ```markdown
49
+ ---
50
+ name: Hello Todo
51
+ idea: A todo list that only shows today's three most important tasks.
52
+ ---
53
+
54
+ ## Users
55
+ Who it's for.
56
+
57
+ ## Problem
58
+ What hurts today, in their words.
59
+
60
+ ## Switch
61
+ What makes them switch now, and from what.
62
+
63
+ ## First
64
+ The smallest first version that proves it.
65
+
66
+ ## Proof
67
+ How you'll know it's working.
68
+ ```
69
+
70
+ Further `##` sections may follow the five required ones. The
71
+ idea-to-blueprint playbook writes `## Jobs to be done` and
72
+ `## Founding hypothesis`; the validate playbook writes `## Validation`, one entry per round of
73
+ outreach, and keeps its drafts in `intent/outreach/`. A draft is marked
74
+ `Status: draft, not sent` until the founder signs it off; the founder sends it.
75
+ `nikos validate` checks the front matter has `name` and `idea`, and that the
76
+ five vision sections come first, in order, and aren't empty.
77
+
78
+ ---
79
+
80
+ ## storymap.yaml
81
+
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
84
+ themselves live in feature files.
85
+
86
+ **Path:** `intent/storymap.yaml`
87
+
88
+ **Format:** YAML.
89
+
90
+ ```yaml
91
+ format_version: 1
92
+ project: hello-todo
93
+ key: HT # story id prefix: HT-1, HT-2 …
94
+ activities:
95
+ - id: tasks # slug, matches the features/<activity>/ folder
96
+ title: Manage tasks
97
+ releases:
98
+ - number: 1
99
+ title: MVP
100
+ stories: [HT-1, HT-2] # build order within the release
101
+ - number: 2
102
+ title: Enhancements
103
+ stories: [HT-3]
104
+ ```
105
+
106
+ Rules:
107
+
108
+ - Every story id appears in exactly one release.
109
+ - Every story id has exactly one feature file and one `state.yaml` entry.
110
+ - Release numbers start at 1 and have no gaps.
111
+
112
+ ---
113
+
114
+ ## features/&lt;activity&gt;/&lt;story-slug&gt;.feature
115
+
116
+ **Purpose:** one user story and its acceptance criteria, written so they
117
+ run as tests.
118
+
119
+ **Path:** `intent/features/<activity-id>/<story-slug>.feature`, where the
120
+ activity id matches `storymap.yaml` and the slug is the story title in
121
+ kebab-case.
122
+
123
+ **Format:** Gherkin. One `Feature` per file. The description holds the user
124
+ story; each acceptance criterion is a `Scenario` (or `Scenario Outline`)
125
+ titled with its label. Full rules are in [gherkin.md](gherkin.md).
126
+
127
+ ```gherkin
128
+ @HT-1 @release-1 @must @activity-tasks
129
+ Feature: Add a task
130
+
131
+ As a busy person
132
+ I want to add a task in one step
133
+ So that capturing it is faster than forgetting it
134
+
135
+ @AC1 @must
136
+ Scenario: AC1 — Adding a task shows it at the top
137
+ Given my list is empty
138
+ When I add the task "Call the bank"
139
+ Then I see "Call the bank" at the top of my list
140
+ ```
141
+
142
+ ---
143
+
144
+ ## plans/&lt;story-id&gt;.v&lt;N&gt;.md
145
+
146
+ **Purpose:** how a story will be built. Plans are versioned: a new approach
147
+ is a new file, so history is never lost.
148
+
149
+ **Path:** `intent/plans/<story-id>.v<N>.md`, for example
150
+ `intent/plans/HT-1.v2.md`. `N` starts at 1 and increases by one.
151
+
152
+ **Format:** Markdown with front matter, then one `##` section per step:
153
+
154
+ ```markdown
155
+ ---
156
+ story: HT-1
157
+ version: 2
158
+ created: 2026-11-03
159
+ supersedes: 1 # omit for v1
160
+ summary: One to three plain sentences on the approach.
161
+ ---
162
+
163
+ ## 1. Store tasks locally
164
+ **Why:** tasks survive a refresh.
165
+ **Criteria:** AC1
166
+ **Files:** src/store.ts
167
+
168
+ Notes for the agent.
169
+ ```
170
+
171
+ These fields match intentdocs plans one to one (see the mapping doc).
172
+
173
+ Start a new version with `nikos plan new <story-id>`. It writes the next
174
+ `v<N>` from a template, sets `supersedes`, and refuses to overwrite an
175
+ existing file.
176
+
177
+ ---
178
+
179
+ ## decisions.md
180
+
181
+ **Purpose:** why things are the way they are. Append-only; never rewrite an
182
+ entry, add a new one that supersedes it.
183
+
184
+ **Path:** `intent/decisions.md`
185
+
186
+ **Format:** Markdown. One `##` entry per decision, newest last:
187
+
188
+ ```markdown
189
+ ## 2026-11-03 — Store tasks in localStorage (HT-1)
190
+ **Category:** architecture
191
+ **Supersedes:** none
192
+
193
+ Why this, and what we rejected.
194
+ ```
195
+
196
+ The heading is `date — title (story id)`; the story id is optional for
197
+ project-wide decisions. Category is one of `product`, `architecture`,
198
+ `design`, `process`.
199
+
200
+ ---
201
+
202
+ ## state.yaml
203
+
204
+ **Purpose:** everything that changes as work happens: status, who's on it,
205
+ blockers, and the run queue. Kept apart so specs stay clean.
206
+
207
+ **Path:** `intent/state.yaml`
208
+
209
+ **Format:** YAML.
210
+
211
+ ```yaml
212
+ format_version: 1
213
+ stories:
214
+ HT-1:
215
+ status: done # todo | in_progress | needs_rework | done
216
+ claimed_by: claude-code # optional
217
+ plan_version: 2 # optional, the plan in use
218
+ blockers: [] # optional, plain sentences
219
+ updated: 2026-11-03
220
+ HT-2:
221
+ status: todo
222
+ run: # optional, an ordered build queue
223
+ queue: [HT-2]
224
+ ```
225
+
226
+ Status moves `todo → in_progress → done`, or `in_progress → needs_rework →
227
+ in_progress`. Only a passing verification can set `done` (see the
228
+ build-a-story playbook).
229
+
230
+ ---
231
+
232
+ ## outreach/&lt;date&gt;-&lt;channel&gt;.md (optional)
233
+
234
+ **Purpose:** outreach drafted to test the idea with real people, kept so the
235
+ founder can review it and the results can be traced back to it.
236
+
237
+ **Path:** `intent/outreach/<yyyy-mm-dd>-<channel>.md`
238
+
239
+ **Format:** Markdown. The first line is the status: `Status: draft, not sent`
240
+ until the founder signs it off, then `Status: signed off <date>, for the
241
+ person to send`. Then who it's for, the message, the questions to ask and,
242
+ optionally, a demo or reel script. Written by the validate playbook; the
243
+ founder sends it, never the agent.
244
+
245
+ ---
246
+
247
+ ## bets/&lt;bet-id&gt;.md (optional)
248
+
249
+ **Purpose:** a time-boxed bet that a set of stories will move a measure.
250
+
251
+ **Path:** `intent/bets/<bet-id>.md`, where `<bet-id>` is lowercase words
252
+ joined by hyphens.
253
+
254
+ **Format:** Markdown with YAML front matter, then free-form notes. Create one
255
+ with `nikos bet new`; the bet playbook frames and closes it.
256
+
257
+ ```markdown
258
+ ---
259
+ id: faster-reorder
260
+ hypothesis: We believe drag to reorder will make people plan their day in the app because they reorder on paper today.
261
+ key_result: Share of daily users who reorder at least once
262
+ expected_uplift: from 10% to 30%
263
+ time_box: 2026-12-01
264
+ blockers: []
265
+ stories: [HT-3]
266
+ status: open
267
+ ---
268
+
269
+ ## Why we think so
270
+ The evidence behind the hypothesis.
271
+
272
+ ## Outcome
273
+ Filled in when the time box ends.
274
+ ```
275
+
276
+ | Field | Required | Meaning |
277
+ | --- | --- | --- |
278
+ | `id` | yes | Matches the file name |
279
+ | `hypothesis` | yes | What you believe and why |
280
+ | `key_result` | yes | The one measure that says whether it worked |
281
+ | `expected_uplift` | yes | How far you expect it to move, from what to what |
282
+ | `time_box` | yes | End date, `YYYY-MM-DD` |
283
+ | `blockers` | yes | What stands in the way; `[]` if nothing |
284
+ | `stories` | yes | At least one story id; each must be in `storymap.yaml` |
285
+ | `status` | yes | `open \| won \| lost \| killed` |
286
+
287
+ `nikos validate` checks every field against `schemas/bet.schema.json`, that
288
+ the id matches the file name, and that every linked story exists.
289
+
290
+ ---
291
+
292
+ ## Versioning this format
293
+
294
+ `format_version` in `storymap.yaml` and `state.yaml` is the version of this
295
+ document. Breaking changes bump it; `nikos validate` reads it and explains
296
+ any migration needed.
@@ -0,0 +1,81 @@
1
+ # Writing stories as feature files
2
+
3
+ Every story is one Gherkin `.feature` file in
4
+ `intent/features/<activity>/<story-slug>.feature`. The file is both the spec
5
+ and the test: each acceptance criterion is a scenario that Cucumber can run.
6
+ `nikos validate` checks all the rules on this page.
7
+
8
+ ## The shape of a story
9
+
10
+ ```gherkin
11
+ @HT-1 @release-1 @must @activity-tasks @effort-S
12
+ Feature: Add a task
13
+
14
+ As a busy person
15
+ I want to add a task in one step
16
+ So that capturing it is faster than forgetting it
17
+
18
+ @AC1 @must
19
+ Scenario: AC1 — Adding a task shows it at the top
20
+ Given my list is empty
21
+ When I add the task "Call the bank"
22
+ Then I see "Call the bank" at the top of my list
23
+
24
+ @AC2 @should
25
+ Scenario: AC2 — Blank tasks are ignored
26
+ Given my list is empty
27
+ When I add the task ""
28
+ Then my list is still empty
29
+ ```
30
+
31
+ ## Rules
32
+
33
+ **One story per file.** Exactly one `Feature`, and exactly one story id tag.
34
+
35
+ **The user story goes in the Feature description.** Three lines under
36
+ `Feature:`, starting `As a`, `I want` and `So that`.
37
+
38
+ **Each acceptance criterion is a scenario.** Tag it `@AC1`, `@AC2` … and
39
+ start its title with the same label (`AC1 — …`). Labels are unique within
40
+ the file. A `Scenario Outline` counts as one criterion. Scenarios may sit
41
+ inside a `Rule:` block.
42
+
43
+ **Every scenario has a When and a Then.** `Given` is optional.
44
+
45
+ **Priority is a tag.** Exactly one of `@must`, `@should` or `@could` on the
46
+ Feature (the story's priority), and optionally one on each scenario (the
47
+ criterion's priority).
48
+
49
+ ## Allowed Feature tags
50
+
51
+ | Tag | Meaning | Required |
52
+ |---|---|---|
53
+ | `@HT-1` | story id, using the project key | yes |
54
+ | `@release-N` | release the story is in | yes |
55
+ | `@must` / `@should` / `@could` | story priority | yes |
56
+ | `@activity-<id>` | activity, matching the folder name | no |
57
+ | `@effort-XS` … `@effort-XL` | size estimate | no |
58
+
59
+ Anything else is a warning, so you notice typos.
60
+
61
+ ## Never put status in a feature
62
+
63
+ Tags like `@todo`, `@wip`, `@in-progress`, `@done`, `@blocked` or `@ready`
64
+ are errors. Status, owners, blockers and dates live in `intent/state.yaml`,
65
+ so a feature file only changes when the intent changes and its git history
66
+ reads as a history of decisions about the product.
67
+
68
+ ## Keep it about behaviour, not implementation
69
+
70
+ Write steps the way a user would describe what happens: "When I add the task
71
+ 'Call the bank'", not "When I POST to /api/tasks". Implementation detail
72
+ belongs in the story's plan. `nikos clear` flags file paths, endpoints and
73
+ framework names in feature text.
74
+
75
+ ## Checking your work
76
+
77
+ ```sh
78
+ npx nikos validate
79
+ ```
80
+
81
+ Errors block (exit code 1); warnings are shown but don't fail.
@@ -0,0 +1,72 @@
1
+ # Installing nikOS in your agent tool
2
+
3
+ nikOS is one set of skills in `skills/`. Each tool reads its own small
4
+ manifest, and every manifest points at that same folder, so no skill file is
5
+ copied per tool.
6
+
7
+ | Tool | Manifest | Install |
8
+ | --- | --- | --- |
9
+ | Claude Code | `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json` | `/plugin install nikos --marketplace nikovijay/NikOS` |
10
+ | Codex | `.codex-plugin/plugin.json`, `.agents/plugins/marketplace.json` | `codex plugin marketplace add nikovijay/NikOS` |
11
+ | Cursor | `.cursor-plugin/plugin.json` | Add the repo as a marketplace (below) |
12
+
13
+ After installing, ask the agent to plan, build or check a story. The
14
+ `nikos-mode` skill picks the playbook.
15
+
16
+ ## Claude Code
17
+
18
+ In a session:
19
+
20
+ ```
21
+ /plugin install nikos --marketplace nikovijay/NikOS
22
+ ```
23
+
24
+ That works in one step on Claude Code 2.1.275 or later. On older versions,
25
+ add the marketplace first, then install:
26
+
27
+ ```
28
+ /plugin marketplace add nikovijay/NikOS
29
+ /plugin install nikos@nikos
30
+ ```
31
+
32
+ From a terminal, the same commands are `claude plugin marketplace add
33
+ nikovijay/NikOS` and `claude plugin install nikos@nikos`.
34
+
35
+ ## Codex
36
+
37
+ ```
38
+ codex plugin marketplace add nikovijay/NikOS
39
+ ```
40
+
41
+ Then install nikOS from the Plugins directory. Update it later with `codex
42
+ plugin marketplace upgrade`.
43
+
44
+ ## Cursor
45
+
46
+ Cursor installs plugins from a marketplace in its settings rather than a
47
+ command. Add `https://github.com/nikovijay/NikOS` as a marketplace (Plugins,
48
+ then Add Marketplace, then Import from Repo), and install nikOS from it.
49
+
50
+ To try it without a marketplace, copy the repo to
51
+ `~/.cursor/plugins/local/nikos` and run "Developer: Reload Window".
52
+
53
+ ## The command-line tool
54
+
55
+ The skills run the `nikos` command. When it isn't installed, they run it
56
+ through `npx -y nikos`, so nothing has to be installed globally. To install
57
+ it anyway: `npm install -g nikos`.
58
+
59
+ ## Formats checked
60
+
61
+ Plugin formats change often. These were read on 2026-11-04 (no page showed a
62
+ version):
63
+
64
+ - Claude Code: https://code.claude.com/docs/en/plugins-reference and
65
+ https://code.claude.com/docs/en/plugins/marketplace-reference. Checked with
66
+ `claude plugin validate .` on Claude Code 2.1.318.
67
+ - Cursor: https://cursor.com/docs/reference/plugins
68
+ - Codex: https://developers.openai.com/plugins/build/plugins
69
+
70
+ All three find skills as `skills/<name>/SKILL.md` at the plugin root.
71
+ `test/install.test.ts` checks the manifests agree with each other and with
72
+ the skills folder. `evals/install.md` records each install tried.
@@ -0,0 +1,117 @@
1
+ # Mapping intent/ to intentdocs
2
+
3
+ `intentdocs push` and `intentdocs pull` translate between the local
4
+ `intent/` folder and an intentdocs project. This table is the contract: every
5
+ local field maps to an intentdocs field, or is marked **local-only**.
6
+ Fields that exist only in intentdocs are listed at the end.
7
+
8
+ ## Project and vision
9
+
10
+ | Local | intentdocs | Notes |
11
+ |---|---|---|
12
+ | `constitution.md` front matter `name` | project name | |
13
+ | `constitution.md` front matter `idea` | project idea | |
14
+ | `## Users` | vision `users` | |
15
+ | `## Problem` | vision `problem` | |
16
+ | `## Switch` | vision `switch` | |
17
+ | `## First` | vision `first` | |
18
+ | `## Proof` | vision `proof` | |
19
+ | extra `##` sections (e.g. `## Validation`) | **local-only** | pushed as a project note in a later format version |
20
+ | `storymap.yaml` `key` | project story key prefix | e.g. `HT` → `HT-1` |
21
+ | `storymap.yaml` `project` | **local-only** | slug used for paths |
22
+ | `storymap.yaml` `format_version` | **local-only** | |
23
+
24
+ ## Activities and releases
25
+
26
+ | Local | intentdocs | Notes |
27
+ |---|---|---|
28
+ | `activities[].title` | story `activity` | intentdocs groups by activity name |
29
+ | `activities[].id` | **local-only** | folder slug under `features/` |
30
+ | `releases[].number` | release order | |
31
+ | `releases[].title` | release label | |
32
+ | `releases[].stories` order | build sequence within the release | |
33
+
34
+ ## Stories (feature files)
35
+
36
+ | Local | intentdocs | Notes |
37
+ |---|---|---|
38
+ | story id tag, e.g. `@HT-1` | story `key` | |
39
+ | `Feature:` title | story `title` | |
40
+ | description `As a …` | `as_a` | |
41
+ | description `I want …` | `i_want` | |
42
+ | description `So that …` | `so_that` | |
43
+ | `@must` / `@should` / `@could` on the Feature | story `priority` | |
44
+ | `@release-N` | story `release` | must agree with `storymap.yaml` |
45
+ | `@activity-<id>` | story `activity` | resolved to the activity title |
46
+ | `@effort-XS` … `@effort-XL` (optional) | story `effort` | |
47
+ | file path | **local-only** | |
48
+
49
+ ## Acceptance criteria (scenarios)
50
+
51
+ | Local | intentdocs | Notes |
52
+ |---|---|---|
53
+ | `@AC<n>` tag and scenario title prefix | criterion `label` | |
54
+ | scenario title after the label + its steps | criterion `text` | pushed as one Given/When/Then sentence |
55
+ | `@must` / `@should` / `@could` on the Scenario | criterion `priority` | |
56
+ | scenario pass/fail from `nikos verify` | criterion `last_result` | sent via report_criteria |
57
+ | step definition file and test name | linked tests | sent via save_tests |
58
+
59
+ ## Plans
60
+
61
+ | Local | intentdocs | Notes |
62
+ |---|---|---|
63
+ | file `plans/<id>.v<N>.md` | plan `version` N | |
64
+ | front matter `summary` | plan `summary` | |
65
+ | `## <n>. <title>` | step `title` | |
66
+ | `**Why:**` | step `why` | |
67
+ | `**Criteria:**` | step `criteria` | labels resolved to criterion ids |
68
+ | `**Files:**` | step `files` | |
69
+ | `**Tests:**` (optional) | step `tests` | |
70
+ | `**Needs you:**` (optional) | step `needs_you.question` | |
71
+ | body text | step `agent_notes` | |
72
+ | front matter `risk` (optional) | plan `risk` | |
73
+ | front matter `introduces` (optional) | plan `introduces` | new dependencies |
74
+ | front matter `supersedes`, `created` | **local-only** | intentdocs keeps its own history |
75
+
76
+ ## Decisions
77
+
78
+ | Local | intentdocs | Notes |
79
+ |---|---|---|
80
+ | entry heading title | decision `title` | |
81
+ | entry body | decision `description` | |
82
+ | `**Category:**` | decision `category` | |
83
+ | entry date | decision created date | |
84
+ | story id in heading | decision linked story | |
85
+ | `**Supersedes:**` | **local-only** | intentdocs amends instead |
86
+
87
+ ## State
88
+
89
+ Status isn't pushed: intentdocs sets it. New stories start as To do,
90
+ existing ones keep theirs, and they move through build and acceptance in
91
+ intentdocs. `intentdocs push` still sends the local status, and says how
92
+ many it ignored.
93
+
94
+ | Local | intentdocs | Notes |
95
+ |---|---|---|
96
+ | `status: todo` | **not pushed** | intentdocs sets status |
97
+ | `status: in_progress` | **not pushed** | intentdocs sets status |
98
+ | `status: needs_rework` | **not pushed** | intentdocs sets status |
99
+ | `status: done` | **not pushed** | intentdocs sets status; its own done needs acceptance after build |
100
+ | `blockers` | raised blockers | |
101
+ | `plan_version` | current plan version | |
102
+ | `claimed_by` | story claim | |
103
+ | `run.queue` | build run story order | |
104
+ | `updated` | **local-only** | |
105
+
106
+ ## Bets
107
+
108
+ | Local | intentdocs | Notes |
109
+ |---|---|---|
110
+ | `outreach/*.md`, `## Validation` | **local-only** | intentdocs keeps the vision answers, not outreach drafts or results |
111
+ | `bets/*.md` | **local-only** | intentdocs has no bet object yet |
112
+
113
+ ## intentdocs-only (not pulled into files)
114
+
115
+ Comments, design references, plan approvals, story approval after build,
116
+ founder to-dos, releases readiness checks, collaborators and workspace
117
+ settings stay in intentdocs. `intentdocs pull` never writes them to the repo.