@skilly-hand/skilly-hand 0.23.2 → 0.24.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.
- package/CHANGELOG.md +32 -0
- package/catalog/skills/accessibility-audit/SKILL.md +1 -0
- package/catalog/skills/agents-root-orchestrator/SKILL.md +1 -0
- package/catalog/skills/angular-guidelines/SKILL.md +1 -0
- package/catalog/skills/figma-mcp-0to1/SKILL.md +1 -0
- package/catalog/skills/frontend-design/SKILL.md +1 -0
- package/catalog/skills/output-optimizer/SKILL.md +1 -0
- package/catalog/skills/project-security/SKILL.md +1 -0
- package/catalog/skills/project-teacher/SKILL.md +1 -0
- package/catalog/skills/react-guidelines/SKILL.md +1 -0
- package/catalog/skills/review-rangers/SKILL.md +66 -11
- package/catalog/skills/review-rangers/manifest.json +5 -3
- package/catalog/skills/skill-creator/SKILL.md +2 -1
- package/catalog/skills/skill-creator/assets/SKILL-TEMPLATE.md +1 -1
- package/catalog/skills/spec-driven-development/SKILL.md +1 -0
- package/catalog/skills/test-driven-development/SKILL.md +1 -0
- package/catalog/skills/token-optimizer/SKILL.md +1 -0
- package/catalog/skills/user-story-crafting/SKILL.md +1 -0
- package/package.json +11 -3
- package/packages/catalog/package.json +1 -1
- package/packages/catalog/src/index.js +7 -0
- package/packages/cli/package.json +1 -1
- package/packages/cli/src/bin.js +13 -0
- package/packages/core/package.json +1 -1
- package/packages/core/src/index.js +82 -0
- package/packages/detectors/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -16,6 +16,38 @@ All notable changes to this project are documented in this file.
|
|
|
16
16
|
### Removed
|
|
17
17
|
- _None._
|
|
18
18
|
|
|
19
|
+
## [0.24.0] - 2026-04-26
|
|
20
|
+
[View on npm](https://www.npmjs.com/package/@skilly-hand/skilly-hand/v/0.24.0)
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
- Added install-time creation of the user-owned `.ai/DECISIONS.md` decisions registry, including entry criteria, an entry template, and a required registry changelog section.
|
|
24
|
+
- Added CLI install output that reports the `.ai/DECISIONS.md` decisions registry status during dry runs and applied installs.
|
|
25
|
+
- Added regression coverage for decisions registry planning, creation, existing-registry preservation, uninstall preservation, and invalid `.ai` parent handling.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- Updated `review-rangers` to own decisions registry read/write guidance and bumped the skill metadata version to `1.1.0`.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
- Preserved existing user-owned decisions registry content across reinstalls and uninstalls.
|
|
32
|
+
|
|
33
|
+
### Removed
|
|
34
|
+
- _None._
|
|
35
|
+
|
|
36
|
+
## [0.23.3] - 2026-04-20
|
|
37
|
+
[View on npm](https://www.npmjs.com/package/@skilly-hand/skilly-hand/v/0.23.3)
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
- Mirrored each skill `manifest.id` into top-level `name` frontmatter across catalog `SKILL.md` files.
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
- Updated catalog frontmatter rendering to include `name` and require a non-empty `manifest.id` during frontmatter validation.
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
- Expanded frontmatter sync tests to catch stale or missing `name` metadata regressions and enforce manifest id requirements.
|
|
47
|
+
|
|
48
|
+
### Removed
|
|
49
|
+
- _None._
|
|
50
|
+
|
|
19
51
|
## [0.23.2] - 2026-04-13
|
|
20
52
|
[View on npm](https://www.npmjs.com/package/@skilly-hand/skilly-hand/v/0.23.2)
|
|
21
53
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
+
name: "frontend-design"
|
|
2
3
|
description: "Project-aware frontend design skill that detects the existing tech stack, UI libraries, CSS variables, and design tokens before proposing any UI work. Supports greenfield projects via DESIGN.md context setup, and includes post-generation motion and visual refinement phases."
|
|
3
4
|
skillMetadata:
|
|
4
5
|
author: "skilly-hand"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
+
name: "output-optimizer"
|
|
2
3
|
description: "Optimize output token consumption through compact interpreter modes with controlled expansion when complexity, ambiguity, or risk requires more detail. Trigger: minimizing response verbosity while preserving clarity and correctness."
|
|
3
4
|
skillMetadata:
|
|
4
5
|
author: "skilly-hand"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
+
name: "project-security"
|
|
2
3
|
description: "Scan project configuration and release surfaces for leak and security risks, and enforce security gates on commit, push, and publish workflows across GitHub, GitLab, npm, pnpm, yarn, and generic CI. Trigger: validating repository security posture, preventing secret leaks, or hardening delivery pipelines."
|
|
3
4
|
skillMetadata:
|
|
4
5
|
author: "skilly-hand"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
+
name: "project-teacher"
|
|
2
3
|
description: "Scan the active project and teach any concept, code path, or decision using verified information, interactive questions, and simple explanations. Trigger: user asks to explain, understand, clarify, or learn about anything in the project or codebase."
|
|
3
4
|
skillMetadata:
|
|
4
5
|
author: "skilly-hand"
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
---
|
|
2
|
+
name: "review-rangers"
|
|
2
3
|
description: "Review code, decisions, and artifacts through a multi-perspective committee and a domain expert safety guard, then synthesize a structured verdict."
|
|
3
4
|
skillMetadata:
|
|
4
5
|
author: "skilly-hand"
|
|
5
|
-
last-edit: "2026-04-
|
|
6
|
+
last-edit: "2026-04-26"
|
|
6
7
|
license: "Apache-2.0"
|
|
7
|
-
version: "1.
|
|
8
|
-
changelog: "Added
|
|
8
|
+
version: "1.1.0"
|
|
9
|
+
changelog: "Added DECISIONS.md registry ownership guidance; preserves durable review insights and anti-slop decisions across sessions; affects review-rangers workflow, install scaffolding, and project memory usage"
|
|
9
10
|
auto-invoke: "Reviewing code, decisions, or artifacts where adversarial multi-perspective evaluation adds value"
|
|
10
11
|
allowed-tools:
|
|
11
12
|
- "Read"
|
|
13
|
+
- "Edit"
|
|
14
|
+
- "Write"
|
|
12
15
|
- "Grep"
|
|
13
16
|
- "Glob"
|
|
14
17
|
- "Bash"
|
|
@@ -37,14 +40,16 @@ Do not use this skill for:
|
|
|
37
40
|
## Core Workflow
|
|
38
41
|
|
|
39
42
|
1. Identify the target (code, decision, artifact) and its domain.
|
|
40
|
-
2.
|
|
41
|
-
3.
|
|
42
|
-
4.
|
|
43
|
-
5.
|
|
44
|
-
6.
|
|
45
|
-
7.
|
|
46
|
-
8.
|
|
47
|
-
9.
|
|
43
|
+
2. Read `.ai/DECISIONS.md` if it exists. Treat it as project memory for avoiding repeated mistakes and reusing documented decisions.
|
|
44
|
+
3. Determine committee size: 3 members for routine reviews, 5 for high-risk or cross-domain targets.
|
|
45
|
+
4. Spawn N committee members using `assets/committee-member-template.md`. Assign each a distinct evaluation lens. Run them independently — no member sees another's output.
|
|
46
|
+
5. Determine the expert domain for the safety guard.
|
|
47
|
+
6. Spawn 1 safety guard using `assets/safety-guard-template.md`. It evaluates the target from an authoritative expert position.
|
|
48
|
+
7. Run the committee and safety guard in parallel.
|
|
49
|
+
8. Collect all outputs.
|
|
50
|
+
9. Synthesize a structured verdict following the Synthesis Rules.
|
|
51
|
+
10. Emit the final verdict with confidence tier, top findings, and recommended action.
|
|
52
|
+
11. Decide whether any insight qualifies for `.ai/DECISIONS.md`; if yes, update the registry and its changelog in the same edit.
|
|
48
53
|
|
|
49
54
|
---
|
|
50
55
|
|
|
@@ -141,6 +146,56 @@ RECOMMENDED ACTION:
|
|
|
141
146
|
|
|
142
147
|
---
|
|
143
148
|
|
|
149
|
+
## Decisions Registry Protocol
|
|
150
|
+
|
|
151
|
+
`review-rangers` owns `.ai/DECISIONS.md` maintenance when the registry exists. Use it as both:
|
|
152
|
+
|
|
153
|
+
- A documentary source before solving or reviewing relevant problems.
|
|
154
|
+
- A durable memory target after review when a finding has future value.
|
|
155
|
+
|
|
156
|
+
### Read Rules
|
|
157
|
+
|
|
158
|
+
- Read `.ai/DECISIONS.md` near the start of relevant review or problem-solving work.
|
|
159
|
+
- Apply documented decisions and "avoid repeating" notes as project constraints.
|
|
160
|
+
- If the file does not exist, continue the review without creating it unless the current task is installation or explicit registry setup.
|
|
161
|
+
|
|
162
|
+
### Write Criteria
|
|
163
|
+
|
|
164
|
+
Write to `.ai/DECISIONS.md` only for:
|
|
165
|
+
|
|
166
|
+
- Breaking changes.
|
|
167
|
+
- Mid-interest or high-interest solutions.
|
|
168
|
+
- Architectural decisions.
|
|
169
|
+
- Repeated issue patterns.
|
|
170
|
+
- Project-specific conventions likely to matter in future sessions.
|
|
171
|
+
|
|
172
|
+
Do not write entries for minimal cleanup, obvious one-off bugs, insignificant changes, local-only implementation details, or full review transcripts.
|
|
173
|
+
|
|
174
|
+
### Write Format
|
|
175
|
+
|
|
176
|
+
Insert new entries above the final `## Changelog` section so the changelog remains the last section.
|
|
177
|
+
|
|
178
|
+
```md
|
|
179
|
+
## YYYY-MM-DD - Short Decision Title
|
|
180
|
+
|
|
181
|
+
- Interest level: Mid | High | Breaking
|
|
182
|
+
- Context:
|
|
183
|
+
- Decision / Insight:
|
|
184
|
+
- Rationale:
|
|
185
|
+
- Avoid repeating:
|
|
186
|
+
- Source:
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Every change to `.ai/DECISIONS.md` must update `## Changelog` in the same edit.
|
|
190
|
+
|
|
191
|
+
```md
|
|
192
|
+
- YYYY-MM-DD: Created/updated entry "<title>" because <why>.
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
If the changelog section is missing, add it as the final section before making any other registry change.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
144
199
|
## Decision Tree
|
|
145
200
|
|
|
146
201
|
```text
|
|
@@ -10,13 +10,15 @@
|
|
|
10
10
|
"agentSupport": ["codex", "claude", "cursor", "gemini", "copilot", "antigravity", "windsurf", "trae"],
|
|
11
11
|
"skillMetadata": {
|
|
12
12
|
"author": "skilly-hand",
|
|
13
|
-
"last-edit": "2026-04-
|
|
13
|
+
"last-edit": "2026-04-26",
|
|
14
14
|
"license": "Apache-2.0",
|
|
15
|
-
"version": "1.
|
|
16
|
-
"changelog": "Added
|
|
15
|
+
"version": "1.1.0",
|
|
16
|
+
"changelog": "Added DECISIONS.md registry ownership guidance; preserves durable review insights and anti-slop decisions across sessions; affects review-rangers workflow, install scaffolding, and project memory usage",
|
|
17
17
|
"auto-invoke": "Reviewing code, decisions, or artifacts where adversarial multi-perspective evaluation adds value",
|
|
18
18
|
"allowed-tools": [
|
|
19
19
|
"Read",
|
|
20
|
+
"Edit",
|
|
21
|
+
"Write",
|
|
20
22
|
"Grep",
|
|
21
23
|
"Glob",
|
|
22
24
|
"Bash",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
+
name: "skill-creator"
|
|
2
3
|
description: "Create and standardize AI skills with reusable structure, metadata rules, and templates."
|
|
3
4
|
skillMetadata:
|
|
4
5
|
author: "skilly-hand"
|
|
@@ -115,7 +116,7 @@ Top-level `SKILL.md` files now include managed YAML frontmatter mirrored from `m
|
|
|
115
116
|
Rules:
|
|
116
117
|
|
|
117
118
|
- `manifest.json` is the single source of truth.
|
|
118
|
-
- Mirror only `
|
|
119
|
+
- Mirror only `name` (from `manifest.id`), `description`, and `skillMetadata.{author,last-edit,license,version,changelog,auto-invoke,allowed-tools}`.
|
|
119
120
|
- Do not manually edit mirrored frontmatter in `SKILL.md`; run sync automation instead.
|
|
120
121
|
- Keep instruction body content in `SKILL.md` focused on workflow guidance.
|
|
121
122
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# {Name of the Skill} Guide
|
|
2
2
|
|
|
3
3
|
<!--
|
|
4
|
-
Managed frontmatter is mirrored from manifest.json by automation.
|
|
4
|
+
Managed frontmatter is mirrored from manifest.json by automation (`name` is derived from `manifest.id`).
|
|
5
5
|
Do not hand-author frontmatter in this template.
|
|
6
6
|
-->
|
|
7
7
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
+
name: "user-story-crafting"
|
|
2
3
|
description: "Create and refine user stories with structured quality gates, splitting heuristics, and lightweight story mapping for release slicing. Trigger: writing, restructuring, splitting, or sequencing user stories for delivery-ready backlog work."
|
|
3
4
|
skillMetadata:
|
|
4
5
|
author: "skilly-hand"
|
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skilly-hand/skilly-hand",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"license": "CC-BY-NC-4.0",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/Davecelot/skilly-hand.git"
|
|
9
|
+
},
|
|
6
10
|
"publishConfig": {
|
|
7
11
|
"access": "public"
|
|
8
12
|
},
|
|
@@ -18,7 +22,8 @@
|
|
|
18
22
|
"SECURITY.md"
|
|
19
23
|
],
|
|
20
24
|
"workspaces": [
|
|
21
|
-
"packages/*"
|
|
25
|
+
"packages/*",
|
|
26
|
+
"site"
|
|
22
27
|
],
|
|
23
28
|
"engines": {
|
|
24
29
|
"node": ">=22.0.0"
|
|
@@ -47,7 +52,10 @@
|
|
|
47
52
|
"cli": "node ./packages/cli/src/bin.js",
|
|
48
53
|
"detect": "node ./packages/cli/src/bin.js detect",
|
|
49
54
|
"list": "node ./packages/cli/src/bin.js list",
|
|
50
|
-
"doctor": "node ./packages/cli/src/bin.js doctor"
|
|
55
|
+
"doctor": "node ./packages/cli/src/bin.js doctor",
|
|
56
|
+
"site:dev": "npm run dev -w @skilly-hand/site",
|
|
57
|
+
"site:build": "npm run build -w @skilly-hand/site",
|
|
58
|
+
"site:preview": "npm run preview -w @skilly-hand/site"
|
|
51
59
|
},
|
|
52
60
|
"dependencies": {
|
|
53
61
|
"inquirer": "13.4.1"
|
|
@@ -128,6 +128,10 @@ function assertFrontmatterFields(manifest) {
|
|
|
128
128
|
throw new Error("Invalid manifest while building SKILL.md frontmatter");
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
if (typeof manifest.id !== "string" || manifest.id.trim().length === 0) {
|
|
132
|
+
throw new Error(`Skill "${manifest.id}" is missing required manifest.id for frontmatter mirroring`);
|
|
133
|
+
}
|
|
134
|
+
|
|
131
135
|
if (typeof manifest.description !== "string" || manifest.description.length === 0) {
|
|
132
136
|
throw new Error(`Skill "${manifest.id}" is missing required manifest.description for frontmatter mirroring`);
|
|
133
137
|
}
|
|
@@ -163,6 +167,7 @@ function assertFrontmatterFields(manifest) {
|
|
|
163
167
|
export function buildSkillFrontmatterPayload(manifest) {
|
|
164
168
|
assertFrontmatterFields(manifest);
|
|
165
169
|
return {
|
|
170
|
+
name: manifest.id,
|
|
166
171
|
description: manifest.description,
|
|
167
172
|
skillMetadata: {
|
|
168
173
|
author: manifest.skillMetadata.author,
|
|
@@ -178,6 +183,7 @@ export function buildSkillFrontmatterPayload(manifest) {
|
|
|
178
183
|
|
|
179
184
|
function renderSkillFrontmatterInner(payload) {
|
|
180
185
|
const lines = [
|
|
186
|
+
`name: ${yamlQuote(payload.name)}`,
|
|
181
187
|
`description: ${yamlQuote(payload.description)}`,
|
|
182
188
|
"skillMetadata:",
|
|
183
189
|
` author: ${yamlQuote(payload.skillMetadata.author)}`,
|
|
@@ -206,6 +212,7 @@ export function splitSkillMarkdown(content) {
|
|
|
206
212
|
const source = normalized.startsWith("\uFEFF") ? normalized.slice(1) : normalized;
|
|
207
213
|
const lines = splitLinesWithOffsets(source);
|
|
208
214
|
const mirroredKeys = new Set([
|
|
215
|
+
"name",
|
|
209
216
|
"description",
|
|
210
217
|
"skillMetadata",
|
|
211
218
|
"author",
|
package/packages/cli/src/bin.js
CHANGED
|
@@ -131,11 +131,24 @@ function buildHelpText(renderer, appVersion) {
|
|
|
131
131
|
|
|
132
132
|
function buildInstallResultDoc(result, flags, detectionGridText = "") {
|
|
133
133
|
const mode = flags.dryRun ? "dry-run" : "apply";
|
|
134
|
+
const decisionsRegistry = result.plan.decisionsRegistry || {
|
|
135
|
+
relativePath: ".ai/DECISIONS.md",
|
|
136
|
+
exists: false,
|
|
137
|
+
willCreate: false
|
|
138
|
+
};
|
|
139
|
+
const decisionsRegistryStatus = decisionsRegistry.created
|
|
140
|
+
? "created"
|
|
141
|
+
: decisionsRegistry.exists
|
|
142
|
+
? "existing"
|
|
143
|
+
: decisionsRegistry.willCreate
|
|
144
|
+
? "will create"
|
|
145
|
+
: "not reported";
|
|
134
146
|
return createResultDoc("Install", [
|
|
135
147
|
section("Install Preflight", [
|
|
136
148
|
kvBlock([
|
|
137
149
|
["Project", result.plan.cwd],
|
|
138
150
|
["Install root", result.plan.installRoot],
|
|
151
|
+
["Decisions registry", `${decisionsRegistry.relativePath} (${decisionsRegistryStatus})`],
|
|
139
152
|
["Agents", result.plan.agents.join(", ") || "none"],
|
|
140
153
|
["Include tags", flags.include.join(", ") || "none"],
|
|
141
154
|
["Exclude tags", flags.exclude.join(", ") || "none"],
|
|
@@ -6,6 +6,35 @@ import { detectProject, inspectProjectFiles } from "../../detectors/src/index.js
|
|
|
6
6
|
export const DEFAULT_AGENTS = ["standard", "codex", "claude", "cursor", "gemini", "copilot", "antigravity", "windsurf", "trae"];
|
|
7
7
|
const MANAGED_MARKER = "<!-- Managed by skilly-hand.";
|
|
8
8
|
const NATIVE_SETUP_MARKER = "<!-- Managed by skilly-hand native setup.";
|
|
9
|
+
const DECISIONS_REGISTRY_RELATIVE_PATH = ".ai/DECISIONS.md";
|
|
10
|
+
const DECISIONS_REGISTRY_TEMPLATE = `# AI Decisions
|
|
11
|
+
|
|
12
|
+
Durable project memory for \`review-rangers\`. Use this file to record breaking changes, mid/high-interest solutions, and important review insights that future agents should reuse.
|
|
13
|
+
|
|
14
|
+
## Entry Criteria
|
|
15
|
+
|
|
16
|
+
- Add entries only for breaking changes, mid/high-interest solutions, architectural decisions, repeated issue patterns, or project-specific conventions with future value.
|
|
17
|
+
- Do not add minimal, obvious, one-off, or insignificant changes.
|
|
18
|
+
- Do not paste full review transcripts.
|
|
19
|
+
- Every change to this file must update the changelog at the end.
|
|
20
|
+
|
|
21
|
+
## Entry Template
|
|
22
|
+
|
|
23
|
+
\`\`\`md
|
|
24
|
+
## YYYY-MM-DD - Short Decision Title
|
|
25
|
+
|
|
26
|
+
- Interest level: Mid | High | Breaking
|
|
27
|
+
- Context:
|
|
28
|
+
- Decision / Insight:
|
|
29
|
+
- Rationale:
|
|
30
|
+
- Avoid repeating:
|
|
31
|
+
- Source:
|
|
32
|
+
\`\`\`
|
|
33
|
+
|
|
34
|
+
## Changelog
|
|
35
|
+
|
|
36
|
+
- YYYY-MM-DD: Created/updated entry "<title>" because <why>.
|
|
37
|
+
`;
|
|
9
38
|
const AGENT_INSTALL_PROFILES = {
|
|
10
39
|
standard: {
|
|
11
40
|
instructionFiles: [["AGENTS.md"]],
|
|
@@ -263,10 +292,60 @@ export function buildInstallPlan({ cwd, detections, skills, agents }) {
|
|
|
263
292
|
tags: skill.tags
|
|
264
293
|
})),
|
|
265
294
|
installRoot: path.join(cwd, ".skilly-hand"),
|
|
295
|
+
decisionsRegistry: {
|
|
296
|
+
path: path.join(cwd, ".ai", "DECISIONS.md"),
|
|
297
|
+
relativePath: DECISIONS_REGISTRY_RELATIVE_PATH,
|
|
298
|
+
exists: false,
|
|
299
|
+
willCreate: true
|
|
300
|
+
},
|
|
266
301
|
generatedAt: nowIso()
|
|
267
302
|
};
|
|
268
303
|
}
|
|
269
304
|
|
|
305
|
+
async function planDecisionsRegistry(cwd) {
|
|
306
|
+
const aiDir = path.join(cwd, ".ai");
|
|
307
|
+
const registryPath = path.join(cwd, ".ai", "DECISIONS.md");
|
|
308
|
+
|
|
309
|
+
if (await exists(aiDir)) {
|
|
310
|
+
const info = await lstat(aiDir);
|
|
311
|
+
if (!info.isDirectory()) {
|
|
312
|
+
throw new Error("Cannot create decisions registry because .ai exists and is not a directory.");
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
let registryExists = false;
|
|
317
|
+
if (await exists(registryPath)) {
|
|
318
|
+
const info = await lstat(registryPath);
|
|
319
|
+
if (!info.isFile()) {
|
|
320
|
+
throw new Error("Cannot use decisions registry because .ai/DECISIONS.md exists and is not a file.");
|
|
321
|
+
}
|
|
322
|
+
registryExists = true;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return {
|
|
326
|
+
path: registryPath,
|
|
327
|
+
relativePath: DECISIONS_REGISTRY_RELATIVE_PATH,
|
|
328
|
+
exists: registryExists,
|
|
329
|
+
willCreate: !registryExists
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
async function ensureDecisionsRegistry(cwd) {
|
|
334
|
+
const registry = await planDecisionsRegistry(cwd);
|
|
335
|
+
if (registry.exists) {
|
|
336
|
+
return registry;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
await mkdir(path.dirname(registry.path), { recursive: true });
|
|
340
|
+
await writeFile(registry.path, DECISIONS_REGISTRY_TEMPLATE, "utf8");
|
|
341
|
+
return {
|
|
342
|
+
...registry,
|
|
343
|
+
exists: true,
|
|
344
|
+
willCreate: false,
|
|
345
|
+
created: true
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
270
349
|
async function backupPathIfNeeded(targetPath, backupsDir, lockData) {
|
|
271
350
|
if (!(await exists(targetPath))) {
|
|
272
351
|
return null;
|
|
@@ -600,6 +679,7 @@ export async function installProject({
|
|
|
600
679
|
excludeTags: parseTags(excludeTags)
|
|
601
680
|
});
|
|
602
681
|
const plan = buildInstallPlan({ cwd, detections, skills, agents: selectedAgents });
|
|
682
|
+
plan.decisionsRegistry = await planDecisionsRegistry(cwd);
|
|
603
683
|
|
|
604
684
|
if (dryRun) {
|
|
605
685
|
return { plan, applied: false };
|
|
@@ -621,6 +701,8 @@ export async function installProject({
|
|
|
621
701
|
await mkdir(installRoot, { recursive: true });
|
|
622
702
|
await mkdir(targetCatalogDir, { recursive: true });
|
|
623
703
|
await mkdir(backupsDir, { recursive: true });
|
|
704
|
+
const decisionsRegistry = await ensureDecisionsRegistry(cwd);
|
|
705
|
+
plan.decisionsRegistry = decisionsRegistry;
|
|
624
706
|
|
|
625
707
|
for (const skill of skills) {
|
|
626
708
|
await copySkillTo(targetCatalogDir, skill.id);
|