gsd-pi 2.11.0 → 2.13.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.
Files changed (165) hide show
  1. package/dist/cli.js +18 -1
  2. package/dist/onboarding.js +3 -0
  3. package/dist/resource-loader.d.ts +2 -0
  4. package/dist/resource-loader.js +36 -1
  5. package/dist/resources/extensions/bg-shell/index.ts +51 -7
  6. package/dist/resources/extensions/gsd/auto-worktree.ts +509 -0
  7. package/dist/resources/extensions/gsd/auto.ts +381 -13
  8. package/dist/resources/extensions/gsd/commands.ts +9 -3
  9. package/dist/resources/extensions/gsd/doctor.ts +254 -3
  10. package/dist/resources/extensions/gsd/git-self-heal.ts +198 -0
  11. package/dist/resources/extensions/gsd/git-service.ts +11 -0
  12. package/dist/resources/extensions/gsd/guided-flow.ts +81 -9
  13. package/dist/resources/extensions/gsd/post-unit-hooks.ts +449 -0
  14. package/dist/resources/extensions/gsd/preferences.ts +209 -1
  15. package/dist/resources/extensions/gsd/prompt-loader.ts +28 -1
  16. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  17. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -3
  18. package/dist/resources/extensions/gsd/prompts/discuss.md +10 -8
  19. package/dist/resources/extensions/gsd/prompts/execute-task.md +4 -2
  20. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +3 -1
  21. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +3 -1
  22. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +3 -1
  23. package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +3 -1
  24. package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +4 -2
  25. package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +3 -1
  26. package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +3 -1
  27. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +9 -12
  28. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -3
  29. package/dist/resources/extensions/gsd/prompts/queue.md +3 -1
  30. package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  31. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  32. package/dist/resources/extensions/gsd/prompts/system.md +32 -29
  33. package/dist/resources/extensions/gsd/templates/context.md +1 -1
  34. package/dist/resources/extensions/gsd/templates/state.md +3 -3
  35. package/dist/resources/extensions/gsd/tests/auto-worktree-merge.test.ts +282 -0
  36. package/dist/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +259 -0
  37. package/dist/resources/extensions/gsd/tests/auto-worktree.test.ts +147 -0
  38. package/dist/resources/extensions/gsd/tests/doctor-git.test.ts +246 -0
  39. package/dist/resources/extensions/gsd/tests/doctor.test.ts +115 -1
  40. package/dist/resources/extensions/gsd/tests/git-self-heal.test.ts +234 -0
  41. package/dist/resources/extensions/gsd/tests/isolation-resolver.test.ts +107 -0
  42. package/dist/resources/extensions/gsd/tests/post-unit-hooks.test.ts +297 -0
  43. package/dist/resources/extensions/gsd/tests/preferences-git.test.ts +88 -0
  44. package/dist/resources/extensions/gsd/tests/preferences-hooks.test.ts +226 -0
  45. package/dist/resources/extensions/gsd/tests/regex-hardening.test.ts +12 -0
  46. package/dist/resources/extensions/gsd/tests/worktree-e2e.test.ts +315 -0
  47. package/dist/resources/extensions/gsd/types.ts +109 -0
  48. package/dist/resources/extensions/gsd/worktree-manager.ts +6 -4
  49. package/dist/resources/extensions/search-the-web/command-search-provider.ts +8 -4
  50. package/dist/resources/extensions/search-the-web/native-search.ts +15 -10
  51. package/dist/resources/extensions/search-the-web/provider.ts +19 -2
  52. package/dist/resources/extensions/search-the-web/tool-fetch-page.ts +62 -0
  53. package/dist/resources/extensions/search-the-web/tool-llm-context.ts +62 -3
  54. package/dist/resources/extensions/search-the-web/tool-search.ts +62 -3
  55. package/dist/wizard.js +1 -0
  56. package/package.json +1 -1
  57. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  58. package/packages/pi-agent-core/dist/agent-loop.js +169 -55
  59. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  60. package/packages/pi-agent-core/dist/agent.d.ts +13 -1
  61. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  62. package/packages/pi-agent-core/dist/agent.js +16 -0
  63. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  64. package/packages/pi-agent-core/dist/types.d.ts +91 -1
  65. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  66. package/packages/pi-agent-core/dist/types.js.map +1 -1
  67. package/packages/pi-agent-core/src/agent-loop.ts +273 -63
  68. package/packages/pi-agent-core/src/agent.ts +24 -0
  69. package/packages/pi-agent-core/src/types.ts +98 -0
  70. package/packages/pi-ai/dist/env-api-keys.js +1 -0
  71. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  72. package/packages/pi-ai/dist/models.generated.d.ts +314 -0
  73. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  74. package/packages/pi-ai/dist/models.generated.js +236 -0
  75. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  76. package/packages/pi-ai/dist/types.d.ts +1 -1
  77. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  78. package/packages/pi-ai/dist/types.js.map +1 -1
  79. package/packages/pi-ai/src/env-api-keys.ts +1 -0
  80. package/packages/pi-ai/src/models.generated.ts +236 -0
  81. package/packages/pi-ai/src/types.ts +2 -1
  82. package/packages/pi-coding-agent/dist/cli/args.d.ts.map +1 -1
  83. package/packages/pi-coding-agent/dist/cli/args.js +2 -1
  84. package/packages/pi-coding-agent/dist/cli/args.js.map +1 -1
  85. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +10 -0
  86. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  87. package/packages/pi-coding-agent/dist/core/agent-session.js +69 -8
  88. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  89. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +4 -1
  90. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  91. package/packages/pi-coding-agent/dist/core/extensions/runner.js +2 -1
  92. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  93. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +5 -0
  94. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  95. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  96. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  97. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
  98. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  99. package/packages/pi-coding-agent/dist/core/sdk.js +3 -3
  100. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  101. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  102. package/packages/pi-coding-agent/dist/core/system-prompt.js +6 -0
  103. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  104. package/packages/pi-coding-agent/src/cli/args.ts +2 -1
  105. package/packages/pi-coding-agent/src/core/agent-session.ts +76 -7
  106. package/packages/pi-coding-agent/src/core/extensions/runner.ts +2 -1
  107. package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -0
  108. package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
  109. package/packages/pi-coding-agent/src/core/sdk.ts +3 -3
  110. package/packages/pi-coding-agent/src/core/system-prompt.ts +9 -0
  111. package/packages/pi-tui/dist/components/editor.d.ts +11 -0
  112. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  113. package/packages/pi-tui/dist/components/editor.js +64 -6
  114. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  115. package/packages/pi-tui/src/components/editor.ts +71 -6
  116. package/src/resources/extensions/bg-shell/index.ts +51 -7
  117. package/src/resources/extensions/gsd/auto-worktree.ts +509 -0
  118. package/src/resources/extensions/gsd/auto.ts +381 -13
  119. package/src/resources/extensions/gsd/commands.ts +9 -3
  120. package/src/resources/extensions/gsd/doctor.ts +254 -3
  121. package/src/resources/extensions/gsd/git-self-heal.ts +198 -0
  122. package/src/resources/extensions/gsd/git-service.ts +11 -0
  123. package/src/resources/extensions/gsd/guided-flow.ts +81 -9
  124. package/src/resources/extensions/gsd/post-unit-hooks.ts +449 -0
  125. package/src/resources/extensions/gsd/preferences.ts +209 -1
  126. package/src/resources/extensions/gsd/prompt-loader.ts +28 -1
  127. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  128. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -3
  129. package/src/resources/extensions/gsd/prompts/discuss.md +10 -8
  130. package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
  131. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +3 -1
  132. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +3 -1
  133. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +3 -1
  134. package/src/resources/extensions/gsd/prompts/guided-execute-task.md +3 -1
  135. package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +4 -2
  136. package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +3 -1
  137. package/src/resources/extensions/gsd/prompts/guided-research-slice.md +3 -1
  138. package/src/resources/extensions/gsd/prompts/plan-milestone.md +9 -12
  139. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -3
  140. package/src/resources/extensions/gsd/prompts/queue.md +3 -1
  141. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  142. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  143. package/src/resources/extensions/gsd/prompts/system.md +32 -29
  144. package/src/resources/extensions/gsd/templates/context.md +1 -1
  145. package/src/resources/extensions/gsd/templates/state.md +3 -3
  146. package/src/resources/extensions/gsd/tests/auto-worktree-merge.test.ts +282 -0
  147. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +259 -0
  148. package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +147 -0
  149. package/src/resources/extensions/gsd/tests/doctor-git.test.ts +246 -0
  150. package/src/resources/extensions/gsd/tests/doctor.test.ts +115 -1
  151. package/src/resources/extensions/gsd/tests/git-self-heal.test.ts +234 -0
  152. package/src/resources/extensions/gsd/tests/isolation-resolver.test.ts +107 -0
  153. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +297 -0
  154. package/src/resources/extensions/gsd/tests/preferences-git.test.ts +88 -0
  155. package/src/resources/extensions/gsd/tests/preferences-hooks.test.ts +226 -0
  156. package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +12 -0
  157. package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +315 -0
  158. package/src/resources/extensions/gsd/types.ts +109 -0
  159. package/src/resources/extensions/gsd/worktree-manager.ts +6 -4
  160. package/src/resources/extensions/search-the-web/command-search-provider.ts +8 -4
  161. package/src/resources/extensions/search-the-web/native-search.ts +15 -10
  162. package/src/resources/extensions/search-the-web/provider.ts +19 -2
  163. package/src/resources/extensions/search-the-web/tool-fetch-page.ts +62 -0
  164. package/src/resources/extensions/search-the-web/tool-llm-context.ts +62 -3
  165. package/src/resources/extensions/search-the-web/tool-search.ts +62 -3
@@ -3,6 +3,7 @@ import { homedir } from "node:os";
3
3
  import { isAbsolute, join } from "node:path";
4
4
  import { getAgentDir } from "@gsd/pi-coding-agent";
5
5
  import type { GitPreferences } from "./git-service.js";
6
+ import type { PostUnitHookConfig, PreDispatchHookConfig } from "./types.js";
6
7
  import { VALID_BRANCH_NAME } from "./git-service.js";
7
8
 
8
9
  const GLOBAL_PREFERENCES_PATH = join(homedir(), ".gsd", "preferences.md");
@@ -93,6 +94,8 @@ export interface GSDPreferences {
93
94
  budget_ceiling?: number;
94
95
  remote_questions?: RemoteQuestionsConfig;
95
96
  git?: GitPreferences;
97
+ post_unit_hooks?: PostUnitHookConfig[];
98
+ pre_dispatch_hooks?: PreDispatchHookConfig[];
96
99
  }
97
100
 
98
101
  export interface LoadedGSDPreferences {
@@ -626,10 +629,12 @@ function mergePreferences(base: GSDPreferences, override: GSDPreferences): GSDPr
626
629
  git: (base.git || override.git)
627
630
  ? { ...(base.git ?? {}), ...(override.git ?? {}) }
628
631
  : undefined,
632
+ post_unit_hooks: mergePostUnitHooks(base.post_unit_hooks, override.post_unit_hooks),
633
+ pre_dispatch_hooks: mergePreDispatchHooks(base.pre_dispatch_hooks, override.pre_dispatch_hooks),
629
634
  };
630
635
  }
631
636
 
632
- function validatePreferences(preferences: GSDPreferences): {
637
+ export function validatePreferences(preferences: GSDPreferences): {
633
638
  preferences: GSDPreferences;
634
639
  errors: string[];
635
640
  } {
@@ -713,6 +718,138 @@ function validatePreferences(preferences: GSDPreferences): {
713
718
  }
714
719
  }
715
720
 
721
+ // ─── Post-Unit Hooks ─────────────────────────────────────────────────
722
+ if (preferences.post_unit_hooks && Array.isArray(preferences.post_unit_hooks)) {
723
+ const validHooks: PostUnitHookConfig[] = [];
724
+ const seenNames = new Set<string>();
725
+ const knownUnitTypes = new Set([
726
+ "research-milestone", "plan-milestone", "research-slice", "plan-slice",
727
+ "execute-task", "complete-slice", "replan-slice", "reassess-roadmap",
728
+ "run-uat", "fix-merge", "complete-milestone",
729
+ ]);
730
+ for (const hook of preferences.post_unit_hooks) {
731
+ if (!hook || typeof hook !== "object") {
732
+ errors.push("post_unit_hooks entry must be an object");
733
+ continue;
734
+ }
735
+ const name = typeof hook.name === "string" ? hook.name.trim() : "";
736
+ if (!name) {
737
+ errors.push("post_unit_hooks entry missing name");
738
+ continue;
739
+ }
740
+ if (seenNames.has(name)) {
741
+ errors.push(`duplicate post_unit_hooks name: ${name}`);
742
+ continue;
743
+ }
744
+ const after = normalizeStringList(hook.after);
745
+ if (after.length === 0) {
746
+ errors.push(`post_unit_hooks "${name}" missing after`);
747
+ continue;
748
+ }
749
+ for (const ut of after) {
750
+ if (!knownUnitTypes.has(ut)) {
751
+ errors.push(`post_unit_hooks "${name}" unknown unit type in after: ${ut}`);
752
+ }
753
+ }
754
+ const prompt = typeof hook.prompt === "string" ? hook.prompt.trim() : "";
755
+ if (!prompt) {
756
+ errors.push(`post_unit_hooks "${name}" missing prompt`);
757
+ continue;
758
+ }
759
+ const validHook: PostUnitHookConfig = { name, after, prompt };
760
+ if (hook.max_cycles !== undefined) {
761
+ const mc = typeof hook.max_cycles === "number" ? hook.max_cycles : Number(hook.max_cycles);
762
+ validHook.max_cycles = Number.isFinite(mc) ? Math.max(1, Math.min(10, Math.round(mc))) : 1;
763
+ }
764
+ if (typeof hook.model === "string" && hook.model.trim()) {
765
+ validHook.model = hook.model.trim();
766
+ }
767
+ if (typeof hook.artifact === "string" && hook.artifact.trim()) {
768
+ validHook.artifact = hook.artifact.trim();
769
+ }
770
+ if (typeof hook.retry_on === "string" && hook.retry_on.trim()) {
771
+ validHook.retry_on = hook.retry_on.trim();
772
+ }
773
+ if (typeof hook.agent === "string" && hook.agent.trim()) {
774
+ validHook.agent = hook.agent.trim();
775
+ }
776
+ if (hook.enabled !== undefined) {
777
+ validHook.enabled = !!hook.enabled;
778
+ }
779
+ seenNames.add(name);
780
+ validHooks.push(validHook);
781
+ }
782
+ if (validHooks.length > 0) {
783
+ validated.post_unit_hooks = validHooks;
784
+ }
785
+ }
786
+
787
+ // ─── Pre-Dispatch Hooks ─────────────────────────────────────────────────
788
+ if (preferences.pre_dispatch_hooks && Array.isArray(preferences.pre_dispatch_hooks)) {
789
+ const validPreHooks: PreDispatchHookConfig[] = [];
790
+ const seenPreNames = new Set<string>();
791
+ const knownUnitTypes = new Set([
792
+ "research-milestone", "plan-milestone", "research-slice", "plan-slice",
793
+ "execute-task", "complete-slice", "replan-slice", "reassess-roadmap",
794
+ "run-uat", "fix-merge", "complete-milestone",
795
+ ]);
796
+ const validActions = new Set(["modify", "skip", "replace"]);
797
+ for (const hook of preferences.pre_dispatch_hooks) {
798
+ if (!hook || typeof hook !== "object") {
799
+ errors.push("pre_dispatch_hooks entry must be an object");
800
+ continue;
801
+ }
802
+ const name = typeof hook.name === "string" ? hook.name.trim() : "";
803
+ if (!name) {
804
+ errors.push("pre_dispatch_hooks entry missing name");
805
+ continue;
806
+ }
807
+ if (seenPreNames.has(name)) {
808
+ errors.push(`duplicate pre_dispatch_hooks name: ${name}`);
809
+ continue;
810
+ }
811
+ const before = normalizeStringList(hook.before);
812
+ if (before.length === 0) {
813
+ errors.push(`pre_dispatch_hooks "${name}" missing before`);
814
+ continue;
815
+ }
816
+ for (const ut of before) {
817
+ if (!knownUnitTypes.has(ut)) {
818
+ errors.push(`pre_dispatch_hooks "${name}" unknown unit type in before: ${ut}`);
819
+ }
820
+ }
821
+ const action = typeof hook.action === "string" ? hook.action.trim() : "";
822
+ if (!validActions.has(action)) {
823
+ errors.push(`pre_dispatch_hooks "${name}" invalid action: ${action} (must be modify, skip, or replace)`);
824
+ continue;
825
+ }
826
+ const validHook: PreDispatchHookConfig = { name, before, action: action as PreDispatchHookConfig["action"] };
827
+ if (typeof hook.prepend === "string" && hook.prepend.trim()) validHook.prepend = hook.prepend.trim();
828
+ if (typeof hook.append === "string" && hook.append.trim()) validHook.append = hook.append.trim();
829
+ if (typeof hook.prompt === "string" && hook.prompt.trim()) validHook.prompt = hook.prompt.trim();
830
+ if (typeof hook.unit_type === "string" && hook.unit_type.trim()) validHook.unit_type = hook.unit_type.trim();
831
+ if (typeof hook.skip_if === "string" && hook.skip_if.trim()) validHook.skip_if = hook.skip_if.trim();
832
+ if (typeof hook.model === "string" && hook.model.trim()) validHook.model = hook.model.trim();
833
+ if (hook.enabled !== undefined) validHook.enabled = !!hook.enabled;
834
+
835
+ // Validation: action-specific required fields
836
+ if (action === "replace" && !validHook.prompt) {
837
+ errors.push(`pre_dispatch_hooks "${name}" action "replace" requires prompt`);
838
+ continue;
839
+ }
840
+ if (action === "modify" && !validHook.prepend && !validHook.append) {
841
+ errors.push(`pre_dispatch_hooks "${name}" action "modify" requires prepend or append`);
842
+ continue;
843
+ }
844
+
845
+ seenPreNames.add(name);
846
+ validPreHooks.push(validHook);
847
+ }
848
+ if (validPreHooks.length > 0) {
849
+ validated.pre_dispatch_hooks = validPreHooks;
850
+ }
851
+ }
852
+
716
853
  // ─── Git Preferences ───────────────────────────────────────────────────
717
854
  if (preferences.git && typeof preferences.git === "object") {
718
855
  const git: Record<string, unknown> = {};
@@ -768,6 +905,22 @@ function validatePreferences(preferences: GSDPreferences): {
768
905
  errors.push("git.main_branch must be a valid branch name (alphanumeric, _, -, /, .)");
769
906
  }
770
907
  }
908
+ if (g.isolation !== undefined) {
909
+ const validIsolation = new Set(["worktree", "branch"]);
910
+ if (typeof g.isolation === "string" && validIsolation.has(g.isolation)) {
911
+ git.isolation = g.isolation as "worktree" | "branch";
912
+ } else {
913
+ errors.push("git.isolation must be one of: worktree, branch");
914
+ }
915
+ }
916
+ if (g.merge_to_main !== undefined) {
917
+ const validMergeToMain = new Set(["milestone", "slice"]);
918
+ if (typeof g.merge_to_main === "string" && validMergeToMain.has(g.merge_to_main)) {
919
+ git.merge_to_main = g.merge_to_main as "milestone" | "slice";
920
+ } else {
921
+ errors.push("git.merge_to_main must be one of: milestone, slice");
922
+ }
923
+ }
771
924
 
772
925
  if (Object.keys(git).length > 0) {
773
926
  validated.git = git as GitPreferences;
@@ -794,3 +947,58 @@ function normalizeStringList(value: unknown): string[] {
794
947
  .map((item) => item.trim())
795
948
  .filter(Boolean);
796
949
  }
950
+
951
+ function mergePostUnitHooks(
952
+ base?: PostUnitHookConfig[],
953
+ override?: PostUnitHookConfig[],
954
+ ): PostUnitHookConfig[] | undefined {
955
+ if (!base?.length && !override?.length) return undefined;
956
+ const merged = [...(base ?? [])];
957
+ for (const hook of override ?? []) {
958
+ // Override hooks with same name replace base hooks
959
+ const idx = merged.findIndex(h => h.name === hook.name);
960
+ if (idx >= 0) {
961
+ merged[idx] = hook;
962
+ } else {
963
+ merged.push(hook);
964
+ }
965
+ }
966
+ return merged.length > 0 ? merged : undefined;
967
+ }
968
+
969
+ /**
970
+ * Resolve enabled post-unit hooks from effective preferences.
971
+ * Returns an empty array when no hooks are configured.
972
+ */
973
+ export function resolvePostUnitHooks(): PostUnitHookConfig[] {
974
+ const prefs = loadEffectiveGSDPreferences();
975
+ return (prefs?.preferences.post_unit_hooks ?? [])
976
+ .filter(h => h.enabled !== false);
977
+ }
978
+
979
+ function mergePreDispatchHooks(
980
+ base?: PreDispatchHookConfig[],
981
+ override?: PreDispatchHookConfig[],
982
+ ): PreDispatchHookConfig[] | undefined {
983
+ if (!base?.length && !override?.length) return undefined;
984
+ const merged = [...(base ?? [])];
985
+ for (const hook of override ?? []) {
986
+ const idx = merged.findIndex(h => h.name === hook.name);
987
+ if (idx >= 0) {
988
+ merged[idx] = hook;
989
+ } else {
990
+ merged.push(hook);
991
+ }
992
+ }
993
+ return merged.length > 0 ? merged : undefined;
994
+ }
995
+
996
+ /**
997
+ * Resolve enabled pre-dispatch hooks from effective preferences.
998
+ * Returns an empty array when no hooks are configured.
999
+ */
1000
+ export function resolvePreDispatchHooks(): PreDispatchHookConfig[] {
1001
+ const prefs = loadEffectiveGSDPreferences();
1002
+ return (prefs?.preferences.pre_dispatch_hooks ?? [])
1003
+ .filter(h => h.enabled !== false);
1004
+ }
@@ -19,7 +19,9 @@ import { readFileSync } from "node:fs";
19
19
  import { join, dirname } from "node:path";
20
20
  import { fileURLToPath } from "node:url";
21
21
 
22
- const promptsDir = join(dirname(fileURLToPath(import.meta.url)), "prompts");
22
+ const __extensionDir = dirname(fileURLToPath(import.meta.url));
23
+ const promptsDir = join(__extensionDir, "prompts");
24
+ const templatesDir = join(__extensionDir, "templates");
23
25
 
24
26
  // Cache templates on first read — a running session uses the template versions
25
27
  // that were on disk when it first loaded them, immune to later overwrites.
@@ -63,3 +65,28 @@ export function loadPrompt(name: string, vars: Record<string, string> = {}): str
63
65
 
64
66
  return content.trim();
65
67
  }
68
+
69
+ /**
70
+ * Load a raw template file from the templates/ directory.
71
+ * Cached with a `tpl:` prefix to avoid collisions with prompt cache keys.
72
+ */
73
+ export function loadTemplate(name: string): string {
74
+ const cacheKey = `tpl:${name}`;
75
+ let content = templateCache.get(cacheKey);
76
+ if (content === undefined) {
77
+ const path = join(templatesDir, `${name}.md`);
78
+ content = readFileSync(path, "utf-8");
79
+ templateCache.set(cacheKey, content);
80
+ }
81
+ return content.trim();
82
+ }
83
+
84
+ /**
85
+ * Load a template and wrap it with a labeled footer for inlining into prompts.
86
+ * The template body is emitted first so that any YAML frontmatter (---) remains
87
+ * at the first non-whitespace line of the template content.
88
+ */
89
+ export function inlineTemplate(name: string, label: string): string {
90
+ const content = loadTemplate(name);
91
+ return `${content}\n\n### Output Template: ${label}\nSource: \`templates/${name}.md\``;
92
+ }
@@ -7,7 +7,7 @@ All relevant context has been preloaded below — the roadmap, all slice summari
7
7
  {{inlinedContext}}
8
8
 
9
9
  Then:
10
- 1. Read the milestone-summary template at `~/.gsd/agent/extensions/gsd/templates/milestone-summary.md`
10
+ 1. Use the **Milestone Summary** output template from the inlined context above
11
11
  2. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow during completion, without relaxing required verification or artifact rules
12
12
  3. Verify each **success criterion** from the milestone definition in `{{roadmapPath}}`. For each criterion, confirm it was met with specific evidence from slice summaries, test results, or observable behavior. List any criterion that was NOT met.
13
13
  4. Verify the milestone's **definition of done** — all slices are `[x]`, all slice summaries exist, and any cross-slice integration points work correctly.
@@ -9,9 +9,7 @@ All relevant context has been preloaded below — the slice plan, all task summa
9
9
  **Match effort to complexity.** A simple slice with 1-2 tasks needs a brief summary and lightweight verification. A complex slice with 5 tasks across multiple subsystems needs thorough verification and a detailed summary. Scale the work below accordingly.
10
10
 
11
11
  Then:
12
- 1. Read the templates:
13
- - `~/.gsd/agent/extensions/gsd/templates/slice-summary.md`
14
- - `~/.gsd/agent/extensions/gsd/templates/uat.md`
12
+ 1. Use the **Slice Summary** and **UAT** output templates from the inlined context above
15
13
  2. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow during completion, without relaxing required verification or artifact rules
16
14
  3. Run all slice-level verification checks defined in the slice plan. All must pass before marking the slice done. If any fail, fix them first.
17
15
  4. If the slice plan includes observability/diagnostic surfaces, confirm they work. Skip this for simple slices that don't have observability sections.
@@ -186,14 +186,14 @@ Directories use bare IDs. Files use ID-SUFFIX format. Titles live inside file co
186
186
 
187
187
  Once the user is satisfied, in a single pass:
188
188
  1. `mkdir -p .gsd/milestones/{{milestoneId}}/slices`
189
- 2. Write or update `.gsd/PROJECT.md` — read the template at `~/.gsd/agent/extensions/gsd/templates/project.md` first. Describe what the project is, its current state, and list the milestone sequence.
190
- 3. Write or update `.gsd/REQUIREMENTS.md` — read the template at `~/.gsd/agent/extensions/gsd/templates/requirements.md` first. Confirm requirement states, ownership, and traceability before roadmap creation.
189
+ 2. Write or update `.gsd/PROJECT.md` — use the **Project** output template below. Describe what the project is, its current state, and list the milestone sequence.
190
+ 3. Write or update `.gsd/REQUIREMENTS.md` — use the **Requirements** output template below. Confirm requirement states, ownership, and traceability before roadmap creation.
191
191
  **Depth-Preservation Guidance for context.md:**
192
192
  When writing context.md, preserve the user's exact terminology, emphasis, and specific framing from the discussion. Do not paraphrase user nuance into generic summaries. If the user said "craft feel," write "craft feel" — not "high-quality user experience." If they emphasized a specific constraint or negative requirement, carry that emphasis through verbatim. The context file is downstream agents' only window into this conversation — flattening specifics into generics loses the signal that shaped every decision.
193
193
 
194
- 4. Write `{{contextPath}}` — read the template at `~/.gsd/agent/extensions/gsd/templates/context.md` first. Preserve key risks, unknowns, existing codebase constraints, integration points, and relevant requirements surfaced during discussion.
195
- 5. Write `{{roadmapPath}}` — read the template at `~/.gsd/agent/extensions/gsd/templates/roadmap.md` first. Decompose into demoable vertical slices with checkboxes, risk, depends, demo sentences, proof strategy, verification classes, milestone definition of done, requirement coverage, and a boundary map. If the milestone crosses multiple runtime boundaries, include an explicit final integration slice that proves the assembled system works end-to-end in a real environment.
196
- 6. Seed `.gsd/DECISIONS.md` — read the template at `~/.gsd/agent/extensions/gsd/templates/decisions.md` first. Append rows for any architectural or pattern decisions made during discussion.
194
+ 4. Write `{{contextPath}}` — use the **Context** output template below. Preserve key risks, unknowns, existing codebase constraints, integration points, and relevant requirements surfaced during discussion.
195
+ 5. Write `{{roadmapPath}}` — use the **Roadmap** output template below. Decompose into demoable vertical slices with checkboxes, risk, depends, demo sentences, proof strategy, verification classes, milestone definition of done, requirement coverage, and a boundary map. If the milestone crosses multiple runtime boundaries, include an explicit final integration slice that proves the assembled system works end-to-end in a real environment.
196
+ 6. Seed `.gsd/DECISIONS.md` — use the **Decisions** output template below. Append rows for any architectural or pattern decisions made during discussion.
197
197
  7. Update `.gsd/STATE.md`
198
198
  8. Commit: `docs({{milestoneId}}): context, requirements, and roadmap`
199
199
 
@@ -206,9 +206,9 @@ Once the user confirms the milestone split:
206
206
  #### Phase 1: Shared artifacts
207
207
 
208
208
  1. `mkdir -p .gsd/milestones/{{milestoneId}}/slices` for each milestone
209
- 2. Write `.gsd/PROJECT.md` — read the template at `~/.gsd/agent/extensions/gsd/templates/project.md` first.
210
- 3. Write `.gsd/REQUIREMENTS.md` — read the template at `~/.gsd/agent/extensions/gsd/templates/requirements.md` first. Capture Active, Deferred, Out of Scope, and any already Validated requirements. Later milestones may have provisional ownership where slice plans do not exist yet.
211
- 4. Seed `.gsd/DECISIONS.md` — read the template at `~/.gsd/agent/extensions/gsd/templates/decisions.md` first.
209
+ 2. Write `.gsd/PROJECT.md` — use the **Project** output template below.
210
+ 3. Write `.gsd/REQUIREMENTS.md` — use the **Requirements** output template below. Capture Active, Deferred, Out of Scope, and any already Validated requirements. Later milestones may have provisional ownership where slice plans do not exist yet.
211
+ 4. Seed `.gsd/DECISIONS.md` — use the **Decisions** output template below.
212
212
 
213
213
  #### Phase 2: Primary milestone
214
214
 
@@ -233,3 +233,5 @@ Each context file (full or draft) should be rich enough that a future agent enco
233
233
  8. Commit: `docs: project plan — N milestones` (replace N with the actual milestone count)
234
234
 
235
235
  After writing the files and committing, say exactly: "Milestone M001 ready." — nothing else. Auto-mode will start automatically.
236
+
237
+ {{inlinedTemplates}}
@@ -47,8 +47,8 @@ Then:
47
47
  - Know when to stop. If you've tried 3+ fixes without progress, your mental model is probably wrong. Stop. List what you know for certain. List what you've ruled out. Form fresh hypotheses from there.
48
48
  - Don't fix symptoms. Understand *why* something fails before changing code. A test that passes after a change you don't understand is luck, not a fix.
49
49
  11. **Blocker discovery:** If execution reveals that the remaining slice plan is fundamentally invalid — not just a bug or minor deviation, but a plan-invalidating finding like a wrong API, missing capability, or architectural mismatch — set `blocker_discovered: true` in the task summary frontmatter and describe the blocker clearly in the summary narrative. Do NOT set `blocker_discovered: true` for ordinary debugging, minor deviations, or issues that can be fixed within the current task or the remaining plan. This flag triggers an automatic replan of the slice.
50
- 12. If you made an architectural, pattern, library, or observability decision during this task that downstream work should know about, append it to `.gsd/DECISIONS.md` (read the template at `~/.gsd/agent/extensions/gsd/templates/decisions.md` if the file doesn't exist yet). Not every task produces decisions — only append when a meaningful choice was made.
51
- 13. Read the template at `~/.gsd/agent/extensions/gsd/templates/task-summary.md`
50
+ 12. If you made an architectural, pattern, library, or observability decision during this task that downstream work should know about, append it to `.gsd/DECISIONS.md` (use the **Decisions** output template from the inlined templates below if the file doesn't exist yet). Not every task produces decisions — only append when a meaningful choice was made.
51
+ 13. Use the **Task Summary** output template from the inlined templates below
52
52
  14. Write `{{taskSummaryPath}}`
53
53
  15. Mark {{taskId}} done in `{{planPath}}` (change `[ ]` to `[x]`)
54
54
  16. Do not commit manually — the system auto-commits your changes after this unit completes.
@@ -58,4 +58,6 @@ You are on the slice branch. All work stays here.
58
58
 
59
59
  **You MUST mark {{taskId}} as `[x]` in `{{planPath}}` AND write `{{taskSummaryPath}}` before finishing.**
60
60
 
61
+ {{inlinedTemplates}}
62
+
61
63
  When done, say: "Task {{taskId}} complete."
@@ -1 +1,3 @@
1
- Complete slice {{sliceId}} ("{{sliceTitle}}") of milestone {{milestoneId}}. All tasks are done. Read the templates at `~/.gsd/agent/extensions/gsd/templates/slice-summary.md` and `uat.md`. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow during completion, without relaxing required verification or artifact rules. Write `{{sliceId}}-SUMMARY.md` (compress task summaries), write `{{sliceId}}-UAT.md`, and fill the `UAT Type` plus `Not Proven By This UAT` sections explicitly so the artifact states what class of acceptance it covers and what still remains unproven. Review task summaries for `key_decisions` and ensure any significant ones are in `.gsd/DECISIONS.md`. Mark the slice checkbox done in the roadmap, update STATE.md, update milestone summary, and leave the slice branch clean for the extension to squash-merge back into the integration branch automatically.
1
+ Complete slice {{sliceId}} ("{{sliceTitle}}") of milestone {{milestoneId}}. All tasks are done. Use the **Slice Summary** and **UAT** output templates below. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow during completion, without relaxing required verification or artifact rules. Write `{{sliceId}}-SUMMARY.md` (compress task summaries), write `{{sliceId}}-UAT.md`, and fill the `UAT Type` plus `Not Proven By This UAT` sections explicitly so the artifact states what class of acceptance it covers and what still remains unproven. Review task summaries for `key_decisions` and ensure any significant ones are in `.gsd/DECISIONS.md`. Mark the slice checkbox done in the roadmap, update STATE.md, update milestone summary, and leave the slice branch clean for the extension to squash-merge back into the integration branch automatically.
2
+
3
+ {{inlinedTemplates}}
@@ -1,3 +1,5 @@
1
- Discuss milestone {{milestoneId}} ("{{milestoneTitle}}"). Identify gray areas, ask the user about them, and write `{{milestoneId}}-CONTEXT.md` in the milestone directory with the decisions. Read the template at `~/.gsd/agent/extensions/gsd/templates/context.md` first. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow; do not override required artifact rules.
1
+ Discuss milestone {{milestoneId}} ("{{milestoneTitle}}"). Identify gray areas, ask the user about them, and write `{{milestoneId}}-CONTEXT.md` in the milestone directory with the decisions. Use the **Context** output template below. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow; do not override required artifact rules.
2
+
3
+ {{inlinedTemplates}}
2
4
 
3
5
  **Investigate between question rounds to make your questions smarter.** Before each round of questions, do enough lightweight research that your questions are grounded in reality — not guesses about what exists or what's possible. Check library docs (`resolve_library`/`get_library_docs`) when tech choices are relevant, search the web (`search-the-web` with `freshness`/`domain` filters, then `fetch_page` for full content) to verify the landscape, scout the codebase (`rg`, `find`, `scout`) to understand what already exists. Don't go deep — just enough that your next question reflects what's actually true. The goal is to ask questions the user can't answer by saying "did you check the docs?" or "look at the code."
@@ -45,7 +45,7 @@ If the user wants to keep going, keep asking. Stop when they say wrap up.
45
45
 
46
46
  Once the user is ready to wrap up:
47
47
 
48
- 1. Read the slice context template at `~/.gsd/agent/extensions/gsd/templates/slice-context.md`
48
+ 1. Use the **Slice Context** output template below
49
49
  2. `mkdir -p {{sliceDirPath}}`
50
50
  3. Write `{{contextPath}}` — use the template structure, filling in:
51
51
  - **Goal** — one sentence: what this slice delivers
@@ -57,3 +57,5 @@ Once the user is ready to wrap up:
57
57
  - **Open Questions** — anything still unresolved, with current thinking
58
58
  4. Commit: `git -C {{projectRoot}} add {{contextPath}} && git -C {{projectRoot}} commit -m "docs({{milestoneId}}/{{sliceId}}): slice context from discuss"`
59
59
  5. Say exactly: `"{{sliceId}} context written."` — nothing else.
60
+
61
+ {{inlinedTemplates}}
@@ -1 +1,3 @@
1
- Execute the next task: {{taskId}} ("{{taskTitle}}") in slice {{sliceId}} of milestone {{milestoneId}}. Read the task plan (`{{taskId}}-PLAN.md`), load relevant summaries from prior tasks, and execute each step. Verify must-haves when done. If the task touches UI, browser flows, DOM behavior, or user-visible web state, exercise the real flow in the browser, prefer `browser_batch` for obvious sequences, prefer `browser_assert` for explicit pass/fail verification, use `browser_diff` when an action's effect is ambiguous, and use browser diagnostics when validating async or failure-prone UI. If you made an architectural, pattern, or library decision, append it to `.gsd/DECISIONS.md`. Read the template at `~/.gsd/agent/extensions/gsd/templates/task-summary.md`. Write `{{taskId}}-SUMMARY.md`, mark it done, commit, and advance. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow during execution, without relaxing required verification or artifact rules. If running long and not all steps are finished, stop implementing and prioritize writing a clean partial summary over attempting one more step — a recoverable handoff is more valuable than a half-finished step with no documentation. If verification fails, debug methodically: form a hypothesis and test that specific theory before changing anything, change one variable at a time, read entire functions not just the suspect line, distinguish observable facts from assumptions, and if 3+ fixes fail without progress stop and reassess your mental model — list what you know for certain, what you've ruled out, and form fresh hypotheses. Don't fix symptoms — understand why something fails before changing code.
1
+ Execute the next task: {{taskId}} ("{{taskTitle}}") in slice {{sliceId}} of milestone {{milestoneId}}. Read the task plan (`{{taskId}}-PLAN.md`), load relevant summaries from prior tasks, and execute each step. Verify must-haves when done. If the task touches UI, browser flows, DOM behavior, or user-visible web state, exercise the real flow in the browser, prefer `browser_batch` for obvious sequences, prefer `browser_assert` for explicit pass/fail verification, use `browser_diff` when an action's effect is ambiguous, and use browser diagnostics when validating async or failure-prone UI. If you made an architectural, pattern, or library decision, append it to `.gsd/DECISIONS.md`. Use the **Task Summary** output template below. Write `{{taskId}}-SUMMARY.md`, mark it done, commit, and advance. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow during execution, without relaxing required verification or artifact rules. If running long and not all steps are finished, stop implementing and prioritize writing a clean partial summary over attempting one more step — a recoverable handoff is more valuable than a half-finished step with no documentation. If verification fails, debug methodically: form a hypothesis and test that specific theory before changing anything, change one variable at a time, read entire functions not just the suspect line, distinguish observable facts from assumptions, and if 3+ fixes fail without progress stop and reassess your mental model — list what you know for certain, what you've ruled out, and form fresh hypotheses. Don't fix symptoms — understand why something fails before changing code.
2
+
3
+ {{inlinedTemplates}}
@@ -1,4 +1,4 @@
1
- Plan milestone {{milestoneId}} ("{{milestoneTitle}}"). Read `.gsd/DECISIONS.md` if it exists — respect existing decisions. Read `.gsd/REQUIREMENTS.md` if it exists and treat Active requirements as the capability contract. If `REQUIREMENTS.md` is missing, continue in legacy compatibility mode but explicitly note missing requirement coverage. Read the template at `~/.gsd/agent/extensions/gsd/templates/roadmap.md`. Create `{{milestoneId}}-ROADMAP.md` in the milestone directory with slices, risk levels, dependencies, demo sentences, verification classes, milestone definition of done, requirement coverage, and a boundary map. Write success criteria as observable truths, not implementation tasks. If the milestone crosses multiple runtime boundaries, include an explicit final integration slice that proves the assembled system works end-to-end in a real environment. If planning produces structural decisions, append them to `.gsd/DECISIONS.md`. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow during planning, without overriding required roadmap formatting.
1
+ Plan milestone {{milestoneId}} ("{{milestoneTitle}}"). Read `.gsd/DECISIONS.md` if it exists — respect existing decisions. Read `.gsd/REQUIREMENTS.md` if it exists and treat Active requirements as the capability contract. If `REQUIREMENTS.md` is missing, continue in legacy compatibility mode but explicitly note missing requirement coverage. Use the **Roadmap** output template below. Create `{{milestoneId}}-ROADMAP.md` in the milestone directory with slices, risk levels, dependencies, demo sentences, verification classes, milestone definition of done, requirement coverage, and a boundary map. Write success criteria as observable truths, not implementation tasks. If the milestone crosses multiple runtime boundaries, include an explicit final integration slice that proves the assembled system works end-to-end in a real environment. If planning produces structural decisions, append them to `.gsd/DECISIONS.md`. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow during planning, without overriding required roadmap formatting.
2
2
 
3
3
  ## Requirement Rules
4
4
 
@@ -24,4 +24,6 @@ Plan milestone {{milestoneId}} ("{{milestoneTitle}}"). Read `.gsd/DECISIONS.md`
24
24
 
25
25
  ## Secret Forecasting
26
26
 
27
- After writing the roadmap, analyze the slices and their boundary maps for external service dependencies (third-party APIs, SaaS platforms, cloud providers, databases requiring credentials, OAuth providers, etc.). If this milestone requires any external API keys or secrets, read the template at `~/.gsd/agent/extensions/gsd/templates/secrets-manifest.md` for the expected format and write `{{secretsOutputPath}}` listing every predicted secret as an H3 section with the Service name, a direct Dashboard URL to the console page where the key is created, a Format hint showing what the key looks like, Status set to `pending`, and Destination (`dotenv`, `vercel`, or `convex`). Include numbered step-by-step guidance for obtaining each key. If this milestone does not require any external API keys or secrets, skip this step entirely — do not create an empty manifest.
27
+ After writing the roadmap, analyze the slices and their boundary maps for external service dependencies (third-party APIs, SaaS platforms, cloud providers, databases requiring credentials, OAuth providers, etc.). If this milestone requires any external API keys or secrets, use the **Secrets Manifest** output template below for the expected format and write `{{secretsOutputPath}}` listing every predicted secret as an H3 section with the Service name, a direct Dashboard URL to the console page where the key is created, a Format hint showing what the key looks like, Status set to `pending`, and Destination (`dotenv`, `vercel`, or `convex`). Include numbered step-by-step guidance for obtaining each key. If this milestone does not require any external API keys or secrets, skip this step entirely — do not create an empty manifest.
28
+
29
+ {{inlinedTemplates}}
@@ -1 +1,3 @@
1
- Plan slice {{sliceId}} ("{{sliceTitle}}") of milestone {{milestoneId}}. Read `.gsd/DECISIONS.md` if it exists — respect existing decisions. Read `.gsd/REQUIREMENTS.md` if it exists — identify which Active requirements the roadmap says this slice owns or supports, and ensure the plan delivers them. Read the roadmap boundary map, any existing context/research files, and dependency summaries. Read the templates at `~/.gsd/agent/extensions/gsd/templates/plan.md` and `task-plan.md`. Decompose into tasks with must-haves. Fill the `Proof Level` and `Integration Closure` sections truthfully so the plan says what class of proof this slice really delivers and what end-to-end wiring still remains. Write `{{sliceId}}-PLAN.md` and individual `T##-PLAN.md` files in the `tasks/` subdirectory. If planning produces structural decisions, append them to `.gsd/decisions.md`. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow during planning, without overriding required plan formatting. Before committing, self-audit the plan: every must-have maps to at least one task, every task has complete sections (steps, must-haves, verification, observability impact, inputs, and expected output), task ordering is consistent with no circular references, every pair of artifacts that must connect has an explicit wiring step, task scope targets 2–5 steps and 3–8 files (6–8 steps or 8–10 files — consider splitting; 10+ steps or 12+ files — must split), the plan honors locked decisions from context/research/decisions artifacts, the proof-level wording does not overclaim live integration if only fixture/contract proof is planned, every Active requirement this slice owns has at least one task with verification that proves it is met, and every task produces real user-facing progress — if the slice has a UI surface at least one task builds the real UI, if it has an API at least one task connects it to a real data source, and showing the completed result to a non-technical stakeholder would demonstrate real product progress rather than developer artifacts.
1
+ Plan slice {{sliceId}} ("{{sliceTitle}}") of milestone {{milestoneId}}. Read `.gsd/DECISIONS.md` if it exists — respect existing decisions. Read `.gsd/REQUIREMENTS.md` if it exists — identify which Active requirements the roadmap says this slice owns or supports, and ensure the plan delivers them. Read the roadmap boundary map, any existing context/research files, and dependency summaries. Use the **Slice Plan** and **Task Plan** output templates below. Decompose into tasks with must-haves. Fill the `Proof Level` and `Integration Closure` sections truthfully so the plan says what class of proof this slice really delivers and what end-to-end wiring still remains. Write `{{sliceId}}-PLAN.md` and individual `T##-PLAN.md` files in the `tasks/` subdirectory. If planning produces structural decisions, append them to `.gsd/DECISIONS.md`. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow during planning, without overriding required plan formatting. Before committing, self-audit the plan: every must-have maps to at least one task, every task has complete sections (steps, must-haves, verification, observability impact, inputs, and expected output), task ordering is consistent with no circular references, every pair of artifacts that must connect has an explicit wiring step, task scope targets 2–5 steps and 3–8 files (6–8 steps or 8–10 files — consider splitting; 10+ steps or 12+ files — must split), the plan honors locked decisions from context/research/decisions artifacts, the proof-level wording does not overclaim live integration if only fixture/contract proof is planned, every Active requirement this slice owns has at least one task with verification that proves it is met, and every task produces real user-facing progress — if the slice has a UI surface at least one task builds the real UI, if it has an API at least one task connects it to a real data source, and showing the completed result to a non-technical stakeholder would demonstrate real product progress rather than developer artifacts.
2
+
3
+ {{inlinedTemplates}}
@@ -1,4 +1,4 @@
1
- Research slice {{sliceId}} ("{{sliceTitle}}") of milestone {{milestoneId}}. Read `.gsd/DECISIONS.md` if it exists — respect existing decisions, don't contradict them. Read `.gsd/REQUIREMENTS.md` if it exists — identify which Active requirements this slice owns or supports and target research toward risks, unknowns, and constraints that could affect delivery of those requirements. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow during research, without relaxing required verification or artifact rules. Explore the relevant code — use `rg`/`find` for targeted reads, or `scout` if the area is broad or unfamiliar. Check libraries with `resolve_library`/`get_library_docs`. Read the template at `~/.gsd/agent/extensions/gsd/templates/research.md`. Write `{{sliceId}}-RESEARCH.md` in the slice directory with summary, don't-hand-roll, common pitfalls, and relevant code sections.
1
+ Research slice {{sliceId}} ("{{sliceTitle}}") of milestone {{milestoneId}}. Read `.gsd/DECISIONS.md` if it exists — respect existing decisions, don't contradict them. Read `.gsd/REQUIREMENTS.md` if it exists — identify which Active requirements this slice owns or supports and target research toward risks, unknowns, and constraints that could affect delivery of those requirements. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow during research, without relaxing required verification or artifact rules. Explore the relevant code — use `rg`/`find` for targeted reads, or `scout` if the area is broad or unfamiliar. Check libraries with `resolve_library`/`get_library_docs`. Use the **Research** output template below. Write `{{sliceId}}-RESEARCH.md` in the slice directory with summary, don't-hand-roll, common pitfalls, and relevant code sections.
2
2
 
3
3
  ## Strategic Questions to Answer
4
4
 
@@ -9,3 +9,5 @@ Research should drive planning decisions, not just collect facts. Explicitly add
9
9
  - **What boundary contracts matter?** What interfaces, data shapes, event formats, or invariants will slices need to agree on?
10
10
  - **What constraints does the existing codebase impose?** What can't be changed, what's expensive to change, what patterns must be respected?
11
11
  - **Are there known failure modes that should shape slice ordering?** Pitfalls that mean certain work should come before or after other work?
12
+
13
+ {{inlinedTemplates}}
@@ -9,14 +9,13 @@ All relevant context has been preloaded below — start working immediately with
9
9
  Narrate your decomposition reasoning — why you're grouping work this way, what risks are driving the order, what verification strategy you're choosing and why.
10
10
 
11
11
  Then:
12
- 1. Read the template at `~/.gsd/agent/extensions/gsd/templates/roadmap.md`
13
- 2. Read `.gsd/REQUIREMENTS.md` if it exists. Treat **Active** requirements as the capability contract for planning. If it does not exist, continue in legacy compatibility mode but explicitly note that requirement coverage is operating without a contract.
14
- 3. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow during planning, without overriding required roadmap formatting
15
- 4. Create the roadmap: decompose into demoable vertical slices — as many as the work genuinely needs, no more. A simple feature might be 1 slice. Don't decompose for decomposition's sake.
16
- 5. Order by risk (high-risk first)
17
- 6. Write `{{outputPath}}` with checkboxes, risk, depends, demo sentences, proof strategy, verification classes, milestone definition of done, **requirement coverage**, and a boundary map. Write success criteria as observable truths, not implementation tasks. If the milestone crosses multiple runtime boundaries, include an explicit final integration slice that proves the assembled system works end-to-end in a real environment
18
- 7. If planning produced structural decisions (e.g. slice ordering rationale, technology choices, scope exclusions), append them to `.gsd/DECISIONS.md` (read the template at `~/.gsd/agent/extensions/gsd/templates/decisions.md` if the file doesn't exist yet)
19
- 8. Update `.gsd/STATE.md`
12
+ 1. Use the **Roadmap** output template from the inlined context above
13
+ 2. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow during planning, without overriding required roadmap formatting
14
+ 3. Create the roadmap: decompose into demoable vertical slices as many as the work genuinely needs, no more. A simple feature might be 1 slice. Don't decompose for decomposition's sake.
15
+ 4. Order by risk (high-risk first)
16
+ 5. Write `{{outputPath}}` with checkboxes, risk, depends, demo sentences, proof strategy, verification classes, milestone definition of done, **requirement coverage**, and a boundary map. Write success criteria as observable truths, not implementation tasks. If the milestone crosses multiple runtime boundaries, include an explicit final integration slice that proves the assembled system works end-to-end in a real environment
17
+ 6. If planning produced structural decisions (e.g. slice ordering rationale, technology choices, scope exclusions), append them to `.gsd/DECISIONS.md` (use the **Decisions** output template from the inlined context above if the file doesn't exist yet)
18
+ 7. Update `.gsd/STATE.md`
20
19
 
21
20
  ## Requirement Mapping Rules
22
21
 
@@ -49,9 +48,7 @@ Apply these when decomposing and ordering slices:
49
48
 
50
49
  If the roadmap has only one slice, also write the slice plan and task plans inline during this unit — don't leave them for a separate planning session.
51
50
 
52
- 1. Read the templates:
53
- - `~/.gsd/agent/extensions/gsd/templates/plan.md`
54
- - `~/.gsd/agent/extensions/gsd/templates/task-plan.md`
51
+ 1. Use the **Slice Plan** and **Task Plan** output templates from the inlined context above
55
52
  2. `mkdir -p {{milestonePath}}/slices/S01/tasks`
56
53
  3. Write the S01 plan file at `{{milestonePath}}/slices/S01/S01-PLAN.md`
57
54
  4. Write individual task plans at `{{milestonePath}}/slices/S01/tasks/T01-PLAN.md`, etc.
@@ -65,7 +62,7 @@ After writing the roadmap, analyze the slices and their boundary maps for extern
65
62
 
66
63
  If this milestone requires any external API keys or secrets:
67
64
 
68
- 1. Read the template at `~/.gsd/agent/extensions/gsd/templates/secrets-manifest.md` for the expected format
65
+ 1. Use the **Secrets Manifest** output template from the inlined context above for the expected format
69
66
  2. Write `{{secretsOutputPath}}` listing every predicted secret as an H3 section with:
70
67
  - **Service** — the external service name
71
68
  - **Dashboard** — direct URL to the console/dashboard page where the key is created (not a generic homepage)
@@ -18,9 +18,7 @@ Narrate your decomposition reasoning — why you're grouping work this way, what
18
18
 
19
19
  Then:
20
20
  0. If `REQUIREMENTS.md` was preloaded above, identify which Active requirements the roadmap says this slice owns or supports. These are the requirements this plan must deliver — every owned requirement needs at least one task that directly advances it, and verification must prove the requirement is met.
21
- 1. Read the templates:
22
- - `~/.gsd/agent/extensions/gsd/templates/plan.md`
23
- - `~/.gsd/agent/extensions/gsd/templates/task-plan.md`
21
+ 1. Use the **Slice Plan** and **Task Plan** output templates from the inlined context above
24
22
  2. If a `GSD Skill Preferences` block is present in system context, use it to decide which skills to load and follow during planning, without overriding required plan formatting
25
23
  3. Define slice-level verification — the objective stopping condition for this slice:
26
24
  - For non-trivial slices: plan actual test files with real assertions. Name the files.
@@ -82,7 +82,7 @@ Determine where the new milestones should go in the overall sequence. Consider d
82
82
  Once the user is satisfied, in a single pass for **each** new milestone (starting from {{nextId}}):
83
83
 
84
84
  1. `mkdir -p .gsd/milestones/<ID>/slices`
85
- 2. Write `.gsd/milestones/<ID>/<ID>-CONTEXT.md` — read the template at `~/.gsd/agent/extensions/gsd/templates/context.md` first. Capture intent, scope, risks, constraints, integration points, and relevant requirements. Mark the status as "Queued — pending auto-mode execution."
85
+ 2. Write `.gsd/milestones/<ID>/<ID>-CONTEXT.md` — use the **Context** output template below. Capture intent, scope, risks, constraints, integration points, and relevant requirements. Mark the status as "Queued — pending auto-mode execution."
86
86
 
87
87
  Then, after all milestone directories and context files are written:
88
88
 
@@ -96,3 +96,5 @@ Then, after all milestone directories and context files are written:
96
96
  **Do NOT update `.gsd/STATE.md`.**
97
97
 
98
98
  After writing the files and committing, say exactly: "Queued N milestone(s). Auto-mode will pick them up after current work completes." — nothing else.
99
+
100
+ {{inlinedTemplates}}
@@ -11,7 +11,7 @@ Then research the codebase and relevant technologies. Narrate key findings and s
11
11
  2. **Skill Discovery ({{skillDiscoveryMode}}):**{{skillDiscoveryInstructions}}
12
12
  3. Explore relevant code. For small/familiar codebases, use `rg`, `find`, and targeted reads. For large or unfamiliar codebases, use `scout` to build a broad map efficiently before diving in.
13
13
  4. Use `resolve_library` / `get_library_docs` for unfamiliar libraries
14
- 5. Read the template at `~/.gsd/agent/extensions/gsd/templates/research.md`
14
+ 5. Use the **Research** output template from the inlined context above
15
15
  6. If `.gsd/REQUIREMENTS.md` exists, research against it. Identify which Active requirements are table stakes, likely omissions, overbuilt risks, or domain-standard behaviors the user may or may not want.
16
16
  7. Write `{{outputPath}}` with:
17
17
  - Summary (2-3 paragraphs, primary recommendation)
@@ -18,7 +18,7 @@ Then research what this slice needs. Narrate key findings and surprises as you g
18
18
  2. **Skill Discovery ({{skillDiscoveryMode}}):**{{skillDiscoveryInstructions}}
19
19
  3. Explore relevant code for this slice's scope. For targeted exploration, use `rg`, `find`, and reads. For broad or unfamiliar subsystems, use `scout` to map the relevant area first.
20
20
  4. Use `resolve_library` / `get_library_docs` for unfamiliar libraries
21
- 5. Read the template at `~/.gsd/agent/extensions/gsd/templates/research.md`
21
+ 5. Use the **Research** output template from the inlined context above
22
22
  6. Write `{{outputPath}}`
23
23
 
24
24
  The slice directory already exists at `{{slicePath}}/`. Do NOT mkdir — just write the file.