@rasensio/aidlc-content 1.38.0 → 1.40.0

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.
@@ -0,0 +1,17 @@
1
+ import type { HowTo } from './types.js';
2
+ /**
3
+ * The only headings a how-to body may contain at level 1 or 2, in this order
4
+ * (docs-how-to-recipes/AC-3). Holding the list exact — no `#` heading, no extra
5
+ * `##` — is also what keeps the page to a single `h1` (AC-7): the title comes
6
+ * from frontmatter, so a `# Title` in the body would be a second one.
7
+ */
8
+ export declare const HOWTO_SECTIONS: readonly ["What you'll do", "Steps", "Check it worked"];
9
+ /** Parse one how-to. `filename` only labels errors. */
10
+ export declare function parseHowToSource(raw: string, filename?: string): HowTo;
11
+ /**
12
+ * Every how-to, sorted by `order` (AC-5). Throws on the first bad file — this
13
+ * runs inside `next build`, so a bad recipe fails the build rather than shipping.
14
+ */
15
+ export declare function loadHowTos(dir?: string): HowTo[];
16
+ export declare function getHowTo(slug: string): HowTo | undefined;
17
+ //# sourceMappingURL=howto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"howto.d.ts","sourceRoot":"","sources":["../src/howto.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAOxC;;;;;GAKG;AACH,eAAO,MAAM,cAAc,yDAA0D,CAAC;AA0FtF,uDAAuD;AACvD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAGtE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAkB,GAAG,KAAK,EAAE,CAwB3D;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAExD"}
package/dist/howto.js ADDED
@@ -0,0 +1,121 @@
1
+ import { fileURLToPath } from 'node:url';
2
+ import { resolve, dirname } from 'node:path';
3
+ import { readdirSync, readFileSync, existsSync } from 'node:fs';
4
+ import { parse as parseYaml } from 'yaml';
5
+ const CONTENT_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
6
+ const HOWTO_DIR = resolve(CONTENT_ROOT, 'howto');
7
+ const SLUG_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;
8
+ /**
9
+ * The only headings a how-to body may contain at level 1 or 2, in this order
10
+ * (docs-how-to-recipes/AC-3). Holding the list exact — no `#` heading, no extra
11
+ * `##` — is also what keeps the page to a single `h1` (AC-7): the title comes
12
+ * from frontmatter, so a `# Title` in the body would be a second one.
13
+ */
14
+ export const HOWTO_SECTIONS = ["What you'll do", 'Steps', 'Check it worked'];
15
+ function fail(filename, message) {
16
+ throw new Error(filename ? `How-to "${filename}": ${message}` : message);
17
+ }
18
+ function parseFrontmatter(raw, filename) {
19
+ const match = raw.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
20
+ if (!match)
21
+ fail(filename, 'missing YAML frontmatter');
22
+ const parsed = (parseYaml(match[1]) ?? {});
23
+ const { title, description, order, slug } = parsed;
24
+ // Same four rules as tutorials, so one mental model covers both (AC-2).
25
+ if (typeof title !== 'string' || title.length === 0 || title.length > 100) {
26
+ fail(filename, 'invalid title: must be a string of 1-100 characters');
27
+ }
28
+ if (typeof description !== 'string' || description.length === 0 || description.length > 300) {
29
+ fail(filename, 'invalid description: must be a string of 1-300 characters');
30
+ }
31
+ if (typeof order !== 'number' || !Number.isInteger(order) || order < 1 || order > 999) {
32
+ fail(filename, 'invalid order: must be an integer between 1 and 999');
33
+ }
34
+ if (typeof slug !== 'string' || slug.length === 0 || slug.length > 80 || !SLUG_PATTERN.test(slug)) {
35
+ fail(filename, 'invalid slug: must be lowercase alphanumeric with hyphens, max 80 characters');
36
+ }
37
+ return { meta: { title, description, order, slug }, body: match[2] };
38
+ }
39
+ /**
40
+ * Level-1 and level-2 headings outside code fences. A recipe may well show a
41
+ * Markdown file in a fence, and a `## ` inside it is content, not structure.
42
+ */
43
+ function topHeadings(lines) {
44
+ const headings = [];
45
+ let fence = null;
46
+ lines.forEach((line, index) => {
47
+ const marker = line.match(/^\s*(```|~~~)/)?.[1];
48
+ if (marker) {
49
+ if (fence === null)
50
+ fence = marker;
51
+ else if (fence === marker)
52
+ fence = null;
53
+ return;
54
+ }
55
+ if (fence !== null)
56
+ return;
57
+ const m = line.match(/^(#{1,2})\s+(.+?)\s*#*\s*$/);
58
+ if (m)
59
+ headings.push({ level: m[1].length, text: m[2], line: index });
60
+ });
61
+ return headings;
62
+ }
63
+ function splitSections(body, filename) {
64
+ const lines = body.split('\n');
65
+ const headings = topHeadings(lines);
66
+ const stray = headings.find((h) => h.level === 1);
67
+ if (stray) {
68
+ fail(filename, `level-1 heading "# ${stray.text}" is not allowed — the title comes from frontmatter`);
69
+ }
70
+ HOWTO_SECTIONS.forEach((expected, i) => {
71
+ const found = headings[i];
72
+ if (!found)
73
+ fail(filename, `missing heading "## ${expected}"`);
74
+ if (found.text !== expected) {
75
+ fail(filename, `expected heading "## ${expected}" but found "## ${found.text}"`);
76
+ }
77
+ });
78
+ if (headings.length > HOWTO_SECTIONS.length) {
79
+ fail(filename, `unexpected heading "## ${headings[HOWTO_SECTIONS.length].text}"`);
80
+ }
81
+ const text = (i) => {
82
+ const start = headings[i].line + 1;
83
+ const end = i + 1 < headings.length ? headings[i + 1].line : lines.length;
84
+ return lines.slice(start, end).join('\n').trim();
85
+ };
86
+ return { whatYoullDo: text(0), steps: text(1), checkItWorked: text(2) };
87
+ }
88
+ /** Parse one how-to. `filename` only labels errors. */
89
+ export function parseHowToSource(raw, filename) {
90
+ const { meta, body } = parseFrontmatter(raw, filename);
91
+ return { ...meta, body, sections: splitSections(body, filename) };
92
+ }
93
+ /**
94
+ * Every how-to, sorted by `order` (AC-5). Throws on the first bad file — this
95
+ * runs inside `next build`, so a bad recipe fails the build rather than shipping.
96
+ */
97
+ export function loadHowTos(dir = HOWTO_DIR) {
98
+ if (!existsSync(dir))
99
+ return [];
100
+ const entries = readdirSync(dir)
101
+ .filter((f) => f.endsWith('.md'))
102
+ .sort()
103
+ .map((filename) => ({
104
+ filename,
105
+ howTo: parseHowToSource(readFileSync(resolve(dir, filename), 'utf8'), filename),
106
+ }));
107
+ // A property of the set, not of one file, so it lives here (AC-4).
108
+ const owners = new Map();
109
+ for (const { filename, howTo } of entries) {
110
+ const first = owners.get(howTo.slug);
111
+ if (first !== undefined) {
112
+ throw new Error(`How-to slug "${howTo.slug}" is used by both "${first}" and "${filename}" — two pages would share one URL`);
113
+ }
114
+ owners.set(howTo.slug, filename);
115
+ }
116
+ return entries.map((e) => e.howTo).sort((a, b) => a.order - b.order);
117
+ }
118
+ export function getHowTo(slug) {
119
+ return loadHowTos().find((h) => h.slug === slug);
120
+ }
121
+ //# sourceMappingURL=howto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"howto.js","sourceRoot":"","sources":["../src/howto.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -7,5 +7,6 @@ export { loadPhases, getPhase } from './phases.js';
7
7
  export { loadRules } from './rules.js';
8
8
  export { loadBoardWorkflow, BOARD_WORKFLOW_PATH } from './recipes.js';
9
9
  export { loadTutorials, getTutorial, getSeries, parseTutorialSource } from './tutorials.js';
10
- export type { Skill, WorkflowTemplate, GuidanceLayer, GlossaryTerm, CapabilityMap, QuestionRendering, PhaseDefinition, Rule, CodeSample, ContentReference, TutorialStep, Tutorial, WidgetKind, WidgetReference } from './types.js';
10
+ export { loadHowTos, getHowTo, parseHowToSource, HOWTO_SECTIONS } from './howto.js';
11
+ export type { Skill, WorkflowTemplate, GuidanceLayer, GlossaryTerm, CapabilityMap, QuestionRendering, PhaseDefinition, Rule, CodeSample, ContentReference, TutorialStep, Tutorial, WidgetKind, WidgetReference, HowTo } from './types.js';
11
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC5F,YAAY,EAAE,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,EAAE,gBAAgB,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC5F,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACpF,YAAY,EAAE,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,EAAE,gBAAgB,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -7,4 +7,5 @@ export { loadPhases, getPhase } from './phases.js';
7
7
  export { loadRules } from './rules.js';
8
8
  export { loadBoardWorkflow, BOARD_WORKFLOW_PATH } from './recipes.js';
9
9
  export { loadTutorials, getTutorial, getSeries, parseTutorialSource } from './tutorials.js';
10
+ export { loadHowTos, getHowTo, parseHowToSource, HOWTO_SECTIONS } from './howto.js';
10
11
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC5F,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
package/dist/types.d.ts CHANGED
@@ -133,4 +133,22 @@ export interface Tutorial {
133
133
  /** Position within `series`. Falls back to `order` when absent (AC-9). */
134
134
  seriesOrder?: number;
135
135
  }
136
+ /**
137
+ * One task-shaped page: the steps to do one thing, and how to check it worked
138
+ * (docs-how-to-recipes). Unlike a tutorial it teaches nothing, so its shape is
139
+ * fixed to exactly three sections, in order.
140
+ */
141
+ export interface HowTo {
142
+ title: string;
143
+ description: string;
144
+ order: number;
145
+ slug: string;
146
+ /** The full body after the frontmatter. */
147
+ body: string;
148
+ sections: {
149
+ whatYoullDo: string;
150
+ steps: string;
151
+ checkItWorked: string;
152
+ };
153
+ }
136
154
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ ---
2
+ title: Add AIDLC to a project you already have
3
+ description: Install AIDLC into an existing repository so your AI assistant starts with real knowledge of the code.
4
+ order: 10
5
+ slug: add-to-existing-project
6
+ ---
7
+
8
+ ## What you'll do
9
+
10
+ Install the CLI and run `init` in your repository. It adds the AIDLC files and writes a
11
+ first description of your code for your AI assistant to read. None of your code is changed.
12
+
13
+ ## Steps
14
+
15
+ 1. Install the CLI once, so `aidlc` is on your path:
16
+
17
+ ```bash
18
+ npm install -g @rasensio/aidlc
19
+ ```
20
+
21
+ 2. Go to the root of your repository and run `init`. It asks which AI tools you use:
22
+
23
+ ```bash
24
+ cd path/to/your-repo
25
+ aidlc init
26
+ ```
27
+
28
+ To skip the questions and set up one tool, name it instead:
29
+
30
+ ```bash
31
+ aidlc init --platform claude-code
32
+ ```
33
+
34
+ The other names are `codex`, `copilot`, `cursor`, `kiro` and `windsurf`. To see what
35
+ `init` would write before it writes anything, add `--dry-run`.
36
+
37
+ 3. Read the two files `init` wrote in `.aidlc/context/`: `architecture.md` and
38
+ `style-guide.md`. They describe your code, and your assistant reads them before every
39
+ phase, so fix anything they get wrong now. A mistake here repeats in every piece of work.
40
+
41
+ 4. See the new files, then commit them:
42
+
43
+ ```bash
44
+ git status
45
+ git add .aidlc .claude CLAUDE.md .gitattributes
46
+ git commit -m "chore: add AIDLC"
47
+ ```
48
+
49
+ The tool folder and instructions file depend on the tool you chose — for example
50
+ `.cursor/` for Cursor or `.kiro/` for Kiro. Add whatever `git status` lists as new.
51
+
52
+ ## Check it worked
53
+
54
+ Run `aidlc status`. You should see `No active lifecycle instances.` That means AIDLC is set
55
+ up and waiting for your first piece of work.
@@ -0,0 +1,60 @@
1
+ ---
2
+ title: Change a requirement after its phase is finished
3
+ description: Record a change to finished requirements as an amendment, so the gates, the tasks and the code stay in step.
4
+ order: 30
5
+ slug: change-a-finished-requirement
6
+ ---
7
+
8
+ ## What you'll do
9
+
10
+ Add an amendment to `requirements.md` that says which criteria are retired, which are new,
11
+ and which phase to reopen. Then run `aidlc amend`. Editing the finished file directly leaves
12
+ every gate passing while the requirements and the code disagree.
13
+
14
+ ## Steps
15
+
16
+ 1. Open `.aidlc/state/<instance>/requirements.md`. Change each criterion you are dropping
17
+ into its retired form, in place — never delete it or reuse its number:
18
+
19
+ ```markdown
20
+ - AC-4 (retired 2026-09-07, superseded by AC-31): export as CSV only
21
+ ```
22
+
23
+ Add each new criterion with the next free number, for example `AC-31`. Then add an
24
+ amendment section at the end of the file:
25
+
26
+ ```markdown
27
+ ## Amendment 1 — 2026-09-07
28
+ - **Retires:** AC-4
29
+ - **Issues:** AC-31
30
+ - **Reopens:** design
31
+ - **Reason:** the customer needs JSON as well as CSV
32
+ ```
33
+
34
+ List each criterion by its full name. `AC-4..AC-6` is not read as a range.
35
+
36
+ 2. See what still depends on the criteria you are retiring. This writes nothing:
37
+
38
+ ```bash
39
+ aidlc amend <instance> --impact
40
+ ```
41
+
42
+ It prints a line starting `Reopens:` that names the earliest phase the change must
43
+ reopen, or `none`. If your `Reopens:` is later than that, move it earlier.
44
+
45
+ 3. Apply the amendment:
46
+
47
+ ```bash
48
+ aidlc amend <instance>
49
+ ```
50
+
51
+ If the work is already in testing or later, add `--confirm`. Reopening that far is
52
+ costly, and the flag makes you say so.
53
+
54
+ 4. Ask your assistant to continue. It resumes in the reopened phase.
55
+
56
+ The full rules for amendments are on the {{ref:phase/requirements}} phase page.
57
+
58
+ ## Check it worked
59
+
60
+ Run `aidlc status`. The instance's phase should now be the one you named in `Reopens:`.
@@ -0,0 +1,56 @@
1
+ ---
2
+ title: Keep AIDLC up to date
3
+ description: Update the CLI and your project's AIDLC files, then let doctor tidy what older versions left behind.
4
+ order: 60
5
+ slug: keep-aidlc-up-to-date
6
+ ---
7
+
8
+ ## What you'll do
9
+
10
+ Update the CLI and refresh the AIDLC files in your project with one command, then run
11
+ `doctor` to fix anything older versions left behind. Your own context documents in
12
+ `.aidlc/context/` are not overwritten.
13
+
14
+ ## Steps
15
+
16
+ 1. See what an update would change. This writes nothing:
17
+
18
+ ```bash
19
+ aidlc update --dry-run
20
+ ```
21
+
22
+ 2. Update:
23
+
24
+ ```bash
25
+ aidlc update
26
+ ```
27
+
28
+ It updates the CLI if a newer version exists, then refreshes the skills and instruction
29
+ files for each tool you set up. Text you wrote outside the AIDLC markers in files like
30
+ `CLAUDE.md` is kept.
31
+
32
+ 3. Tidy up. `doctor` applies safe fixes on its own and asks before it changes what git
33
+ tracks:
34
+
35
+ ```bash
36
+ aidlc doctor
37
+ ```
38
+
39
+ To preview first, run `aidlc doctor --dry-run`. In CI, where nothing can answer a
40
+ question, use `aidlc doctor --yes`.
41
+
42
+ 4. See what changed, then commit it:
43
+
44
+ ```bash
45
+ git status
46
+ git add .aidlc
47
+ git commit -m "chore: update AIDLC"
48
+ ```
49
+
50
+ Also add any tool folder or instructions file `git status` lists, such as `.claude/` or
51
+ `CLAUDE.md`.
52
+
53
+ ## Check it worked
54
+
55
+ Run `aidlc update --dry-run` again. You should see `CLI: <version> (already up to date)`, and
56
+ every project file listed under `Unchanged:`.
@@ -0,0 +1,49 @@
1
+ ---
2
+ title: Run two pieces of work at the same time
3
+ description: Give each piece of work its own folder and branch, so two sessions never overwrite each other's files.
4
+ order: 20
5
+ slug: run-two-pieces-of-work
6
+ ---
7
+
8
+ ## What you'll do
9
+
10
+ Start the second piece of work in a separate folder with its own branch. Two AI sessions in
11
+ one folder share every file on disk, so one session's `git add -A` picks up the other's
12
+ half-finished work. A separate folder removes that problem.
13
+
14
+ ## Steps
15
+
16
+ 1. From your main folder, start the new work with `--worktree`:
17
+
18
+ ```bash
19
+ aidlc start bugfix --name login-500 --worktree
20
+ ```
21
+
22
+ AIDLC creates a new branch from `main` and a new folder next to your repository, named
23
+ after the repository and the work — for example `../your-repo-login-500`. It prints both.
24
+
25
+ 2. Open a new terminal and AI session in that folder:
26
+
27
+ ```bash
28
+ cd ../your-repo-login-500
29
+ ```
30
+
31
+ Do all the work for this piece there. Your first session keeps working in the main folder.
32
+
33
+ 3. If the second piece of work needs no code yet — say, only requirements — you can skip
34
+ the folder and start it with `--no-code` instead. It stays in your main folder and
35
+ cannot reach implementation until it has a branch.
36
+
37
+ 4. When the work is merged, remove the folder:
38
+
39
+ ```bash
40
+ git worktree remove ../your-repo-login-500
41
+ ```
42
+
43
+ Git refuses if the folder still has changes that are not committed. That protects work
44
+ you have not saved.
45
+
46
+ ## Check it worked
47
+
48
+ Run `aidlc status` from either folder. You should see both pieces of work. The one that
49
+ lives in the other folder shows `(remote worktree)` in the Template column.
@@ -0,0 +1,52 @@
1
+ ---
2
+ title: See what a piece of work cost
3
+ description: Read the AI spend for one piece of work, split by phase, and the cost across all your work.
4
+ order: 50
5
+ slug: see-what-work-cost
6
+ ---
7
+
8
+ ## What you'll do
9
+
10
+ Check that cost capture is on, then read the spend for one piece of work, phase by phase.
11
+ Cost is read from your AI tool's own session records on your machine. Nothing is sent
12
+ anywhere.
13
+
14
+ ## Steps
15
+
16
+ 1. Check that capture is on for your tool:
17
+
18
+ ```bash
19
+ aidlc cost hooks status
20
+ ```
21
+
22
+ `init` turns it on. If your tool shows `not installed`, turn it on:
23
+
24
+ ```bash
25
+ aidlc cost hooks install --platform claude-code
26
+ ```
27
+
28
+ Use the name of your tool in place of `claude-code`.
29
+
30
+ 2. Read the cost of one piece of work:
31
+
32
+ ```bash
33
+ aidlc cost <instance>
34
+ ```
35
+
36
+ You get one line per phase with its cost and time, then a total.
37
+
38
+ 3. See every piece of work at once, or the average per template:
39
+
40
+ ```bash
41
+ aidlc cost
42
+ aidlc cost --by-template
43
+ ```
44
+
45
+ 4. To see what a piece of work cost including the bugfixes it later caused, run
46
+ `aidlc metrics`. Its true-cost figure adds those fixes to the work's own cost.
47
+
48
+ ## Check it worked
49
+
50
+ Run `aidlc cost <instance>` on a piece of work you have spent time on. You should see a
51
+ dollar amount on its `total:` line. `no data` means capture was off while you worked — turn
52
+ it on as in step 1, and the next session is counted.
@@ -0,0 +1,62 @@
1
+ ---
2
+ title: Send your roadmap to GitHub Issues and a Project board
3
+ description: Turn roadmap items into GitHub issues, and optionally keep a Project board's Status column in step with them.
4
+ order: 40
5
+ slug: send-roadmap-to-github
6
+ ---
7
+
8
+ ## What you'll do
9
+
10
+ Copy your roadmap items to GitHub Issues with one command. Items in `backlog/`,
11
+ `in-progress/` and `done/` become issues; `inbox/` and `hold/` stay private. The copy is one
12
+ way: the files in `.aidlc/roadmap/` stay the source, and GitHub follows them. Moving cards
13
+ on a Project board is an optional second part.
14
+
15
+ ## Steps
16
+
17
+ 1. Install the GitHub CLI and sign in. AIDLC uses its login and never asks for a token:
18
+
19
+ ```bash
20
+ gh auth login
21
+ ```
22
+
23
+ 2. Preview what would change. This writes nothing:
24
+
25
+ ```bash
26
+ aidlc roadmap sync --dry-run
27
+ ```
28
+
29
+ It uses the repository your folder points at. To target another one, add
30
+ `--repo <owner/name>`.
31
+
32
+ 3. Apply it:
33
+
34
+ ```bash
35
+ aidlc roadmap sync
36
+ ```
37
+
38
+ It shows the plan and asks before it writes. Run it again whenever items move — it
39
+ updates labels, and closes an issue when its item reaches `done/`.
40
+
41
+ 4. Optional — move a Project board too. Save the workflow AIDLC ships into your repository:
42
+
43
+ ```bash
44
+ aidlc roadmap board-workflow > .github/workflows/aidlc-project-status.yml
45
+ ```
46
+
47
+ Then, in your repository's settings on GitHub:
48
+
49
+ - Create a classic token with the `project` and `read:org` scopes (add `repo` if the
50
+ repository is private). Store it as the repository secret `AIDLC_PROJECT_TOKEN`, with
51
+ `<your-github-token>` as the value. Never paste it into a file you commit.
52
+ - Set the repository variable `AIDLC_PROJECT_NUMBER` to your project's number — the
53
+ digits in its URL.
54
+
55
+ The top of the workflow file lists the Status columns it expects and how to rename them.
56
+
57
+ ## Check it worked
58
+
59
+ Open your repository's Issues tab on GitHub. You should see one issue per roadmap item in
60
+ `backlog/`, `in-progress/` and `done/`, each labelled `aidlc`. If you set up the board, move
61
+ an item and run `aidlc roadmap sync` again: once the workflow run shows in your Actions tab,
62
+ its card should be in the new column.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rasensio/aidlc-content",
3
- "version": "1.38.0",
3
+ "version": "1.40.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -20,6 +20,7 @@
20
20
  "capabilities/",
21
21
  "phases/",
22
22
  "tutorials/",
23
+ "howto/",
23
24
  "resources/",
24
25
  "glossary.yaml"
25
26
  ],
@@ -65,6 +65,7 @@ If `.aidlc/state/` is empty or missing, offer just three options: start somethin
65
65
  | Answer pending questions | Open the question file, re-render its open questions per the **Question Protocol** (`.aidlc/resources/rules/question-protocol.md`), record each answer in the file, then fold them into the artifact they were gathered for |
66
66
  | Triage the inbox | Follow the **aidlc-roadmap** skill (triage flow) |
67
67
  | Browse / promote the roadmap | Follow the **aidlc-roadmap** skill (browse/promote flow) |
68
+ | Start a roadmap item in a new worktree | Follow the **aidlc-roadmap** skill (**Promote into a new worktree**). It ends by handing off to a new session; do not start the phase here |
68
69
  | Show status | Summarize each instance from its state files — name, template, current phase, completion %, and whether it looks stalled. When the roadmap is non-empty, append the per-status counts (e.g. "roadmap: 3 inbox, 5 backlog, 12 done") |
69
70
  | Review an artifact | Follow the **aidlc-review** skill |
70
71
  | Help / getting started | Follow the **aidlc-getting-started** skill |
@@ -3,7 +3,7 @@ name: aidlc-roadmap
3
3
  description: Captures roadmap items into .aidlc/roadmap/inbox/ at any moment — no instance, claim, or phase required — and browses, triages, promotes, or drops them
4
4
  phase: ideation
5
5
  priority: 90
6
- trigger: When the user says "idea:", asks to capture/record an idea or roadmap item, wants to browse the roadmap, or wants to triage, promote, or drop an item
6
+ trigger: When the user says "idea:", asks to capture/record an idea or roadmap item, wants to browse the roadmap, or wants to triage, promote, or drop an item, or asks to start a roadmap item in a new worktree
7
7
  native_mode_hint:
8
8
  claude-code: >-
9
9
  This skill is an interactive inbox, not a phase artifact. Do not enter
@@ -170,6 +170,20 @@ Promotion is where the roadmap meets the lifecycle:
170
170
  5. Seed the instance with the item: Full scope → the item is raw material the Ideation phase refines into that phase's required artifact (`idea.md` for the feature templates, `research-question.md` for `spike`); Standard scope → the item is input context for Requirements.
171
171
  6. Set `promoted_to: <instance-name>`, move the file to `in-progress/`, and append the `history` entry.
172
172
 
173
+ ### Promote into a new worktree
174
+
175
+ When the user asks for a worktree ("create a new worktree for roadmap `<file>`"), they want to work on the item in a separate session — for example one per pane of a session manager. Run the promote steps above with these changes, and do not stop to ask anything the item and config already answer:
176
+
177
+ 1. **Find the item** by file name, `id`, or title, in `backlog/` or `inbox/`. Asking for a worktree counts as choosing to skip triage. When more than one item matches, list them and ask which one.
178
+ 2. **Instance name**: the item's file name without its date prefix and extension (the item filed as `20260929-say-what-to-do-next` becomes `say-what-to-do-next`). Template and scope come from the config defaults, unless the item or the user names them.
179
+ 3. **Create the instance with** `aidlc start <template> --name <name> --scope <scope> --worktree --non-interactive`. Take the worktree path from the `Worktree:` line it prints. That command creates the branch and the worktree and fires `on-instance-start`; do not repeat any of it by hand.
180
+ 4. **Seed the instance inside the worktree** (`<worktree>/.aidlc/state/<name>/`), not the primary checkout. Copy the item into it per step 5 above. Keep the roadmap move (step 6) in the primary checkout, as always.
181
+ 5. **Hand off. Do not start the phase in this session.** The work belongs to the new session. End with the exact command that opens it:
182
+ ```
183
+ cd <worktree> && claude "/aidlc-continue <name>"
184
+ ```
185
+ For Codex, swap `claude` for `codex`. If the user names a session manager, give them the worktree path to point it at.
186
+
173
187
  When the instance completes, the `roadmap-done` lifecycle action moves the item to `done/` on its own — do not do it by hand, and do not remove that action to do it manually.
174
188
 
175
189
  ## Drop