skilldrop-cli 0.13.0 → 0.13.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 +66 -26
- package/bin/skilldrop.js +87 -9
- package/contracts/pack.schema.json +9 -2
- package/loops/release/LOOP.md +76 -0
- package/loops/release/loop.json +47 -0
- package/model-routing.json +4 -0
- package/package.json +1 -1
- package/packs.json +33 -32
- package/skills/launch-readiness/SKILL.md +95 -0
- package/skills/launch-readiness/evals/eval_queries.json +10 -0
- package/skills/launch-readiness/evals/evals.json +19 -0
- package/skills/launch-readiness/examples/schema-change-revise.md +54 -0
- package/skills/launch-readiness/manifest.json +24 -0
- package/skills/launch-readiness/templates/readiness-report.md +41 -0
package/README.md
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/skilldrop-cli)
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
|
|
6
|
-
**[Browse the catalogue →](https://sananthanarayan.github.io/skilldrop/)** — all
|
|
6
|
+
**[Browse the catalogue →](https://sananthanarayan.github.io/skilldrop/)** — all 63 skills, filterable by outcome, pack, tag, and model tier.
|
|
7
7
|
|
|
8
|
-
**
|
|
8
|
+
**63 portable AI-agent skills for the deliverables knowledge workers actually ship** — diagrams, design docs, ADRs, PRDs, runbooks, decks, decision logs, threat models, adversarial reviews — installable into **Claude Code**, **Cursor**, **Kiro**, **Codex**, **GitHub Copilot**, and any AI tool that accepts custom instructions, one skill or one role-based pack at a time:
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
|
-
npx skilldrop-cli install --pack product-manager # or: solution-architect, dev-team,
|
|
12
|
-
npx skilldrop-cli list #
|
|
11
|
+
npx skilldrop-cli install --pack product-manager # or: solution-architect, dev-team, sre-oncall,
|
|
12
|
+
npx skilldrop-cli list # stakeholder-comms, ai-engineering, claude-api (each brings core)
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Originally scoped to solution architects, now broadly useful to PMs, founders, consultants, engineering leaders, exec assistants — anyone who turns ideas into stakeholder-ready artifacts.
|
|
@@ -24,13 +24,14 @@ skilldrop ships **loops**, not just parts. A loop is a named sequence of stages
|
|
|
24
24
|
|
|
25
25
|
A loop *sequences* skills — it never contains one. Every skill stays independently installable and runnable on its own, which is what keeps a single-folder copy working in Cursor, Kiro, or Aider.
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Five loops cover the lifecycle, and they are separated by **reversibility** — how expensive the mistake is to unwind — which is why each gets its own gate rather than folding into a neighbour:
|
|
28
28
|
|
|
29
29
|
| Loop | Takes | Gate | Produces | Mistake costs |
|
|
30
30
|
|---|---|---|---|---|
|
|
31
31
|
| [`discover`](loops/discover/LOOP.md) | interviews, journeys, a strategy question | **G0** human — a person ratifies the brief | a ratified requirement | a re-brief |
|
|
32
32
|
| [`design`](loops/design/LOOP.md) | a ratified requirement | **G1** review — `council-review`'s panel | a recorded decision (ADR) | months, unwound in code |
|
|
33
33
|
| [`build`](loops/build/LOOP.md) | an agreed requirement or triaged defect | **G2** mechanical — `pre-merge-review`'s gate script decides | merged code | a revert |
|
|
34
|
+
| [`release`](loops/release/LOOP.md) | merged code | **G2.5** review — `launch-readiness` on evidence; **G2.6** human go/no-go | a live, reversible rollout | users and data, often irreversible |
|
|
34
35
|
| [`operate`](loops/operate/LOOP.md) | a shipped service | **G3** human — the incident is closed | a postmortem and runbook deltas | live users, irreversible |
|
|
35
36
|
|
|
36
37
|
Plus one **wrapper**, which is not a lifecycle stage but the two passes either side of *any* generator:
|
|
@@ -144,6 +145,41 @@ flowchart LR
|
|
|
144
145
|
|
|
145
146
|
<!-- loop:build:end -->
|
|
146
147
|
|
|
148
|
+
### `release` — merged code to live users
|
|
149
|
+
|
|
150
|
+
Plan the rollout and the way back, judge readiness on evidence, draft the release notes, then a human makes the go/no-go call. The gap between a merge you can revert and a launch you often cannot.
|
|
151
|
+
|
|
152
|
+
<!-- loop:release:start -->
|
|
153
|
+
|
|
154
|
+
```mermaid
|
|
155
|
+
%%{init: {'theme':'base','themeVariables':{'fontFamily':'Segoe UI, Helvetica, Arial','fontSize':'15px','lineColor':'#9AA5B1'},'flowchart':{'curve':'basis','rankSpacing':70,'nodeSpacing':50,'padding':16}}}%%
|
|
156
|
+
flowchart LR
|
|
157
|
+
classDef gen fill:#E8F0FE,stroke:#4C7DF0,stroke-width:1.5px,color:#1A3A8F;
|
|
158
|
+
classDef review fill:#FDEAEA,stroke:#E05B5B,stroke-width:1.5px,color:#8A1F1F;
|
|
159
|
+
classDef gate fill:#FBE3A2,stroke:#D9971E,stroke-width:2px,color:#6B4500,font-weight:bold;
|
|
160
|
+
classDef ship fill:#E6F7EC,stroke:#34A853,stroke-width:2px,color:#0F6B33,font-weight:bold;
|
|
161
|
+
|
|
162
|
+
plan["plan<br/><small>migration-plan</small>"]:::gen
|
|
163
|
+
ready["ready<br/><small>launch-readiness</small>"]:::review
|
|
164
|
+
announce["announce<br/><small>release-notes</small>"]:::gen
|
|
165
|
+
go["go<br/><small>council-review</small>"]:::gate
|
|
166
|
+
G2_5{"G2.5 · review"}:::gate
|
|
167
|
+
G2_6{"G2.6 · human"}:::gate
|
|
168
|
+
DONE(["complete"]):::ship
|
|
169
|
+
|
|
170
|
+
plan --> ready
|
|
171
|
+
ready --> G2_5
|
|
172
|
+
G2_5 == "PROCEED" ==> announce
|
|
173
|
+
announce --> go
|
|
174
|
+
go --> G2_6
|
|
175
|
+
G2_6 == "PROCEED" ==> DONE
|
|
176
|
+
|
|
177
|
+
G2_5 -- "REVISE (max 3)" --> plan
|
|
178
|
+
G2_6 -- "REVISE (max 3)" --> plan
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
<!-- loop:release:end -->
|
|
182
|
+
|
|
147
183
|
### `operate` — a shipped service through detection and learning
|
|
148
184
|
|
|
149
185
|
Instrument, write the runbook, communicate the incident, then feed the postmortem's runbook deltas straight back into the runbook. The one loop whose failures are live.
|
|
@@ -235,6 +271,7 @@ Skills for the SDLC steps around the code itself — turning raw requirements in
|
|
|
235
271
|
| [`release-notes`](skills/release-notes/SKILL.md) | Turn git history between two refs (default: last tag → HEAD) into two artifacts: customer-facing release notes rewritten in reader benefits — no commit-speak, no ticket IDs, no "various improvements" — and an internal Keep-a-Changelog version with a commit hash on every line. Breaking changes hoisted to the top of both with an "Action required" line (detected via `!:` markers, removed public API, migration files, major bumps); internal noise (refactors, CI, deps) never leaks into customer notes; vague commits land in a "Needs review" list instead of being guessed at. |
|
|
236
272
|
| [`bug-triage`](skills/bug-triage/SKILL.md) | Turn a vague bug report ("it's broken on mobile sometimes") into a ticket an engineer can start without contacting the reporter: searchable symptom-plus-condition title, numbered repro steps from a clean state (or an explicit "no repro yet" with the exact diagnostics to collect), expected-vs-actual with the verbatim error string, every claim tagged `[reported]` / `[verified]` / `[assumption]`, severity and priority judged independently (S4/P1 is a legitimate combination), ≤3 hypotheses each with a 5-minute check, and duplicate-search hints. One bug per ticket — multi-symptom reports get split. |
|
|
237
273
|
| [`migration-plan`](skills/migration-plan/SKILL.md) | Phased migration/rollout plan (schema change with live backfill, API version, datastore/auth/platform swap) built on the parallel-change pattern: expand → migrate → contract. One change per phase (a failed phase implicates exactly one thing); every phase carries an observable gate with bake time, a tested rollback with an explicit data story, and a blast radius; at most one **named point of no return**; backfill specified idempotent + resumable + rate-limited with 3-depth parity checks; dual-write requires a named reconciler; the contract phase gets a date and an owner so "we'll remove the old path later" actually happens. |
|
|
274
|
+
| [`launch-readiness`](skills/launch-readiness/SKILL.md) | Go/no-go readiness report for a merged change before it reaches users. It lists the change's own failure modes first, then judges seven checks in order: rollback, detection, response, measured NFR targets, data & privacy, comms, staged exposure. Each row is met / not met / n/a-with-reason, with an evidence link and an owner role, and a row with no evidence is `not met`. The verdict (PROCEED / PROCEED WITH CONDITIONS / REVISE / BLOCKED) follows mechanically from the rows, and a missing rollback blocks on its own. Gaps go to `migration-plan`, `observability-plan` or `runbook-generator` instead of being drafted inline. The `ready` stage of the `release` loop. |
|
|
238
275
|
|
|
239
276
|
### Product strategy
|
|
240
277
|
|
|
@@ -388,17 +425,18 @@ Why not have an LLM pick the model live on every call? Because that pays tokens
|
|
|
388
425
|
|
|
389
426
|
## Skill packs — install a role's toolkit in one command
|
|
390
427
|
|
|
391
|
-
Categories (above) say what a skill *is*; packs say *who needs it*. [`packs.json`](packs.json)
|
|
428
|
+
Categories (above) say what a skill *is*; packs say *who needs it*. [`packs.json`](packs.json) gives every skill and every loop **exactly one home** ([RFC-0033](docs/rfcs/0033-core-pack-and-single-home-skills.md)). Skills every role uses live in **`core`**, and each role pack `requires` it, so installing a role pack installs `core` with it in the same command:
|
|
392
429
|
|
|
393
|
-
| Pack | Skills | For |
|
|
394
|
-
|
|
395
|
-
| `
|
|
396
|
-
| `dev-team` | 14 | Build-and-ship
|
|
397
|
-
| `
|
|
398
|
-
| `ai-engineering` |
|
|
399
|
-
| `
|
|
400
|
-
| `
|
|
401
|
-
| `
|
|
430
|
+
| Pack | Skills | Loops | For |
|
|
431
|
+
|---|---|---|---|
|
|
432
|
+
| `core` | 4 | `ship-a-draft` | Every role: structured intake, document critique, the review council, output hygiene. Comes with every role pack |
|
|
433
|
+
| `dev-team` | 14 + core | `build`, `release` | Build-and-ship: story splitting, implementation with adversarial review, test plans, triage, migrations, launch readiness, release notes, quality gates |
|
|
434
|
+
| `solution-architect` | 11 + core | `design` | Design-phase artifacts: diagrams, ADRs, design docs, contracts, schemas, threat models |
|
|
435
|
+
| `ai-engineering` | 11 + core | — | Adopt and build AI systems: readiness, use-case triage, rollout and policy, agent loop design, subagents, spend budgets, agent threat models, evals, usage reporting |
|
|
436
|
+
| `product-manager` | 8 + core | `discover` | Direction to requirements: PR/FAQs, strategy frameworks, OKRs, business cases, interviews, PRDs, journey maps, success measurement |
|
|
437
|
+
| `stakeholder-comms` | 6 + core | — | Non-technical audiences: audience profiling, deck outlines and real `.pptx` decks, exec summaries, decision logs, guides |
|
|
438
|
+
| `sre-oncall` | 5 + core | `operate` | Operate the service: runbooks, observability design, incident comms, postmortems, capacity/cost models |
|
|
439
|
+
| `claude-api` | 4 | — | Build on the Anthropic API: prompt caching strategy, token budgeting, eval generation for skills, tool-use schema writing. A specialist add-on; it does not bring core |
|
|
402
440
|
|
|
403
441
|
```bash
|
|
404
442
|
python3 pack.py # list packs
|
|
@@ -408,7 +446,7 @@ python3 pack.py product-manager --install --project # into .claude/skills/
|
|
|
408
446
|
python3 pack.py product-manager --install --dest .cursor/skills # any dir, for non-Claude IDEs
|
|
409
447
|
```
|
|
410
448
|
|
|
411
|
-
For non-Claude IDEs, `--dest` drops the folders where your tool expects them; the per-IDE wiring steps below still apply. Packs are metadata only — skills stay in flat `skills/<name>` folders, so per-skill `cp -R` installs keep working unchanged ([RFC-0001](docs/rfcs/0001-skill-packs.md) records the
|
|
449
|
+
For non-Claude IDEs, `--dest` drops the folders where your tool expects them; the per-IDE wiring steps below still apply. Packs are metadata only — skills stay in flat `skills/<name>` folders, so per-skill `cp -R` installs keep working unchanged ([RFC-0001](docs/rfcs/0001-skill-packs.md) records the original decision; [RFC-0033](docs/rfcs/0033-core-pack-and-single-home-skills.md) replaced its overlapping packs with `core` and one home per skill).
|
|
412
450
|
|
|
413
451
|
## Outcomes — browse by why you're here
|
|
414
452
|
|
|
@@ -442,13 +480,13 @@ npx skilldrop-cli install --pack dev-team --project # .claude/skills — als
|
|
|
442
480
|
npx skilldrop-cli install prfaq --ide cursor # + writes .cursor/rules/prfaq.mdc
|
|
443
481
|
npx skilldrop-cli install --pack sre-oncall --ide kiro # .kiro/skills — Kiro IDE + Kiro CLI, discovered natively
|
|
444
482
|
npx skilldrop-cli install adr-generator --dest .agents/skills # Codex + Copilot CLI (see below)
|
|
445
|
-
npx skilldrop-cli loops # the
|
|
483
|
+
npx skilldrop-cli loops # the six loops, their stages and gates
|
|
446
484
|
npx skilldrop-cli install --loop build # a loop + every stage skill it sequences (RFC-0028)
|
|
447
485
|
npx skilldrop-cli install --loop --pack sre-oncall # every loop that pack declares
|
|
448
486
|
npx skilldrop-cli agents # the reviewer subagents
|
|
449
487
|
npx skilldrop-cli install --agent devils-advocate # -> ~/.claude/agents/ (RFC-0012)
|
|
450
488
|
npx skilldrop-cli install --panel review # the whole review fleet: 3 subagents + the pre-merge-review orchestrator (RFC-0020)
|
|
451
|
-
npx skilldrop-cli outdated && npx skilldrop-cli update # skills improve;
|
|
489
|
+
npx skilldrop-cli outdated && npx skilldrop-cli update # skills improve; files you edited are kept, new copy as <file>.upstream
|
|
452
490
|
npx skilldrop-cli list | skilldrop info <skill> | skilldrop packs | skilldrop uninstall <skill>
|
|
453
491
|
npx skilldrop-cli list --json # machine-readable: list/info/packs/agents/outdated (RFC-0021)
|
|
454
492
|
```
|
|
@@ -466,18 +504,20 @@ skilldrop is also a **Claude Code plugin marketplace** — one marketplace, seve
|
|
|
466
504
|
Then take the whole catalogue, or just your role's pack:
|
|
467
505
|
|
|
468
506
|
```text
|
|
469
|
-
/plugin install skilldrop@skilldrop # all
|
|
470
|
-
/plugin install
|
|
471
|
-
/plugin install
|
|
472
|
-
/plugin install
|
|
473
|
-
/plugin install
|
|
474
|
-
/plugin install stakeholder-comms@skilldrop #
|
|
475
|
-
/plugin install sre-oncall@skilldrop #
|
|
507
|
+
/plugin install skilldrop@skilldrop # all 63 skills + 3 reviewer subagents
|
|
508
|
+
/plugin install dev-team@skilldrop # 18 skills (incl. core) + the 3 reviewer subagents
|
|
509
|
+
/plugin install solution-architect@skilldrop # 15 skills (incl. core)
|
|
510
|
+
/plugin install ai-engineering@skilldrop # 15 skills (incl. core)
|
|
511
|
+
/plugin install product-manager@skilldrop # 12 skills (incl. core)
|
|
512
|
+
/plugin install stakeholder-comms@skilldrop # 10 skills (incl. core)
|
|
513
|
+
/plugin install sre-oncall@skilldrop # 9 skills (incl. core)
|
|
514
|
+
/plugin install claude-api@skilldrop # 4 skills
|
|
515
|
+
/plugin install core@skilldrop # 4 skills, on their own
|
|
476
516
|
```
|
|
477
517
|
|
|
478
518
|
Every skill then invokes as `/<plugin>:<name>` (e.g. `/skilldrop:prfaq`). The whole-catalogue plugin ships the flat `skills/` and `agents/` trees at the repo root unchanged — same copy-install premise, expressed in Claude's own plugin format.
|
|
479
519
|
|
|
480
|
-
The
|
|
520
|
+
The eight **pack plugins** work differently, because a plugin's skills have to sit in a `skills/` folder inside the plugin. Rather than duplicate every skill into eight directories on `main` — physical packs, which [RFC-0001](docs/rfcs/0001-skill-packs.md) rejected — the marketplace entries use Claude's `git-subdir` source to point at `packs/<name>/` on a generated [`plugins`](https://github.com/sananthanarayan/skilldrop/tree/plugins) branch, rebuilt by CI on every push to main. Nothing moves in the source tree, and you still only ever type the one `marketplace add`. Each role pack's plugin also carries `core`'s skills and loops, since a plugin installs on its own. A pack carries the reviewer subagents its own skills delegate to, so `dev-team` brings the review panel and `sre-oncall` does not.
|
|
481
521
|
|
|
482
522
|
`.claude-plugin/{marketplace,plugin}.json` are generated from `package.json` + `packs.json` by [`build_marketplace.py`](build_marketplace.py) (`--check` guards drift in CI; `--dist` renders the branch). Use the CLI above when you want per-skill granularity, another IDE, or hooks; use the marketplace when you're in Claude Code. Rationale: [RFC-0027](docs/rfcs/0027-retire-agentbundle-export.md).
|
|
483
523
|
|
package/bin/skilldrop.js
CHANGED
|
@@ -13,6 +13,7 @@ const fs = require("fs");
|
|
|
13
13
|
const path = require("path");
|
|
14
14
|
const os = require("os");
|
|
15
15
|
const { execFileSync } = require("child_process");
|
|
16
|
+
const crypto = require("crypto");
|
|
16
17
|
|
|
17
18
|
const ROOT = path.resolve(__dirname, "..");
|
|
18
19
|
const LEDGER = ".skilldrop.json";
|
|
@@ -48,7 +49,9 @@ Usage:
|
|
|
48
49
|
(--no-skills for the loop alone) (RFC-0028)
|
|
49
50
|
skilldrop install --panel review install the review panel — the 3 reviewer subagents +
|
|
50
51
|
the pre-merge-review orchestrator that fires them (RFC-0020)
|
|
51
|
-
skilldrop update
|
|
52
|
+
skilldrop update [--force] re-copy installed skills whose version changed; files
|
|
53
|
+
you edited are kept and the new copy lands beside them
|
|
54
|
+
as <file>.upstream (--force overwrites) (RFC-0032)
|
|
52
55
|
skilldrop outdated show installed vs current versions, change nothing
|
|
53
56
|
skilldrop uninstall <skill...> remove skills (and wiring files this tool wrote)
|
|
54
57
|
skilldrop uninstall --agent <name...> remove subagents
|
|
@@ -264,6 +267,15 @@ function packsOf(cat) {
|
|
|
264
267
|
const p = path.join(cat.dir, "packs.json");
|
|
265
268
|
return fs.existsSync(p) ? readJSON(p).packs : null;
|
|
266
269
|
}
|
|
270
|
+
/* RFC-0033: a pack installs together with the packs it `requires` (in practice, core), so
|
|
271
|
+
one --pack still delivers a role's whole toolkit now that shared skills have one home. */
|
|
272
|
+
function packMembers(ps, name, key) {
|
|
273
|
+
const req = (ps[name].requires || []).filter((r) => ps[r]);
|
|
274
|
+
const out = [];
|
|
275
|
+
for (const n of [...req, name]) for (const x of ps[n][key] || []) if (!out.includes(x)) out.push(x);
|
|
276
|
+
if (req.length) console.log(`pack '${name}' includes ${req.join(", ")}`);
|
|
277
|
+
return out;
|
|
278
|
+
}
|
|
267
279
|
function profilesOf(cat) {
|
|
268
280
|
const p = path.join(cat.dir, "profiles.json");
|
|
269
281
|
return fs.existsSync(p) ? readJSON(p).profiles : null;
|
|
@@ -709,7 +721,7 @@ function expandNames(args, cat) {
|
|
|
709
721
|
if (!ps) die(`catalog '${cat.source}' has no packs.json — install skills by name`);
|
|
710
722
|
const p = ps[args.flags.pack];
|
|
711
723
|
if (!p) die(`unknown pack '${args.flags.pack}' in catalog '${cat.source}'`);
|
|
712
|
-
return
|
|
724
|
+
return packMembers(ps, args.flags.pack, "skills");
|
|
713
725
|
}
|
|
714
726
|
if (!args._.length) die("nothing to install — pass skill names, --pack <name>, or --all");
|
|
715
727
|
for (const s of args._) if (!skillExists(cat, s)) die(`unknown skill '${s}' in catalog '${cat.source}'`);
|
|
@@ -721,10 +733,64 @@ function copyOne(cat, s, dest, ide, l, notes) {
|
|
|
721
733
|
fs.cpSync(skillDir(cat, s), path.join(dest, s), { recursive: true });
|
|
722
734
|
const note = writeWiring(ide, dest, s, m.description);
|
|
723
735
|
if (note && notes) notes.push(note);
|
|
724
|
-
l.data[s] = { version: m.version, source: cat.source };
|
|
736
|
+
l.data[s] = { version: m.version, source: cat.source, files: fileHashes(skillDir(cat, s)) };
|
|
725
737
|
return m;
|
|
726
738
|
}
|
|
727
739
|
|
|
740
|
+
/* RFC-0032: per-file SHA-256 of a skill as the catalog shipped it, recorded in the ledger at
|
|
741
|
+
copy time. It is the baseline `update` compares against, so a file the user edited is never
|
|
742
|
+
overwritten. Paths are forward-slash relative; *.upstream files are this tool's output. */
|
|
743
|
+
function sha256(buf) { return crypto.createHash("sha256").update(buf).digest("hex"); }
|
|
744
|
+
function fileHashes(dir) {
|
|
745
|
+
const out = {};
|
|
746
|
+
(function walk(d, rel) {
|
|
747
|
+
for (const e of fs.readdirSync(d, { withFileTypes: true })) {
|
|
748
|
+
const r = rel ? `${rel}/${e.name}` : e.name;
|
|
749
|
+
if (e.isDirectory()) walk(path.join(d, e.name), r);
|
|
750
|
+
else if (e.isFile() && !e.name.endsWith(".upstream")) out[r] = sha256(fs.readFileSync(path.join(d, e.name)));
|
|
751
|
+
}
|
|
752
|
+
})(dir, "");
|
|
753
|
+
return out;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/* Update one skill file by file against the ledger baseline (RFC-0032):
|
|
757
|
+
upstream unchanged -> leave the local file alone, edited or not
|
|
758
|
+
local untouched, or new file -> take the new version
|
|
759
|
+
local edited, upstream moved -> keep the local file, write the new one as <file>.upstream
|
|
760
|
+
A file the catalog dropped is removed only if the user never touched it. The new baseline is
|
|
761
|
+
what the catalog ships now, so a kept edit stays "edited" until the user merges it. */
|
|
762
|
+
function mergeOne(cat, s, dest, ide, l, notes) {
|
|
763
|
+
const m = manifestOf(cat, s);
|
|
764
|
+
const src = skillDir(cat, s), dst = path.join(dest, s);
|
|
765
|
+
const base = l.data[s].files, next = fileHashes(src);
|
|
766
|
+
const kept = [], orphaned = [];
|
|
767
|
+
const at = (root, rel) => path.join(root, ...rel.split("/"));
|
|
768
|
+
const localHash = (rel) => { try { return sha256(fs.readFileSync(at(dst, rel))); } catch (e) { return null; } };
|
|
769
|
+
for (const [rel, h] of Object.entries(next)) {
|
|
770
|
+
const mine = localHash(rel), to = at(dst, rel);
|
|
771
|
+
if (mine === h) { fs.rmSync(to + ".upstream", { force: true }); continue; }
|
|
772
|
+
if (h === base[rel]) continue;
|
|
773
|
+
fs.mkdirSync(path.dirname(to), { recursive: true });
|
|
774
|
+
if (mine === null ? !(rel in base) : mine === base[rel]) {
|
|
775
|
+
fs.copyFileSync(at(src, rel), to);
|
|
776
|
+
fs.rmSync(to + ".upstream", { force: true });
|
|
777
|
+
} else {
|
|
778
|
+
fs.copyFileSync(at(src, rel), to + ".upstream");
|
|
779
|
+
kept.push(rel);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
for (const rel of Object.keys(base)) {
|
|
783
|
+
if (rel in next) continue;
|
|
784
|
+
const mine = localHash(rel);
|
|
785
|
+
if (mine === base[rel]) fs.rmSync(at(dst, rel), { force: true });
|
|
786
|
+
else if (mine !== null) orphaned.push(rel);
|
|
787
|
+
}
|
|
788
|
+
const note = writeWiring(ide, dest, s, m.description);
|
|
789
|
+
if (note && notes) notes.push(note);
|
|
790
|
+
l.data[s] = { version: m.version, source: cat.source, files: next };
|
|
791
|
+
return { m, kept, orphaned };
|
|
792
|
+
}
|
|
793
|
+
|
|
728
794
|
/* Install a whole review panel — the reviewer subagents + the orchestrator skill — in one
|
|
729
795
|
command (RFC-0020). Needs a target with BOTH a subagent and a skill format, so it accepts
|
|
730
796
|
the default (Claude Code), --project, --ide kiro, or --dest; other IDEs install the halves
|
|
@@ -874,18 +940,30 @@ function installedRows(flags) {
|
|
|
874
940
|
function update(args) {
|
|
875
941
|
const { dest, ide, l, rows } = installedRows(args.flags);
|
|
876
942
|
if (!rows.length) return console.log(`nothing installed at ${dest}`);
|
|
877
|
-
let n = 0;
|
|
943
|
+
let n = 0, conflicts = 0;
|
|
878
944
|
for (const r of rows) {
|
|
879
945
|
if (!r.current) { console.log(`skip ${r.s}: source '${r.src}' unreachable or skill gone from it`); continue; }
|
|
880
946
|
if (r.current === r.installed) continue;
|
|
881
947
|
const problems = checkSkill(r.cat, r.s);
|
|
882
948
|
if (problems.length) { console.log(`skip ${r.s}: fails structural check in '${r.src}' (${problems[0]})`); continue; }
|
|
883
|
-
|
|
884
|
-
|
|
949
|
+
// No baseline (installed before RFC-0032) or --force: overwrite as before, and record one.
|
|
950
|
+
const entry = l.data[r.s];
|
|
951
|
+
if (args.flags.force || typeof entry !== "object" || !entry.files) {
|
|
952
|
+
copyOne(r.cat, r.s, dest, ide, l);
|
|
953
|
+
console.log(`updated ${r.s} ${r.installed} -> ${r.current} (${r.src})`);
|
|
954
|
+
} else {
|
|
955
|
+
const { kept, orphaned } = mergeOne(r.cat, r.s, dest, ide, l);
|
|
956
|
+
console.log(`updated ${r.s} ${r.installed} -> ${r.current} (${r.src})`);
|
|
957
|
+
for (const f of kept) console.log(` kept your edits in ${f} — new version at ${f}.upstream`);
|
|
958
|
+
for (const f of orphaned) console.log(` kept ${f} — dropped upstream, but you edited it`);
|
|
959
|
+
conflicts += kept.length;
|
|
960
|
+
}
|
|
885
961
|
n++;
|
|
886
962
|
}
|
|
887
963
|
saveLedger(l);
|
|
888
964
|
console.log(n ? `\n${n} skill(s) updated.` : "everything up to date.");
|
|
965
|
+
if (conflicts)
|
|
966
|
+
console.log(`${conflicts} file(s) kept your edits. Merge each <file>.upstream into its file, then delete it — or rerun with --force to take every new version.`);
|
|
889
967
|
}
|
|
890
968
|
|
|
891
969
|
function outdated(args) {
|
|
@@ -1013,7 +1091,7 @@ function installLoops(args) {
|
|
|
1013
1091
|
if (!ps) die(`catalog '${cat.source}' has no packs.json`);
|
|
1014
1092
|
const pk = ps[args.flags.pack];
|
|
1015
1093
|
if (!pk) die(`unknown pack '${args.flags.pack}' in catalog '${cat.source}'`);
|
|
1016
|
-
names = (
|
|
1094
|
+
names = packMembers(ps, args.flags.pack, "loops");
|
|
1017
1095
|
if (!names.length) die(`pack '${args.flags.pack}' declares no loops`);
|
|
1018
1096
|
}
|
|
1019
1097
|
if (!names.length && args.flags.all) names = available.slice();
|
|
@@ -1182,13 +1260,13 @@ function listPacks(args) {
|
|
|
1182
1260
|
catalog: cat.source,
|
|
1183
1261
|
count: ps ? Object.keys(ps).length : 0,
|
|
1184
1262
|
packs: Object.entries(ps || {}).map(([name, p]) => ({
|
|
1185
|
-
name, description: p.description || null, skills: p.skills || [],
|
|
1263
|
+
name, description: p.description || null, skills: p.skills || [], requires: p.requires || [],
|
|
1186
1264
|
})),
|
|
1187
1265
|
});
|
|
1188
1266
|
if (!ps) return console.log(`catalog '${cat.source}' defines no packs.`);
|
|
1189
1267
|
const w = Math.max(...Object.keys(ps).map((n) => n.length));
|
|
1190
1268
|
for (const [n, p] of Object.entries(ps))
|
|
1191
|
-
console.log(`${n.padEnd(w)} (${p.skills.length} skills) ${p.description}`);
|
|
1269
|
+
console.log(`${n.padEnd(w)} (${p.skills.length} skills${(p.requires || []).length ? ` + ${p.requires.join(", ")}` : ""}) ${p.description}`);
|
|
1192
1270
|
console.log("\nInstall one: skilldrop install --pack <name>");
|
|
1193
1271
|
}
|
|
1194
1272
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://github.com/sananthanarayan/skilldrop/contracts/pack.schema.json",
|
|
4
4
|
"title": "skilldrop packs.json",
|
|
5
|
-
"$comment": "RFC-0001 / RFC-0026 / RFC-0029. Packs and outcomes are METADATA ONLY — skills never move out of flat skills/<name> folders. Packs answer WHO needs a skill; outcomes answer WHY someone opened the catalogue. Both get the same two-way membership check in validate.py.",
|
|
5
|
+
"$comment": "RFC-0001 / RFC-0026 / RFC-0029 / RFC-0033. Packs and outcomes are METADATA ONLY — skills never move out of flat skills/<name> folders. RFC-0033: each skill and loop sits in exactly one pack; shared skills live in `core`, which other packs pull in via `requires`. Packs answer WHO needs a skill; outcomes answer WHY someone opened the catalogue. Both get the same two-way membership check in validate.py.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": false,
|
|
8
8
|
"required": ["version", "packs", "outcomes"],
|
|
@@ -20,7 +20,14 @@
|
|
|
20
20
|
"description": { "type": "string", "description": "One line — who this pack is for." },
|
|
21
21
|
"skills": { "type": "array", "items": { "type": "string" }, "minItems": 1,
|
|
22
22
|
"description": "Real skill folders. Every skill must appear in at least one pack." },
|
|
23
|
-
"
|
|
23
|
+
"requires": {
|
|
24
|
+
"type": "array",
|
|
25
|
+
"items": {
|
|
26
|
+
"type": "string"
|
|
27
|
+
},
|
|
28
|
+
"description": "RFC-0033. Packs installed together with this one (in practice, `core`). One level only: a required pack may not itself require."
|
|
29
|
+
},
|
|
30
|
+
"loops": { "type": "array", "items": { "type": "string" },
|
|
24
31
|
"description": "RFC-0028. Real loops/ folders. Every loop must appear in at least one pack." }
|
|
25
32
|
}
|
|
26
33
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: release
|
|
3
|
+
description: Take merged code to live users through a planned, reversible rollout — plan the phases and the rollback, judge readiness on evidence, draft the release notes, then a human makes the go/no-go call. Use when the user has merged a change and asks how to roll it out, whether they are ready to launch, or for a go/no-go decision.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# release
|
|
7
|
+
|
|
8
|
+
This loop covers the step between `build`, which ends when a human merges, and `operate`,
|
|
9
|
+
which assumes the service is already live. A merge can be undone with a revert. A launch that
|
|
10
|
+
has touched users or data often cannot be undone, so this loop gets its own gates instead of
|
|
11
|
+
being folded into either neighbour.
|
|
12
|
+
|
|
13
|
+
## Stages
|
|
14
|
+
|
|
15
|
+
| # | Stage | Type | Skills | Gate |
|
|
16
|
+
|---|---|---|---|---|
|
|
17
|
+
| 1 | `plan` | generate | [`migration-plan`](../../skills/migration-plan/SKILL.md) | — |
|
|
18
|
+
| 2 | `ready` | verify | [`launch-readiness`](../../skills/launch-readiness/SKILL.md) | **G2.5** review |
|
|
19
|
+
| 3 | `announce` | generate | [`release-notes`](../../skills/release-notes/SKILL.md) | — |
|
|
20
|
+
| 4 | `go` | gate | [`council-review`](../../skills/council-review/SKILL.md) | **G2.6** human |
|
|
21
|
+
|
|
22
|
+
## How to run this loop
|
|
23
|
+
|
|
24
|
+
1. **Plan the rollout and the way back.** `migration-plan` sets out the phases, a tested
|
|
25
|
+
rollback for each one, and at most one named point of no return. For a code-only change
|
|
26
|
+
behind a flag, the plan can be short: the flag, the stages and how to turn it off. It still
|
|
27
|
+
has to exist.
|
|
28
|
+
2. **Judge readiness at G2.5.** `launch-readiness` lists the change's own failure modes, then
|
|
29
|
+
checks rollback, detection, response, measured targets, data and privacy, comms and
|
|
30
|
+
exposure, each with evidence. `REVISE` returns to `plan`, and the report names which gap to
|
|
31
|
+
close and which skill closes it. A missing rollback is `BLOCKED` on its own.
|
|
32
|
+
3. **Announce only once it is ready.** `release-notes` drafts the customer-facing and
|
|
33
|
+
internal notes from the git range. Writing them before G2.5 risks announcing a launch that
|
|
34
|
+
then does not happen.
|
|
35
|
+
4. **A human decides at G2.6.** The release owner decides whether to ship *now*, given
|
|
36
|
+
timing, freeze windows and on-call coverage. When that decision is contested, use
|
|
37
|
+
`council-review`. `RECONSIDER` means it is ready but this is the wrong time, and the work
|
|
38
|
+
waits instead of going back to `plan`.
|
|
39
|
+
|
|
40
|
+
After `PROCEED`, the change is live and the work moves to `operate`. Gaps that G2.5 sent to
|
|
41
|
+
`observability-plan` or `runbook-generator` are the first things `operate` picks up.
|
|
42
|
+
|
|
43
|
+
## Verdicts
|
|
44
|
+
|
|
45
|
+
Defined in [`contracts/terminals.json`](../../contracts/terminals.json). G2.5 emits `PROCEED`,
|
|
46
|
+
`PROCEED WITH CONDITIONS`, `REVISE` or `BLOCKED`. G2.6 adds `RECONSIDER`. `PROCEED WITH
|
|
47
|
+
CONDITIONS` at G2.5 is allowed only when the open rows are comms or exposure. A detection or
|
|
48
|
+
response gap is always `REVISE`.
|
|
49
|
+
|
|
50
|
+
## Non-interactive runs
|
|
51
|
+
|
|
52
|
+
Never invent evidence such as rehearsal logs, load-test numbers, dashboards or sign-offs.
|
|
53
|
+
When the change being released cannot be identified, emit `BLOCKED: need <the PR, tag, or
|
|
54
|
+
feature name>`. G2.6 is a human gate. A headless run stops after `announce` and reports the
|
|
55
|
+
G2.5 verdict for a person to act on.
|
|
56
|
+
|
|
57
|
+
## When a stage's skill is not installed
|
|
58
|
+
|
|
59
|
+
Name the missing skill and skilldrop as its source, do the minimal inline version of that
|
|
60
|
+
stage, and record the stage as degraded. For `ready`, the minimal version is the seven checks
|
|
61
|
+
written as a list, each marked met, not met or n/a with a reason. Skipping it is never the
|
|
62
|
+
minimal version.
|
|
63
|
+
|
|
64
|
+
## Quality bar
|
|
65
|
+
|
|
66
|
+
- **Rollback exists before readiness is judged.** A plan with no way back is the one thing that cannot be fixed after launch.
|
|
67
|
+
- **Readiness rests on evidence.** Every check links to something; "we're good" is `not met`.
|
|
68
|
+
- **Can and should are separate gates.** G2.5 says whether it can ship; G2.6 says whether it should ship now.
|
|
69
|
+
- **Detection gaps leave this loop as hand-offs.** `operate` picks them up first, rather than discovering them during the first incident.
|
|
70
|
+
|
|
71
|
+
## Anti-patterns to avoid
|
|
72
|
+
|
|
73
|
+
- ❌ **Jumping from merge to "instrument a running service".** That skips this loop entirely, which is the gap it exists to close.
|
|
74
|
+
- ❌ **Announcing before G2.5.** Customers hear about a launch that is then pulled.
|
|
75
|
+
- ❌ **Treating flag-off as a rollback without a data story.** If dual-write or a backfill has run, turning the flag off does not undo the data.
|
|
76
|
+
- ❌ **Letting G2.6 overrule a G2.5 `BLOCKED`.** A human can delay a ready launch; they cannot make an unready one ready by deciding to go.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "RFC-0031. Covers the step between build (ends at merge, G2.1) and operate (starts at instrument). The gate ids sit between G2 and G3 to match where the loop sits in the lifecycle.",
|
|
3
|
+
"name": "release",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "Take merged code to live users through a planned, reversible rollout — plan the phases and the rollback, judge readiness on evidence, draft the release notes, then a human makes the go/no-go call. Use when the user has merged a change and asks how to roll it out, whether they are ready to launch, or for a go/no-go decision.",
|
|
6
|
+
"entrypoint": "LOOP.md",
|
|
7
|
+
"kind": "loop",
|
|
8
|
+
"cap": 3,
|
|
9
|
+
"stages": [
|
|
10
|
+
{
|
|
11
|
+
"id": "plan",
|
|
12
|
+
"type": "generate",
|
|
13
|
+
"intent": "Decide the rollout phases, the rollback for each, and the one point of no return, before anything reaches users.",
|
|
14
|
+
"skills": ["migration-plan"]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": "ready",
|
|
18
|
+
"type": "verify",
|
|
19
|
+
"intent": "Judge on evidence whether the change can go live: rollback, detection, response, measured targets, data, comms, exposure.",
|
|
20
|
+
"skills": ["launch-readiness"],
|
|
21
|
+
"gate": {
|
|
22
|
+
"id": "G2.5",
|
|
23
|
+
"kind": "review",
|
|
24
|
+
"verdicts": ["PROCEED", "PROCEED WITH CONDITIONS", "REVISE", "BLOCKED"],
|
|
25
|
+
"revise_to": "plan"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": "announce",
|
|
30
|
+
"type": "generate",
|
|
31
|
+
"intent": "Write what users and the team are told. Only after readiness, so nobody announces a launch that then fails the check.",
|
|
32
|
+
"skills": ["release-notes"]
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": "go",
|
|
36
|
+
"type": "gate",
|
|
37
|
+
"intent": "A human decides whether it should ship now. Readiness says it can; this decides timing, freeze windows, and who is on call.",
|
|
38
|
+
"skills": ["council-review"],
|
|
39
|
+
"gate": {
|
|
40
|
+
"id": "G2.6",
|
|
41
|
+
"kind": "human",
|
|
42
|
+
"verdicts": ["PROCEED", "PROCEED WITH CONDITIONS", "REVISE", "RECONSIDER", "BLOCKED"],
|
|
43
|
+
"revise_to": "plan"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
package/model-routing.json
CHANGED
|
@@ -146,6 +146,10 @@
|
|
|
146
146
|
"tier": "standard",
|
|
147
147
|
"rationale": "Extracts architecture from code/IaC. Escalate to heavy on large codebases where cross-file inference is heavy."
|
|
148
148
|
},
|
|
149
|
+
"launch-readiness": {
|
|
150
|
+
"tier": "standard",
|
|
151
|
+
"rationale": "Checks evidence against a fixed checklist. Bounded synthesis, not adversarial review."
|
|
152
|
+
},
|
|
149
153
|
"runbook-generator": {
|
|
150
154
|
"tier": "standard",
|
|
151
155
|
"rationale": "Operational doc from service facts. Bounded synthesis."
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skilldrop-cli",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.2",
|
|
4
4
|
"description": "Portable AI-agent skills for the deliverables knowledge workers ship \u2014 diagrams, ADRs, PRDs, runbooks, decks, reviews \u2014 installable into Claude Code, Cursor, Kiro, and any IDE that takes custom instructions. One command per skill or per role-based pack.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Sanjay Ananthanarayan",
|
package/packs.json
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$comment": "Virtual skill packs — role-based bundles for one-command install. Packs are METADATA ONLY: skills stay in flat skills/<name> folders (golden rule: skills are discovered by path),
|
|
3
|
-
"version": "0.
|
|
2
|
+
"$comment": "Virtual skill packs — role-based bundles for one-command install. Packs are METADATA ONLY: skills stay in flat skills/<name> folders (golden rule: skills are discovered by path), every skill and every loop belongs to exactly one pack (RFC-0033 — the shape a later physical packs/<name>/ layout needs), and a pack may `requires` the `core` pack, which every installer then installs with it. validate.py enforces all of this. Install a pack with `python3 pack.py <pack> --install`; see README. Rationale: docs/rfcs/0001-skill-packs.md. `outcomes` (RFC-0026) is the second browse axis: packs say WHO needs a skill, outcomes say WHY someone opens the catalogue. It is the README's nine categories restated as seven outcomes and made machine-readable so the site cannot drift from them. Outcomes are a browse aid only — not an install unit — and validate.py enforces the same two-way check packs get.",
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"packs": {
|
|
5
|
+
"core": {
|
|
6
|
+
"description": "The cross-role toolkit every pack builds on: structured intake, document critique, the review council, and output hygiene, plus the ship-a-draft wrapper. Installed automatically with every role pack.",
|
|
7
|
+
"loops": ["ship-a-draft"],
|
|
8
|
+
"skills": [
|
|
9
|
+
"brief-intake",
|
|
10
|
+
"doc-critique",
|
|
11
|
+
"output-hygiene",
|
|
12
|
+
"council-review"
|
|
13
|
+
]
|
|
14
|
+
},
|
|
5
15
|
"solution-architect": {
|
|
6
16
|
"description": "Design-phase artifacts: diagrams, decision records, design docs, contracts, schemas, threat models, and the reviews that gate them.",
|
|
7
|
-
"
|
|
17
|
+
"requires": ["core"],
|
|
18
|
+
"loops": ["design"],
|
|
8
19
|
"skills": [
|
|
9
|
-
"brief-intake",
|
|
10
20
|
"architecture-diagrams",
|
|
11
21
|
"reverse-architecture",
|
|
12
22
|
"figma-diagrams",
|
|
@@ -14,22 +24,17 @@
|
|
|
14
24
|
"design-doc",
|
|
15
25
|
"tech-comparison-matrix",
|
|
16
26
|
"threat-model",
|
|
17
|
-
"agent-threat-model",
|
|
18
|
-
"agents-md-generator",
|
|
19
27
|
"api-contract-draft",
|
|
20
28
|
"data-contract",
|
|
21
29
|
"db-schema-design",
|
|
22
|
-
"nfr-spec"
|
|
23
|
-
"capacity-cost-model",
|
|
24
|
-
"council-review",
|
|
25
|
-
"doc-critique"
|
|
30
|
+
"nfr-spec"
|
|
26
31
|
]
|
|
27
32
|
},
|
|
28
33
|
"product-manager": {
|
|
29
|
-
"description": "Direction to requirements: PR/FAQs, strategy frameworks, OKRs, PRDs, journey maps,
|
|
30
|
-
"
|
|
34
|
+
"description": "Direction to requirements: PR/FAQs, strategy frameworks, OKRs, business cases, interviews, PRDs, journey maps, and success measurement.",
|
|
35
|
+
"requires": ["core"],
|
|
36
|
+
"loops": ["discover"],
|
|
31
37
|
"skills": [
|
|
32
|
-
"brief-intake",
|
|
33
38
|
"prfaq",
|
|
34
39
|
"strategy-analysis",
|
|
35
40
|
"okr-cascade",
|
|
@@ -37,23 +42,19 @@
|
|
|
37
42
|
"requirements-interview",
|
|
38
43
|
"prd-draft",
|
|
39
44
|
"user-journey-map",
|
|
40
|
-
"
|
|
41
|
-
"success-metrics",
|
|
42
|
-
"exec-summary",
|
|
43
|
-
"doc-critique",
|
|
44
|
-
"ai-use-case-triage"
|
|
45
|
+
"success-metrics"
|
|
45
46
|
]
|
|
46
47
|
},
|
|
47
48
|
"dev-team": {
|
|
48
|
-
"description": "Build-and-ship
|
|
49
|
-
"
|
|
49
|
+
"description": "Build-and-ship: story splitting, implementation with adversarial review, test plans, triage, migrations, launch readiness, release notes, agent-policy files, and code-quality gates.",
|
|
50
|
+
"requires": ["core"],
|
|
51
|
+
"loops": ["build", "release"],
|
|
50
52
|
"skills": [
|
|
51
53
|
"agents-md-generator",
|
|
52
54
|
"user-story-splitter",
|
|
53
55
|
"feature-implement-loop",
|
|
54
56
|
"pre-merge-review",
|
|
55
57
|
"devils-advocate",
|
|
56
|
-
"council-review",
|
|
57
58
|
"test-plan-generator",
|
|
58
59
|
"bug-triage",
|
|
59
60
|
"migration-plan",
|
|
@@ -61,12 +62,13 @@
|
|
|
61
62
|
"sonar-onboard",
|
|
62
63
|
"sonar-review",
|
|
63
64
|
"accessibility-audit",
|
|
64
|
-
"
|
|
65
|
-
"
|
|
65
|
+
"contribution-wizard",
|
|
66
|
+
"launch-readiness"
|
|
66
67
|
]
|
|
67
68
|
},
|
|
68
69
|
"sre-oncall": {
|
|
69
70
|
"description": "Operate the service: runbooks, observability design, incident communications, postmortems, and capacity/cost models.",
|
|
71
|
+
"requires": ["core"],
|
|
70
72
|
"loops": ["operate"],
|
|
71
73
|
"skills": [
|
|
72
74
|
"runbook-generator",
|
|
@@ -78,22 +80,21 @@
|
|
|
78
80
|
},
|
|
79
81
|
"stakeholder-comms": {
|
|
80
82
|
"description": "Non-technical audiences: audience profiling, deck outlines and real .pptx decks, exec summaries, decision logs, and guides.",
|
|
81
|
-
"
|
|
83
|
+
"requires": ["core"],
|
|
84
|
+
"loops": [],
|
|
82
85
|
"skills": [
|
|
83
|
-
"brief-intake",
|
|
84
86
|
"audience-profile",
|
|
85
87
|
"slide-outliner",
|
|
86
88
|
"deck-builder",
|
|
87
89
|
"exec-summary",
|
|
88
90
|
"decision-log",
|
|
89
|
-
"guide-builder"
|
|
90
|
-
"doc-critique",
|
|
91
|
-
"output-hygiene"
|
|
91
|
+
"guide-builder"
|
|
92
92
|
]
|
|
93
93
|
},
|
|
94
94
|
"ai-engineering": {
|
|
95
|
-
"description": "Adopt and build AI systems: readiness assessment, use-case triage, rollout and acceptable-use policy, plus agent loop design, subagent orchestration, spend budgets, agent security review, eval harnesses, AI-usage reporting
|
|
96
|
-
"
|
|
95
|
+
"description": "Adopt and build AI systems: readiness assessment, use-case triage, rollout and acceptable-use policy, plus agent loop design, subagent orchestration, spend budgets, agent security review, eval harnesses, and AI-usage reporting.",
|
|
96
|
+
"requires": ["core"],
|
|
97
|
+
"loops": [],
|
|
97
98
|
"skills": [
|
|
98
99
|
"agent-loop-design",
|
|
99
100
|
"subagent-design",
|
|
@@ -101,7 +102,6 @@
|
|
|
101
102
|
"agent-threat-model",
|
|
102
103
|
"llm-eval-harness",
|
|
103
104
|
"ai-usage-report",
|
|
104
|
-
"data-contract",
|
|
105
105
|
"ai-readiness-assessment",
|
|
106
106
|
"ai-use-case-triage",
|
|
107
107
|
"ai-adoption-rollout",
|
|
@@ -191,7 +191,8 @@
|
|
|
191
191
|
"observability-plan",
|
|
192
192
|
"release-notes",
|
|
193
193
|
"incident-comms",
|
|
194
|
-
"postmortem-generator"
|
|
194
|
+
"postmortem-generator",
|
|
195
|
+
"launch-readiness"
|
|
195
196
|
]
|
|
196
197
|
},
|
|
197
198
|
"explain-it-to-decision-makers": {
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: launch-readiness
|
|
3
|
+
description: Produce a go/no-go launch readiness report for a merged change before it goes live — one row per check (rollback path, alert and runbook per new failure mode, NFR targets measured, comms drafted, data/privacy sign-off), each with an owner, evidence link, and met / not met / n/a-because status, ending in a PROCEED / PROCEED WITH CONDITIONS / REVISE / BLOCKED verdict. Use when the user asks "are we ready to launch", "go/no-go", "production readiness review", "launch checklist", or "can we ship this to users".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# launch-readiness
|
|
7
|
+
|
|
8
|
+
You judge whether a change that is already merged *can* go live, using evidence rather than
|
|
9
|
+
reassurance. The output is a readiness report a release owner can act on in five minutes.
|
|
10
|
+
Whether it *should* go live now (timing, freeze windows, who is on call) is a separate human
|
|
11
|
+
decision. That belongs to `council-review` or the release owner, not to this report.
|
|
12
|
+
|
|
13
|
+
## How to respond
|
|
14
|
+
|
|
15
|
+
1. **Pin down what is launching.** You need: the change (a PR, a release tag, or a feature
|
|
16
|
+
name), who it reaches (internal, a percentage, everyone), and the release owner. If the
|
|
17
|
+
change itself is unknown, ask. You may ask at most 2 questions. A missing reach or owner
|
|
18
|
+
becomes an `[assumption]` to confirm. Everything else becomes a row that is `not met`
|
|
19
|
+
because evidence is missing.
|
|
20
|
+
|
|
21
|
+
2. **List the new failure modes first.** Before any checklist, write 3–5 ways this specific
|
|
22
|
+
change could hurt users or data once it is live. Read them from the diff, the design doc or
|
|
23
|
+
the migration plan. Each later check is judged against this list. A generic checklist with
|
|
24
|
+
no failure modes is a ritual.
|
|
25
|
+
|
|
26
|
+
3. **Fill [`templates/readiness-report.md`](templates/readiness-report.md).** It has one row
|
|
27
|
+
per check, and every row carries:
|
|
28
|
+
- **Status:** `met`, `not met`, or `n/a — <reason>`. `n/a` without a reason counts as `not met`.
|
|
29
|
+
- **Evidence:** a link, a command output, or a file path. A row with no evidence counts as
|
|
30
|
+
`not met`, however confident the user sounds. Evidence must cover the path the failure
|
|
31
|
+
mode touches; if it is unclear what it covered (which endpoint a load test hit), tag it
|
|
32
|
+
`[assumption]`.
|
|
33
|
+
- **Owner:** a role, not a person's name.
|
|
34
|
+
|
|
35
|
+
4. **Apply the checks in this order.** The order matters: the first ones are the costliest to
|
|
36
|
+
discover after launch.
|
|
37
|
+
1. **Rollback.** It must be a tested path back, with its data story stated. If a data or
|
|
38
|
+
schema change is involved and no plan exists, hand off to `migration-plan`.
|
|
39
|
+
2. **Detection.** Each new failure mode needs an alert that fires before users complain. If
|
|
40
|
+
one is missing, hand off to `observability-plan`.
|
|
41
|
+
3. **Response.** Each such alert needs a runbook entry. If one is missing, hand off to
|
|
42
|
+
`runbook-generator`.
|
|
43
|
+
4. **Quality targets.** Every target in `nfr-spec` (latency, availability, scale) must be
|
|
44
|
+
*measured*, for example by a load test or canary result. A target that is only asserted
|
|
45
|
+
does not count.
|
|
46
|
+
5. **Data and privacy.** New personal data, retention changes or new processors need a
|
|
47
|
+
named sign-off, or `n/a — <reason>`.
|
|
48
|
+
6. **Comms.** User-facing notes are drafted (see `release-notes`), support is briefed, and
|
|
49
|
+
the status page owner is known if the launch is risky.
|
|
50
|
+
7. **Exposure.** The first exposure is staged (flag, percentage or cohort), or there is a
|
|
51
|
+
stated reason why all-at-once is safe.
|
|
52
|
+
|
|
53
|
+
5. **Give the verdict.** It is the last line, with exactly one reason:
|
|
54
|
+
- `PROCEED`: every row is `met` or `n/a — <reason>`.
|
|
55
|
+
- `PROCEED WITH CONDITIONS`: only rows 6–7 are open, and each open row has an owner and a
|
|
56
|
+
date. The open rows travel with the release.
|
|
57
|
+
- `REVISE`: any row 2–5 is `not met`. Name the row and the hand-off that fixes it.
|
|
58
|
+
- `BLOCKED`: rollback is `not met`, or the change or its reach is unknown. A missing
|
|
59
|
+
rollback blocks on its own, whatever else passes.
|
|
60
|
+
|
|
61
|
+
**Non-interactive runs** (CI, subagent, headless): never invent evidence such as test results,
|
|
62
|
+
dashboards or sign-offs. Tag a guessed fact `[assumption]` and list it first. If the change
|
|
63
|
+
being launched cannot be identified, emit `BLOCKED: need <the PR, tag, or feature name>`.
|
|
64
|
+
|
|
65
|
+
## Useful references in this skill
|
|
66
|
+
|
|
67
|
+
- [`templates/readiness-report.md`](templates/readiness-report.md) — the report skeleton, one row per check.
|
|
68
|
+
- [`examples/schema-change-revise.md`](examples/schema-change-revise.md) — a worked report for a schema change that comes out `REVISE`.
|
|
69
|
+
|
|
70
|
+
## Quality bar
|
|
71
|
+
|
|
72
|
+
- **Every row has evidence or is `not met`.** Readiness asserted is not readiness.
|
|
73
|
+
- **The failure modes are specific to this change.** "The service could go down" is true of everything and checks nothing.
|
|
74
|
+
- **Rollback is judged first and can block alone.** Every other gap can be fixed while live; an irreversible launch with no way back cannot.
|
|
75
|
+
- **The verdict follows mechanically from the rows.** Two reviewers given the same rows reach the same verdict.
|
|
76
|
+
- **Owners are roles.** "Payments on-call", not a person who will change teams.
|
|
77
|
+
|
|
78
|
+
## When to use this skill
|
|
79
|
+
|
|
80
|
+
- ✅ A merged change is about to reach users and someone asks "are we ready?"
|
|
81
|
+
- ✅ A production readiness review needs a written go/no-go record.
|
|
82
|
+
- ✅ The `ready` stage of the `release` loop.
|
|
83
|
+
|
|
84
|
+
## When NOT to use this skill
|
|
85
|
+
|
|
86
|
+
- ❌ Deciding whether to *merge*. That is `pre-merge-review`'s gate, which happens earlier.
|
|
87
|
+
- ❌ Planning the rollout phases themselves. That is `migration-plan`; this skill checks that the plan exists and has been rehearsed.
|
|
88
|
+
- ❌ Choosing *when* to launch. Timing and freeze windows are the release owner's call, or `council-review`'s if they are contested.
|
|
89
|
+
|
|
90
|
+
## Anti-patterns to avoid
|
|
91
|
+
|
|
92
|
+
- ❌ **A generic checklist with every box ticked.** If no row is `not met` on a non-trivial launch, the evidence was not checked.
|
|
93
|
+
- ❌ **`n/a` as a way out.** Data and privacy marked `n/a` with no reason is the most common way a launch skips a review it needed.
|
|
94
|
+
- ❌ **Letting a strong row offset a missing rollback.** Great dashboards do not make an irreversible launch safe.
|
|
95
|
+
- ❌ **Writing the runbook or the alert inside this report.** Name the gap and hand it off; a readiness report that also drafts fixes becomes too long to read.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
[
|
|
2
|
+
{ "query": "Are we ready to launch this to users on Monday?", "should_trigger": true },
|
|
3
|
+
{ "query": "Run a go/no-go check on the checkout redesign before we turn it on", "should_trigger": true },
|
|
4
|
+
{ "query": "Do a production readiness review for the new search service", "should_trigger": true },
|
|
5
|
+
{ "query": "Give me a launch checklist for this release and tell me what's missing", "should_trigger": true },
|
|
6
|
+
{ "query": "Is this PR safe to merge?", "should_trigger": false },
|
|
7
|
+
{ "query": "Plan the phased rollout and backfill for moving users to the new auth provider", "should_trigger": false },
|
|
8
|
+
{ "query": "Write the release notes for everything since v2.3", "should_trigger": false },
|
|
9
|
+
{ "query": "Write the runbook for the payments service", "should_trigger": false }
|
|
10
|
+
]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill_name": "launch-readiness",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "Are we ready to launch? PR #412 adds a `loyalty_points` column to `customers`, backfills it from order history, and shows points on the checkout page. Going to 100% of users Thursday. Load test hit p99 180ms against a 250ms target (link: grafana/d/lt-412). We have a dashboard but haven't added alerts yet. Support hasn't been told.",
|
|
7
|
+
"assertions": [
|
|
8
|
+
"Lists 3-5 failure modes specific to this change (e.g. backfill load on customers, wrong point totals shown at checkout) before the checklist",
|
|
9
|
+
"Every check row has a status of met, not met, or n/a with a reason, plus an evidence column and an owner expressed as a role",
|
|
10
|
+
"Rollback is the first row and is not met, because no tested rollback or data story was supplied",
|
|
11
|
+
"Detection is not met because no alerts exist, and the report hands off to observability-plan rather than drafting the alert inline",
|
|
12
|
+
"The quality-targets row is met and cites the supplied load-test link as evidence",
|
|
13
|
+
"Exposure is flagged because a 100% launch is not staged and no reason is given for why all-at-once is safe",
|
|
14
|
+
"The verdict is BLOCKED, and the reason given is the missing rollback",
|
|
15
|
+
"No dashboards, test results, or sign-offs are invented beyond what the prompt supplied"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Worked example — schema change that comes out REVISE
|
|
2
|
+
|
|
3
|
+
## Input given to the skill
|
|
4
|
+
|
|
5
|
+
> Go/no-go for release `orders-v4.2`. It splits `orders.address` into `shipping_address_id`
|
|
6
|
+
> pointing at a new `addresses` table. We followed the migration plan
|
|
7
|
+
> (docs/migrations/orders-address.md): expand and backfill are done in staging, and dual-write
|
|
8
|
+
> is behind the flag `orders.address_split`. Rollback is "turn the flag off". It was rehearsed
|
|
9
|
+
> in staging on 2026-09-28 (log: ci/run/88213). The p99 target for order reads is 120ms, and
|
|
10
|
+
> the canary at 5% shows 96ms (grafana/d/orders-canary). The existing `orders-5xx` alert
|
|
11
|
+
> covers this. Release notes are drafted in PR #977. Plan is 5% → 50% → 100% over three days.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Launch readiness — orders-v4.2 (address split)
|
|
16
|
+
|
|
17
|
+
**Change:** release `orders-v4.2` · **Reach:** 5% → 50% → 100% over 3 days · **Release owner:** Orders tech lead
|
|
18
|
+
**Assessed:** 2026-10-01 · **Inputs:** migration plan, staging rollback log, canary dashboard, PR #977
|
|
19
|
+
|
|
20
|
+
## New failure modes
|
|
21
|
+
|
|
22
|
+
| # | Failure mode | Who is hurt | Reversible? |
|
|
23
|
+
|---|---|---|---|
|
|
24
|
+
| F1 | Dual-write diverges: an order is saved with an `addresses` row that doesn't match `orders.address` | Customers shipped to the wrong address | Partly. Data can be fixed, parcels already sent cannot |
|
|
25
|
+
| F2 | The read path picks the new column before the backfill is complete for that tenant | Customers who see a blank address at checkout | Yes, by turning the flag off |
|
|
26
|
+
| F3 | The extra join pushes order reads past p99 under full load | All checkout users | Yes, by turning the flag off |
|
|
27
|
+
|
|
28
|
+
## Checks
|
|
29
|
+
|
|
30
|
+
| # | Check | Covers | Status | Evidence | Owner |
|
|
31
|
+
|---|---|---|---|---|---|
|
|
32
|
+
| 1 | Rollback | all | met | Flag-off rehearsed in staging, ci/run/88213. While the old column is still written, flag-off loses no data | Orders on-call |
|
|
33
|
+
| 2 | Detection | F1–F3 | **not met** | `orders-5xx` catches F3 errors only. Nothing detects F1 divergence or F2 blank reads, because both return 200 | Orders on-call |
|
|
34
|
+
| 3 | Response | F1–F3 | **not met** | There is no runbook entry for divergence. `orders-5xx` has a runbook entry, but it does not mention the flag | Orders on-call |
|
|
35
|
+
| 4 | Quality targets | F3 | met | Canary p99 96ms against a 120ms target at 5%, grafana/d/orders-canary | Orders tech lead |
|
|
36
|
+
| 5 | Data & privacy | — | n/a — no new personal data. Address data moves between tables, and retention and processors are unchanged | Migration plan §2 | Data protection lead |
|
|
37
|
+
| 6 | Comms | — | met | Release notes drafted in PR #977. No customer-visible change | Orders tech lead |
|
|
38
|
+
| 7 | Exposure | — | met | Staged 5% → 50% → 100% behind `orders.address_split` | Release owner |
|
|
39
|
+
|
|
40
|
+
## Open items
|
|
41
|
+
|
|
42
|
+
- Row 2: add a reconciliation metric for dual-write divergence, and an alert on any non-zero count, plus an alert on blank-address reads. Orders on-call, before the 5% → 50% step. Hand off to `observability-plan`.
|
|
43
|
+
- Row 3: add a runbook entry for "divergence alert fires" (flag off, then run the reconciler), and add the flag to the `orders-5xx` entry. Orders on-call, same deadline. Hand off to `runbook-generator`.
|
|
44
|
+
|
|
45
|
+
## Verdict
|
|
46
|
+
|
|
47
|
+
**REVISE.** Row 2 is not met: the two failure modes that do lasting damage (F1, F2) return 200, so nothing would detect them. Fix rows 2 and 3, then run readiness again.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
**Why this is a good output:** the rollback is genuinely in place, so the verdict is REVISE and
|
|
52
|
+
not BLOCKED. The report notices that an existing alert covering the change only catches the
|
|
53
|
+
failure that is easiest to undo. It does not draft the alert or runbook itself; it names the
|
|
54
|
+
gap, the owner and the hand-off.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "launch-readiness",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Produce a go/no-go launch readiness report for a merged change before it goes live — one row per check (rollback path, alert and runbook per new failure mode, NFR targets measured, comms drafted, data/privacy sign-off), each with an owner, evidence link, and met / not met / n/a-because status, ending in a PROCEED / PROCEED WITH CONDITIONS / REVISE / BLOCKED verdict. Use when the user asks \"are we ready to launch\", \"go/no-go\", \"production readiness review\", \"launch checklist\", or \"can we ship this to users\".",
|
|
5
|
+
"entrypoint": "SKILL.md",
|
|
6
|
+
"deps": { "npm": [], "pip": [] },
|
|
7
|
+
"env": { "required": [], "optional": [] },
|
|
8
|
+
"related": [
|
|
9
|
+
"migration-plan",
|
|
10
|
+
"observability-plan",
|
|
11
|
+
"runbook-generator",
|
|
12
|
+
"nfr-spec",
|
|
13
|
+
"release-notes",
|
|
14
|
+
"council-review",
|
|
15
|
+
"pre-merge-review"
|
|
16
|
+
],
|
|
17
|
+
"handoff": [
|
|
18
|
+
{ "to": "migration-plan", "when": "the change has no tested rollback path", "purpose": "Plan the phases and the rollback, and name the point of no return, before readiness is judged again.", "fallback": "If migration-plan is absent, write the rollback as numbered steps with its data story inline, and mark the row not met until someone has rehearsed it." },
|
|
19
|
+
{ "to": "observability-plan", "when": "a new failure mode has no alert", "purpose": "Define the SLI and the burn-rate alert that would detect it.", "fallback": "If observability-plan is absent, name the symptom, the metric that shows it, and a threshold inline, tagged [assumption] for the owner to confirm." },
|
|
20
|
+
{ "to": "runbook-generator", "when": "an alert exists but has no runbook entry", "purpose": "Write the procedure the on-call follows when that alert fires.", "fallback": "If runbook-generator is absent, write recognise / mitigate / escalate as three lines under the row, and keep the row not met until the on-call owner has reviewed them." }
|
|
21
|
+
],
|
|
22
|
+
"tags": ["launch", "release", "readiness", "go-no-go", "production-readiness"],
|
|
23
|
+
"model": { "tier": "standard", "rationale": "Checks evidence against a fixed checklist. Bounded synthesis, not adversarial review." }
|
|
24
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Launch readiness — {change name}
|
|
2
|
+
|
|
3
|
+
**Change:** {PR / tag / feature} · **Reach:** {internal / N% / cohort / everyone} · **Release owner:** {role}
|
|
4
|
+
**Assessed:** {YYYY-MM-DD} · **Inputs:** {what was read — diff, design doc, migration plan, dashboards}
|
|
5
|
+
|
|
6
|
+
> **Assumptions to confirm first** (omit if none)
|
|
7
|
+
> - `[assumption]` {fact guessed rather than given}
|
|
8
|
+
|
|
9
|
+
## New failure modes
|
|
10
|
+
|
|
11
|
+
What this change, specifically, could do to users or data once live.
|
|
12
|
+
|
|
13
|
+
| # | Failure mode | Who is hurt | Reversible? |
|
|
14
|
+
|---|---|---|---|
|
|
15
|
+
| F1 | {e.g. backfill locks `orders` table under peak write load} | {checkout users} | {yes / no / partly} |
|
|
16
|
+
| F2 | | | |
|
|
17
|
+
| F3 | | | |
|
|
18
|
+
|
|
19
|
+
## Checks
|
|
20
|
+
|
|
21
|
+
Status is `met`, `not met`, or `n/a — <reason>`. No evidence means `not met`.
|
|
22
|
+
|
|
23
|
+
| # | Check | Covers | Status | Evidence | Owner |
|
|
24
|
+
|---|---|---|---|---|---|
|
|
25
|
+
| 1 | **Rollback** — tested path back, data story stated | all | | {link / command output} | {role} |
|
|
26
|
+
| 2 | **Detection** — an alert per failure mode, fires before users complain | F1–F3 | | | |
|
|
27
|
+
| 3 | **Response** — a runbook entry per alert in row 2 | F1–F3 | | | |
|
|
28
|
+
| 4 | **Quality targets** — each NFR target measured, not asserted | | | | |
|
|
29
|
+
| 5 | **Data & privacy** — sign-off for new personal data, retention, or processors | | | | |
|
|
30
|
+
| 6 | **Comms** — release notes drafted, support briefed, status-page owner known | | | | |
|
|
31
|
+
| 7 | **Exposure** — first exposure staged, or why all-at-once is safe | | | | |
|
|
32
|
+
|
|
33
|
+
## Open items
|
|
34
|
+
|
|
35
|
+
One line per `not met` row: what closes it, who, by when, and the hand-off if any.
|
|
36
|
+
|
|
37
|
+
- Row {n}: {what closes it} — {owner role}, {date} → {`migration-plan` / `observability-plan` / `runbook-generator` / none}
|
|
38
|
+
|
|
39
|
+
## Verdict
|
|
40
|
+
|
|
41
|
+
**{PROCEED | PROCEED WITH CONDITIONS | REVISE | BLOCKED}** — {the one reason, naming the row}.
|