@skilly-hand/skilly-hand 0.16.0 → 0.17.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 +34 -0
- package/catalog/skills/spec-driven-development/SKILL.md +1 -1
- package/catalog/skills/spec-driven-development/agents/orchestrate.md +1 -1
- package/catalog/skills/spec-driven-development/agents/verify.md +9 -1
- package/catalog/skills/spec-driven-development/assets/validation-checklist.md +1 -0
- package/package.json +2 -2
- package/packages/catalog/package.json +1 -1
- package/packages/catalog/src/index.js +13 -0
- package/packages/cli/package.json +1 -1
- package/packages/core/package.json +1 -1
- package/packages/core/src/index.js +82 -5
- package/packages/detectors/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -16,6 +16,40 @@ All notable changes to this project are documented in this file.
|
|
|
16
16
|
### Removed
|
|
17
17
|
- _None._
|
|
18
18
|
|
|
19
|
+
## [0.17.0] - 2026-04-08
|
|
20
|
+
[View on npm](https://www.npmjs.com/package/@skilly-hand/skilly-hand/v/0.17.0)
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
- Added sandbox harness and matrix integration tests (`scripts/test-in-sandbox.mjs`, `tests/sandbox-harness.test.js`, `tests/sandbox-matrix.test.js`) and wired them into the root test pipeline.
|
|
24
|
+
- Added required `review-rangers` final-gate guidance to the spec-driven-development verify flow and validation checklist.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- Updated installer reconciliation logic to remove stale managed targets when agent selection narrows, while preserving/restoring backups for retained targets.
|
|
28
|
+
- Updated backup behavior to skip backup creation for files already marked as managed content.
|
|
29
|
+
- Updated root `npm test` to run sandbox integration verification after the node test suite.
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
- Fixed uninstall and re-install behavior for narrowed agent selections by restoring original files and cleaning obsolete managed artifacts.
|
|
33
|
+
|
|
34
|
+
### Removed
|
|
35
|
+
- _None._
|
|
36
|
+
|
|
37
|
+
## [0.16.1] - 2026-04-08
|
|
38
|
+
[View on npm](https://www.npmjs.com/package/@skilly-hand/skilly-hand/v/0.16.1)
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
- Added a Mandatory Skill Gate section to generated agent instruction files to enforce optimizer sequencing across interactions.
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
- Updated routing guidance to apply mandatory-gate precedence before task-specific skill chains.
|
|
45
|
+
- Synced catalog markdown rendering so generated AGENTS output includes the Mandatory Skill Gate and precedence guidance.
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
- Updated install and self-sync test coverage to assert Mandatory Skill Gate propagation across managed instruction targets.
|
|
49
|
+
|
|
50
|
+
### Removed
|
|
51
|
+
- _None._
|
|
52
|
+
|
|
19
53
|
## [0.16.0] - 2026-04-07
|
|
20
54
|
[View on npm](https://www.npmjs.com/package/@skilly-hand/skilly-hand/v/0.16.0)
|
|
21
55
|
|
|
@@ -22,7 +22,7 @@ Do not use this skill for:
|
|
|
22
22
|
1. Define the spec in `.sdd/active/<feature-name>/spec.md`.
|
|
23
23
|
2. Review and refine scope, constraints, and tasks.
|
|
24
24
|
3. Execute one small task at a time.
|
|
25
|
-
4. Verify each task and the end-to-end outcome.
|
|
25
|
+
4. Verify each task and the end-to-end outcome, ending with a required `review-rangers` final gate.
|
|
26
26
|
5. Archive to `.sdd/archive/` when complete.
|
|
27
27
|
|
|
28
28
|
Recommended task size:
|
|
@@ -14,7 +14,7 @@ Coordinate planning, implementation, and verification through explicit checkpoin
|
|
|
14
14
|
1. PLAN: Produce or update the spec.
|
|
15
15
|
2. REVIEW CHECKPOINT: Confirm the plan is approved.
|
|
16
16
|
3. APPLY: Execute agreed task batch.
|
|
17
|
-
4. VERIFY CHECKPOINT: Validate outputs against the spec.
|
|
17
|
+
4. VERIFY CHECKPOINT: Validate outputs against the spec and run the required final `review-rangers` gate.
|
|
18
18
|
5. REPEAT: Continue by phase or task batch.
|
|
19
19
|
6. ARCHIVE: Move completed work from `.sdd/active/` to `.sdd/archive/`.
|
|
20
20
|
|
|
@@ -15,7 +15,15 @@ Validate that implementation matches the approved spec and passes quality checks
|
|
|
15
15
|
2. Run task-level verification evidence checks.
|
|
16
16
|
3. Run feature-level validation commands.
|
|
17
17
|
4. Confirm constraints (`MUST`, `MUST NOT`) were respected.
|
|
18
|
-
5.
|
|
18
|
+
5. Run a final structured `review-rangers` pass over the full change set.
|
|
19
|
+
6. Report pass/fail per area with concrete evidence.
|
|
20
|
+
|
|
21
|
+
### Required Final Gate (`review-rangers`)
|
|
22
|
+
|
|
23
|
+
- Validate selected agent targets vs actual instruction files/symlinks written.
|
|
24
|
+
- Validate stale managed target cleanup after re-install/reselection.
|
|
25
|
+
- Validate backup and restore safety (including uninstall restore behavior).
|
|
26
|
+
- Any unresolved `review-rangers` blocker keeps verification in failed state.
|
|
19
27
|
|
|
20
28
|
## Quality Bar
|
|
21
29
|
|
|
@@ -28,5 +28,6 @@ Use this checklist before implementation and again before archive.
|
|
|
28
28
|
- [ ] All planned tasks are complete.
|
|
29
29
|
- [ ] Feature-level validation passes.
|
|
30
30
|
- [ ] Constraints were respected.
|
|
31
|
+
- [ ] Final `review-rangers` gate completed with no unresolved blockers.
|
|
31
32
|
- [ ] No unintended scope creep.
|
|
32
33
|
- [ ] Work is moved from `.sdd/active/` to `.sdd/archive/`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skilly-hand/skilly-hand",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"license": "CC-BY-NC-4.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"catalog:check": "node ./scripts/check-catalog.mjs",
|
|
29
29
|
"catalog:sync": "node ./scripts/sync-catalog-readme.mjs",
|
|
30
30
|
"agentic:self:sync": "node ./scripts/sync-self-agentic.mjs",
|
|
31
|
-
"test": "node --test tests/*.test.js",
|
|
31
|
+
"test": "node --test tests/*.test.js && node ./scripts/test-in-sandbox.mjs",
|
|
32
32
|
"security:check": "node ./scripts/security-check.mjs",
|
|
33
33
|
"verify:packlist": "node ./scripts/verify-packlist.mjs",
|
|
34
34
|
"verify:versions": "node ./scripts/verify-versions.mjs",
|
|
@@ -118,9 +118,22 @@ export function renderAgentsMarkdown({ skills, detections, generatedAt, projectN
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
lines.push(
|
|
121
|
+
"",
|
|
122
|
+
"### Mandatory Skill Gate (Must Use / Must Read)",
|
|
123
|
+
"",
|
|
124
|
+
"This gate has global precedence and applies to every user interaction across all supported agent conventions/files.",
|
|
125
|
+
"",
|
|
126
|
+
"1. Always run `token-optimizer` first to classify complexity and set the minimum viable reasoning depth.",
|
|
127
|
+
"2. Always run `output-optimizer` immediately after `token-optimizer` for response-shape control.",
|
|
128
|
+
"3. `output-optimizer` mode policy:",
|
|
129
|
+
" - Default: select a random canonical mode for each new interaction.",
|
|
130
|
+
" - Override: if user explicitly requests a mode (for example `mode: step-brief`), that explicit mode wins.",
|
|
131
|
+
" - Persistence: keep the explicitly requested mode active until the user asks for a different mode.",
|
|
121
132
|
"",
|
|
122
133
|
"### Task Routing",
|
|
123
134
|
"",
|
|
135
|
+
"**Mandatory-gate precedence:** apply the mandatory optimizer gate before task-routing chains below.",
|
|
136
|
+
"",
|
|
124
137
|
"**SDD-first policy:** for feature delivery, bug fixes, or any multi-step implementation, start with `spec-driven-development` unless the task is clearly trivial and one-step.",
|
|
125
138
|
"",
|
|
126
139
|
"| Task Type | Recommended Skill Chain |",
|
|
@@ -175,7 +175,11 @@ async function ensureManagedTextFile(targetPath, content, backupsDir, lockData)
|
|
|
175
175
|
return;
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
|
|
178
|
+
// Do not back up previously managed content; backups are for restoring
|
|
179
|
+
// user-authored files replaced by managed files.
|
|
180
|
+
if (!current.includes(MANAGED_MARKER)) {
|
|
181
|
+
await backupPathIfNeeded(targetPath, backupsDir, lockData);
|
|
182
|
+
}
|
|
179
183
|
}
|
|
180
184
|
|
|
181
185
|
await mkdir(path.dirname(targetPath), { recursive: true });
|
|
@@ -230,6 +234,69 @@ function buildInstallTargets(selectedAgents) {
|
|
|
230
234
|
};
|
|
231
235
|
}
|
|
232
236
|
|
|
237
|
+
async function reconcileManagedTargets({
|
|
238
|
+
previousLock,
|
|
239
|
+
selectedInstructionTargets,
|
|
240
|
+
selectedSkillTargets,
|
|
241
|
+
lockData
|
|
242
|
+
}) {
|
|
243
|
+
if (!previousLock) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const selectedInstructions = new Set(selectedInstructionTargets);
|
|
248
|
+
const selectedSkills = new Set(selectedSkillTargets);
|
|
249
|
+
const selectedTargets = new Set([...selectedInstructions, ...selectedSkills]);
|
|
250
|
+
const previousBackups = previousLock.backups || {};
|
|
251
|
+
|
|
252
|
+
for (const [targetPath, backupPath] of Object.entries(previousBackups)) {
|
|
253
|
+
if (!selectedTargets.has(targetPath)) {
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
if (await exists(backupPath)) {
|
|
257
|
+
lockData.backups[targetPath] = backupPath;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
for (const symlinkPath of previousLock.managedSymlinks || []) {
|
|
262
|
+
if (selectedSkills.has(symlinkPath)) {
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (await exists(symlinkPath)) {
|
|
267
|
+
await rm(symlinkPath, { recursive: true, force: true });
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const backupPath = previousBackups[symlinkPath];
|
|
271
|
+
if (backupPath && await exists(backupPath)) {
|
|
272
|
+
await mkdir(path.dirname(symlinkPath), { recursive: true });
|
|
273
|
+
await cp(backupPath, symlinkPath, { recursive: true, force: true });
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
for (const filePath of previousLock.managedFiles || []) {
|
|
278
|
+
if (selectedInstructions.has(filePath)) {
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const backupPath = previousBackups[filePath];
|
|
283
|
+
if (backupPath && await exists(backupPath)) {
|
|
284
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
285
|
+
await cp(backupPath, filePath, { recursive: true, force: true });
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (!(await exists(filePath))) {
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const content = await readFile(filePath, "utf8");
|
|
294
|
+
if (content.includes(MANAGED_MARKER)) {
|
|
295
|
+
await rm(filePath, { force: true });
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
233
300
|
export async function installProject({
|
|
234
301
|
cwd,
|
|
235
302
|
agents,
|
|
@@ -259,6 +326,7 @@ export async function installProject({
|
|
|
259
326
|
const targetCatalogDir = path.join(installRoot, "catalog");
|
|
260
327
|
const backupsDir = path.join(installRoot, "backups");
|
|
261
328
|
const lockPath = path.join(installRoot, "manifest.lock.json");
|
|
329
|
+
const previousLock = await exists(lockPath) ? await readJson(lockPath) : null;
|
|
262
330
|
const lockData = {
|
|
263
331
|
version: 1,
|
|
264
332
|
generatedAt: plan.generatedAt,
|
|
@@ -289,15 +357,24 @@ export async function installProject({
|
|
|
289
357
|
await writeFile(path.join(installRoot, "AGENTS.md"), agentsMarkdown, "utf8");
|
|
290
358
|
|
|
291
359
|
const { instructionTargets, skillTargets } = buildInstallTargets(selectedAgents);
|
|
360
|
+
const absoluteInstructionTargets = instructionTargets.map((pathParts) => path.join(cwd, ...pathParts));
|
|
361
|
+
const absoluteSkillTargets = skillTargets.map((pathParts) => path.join(cwd, ...pathParts));
|
|
362
|
+
|
|
363
|
+
await reconcileManagedTargets({
|
|
364
|
+
previousLock,
|
|
365
|
+
selectedInstructionTargets: absoluteInstructionTargets,
|
|
366
|
+
selectedSkillTargets: absoluteSkillTargets,
|
|
367
|
+
lockData
|
|
368
|
+
});
|
|
292
369
|
|
|
293
|
-
for (const
|
|
294
|
-
await ensureManagedTextFile(
|
|
370
|
+
for (const targetPath of absoluteInstructionTargets) {
|
|
371
|
+
await ensureManagedTextFile(targetPath, agentsMarkdown, backupsDir, lockData);
|
|
295
372
|
}
|
|
296
373
|
|
|
297
374
|
const skillsSourcePath = path.join(installRoot, "catalog");
|
|
298
375
|
|
|
299
|
-
for (const
|
|
300
|
-
await ensureSymlink(
|
|
376
|
+
for (const targetPath of absoluteSkillTargets) {
|
|
377
|
+
await ensureSymlink(targetPath, skillsSourcePath, backupsDir, lockData);
|
|
301
378
|
}
|
|
302
379
|
|
|
303
380
|
await writeJson(lockPath, lockData);
|