goalbuddy 0.2.17 → 0.2.18

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 CHANGED
@@ -175,7 +175,7 @@ npx goalbuddy extend install --all --dry-run
175
175
  npx goalbuddy extend install --all
176
176
  ```
177
177
 
178
- `goalbuddy extend` shows available extensions plus local install state, activation state, credential requirements, safe-by-default status, and missing environment variables.
178
+ `goalbuddy extend` shows available extensions and detail commands. `goalbuddy extend <id>` shows local install state, activation state, credential requirements, safe-by-default status, and missing environment variables.
179
179
 
180
180
  Current catalog examples include:
181
181
 
@@ -572,17 +572,9 @@ async function extendCatalog() {
572
572
  for (const extension of extensions) {
573
573
  console.log(extension.name || extension.id);
574
574
  if (extension.summary) console.log(` ${extension.summary}`);
575
- console.log(` id: ${extension.id}`);
576
- console.log(` kind: ${extension.kind} | activation: ${extension.activation || "unspecified"}`);
577
- console.log(` state: ${extension.state.installed ? "installed" : "available"} | configured: ${extension.state.configured ? "yes" : "no"}`);
578
- console.log(` safe by default: ${extension.safe_by_default ? "yes" : "no"} | requires approval: ${extension.requires_approval ? "yes" : "no"}`);
579
- if (extension.state.missing_env.length) {
580
- console.log(` missing env: ${extension.state.missing_env.join(", ")}`);
581
- }
575
+ console.log(` Details: npx ${canonicalCliName} extend ${extension.id}`);
582
576
  console.log("");
583
577
  }
584
- console.log("View details:");
585
- console.log(` npx ${canonicalCliName} extend ${extensions[0].id}`);
586
578
  console.log("Install all:");
587
579
  console.log(` npx ${canonicalCliName} extend install --all`);
588
580
  }
@@ -803,12 +795,34 @@ function installedSkillRoot() {
803
795
  return join(codexHome(), "skills", canonicalSkillDirectory);
804
796
  }
805
797
 
798
+ function installedPluginSkillRoot() {
799
+ const root = join(codexHome(), "plugins", "cache", pluginName, pluginName);
800
+ if (!existsSync(root)) return "";
801
+ const versions = readdirSync(root, { withFileTypes: true })
802
+ .filter((entry) => entry.isDirectory())
803
+ .map((entry) => entry.name)
804
+ .sort(compareVersions)
805
+ .reverse();
806
+ for (const version of versions) {
807
+ const skillPath = join(root, version, "skills", canonicalSkillDirectory);
808
+ if (existsSync(join(skillPath, "SKILL.md"))) return skillPath;
809
+ }
810
+ return "";
811
+ }
812
+
813
+ function activeSkillRoot() {
814
+ if (existsSync(join(installedSkillRoot(), "SKILL.md"))) return installedSkillRoot();
815
+ const pluginSkillRoot = installedPluginSkillRoot();
816
+ if (pluginSkillRoot) return pluginSkillRoot;
817
+ return installedSkillRoot();
818
+ }
819
+
806
820
  function legacyInstalledSkillRoot() {
807
821
  return join(codexHome(), "skills", legacySkillName);
808
822
  }
809
823
 
810
824
  function extendRoot() {
811
- return join(installedSkillRoot(), "extend");
825
+ return join(activeSkillRoot(), "extend");
812
826
  }
813
827
 
814
828
  function extensionTarget(id) {
@@ -1109,9 +1123,20 @@ function summarizeStatuses(items) {
1109
1123
  }
1110
1124
 
1111
1125
  function assertSkillInstalledForExtensionInstall() {
1112
- if (!existsSync(join(installedSkillRoot(), "SKILL.md"))) {
1113
- throw new Error(`${canonicalProductName} skill is not installed at ${installedSkillRoot()}. Run: npx ${canonicalCliName}`);
1126
+ if (!existsSync(join(activeSkillRoot(), "SKILL.md"))) {
1127
+ throw new Error(`${canonicalProductName} skill is not installed. Run: npx ${canonicalCliName}`);
1128
+ }
1129
+ }
1130
+
1131
+ function compareVersions(left, right) {
1132
+ const leftParts = left.split(".").map((part) => Number.parseInt(part, 10) || 0);
1133
+ const rightParts = right.split(".").map((part) => Number.parseInt(part, 10) || 0);
1134
+ const length = Math.max(leftParts.length, rightParts.length);
1135
+ for (let index = 0; index < length; index += 1) {
1136
+ const diff = (leftParts[index] || 0) - (rightParts[index] || 0);
1137
+ if (diff !== 0) return diff;
1114
1138
  }
1139
+ return left.localeCompare(right);
1115
1140
  }
1116
1141
 
1117
1142
  function installedExtensions() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "goalbuddy",
3
- "version": "0.2.17",
3
+ "version": "0.2.18",
4
4
  "description": "Turn open-ended Codex goals into a GoalBuddy Scout/Judge/Worker board with receipts, verification, and optional extensions.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "goalbuddy",
3
- "version": "0.2.17",
3
+ "version": "0.2.18",
4
4
  "description": "Turn broad Codex work into verified GoalBuddy boards with Scout, Judge, Worker, receipts, and optional extensions.",
5
5
  "author": {
6
6
  "name": "tolibear",