@dzhechkov/harness-core 0.3.34 → 0.3.36

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.
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Emit minimal, self-contained skill bundles for a generic external consumer
3
+ * (e.g. a LangGraph app that loads skills via its own `load_skill`).
4
+ *
5
+ * A bundle is the portable agentskills.io skill directory — `SKILL.md`
6
+ * (YAML frontmatter + instructions, verbatim) plus `references/`, `scripts/`,
7
+ * and `assets/` — with the dz-internal QA artifacts (`schemas/`, `evals/`,
8
+ * `sources.json`) stripped. No `manifest.json` is written (the consumer builds
9
+ * its own file-manifest on load); the skill describes instructions + resources,
10
+ * not graph nodes.
11
+ *
12
+ * @packageDocumentation
13
+ */
14
+ /** Options for {@link bundleSkills}. */
15
+ export interface BundleOptions {
16
+ /** Skill ids to bundle. */
17
+ readonly ids: readonly string[];
18
+ /** Directories to resolve the ids from (first match wins). */
19
+ readonly skillsDirs: readonly string[];
20
+ /** Root to write bundles under — each lands at `<outRoot>/skills/<id>/`. */
21
+ readonly outRoot: string;
22
+ /** Overwrite existing files. */
23
+ readonly force?: boolean;
24
+ }
25
+ /** Per-skill outcome of {@link bundleSkills}. */
26
+ export interface BundledSkill {
27
+ readonly id: string;
28
+ readonly written: number;
29
+ readonly skipped: number;
30
+ readonly warnings: readonly string[];
31
+ }
32
+ /** Outcome of {@link bundleSkills}. */
33
+ export interface BundleResult {
34
+ readonly bundled: BundledSkill[];
35
+ /** Ids not found in any `skillsDirs`. */
36
+ readonly missing: string[];
37
+ }
38
+ /**
39
+ * Resolve each id from `skillsDirs`, emit it as a minimal bundle under
40
+ * `<outRoot>/skills/<id>/`, and write it to disk. Idempotent (skips existing
41
+ * files unless `force`). Returns what was written + any unresolved ids.
42
+ */
43
+ export declare function bundleSkills(opts: BundleOptions): BundleResult;
44
+ //# sourceMappingURL=bundle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA6CH,wCAAwC;AACxC,MAAM,WAAW,aAAa;IAC5B,2BAA2B;IAC3B,QAAQ,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,gCAAgC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED,uCAAuC;AACvC,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC;IACjC,yCAAyC;IACzC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,YAAY,CA6B9D"}
package/dist/bundle.js ADDED
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Emit minimal, self-contained skill bundles for a generic external consumer
3
+ * (e.g. a LangGraph app that loads skills via its own `load_skill`).
4
+ *
5
+ * A bundle is the portable agentskills.io skill directory — `SKILL.md`
6
+ * (YAML frontmatter + instructions, verbatim) plus `references/`, `scripts/`,
7
+ * and `assets/` — with the dz-internal QA artifacts (`schemas/`, `evals/`,
8
+ * `sources.json`) stripped. No `manifest.json` is written (the consumer builds
9
+ * its own file-manifest on load); the skill describes instructions + resources,
10
+ * not graph nodes.
11
+ *
12
+ * @packageDocumentation
13
+ */
14
+ import { emitSkillTree } from '@dzhechkov/core';
15
+ import { applyEmitResult } from './apply.js';
16
+ import { loadSkillFromDir } from './skills.js';
17
+ /** Files excluded from a bundle — dz-internal, not part of a portable skill. */
18
+ function isInternalArtifact(path) {
19
+ return /(^|\/)(schemas|evals)\//.test(path) || path.endsWith('/sources.json') || path === 'sources.json';
20
+ }
21
+ /**
22
+ * Detect Claude-Code host coupling the consumer must adapt (advisory) — including
23
+ * **cross-skill references** (a composite that loads sibling skills by path). Those
24
+ * sibling skills are separate bundles; if they aren't bundled too, the skill won't
25
+ * work standalone in a generic runtime, so they're surfaced loudly.
26
+ */
27
+ function hostCouplingWarnings(id, skillMd, bundledIds) {
28
+ const w = [];
29
+ // Cross-skill references: `.claude/skills/<sub>/...` or `/mnt/skills/{user,public}/<sub>/...`.
30
+ // These are the load-bearing dependency for composites (e.g. analyst-manual-full → explore,
31
+ // goap-research-ed25519, problem-solver-enhanced). Only warn about sub-skills NOT already in
32
+ // this bundle set — if they're all bundled, the set is self-contained.
33
+ const subs = new Set();
34
+ for (const m of skillMd.matchAll(/(?:\.claude\/skills|\/mnt\/skills\/(?:user|public))\/([a-z0-9][a-z0-9-]*)/g)) {
35
+ if (m[1] !== undefined && m[1] !== id)
36
+ subs.add(m[1]);
37
+ }
38
+ const missing = [...subs].filter((s) => !bundledIds.has(s)).sort();
39
+ if (missing.length > 0) {
40
+ w.push(`${id}: depends on sub-skill(s) ${missing.join(', ')} NOT in this bundle — add them ` +
41
+ `(--select …,${missing.join(',')}) or this skill won't load them standalone`);
42
+ }
43
+ if (/\/mnt\/skills\//.test(skillMd)) {
44
+ w.push(`${id}: references absolute /mnt/skills/... paths — rewrite to bundle-relative paths (e.g. just the skill id) for your runtime`);
45
+ }
46
+ if (/\bview\(\)/.test(skillMd)) {
47
+ w.push(`${id}: uses view() (Claude-Code file-read) — inline the reference or expose a file-read tool`);
48
+ }
49
+ return w;
50
+ }
51
+ /**
52
+ * Resolve each id from `skillsDirs`, emit it as a minimal bundle under
53
+ * `<outRoot>/skills/<id>/`, and write it to disk. Idempotent (skips existing
54
+ * files unless `force`). Returns what was written + any unresolved ids.
55
+ */
56
+ export function bundleSkills(opts) {
57
+ const found = new Set();
58
+ const bundledIds = new Set(opts.ids);
59
+ const bundled = [];
60
+ for (const id of opts.ids) {
61
+ if (found.has(id))
62
+ continue;
63
+ for (const dir of opts.skillsDirs) {
64
+ let skill;
65
+ try {
66
+ skill = loadSkillFromDir(dir, id);
67
+ }
68
+ catch {
69
+ continue; // not in this dir — try the next
70
+ }
71
+ found.add(id);
72
+ const emit = emitSkillTree(skill, { skillsRoot: 'skills' });
73
+ const files = emit.files.filter((f) => !isInternalArtifact(f.path));
74
+ const skillMd = files.find((f) => f.path.endsWith('/SKILL.md'))?.content;
75
+ const warnings = [
76
+ ...emit.warnings,
77
+ ...(typeof skillMd === 'string' ? hostCouplingWarnings(id, skillMd, bundledIds) : []),
78
+ ];
79
+ const applied = applyEmitResult({ files, warnings: [] }, { targetRoot: opts.outRoot, force: opts.force === true });
80
+ bundled.push({ id, written: applied.written.length, skipped: applied.skipped.length, warnings });
81
+ break;
82
+ }
83
+ }
84
+ return { bundled, missing: [...opts.ids].filter((id) => !found.has(id)) };
85
+ }
86
+ //# sourceMappingURL=bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.js","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -7,6 +7,8 @@
7
7
  export declare const HARNESS_CORE_VERSION: string;
8
8
  export * from './skills.js';
9
9
  export * from './apply.js';
10
+ export { bundleSkills } from './bundle.js';
11
+ export type { BundleOptions, BundleResult, BundledSkill } from './bundle.js';
10
12
  export * from './targets.js';
11
13
  export * from './operations.js';
12
14
  export * from './workflows.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ import { createRequire } from 'node:module';
8
8
  export const HARNESS_CORE_VERSION = createRequire(import.meta.url)('../package.json').version;
9
9
  export * from './skills.js';
10
10
  export * from './apply.js';
11
+ export { bundleSkills } from './bundle.js';
11
12
  export * from './targets.js';
12
13
  export * from './operations.js';
13
14
  export * from './workflows.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,mFAAmF;AACnF,MAAM,CAAC,MAAM,oBAAoB,GAC9B,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAyB,CAAC,OAAO,CAAC;AAErF,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,gBAAgB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAElH,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,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,qBAAqB,EAAE,eAAe,EAAE,eAAe,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE5N,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAK7C,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,SAAS,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACnH,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAGhE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EACL,YAAY,EACZ,UAAU,EACV,cAAc,EACd,SAAS,EACT,cAAc,EACd,cAAc,EACd,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAS3B,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,mBAAmB,EACnB,cAAc,EACd,QAAQ,GACT,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,mFAAmF;AACnF,MAAM,CAAC,MAAM,oBAAoB,GAC9B,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAyB,CAAC,OAAO,CAAC;AAErF,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,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,gBAAgB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAElH,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,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,qBAAqB,EAAE,eAAe,EAAE,eAAe,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE5N,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAK7C,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,SAAS,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACnH,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAGhE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EACL,YAAY,EACZ,UAAU,EACV,cAAc,EACd,SAAS,EACT,cAAc,EACd,cAAc,EACd,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAS3B,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,mBAAmB,EACnB,cAAc,EACd,QAAQ,GACT,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dzhechkov/harness-core",
3
- "version": "0.3.34",
3
+ "version": "0.3.36",
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",
@@ -30,9 +30,9 @@
30
30
  "@dzhechkov/adapter-openclaude": "^0.1.0",
31
31
  "@dzhechkov/adapter-opencode": "^0.2.0",
32
32
  "yaml": "^2.0.0",
33
- "@dzhechkov/memory": "0.2.5",
33
+ "@dzhechkov/adapter-copilot": "0.1.1",
34
34
  "@dzhechkov/core": "0.2.4",
35
- "@dzhechkov/adapter-copilot": "0.1.1"
35
+ "@dzhechkov/memory": "0.2.5"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/node": "^25.6.0",
package/src/bundle.ts ADDED
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Emit minimal, self-contained skill bundles for a generic external consumer
3
+ * (e.g. a LangGraph app that loads skills via its own `load_skill`).
4
+ *
5
+ * A bundle is the portable agentskills.io skill directory — `SKILL.md`
6
+ * (YAML frontmatter + instructions, verbatim) plus `references/`, `scripts/`,
7
+ * and `assets/` — with the dz-internal QA artifacts (`schemas/`, `evals/`,
8
+ * `sources.json`) stripped. No `manifest.json` is written (the consumer builds
9
+ * its own file-manifest on load); the skill describes instructions + resources,
10
+ * not graph nodes.
11
+ *
12
+ * @packageDocumentation
13
+ */
14
+
15
+ import { emitSkillTree } from '@dzhechkov/core';
16
+ import { applyEmitResult } from './apply.js';
17
+ import { loadSkillFromDir } from './skills.js';
18
+
19
+ /** Files excluded from a bundle — dz-internal, not part of a portable skill. */
20
+ function isInternalArtifact(path: string): boolean {
21
+ return /(^|\/)(schemas|evals)\//.test(path) || path.endsWith('/sources.json') || path === 'sources.json';
22
+ }
23
+
24
+ /**
25
+ * Detect Claude-Code host coupling the consumer must adapt (advisory) — including
26
+ * **cross-skill references** (a composite that loads sibling skills by path). Those
27
+ * sibling skills are separate bundles; if they aren't bundled too, the skill won't
28
+ * work standalone in a generic runtime, so they're surfaced loudly.
29
+ */
30
+ function hostCouplingWarnings(id: string, skillMd: string, bundledIds: ReadonlySet<string>): string[] {
31
+ const w: string[] = [];
32
+
33
+ // Cross-skill references: `.claude/skills/<sub>/...` or `/mnt/skills/{user,public}/<sub>/...`.
34
+ // These are the load-bearing dependency for composites (e.g. analyst-manual-full → explore,
35
+ // goap-research-ed25519, problem-solver-enhanced). Only warn about sub-skills NOT already in
36
+ // this bundle set — if they're all bundled, the set is self-contained.
37
+ const subs = new Set<string>();
38
+ for (const m of skillMd.matchAll(/(?:\.claude\/skills|\/mnt\/skills\/(?:user|public))\/([a-z0-9][a-z0-9-]*)/g)) {
39
+ if (m[1] !== undefined && m[1] !== id) subs.add(m[1]);
40
+ }
41
+ const missing = [...subs].filter((s) => !bundledIds.has(s)).sort();
42
+ if (missing.length > 0) {
43
+ w.push(
44
+ `${id}: depends on sub-skill(s) ${missing.join(', ')} NOT in this bundle — add them ` +
45
+ `(--select …,${missing.join(',')}) or this skill won't load them standalone`,
46
+ );
47
+ }
48
+
49
+ if (/\/mnt\/skills\//.test(skillMd)) {
50
+ w.push(`${id}: references absolute /mnt/skills/... paths — rewrite to bundle-relative paths (e.g. just the skill id) for your runtime`);
51
+ }
52
+ if (/\bview\(\)/.test(skillMd)) {
53
+ w.push(`${id}: uses view() (Claude-Code file-read) — inline the reference or expose a file-read tool`);
54
+ }
55
+ return w;
56
+ }
57
+
58
+ /** Options for {@link bundleSkills}. */
59
+ export interface BundleOptions {
60
+ /** Skill ids to bundle. */
61
+ readonly ids: readonly string[];
62
+ /** Directories to resolve the ids from (first match wins). */
63
+ readonly skillsDirs: readonly string[];
64
+ /** Root to write bundles under — each lands at `<outRoot>/skills/<id>/`. */
65
+ readonly outRoot: string;
66
+ /** Overwrite existing files. */
67
+ readonly force?: boolean;
68
+ }
69
+
70
+ /** Per-skill outcome of {@link bundleSkills}. */
71
+ export interface BundledSkill {
72
+ readonly id: string;
73
+ readonly written: number;
74
+ readonly skipped: number;
75
+ readonly warnings: readonly string[];
76
+ }
77
+
78
+ /** Outcome of {@link bundleSkills}. */
79
+ export interface BundleResult {
80
+ readonly bundled: BundledSkill[];
81
+ /** Ids not found in any `skillsDirs`. */
82
+ readonly missing: string[];
83
+ }
84
+
85
+ /**
86
+ * Resolve each id from `skillsDirs`, emit it as a minimal bundle under
87
+ * `<outRoot>/skills/<id>/`, and write it to disk. Idempotent (skips existing
88
+ * files unless `force`). Returns what was written + any unresolved ids.
89
+ */
90
+ export function bundleSkills(opts: BundleOptions): BundleResult {
91
+ const found = new Set<string>();
92
+ const bundledIds = new Set(opts.ids);
93
+ const bundled: BundledSkill[] = [];
94
+
95
+ for (const id of opts.ids) {
96
+ if (found.has(id)) continue;
97
+ for (const dir of opts.skillsDirs) {
98
+ let skill;
99
+ try {
100
+ skill = loadSkillFromDir(dir, id);
101
+ } catch {
102
+ continue; // not in this dir — try the next
103
+ }
104
+ found.add(id);
105
+ const emit = emitSkillTree(skill, { skillsRoot: 'skills' });
106
+ const files = emit.files.filter((f) => !isInternalArtifact(f.path));
107
+ const skillMd = files.find((f) => f.path.endsWith('/SKILL.md'))?.content;
108
+ const warnings = [
109
+ ...emit.warnings,
110
+ ...(typeof skillMd === 'string' ? hostCouplingWarnings(id, skillMd, bundledIds) : []),
111
+ ];
112
+ const applied = applyEmitResult({ files, warnings: [] }, { targetRoot: opts.outRoot, force: opts.force === true });
113
+ bundled.push({ id, written: applied.written.length, skipped: applied.skipped.length, warnings });
114
+ break;
115
+ }
116
+ }
117
+
118
+ return { bundled, missing: [...opts.ids].filter((id) => !found.has(id)) };
119
+ }
package/src/index.ts CHANGED
@@ -12,6 +12,8 @@ export const HARNESS_CORE_VERSION: string =
12
12
 
13
13
  export * from './skills.js';
14
14
  export * from './apply.js';
15
+ export { bundleSkills } from './bundle.js';
16
+ export type { BundleOptions, BundleResult, BundledSkill } from './bundle.js';
15
17
  export * from './targets.js';
16
18
  export * from './operations.js';
17
19
  export * from './workflows.js';