@skilly-hand/skilly-hand 0.23.3 → 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 +17 -0
- package/catalog/skills/review-rangers/SKILL.md +65 -11
- package/catalog/skills/review-rangers/manifest.json +5 -3
- package/package.json +11 -3
- package/packages/catalog/package.json +1 -1
- 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,23 @@ 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
|
+
|
|
19
36
|
## [0.23.3] - 2026-04-20
|
|
20
37
|
[View on npm](https://www.npmjs.com/package/@skilly-hand/skilly-hand/v/0.23.3)
|
|
21
38
|
|
|
@@ -3,13 +3,15 @@ name: "review-rangers"
|
|
|
3
3
|
description: "Review code, decisions, and artifacts through a multi-perspective committee and a domain expert safety guard, then synthesize a structured verdict."
|
|
4
4
|
skillMetadata:
|
|
5
5
|
author: "skilly-hand"
|
|
6
|
-
last-edit: "2026-04-
|
|
6
|
+
last-edit: "2026-04-26"
|
|
7
7
|
license: "Apache-2.0"
|
|
8
|
-
version: "1.
|
|
9
|
-
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"
|
|
10
10
|
auto-invoke: "Reviewing code, decisions, or artifacts where adversarial multi-perspective evaluation adds value"
|
|
11
11
|
allowed-tools:
|
|
12
12
|
- "Read"
|
|
13
|
+
- "Edit"
|
|
14
|
+
- "Write"
|
|
13
15
|
- "Grep"
|
|
14
16
|
- "Glob"
|
|
15
17
|
- "Bash"
|
|
@@ -38,14 +40,16 @@ Do not use this skill for:
|
|
|
38
40
|
## Core Workflow
|
|
39
41
|
|
|
40
42
|
1. Identify the target (code, decision, artifact) and its domain.
|
|
41
|
-
2.
|
|
42
|
-
3.
|
|
43
|
-
4.
|
|
44
|
-
5.
|
|
45
|
-
6.
|
|
46
|
-
7.
|
|
47
|
-
8.
|
|
48
|
-
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.
|
|
49
53
|
|
|
50
54
|
---
|
|
51
55
|
|
|
@@ -142,6 +146,56 @@ RECOMMENDED ACTION:
|
|
|
142
146
|
|
|
143
147
|
---
|
|
144
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
|
+
|
|
145
199
|
## Decision Tree
|
|
146
200
|
|
|
147
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",
|
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"
|
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);
|