@aiwg/cli 2026.8.28 → 2026.9.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.
@@ -1022,12 +1022,13 @@ async function countBundleDeployedArtifacts(bundlePath, target, provider) {
1022
1022
  }
1023
1023
  const SKILL_SUPPORT_REFERENCE = /(?:^|[\s`('"\[])((?:templates|references|scripts|assets)\/[A-Za-z0-9._@/+\-]+)(?=$|[\s`)'"\],:;])/gm;
1024
1024
  /**
1025
- * Project skill-relative support files may live beside the skill or at the
1026
- * bundle root (plugin payloads commonly share report templates). Materialize
1025
+ * Skill-relative support files may live beside the skill or at the bundle root
1026
+ * (plugin payloads commonly share report templates). Materialize
1027
1027
  * only paths explicitly named by SKILL.md, and fail closed on missing or
1028
1028
  * unsafe sources so a deployed instruction can never point at absent assets.
1029
1029
  */
1030
- async function reconcileProjectLocalSkillAssets(bundlePath, target, provider) {
1030
+ async function reconcileDeployedSkillAssets(bundlePath, target, provider, options = {}) {
1031
+ const strictReferences = options.strictReferences ?? true;
1031
1032
  const skillsRoot = path.join(bundlePath, 'skills');
1032
1033
  let skillDirs;
1033
1034
  try {
@@ -1054,7 +1055,13 @@ async function reconcileProjectLocalSkillAssets(bundlePath, target, provider) {
1054
1055
  catch {
1055
1056
  continue;
1056
1057
  }
1057
- const references = [...new Set([...content.matchAll(SKILL_SUPPORT_REFERENCE)].map(match => match[1]))];
1058
+ const frontmatter = content.match(/^---\r?\n([\s\S]*?)\r?\n---/)?.[1] ?? '';
1059
+ const declaredEntrypoint = frontmatter
1060
+ .match(/^[ \t]+entrypoint:\s*["']?([^"'\s]+)["']?\s*$/m)?.[1];
1061
+ const declaredEntrypoints = new Set(declaredEntrypoint ? [declaredEntrypoint] : []);
1062
+ const references = [...new Set([
1063
+ ...content.matchAll(SKILL_SUPPORT_REFERENCE),
1064
+ ].map(match => match[1]).concat([...declaredEntrypoints]))];
1058
1065
  for (const relative of references) {
1059
1066
  const normalized = path.posix.normalize(relative);
1060
1067
  if (normalized !== relative || normalized.startsWith('../') || path.isAbsolute(normalized)) {
@@ -1072,8 +1079,12 @@ async function reconcileProjectLocalSkillAssets(bundlePath, target, provider) {
1072
1079
  }
1073
1080
  catch { /* try bundle-root fallback */ }
1074
1081
  }
1075
- if (!source)
1076
- throw new Error(`missing skill support asset '${relative}' referenced by ${sourceSkillMd}`);
1082
+ if (!source) {
1083
+ if (strictReferences || declaredEntrypoints.has(relative)) {
1084
+ throw new Error(`missing skill support asset '${relative}' referenced by ${sourceSkillMd}`);
1085
+ }
1086
+ continue;
1087
+ }
1077
1088
  let deployedSkillRoot;
1078
1089
  for (const root of deployRoots) {
1079
1090
  // The deployer may select the bulk or kernel tier; use the tier that
@@ -1162,7 +1173,7 @@ async function deployOneProjectLocalBundle(opts) {
1162
1173
  exitCode = result.exitCode;
1163
1174
  if (exitCode === 0 && !dryRun) {
1164
1175
  try {
1165
- await reconcileProjectLocalSkillAssets(bundle.artifactPath, target, provider);
1176
+ await reconcileDeployedSkillAssets(bundle.artifactPath, target, provider);
1166
1177
  }
1167
1178
  catch (error) {
1168
1179
  ui.warn(`Project-local skill asset deployment failed for '${bundle.id}': ${error.message}`);
@@ -2733,6 +2744,17 @@ export class UseHandler {
2733
2744
  || `Failed to deploy required addon '${dependency}'`,
2734
2745
  };
2735
2746
  }
2747
+ if (!dryRunAddon) {
2748
+ try {
2749
+ await reconcileDeployedSkillAssets(dependencySource, target, provider, { strictReferences: false });
2750
+ }
2751
+ catch (error) {
2752
+ return {
2753
+ exitCode: 1,
2754
+ message: `Required addon '${dependency}' skill asset deployment failed: ${error instanceof Error ? error.message : String(error)}`,
2755
+ };
2756
+ }
2757
+ }
2736
2758
  try {
2737
2759
  await registerSourceCliCommands({
2738
2760
  source: dependencySource,
@@ -2764,6 +2786,17 @@ export class UseHandler {
2764
2786
  if (addonResult.exitCode !== 0) {
2765
2787
  return addonResult;
2766
2788
  }
2789
+ if (!dryRunAddon) {
2790
+ try {
2791
+ await reconcileDeployedSkillAssets(addonSource, target, provider, { strictReferences: false });
2792
+ }
2793
+ catch (error) {
2794
+ return {
2795
+ exitCode: 1,
2796
+ message: `${kind} '${framework}' skill asset deployment failed: ${error instanceof Error ? error.message : String(error)}`,
2797
+ };
2798
+ }
2799
+ }
2767
2800
  // Register only artifacts actually written by a confirmed deployment.
2768
2801
  if (!dryRunAddon) {
2769
2802
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiwg/cli",
3
- "version": "2026.8.28",
3
+ "version": "2026.9.0",
4
4
  "description": "Lightweight AIWG CLI for signed, versioned web-backed resources.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -68,6 +68,7 @@
68
68
  "@fortemi/core": "2026.7.15",
69
69
  "@modelcontextprotocol/sdk": "^1.30.0",
70
70
  "ajv": "^8.20.0",
71
+ "ajv-formats": "^3.0.1",
71
72
  "chalk": "^4.1.2",
72
73
  "chokidar": "^4.0.3",
73
74
  "commander": "^12.1.0",