@novare-technologies/nvaid 0.2.0 → 0.2.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 +21 -0
- package/dist/cli.js +96 -12
- package/package.json +2 -2
- package/templates/commands/install.md +41 -4
- package/templates/nvaid/config.yml +1 -1
- package/templates/skills/customer-experience/SKILL.md +3 -3
- package/templates/skills/frontend/SKILL.md +3 -3
- package/templates/skills/project-ticketing/SKILL.md +2 -2
- package/templates/skills/quality/SKILL.md +4 -4
- package/templates/skills/solutions/SKILL.md +10 -8
- package/templates/skills/unit-breakdown/SKILL.md +5 -5
package/README.md
CHANGED
|
@@ -31,6 +31,27 @@ nvaid init --owning-repo frontend # preset the config's owning_repo
|
|
|
31
31
|
nvaid init --yes # non-interactive (defaults to the AGENTS.md catch-all)
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
## Upgrading
|
|
35
|
+
|
|
36
|
+
Upgrading is **two steps**, because `nvaid update` re-syncs a repo to the version of the
|
|
37
|
+
tool installed on your machine — it does not upgrade the tool itself:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# 1. upgrade the tool (once per machine, when a new version ships)
|
|
41
|
+
npm i -g @novare-technologies/nvaid@latest
|
|
42
|
+
|
|
43
|
+
# 2. re-sync each repo to the new version (run inside each repo)
|
|
44
|
+
nvaid update
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
nvaid checks npm (at most once a day, cached, non-blocking) and prints a one-line nudge
|
|
48
|
+
when a newer version is available — it never upgrades itself (the package manager owns the
|
|
49
|
+
tool's lifecycle). Silence the check with `NVAID_NO_UPDATE_CHECK=1`.
|
|
50
|
+
|
|
51
|
+
Note: `nvaid update` never touches hand-owned files (`config.yml`, `PROJECT-RULES.md`,
|
|
52
|
+
`DESIGN-CODE-DICTIONARY.md`, `intents/`). If a new version adds a config field, add it to
|
|
53
|
+
your `config.yml` by hand — the changelog will call these out.
|
|
54
|
+
|
|
34
55
|
## How it works
|
|
35
56
|
|
|
36
57
|
- **Full skill set, no profiles.** `init` injects every skill into each selected agent. A
|
package/dist/cli.js
CHANGED
|
@@ -13,6 +13,8 @@ var AGENTS = [
|
|
|
13
13
|
id: "claude",
|
|
14
14
|
label: "Claude Code",
|
|
15
15
|
skillsPath: ".claude/skills",
|
|
16
|
+
commandsPath: ".claude/commands",
|
|
17
|
+
// /nvaid:install resolves from .claude/commands/nvaid/install.md
|
|
16
18
|
instructionsFile: "CLAUDE.md",
|
|
17
19
|
format: "markdown",
|
|
18
20
|
bespoke: true
|
|
@@ -29,6 +31,8 @@ var AGENTS = [
|
|
|
29
31
|
id: "cursor",
|
|
30
32
|
label: "Cursor",
|
|
31
33
|
skillsPath: ".cursor/rules",
|
|
34
|
+
commandsPath: ".cursor/commands",
|
|
35
|
+
// Cursor reads custom commands from .cursor/commands
|
|
32
36
|
format: "mdc",
|
|
33
37
|
bespoke: true
|
|
34
38
|
},
|
|
@@ -109,8 +113,8 @@ var NVAID_DIR_NAME = "nvaid";
|
|
|
109
113
|
var CONFIG_FILE = "config.yml";
|
|
110
114
|
var AIDLC_ROOT_TOKEN = "{{AIDLC_ROOT}}";
|
|
111
115
|
async function nvaidVersion() {
|
|
112
|
-
const { readFile:
|
|
113
|
-
const pkg = JSON.parse(await
|
|
116
|
+
const { readFile: readFile4 } = await import("fs/promises");
|
|
117
|
+
const pkg = JSON.parse(await readFile4(resolve(TEMPLATES_DIR, "..", "package.json"), "utf8"));
|
|
114
118
|
return pkg.version;
|
|
115
119
|
}
|
|
116
120
|
|
|
@@ -149,7 +153,10 @@ function skillTarget(projectRoot, agent, skill) {
|
|
|
149
153
|
function commandTarget(projectRoot, agent, cmdFile) {
|
|
150
154
|
const base = cmdFile.replace(/\.md$/, "");
|
|
151
155
|
const ext = agent.format === "mdc" ? "mdc" : "md";
|
|
152
|
-
|
|
156
|
+
if (agent.commandsPath) {
|
|
157
|
+
return join(projectRoot, agent.commandsPath, "nvaid", `${base}.${ext}`);
|
|
158
|
+
}
|
|
159
|
+
return join(projectRoot, agent.skillsPath, "nvaid-commands", `nvaid-${base}.${ext}`);
|
|
153
160
|
}
|
|
154
161
|
async function writeFileEnsuringDir(path, body, force, result) {
|
|
155
162
|
if (!force && existsSync(path)) {
|
|
@@ -186,15 +193,14 @@ async function diffAgentFiles(opts) {
|
|
|
186
193
|
for (const agent of opts.agents) {
|
|
187
194
|
for (const skill of skills) {
|
|
188
195
|
const src = join(SKILLS_SRC, skill, "SKILL.md");
|
|
189
|
-
if (existsSync(src)) checks.push({ target: skillTarget(opts.projectRoot, agent, skill), src });
|
|
196
|
+
if (existsSync(src)) checks.push({ target: skillTarget(opts.projectRoot, agent, skill), src, agent });
|
|
190
197
|
}
|
|
191
198
|
for (const cmd of commands) {
|
|
192
|
-
checks.push({ target: commandTarget(opts.projectRoot, agent, cmd), src: join(COMMANDS_SRC, cmd) });
|
|
199
|
+
checks.push({ target: commandTarget(opts.projectRoot, agent, cmd), src: join(COMMANDS_SRC, cmd), agent });
|
|
193
200
|
}
|
|
194
201
|
}
|
|
195
|
-
for (const { target, src } of checks) {
|
|
196
|
-
const
|
|
197
|
-
const expected = await renderTemplate(src, agent ?? opts.agents[0]);
|
|
202
|
+
for (const { target, src, agent } of checks) {
|
|
203
|
+
const expected = await renderTemplate(src, agent);
|
|
198
204
|
if (!existsSync(target)) {
|
|
199
205
|
drift.push(`${relative(opts.projectRoot, target)} (missing)`);
|
|
200
206
|
continue;
|
|
@@ -206,8 +212,7 @@ async function diffAgentFiles(opts) {
|
|
|
206
212
|
}
|
|
207
213
|
async function cleanAgentDirs(projectRoot, agents) {
|
|
208
214
|
for (const agent of agents) {
|
|
209
|
-
const
|
|
210
|
-
const commandsDir = join(dir, "commands");
|
|
215
|
+
const commandsDir = agent.commandsPath ? join(projectRoot, agent.commandsPath, "nvaid") : join(projectRoot, agent.skillsPath, "nvaid-commands");
|
|
211
216
|
if (existsSync(commandsDir)) await rm(commandsDir, { recursive: true, force: true });
|
|
212
217
|
}
|
|
213
218
|
}
|
|
@@ -460,6 +465,81 @@ async function runValidate() {
|
|
|
460
465
|
return 0;
|
|
461
466
|
}
|
|
462
467
|
|
|
468
|
+
// src/updateNotifier.ts
|
|
469
|
+
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
470
|
+
import { homedir, tmpdir } from "os";
|
|
471
|
+
import { join as join4 } from "path";
|
|
472
|
+
import pc4 from "picocolors";
|
|
473
|
+
var PKG = "@novare-technologies/nvaid";
|
|
474
|
+
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
475
|
+
var FETCH_TIMEOUT_MS = 1500;
|
|
476
|
+
function cacheFile() {
|
|
477
|
+
const base = process.env.XDG_CACHE_HOME || join4(homedir(), ".cache");
|
|
478
|
+
return join4(base || tmpdir(), "nvaid", "update-check.json");
|
|
479
|
+
}
|
|
480
|
+
async function readCache() {
|
|
481
|
+
try {
|
|
482
|
+
return JSON.parse(await readFile3(cacheFile(), "utf8"));
|
|
483
|
+
} catch {
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
async function writeCache(c) {
|
|
488
|
+
try {
|
|
489
|
+
const f = cacheFile();
|
|
490
|
+
await mkdir3(join4(f, ".."), { recursive: true });
|
|
491
|
+
await writeFile3(f, JSON.stringify(c), "utf8");
|
|
492
|
+
} catch {
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
async function fetchLatest() {
|
|
496
|
+
try {
|
|
497
|
+
const ctrl = new AbortController();
|
|
498
|
+
const timer = setTimeout(() => ctrl.abort(), FETCH_TIMEOUT_MS);
|
|
499
|
+
const res = await fetch(`https://registry.npmjs.org/${PKG}/latest`, {
|
|
500
|
+
signal: ctrl.signal
|
|
501
|
+
});
|
|
502
|
+
clearTimeout(timer);
|
|
503
|
+
if (!res.ok) return null;
|
|
504
|
+
const data = await res.json();
|
|
505
|
+
return data.version ?? null;
|
|
506
|
+
} catch {
|
|
507
|
+
return null;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
function isNewer(a, b) {
|
|
511
|
+
const pa = a.split(".").map((n) => parseInt(n, 10));
|
|
512
|
+
const pb = b.split(".").map((n) => parseInt(n, 10));
|
|
513
|
+
for (let i = 0; i < 3; i++) {
|
|
514
|
+
const x = pa[i] ?? 0;
|
|
515
|
+
const y = pb[i] ?? 0;
|
|
516
|
+
if (x > y) return true;
|
|
517
|
+
if (x < y) return false;
|
|
518
|
+
}
|
|
519
|
+
return false;
|
|
520
|
+
}
|
|
521
|
+
async function notifyIfOutdated() {
|
|
522
|
+
if (process.env.NVAID_NO_UPDATE_CHECK) return;
|
|
523
|
+
const current = await nvaidVersion();
|
|
524
|
+
const cache = await readCache();
|
|
525
|
+
const now = Date.now();
|
|
526
|
+
let latest = null;
|
|
527
|
+
if (cache && now - cache.lastCheck < CHECK_INTERVAL_MS) {
|
|
528
|
+
latest = cache.latest;
|
|
529
|
+
} else {
|
|
530
|
+
latest = await fetchLatest();
|
|
531
|
+
if (latest) await writeCache({ lastCheck: now, latest });
|
|
532
|
+
}
|
|
533
|
+
if (!latest || !isNewer(latest, current)) return;
|
|
534
|
+
const line = (s) => process.stderr.write(s + "\n");
|
|
535
|
+
line("");
|
|
536
|
+
line(pc4.yellow(` \u250C\u2500 nvaid update available \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`));
|
|
537
|
+
line(pc4.yellow(" \u2502 ") + `${pc4.dim(current)} \u2192 ${pc4.green(latest)}`);
|
|
538
|
+
line(pc4.yellow(" \u2502 ") + `run: ${pc4.cyan(`npm i -g ${PKG}@latest`)}`);
|
|
539
|
+
line(pc4.yellow(" \u2502 ") + pc4.dim(`then re-sync your repo: nvaid update`));
|
|
540
|
+
line(pc4.yellow(` \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`));
|
|
541
|
+
}
|
|
542
|
+
|
|
463
543
|
// src/cli.ts
|
|
464
544
|
var program = new Command();
|
|
465
545
|
program.name("nvaid").description("nvaid \u2014 install an AI-DLC skills + workflow toolkit into any coding agent").version(await nvaidVersion());
|
|
@@ -475,9 +555,13 @@ program.command("update").description("Re-sync agent files to the installed nvai
|
|
|
475
555
|
await runUpdate();
|
|
476
556
|
});
|
|
477
557
|
program.command("validate").description("Fail if generated agent files are stale or hand-edited").action(async () => {
|
|
478
|
-
|
|
558
|
+
const code = await runValidate();
|
|
559
|
+
await notifyIfOutdated();
|
|
560
|
+
process.exit(code);
|
|
479
561
|
});
|
|
480
|
-
program.parseAsync().
|
|
562
|
+
program.parseAsync().then(async () => {
|
|
563
|
+
await notifyIfOutdated();
|
|
564
|
+
}).catch((err) => {
|
|
481
565
|
console.error(err instanceof Error ? err.message : err);
|
|
482
566
|
process.exit(1);
|
|
483
567
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@novare-technologies/nvaid",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "nvaid — one CLI that installs an AI-DLC skills-and-workflow toolkit into any coding agent, and houses intents, config, and the design-code dictionary in a single nvaid/ folder.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"scripts": {
|
|
17
17
|
"build": "tsup src/cli.ts --format esm --clean",
|
|
18
18
|
"dev": "tsx src/cli.ts",
|
|
19
|
-
"test": "vitest run
|
|
19
|
+
"test": "vitest run",
|
|
20
20
|
"typecheck": "tsc --noEmit",
|
|
21
21
|
"prepublishOnly": "npm run build"
|
|
22
22
|
},
|
|
@@ -47,13 +47,48 @@ not a file-scan's. This skill does that reading. A human reviews before it's mar
|
|
|
47
47
|
narrative derived from reading the code; §1 references `config.yml`'s `tech_stack`
|
|
48
48
|
rather than repeating it. Be honest in the "not yet mapped" section about coverage.
|
|
49
49
|
|
|
50
|
-
5. **
|
|
51
|
-
a
|
|
50
|
+
5. **Set up ADRs (Architecture Decision Records) — the project's decision anchors.**
|
|
51
|
+
ADRs are where a significant decision is justified and preserved, so the project (and
|
|
52
|
+
any future agent) can trace *why* a choice was made and revisit it later. Create them
|
|
53
|
+
on demand, not as empty ceremony:
|
|
54
|
+
- If authoring PROJECT-RULES (step 3) surfaced genuine, non-obvious decisions — an
|
|
55
|
+
approved-stack choice, a deliberate constraint, something a reviewer might otherwise
|
|
56
|
+
question — **create `nvaid/adr/`** and seed one ADR per such decision, numbered
|
|
57
|
+
`ADR-001`, `ADR-002`, … using the template below. These are the decisions the project
|
|
58
|
+
has already made, now anchored.
|
|
59
|
+
- If the project is simple enough that no decision needs anchoring yet, **do not create
|
|
60
|
+
an empty `adr/` folder** — just tell the user ADRs will be added when the first real
|
|
61
|
+
decision arises (e.g. via the `solutions` skill flagging "needs a new ADR"). The
|
|
62
|
+
folder appears when there's a decision to put in it.
|
|
63
|
+
- Each ADR follows this shape:
|
|
64
|
+
```markdown
|
|
65
|
+
---
|
|
66
|
+
adr: ADR-NNN
|
|
67
|
+
title: "<the decision, stated as a choice>"
|
|
68
|
+
status: accepted # proposed | accepted | superseded by ADR-XXX
|
|
69
|
+
date: "<YYYY-MM-DD>"
|
|
70
|
+
---
|
|
71
|
+
# ADR-NNN — <title>
|
|
72
|
+
## Context
|
|
73
|
+
<the forces at play: what problem/constraint prompted this decision>
|
|
74
|
+
## Decision
|
|
75
|
+
<what was decided, stated plainly>
|
|
76
|
+
## Consequences
|
|
77
|
+
<what this makes easier, what it makes harder, what it rules out>
|
|
78
|
+
## Alternatives considered
|
|
79
|
+
<options weighed and why they lost — so the decision can be revisited with the same context>
|
|
80
|
+
```
|
|
81
|
+
- A decision anchored in an ADR must not contradict `PROJECT-RULES.md`; if it does,
|
|
82
|
+
reconcile them (an ADR can *drive* a rules change, recorded in the rules change log).
|
|
52
83
|
|
|
53
|
-
6. **
|
|
84
|
+
6. **Human review.** Present all documents (config, PROJECT-RULES, dictionary, any ADRs)
|
|
85
|
+
for review. Per propose-don't-dispose, you draft; a human confirms. Do not self-approve.
|
|
86
|
+
|
|
87
|
+
7. **Flip the gate.** Only after the user confirms each document is genuinely filled (not
|
|
54
88
|
placeholder text), set the matching flag in `config.yml`'s `install:` block to `true`:
|
|
55
89
|
`config`, `project_rules`, `design_code_dictionary`. When all three are true, the
|
|
56
|
-
workflow commands unblock.
|
|
90
|
+
workflow commands unblock. (ADRs are not a gate flag — they are created as decisions
|
|
91
|
+
warrant, not required for the install to be complete.)
|
|
57
92
|
|
|
58
93
|
## Boundaries
|
|
59
94
|
|
|
@@ -61,3 +96,5 @@ not a file-scan's. This skill does that reading. A human reviews before it's mar
|
|
|
61
96
|
don't fabricate.
|
|
62
97
|
- Never set an `install:` flag to `true` on a document that still contains template
|
|
63
98
|
`<placeholder>` text or that the user hasn't confirmed.
|
|
99
|
+
- **Create `nvaid/adr/` only when there is a real decision to anchor** — never an empty
|
|
100
|
+
folder for its own sake.
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
name: customer-experience
|
|
3
3
|
description: Drafts the Customer Experience Contract for an Intent, per customer-experience-contract-generation-rules.md. Use when asked to run the Customer Experience Skill or draft a Customer Experience contract during Mob Elaboration.
|
|
4
4
|
invoked_by: Mob Elaboration (Ceremony 1), Phases 2–5
|
|
5
|
-
output: file — intents/<INTENT-ID>/contracts/customer-experience-contract.md
|
|
5
|
+
output: file — nvaid/intents/<INTENT-ID>/contracts/customer-experience-contract.md
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Customer Experience Skill
|
|
9
9
|
|
|
10
10
|
Drafts the Customer Experience Contract for an Intent, per
|
|
11
|
-
`
|
|
11
|
+
`{{AIDLC_ROOT}}/customer-experience-contract-generation-rules.md` — reconciling what the
|
|
12
12
|
room actually committed to against what `intent.md` originally asked for.
|
|
13
13
|
|
|
14
14
|
## Steps
|
|
@@ -18,7 +18,7 @@ room actually committed to against what `intent.md` originally asked for.
|
|
|
18
18
|
2. Write the Final Acceptance Criteria: the Intent's Success Criteria, incorporating
|
|
19
19
|
what the other contracts actually committed to, not a verbatim restatement.
|
|
20
20
|
3. Tie "done" to a concrete validation scenario, never just "the code merged."
|
|
21
|
-
4. Write `intents/<INTENT-ID>/contracts/customer-experience-contract.md`.
|
|
21
|
+
4. Write `nvaid/intents/<INTENT-ID>/contracts/customer-experience-contract.md`.
|
|
22
22
|
|
|
23
23
|
## Boundaries
|
|
24
24
|
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
name: frontend
|
|
3
3
|
description: Drafts the Frontend Architecture Contract for an Intent, per frontend-architecture-contract-generation-rules.md. Use when asked to run the Frontend Skill or draft a Frontend contract during Mob Elaboration.
|
|
4
4
|
invoked_by: Mob Elaboration (Ceremony 1), Phases 2–5
|
|
5
|
-
output: file — intents/<INTENT-ID>/contracts/frontend-architecture-contract.md
|
|
5
|
+
output: file — nvaid/intents/<INTENT-ID>/contracts/frontend-architecture-contract.md
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Frontend Skill
|
|
9
9
|
|
|
10
10
|
Drafts the Frontend Architecture Contract for an Intent, per
|
|
11
|
-
`
|
|
11
|
+
`{{AIDLC_ROOT}}/frontend-architecture-contract-generation-rules.md` — consuming the
|
|
12
12
|
Backend contract's shapes verbatim rather than reinterpreting them.
|
|
13
13
|
|
|
14
14
|
## Steps
|
|
@@ -22,7 +22,7 @@ Backend contract's shapes verbatim rather than reinterpreting them.
|
|
|
22
22
|
4. State Identity/Access implications explicitly, even when "none for this Intent" —
|
|
23
23
|
never left implicit.
|
|
24
24
|
5. List components touched (Design-Code Dictionary impact).
|
|
25
|
-
6. Write `intents/<INTENT-ID>/contracts/frontend-architecture-contract.md`.
|
|
25
|
+
6. Write `nvaid/intents/<INTENT-ID>/contracts/frontend-architecture-contract.md`.
|
|
26
26
|
|
|
27
27
|
## Boundaries
|
|
28
28
|
|
|
@@ -7,13 +7,13 @@ output: link — a Jira or GitHub Projects ticket
|
|
|
7
7
|
|
|
8
8
|
# Project Ticketing Skill
|
|
9
9
|
|
|
10
|
-
Creates and updates Epics, Stories, and Bugs per `
|
|
10
|
+
Creates and updates Epics, Stories, and Bugs per `{{AIDLC_ROOT}}/ISSUE-TRACKER-TEMPLATE.md`
|
|
11
11
|
— so ticket shape never drifts from one Intent to the next.
|
|
12
12
|
|
|
13
13
|
## Steps
|
|
14
14
|
|
|
15
15
|
1. On Unit Breakdown (Mob Elaboration Phase 5), create one Story or Bug per Unit,
|
|
16
|
-
classified per `
|
|
16
|
+
classified per `{{AIDLC_ROOT}}/unit-breakdown-rules.md` §3.
|
|
17
17
|
2. Attach each ticket's Acceptance Criteria verbatim from the Unit's own design doc —
|
|
18
18
|
never re-worded independently.
|
|
19
19
|
3. As Mob Construction moves a Unit through Design → Building → Gates → Merged, update
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
name: quality
|
|
3
3
|
description: Drafts the Quality Architecture Contract for an Intent, per quality-architecture-contract-generation-rules.md. Use when asked to run the Quality Skill or draft a Quality contract during Mob Elaboration.
|
|
4
4
|
invoked_by: Mob Elaboration (Ceremony 1), Phases 2–5
|
|
5
|
-
output: file — intents/<INTENT-ID>/contracts/quality-architecture-contract.md
|
|
5
|
+
output: file — nvaid/intents/<INTENT-ID>/contracts/quality-architecture-contract.md
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Quality Skill
|
|
9
9
|
|
|
10
10
|
Drafts the Quality Architecture Contract for an Intent, per
|
|
11
|
-
`
|
|
11
|
+
`{{AIDLC_ROOT}}/quality-architecture-contract-generation-rules.md` — the Required Test
|
|
12
12
|
Coverage table the Unit Test and Integration Test gates run against.
|
|
13
13
|
|
|
14
14
|
## Steps
|
|
@@ -20,12 +20,12 @@ Coverage table the Unit Test and Integration Test gates run against.
|
|
|
20
20
|
3. State which existing SRS NFRs this Intent's Units are held to, beyond the standing
|
|
21
21
|
baseline; say "none beyond baseline" explicitly when true.
|
|
22
22
|
4. Log any Known Gap the room consciously accepted, flagged rather than dropped.
|
|
23
|
-
5. Write `intents/<INTENT-ID>/contracts/quality-architecture-contract.md`.
|
|
23
|
+
5. Write `nvaid/intents/<INTENT-ID>/contracts/quality-architecture-contract.md`.
|
|
24
24
|
|
|
25
25
|
## Boundaries
|
|
26
26
|
|
|
27
27
|
- Never define Solution-Specific gates (Build, Code Coverage, Code Quality,
|
|
28
|
-
Reusability, Regression Test, SAST) — those are fixed in `
|
|
28
|
+
Reusability, Regression Test, SAST) — those are fixed in `nvaid/PROJECT-RULES.md`
|
|
29
29
|
§5.2, not something any Intent's contract opts into or out of.
|
|
30
30
|
- A draft, not a verdict — flag it awaiting the Quality Architect's Sign-Off; never
|
|
31
31
|
present it as final.
|
|
@@ -2,26 +2,28 @@
|
|
|
2
2
|
name: solutions
|
|
3
3
|
description: Drafts the Solutions Architecture Contract for an Intent, per solutions-architecture-contract-generation-rules.md. Use when asked to run the Solutions Skill or draft a Solutions contract during Mob Elaboration.
|
|
4
4
|
invoked_by: Mob Elaboration (Ceremony 1), Phases 2–5
|
|
5
|
-
output: file — intents/<INTENT-ID>/contracts/solutions-architecture-contract.md
|
|
5
|
+
output: file — nvaid/intents/<INTENT-ID>/contracts/solutions-architecture-contract.md
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Solutions Skill
|
|
9
9
|
|
|
10
10
|
Drafts the Solutions Architecture Contract for an Intent, per
|
|
11
|
-
`
|
|
11
|
+
`{{AIDLC_ROOT}}/solutions-architecture-contract-generation-rules.md` — the cross-role
|
|
12
12
|
boundary and consistency check every other contract this session has to fit inside.
|
|
13
13
|
|
|
14
14
|
## Steps
|
|
15
15
|
|
|
16
|
-
1. Assess whether this Intent introduces a new system container, crosses an
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
1. Assess whether this Intent introduces a new system container, crosses an architectural
|
|
17
|
+
boundary, or **needs a new ADR** — state the answer even when it's "no" on every count.
|
|
18
|
+
If a new ADR is warranted, record it as `nvaid/adr/ADR-NNN-<slug>.md` (next free number)
|
|
19
|
+
using the ADR shape from the `/nvaid:install` skill: Context, Decision, Consequences,
|
|
20
|
+
Alternatives considered. An ADR is a decision anchor — it must not contradict
|
|
21
|
+
`nvaid/PROJECT-RULES.md`; if it would, reconcile them.
|
|
19
22
|
2. State explicitly what this Intent is and isn't allowed to touch.
|
|
20
|
-
3. Flag any unsupervised-action surface `
|
|
21
|
-
already cover.
|
|
23
|
+
3. Flag any unsupervised-action surface `nvaid/PROJECT-RULES.md` §7 doesn't already cover.
|
|
22
24
|
4. Cross-check the other contracts drafted this session for contradictions — the
|
|
23
25
|
Consistency Gate, recorded in writing.
|
|
24
|
-
5. Write `intents/<INTENT-ID>/contracts/solutions-architecture-contract.md`.
|
|
26
|
+
5. Write `nvaid/intents/<INTENT-ID>/contracts/solutions-architecture-contract.md`.
|
|
25
27
|
|
|
26
28
|
## Boundaries
|
|
27
29
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: unit-breakdown
|
|
3
3
|
description: Cuts an Intent into Units of Work, each with its own Acceptance Criteria, per unit-breakdown-rules.md. Use when asked to run the Unit Breakdown Skill, break down an Intent into Units, or produce a Unit Breakdown during Mob Elaboration Phase 5.
|
|
4
4
|
invoked_by: Mob Elaboration (Ceremony 1), Phase 5
|
|
5
|
-
output: file — intents/<INTENT-ID>/unit-breakdown.md
|
|
5
|
+
output: file — nvaid/intents/<INTENT-ID>/unit-breakdown.md
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Unit Breakdown Skill
|
|
@@ -12,14 +12,14 @@ a first-cut proposal the room then critiques, not the decomposition of record.
|
|
|
12
12
|
|
|
13
13
|
## Steps
|
|
14
14
|
|
|
15
|
-
1. Read the Intent file (`intents/<INTENT-ID>/intent.md`) and its stated success
|
|
15
|
+
1. Read the Intent file (`nvaid/intents/<INTENT-ID>/intent.md`) and its stated success
|
|
16
16
|
criteria.
|
|
17
17
|
2. Propose a decomposition into Units, each with its own Acceptance Criteria narrowed
|
|
18
|
-
from the Intent's success criteria, per `
|
|
18
|
+
from the Intent's success criteria, per `{{AIDLC_ROOT}}/unit-breakdown-rules.md` §2.
|
|
19
19
|
3. Classify each Unit as a Story or Bug (§3), and size it per the file's decomposition
|
|
20
20
|
heuristics (§4).
|
|
21
21
|
4. Number Units per §5.
|
|
22
|
-
5. Write `intents/<INTENT-ID>/unit-breakdown.md` — the contract index every
|
|
22
|
+
5. Write `nvaid/intents/<INTENT-ID>/unit-breakdown.md` — the contract index every
|
|
23
23
|
Architecture Contract Skill downstream reads from.
|
|
24
24
|
|
|
25
25
|
## Boundaries
|
|
@@ -27,5 +27,5 @@ a first-cut proposal the room then critiques, not the decomposition of record.
|
|
|
27
27
|
- This is a proposal, not the decomposition of record. Mob Elaboration Phase 3
|
|
28
28
|
("Mark it up alone") and Phase 4 ("Negotiate live") are where the room actually owns
|
|
29
29
|
the cut — flag this file as a draft awaiting that review, never as final.
|
|
30
|
-
- Read `
|
|
30
|
+
- Read `{{AIDLC_ROOT}}/unit-breakdown-rules.md` in full before drafting; don't rely on
|
|
31
31
|
this summary alone for the numbering and classification rules.
|