@dzhechkov/harness-core 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/dist/apply.d.ts +31 -0
- package/dist/apply.d.ts.map +1 -0
- package/dist/apply.js +36 -0
- package/dist/apply.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/operations.d.ts +126 -0
- package/dist/operations.d.ts.map +1 -0
- package/dist/operations.js +247 -0
- package/dist/operations.js.map +1 -0
- package/dist/skills.d.ts +36 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +87 -0
- package/dist/skills.js.map +1 -0
- package/dist/targets.d.ts +23 -0
- package/dist/targets.d.ts.map +1 -0
- package/dist/targets.js +26 -0
- package/dist/targets.js.map +1 -0
- package/dist/workflows.d.ts +28 -0
- package/dist/workflows.d.ts.map +1 -0
- package/dist/workflows.js +103 -0
- package/dist/workflows.js.map +1 -0
- package/package.json +58 -0
- package/src/apply.ts +57 -0
- package/src/index.ts +14 -0
- package/src/operations.ts +388 -0
- package/src/security/boundaries.json +55 -0
- package/src/skills.ts +109 -0
- package/src/targets.ts +33 -0
- package/src/workflows.ts +123 -0
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# @dzhechkov/harness-core
|
|
2
|
+
|
|
3
|
+
Shared logic for the DZ harness — the engine behind `@dzhechkov/harness-cli`
|
|
4
|
+
and any other consumer.
|
|
5
|
+
|
|
6
|
+
## What it provides
|
|
7
|
+
|
|
8
|
+
| Module | Exports | Purpose |
|
|
9
|
+
|---|---|---|
|
|
10
|
+
| `skills` | `loadSkillFromDir`, `listSkills`, `discoverSkillIds` | Read skill directories into `CanonicalSkill` objects |
|
|
11
|
+
| `apply` | `applyEmitResult` | Write an adapter `EmitResult` to disk — **additively** |
|
|
12
|
+
| `targets` | `TARGETS`, `TargetName`, `isTargetName` | `--target` name → platform adapter |
|
|
13
|
+
| `operations` | `runInit`, `runSync`, `runVerify`, `runDoctor` | The harness operations, returning structured reports |
|
|
14
|
+
|
|
15
|
+
## The additive guarantee
|
|
16
|
+
|
|
17
|
+
`applyEmitResult` is the only part of the harness that writes to disk. It is
|
|
18
|
+
**additive** (ADR-001): it creates new files and directories, it never deletes,
|
|
19
|
+
and it never overwrites an existing file unless `force: true` is passed
|
|
20
|
+
explicitly. Operations that would overwrite are reported as `skipped`.
|
|
21
|
+
|
|
22
|
+
## Status
|
|
23
|
+
|
|
24
|
+
`0.1.0` — alpha, part of the `extended-a-migration` feature (Phase 6).
|
package/dist/apply.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The additive disk writer — the only part of the harness that writes files.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
import type { EmitResult } from '@dzhechkov/core';
|
|
7
|
+
/** Options for {@link applyEmitResult}. */
|
|
8
|
+
export interface ApplyOptions {
|
|
9
|
+
/** Root directory the emit's relative paths are written under. */
|
|
10
|
+
readonly targetRoot: string;
|
|
11
|
+
/** Overwrite files that already exist. Default `false` — purely additive. */
|
|
12
|
+
readonly force?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/** The outcome of {@link applyEmitResult}. */
|
|
15
|
+
export interface ApplyReport {
|
|
16
|
+
/** Files written (created, or overwritten under `force`). */
|
|
17
|
+
readonly written: string[];
|
|
18
|
+
/** Files left untouched because they already existed and `force` was off. */
|
|
19
|
+
readonly skipped: string[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Write an adapter {@link EmitResult} to disk under `targetRoot`.
|
|
23
|
+
*
|
|
24
|
+
* **Additive (ADR-001):** creates files and parent directories, never deletes,
|
|
25
|
+
* and never overwrites an existing file unless `force` is `true`. A file that
|
|
26
|
+
* already exists (without `force`) is reported in `skipped`, not `written`.
|
|
27
|
+
*
|
|
28
|
+
* @throws if an emit path is absolute or contains a `..` segment.
|
|
29
|
+
*/
|
|
30
|
+
export declare function applyEmitResult(emit: EmitResult, options: ApplyOptions): ApplyReport;
|
|
31
|
+
//# sourceMappingURL=apply.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../src/apply.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,2CAA2C;AAC3C,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,8CAA8C;AAC9C,MAAM,WAAW,WAAW;IAC1B,6DAA6D;IAC7D,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,GAAG,WAAW,CAoBpF"}
|
package/dist/apply.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The additive disk writer — the only part of the harness that writes files.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
7
|
+
import { dirname, join } from 'node:path';
|
|
8
|
+
/**
|
|
9
|
+
* Write an adapter {@link EmitResult} to disk under `targetRoot`.
|
|
10
|
+
*
|
|
11
|
+
* **Additive (ADR-001):** creates files and parent directories, never deletes,
|
|
12
|
+
* and never overwrites an existing file unless `force` is `true`. A file that
|
|
13
|
+
* already exists (without `force`) is reported in `skipped`, not `written`.
|
|
14
|
+
*
|
|
15
|
+
* @throws if an emit path is absolute or contains a `..` segment.
|
|
16
|
+
*/
|
|
17
|
+
export function applyEmitResult(emit, options) {
|
|
18
|
+
const written = [];
|
|
19
|
+
const skipped = [];
|
|
20
|
+
for (const file of emit.files) {
|
|
21
|
+
if (file.path.startsWith('/') || file.path.split('/').includes('..')) {
|
|
22
|
+
throw new Error(`apply: refusing unsafe emit path ${JSON.stringify(file.path)}`);
|
|
23
|
+
}
|
|
24
|
+
const absolutePath = join(options.targetRoot, file.path);
|
|
25
|
+
if (existsSync(absolutePath) && options.force !== true) {
|
|
26
|
+
skipped.push(file.path);
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
mkdirSync(dirname(absolutePath), { recursive: true });
|
|
30
|
+
const data = file.encoding === 'base64' ? Buffer.from(file.content, 'base64') : file.content;
|
|
31
|
+
writeFileSync(absolutePath, data);
|
|
32
|
+
written.push(file.path);
|
|
33
|
+
}
|
|
34
|
+
return { written, skipped };
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=apply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../src/apply.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAoB1C;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,IAAgB,EAAE,OAAqB;IACrE,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACrE,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnF,CAAC;QACD,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,UAAU,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YACvD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxB,SAAS;QACX,CAAC;QACD,SAAS,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;QAC7F,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;QAClC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@dzhechkov/harness-core` — shared harness logic behind `@dzhechkov/harness-cli`.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
/** Package version. Kept in sync with `package.json`. */
|
|
7
|
+
export declare const HARNESS_CORE_VERSION = "0.1.0";
|
|
8
|
+
export * from './skills.js';
|
|
9
|
+
export * from './apply.js';
|
|
10
|
+
export * from './targets.js';
|
|
11
|
+
export * from './operations.js';
|
|
12
|
+
export * from './workflows.js';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@dzhechkov/harness-core` — shared harness logic behind `@dzhechkov/harness-cli`.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
/** Package version. Kept in sync with `package.json`. */
|
|
7
|
+
export const HARNESS_CORE_VERSION = '0.1.0';
|
|
8
|
+
export * from './skills.js';
|
|
9
|
+
export * from './apply.js';
|
|
10
|
+
export * from './targets.js';
|
|
11
|
+
export * from './operations.js';
|
|
12
|
+
export * from './workflows.js';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The harness operations — `init`, `sync`, `verify`, `doctor` — as pure-ish
|
|
3
|
+
* functions returning structured reports. `@dzhechkov/harness-cli` is a thin
|
|
4
|
+
* argv shell over these.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
import type { TargetName } from './targets.js';
|
|
9
|
+
/** Options for {@link runInit}. */
|
|
10
|
+
export interface InitOptions {
|
|
11
|
+
readonly target: TargetName;
|
|
12
|
+
/** Source directory of canonical skills. */
|
|
13
|
+
readonly skillsDir: string;
|
|
14
|
+
/** Project root the platform tree is written under. */
|
|
15
|
+
readonly projectRoot: string;
|
|
16
|
+
/** Overwrite existing files. Default `false` — additive. */
|
|
17
|
+
readonly force?: boolean;
|
|
18
|
+
/** When set, install only these skill ids (a preset selection). */
|
|
19
|
+
readonly select?: readonly string[];
|
|
20
|
+
}
|
|
21
|
+
/** Per-skill outcome of {@link runInit}. */
|
|
22
|
+
export interface InitSkillResult {
|
|
23
|
+
readonly id: string;
|
|
24
|
+
readonly written: string[];
|
|
25
|
+
readonly skipped: string[];
|
|
26
|
+
readonly warnings: string[];
|
|
27
|
+
}
|
|
28
|
+
/** The outcome of {@link runInit}. */
|
|
29
|
+
export interface InitReport {
|
|
30
|
+
readonly target: TargetName;
|
|
31
|
+
readonly skillsDir: string;
|
|
32
|
+
readonly projectRoot: string;
|
|
33
|
+
readonly skills: InitSkillResult[];
|
|
34
|
+
}
|
|
35
|
+
/** Compile every skill in `skillsDir` for `target` and apply it under `projectRoot`. */
|
|
36
|
+
export declare function runInit(options: InitOptions): Promise<InitReport>;
|
|
37
|
+
/** Options for {@link runVerify}. */
|
|
38
|
+
export interface VerifyOptions {
|
|
39
|
+
readonly skillsDir: string;
|
|
40
|
+
/** Target to verify against. Default `claude-code`. */
|
|
41
|
+
readonly target?: TargetName;
|
|
42
|
+
}
|
|
43
|
+
/** Per-skill outcome of {@link runVerify}. */
|
|
44
|
+
export interface VerifySkillResult {
|
|
45
|
+
readonly id: string;
|
|
46
|
+
readonly ok: boolean;
|
|
47
|
+
readonly errors: string[];
|
|
48
|
+
readonly warnings: string[];
|
|
49
|
+
}
|
|
50
|
+
/** The outcome of {@link runVerify}. */
|
|
51
|
+
export interface VerifyReport {
|
|
52
|
+
readonly target: TargetName;
|
|
53
|
+
readonly skillsDir: string;
|
|
54
|
+
readonly total: number;
|
|
55
|
+
readonly valid: number;
|
|
56
|
+
readonly skills: VerifySkillResult[];
|
|
57
|
+
}
|
|
58
|
+
/** Compile every skill for `target` and report whether each verifies. */
|
|
59
|
+
export declare function runVerify(options: VerifyOptions): Promise<VerifyReport>;
|
|
60
|
+
/** Options for {@link runSync}. */
|
|
61
|
+
export interface SyncOptions {
|
|
62
|
+
/** Canonical skill pack directory (single source). */
|
|
63
|
+
readonly canonicalDir?: string;
|
|
64
|
+
/** Multiple canonical pack directories (multi-source). Takes precedence over canonicalDir. */
|
|
65
|
+
readonly canonicalDirs?: readonly string[];
|
|
66
|
+
/** Project root containing the legacy `.claude/skills` tree. */
|
|
67
|
+
readonly projectRoot: string;
|
|
68
|
+
/** Report only, write nothing. */
|
|
69
|
+
readonly dryRun?: boolean;
|
|
70
|
+
/** Overwrite drifted legacy files. Default `false`. */
|
|
71
|
+
readonly force?: boolean;
|
|
72
|
+
}
|
|
73
|
+
/** Per-skill outcome of {@link runSync}. */
|
|
74
|
+
export interface SyncSkillResult {
|
|
75
|
+
readonly id: string;
|
|
76
|
+
readonly status: 'in-sync' | 'missing' | 'drift';
|
|
77
|
+
readonly written: string[];
|
|
78
|
+
}
|
|
79
|
+
/** The outcome of {@link runSync}. */
|
|
80
|
+
export interface SyncReport {
|
|
81
|
+
readonly dryRun: boolean;
|
|
82
|
+
readonly skills: SyncSkillResult[];
|
|
83
|
+
readonly summary: {
|
|
84
|
+
total: number;
|
|
85
|
+
inSync: number;
|
|
86
|
+
missing: number;
|
|
87
|
+
drift: number;
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/** Compare each canonical skill (compiled for Claude Code) to the legacy tree. */
|
|
91
|
+
export declare function runSync(options: SyncOptions): Promise<SyncReport>;
|
|
92
|
+
/** A detected legacy CLI installation. */
|
|
93
|
+
export interface MigrateDetection {
|
|
94
|
+
readonly manifest: string;
|
|
95
|
+
readonly version: string;
|
|
96
|
+
readonly components: string[];
|
|
97
|
+
readonly fileCount: number;
|
|
98
|
+
}
|
|
99
|
+
/** The outcome of {@link runMigrate}. */
|
|
100
|
+
export interface MigrateReport {
|
|
101
|
+
readonly projectRoot: string;
|
|
102
|
+
readonly detections: MigrateDetection[];
|
|
103
|
+
readonly skillsFound: number;
|
|
104
|
+
readonly recommendation: string;
|
|
105
|
+
}
|
|
106
|
+
/** Detect keysarium/bto/etc installations and report migration path. */
|
|
107
|
+
export declare function runMigrate(options: {
|
|
108
|
+
projectRoot: string;
|
|
109
|
+
}): MigrateReport;
|
|
110
|
+
/** A single {@link runDoctor} check. */
|
|
111
|
+
export interface DoctorCheck {
|
|
112
|
+
readonly name: string;
|
|
113
|
+
readonly ok: boolean;
|
|
114
|
+
readonly detail: string;
|
|
115
|
+
}
|
|
116
|
+
/** The outcome of {@link runDoctor}. */
|
|
117
|
+
export interface DoctorReport {
|
|
118
|
+
readonly node: string;
|
|
119
|
+
readonly checks: DoctorCheck[];
|
|
120
|
+
readonly ok: boolean;
|
|
121
|
+
}
|
|
122
|
+
/** Report environment diagnostics for the harness. */
|
|
123
|
+
export declare function runDoctor(options: {
|
|
124
|
+
projectRoot: string;
|
|
125
|
+
}): Promise<DoctorReport>;
|
|
126
|
+
//# sourceMappingURL=operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../src/operations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The harness operations — `init`, `sync`, `verify`, `doctor` — as pure-ish
|
|
3
|
+
* functions returning structured reports. `@dzhechkov/harness-cli` is a thin
|
|
4
|
+
* argv shell over these.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { claudeAdapter } from '@dzhechkov/adapter-claude';
|
|
11
|
+
import { applyEmitResult } from './apply.js';
|
|
12
|
+
import { discoverSkillIds, loadSkillFromDir } from './skills.js';
|
|
13
|
+
import { TARGETS } from './targets.js';
|
|
14
|
+
/** Compile every skill in `skillsDir` for `target` and apply it under `projectRoot`. */
|
|
15
|
+
export async function runInit(options) {
|
|
16
|
+
const adapter = TARGETS[options.target];
|
|
17
|
+
const skills = [];
|
|
18
|
+
const selection = options.select;
|
|
19
|
+
const ids = discoverSkillIds(options.skillsDir).filter((id) => selection === undefined || selection.includes(id));
|
|
20
|
+
for (const id of ids) {
|
|
21
|
+
const skill = loadSkillFromDir(options.skillsDir, id);
|
|
22
|
+
const emit = await adapter.compile(skill, { targetRoot: options.projectRoot });
|
|
23
|
+
const applied = applyEmitResult(emit, {
|
|
24
|
+
targetRoot: options.projectRoot,
|
|
25
|
+
force: options.force === true,
|
|
26
|
+
});
|
|
27
|
+
skills.push({ id, written: applied.written, skipped: applied.skipped, warnings: [...emit.warnings] });
|
|
28
|
+
}
|
|
29
|
+
return { target: options.target, skillsDir: options.skillsDir, projectRoot: options.projectRoot, skills };
|
|
30
|
+
}
|
|
31
|
+
/** Compile every skill for `target` and report whether each verifies. */
|
|
32
|
+
export async function runVerify(options) {
|
|
33
|
+
const target = options.target ?? 'claude-code';
|
|
34
|
+
const adapter = TARGETS[target];
|
|
35
|
+
const skills = [];
|
|
36
|
+
for (const id of discoverSkillIds(options.skillsDir)) {
|
|
37
|
+
try {
|
|
38
|
+
const skill = loadSkillFromDir(options.skillsDir, id);
|
|
39
|
+
const emit = await adapter.compile(skill, { targetRoot: '.' });
|
|
40
|
+
const result = await adapter.verify(emit);
|
|
41
|
+
skills.push({ id, ok: result.ok, errors: [...result.errors], warnings: [...result.warnings] });
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
skills.push({
|
|
45
|
+
id,
|
|
46
|
+
ok: false,
|
|
47
|
+
errors: [error instanceof Error ? error.message : String(error)],
|
|
48
|
+
warnings: [],
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
target,
|
|
54
|
+
skillsDir: options.skillsDir,
|
|
55
|
+
total: skills.length,
|
|
56
|
+
valid: skills.filter((skill) => skill.ok).length,
|
|
57
|
+
skills,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** Compare each canonical skill (compiled for Claude Code) to the legacy tree. */
|
|
61
|
+
export async function runSync(options) {
|
|
62
|
+
const dirs = options.canonicalDirs ?? (options.canonicalDir ? [options.canonicalDir] : []);
|
|
63
|
+
const skills = [];
|
|
64
|
+
for (const canonicalDir of dirs) {
|
|
65
|
+
for (const id of discoverSkillIds(canonicalDir)) {
|
|
66
|
+
const skill = loadSkillFromDir(canonicalDir, id);
|
|
67
|
+
const emit = await claudeAdapter.compile(skill, { targetRoot: options.projectRoot });
|
|
68
|
+
let differ = false;
|
|
69
|
+
let missing = false;
|
|
70
|
+
for (const file of emit.files) {
|
|
71
|
+
const absolutePath = join(options.projectRoot, file.path);
|
|
72
|
+
if (!existsSync(absolutePath))
|
|
73
|
+
missing = true;
|
|
74
|
+
else if (readFileSync(absolutePath, 'utf-8') !== file.content)
|
|
75
|
+
differ = true;
|
|
76
|
+
}
|
|
77
|
+
const status = differ ? 'drift' : missing ? 'missing' : 'in-sync';
|
|
78
|
+
let written = [];
|
|
79
|
+
const shouldWrite = status === 'missing' || (status === 'drift' && options.force === true);
|
|
80
|
+
if (options.dryRun !== true && shouldWrite) {
|
|
81
|
+
written = applyEmitResult(emit, {
|
|
82
|
+
targetRoot: options.projectRoot,
|
|
83
|
+
force: status === 'drift',
|
|
84
|
+
}).written;
|
|
85
|
+
}
|
|
86
|
+
skills.push({ id, status, written });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
dryRun: options.dryRun === true,
|
|
91
|
+
skills,
|
|
92
|
+
summary: {
|
|
93
|
+
total: skills.length,
|
|
94
|
+
inSync: skills.filter((skill) => skill.status === 'in-sync').length,
|
|
95
|
+
missing: skills.filter((skill) => skill.status === 'missing').length,
|
|
96
|
+
drift: skills.filter((skill) => skill.status === 'drift').length,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/** Detect keysarium/bto/etc installations and report migration path. */
|
|
101
|
+
export function runMigrate(options) {
|
|
102
|
+
const root = options.projectRoot;
|
|
103
|
+
const detections = [];
|
|
104
|
+
// Check for known manifests
|
|
105
|
+
const manifests = ['.keysarium.json', '.bto.json', '.analyst-manual.json', '.edu-site.json', '.transcript-site.json', '.feature-adr.json'];
|
|
106
|
+
for (const manifest of manifests) {
|
|
107
|
+
const path = join(root, manifest);
|
|
108
|
+
if (existsSync(path)) {
|
|
109
|
+
try {
|
|
110
|
+
const data = JSON.parse(readFileSync(path, 'utf-8'));
|
|
111
|
+
detections.push({
|
|
112
|
+
manifest,
|
|
113
|
+
version: data.version ?? 'unknown',
|
|
114
|
+
components: data.components ?? [],
|
|
115
|
+
fileCount: Array.isArray(data.files) ? data.files.length : 0,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
detections.push({ manifest, version: 'parse-error', components: [], fileCount: 0 });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Count skills in .claude/skills
|
|
124
|
+
const skillsDir = join(root, '.claude', 'skills');
|
|
125
|
+
let skillsFound = 0;
|
|
126
|
+
if (existsSync(skillsDir)) {
|
|
127
|
+
skillsFound = readdirSync(skillsDir, { withFileTypes: true })
|
|
128
|
+
.filter((e) => e.isDirectory() && existsSync(join(skillsDir, e.name, 'SKILL.md')))
|
|
129
|
+
.length;
|
|
130
|
+
}
|
|
131
|
+
let recommendation;
|
|
132
|
+
if (detections.length === 0) {
|
|
133
|
+
recommendation = 'No legacy installations detected. Use `dz init` to install skills.';
|
|
134
|
+
}
|
|
135
|
+
else if (detections.length === 1) {
|
|
136
|
+
const d = detections[0];
|
|
137
|
+
recommendation = `Found ${d.manifest} (v${d.version}, ${d.fileCount} files). Skills are already in .claude/skills/ — use \`dz sync\` to manage them canonically.`;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
recommendation = `Found ${detections.length} legacy manifests. Skills coexist in .claude/skills/. Run \`dz doctor\` to verify health, then \`dz sync\` to adopt canonical management.`;
|
|
141
|
+
}
|
|
142
|
+
return { projectRoot: root, detections, skillsFound, recommendation };
|
|
143
|
+
}
|
|
144
|
+
/** Report environment diagnostics for the harness. */
|
|
145
|
+
export async function runDoctor(options) {
|
|
146
|
+
const checks = [];
|
|
147
|
+
const root = options.projectRoot;
|
|
148
|
+
// 1. Node version
|
|
149
|
+
const nodeMajor = Number(process.versions.node.split('.')[0] ?? '0');
|
|
150
|
+
checks.push({ name: 'node >= 20', ok: nodeMajor >= 20, detail: `node ${process.version}` });
|
|
151
|
+
// 2. Key directories
|
|
152
|
+
for (const dir of ['.claude/skills', 'packages/@dzhechkov/skills-meta']) {
|
|
153
|
+
checks.push({
|
|
154
|
+
name: `${dir} present`,
|
|
155
|
+
ok: existsSync(join(root, dir)),
|
|
156
|
+
detail: dir,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
// 3. Adapter resolvability
|
|
160
|
+
const adapters = ['adapter-claude', 'adapter-codex', 'adapter-hermes', 'adapter-opencode'];
|
|
161
|
+
const foundAdapters = adapters.filter((a) => existsSync(join(root, 'packages/@dzhechkov', a)));
|
|
162
|
+
checks.push({
|
|
163
|
+
name: 'adapters present',
|
|
164
|
+
ok: foundAdapters.length === 4,
|
|
165
|
+
detail: `${foundAdapters.length}/4 adapters found`,
|
|
166
|
+
});
|
|
167
|
+
// 4. Package version consistency
|
|
168
|
+
const pkgsDir = join(root, 'packages/@dzhechkov');
|
|
169
|
+
if (existsSync(pkgsDir)) {
|
|
170
|
+
const versions = new Map();
|
|
171
|
+
let consistent = true;
|
|
172
|
+
let detail = '';
|
|
173
|
+
try {
|
|
174
|
+
const entries = readdirSync(pkgsDir, { withFileTypes: true });
|
|
175
|
+
for (const entry of entries) {
|
|
176
|
+
if (!entry.isDirectory())
|
|
177
|
+
continue;
|
|
178
|
+
const pjPath = join(pkgsDir, entry.name, 'package.json');
|
|
179
|
+
if (!existsSync(pjPath))
|
|
180
|
+
continue;
|
|
181
|
+
const pj = JSON.parse(readFileSync(pjPath, 'utf-8'));
|
|
182
|
+
if (pj.version)
|
|
183
|
+
versions.set(entry.name, pj.version);
|
|
184
|
+
}
|
|
185
|
+
const uniqueVersions = new Set(versions.values());
|
|
186
|
+
detail = `${versions.size} packages, ${uniqueVersions.size} unique version(s)`;
|
|
187
|
+
// Warn if more than 10 unique versions (some variation is expected in a large monorepo)
|
|
188
|
+
if (uniqueVersions.size > 10) {
|
|
189
|
+
consistent = false;
|
|
190
|
+
detail += ' — high version divergence';
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
consistent = false;
|
|
195
|
+
detail = 'failed to read package versions';
|
|
196
|
+
}
|
|
197
|
+
checks.push({ name: 'package versions', ok: consistent, detail });
|
|
198
|
+
}
|
|
199
|
+
// 5. Config lint (.agentic-qe/config.yaml)
|
|
200
|
+
const configPath = join(root, '.agentic-qe', 'config.yaml');
|
|
201
|
+
if (existsSync(configPath)) {
|
|
202
|
+
try {
|
|
203
|
+
const { parse: parseYaml } = await import('yaml');
|
|
204
|
+
const content = readFileSync(configPath, 'utf-8');
|
|
205
|
+
const parsed = parseYaml(content);
|
|
206
|
+
const hasProject = typeof parsed?.project === 'string';
|
|
207
|
+
checks.push({
|
|
208
|
+
name: 'aqe config valid',
|
|
209
|
+
ok: hasProject,
|
|
210
|
+
detail: hasProject ? `project: ${parsed.project}` : 'missing project field',
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
checks.push({
|
|
215
|
+
name: 'aqe config valid',
|
|
216
|
+
ok: false,
|
|
217
|
+
detail: `parse error: ${error instanceof Error ? error.message : String(error)}`,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
checks.push({ name: 'aqe config valid', ok: true, detail: 'no .agentic-qe/config.yaml (optional)' });
|
|
223
|
+
}
|
|
224
|
+
// 6. SQLite memory backend probe
|
|
225
|
+
try {
|
|
226
|
+
const { createRequire } = await import('node:module');
|
|
227
|
+
const req = createRequire(join(root, 'package.json'));
|
|
228
|
+
req.resolve('better-sqlite3');
|
|
229
|
+
checks.push({ name: 'sqlite backend', ok: true, detail: 'better-sqlite3 available' });
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
checks.push({ name: 'sqlite backend', ok: true, detail: 'better-sqlite3 not installed (JSON fallback)' });
|
|
233
|
+
}
|
|
234
|
+
// 7. Skills directory health
|
|
235
|
+
const skillsDir = join(root, '.claude', 'skills');
|
|
236
|
+
if (existsSync(skillsDir)) {
|
|
237
|
+
const skillDirs = readdirSync(skillsDir, { withFileTypes: true }).filter((e) => e.isDirectory());
|
|
238
|
+
const withSkillMd = skillDirs.filter((e) => existsSync(join(skillsDir, e.name, 'SKILL.md')));
|
|
239
|
+
checks.push({
|
|
240
|
+
name: 'skills health',
|
|
241
|
+
ok: withSkillMd.length === skillDirs.length,
|
|
242
|
+
detail: `${withSkillMd.length}/${skillDirs.length} skill dirs have SKILL.md`,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
return { node: process.version, checks, ok: checks.every((check) => check.ok) };
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../src/operations.ts"],"names":[],"mappings":"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"}
|
package/dist/skills.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill discovery + loading — the consolidated filesystem loader.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
import type { CanonicalSkill } from '@dzhechkov/core';
|
|
7
|
+
/** A discovered skill — id plus its description, for listings. */
|
|
8
|
+
export interface SkillSummary {
|
|
9
|
+
readonly id: string;
|
|
10
|
+
readonly description: string;
|
|
11
|
+
}
|
|
12
|
+
/** Detailed skill info. */
|
|
13
|
+
export interface SkillInfo {
|
|
14
|
+
readonly id: string;
|
|
15
|
+
readonly description: string;
|
|
16
|
+
readonly name: string;
|
|
17
|
+
readonly trustTier: number | undefined;
|
|
18
|
+
readonly version: string | number | undefined;
|
|
19
|
+
readonly assetCount: number;
|
|
20
|
+
readonly assetPaths: string[];
|
|
21
|
+
readonly frontmatter: Record<string, unknown>;
|
|
22
|
+
}
|
|
23
|
+
/** Return the ids of every `<skillsDir>/<id>/SKILL.md`, sorted. */
|
|
24
|
+
export declare function discoverSkillIds(skillsDir: string): string[];
|
|
25
|
+
/** Discover every skill in `skillsDir`, returning id + description. */
|
|
26
|
+
export declare function listSkills(skillsDir: string): SkillSummary[];
|
|
27
|
+
/** Get detailed info about a single skill without loading all assets. */
|
|
28
|
+
export declare function getSkillInfo(skillsDir: string, id: string): SkillInfo | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Load one `<skillsDir>/<id>/` directory into a {@link CanonicalSkill}: its
|
|
31
|
+
* `SKILL.md` document plus every other file as a bundled asset.
|
|
32
|
+
*
|
|
33
|
+
* @throws if the skill directory has no `SKILL.md`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function loadSkillFromDir(skillsDir: string, id: string): CanonicalSkill;
|
|
36
|
+
//# sourceMappingURL=skills.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,iBAAiB,CAAC;AAElE,kEAAkE;AAClE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,2BAA2B;AAC3B,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/C;AAaD,mEAAmE;AACnE,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAM5D;AAED,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,EAAE,CAM5D;AAED,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAqBjF;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,cAAc,CAiB9E"}
|