@meyverick/agentic 5.0.2 → 5.1.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.
Files changed (26) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +15 -0
  3. package/README.md +2 -1
  4. package/package.json +5 -5
  5. package/scripts/{check-deps.mjs → check-deps.ts} +124 -59
  6. package/scripts/{git-dl.mjs → git-dl.ts} +11 -9
  7. package/skills/create-skill/SKILL.md +16 -16
  8. package/skills/create-skill/assets/templates/SKILL.md.template +1 -1
  9. package/skills/create-skill/evals/evals.json +4 -4
  10. package/skills/create-skill/evals/grading-template.json +1 -1
  11. package/skills/create-skill/references/component-decomposition.md +1 -1
  12. package/skills/create-skill/scripts/{audit-antipatterns.mjs → audit-antipatterns.ts} +75 -31
  13. package/skills/create-skill/scripts/{compute-benchmark.mjs → compute-benchmark.ts} +71 -30
  14. package/skills/create-skill/scripts/run-cold-eval.ts +202 -0
  15. package/skills/create-skill/scripts/{scaffold-skill.mjs → scaffold-skill.ts} +45 -25
  16. package/skills/create-skill/scripts/validate-routing.ts +218 -0
  17. package/skills/create-skill/scripts/{validate-structure.mjs → validate-structure.ts} +97 -36
  18. package/skills/okf-docs/SKILL.md +1 -1
  19. package/skills/okf-docs/evals/evals.json +2 -2
  20. package/skills/okf-docs/scripts/{validate-frontmatter.mjs → validate-frontmatter.ts} +73 -32
  21. package/skills/openspec-learn/references/evaluation-methodology.md +2 -2
  22. package/skills/openspec-pi-apply/SKILL.md +129 -0
  23. package/skills/openspec-pi-apply/references/rpc-protocol.md +43 -0
  24. package/skills/openspec-pi-apply/scripts/pi-rpc-apply.ts +421 -0
  25. package/skills/create-skill/scripts/run-cold-eval.mjs +0 -118
  26. package/skills/create-skill/scripts/validate-routing.mjs +0 -137
package/AGENTS.md CHANGED
@@ -181,7 +181,7 @@ stale_after: 2027-08-15
181
181
  - **QMD** (Hybrid Search & Local Memory): Project-local index only — `qmd init` at repo root → `<repo>/.qmd/` (gitignored); NEVER create or populate a global/shared index, never fall back to one. Mode select: exact terms/titles/headings/symbols → `qmd search '"<phrase>"' --json -n 10 -c <collection>` (BM25, no LLM); concept/paraphrase → `qmd query $'intent: <goal + what to avoid>\nlex: <anchors>\nvec: <paraphrase>' --json -n 10` (author the fields yourself — never paste raw request text). Retrieve before claiming: `qmd get "#id:from:count"` / `qmd multi-get "<ids>" --json` (never pipe `sed`/`head`/`tail`). Maintenance [CRITICAL] mutations → `qmd update && qmd embed --chunk-strategy auto`; health `qmd status`; depth `.agents/skills/qmd-research/` (query grammar · filters · index upkeep).
182
182
  - **Context7** (External Framework Intelligence): Trigger [CRITICAL] generating third-party setup/config or touching frameworks/packages (SvelteKit, Tailwind, SQLx, ts-rs, miniplex, Threlte, babylonjs, PixiJS, Phaser, Axum, Rayon, candle, tauri, grammY, `@telegram-apps/sdk`) → autonomous Context7 → prevent hallucinated outdated training data. Flow: `resolve-library-id(name, query)` → `/org/project` ID → `query-docs(id, full_query)` → SOTA patterns. Append explicit versions to queries. Priority Context7 > web search. Bypass for internal business logic.
183
183
  - **check** (Workspace Gate Verification): Textbook and diagnostic manual for `./scripts/check.sh` gates. Consult `.agents/skills/check/SKILL.md` when executing check-gates, configuring the 6-slot harness (pointers, secrets, native lanes, tracked compile-time assets, clean-clone sandbox, smoke), or diagnosing and self-healing gate failures.
184
- - **Skill Engineering** (`./.agents/skills/`): Utilization [CRITICAL] task initiation → scan `./.agents/skills/` → evaluate `description` frontmatters → load `SKILL.md` if relevant. Creation: extract recurring gotchas/workflows into `skills/<name>/SKILL.md` (action gerund, Validation Loops, Plan-Validate-Execute, `references/` offload for progressive disclosure). Anatomy [CRITICAL] frontmatter per the Agent Skills spec (`name` + `description` required; `license` · `compatibility` · `metadata` · `allowed-tools` optional — OKF provenance `type`/`generated` is for documents, §7), `description` <1024 chars imperative "Use this skill when...". Script bundling: self-contained (Bun `.mjs`/single-file Go/PEP 723), idempotent, structured JSON/CSV, ZERO prompts. Ad-hoc spikes [CRITICAL] candid debug scripts / pre-implementation endpoint tests / quick API validation → self-contained `.mjs` via `bun <file>.mjs` (native top-level await+fetch, zero setup). Eval-driven evolution: generate `evals/evals.json`, measure baseline vs with-skill (pass rate/tokens/duration) → optimize `SKILL.md`.
184
+ - **Skill Engineering** (`./.agents/skills/`): Utilization [CRITICAL] task initiation → scan `./.agents/skills/` → evaluate `description` frontmatters → load `SKILL.md` if relevant. Creation: extract recurring gotchas/workflows into `skills/<name>/SKILL.md` (action gerund, Validation Loops, Plan-Validate-Execute, `references/` offload for progressive disclosure). Anatomy [CRITICAL] frontmatter per the Agent Skills spec (`name` + `description` required; `license` · `compatibility` · `metadata` · `allowed-tools` optional — OKF provenance `type`/`generated` is for documents, §7), `description` <1024 chars imperative "Use this skill when...". Script bundling: self-contained (Bun `.ts`/single-file Go/PEP 723), idempotent, structured JSON/CSV, ZERO prompts. Ad-hoc spikes [CRITICAL] candid debug scripts / pre-implementation endpoint tests / quick API validation → self-contained `.ts` via `bun <file>.ts` (native top-level await+fetch, zero setup). Eval-driven evolution: generate `evals/evals.json`, measure baseline vs with-skill (pass rate/tokens/duration) → optimize `SKILL.md`.
185
185
 
186
186
  ## 9. Exploration & Discovery Stance
187
187
 
package/CHANGELOG.md CHANGED
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
+ ## [5.1.0] - 2026-09-28
9
+
10
+ ### Added
11
+
12
+ - **openspec-pi-apply skill** (`add-openspec-pi-apply-skill`): 10th shipped skill — delegate OpenSpec change task implementation to a headless pi worker agent via JSON-RPC (`scripts/pi-rpc-apply.ts`), providing live streaming, automated event loop triage, and non-blocking background task orchestration
13
+
14
+ ### Changed
15
+
16
+ - **Consumer scripts migrated to Bun TypeScript** (`migrate-consumer-scripts-to-bun-ts`): convert all 9 consumer scripts across `scripts/` and skill packages to self-contained, typed Bun `.ts` (`check-deps.ts`, `git-dl.ts`, `validate-frontmatter.ts`, `validate-structure.ts`, `validate-routing.ts`, `audit-antipatterns.ts`, `run-cold-eval.ts`, `compute-benchmark.ts`, `scaffold-skill.ts`) with `#!/usr/bin/env bun` shebangs, eliminating language fragmentation
17
+ - **CI validator runners modernized**: update `project/.github/workflows/quality.yml` to execute validators natively with `bun run`
18
+ - **Package scripts and binaries aligned**: update `project/package.json` `scripts` and `bin` to reference `.ts` entrypoints
19
+ - **Agent directives standardized on Bun TypeScript**: update `AGENTS.md` (root and submodule) §8 to mandate self-contained Bun `.ts` (`bun <file>.ts`) for script bundling and ad-hoc spikes
20
+ - **Skill creation and evals alignment**: update `create-skill` instructions, references, template assets, and eval suites (`evals.json`) to reference `.ts` validators and scripts
21
+ - Total shipped skills increased from 9 to 10
22
+
8
23
  ## [5.0.2] - 2026-09-23
9
24
 
10
25
  ### Changed
package/README.md CHANGED
@@ -10,7 +10,7 @@ bunx @meyverick/agentic
10
10
 
11
11
  *(or via GitHub direct: `bunx github:meyverick/agentic`)*
12
12
 
13
- Installs 9 skills into your project's `.agents/skills/`, distributes utility scripts into `./scripts/`, writes a provenance manifest, and creates `openspec/reports/`.
13
+ Installs 10 skills into your project's `.agents/skills/`, distributes utility scripts into `./scripts/`, writes a provenance manifest, and creates `openspec/reports/`.
14
14
 
15
15
  ## Skills
16
16
 
@@ -23,6 +23,7 @@ Installs 9 skills into your project's `.agents/skills/`, distributes utility scr
23
23
  | okf-docs | Author OKF v0.2-compliant documents — ADRs, module docs, decision records — with mandatory provenance frontmatter and mechanical validation |
24
24
  | openspec-harden | Harden an existing OpenSpec change for cold application — enrich artifacts with concrete file paths, code blocks, and verify steps |
25
25
  | openspec-learn | Analyze reports in `./openspec/reports/` and generate OpenSpec proposals for skill/prompt improvements |
26
+ | openspec-pi-apply | Delegate OpenSpec change task implementation to a headless pi worker agent via JSON-RPC |
26
27
  | openspec-report | Generate self-reflection (meditation) reports from archived OpenSpec changes |
27
28
  | qmd-research | Research project markdown and specifications using local QMD hybrid search, and maintain index collections |
28
29
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meyverick/agentic",
3
- "version": "5.0.2",
3
+ "version": "5.1.0",
4
4
  "description": "AI agent skills and prompts for pi.dev",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -18,13 +18,13 @@
18
18
  "CHANGELOG.md"
19
19
  ],
20
20
  "scripts": {
21
- "check-deps": "./scripts/check-deps.mjs",
22
- "git-dl": "./scripts/git-dl.mjs"
21
+ "check-deps": "./scripts/check-deps.ts",
22
+ "git-dl": "./scripts/git-dl.ts"
23
23
  },
24
24
  "bin": {
25
25
  "agentic": "install.ts",
26
- "check-deps": "scripts/check-deps.mjs",
27
- "git-dl": "scripts/git-dl.mjs"
26
+ "check-deps": "scripts/check-deps.ts",
27
+ "git-dl": "scripts/git-dl.ts"
28
28
  },
29
29
  "keywords": [
30
30
  "ai",
@@ -17,6 +17,7 @@ const colors = {
17
17
  };
18
18
 
19
19
  const USER_AGENT = 'agentic-dep-checker/1.0 (https://github.com/meyverick/agentic)';
20
+ const isHelp = process.argv.includes('--help') || process.argv.includes('-h');
20
21
  const includeReferences = process.argv.includes('--all') || process.argv.includes('--references');
21
22
  const isJson = process.argv.includes('--json');
22
23
 
@@ -36,9 +37,72 @@ const IGNORED_DIRS = new Set([
36
37
  ...(includeReferences ? [] : ['references'])
37
38
  ]);
38
39
 
39
- async function asyncPool(limit, items, iteratorFn) {
40
- const ret = [];
41
- const executing = new Set();
40
+ interface ScanResults {
41
+ cargo: string[];
42
+ npm: string[];
43
+ lockFiles: string[];
44
+ toolchains: string[];
45
+ }
46
+
47
+ interface ToolchainItem {
48
+ name: string;
49
+ version: string;
50
+ }
51
+
52
+ interface CargoDependency {
53
+ name: string;
54
+ version: string;
55
+ git: string | null;
56
+ section: string;
57
+ }
58
+
59
+ interface SemverDiff {
60
+ status: 'UP_TO_DATE' | 'MINOR_PATCH' | 'MAJOR_BREAKING' | 'UNKNOWN';
61
+ reason?: string;
62
+ }
63
+
64
+ interface JsonReport {
65
+ summary: {
66
+ totalChecked: number;
67
+ upToDate: number;
68
+ minorPatch: number;
69
+ majorBreaking: number;
70
+ };
71
+ toolchains: Array<{
72
+ name: string;
73
+ current: string;
74
+ latest: string | null;
75
+ status: string;
76
+ reason: string | null;
77
+ }>;
78
+ rustModules: Array<{
79
+ file: string;
80
+ dependencies: Array<{
81
+ name: string;
82
+ declaredVersion: string;
83
+ resolvedVersion: string;
84
+ latest: string | null;
85
+ status: string;
86
+ reason: string | null;
87
+ section: string;
88
+ }>;
89
+ }>;
90
+ npmModules: Array<{
91
+ file: string;
92
+ dependencies: Array<{
93
+ name: string;
94
+ declaredVersion: string;
95
+ latest: string | null;
96
+ status: string;
97
+ reason: string | null;
98
+ type: string;
99
+ }>;
100
+ }>;
101
+ }
102
+
103
+ async function asyncPool<T, R>(limit: number, items: T[], iteratorFn: (item: T) => Promise<R>): Promise<R[]> {
104
+ const ret: Promise<R>[] = [];
105
+ const executing = new Set<Promise<R>>();
42
106
  for (const item of items) {
43
107
  const p = Promise.resolve().then(() => iteratorFn(item));
44
108
  ret.push(p);
@@ -52,10 +116,10 @@ async function asyncPool(limit, items, iteratorFn) {
52
116
  return Promise.all(ret);
53
117
  }
54
118
 
55
- async function scanFiles(dir) {
56
- const results = { cargo: [], npm: [], lockFiles: [], toolchains: [] };
119
+ async function scanFiles(dir: string): Promise<ScanResults> {
120
+ const results: ScanResults = { cargo: [], npm: [], lockFiles: [], toolchains: [] };
57
121
 
58
- async function walk(currentDir) {
122
+ async function walk(currentDir: string): Promise<void> {
59
123
  const entries = await readdir(currentDir, { withFileTypes: true }).catch(() => []);
60
124
  for (const entry of entries) {
61
125
  const fullPath = join(currentDir, entry.name);
@@ -84,8 +148,12 @@ async function scanFiles(dir) {
84
148
  return results;
85
149
  }
86
150
 
87
- async function detectToolchains(toolchainFiles, cargoFiles, npmFiles) {
88
- let rustVersion = null;
151
+ async function detectToolchains(
152
+ toolchainFiles: string[],
153
+ cargoFiles: string[],
154
+ npmFiles: string[]
155
+ ): Promise<ToolchainItem[]> {
156
+ let rustVersion: string | null = null;
89
157
 
90
158
  for (const tf of toolchainFiles) {
91
159
  try {
@@ -119,14 +187,14 @@ async function detectToolchains(toolchainFiles, cargoFiles, npmFiles) {
119
187
  } catch {}
120
188
  }
121
189
 
122
- let cargoVersion = null;
190
+ let cargoVersion: string | null = null;
123
191
  try {
124
192
  const out = execSync('cargo --version', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] });
125
193
  const m = out.match(/cargo\s+([0-9]+\.[0-9]+\.[0-9]+)/);
126
194
  if (m) cargoVersion = m[1];
127
195
  } catch {}
128
196
 
129
- let bunVersion = null;
197
+ let bunVersion: string | null = null;
130
198
  for (const nf of npmFiles) {
131
199
  try {
132
200
  const pkg = JSON.parse(await readFile(nf, 'utf8'));
@@ -150,7 +218,7 @@ async function detectToolchains(toolchainFiles, cargoFiles, npmFiles) {
150
218
  } catch {}
151
219
  }
152
220
 
153
- const items = [];
221
+ const items: ToolchainItem[] = [];
154
222
  if (rustVersion) {
155
223
  items.push({ name: 'rust', version: rustVersion });
156
224
  }
@@ -164,7 +232,7 @@ async function detectToolchains(toolchainFiles, cargoFiles, npmFiles) {
164
232
  return items;
165
233
  }
166
234
 
167
- async function fetchLatestToolchain() {
235
+ async function fetchLatestToolchain(): Promise<string | null> {
168
236
  try {
169
237
  const res = await fetch('https://static.rust-lang.org/dist/channel-rust-stable.toml', {
170
238
  headers: { 'User-Agent': USER_AGENT }
@@ -178,8 +246,8 @@ async function fetchLatestToolchain() {
178
246
  }
179
247
  }
180
248
 
181
- async function parseCargoLocks(lockFiles) {
182
- const lockedVersions = new Map();
249
+ async function parseCargoLocks(lockFiles: string[]): Promise<Map<string, string[]>> {
250
+ const lockedVersions = new Map<string, string[]>();
183
251
  for (const lockPath of lockFiles) {
184
252
  try {
185
253
  const content = await readFile(lockPath, 'utf8');
@@ -193,7 +261,7 @@ async function parseCargoLocks(lockFiles) {
193
261
  if (!lockedVersions.has(name)) {
194
262
  lockedVersions.set(name, []);
195
263
  }
196
- lockedVersions.get(name).push(ver);
264
+ lockedVersions.get(name)!.push(ver);
197
265
  }
198
266
  }
199
267
  } catch {}
@@ -201,7 +269,7 @@ async function parseCargoLocks(lockFiles) {
201
269
  return lockedVersions;
202
270
  }
203
271
 
204
- function resolveLockedVersion(name, declaredVer, lockedMap) {
272
+ function resolveLockedVersion(name: string, declaredVer: string, lockedMap: Map<string, string[]>): string {
205
273
  const versions = lockedMap.get(name);
206
274
  if (!versions || versions.length === 0) return declaredVer;
207
275
  if (versions.length === 1) return versions[0];
@@ -220,7 +288,7 @@ function resolveLockedVersion(name, declaredVer, lockedMap) {
220
288
  return matched || versions[0];
221
289
  }
222
290
 
223
- function getCrateIndexPath(crateName) {
291
+ function getCrateIndexPath(crateName: string): string {
224
292
  const name = crateName.toLowerCase();
225
293
  if (name.length === 1) return `1/${name}`;
226
294
  if (name.length === 2) return `2/${name}`;
@@ -228,9 +296,7 @@ function getCrateIndexPath(crateName) {
228
296
  return `${name.slice(0, 2)}/${name.slice(2, 4)}/${name}`;
229
297
  }
230
298
 
231
- async function fetchLatestCrate(crateName) {
232
- let version = null;
233
-
299
+ async function fetchLatestCrate(crateName: string): Promise<{ version: string | null }> {
234
300
  try {
235
301
  const indexPath = getCrateIndexPath(crateName);
236
302
  const indexRes = await fetch(`https://index.crates.io/${indexPath}`, {
@@ -244,27 +310,26 @@ async function fetchLatestCrate(crateName) {
244
310
  try {
245
311
  const entry = JSON.parse(lines[i]);
246
312
  if (!entry.yanked) {
247
- version = entry.vers;
248
- break;
313
+ return { version: entry.vers };
249
314
  }
250
315
  } catch {}
251
316
  }
252
317
  }
253
318
 
254
- return { version };
319
+ return { version: null };
255
320
  } catch {
256
321
  return { version: null };
257
322
  }
258
323
  }
259
324
 
260
- async function fetchLatestNpm(pkgName) {
325
+ async function fetchLatestNpm(pkgName: string): Promise<{ version: string | null }> {
261
326
  try {
262
327
  const encoded = pkgName.startsWith('@')
263
328
  ? `@${encodeURIComponent(pkgName.slice(1))}`
264
329
  : encodeURIComponent(pkgName);
265
330
  const res = await fetch(`https://registry.npmjs.org/${encoded}`);
266
331
  if (!res.ok) return { version: null };
267
- const data = await res.json();
332
+ const data = (await res.json()) as { 'dist-tags'?: { latest?: string }; versions?: Record<string, unknown> };
268
333
  const version = data['dist-tags']?.latest ?? Object.keys(data.versions || {}).pop() ?? null;
269
334
  return { version };
270
335
  } catch {
@@ -272,10 +337,10 @@ async function fetchLatestNpm(pkgName) {
272
337
  }
273
338
  }
274
339
 
275
- function parseCargoDependencies(content) {
276
- const deps = [];
340
+ function parseCargoDependencies(content: string): CargoDependency[] {
341
+ const deps: CargoDependency[] = [];
277
342
  const lines = content.split('\n');
278
- let currentSection = null;
343
+ let currentSection: string | null = null;
279
344
 
280
345
  for (const line of lines) {
281
346
  const trimmed = line.trim();
@@ -298,8 +363,8 @@ function parseCargoDependencies(content) {
298
363
  if (depMatch) {
299
364
  const name = depMatch[1];
300
365
  const val = depMatch[2];
301
- let version = null;
302
- let git = null;
366
+ let version: string | null = null;
367
+ let git: string | null = null;
303
368
 
304
369
  if (val.startsWith('"')) {
305
370
  version = val.split('"')[1];
@@ -320,7 +385,7 @@ function parseCargoDependencies(content) {
320
385
  return deps;
321
386
  }
322
387
 
323
- function getSemverDiff(declared, latest) {
388
+ function getSemverDiff(declared: string, latest: string | null): SemverDiff {
324
389
  if (!latest) return { status: 'UNKNOWN' };
325
390
 
326
391
  const cleanDeclared = declared.replace(/^[\^~>=<]+/, '').trim();
@@ -345,7 +410,22 @@ function getSemverDiff(declared, latest) {
345
410
  return { status: 'MINOR_PATCH', reason: `${cleanDeclared} -> ${latest}` };
346
411
  }
347
412
 
348
- async function main() {
413
+ function printUsage(): void {
414
+ console.log(`Usage: bun check-deps.ts [options] [target-dir]
415
+
416
+ Options:
417
+ --all, --references Include scanning of references directories
418
+ --json Output machine-readable JSON report
419
+ -h, --help Show this help message
420
+ `);
421
+ }
422
+
423
+ async function main(): Promise<void> {
424
+ if (isHelp) {
425
+ printUsage();
426
+ process.exit(0);
427
+ }
428
+
349
429
  if (!isJson) {
350
430
  console.log(`${colors.bold}${colors.cyan}================================================================${colors.reset}`);
351
431
  console.log(`${colors.bold}${colors.cyan} Agentic - Dependency Freshness Verifier ${colors.reset}`);
@@ -362,13 +442,8 @@ async function main() {
362
442
  let totalMinorPatch = 0;
363
443
  let totalMajorBreaking = 0;
364
444
 
365
- const jsonReport = {
366
- summary: {
367
- totalChecked: 0,
368
- upToDate: 0,
369
- minorPatch: 0,
370
- majorBreaking: 0
371
- },
445
+ const jsonReport: JsonReport = {
446
+ summary: { totalChecked: 0, upToDate: 0, minorPatch: 0, majorBreaking: 0 },
372
447
  toolchains: [],
373
448
  rustModules: [],
374
449
  npmModules: []
@@ -376,9 +451,7 @@ async function main() {
376
451
 
377
452
  // 1. Toolchains (Rust, Cargo, Bun)
378
453
  if (toolchainItems.length > 0) {
379
- if (!isJson) {
380
- console.log(`${colors.bold}${colors.blue}⚙ Toolchains: Rust, Cargo & Bun${colors.reset}`);
381
- }
454
+ if (!isJson) console.log(`${colors.bold}${colors.blue}⚙ Toolchains: Rust, Cargo & Bun${colors.reset}`);
382
455
  const latestRust = await fetchLatestToolchain();
383
456
  const { version: latestBun } = await fetchLatestNpm('bun');
384
457
 
@@ -424,17 +497,12 @@ async function main() {
424
497
  const deps = parseCargoDependencies(content);
425
498
 
426
499
  if (deps.length === 0) continue;
500
+ if (!isJson) console.log(`${colors.bold}${colors.blue}📦 Rust Module: ${relPath}${colors.reset}`);
427
501
 
428
- if (!isJson) {
429
- console.log(`${colors.bold}${colors.blue}📦 Rust Module: ${relPath}${colors.reset}`);
430
- }
431
-
432
- const currentModule = { file: relPath, dependencies: [] };
502
+ const currentModule: JsonReport['rustModules'][number] = { file: relPath, dependencies: [] };
433
503
 
434
504
  const results = await asyncPool(10, deps, async (dep) => {
435
- if (dep.git) {
436
- return { ...dep, latest: 'git' };
437
- }
505
+ if (dep.git) return { ...dep, latest: 'git' };
438
506
  const { version: latest } = await fetchLatestCrate(dep.name);
439
507
  return { ...dep, latest };
440
508
  });
@@ -482,14 +550,14 @@ async function main() {
482
550
  for (const npmPath of npm) {
483
551
  const relPath = relative(rootDir, npmPath);
484
552
  const raw = await readFile(npmPath, 'utf8');
485
- let pkgJson = {};
553
+ let pkgJson: { dependencies?: Record<string, string>; devDependencies?: Record<string, string> } = {};
486
554
  try {
487
555
  pkgJson = JSON.parse(raw);
488
556
  } catch {
489
557
  continue;
490
558
  }
491
559
 
492
- const allDeps = [];
560
+ const allDeps: Array<{ name: string; version: string; type: string }> = [];
493
561
  if (pkgJson.dependencies) {
494
562
  for (const [name, version] of Object.entries(pkgJson.dependencies)) {
495
563
  if (!version.startsWith('workspace:')) {
@@ -506,12 +574,9 @@ async function main() {
506
574
  }
507
575
 
508
576
  if (allDeps.length === 0) continue;
577
+ if (!isJson) console.log(`${colors.bold}${colors.magenta}🌐 NPM/Web Module: ${relPath}${colors.reset}`);
509
578
 
510
- if (!isJson) {
511
- console.log(`${colors.bold}${colors.magenta}🌐 NPM/Web Module: ${relPath}${colors.reset}`);
512
- }
513
-
514
- const currentModule = { file: relPath, dependencies: [] };
579
+ const currentModule: JsonReport['npmModules'][number] = { file: relPath, dependencies: [] };
515
580
 
516
581
  const results = await asyncPool(10, allDeps, async (dep) => {
517
582
  const { version: latest } = await fetchLatestNpm(dep.name);
@@ -577,11 +642,11 @@ async function main() {
577
642
  }
578
643
  }
579
644
 
580
- main().catch((err) => {
645
+ main().catch((err: Error) => {
581
646
  if (isJson) {
582
647
  console.error(JSON.stringify({ error: err.message }));
583
648
  } else {
584
649
  console.error('Error running dependency check:', err);
585
650
  }
586
651
  process.exit(1);
587
- });
652
+ });
@@ -3,18 +3,19 @@ import { execFileSync, spawn } from 'node:child_process';
3
3
  import { mkdir, rm } from 'node:fs/promises';
4
4
  import { basename, join } from 'node:path';
5
5
  import { Readable } from 'node:stream';
6
+ import type { ReadableStream as WebReadableStream } from 'node:stream/web';
6
7
 
7
8
  const input = process.argv[2];
8
9
 
9
10
  if (input === '-h' || input === '--help') {
10
- console.log('Usage: git-dl.mjs <owner/repo|url> [target-dir]');
11
+ console.log('Usage: git-dl.ts <owner/repo|url> [target-dir]');
11
12
  console.log('Default target-dir: references/<repo>');
12
13
  process.exit(0);
13
14
  }
14
15
 
15
16
  if (!input) {
16
17
  console.error('Error: Provide a GitHub URL or owner/repo');
17
- console.error('Usage: git-dl.mjs <owner/repo|url> [target-dir]');
18
+ console.error('Usage: git-dl.ts <owner/repo|url> [target-dir]');
18
19
  console.error('Default target-dir: references/<repo>');
19
20
  process.exit(1);
20
21
  }
@@ -37,22 +38,23 @@ const defaultDir = join('references', basename(repo));
37
38
  const dir = process.argv[3] || defaultDir;
38
39
 
39
40
  // Resolve the latest tag via git ls-remote (version sorted, handles prefixes and monorepos)
40
- let lsOutput;
41
+ let lsOutput: string;
41
42
  try {
42
43
  lsOutput = execFileSync(
43
44
  'git',
44
45
  ['ls-remote', '--tags', '--refs', '--sort=v:refname', `https://github.com/${repo}.git`],
45
46
  { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }
46
47
  );
47
- } catch (err) {
48
- const errMsg = err.stderr ? err.stderr.trim() : err.message;
48
+ } catch (err: unknown) {
49
+ const execErr = err as { stderr?: Buffer | string; message: string };
50
+ const errMsg = execErr.stderr ? execErr.stderr.toString().trim() : execErr.message;
49
51
  console.error(`Error: Failed to query tags for '${repo}': ${errMsg}`);
50
52
  process.exit(1);
51
53
  }
52
54
 
53
55
  const lines = lsOutput.trim().split('\n').filter(Boolean);
54
56
  const lastLine = lines[lines.length - 1];
55
- let rawTag = null;
57
+ let rawTag: string | null = null;
56
58
  if (lastLine) {
57
59
  const parts = lastLine.split(/\s+/);
58
60
  if (parts.length >= 2) {
@@ -77,12 +79,12 @@ const res = await fetch(tarballUrl, {
77
79
  }
78
80
  });
79
81
 
80
- if (!res.ok) {
82
+ if (!res.ok || !res.body) {
81
83
  console.error(`Error: Failed to download tarball from ${tarballUrl} (${res.status} ${res.statusText})`);
82
84
  process.exit(1);
83
85
  }
84
86
 
85
- await new Promise((resolve, reject) => {
87
+ await new Promise<void>((resolve, reject) => {
86
88
  const tar = spawn('tar', ['-xz', '-C', dir, '--strip-components=1'], {
87
89
  stdio: ['pipe', 'inherit', 'inherit']
88
90
  });
@@ -93,7 +95,7 @@ await new Promise((resolve, reject) => {
93
95
  else reject(new Error(`tar extraction exited with code ${code}`));
94
96
  });
95
97
 
96
- Readable.fromWeb(res.body).pipe(tar.stdin);
98
+ Readable.fromWeb(res.body as unknown as WebReadableStream).pipe(tar.stdin);
97
99
  });
98
100
 
99
101
  const displayDir = dir.startsWith('/') || dir.startsWith('.') ? dir : `./${dir}`;
@@ -32,7 +32,7 @@ Create new Agent Skills from problem descriptions or instruction files. Fully au
32
32
 
33
33
  When the user wants to build a new skill:
34
34
 
35
- 1. Run `scripts/scaffold-skill.mjs <skill-name>` to create skeleton in `./project/skills/`
35
+ 1. Run `scripts/scaffold-skill.ts <skill-name>` to create skeleton in `./project/skills/`
36
36
  2. Follow the workflow below to fill in content
37
37
  3. Skill ships when Phase 7 completes
38
38
 
@@ -95,7 +95,7 @@ Determine:
95
95
  - Tier 2 (SKILL.md body): <1500 tokens
96
96
  - Tier 3 (references/): on-demand only
97
97
  4. **Components**: Persona / instructions / templates / data (not omnibus) — see `references/component-decomposition.md` (Level 2).
98
- 5. **Scripts**: Reusable logic to bundle (.mjs, cold/isolated, relative paths only)
98
+ 5. **Scripts**: Reusable logic to bundle (.ts, cold/isolated, relative paths only)
99
99
  6. **Eval strategy**: Test cases, assertions, near-miss negatives, baseline comparison
100
100
  7. **Activation boundary**: Define what triggers and what does NOT trigger
101
101
  8. **Runtime contract**: Required runtimes (bun/node/python), timeout_seconds, output_format (json)
@@ -104,7 +104,7 @@ Determine:
104
104
 
105
105
  ### Phase 3: Authoring
106
106
 
107
- 1. **Scaffold**: `scripts/scaffold-skill.mjs <name>` → creates directory + SKILL.md skeleton
107
+ 1. **Scaffold**: `scripts/scaffold-skill.ts <name>` → creates directory + SKILL.md skeleton
108
108
  2. **Frontmatter**: name, description (imperative, specific, "Use when... Do NOT use when..."), positive_triggers (min 3), anti_triggers (min 2), allowed-tools, compatibility, runtime
109
109
  3. **SKILL.md body sections** (in order):
110
110
  - Activation Boundary: explicit trigger/exclusion lists
@@ -114,7 +114,7 @@ Determine:
114
114
  - Contrast: `| Before (old) | After (new) | Why different |` table when proposal carries `Contrast:` hint (e.g., `C# null → Rust Option`); keep distinct from routing
115
115
  - Anti-examples: `Do NOT: <before>` → `Do: <after>` with Why, when proposal carries `Anti-example:` hint from report's Concrete Gotcha; body content, NOT frontmatter `anti_triggers`
116
116
  - Tiered depth: Level 1 basics inline, Level 2 advanced behind `references/<topic>.md` (cap one file per skill)
117
- 4. **Scripts**: Generate if clearly reusable (.mjs, self-contained, relative paths via import.meta.url, JSON output only)
117
+ 4. **Scripts**: Generate if clearly reusable (.ts, self-contained, relative paths via import.meta.url, JSON output only)
118
118
  5. **References**: Domain-specific docs, loaded on-demand — **Tiered depth:** Level 1 basics inline in SKILL.md, Level 2 advanced behind `references/<topic>.md`; cap at one `references/` file per skill; link explicitly from SKILL.md
119
119
  6. **Templates**: Output shapes, examples
120
120
  7. **Single source**: Define each rule ONCE, reference everywhere else
@@ -126,7 +126,7 @@ Determine:
126
126
 
127
127
  **Step 1: Structural validation**
128
128
  ```bash
129
- scripts/validate-structure.mjs <skill-dir>
129
+ scripts/validate-structure.ts <skill-dir>
130
130
  ```
131
131
  Checks: name format, description format, directory structure, file references, positive_triggers (min 3), anti_triggers (min 2), "Use when" phrasing, "Do NOT use when" phrasing, no compound intent, no hardcoded paths, runtime declared when scripts exist.
132
132
 
@@ -134,7 +134,7 @@ Checks: name format, description format, directory structure, file references, p
134
134
 
135
135
  **Step 2: Semantic routing validation**
136
136
  ```bash
137
- scripts/validate-routing.mjs <skill-dir>
137
+ scripts/validate-routing.ts <skill-dir>
138
138
  ```
139
139
  Checks: positive_triggers coverage, anti_triggers coverage, description-body alignment, single-responsibility verification.
140
140
 
@@ -149,7 +149,7 @@ Agent assesses:
149
149
 
150
150
  **Step 4: Antipattern self-audit**
151
151
  ```bash
152
- scripts/audit-antipatterns.mjs <skill-dir>
152
+ scripts/audit-antipatterns.ts <skill-dir>
153
153
  ```
154
154
  Checks: phantom tools, duplicated invariants, passive-voice triggers, prose bloat, single-file omnibus, vague success bars, multi-domain descriptions (A17), missing activation boundary (A18), hardcoded paths (A19), context budget violation (A20).
155
155
 
@@ -161,14 +161,14 @@ Self-correct any issues before proceeding.
161
161
 
162
162
  **Step 6: Compute benchmarks**
163
163
  ```bash
164
- scripts/compute-benchmark.mjs <eval-dir>
164
+ scripts/compute-benchmark.ts <eval-dir>
165
165
  ```
166
166
 
167
167
  **Step 6b: Cold-agent behavioral proof (mandatory)**
168
168
  ```bash
169
- scripts/run-cold-eval.mjs <skill-dir>
169
+ scripts/run-cold-eval.ts <skill-dir>
170
170
  ```
171
- Runs `evals/evals.json` cold A/B (without vs with skill), computes `d = sign(with - baseline)`, `m = |with - baseline|`, emits unified envelope `{target, pass, checks, summary}` + `behavioral: {at, baseline, with_skill, d, m, ship}` (30s timeout, JSON only). Writes `evals/benchmark.json` with `stage: behavioral` block (`{at, baseline, with_skill, d, m, ship}`) replacing `pending_cold_agent_run`; record outputs in creation session. Reuses `compute-benchmark.mjs` logic; no network, deterministic.
171
+ Runs `evals/evals.json` cold A/B (without vs with skill), computes `d = sign(with - baseline)`, `m = |with - baseline|`, emits unified envelope `{target, pass, checks, summary}` + `behavioral: {at, baseline, with_skill, d, m, ship}` (30s timeout, JSON only). Writes `evals/benchmark.json` with `stage: behavioral` block (`{at, baseline, with_skill, d, m, ship}`) replacing `pending_cold_agent_run`; record outputs in creation session. Reuses `compute-benchmark.ts` logic; no network, deterministic.
172
172
 
173
173
  **Step 7: Calculate quality score**
174
174
  ```
@@ -176,7 +176,7 @@ d = direction (+1 if with_skill > baseline, -1 if lower, 0 if equal)
176
176
  m = magnitude = |with_skill_pass_rate - baseline_pass_rate|
177
177
  quality_score = d × m
178
178
  ```
179
- Ship gate: d must be +1 AND m must be >= 0.2 (20% improvement over baseline) — now proven by `run-cold-eval.mjs` behavioral block.
179
+ Ship gate: d must be +1 AND m must be >= 0.2 (20% improvement over baseline) — now proven by `run-cold-eval.ts` behavioral block.
180
180
 
181
181
  **Step 8: Iterate**
182
182
  If quality insufficient:
@@ -208,12 +208,12 @@ If false positives occur:
208
208
  3. Re-test
209
209
 
210
210
  **Step 5: Final validation**
211
- Run `scripts/validate-structure.mjs` and `scripts/validate-routing.mjs` again after changes.
211
+ Run `scripts/validate-structure.ts` and `scripts/validate-routing.ts` again after changes.
212
212
 
213
213
  ### Phase 7: Ship
214
214
 
215
- 1. **Final structural validation — HARD GATE**: run `scripts/validate-structure.mjs` and `scripts/validate-routing.mjs`; both MUST report pass with outputs recorded. If either fails, the skill is NOT presented for approval — self-correct and re-run until both pass.
216
- 2. **Behavioral proof — HARD GATE (fail-closed)**: run `scripts/run-cold-eval.mjs <skill-dir>`; `d == +1 AND m >= 0.2` required with outputs recorded. If fails, emit `FAIL: m < 0.2 — not worth context cost` with validator + behavioral outputs, loop to Optimization (revise description/instructions) and re-run; never present for approval without behavioral pass.
215
+ 1. **Final structural validation — HARD GATE**: run `scripts/validate-structure.ts` and `scripts/validate-routing.ts`; both MUST report pass with outputs recorded. If either fails, the skill is NOT presented for approval — self-correct and re-run until both pass.
216
+ 2. **Behavioral proof — HARD GATE (fail-closed)**: run `scripts/run-cold-eval.ts <skill-dir>`; `d == +1 AND m >= 0.2` required with outputs recorded. If fails, emit `FAIL: m < 0.2 — not worth context cost` with validator + behavioral outputs, loop to Optimization (revise description/instructions) and re-run; never present for approval without behavioral pass.
217
217
  3. **Portability certificate**: verify no hardcoded paths, runtime deps declared, timeout bounds set, output contract defined
218
218
  4. **Present summary**: what skill does, tier achieved, eval results, trigger rate, quality score (d × m) + behavioral `d×m`
219
219
  5. **Wait for user approval**
@@ -257,7 +257,7 @@ runtime:
257
257
  - **Anti-triggers +31.8% precision**: Frontmatter `anti_triggers` min 2, plus body `Anti-examples` distinct from routing.
258
258
  - **Progressive disclosure**: Tier 1 <50, Tier 2 <1500, Tier 3 on-demand — see `references/component-decomposition.md`.
259
259
  - **Single-responsibility**: One sentence without `and`, else split.
260
- - **Validation + behavioral gate is fail-closed**: `validate-structure` + `validate-routing` + `run-cold-eval.mjs` (`d=+1,m≥0.2`) mandatory; `m<0.2` blocks Ship.
260
+ - **Validation + behavioral gate is fail-closed**: `validate-structure` + `validate-routing` + `run-cold-eval.ts` (`d=+1,m≥0.2`) mandatory; `m<0.2` blocks Ship.
261
261
  - **Fragility**: Mutation strict, read-only loose, creative low — see `references/fragility-matching.md`.
262
262
  - **No hardcoded paths**: Relative via `import.meta.url`; no `.pi`/`.agents` in scripts.
263
263
 
@@ -269,7 +269,7 @@ runtime:
269
269
  /skill-create csv-analyzer
270
270
  # 1. Discovery: Q "analyze CSV" → positive_triggers 3, anti_triggers 2
271
271
  # 2. Design: scope atomic, fragility read-only=loose (see fragility-matching.md)
272
- # 3. Scaffold: scripts/scaffold-skill.mjs csv-analyzer
272
+ # 3. Scaffold: scripts/scaffold-skill.ts csv-analyzer
273
273
  # 4. Author SKILL.md with Contrast/Anti-examples, Tiered depth
274
274
  # 5. Validate routing+structure + run-cold-eval (d×m≥0.2)
275
275
  # 6. Ship when both gates pass
@@ -114,5 +114,5 @@ Why: {{anti_why}}
114
114
 
115
115
  ## Author Self-Check (final step before declaring this skill complete)
116
116
 
117
- Run `scripts/validate-structure.mjs <this-skill-dir>` and `scripts/validate-routing.mjs <this-skill-dir>`.
117
+ Run `scripts/validate-structure.ts <this-skill-dir>` and `scripts/validate-routing.ts <this-skill-dir>`.
118
118
  Both MUST report pass with outputs recorded in the creation record. Failing either = skill not complete.