@dzhechkov/harness-core 0.3.4 → 0.3.6
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/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/publish.d.ts +35 -0
- package/dist/publish.d.ts.map +1 -0
- package/dist/publish.js +87 -0
- package/dist/publish.js.map +1 -0
- package/dist/registry.d.ts +33 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +84 -0
- package/dist/registry.js.map +1 -0
- package/package.json +5 -5
- package/src/index.ts +4 -0
- package/src/publish.ts +121 -0
- package/src/registry.ts +109 -0
package/dist/index.d.ts
CHANGED
|
@@ -15,5 +15,9 @@ export type { CreateSkillOptions, CreateSkillResult } from './create-skill.js';
|
|
|
15
15
|
export { checkUpstream, loadSourcesManifest } from './sync-upstream.js';
|
|
16
16
|
export type { SyncUpstreamReport, UpstreamCheckResult, SourcesManifest } from './sync-upstream.js';
|
|
17
17
|
export { benchmarkSkill, benchmarkSkills, compareSkills } from './benchmark.js';
|
|
18
|
+
export { buildRegistry, searchRegistry, filterByCategory } from './registry.js';
|
|
19
|
+
export { discoverPackages, publishPackages } from './publish.js';
|
|
20
|
+
export type { PublishResult, PublishReport } from './publish.js';
|
|
21
|
+
export type { RegistryEntry, Registry } from './registry.js';
|
|
18
22
|
export type { BenchmarkCheck, BenchmarkScore, BenchmarkReport, CompareResult } from './benchmark.js';
|
|
19
23
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,yDAAyD;AACzD,eAAO,MAAM,oBAAoB,UAAU,CAAC;AAE5C,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACxE,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACnG,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAChF,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,yDAAyD;AACzD,eAAO,MAAM,oBAAoB,UAAU,CAAC;AAE5C,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACxE,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACnG,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACjE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC7D,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -13,4 +13,6 @@ export * from './workflows.js';
|
|
|
13
13
|
export { createSkill } from './create-skill.js';
|
|
14
14
|
export { checkUpstream, loadSourcesManifest } from './sync-upstream.js';
|
|
15
15
|
export { benchmarkSkill, benchmarkSkills, compareSkills } from './benchmark.js';
|
|
16
|
+
export { buildRegistry, searchRegistry, filterByCategory } from './registry.js';
|
|
17
|
+
export { discoverPackages, publishPackages } from './publish.js';
|
|
16
18
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,yDAAyD;AACzD,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC;AAE5C,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAExE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,yDAAyD;AACzD,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC;AAE5C,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAExE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Automated publish — discovers changed packages, bumps patch versions,
|
|
3
|
+
* builds, and publishes to npm.
|
|
4
|
+
*
|
|
5
|
+
* @packageDocumentation
|
|
6
|
+
*/
|
|
7
|
+
/** Result for a single package publish attempt. */
|
|
8
|
+
export interface PublishResult {
|
|
9
|
+
readonly name: string;
|
|
10
|
+
readonly oldVersion: string;
|
|
11
|
+
readonly newVersion: string;
|
|
12
|
+
readonly status: 'published' | 'skipped' | 'error';
|
|
13
|
+
readonly error?: string | undefined;
|
|
14
|
+
}
|
|
15
|
+
/** Full publish report. */
|
|
16
|
+
export interface PublishReport {
|
|
17
|
+
readonly packages: readonly PublishResult[];
|
|
18
|
+
readonly published: number;
|
|
19
|
+
readonly skipped: number;
|
|
20
|
+
readonly errors: number;
|
|
21
|
+
readonly dryRun: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** Discover all publishable @dzhechkov packages. */
|
|
24
|
+
export declare function discoverPackages(monorepoRoot: string): {
|
|
25
|
+
name: string;
|
|
26
|
+
dir: string;
|
|
27
|
+
version: string;
|
|
28
|
+
}[];
|
|
29
|
+
/** Publish packages that have changes since last publish. */
|
|
30
|
+
export declare function publishPackages(monorepoRoot: string, opts?: {
|
|
31
|
+
dryRun?: boolean | undefined;
|
|
32
|
+
filter?: string[] | undefined;
|
|
33
|
+
bumpOnly?: boolean | undefined;
|
|
34
|
+
}): PublishReport;
|
|
35
|
+
//# sourceMappingURL=publish.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../src/publish.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,mDAAmD;AACnD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;IACnD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AAED,2BAA2B;AAC3B,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AASD,oDAAoD;AACpD,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,CAavG;AAED,6DAA6D;AAC7D,wBAAgB,eAAe,CAC7B,YAAY,EAAE,MAAM,EACpB,IAAI,GAAE;IACJ,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC9B,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC3B,GACL,aAAa,CA4Df"}
|
package/dist/publish.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Automated publish — discovers changed packages, bumps patch versions,
|
|
3
|
+
* builds, and publishes to npm.
|
|
4
|
+
*
|
|
5
|
+
* @packageDocumentation
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, readFileSync, writeFileSync, readdirSync } from 'node:fs';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
import { execSync } from 'node:child_process';
|
|
10
|
+
/** Bump patch version: 0.3.11 → 0.3.12 */
|
|
11
|
+
function bumpPatch(version) {
|
|
12
|
+
const parts = version.split('.');
|
|
13
|
+
const patch = parseInt(parts[2] ?? '0', 10);
|
|
14
|
+
return `${parts[0]}.${parts[1]}.${patch + 1}`;
|
|
15
|
+
}
|
|
16
|
+
/** Discover all publishable @dzhechkov packages. */
|
|
17
|
+
export function discoverPackages(monorepoRoot) {
|
|
18
|
+
const baseDir = join(monorepoRoot, 'packages', '@dzhechkov');
|
|
19
|
+
if (!existsSync(baseDir))
|
|
20
|
+
return [];
|
|
21
|
+
return readdirSync(baseDir, { withFileTypes: true })
|
|
22
|
+
.filter((e) => e.isDirectory())
|
|
23
|
+
.map((e) => {
|
|
24
|
+
const pkgPath = join(baseDir, e.name, 'package.json');
|
|
25
|
+
if (!existsSync(pkgPath))
|
|
26
|
+
return undefined;
|
|
27
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
28
|
+
return { name: pkg.name, dir: join(baseDir, e.name), version: pkg.version };
|
|
29
|
+
})
|
|
30
|
+
.filter((p) => p !== undefined);
|
|
31
|
+
}
|
|
32
|
+
/** Publish packages that have changes since last publish. */
|
|
33
|
+
export function publishPackages(monorepoRoot, opts = {}) {
|
|
34
|
+
const packages = discoverPackages(monorepoRoot);
|
|
35
|
+
const results = [];
|
|
36
|
+
const filtered = opts.filter && opts.filter.length > 0
|
|
37
|
+
? packages.filter((p) => opts.filter.some((f) => p.name.includes(f) || p.dir.includes(f)))
|
|
38
|
+
: packages;
|
|
39
|
+
for (const pkg of filtered) {
|
|
40
|
+
const oldVersion = pkg.version;
|
|
41
|
+
const newVersion = bumpPatch(oldVersion);
|
|
42
|
+
if (opts.dryRun) {
|
|
43
|
+
results.push({ name: pkg.name, oldVersion, newVersion, status: 'skipped' });
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
// Bump version in package.json
|
|
48
|
+
const pkgJsonPath = join(pkg.dir, 'package.json');
|
|
49
|
+
const pkgJson = readFileSync(pkgJsonPath, 'utf-8');
|
|
50
|
+
writeFileSync(pkgJsonPath, pkgJson.replace(`"version": "${oldVersion}"`, `"version": "${newVersion}"`));
|
|
51
|
+
if (opts.bumpOnly) {
|
|
52
|
+
results.push({ name: pkg.name, oldVersion, newVersion, status: 'published' });
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
// Build if has build script
|
|
56
|
+
const parsed = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
|
|
57
|
+
if (parsed.scripts?.['build']) {
|
|
58
|
+
execSync('pnpm build', { cwd: pkg.dir, stdio: 'pipe', encoding: 'utf-8' });
|
|
59
|
+
}
|
|
60
|
+
// Publish
|
|
61
|
+
execSync('pnpm publish --access public --no-git-checks', {
|
|
62
|
+
cwd: pkg.dir,
|
|
63
|
+
stdio: 'pipe',
|
|
64
|
+
encoding: 'utf-8',
|
|
65
|
+
env: { ...process.env },
|
|
66
|
+
});
|
|
67
|
+
results.push({ name: pkg.name, oldVersion, newVersion, status: 'published' });
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
results.push({
|
|
71
|
+
name: pkg.name,
|
|
72
|
+
oldVersion,
|
|
73
|
+
newVersion,
|
|
74
|
+
status: 'error',
|
|
75
|
+
error: err instanceof Error ? err.message : String(err),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
packages: results,
|
|
81
|
+
published: results.filter((r) => r.status === 'published').length,
|
|
82
|
+
skipped: results.filter((r) => r.status === 'skipped').length,
|
|
83
|
+
errors: results.filter((r) => r.status === 'error').length,
|
|
84
|
+
dryRun: opts.dryRun === true,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=publish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../src/publish.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill registry — indexes all skills across skill packs for search and discovery.
|
|
3
|
+
*
|
|
4
|
+
* Scans `packages/@dzhechkov/skills-*` directories, reads SKILL.md frontmatter,
|
|
5
|
+
* and builds a searchable index.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
/** A single skill in the registry. */
|
|
10
|
+
export interface RegistryEntry {
|
|
11
|
+
readonly id: string;
|
|
12
|
+
readonly pack: string;
|
|
13
|
+
readonly description: string;
|
|
14
|
+
readonly trustTier: number;
|
|
15
|
+
readonly hasSchema: boolean;
|
|
16
|
+
readonly hasEvals: boolean;
|
|
17
|
+
readonly lineCount: number;
|
|
18
|
+
readonly category: string;
|
|
19
|
+
}
|
|
20
|
+
/** The full registry. */
|
|
21
|
+
export interface Registry {
|
|
22
|
+
readonly entries: readonly RegistryEntry[];
|
|
23
|
+
readonly totalSkills: number;
|
|
24
|
+
readonly totalPacks: number;
|
|
25
|
+
readonly categories: readonly string[];
|
|
26
|
+
}
|
|
27
|
+
/** Build registry from all skills-* packages. */
|
|
28
|
+
export declare function buildRegistry(monorepoRoot: string): Registry;
|
|
29
|
+
/** Search registry by query (matches id and description, case-insensitive). */
|
|
30
|
+
export declare function searchRegistry(registry: Registry, query: string): readonly RegistryEntry[];
|
|
31
|
+
/** Filter registry by category. */
|
|
32
|
+
export declare function filterByCategory(registry: Registry, category: string): readonly RegistryEntry[];
|
|
33
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,sCAAsC;AACtC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,yBAAyB;AACzB,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;IAC3C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAwBD,iDAAiD;AACjD,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,QAAQ,CAwC5D;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,aAAa,EAAE,CAK1F;AAED,mCAAmC;AACnC,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,aAAa,EAAE,CAE/F"}
|
package/dist/registry.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill registry — indexes all skills across skill packs for search and discovery.
|
|
3
|
+
*
|
|
4
|
+
* Scans `packages/@dzhechkov/skills-*` directories, reads SKILL.md frontmatter,
|
|
5
|
+
* and builds a searchable index.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
/** Extract description from SKILL.md frontmatter. */
|
|
12
|
+
function extractFrontmatter(content) {
|
|
13
|
+
const descMatch = /^description:\s*"?(.+?)"?\s*$/m.exec(content);
|
|
14
|
+
const tierMatch = /^trust_tier:\s*(\d)/m.exec(content);
|
|
15
|
+
return {
|
|
16
|
+
description: descMatch?.[1] ?? '',
|
|
17
|
+
trustTier: tierMatch ? parseInt(tierMatch[1] ?? '1', 10) : 1,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/** Infer category from pack name. */
|
|
21
|
+
function categoryFromPack(pack) {
|
|
22
|
+
if (pack.includes('devops'))
|
|
23
|
+
return 'devops';
|
|
24
|
+
if (pack.includes('web3'))
|
|
25
|
+
return 'web3';
|
|
26
|
+
if (pack.includes('mcp'))
|
|
27
|
+
return 'mcp';
|
|
28
|
+
if (pack.includes('qe'))
|
|
29
|
+
return 'qe';
|
|
30
|
+
if (pack.includes('meta'))
|
|
31
|
+
return 'meta';
|
|
32
|
+
if (pack.includes('bto'))
|
|
33
|
+
return 'bto';
|
|
34
|
+
if (pack.includes('health'))
|
|
35
|
+
return 'health';
|
|
36
|
+
return 'other';
|
|
37
|
+
}
|
|
38
|
+
/** Build registry from all skills-* packages. */
|
|
39
|
+
export function buildRegistry(monorepoRoot) {
|
|
40
|
+
const baseDir = join(monorepoRoot, 'packages', '@dzhechkov');
|
|
41
|
+
if (!existsSync(baseDir))
|
|
42
|
+
return { entries: [], totalSkills: 0, totalPacks: 0, categories: [] };
|
|
43
|
+
const entries = [];
|
|
44
|
+
const packs = readdirSync(baseDir, { withFileTypes: true })
|
|
45
|
+
.filter((e) => e.isDirectory() && e.name.startsWith('skills-'));
|
|
46
|
+
for (const pack of packs) {
|
|
47
|
+
const packDir = join(baseDir, pack.name);
|
|
48
|
+
const skillDirs = readdirSync(packDir, { withFileTypes: true })
|
|
49
|
+
.filter((e) => e.isDirectory() && existsSync(join(packDir, e.name, 'SKILL.md')));
|
|
50
|
+
for (const skill of skillDirs) {
|
|
51
|
+
const skillMdPath = join(packDir, skill.name, 'SKILL.md');
|
|
52
|
+
const content = readFileSync(skillMdPath, 'utf-8');
|
|
53
|
+
const { description, trustTier } = extractFrontmatter(content);
|
|
54
|
+
entries.push({
|
|
55
|
+
id: skill.name,
|
|
56
|
+
pack: pack.name,
|
|
57
|
+
description,
|
|
58
|
+
trustTier,
|
|
59
|
+
hasSchema: existsSync(join(packDir, skill.name, 'schemas', 'output.json')),
|
|
60
|
+
hasEvals: existsSync(join(packDir, skill.name, 'evals')),
|
|
61
|
+
lineCount: content.split('\n').length,
|
|
62
|
+
category: categoryFromPack(pack.name),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
entries.sort((a, b) => a.id.localeCompare(b.id));
|
|
67
|
+
const categories = [...new Set(entries.map((e) => e.category))].sort();
|
|
68
|
+
return {
|
|
69
|
+
entries,
|
|
70
|
+
totalSkills: entries.length,
|
|
71
|
+
totalPacks: packs.length,
|
|
72
|
+
categories,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/** Search registry by query (matches id and description, case-insensitive). */
|
|
76
|
+
export function searchRegistry(registry, query) {
|
|
77
|
+
const q = query.toLowerCase();
|
|
78
|
+
return registry.entries.filter((e) => e.id.toLowerCase().includes(q) || e.description.toLowerCase().includes(q) || e.category.includes(q));
|
|
79
|
+
}
|
|
80
|
+
/** Filter registry by category. */
|
|
81
|
+
export function filterByCategory(registry, category) {
|
|
82
|
+
return registry.entries.filter((e) => e.category === category);
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dzhechkov/harness-core",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"description": "Shared harness logic - skill loading, additive apply, and the init/sync/verify/doctor operations.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,12 +25,12 @@
|
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"yaml": "^2.0.0",
|
|
28
|
-
"@dzhechkov/adapter-hermes": "0.2.0",
|
|
29
|
-
"@dzhechkov/adapter-opencode": "0.2.0",
|
|
30
28
|
"@dzhechkov/adapter-claude": "0.2.0",
|
|
29
|
+
"@dzhechkov/adapter-hermes": "0.2.0",
|
|
31
30
|
"@dzhechkov/core": "0.2.0",
|
|
32
|
-
"@dzhechkov/adapter-
|
|
33
|
-
"@dzhechkov/adapter-openclaude": "0.1.0"
|
|
31
|
+
"@dzhechkov/adapter-opencode": "0.2.0",
|
|
32
|
+
"@dzhechkov/adapter-openclaude": "0.1.0",
|
|
33
|
+
"@dzhechkov/adapter-codex": "0.2.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^25.6.0",
|
package/src/index.ts
CHANGED
|
@@ -17,4 +17,8 @@ export type { CreateSkillOptions, CreateSkillResult } from './create-skill.js';
|
|
|
17
17
|
export { checkUpstream, loadSourcesManifest } from './sync-upstream.js';
|
|
18
18
|
export type { SyncUpstreamReport, UpstreamCheckResult, SourcesManifest } from './sync-upstream.js';
|
|
19
19
|
export { benchmarkSkill, benchmarkSkills, compareSkills } from './benchmark.js';
|
|
20
|
+
export { buildRegistry, searchRegistry, filterByCategory } from './registry.js';
|
|
21
|
+
export { discoverPackages, publishPackages } from './publish.js';
|
|
22
|
+
export type { PublishResult, PublishReport } from './publish.js';
|
|
23
|
+
export type { RegistryEntry, Registry } from './registry.js';
|
|
20
24
|
export type { BenchmarkCheck, BenchmarkScore, BenchmarkReport, CompareResult } from './benchmark.js';
|
package/src/publish.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Automated publish — discovers changed packages, bumps patch versions,
|
|
3
|
+
* builds, and publishes to npm.
|
|
4
|
+
*
|
|
5
|
+
* @packageDocumentation
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { existsSync, readFileSync, writeFileSync, readdirSync } from 'node:fs';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { execSync } from 'node:child_process';
|
|
11
|
+
|
|
12
|
+
/** Result for a single package publish attempt. */
|
|
13
|
+
export interface PublishResult {
|
|
14
|
+
readonly name: string;
|
|
15
|
+
readonly oldVersion: string;
|
|
16
|
+
readonly newVersion: string;
|
|
17
|
+
readonly status: 'published' | 'skipped' | 'error';
|
|
18
|
+
readonly error?: string | undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Full publish report. */
|
|
22
|
+
export interface PublishReport {
|
|
23
|
+
readonly packages: readonly PublishResult[];
|
|
24
|
+
readonly published: number;
|
|
25
|
+
readonly skipped: number;
|
|
26
|
+
readonly errors: number;
|
|
27
|
+
readonly dryRun: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Bump patch version: 0.3.11 → 0.3.12 */
|
|
31
|
+
function bumpPatch(version: string): string {
|
|
32
|
+
const parts = version.split('.');
|
|
33
|
+
const patch = parseInt(parts[2] ?? '0', 10);
|
|
34
|
+
return `${parts[0]}.${parts[1]}.${patch + 1}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Discover all publishable @dzhechkov packages. */
|
|
38
|
+
export function discoverPackages(monorepoRoot: string): { name: string; dir: string; version: string }[] {
|
|
39
|
+
const baseDir = join(monorepoRoot, 'packages', '@dzhechkov');
|
|
40
|
+
if (!existsSync(baseDir)) return [];
|
|
41
|
+
|
|
42
|
+
return readdirSync(baseDir, { withFileTypes: true })
|
|
43
|
+
.filter((e) => e.isDirectory())
|
|
44
|
+
.map((e) => {
|
|
45
|
+
const pkgPath = join(baseDir, e.name, 'package.json');
|
|
46
|
+
if (!existsSync(pkgPath)) return undefined;
|
|
47
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as { name: string; version: string };
|
|
48
|
+
return { name: pkg.name, dir: join(baseDir, e.name), version: pkg.version };
|
|
49
|
+
})
|
|
50
|
+
.filter((p): p is { name: string; dir: string; version: string } => p !== undefined);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Publish packages that have changes since last publish. */
|
|
54
|
+
export function publishPackages(
|
|
55
|
+
monorepoRoot: string,
|
|
56
|
+
opts: {
|
|
57
|
+
dryRun?: boolean | undefined;
|
|
58
|
+
filter?: string[] | undefined;
|
|
59
|
+
bumpOnly?: boolean | undefined;
|
|
60
|
+
} = {},
|
|
61
|
+
): PublishReport {
|
|
62
|
+
const packages = discoverPackages(monorepoRoot);
|
|
63
|
+
const results: PublishResult[] = [];
|
|
64
|
+
const filtered = opts.filter && opts.filter.length > 0
|
|
65
|
+
? packages.filter((p) => opts.filter!.some((f) => p.name.includes(f) || p.dir.includes(f)))
|
|
66
|
+
: packages;
|
|
67
|
+
|
|
68
|
+
for (const pkg of filtered) {
|
|
69
|
+
const oldVersion = pkg.version;
|
|
70
|
+
const newVersion = bumpPatch(oldVersion);
|
|
71
|
+
|
|
72
|
+
if (opts.dryRun) {
|
|
73
|
+
results.push({ name: pkg.name, oldVersion, newVersion, status: 'skipped' });
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
// Bump version in package.json
|
|
79
|
+
const pkgJsonPath = join(pkg.dir, 'package.json');
|
|
80
|
+
const pkgJson = readFileSync(pkgJsonPath, 'utf-8');
|
|
81
|
+
writeFileSync(pkgJsonPath, pkgJson.replace(`"version": "${oldVersion}"`, `"version": "${newVersion}"`));
|
|
82
|
+
|
|
83
|
+
if (opts.bumpOnly) {
|
|
84
|
+
results.push({ name: pkg.name, oldVersion, newVersion, status: 'published' });
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Build if has build script
|
|
89
|
+
const parsed = JSON.parse(readFileSync(pkgJsonPath, 'utf-8')) as { scripts?: Record<string, string> };
|
|
90
|
+
if (parsed.scripts?.['build']) {
|
|
91
|
+
execSync('pnpm build', { cwd: pkg.dir, stdio: 'pipe', encoding: 'utf-8' });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Publish
|
|
95
|
+
execSync('pnpm publish --access public --no-git-checks', {
|
|
96
|
+
cwd: pkg.dir,
|
|
97
|
+
stdio: 'pipe',
|
|
98
|
+
encoding: 'utf-8',
|
|
99
|
+
env: { ...process.env },
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
results.push({ name: pkg.name, oldVersion, newVersion, status: 'published' });
|
|
103
|
+
} catch (err) {
|
|
104
|
+
results.push({
|
|
105
|
+
name: pkg.name,
|
|
106
|
+
oldVersion,
|
|
107
|
+
newVersion,
|
|
108
|
+
status: 'error',
|
|
109
|
+
error: err instanceof Error ? err.message : String(err),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
packages: results,
|
|
116
|
+
published: results.filter((r) => r.status === 'published').length,
|
|
117
|
+
skipped: results.filter((r) => r.status === 'skipped').length,
|
|
118
|
+
errors: results.filter((r) => r.status === 'error').length,
|
|
119
|
+
dryRun: opts.dryRun === true,
|
|
120
|
+
};
|
|
121
|
+
}
|
package/src/registry.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill registry — indexes all skills across skill packs for search and discovery.
|
|
3
|
+
*
|
|
4
|
+
* Scans `packages/@dzhechkov/skills-*` directories, reads SKILL.md frontmatter,
|
|
5
|
+
* and builds a searchable index.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
|
|
13
|
+
/** A single skill in the registry. */
|
|
14
|
+
export interface RegistryEntry {
|
|
15
|
+
readonly id: string;
|
|
16
|
+
readonly pack: string;
|
|
17
|
+
readonly description: string;
|
|
18
|
+
readonly trustTier: number;
|
|
19
|
+
readonly hasSchema: boolean;
|
|
20
|
+
readonly hasEvals: boolean;
|
|
21
|
+
readonly lineCount: number;
|
|
22
|
+
readonly category: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** The full registry. */
|
|
26
|
+
export interface Registry {
|
|
27
|
+
readonly entries: readonly RegistryEntry[];
|
|
28
|
+
readonly totalSkills: number;
|
|
29
|
+
readonly totalPacks: number;
|
|
30
|
+
readonly categories: readonly string[];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Extract description from SKILL.md frontmatter. */
|
|
34
|
+
function extractFrontmatter(content: string): { description: string; trustTier: number } {
|
|
35
|
+
const descMatch = /^description:\s*"?(.+?)"?\s*$/m.exec(content);
|
|
36
|
+
const tierMatch = /^trust_tier:\s*(\d)/m.exec(content);
|
|
37
|
+
return {
|
|
38
|
+
description: descMatch?.[1] ?? '',
|
|
39
|
+
trustTier: tierMatch ? parseInt(tierMatch[1] ?? '1', 10) : 1,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Infer category from pack name. */
|
|
44
|
+
function categoryFromPack(pack: string): string {
|
|
45
|
+
if (pack.includes('devops')) return 'devops';
|
|
46
|
+
if (pack.includes('web3')) return 'web3';
|
|
47
|
+
if (pack.includes('mcp')) return 'mcp';
|
|
48
|
+
if (pack.includes('qe')) return 'qe';
|
|
49
|
+
if (pack.includes('meta')) return 'meta';
|
|
50
|
+
if (pack.includes('bto')) return 'bto';
|
|
51
|
+
if (pack.includes('health')) return 'health';
|
|
52
|
+
return 'other';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Build registry from all skills-* packages. */
|
|
56
|
+
export function buildRegistry(monorepoRoot: string): Registry {
|
|
57
|
+
const baseDir = join(monorepoRoot, 'packages', '@dzhechkov');
|
|
58
|
+
if (!existsSync(baseDir)) return { entries: [], totalSkills: 0, totalPacks: 0, categories: [] };
|
|
59
|
+
|
|
60
|
+
const entries: RegistryEntry[] = [];
|
|
61
|
+
const packs = readdirSync(baseDir, { withFileTypes: true })
|
|
62
|
+
.filter((e) => e.isDirectory() && e.name.startsWith('skills-'));
|
|
63
|
+
|
|
64
|
+
for (const pack of packs) {
|
|
65
|
+
const packDir = join(baseDir, pack.name);
|
|
66
|
+
const skillDirs = readdirSync(packDir, { withFileTypes: true })
|
|
67
|
+
.filter((e) => e.isDirectory() && existsSync(join(packDir, e.name, 'SKILL.md')));
|
|
68
|
+
|
|
69
|
+
for (const skill of skillDirs) {
|
|
70
|
+
const skillMdPath = join(packDir, skill.name, 'SKILL.md');
|
|
71
|
+
const content = readFileSync(skillMdPath, 'utf-8');
|
|
72
|
+
const { description, trustTier } = extractFrontmatter(content);
|
|
73
|
+
|
|
74
|
+
entries.push({
|
|
75
|
+
id: skill.name,
|
|
76
|
+
pack: pack.name,
|
|
77
|
+
description,
|
|
78
|
+
trustTier,
|
|
79
|
+
hasSchema: existsSync(join(packDir, skill.name, 'schemas', 'output.json')),
|
|
80
|
+
hasEvals: existsSync(join(packDir, skill.name, 'evals')),
|
|
81
|
+
lineCount: content.split('\n').length,
|
|
82
|
+
category: categoryFromPack(pack.name),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
entries.sort((a, b) => a.id.localeCompare(b.id));
|
|
88
|
+
const categories = [...new Set(entries.map((e) => e.category))].sort();
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
entries,
|
|
92
|
+
totalSkills: entries.length,
|
|
93
|
+
totalPacks: packs.length,
|
|
94
|
+
categories,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Search registry by query (matches id and description, case-insensitive). */
|
|
99
|
+
export function searchRegistry(registry: Registry, query: string): readonly RegistryEntry[] {
|
|
100
|
+
const q = query.toLowerCase();
|
|
101
|
+
return registry.entries.filter(
|
|
102
|
+
(e) => e.id.toLowerCase().includes(q) || e.description.toLowerCase().includes(q) || e.category.includes(q),
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Filter registry by category. */
|
|
107
|
+
export function filterByCategory(registry: Registry, category: string): readonly RegistryEntry[] {
|
|
108
|
+
return registry.entries.filter((e) => e.category === category);
|
|
109
|
+
}
|