goalbuddy 0.3.2 → 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.
Files changed (55) hide show
  1. package/README.md +55 -5
  2. package/RELEASE-0.3.5.md +324 -0
  3. package/goalbuddy/SKILL.md +40 -13
  4. package/goalbuddy/agents/README.md +1 -1
  5. package/goalbuddy/agents/goal_judge.toml +33 -17
  6. package/goalbuddy/agents/goal_scout.toml +34 -14
  7. package/goalbuddy/agents/goal_worker.toml +36 -16
  8. package/goalbuddy/extend/local-goal-board/README.md +8 -4
  9. package/goalbuddy/extend/local-goal-board/examples/subgoal-parent/goal.md +3 -0
  10. package/goalbuddy/extend/local-goal-board/examples/subgoal-parent/notes/.gitkeep +1 -0
  11. package/goalbuddy/extend/local-goal-board/examples/subgoal-parent/state.yaml +60 -0
  12. package/goalbuddy/extend/local-goal-board/examples/subgoal-parent/subgoals/T004-board-view/goal.md +3 -0
  13. package/goalbuddy/extend/local-goal-board/examples/subgoal-parent/subgoals/T004-board-view/notes/.gitkeep +1 -0
  14. package/goalbuddy/extend/local-goal-board/examples/subgoal-parent/subgoals/T004-board-view/state.yaml +52 -0
  15. package/goalbuddy/extend/local-goal-board/extension.yaml +6 -4
  16. package/goalbuddy/extend/local-goal-board/scripts/lib/goal-board.mjs +1188 -31
  17. package/goalbuddy/extend/local-goal-board/scripts/local-goal-board.mjs +389 -54
  18. package/goalbuddy/extend/local-goal-board/test/local-goal-board.test.mjs +479 -5
  19. package/goalbuddy/scripts/check-goal-state.mjs +192 -6
  20. package/goalbuddy/scripts/parallel-plan.mjs +191 -0
  21. package/goalbuddy/scripts/render-task-prompt.mjs +305 -0
  22. package/goalbuddy/templates/agents.md +5 -4
  23. package/goalbuddy/templates/goal.md +18 -4
  24. package/goalbuddy/templates/state.yaml +14 -1
  25. package/internal/assets/goalbuddy-v0.3.5-release.png +0 -0
  26. package/internal/cli/goal-maker.mjs +172 -9
  27. package/package.json +3 -2
  28. package/plugins/goalbuddy/.claude-plugin/plugin.json +2 -2
  29. package/plugins/goalbuddy/.codex-plugin/plugin.json +4 -4
  30. package/plugins/goalbuddy/README.md +5 -3
  31. package/plugins/goalbuddy/agents/goal-judge.md +35 -16
  32. package/plugins/goalbuddy/agents/goal-scout.md +38 -13
  33. package/plugins/goalbuddy/agents/goal-worker.md +37 -14
  34. package/plugins/goalbuddy/skills/goalbuddy/SKILL.md +40 -13
  35. package/plugins/goalbuddy/skills/goalbuddy/agents/README.md +1 -1
  36. package/plugins/goalbuddy/skills/goalbuddy/agents/goal_judge.toml +33 -17
  37. package/plugins/goalbuddy/skills/goalbuddy/agents/goal_scout.toml +34 -14
  38. package/plugins/goalbuddy/skills/goalbuddy/agents/goal_worker.toml +36 -16
  39. package/plugins/goalbuddy/skills/goalbuddy/extend/local-goal-board/README.md +8 -4
  40. package/plugins/goalbuddy/skills/goalbuddy/extend/local-goal-board/examples/subgoal-parent/goal.md +3 -0
  41. package/plugins/goalbuddy/skills/goalbuddy/extend/local-goal-board/examples/subgoal-parent/notes/.gitkeep +1 -0
  42. package/plugins/goalbuddy/skills/goalbuddy/extend/local-goal-board/examples/subgoal-parent/state.yaml +60 -0
  43. package/plugins/goalbuddy/skills/goalbuddy/extend/local-goal-board/examples/subgoal-parent/subgoals/T004-board-view/goal.md +3 -0
  44. package/plugins/goalbuddy/skills/goalbuddy/extend/local-goal-board/examples/subgoal-parent/subgoals/T004-board-view/notes/.gitkeep +1 -0
  45. package/plugins/goalbuddy/skills/goalbuddy/extend/local-goal-board/examples/subgoal-parent/subgoals/T004-board-view/state.yaml +52 -0
  46. package/plugins/goalbuddy/skills/goalbuddy/extend/local-goal-board/extension.yaml +6 -4
  47. package/plugins/goalbuddy/skills/goalbuddy/extend/local-goal-board/scripts/lib/goal-board.mjs +1188 -31
  48. package/plugins/goalbuddy/skills/goalbuddy/extend/local-goal-board/scripts/local-goal-board.mjs +389 -54
  49. package/plugins/goalbuddy/skills/goalbuddy/extend/local-goal-board/test/local-goal-board.test.mjs +479 -5
  50. package/plugins/goalbuddy/skills/goalbuddy/scripts/check-goal-state.mjs +192 -6
  51. package/plugins/goalbuddy/skills/goalbuddy/scripts/parallel-plan.mjs +191 -0
  52. package/plugins/goalbuddy/skills/goalbuddy/scripts/render-task-prompt.mjs +305 -0
  53. package/plugins/goalbuddy/skills/goalbuddy/templates/agents.md +5 -4
  54. package/plugins/goalbuddy/skills/goalbuddy/templates/goal.md +18 -4
  55. package/plugins/goalbuddy/skills/goalbuddy/templates/state.yaml +14 -1
@@ -52,6 +52,8 @@ const optionsWithValues = new Set([
52
52
  "--port",
53
53
  "--source",
54
54
  "--target",
55
+ "--task",
56
+ "--board",
55
57
  ]);
56
58
 
57
59
  const args = process.argv.slice(2);
@@ -81,15 +83,23 @@ async function main() {
81
83
  break;
82
84
  case "install":
83
85
  case "update":
86
+ if (wantsHelp()) {
87
+ usage();
88
+ break;
89
+ }
84
90
  if (installTargetMode() === "all") {
85
91
  await installEverywhere();
86
92
  } else if (installTargetMode() === "codex") {
87
- await installAll();
93
+ installPlugin();
88
94
  } else {
89
95
  await installClaudeAll();
90
96
  }
91
97
  break;
92
98
  case "agents":
99
+ if (wantsHelp()) {
100
+ usage();
101
+ break;
102
+ }
93
103
  if (targetMode() === "codex") {
94
104
  installAgents();
95
105
  } else {
@@ -97,6 +107,10 @@ async function main() {
97
107
  }
98
108
  break;
99
109
  case "doctor":
110
+ if (wantsHelp()) {
111
+ usage();
112
+ break;
113
+ }
100
114
  if (targetMode() === "codex") {
101
115
  doctor();
102
116
  } else {
@@ -108,6 +122,10 @@ async function main() {
108
122
  checkUpdate();
109
123
  break;
110
124
  case "plugin":
125
+ if (wantsHelp()) {
126
+ pluginUsage();
127
+ break;
128
+ }
111
129
  plugin();
112
130
  break;
113
131
  case "extend":
@@ -116,6 +134,12 @@ async function main() {
116
134
  case "board":
117
135
  await board();
118
136
  break;
137
+ case "prompt":
138
+ await prompt();
139
+ break;
140
+ case "parallel-plan":
141
+ await parallelPlan();
142
+ break;
119
143
  case "help":
120
144
  case "--help":
121
145
  case "-h":
@@ -156,6 +180,10 @@ function hasFlag(name) {
156
180
  return args.includes(name);
157
181
  }
158
182
 
183
+ function wantsHelp() {
184
+ return hasFlag("--help") || hasFlag("-h");
185
+ }
186
+
159
187
  function positional(index) {
160
188
  return positionalArgs()[index] || "";
161
189
  }
@@ -191,6 +219,8 @@ Usage:
191
219
  ${canonicalCliName} extend install --all [--catalog-url <url-or-path>] [--dry-run] [--force] [--json]
192
220
  ${canonicalCliName} extend doctor [<id>] [--codex-home <path>] [--json]
193
221
  ${canonicalCliName} board <docs/goals/slug> [--catalog-url <url-or-path>] [--host <host>] [--port <port>] [--once] [--json]
222
+ ${canonicalCliName} prompt <docs/goals/slug> [--task T###] [--board <path/to/state.yaml>] [--json]
223
+ ${canonicalCliName} parallel-plan <docs/goals/slug> [--json]
194
224
 
195
225
  Targets: by default, install/update prepares both Codex (~/.codex) and Claude Code (~/.claude). Use --target codex or --target claude to limit the command.
196
226
 
@@ -542,7 +572,7 @@ This alias has the same invocation boundary as \`$${canonicalSkillName}\`: prepa
542
572
  function installAgents({ quiet = false } = {}) {
543
573
  const source = join(skillSource, "agents");
544
574
  const target = join(codexHome(), "agents");
545
- const force = hasFlag("--force") || command === "update" || command === "install";
575
+ const force = hasFlag("--force") || command === "update" || command === "install" || command === "default" || command === "plugin";
546
576
  mkdirSync(target, { recursive: true });
547
577
 
548
578
  const results = [];
@@ -591,6 +621,7 @@ async function installAll() {
591
621
  function doctor() {
592
622
  const skillPath = join(installedSkillRoot(), "SKILL.md");
593
623
  const legacySkillPath = join(legacyInstalledSkillRoot(), "SKILL.md");
624
+ const plugin = installedCodexPlugin();
594
625
  const agentsPath = join(codexHome(), "agents");
595
626
  const installed = existsSync(skillPath);
596
627
  const legacyInstalled = existsSync(legacySkillPath);
@@ -606,12 +637,38 @@ function doctor() {
606
637
  });
607
638
  const goalRuntime = codexGoalRuntimeStatus();
608
639
  const warnings = [];
640
+ const errors = [];
609
641
  if (!goalRuntime.ready) {
610
642
  warnings.push("native Codex /goal runtime is not ready; run `codex login` and `codex features enable goals` before using /goal.");
611
643
  }
644
+ if (!plugin.skill_installed && !installed) {
645
+ errors.push("Codex GoalBuddy plugin is not installed; run `npx goalbuddy --target codex`.");
646
+ }
647
+ if (plugin.skill_installed && !plugin.enabled) {
648
+ errors.push("Codex GoalBuddy plugin cache exists but is not enabled in config.toml; run `npx goalbuddy --target codex`.");
649
+ }
650
+ for (const file of missingAgents) {
651
+ errors.push(`Missing GoalBuddy Codex agent: ${file}; run \`npx goalbuddy --target codex\`.`);
652
+ }
653
+ for (const file of staleAgents) {
654
+ errors.push(`Stale GoalBuddy Codex agent: ${file}; run \`npx goalbuddy update --target codex\`.`);
655
+ }
656
+ if (hasFlag("--goal-ready") && !goalRuntime.ready) {
657
+ errors.push("Native Codex /goal runtime is not ready. GoalBuddy $goal-prep and local boards are separate from OpenAI-gated native /goal.");
658
+ }
612
659
 
613
660
  console.log(JSON.stringify({
614
661
  codex_home: codexHome(),
662
+ codex_install_model: "plugin",
663
+ expected_state: {
664
+ plugin_cache: true,
665
+ bundled_skill: "$goal-prep",
666
+ standalone_personal_skill: false,
667
+ compatibility_skill: false,
668
+ agents: requiredAgentFiles,
669
+ native_goal: "separate OpenAI-gated Codex feature",
670
+ },
671
+ plugin,
615
672
  skill_installed: installed,
616
673
  skill_path: skillPath,
617
674
  compatibility_skill_installed: legacyInstalled,
@@ -621,11 +678,14 @@ function doctor() {
621
678
  stale_agents: staleAgents,
622
679
  goal_runtime: goalRuntime,
623
680
  warnings,
681
+ errors,
624
682
  }, null, 2));
625
683
 
626
- const installOk = installed && missingAgents.length === 0 && staleAgents.length === 0;
684
+ const pluginOk = plugin.skill_installed && plugin.enabled;
685
+ const legacySkillOk = installed;
686
+ const installOk = (pluginOk || legacySkillOk) && missingAgents.length === 0 && staleAgents.length === 0;
627
687
  const goalReadyOk = !hasFlag("--goal-ready") || goalRuntime.ready;
628
- process.exit(installOk && goalReadyOk ? 0 : 1);
688
+ process.exit(installOk && goalReadyOk && errors.length === 0 ? 0 : 1);
629
689
  }
630
690
 
631
691
  function checkUpdate() {
@@ -670,6 +730,10 @@ function updateReport() {
670
730
 
671
731
  function plugin() {
672
732
  const subcommand = positional(1) || "";
733
+ if (wantsHelp()) {
734
+ pluginUsage();
735
+ return;
736
+ }
673
737
  switch (subcommand) {
674
738
  case "install":
675
739
  installPlugin();
@@ -713,14 +777,17 @@ function installPlugin({ quiet = false } = {}) {
713
777
  throw new Error(`Failed to add Codex plugin marketplace: ${firstLine(marketplace.stderr || marketplace.stdout)}`);
714
778
  }
715
779
 
780
+ const legacySkillPaths = legacyCodexSkillRoots();
716
781
  const existingPluginSkillPath = installedPluginSkillRoot();
717
- const preservedExtensions = preserveInstalledExtensions([existingPluginSkillPath], { tempRoot: dirname(pluginCachePath) });
782
+ const preservedExtensions = preserveInstalledExtensions([existingPluginSkillPath, ...legacySkillPaths], { tempRoot: dirname(pluginCachePath) });
718
783
  mkdirSync(dirname(pluginCachePath), { recursive: true });
719
784
  rmSync(pluginCachePath, { recursive: true, force: true });
720
785
  cpSync(pluginSource, pluginCachePath, { recursive: true });
721
786
  restoreInstalledExtensions(pluginSkillPath, preservedExtensions.tempPath);
722
787
  cleanupPreservedExtensions([preservedExtensions.tempPath]);
788
+ const removedLegacySkillPaths = cleanupLegacyCodexSkills();
723
789
  const configPath = enablePluginConfig();
790
+ const agents = installAgents({ quiet: true });
724
791
 
725
792
  const report = {
726
793
  installed: true,
@@ -731,7 +798,9 @@ function installPlugin({ quiet = false } = {}) {
731
798
  marketplace_source: source,
732
799
  cache_path: pluginCachePath,
733
800
  config_path: configPath,
801
+ agents,
734
802
  preserved_extensions: preservedExtensions.ids,
803
+ removed_legacy_skill_paths: removedLegacySkillPaths,
735
804
  };
736
805
 
737
806
  if (hasFlag("--json") && !quiet) {
@@ -745,9 +814,13 @@ function installPlugin({ quiet = false } = {}) {
745
814
  console.log(`Marketplace: ${source}`);
746
815
  console.log(`Cache: ${pluginCachePath}`);
747
816
  console.log(`Config: ${configPath}`);
817
+ console.log(`Agents: ${summarizeStatuses(report.agents)}`);
748
818
  if (report.preserved_extensions.length) {
749
819
  console.log(`Preserved extensions: ${report.preserved_extensions.join(", ")}`);
750
820
  }
821
+ if (report.removed_legacy_skill_paths.length) {
822
+ console.log(`Removed legacy personal skills: ${report.removed_legacy_skill_paths.join(", ")}`);
823
+ }
751
824
  console.log("");
752
825
  console.log("Restart Codex, then use:");
753
826
  console.log(` $${canonicalSkillName}`);
@@ -758,6 +831,20 @@ function installPlugin({ quiet = false } = {}) {
758
831
  return report;
759
832
  }
760
833
 
834
+ function legacyCodexSkillRoots() {
835
+ return [installedSkillRoot(), legacyInstalledSkillRoot()];
836
+ }
837
+
838
+ function cleanupLegacyCodexSkills() {
839
+ const removed = [];
840
+ for (const path of legacyCodexSkillRoots()) {
841
+ if (!existsSync(path)) continue;
842
+ rmSync(path, { recursive: true, force: true });
843
+ removed.push(path);
844
+ }
845
+ return removed;
846
+ }
847
+
761
848
  function pluginCacheRoot(version) {
762
849
  return join(codexHome(), "plugins", "cache", pluginName, pluginName, version);
763
850
  }
@@ -941,6 +1028,39 @@ async function board() {
941
1028
  process.exit(result.status ?? 1);
942
1029
  }
943
1030
 
1031
+ async function prompt() {
1032
+ if (hasFlag("--parallel-plan")) {
1033
+ await parallelPlan();
1034
+ return;
1035
+ }
1036
+
1037
+ const script = join(skillSource, "scripts", "render-task-prompt.mjs");
1038
+ const scriptArgs = [script, ...args.slice(1)];
1039
+ const result = spawnSync(process.execPath, scriptArgs, {
1040
+ cwd: packageRoot,
1041
+ encoding: "utf8",
1042
+ env: process.env,
1043
+ });
1044
+ if (result.stdout) process.stdout.write(result.stdout);
1045
+ if (result.stderr) process.stderr.write(result.stderr);
1046
+ if (result.error) throw result.error;
1047
+ process.exit(result.status ?? 1);
1048
+ }
1049
+
1050
+ async function parallelPlan() {
1051
+ const script = join(skillSource, "scripts", "parallel-plan.mjs");
1052
+ const scriptArgs = [script, ...args.slice(1).filter((arg) => arg !== "--parallel-plan")];
1053
+ const result = spawnSync(process.execPath, scriptArgs, {
1054
+ cwd: packageRoot,
1055
+ encoding: "utf8",
1056
+ env: process.env,
1057
+ });
1058
+ if (result.stdout) process.stdout.write(result.stdout);
1059
+ if (result.stderr) process.stderr.write(result.stderr);
1060
+ if (result.error) throw result.error;
1061
+ process.exit(result.status ?? 1);
1062
+ }
1063
+
944
1064
  async function ensureLocalBoardExtension() {
945
1065
  const id = "local-goal-board";
946
1066
  const script = join(extensionTarget(id), "scripts", "local-goal-board.mjs");
@@ -1235,8 +1355,24 @@ function installedSkillRoot() {
1235
1355
  }
1236
1356
 
1237
1357
  function installedPluginSkillRoot() {
1358
+ return installedCodexPlugin().skill_path;
1359
+ }
1360
+
1361
+ function installedCodexPlugin() {
1238
1362
  const root = join(codexHome(), "plugins", "cache", pluginName, pluginName);
1239
- if (!existsSync(root)) return "";
1363
+ const configPath = join(codexHome(), "config.toml");
1364
+ const base = {
1365
+ installed: false,
1366
+ enabled: pluginConfigEnabled(configPath),
1367
+ name: `${pluginName}@${pluginName}`,
1368
+ version: "",
1369
+ cache_path: "",
1370
+ manifest_path: "",
1371
+ skill_installed: false,
1372
+ skill_path: "",
1373
+ config_path: configPath,
1374
+ };
1375
+ if (!existsSync(root)) return base;
1240
1376
  const versions = readdirSync(root, { withFileTypes: true })
1241
1377
  .filter((entry) => entry.isDirectory())
1242
1378
  .map((entry) => entry.name)
@@ -1244,10 +1380,37 @@ function installedPluginSkillRoot() {
1244
1380
  .sort(compareVersions)
1245
1381
  .reverse();
1246
1382
  for (const version of versions) {
1247
- const skillPath = join(root, version, "skills", canonicalSkillDirectory);
1248
- if (existsSync(join(skillPath, "SKILL.md"))) return skillPath;
1383
+ const cachePath = join(root, version);
1384
+ const skillPath = join(cachePath, "skills", canonicalSkillDirectory);
1385
+ const manifestPath = join(cachePath, ".codex-plugin", "plugin.json");
1386
+ if (existsSync(join(skillPath, "SKILL.md"))) {
1387
+ return {
1388
+ ...base,
1389
+ installed: true,
1390
+ version,
1391
+ cache_path: cachePath,
1392
+ manifest_path: manifestPath,
1393
+ skill_installed: true,
1394
+ skill_path: skillPath,
1395
+ };
1396
+ }
1397
+ }
1398
+ return base;
1399
+ }
1400
+
1401
+ function pluginConfigEnabled(configPath) {
1402
+ if (!existsSync(configPath)) return false;
1403
+ const lines = readFileSync(configPath, "utf8").split(/\r?\n/);
1404
+ const header = `[plugins."${pluginName}@${pluginName}"]`;
1405
+ const start = lines.findIndex((line) => line.trim() === header);
1406
+ if (start === -1) return false;
1407
+ for (let index = start + 1; index < lines.length; index += 1) {
1408
+ const line = lines[index].trim();
1409
+ if (line.startsWith("[")) break;
1410
+ if (/^enabled\s*=\s*true\b/.test(line)) return true;
1411
+ if (/^enabled\s*=/.test(line)) return false;
1249
1412
  }
1250
- return "";
1413
+ return false;
1251
1414
  }
1252
1415
 
1253
1416
  function activeSkillRoot() {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "goalbuddy",
3
- "version": "0.3.2",
4
- "description": "A /goal operating system for Codex and Claude Code: Scout/Judge/Worker boards with visual board surfaces, receipts, and verification.",
3
+ "version": "0.3.6",
4
+ "description": "A /goal operating system for Codex and Claude Code: subgoals, parallel-agent-ready boards, dark mode, receipts, and verification.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "goalbuddy": "internal/cli/goal-maker.mjs",
@@ -10,6 +10,7 @@
10
10
  "files": [
11
11
  ".agents/plugins/marketplace.json",
12
12
  "README.md",
13
+ "RELEASE-0.3.5.md",
13
14
  "CONTRIBUTING.md",
14
15
  "examples",
15
16
  "plugins/goalbuddy",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "goalbuddy",
3
- "version": "0.3.2",
4
- "description": "Turn broad Claude Code work into verified GoalBuddy boards with Scout, Judge, Worker, visual boards, and receipts.",
3
+ "version": "0.3.6",
4
+ "description": "Turn broad Claude Code work into verified GoalBuddy boards with subgoals, parallel-agent-ready handoffs, dark mode, and receipts.",
5
5
  "author": {
6
6
  "name": "tolibear",
7
7
  "email": "support@tolibear.com",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "goalbuddy",
3
- "version": "0.3.2",
4
- "description": "Turn broad Codex and Claude Code work into verified GoalBuddy boards with Scout, Judge, Worker, visual boards, and receipts.",
3
+ "version": "0.3.6",
4
+ "description": "Turn broad Codex and Claude Code work into verified GoalBuddy boards with subgoals, parallel-agent-ready handoffs, dark mode, and receipts.",
5
5
  "author": {
6
6
  "name": "tolibear",
7
7
  "email": "support@tolibear.com",
@@ -24,8 +24,8 @@
24
24
  "skills": "./skills/",
25
25
  "interface": {
26
26
  "displayName": "GoalBuddy",
27
- "shortDescription": "Turn broad Codex or Claude Code work into verified Scout/Judge/Worker boards",
28
- "longDescription": "GoalBuddy packages a structured goal workflow for broad, long-running, or ambiguous engineering work in Codex or Claude Code. It creates durable goal charters, task boards, visual board surfaces, receipts, verification gates, extension handoffs, and compatibility guidance for teams moving from goal-maker.",
27
+ "shortDescription": "Verified goal boards with subgoals, parallel-agent-ready handoffs, and dark mode",
28
+ "longDescription": "GoalBuddy packages a structured goal workflow for broad, long-running, or ambiguous engineering work in Codex or Claude Code. It creates durable goal charters, task boards, optional depth-1 subgoals, visual board surfaces, parallel-agent-ready handoffs, receipts, verification gates, extension handoffs, and compatibility guidance for teams moving from goal-maker.",
29
29
  "developerName": "tolibear",
30
30
  "category": "Coding",
31
31
  "capabilities": [
@@ -2,13 +2,15 @@
2
2
 
3
3
  GoalBuddy packages the canonical `goal-prep` skill as a plugin so teams can install the reusable workflow in **Codex** and **Claude Code**, while keeping the npm CLI for local setup, doctor checks, and extension management.
4
4
 
5
+ Version 0.3.5 is the Subgoals, Parallel Agents, and Dark Mode release: depth-1 child boards, a shared multi-board local hub, readable dark-mode boards, stricter agent contracts, deterministic prompt rendering, and conservative parallel planning for long-running work.
6
+
5
7
  ## What It Contains
6
8
 
7
9
  - `.codex-plugin/plugin.json`: Codex plugin manifest and Codex UI copy.
8
10
  - `.claude-plugin/plugin.json`: Claude Code plugin manifest.
9
11
  - `skills/goalbuddy/`: the installable GoalBuddy skill payload (shared by both platforms).
10
12
  - `agents/`: Claude Code subagent definitions (`goal-scout.md`, `goal-judge.md`, `goal-worker.md`).
11
- - `commands/goal-prep.md`: Claude Code slash command entry point.
13
+ - `skills/goalbuddy/SKILL.md`: canonical `$goal-prep` / `/goal-prep` entry point.
12
14
  - `assets/goalbuddy-icon.svg`: lightweight plugin icon.
13
15
 
14
16
  ## Local Testing
@@ -27,7 +29,7 @@ npx goalbuddy check-update
27
29
  npx goalbuddy
28
30
  ```
29
31
 
30
- This installs and enables the native Codex plugin in `~/.codex/`, then installs the GoalBuddy skill, Scout/Judge/Worker subagents, and `/goal-prep` slash command into `~/.claude/`.
32
+ This installs and enables the native Codex plugin in `~/.codex/`, then installs the GoalBuddy skill and Scout/Judge/Worker subagents into `~/.claude/`. The skill surfaces `/goal-prep` in Claude Code.
31
33
 
32
34
  ## Install One Target
33
35
 
@@ -36,7 +38,7 @@ npx goalbuddy --target codex
36
38
  npx goalbuddy --target claude
37
39
  ```
38
40
 
39
- This installs the GoalBuddy skill, the three Scout/Judge/Worker subagents, and the `/goal-prep` slash command into `~/.claude/`. Restart Claude Code, then run:
41
+ This installs the GoalBuddy skill and the three Scout/Judge/Worker subagents into `~/.claude/`. Restart Claude Code, then run:
40
42
 
41
43
  ```text
42
44
  /goal-prep
@@ -1,27 +1,46 @@
1
1
  ---
2
2
  name: goal-judge
3
- description: GoalBuddy Judge. High-thinking strategic reviewer for GoalBuddy escalation: ambiguity, risky scope, source/product conflicts, safety/API/live decisions, and tranche completion. Returns a compact Judge receipt for the PM to paste into state.yaml.
3
+ description: GoalBuddy Judge. Skeptical read-only gate for ambiguity, risky scope, phase transitions, completion, and parallel-safety decisions.
4
4
  tools: Read, Grep, Glob, Bash
5
5
  ---
6
6
 
7
7
  You are Judge for GoalBuddy.
8
8
 
9
- Thinking level: high.
10
- Mode: strategic reviewer and escalation authority.
9
+ Use Judge only for decisions that require judgment: contradictory sources, risky scope, dependency order, phase gates, live/API/security/persistence choices, completion, or whether work can safely branch into a depth-1 sub-goal. Routine checks belong to the checker.
11
10
 
12
- Think as a skeptical staff engineer and project-management systems designer. You decide and constrain; you do not broadly implement.
11
+ Hard contract:
13
12
 
14
- Use when source, tests, product behavior, API/live strategy, dirty scope, giant-file risk, safety/auth/money/persistence semantics, task priority, or completion readiness is ambiguous.
13
+ - Read only. Do not edit, stage, install, or implement.
14
+ - Read state receipts before raw files. Then read only the inputs named in the Judge task.
15
+ - Be skeptical of progress. Lots of files, docs, or tests are not completion.
16
+ - A safe Worker package must include objective, allowed_files, verify commands, and stop_if, and should cover the largest reversible local work package at that boundary.
17
+ - Choose the largest safe useful slice: bounded, explicit, verified, reversible, and outcome-moving. Safety does not mean tiny.
18
+ - Judge a whole useful slice, not one helper at a time.
19
+ - Detect micro-slice loops. Reject another tiny helper when the board has enough scaffolding for vertical progress.
20
+ - Select PM reorientation when recent receipts are safe-looking but outcome-light.
21
+ - Prefer milestone reviews over helper reviews.
22
+ - A safe child board must be depth 1, inside `subgoals/`, non-recursive, and linked from exactly one parent task.
23
+ - Parallel Worker work is safe only with provably disjoint `allowed_files`. Separate boards alone are not proof.
24
+ - Reject completion unless the full original outcome is mapped to receipts and current verification.
25
+ - Do not generate routine next tasks, choose the active task, or mutate state. The PM owns continuation after your review.
15
26
 
16
- Do not approve based on lots of docs or lots of tests. Require coherent receipts and current verification.
27
+ Return exactly one parseable JSON receipt object:
17
28
 
18
- Return a compact Judge receipt for the PM to paste into state.yaml:
19
- - result
20
- - decision
21
- - evidence
22
- - next_allowed_task when work may continue
23
- - blocked_tasks when work should not proceed
24
- - completion decision when auditing a tranche
25
- - required board updates
26
-
27
- Do not broadly implement, select the active task, or mark the goal complete yourself.
29
+ ```json
30
+ {
31
+ "goalbuddy_receipt_v1": {
32
+ "result": "done | blocked",
33
+ "task_id": "<T###>",
34
+ "board_path": "<path to state.yaml>",
35
+ "decision": "approved | rejected | approve_subgoal | reject_subgoal | not_complete | complete",
36
+ "full_outcome_complete": false,
37
+ "rationale": "<=120 words>",
38
+ "evidence": [],
39
+ "subgoal_contract": null,
40
+ "parallel_safety": null,
41
+ "blocked_tasks": [],
42
+ "missing_evidence": [],
43
+ "required_board_updates": []
44
+ }
45
+ }
46
+ ```
@@ -1,24 +1,49 @@
1
1
  ---
2
2
  name: goal-scout
3
- description: GoalBuddy Scout. Read-only evidence mapper for one GoalBuddy task. Finds repo/source/spec evidence, verification commands, ambiguities, and candidate next tasks. Returns a compact Scout receipt for the PM to paste into state.yaml.
3
+ description: GoalBuddy Scout. Read-only mapper for one active task. Produces a compact evidence receipt, not a plan, implementation, or next active task.
4
4
  tools: Read, Grep, Glob, Bash
5
5
  ---
6
6
 
7
7
  You are Scout for GoalBuddy.
8
8
 
9
- Thinking level: medium.
10
- Mode: read-only evidence mapping.
9
+ Default effort: low. Use deeper analysis only when the task explicitly asks for conflict synthesis, full-doc reading, or architecture discovery.
11
10
 
12
- You are read-only. Do not edit files, stage files, run destructive commands, or claim implementation is complete.
11
+ Hard contract:
13
12
 
14
- Given one active Scout task, map repo/source/spec evidence, verification commands, health signals, improvement candidates, target files, tests, and unresolved ambiguity.
13
+ - Read only. Do not edit, stage, install, start long-running services, or spawn agents.
14
+ - Work only on the active Scout task the PM gives you.
15
+ - Prefer targeted inspection over broad dumps. Do not paste full files or long command output.
16
+ - Read receipts and named inputs first. Only expand to extra files when needed to answer the task.
17
+ - Return evidence, contradictions, and candidate facts. Do not choose the next active task and do not mark completion.
15
18
 
16
- Return a compact Scout receipt for the PM to paste into state.yaml:
17
- - result
18
- - summary
19
- - evidence paths
20
- - note path if findings are too large for the task card
21
- - spawned_tasks when useful
22
- - ambiguity requiring Judge
19
+ Parallel safety:
23
20
 
24
- Do not select the active task or mark the goal complete.
21
+ - Scout may run in parallel with other Scouts because it is read-only.
22
+ - If asked to work on a child board, inspect only that child board plus explicitly linked parent context.
23
+ - Never mutate parent or child state.
24
+
25
+ Budget:
26
+
27
+ - Max 12 shell commands unless the task explicitly allows more.
28
+ - Max 12 evidence items.
29
+ - Summary max 120 words.
30
+ - If findings are long, request a note file path from the PM instead of dumping content.
31
+
32
+ Return exactly one parseable JSON receipt object:
33
+
34
+ ```json
35
+ {
36
+ "goalbuddy_receipt_v1": {
37
+ "result": "done | blocked",
38
+ "task_id": "<T###>",
39
+ "board_path": "<path to state.yaml>",
40
+ "summary": "<=120 words>",
41
+ "evidence": [],
42
+ "facts": [],
43
+ "contradictions": [],
44
+ "ambiguity_requiring_judge": [],
45
+ "commands": [],
46
+ "note_needed": false
47
+ }
48
+ }
49
+ ```
@@ -1,26 +1,49 @@
1
1
  ---
2
2
  name: goal-worker
3
- description: GoalBuddy Worker. Low-thinking bounded implementer for exactly one GoalBuddy Worker task with allowed files, verification commands, and stop conditions. Returns a compact Worker receipt for the PM to paste into state.yaml.
3
+ description: GoalBuddy Worker. Bounded writer for one coherent reversible Worker work package. Edits only allowed_files, runs verify, returns receipt.
4
4
  tools: Read, Edit, Write, Grep, Glob, Bash
5
5
  ---
6
6
 
7
7
  You are Worker for GoalBuddy.
8
8
 
9
- Thinking level: low.
10
- Mode: one bounded writer.
9
+ Default effort: medium for implementation tasks. Use low only for tiny repair tasks or when the board explicitly sets `reasoning_hint` low.
11
10
 
12
- Execute exactly one active Worker task. Do not broaden scope.
11
+ Hard contract:
13
12
 
14
- You may edit only the task's allowed_files. You may update only explicitly named control files if the PM included them in scope. Do not decide product behavior, retained/excluded scope, API/live/deployment strategy, architecture direction, parity, or completion readiness.
13
+ - Execute exactly one Worker task on exactly one board.
14
+ - Before editing, identify `board_path`, `task_id`, `allowed_files`, `verify`, and `stop_if` from the task. If any are missing, stop.
15
+ - Edit only files matching `allowed_files`. Do not edit GoalBuddy control files unless explicitly listed.
16
+ - Do not decide product strategy, architecture direction, live/API/deployment policy, or completion readiness.
17
+ - Do not spawn agents.
18
+ - Do not create child sub-goals unless the task explicitly allows it.
19
+ - Run the verify commands exactly as listed after edits. You may make at most two fix attempts.
20
+ - Stop immediately if required evidence is missing, a file outside `allowed_files` is needed, source/product/tests conflict, or verification still fails after two attempts.
21
+ - Do not request a Judge just because the package is done. The PM decides whether this is a phase, risk, ambiguity, rejected-verification, or final-completion boundary.
22
+ - Keep the diff coherent, bounded, and reversible. Do not shrink the assigned work below the largest safe useful slice.
23
+ - Complete the whole assigned slice. Do not stop after the first helper if remaining work is inside `allowed_files` and verification is still feasible.
24
+ - If the task asks for a vertical slice, complete the vertical slice.
15
25
 
16
- Stop immediately if required evidence is missing, files outside scope are needed, source/tests/product conflict, verification fails twice, or the diff exceeds the task budget.
26
+ Parallel safety:
17
27
 
18
- Return a compact Worker receipt for the PM to paste into state.yaml:
19
- - result
20
- - changed_files
21
- - commands run with pass/fail
22
- - summary
23
- - remaining_blockers
24
- - needs_judge when strategy or ambiguity remains
28
+ - Do not assume parallel Worker safety.
29
+ - If another active Worker may touch the same files, stop and report a blocker.
30
+ - Work on a child board only when the task `board_path` points to that child `state.yaml`.
31
+ - Never mutate the parent board from a child Worker unless the parent board file is explicitly in `allowed_files`.
25
32
 
26
- Do not select the next active task or mark the goal complete.
33
+ Return exactly one parseable JSON receipt object:
34
+
35
+ ```json
36
+ {
37
+ "goalbuddy_receipt_v1": {
38
+ "result": "done | blocked",
39
+ "task_id": "<T###>",
40
+ "board_path": "<path to state.yaml>",
41
+ "changed_files": [],
42
+ "commands": [],
43
+ "summary": "<=120 words>",
44
+ "remaining_blockers": [],
45
+ "verification_attempts": 1,
46
+ "stopped_because": null
47
+ }
48
+ }
49
+ ```