gsd-pi 2.38.0-dev.eeb3520 → 2.39.0-dev.64cd3ed

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 (255) hide show
  1. package/README.md +15 -11
  2. package/dist/app-paths.js +1 -1
  3. package/dist/cli.js +9 -0
  4. package/dist/extension-discovery.d.ts +5 -3
  5. package/dist/extension-discovery.js +14 -9
  6. package/dist/extension-registry.js +2 -2
  7. package/dist/remote-questions-config.js +2 -2
  8. package/dist/resource-loader.js +34 -1
  9. package/dist/resources/extensions/async-jobs/index.js +10 -0
  10. package/dist/resources/extensions/browser-tools/index.js +3 -1
  11. package/dist/resources/extensions/browser-tools/package.json +3 -1
  12. package/dist/resources/extensions/browser-tools/tools/verify.js +97 -0
  13. package/dist/resources/extensions/cmux/index.js +55 -1
  14. package/dist/resources/extensions/context7/package.json +1 -1
  15. package/dist/resources/extensions/env-utils.js +29 -0
  16. package/dist/resources/extensions/get-secrets-from-user.js +5 -24
  17. package/dist/resources/extensions/github-sync/cli.js +284 -0
  18. package/dist/resources/extensions/github-sync/index.js +73 -0
  19. package/dist/resources/extensions/github-sync/mapping.js +67 -0
  20. package/dist/resources/extensions/github-sync/sync.js +424 -0
  21. package/dist/resources/extensions/github-sync/templates.js +118 -0
  22. package/dist/resources/extensions/github-sync/types.js +7 -0
  23. package/dist/resources/extensions/google-search/package.json +3 -1
  24. package/dist/resources/extensions/gsd/auto/session.js +6 -23
  25. package/dist/resources/extensions/gsd/auto-dispatch.js +8 -9
  26. package/dist/resources/extensions/gsd/auto-loop.js +650 -588
  27. package/dist/resources/extensions/gsd/auto-post-unit.js +99 -70
  28. package/dist/resources/extensions/gsd/auto-prompts.js +202 -48
  29. package/dist/resources/extensions/gsd/auto-start.js +13 -2
  30. package/dist/resources/extensions/gsd/auto-worktree-sync.js +13 -5
  31. package/dist/resources/extensions/gsd/auto-worktree.js +3 -3
  32. package/dist/resources/extensions/gsd/auto.js +143 -96
  33. package/dist/resources/extensions/gsd/captures.js +9 -1
  34. package/dist/resources/extensions/gsd/commands-extensions.js +3 -2
  35. package/dist/resources/extensions/gsd/commands-handlers.js +16 -3
  36. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
  37. package/dist/resources/extensions/gsd/commands.js +24 -3
  38. package/dist/resources/extensions/gsd/context-budget.js +2 -10
  39. package/dist/resources/extensions/gsd/detection.js +1 -2
  40. package/dist/resources/extensions/gsd/docs/preferences-reference.md +0 -2
  41. package/dist/resources/extensions/gsd/doctor-checks.js +82 -0
  42. package/dist/resources/extensions/gsd/doctor-environment.js +78 -0
  43. package/dist/resources/extensions/gsd/doctor-format.js +15 -0
  44. package/dist/resources/extensions/gsd/doctor-providers.js +30 -11
  45. package/dist/resources/extensions/gsd/doctor.js +204 -12
  46. package/dist/resources/extensions/gsd/exit-command.js +2 -1
  47. package/dist/resources/extensions/gsd/export.js +1 -1
  48. package/dist/resources/extensions/gsd/files.js +48 -9
  49. package/dist/resources/extensions/gsd/forensics.js +1 -1
  50. package/dist/resources/extensions/gsd/git-service.js +30 -12
  51. package/dist/resources/extensions/gsd/gitignore.js +16 -3
  52. package/dist/resources/extensions/gsd/guided-flow.js +149 -38
  53. package/dist/resources/extensions/gsd/health-widget-core.js +32 -70
  54. package/dist/resources/extensions/gsd/health-widget.js +3 -86
  55. package/dist/resources/extensions/gsd/index.js +24 -20
  56. package/dist/resources/extensions/gsd/migrate/parsers.js +1 -1
  57. package/dist/resources/extensions/gsd/migrate-external.js +18 -1
  58. package/dist/resources/extensions/gsd/native-git-bridge.js +37 -0
  59. package/dist/resources/extensions/gsd/package.json +1 -1
  60. package/dist/resources/extensions/gsd/paths.js +3 -0
  61. package/dist/resources/extensions/gsd/preferences-models.js +0 -12
  62. package/dist/resources/extensions/gsd/preferences-types.js +1 -1
  63. package/dist/resources/extensions/gsd/preferences-validation.js +59 -11
  64. package/dist/resources/extensions/gsd/preferences.js +22 -11
  65. package/dist/resources/extensions/gsd/prompt-loader.js +6 -2
  66. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  67. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  68. package/dist/resources/extensions/gsd/prompts/discuss.md +11 -14
  69. package/dist/resources/extensions/gsd/prompts/execute-task.md +5 -3
  70. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  71. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +11 -12
  72. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -10
  73. package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  74. package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  75. package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  76. package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  77. package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  78. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  79. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  80. package/dist/resources/extensions/gsd/prompts/queue.md +4 -8
  81. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +11 -8
  82. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  83. package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  84. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  85. package/dist/resources/extensions/gsd/prompts/run-uat.md +28 -11
  86. package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -2
  87. package/dist/resources/extensions/gsd/repo-identity.js +21 -4
  88. package/dist/resources/extensions/gsd/resource-version.js +2 -1
  89. package/dist/resources/extensions/gsd/roadmap-mutations.js +24 -0
  90. package/dist/resources/extensions/gsd/state.js +42 -23
  91. package/dist/resources/extensions/gsd/templates/runtime.md +21 -0
  92. package/dist/resources/extensions/gsd/templates/task-plan.md +3 -0
  93. package/dist/resources/extensions/gsd/visualizer-data.js +1 -1
  94. package/dist/resources/extensions/gsd/worktree.js +35 -16
  95. package/dist/resources/extensions/mcp-client/index.js +14 -1
  96. package/dist/resources/extensions/remote-questions/status.js +4 -1
  97. package/dist/resources/extensions/remote-questions/store.js +4 -1
  98. package/dist/resources/extensions/search-the-web/provider.js +2 -1
  99. package/dist/resources/extensions/shared/frontmatter.js +1 -1
  100. package/dist/resources/extensions/subagent/index.js +12 -3
  101. package/dist/resources/extensions/subagent/isolation.js +2 -1
  102. package/dist/resources/extensions/ttsr/rule-loader.js +2 -1
  103. package/dist/resources/extensions/universal-config/package.json +1 -1
  104. package/dist/welcome-screen.d.ts +12 -0
  105. package/dist/welcome-screen.js +53 -0
  106. package/package.json +1 -1
  107. package/packages/pi-ai/dist/utils/oauth/anthropic.js +2 -2
  108. package/packages/pi-ai/dist/utils/oauth/anthropic.js.map +1 -1
  109. package/packages/pi-ai/src/utils/oauth/anthropic.ts +2 -2
  110. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  111. package/packages/pi-coding-agent/dist/core/extensions/loader.js +205 -7
  112. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  113. package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  114. package/packages/pi-coding-agent/dist/core/package-manager.js +8 -4
  115. package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  116. package/packages/pi-coding-agent/dist/core/skills.d.ts +1 -0
  117. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  118. package/packages/pi-coding-agent/dist/core/skills.js +6 -1
  119. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  120. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  121. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  122. package/packages/pi-coding-agent/dist/index.js +1 -1
  123. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  124. package/packages/pi-coding-agent/package.json +1 -1
  125. package/packages/pi-coding-agent/src/core/extensions/loader.ts +223 -7
  126. package/packages/pi-coding-agent/src/core/package-manager.ts +8 -4
  127. package/packages/pi-coding-agent/src/core/skills.ts +9 -1
  128. package/packages/pi-coding-agent/src/index.ts +1 -0
  129. package/pkg/package.json +1 -1
  130. package/src/resources/extensions/async-jobs/index.ts +11 -0
  131. package/src/resources/extensions/browser-tools/index.ts +3 -0
  132. package/src/resources/extensions/browser-tools/tools/verify.ts +117 -0
  133. package/src/resources/extensions/cmux/index.ts +57 -1
  134. package/src/resources/extensions/env-utils.ts +31 -0
  135. package/src/resources/extensions/get-secrets-from-user.ts +5 -24
  136. package/src/resources/extensions/github-sync/cli.ts +364 -0
  137. package/src/resources/extensions/github-sync/index.ts +93 -0
  138. package/src/resources/extensions/github-sync/mapping.ts +81 -0
  139. package/src/resources/extensions/github-sync/sync.ts +556 -0
  140. package/src/resources/extensions/github-sync/templates.ts +183 -0
  141. package/src/resources/extensions/github-sync/tests/cli.test.ts +20 -0
  142. package/src/resources/extensions/github-sync/tests/commit-linking.test.ts +39 -0
  143. package/src/resources/extensions/github-sync/tests/mapping.test.ts +104 -0
  144. package/src/resources/extensions/github-sync/tests/templates.test.ts +110 -0
  145. package/src/resources/extensions/github-sync/types.ts +47 -0
  146. package/src/resources/extensions/gsd/auto/session.ts +7 -25
  147. package/src/resources/extensions/gsd/auto-dispatch.ts +7 -9
  148. package/src/resources/extensions/gsd/auto-loop.ts +553 -546
  149. package/src/resources/extensions/gsd/auto-post-unit.ts +80 -44
  150. package/src/resources/extensions/gsd/auto-prompts.ts +247 -50
  151. package/src/resources/extensions/gsd/auto-start.ts +18 -2
  152. package/src/resources/extensions/gsd/auto-worktree-sync.ts +15 -4
  153. package/src/resources/extensions/gsd/auto-worktree.ts +3 -3
  154. package/src/resources/extensions/gsd/auto.ts +139 -101
  155. package/src/resources/extensions/gsd/captures.ts +10 -1
  156. package/src/resources/extensions/gsd/commands-extensions.ts +4 -2
  157. package/src/resources/extensions/gsd/commands-handlers.ts +17 -2
  158. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
  159. package/src/resources/extensions/gsd/commands.ts +26 -4
  160. package/src/resources/extensions/gsd/context-budget.ts +2 -12
  161. package/src/resources/extensions/gsd/detection.ts +2 -2
  162. package/src/resources/extensions/gsd/docs/preferences-reference.md +0 -2
  163. package/src/resources/extensions/gsd/doctor-checks.ts +75 -0
  164. package/src/resources/extensions/gsd/doctor-environment.ts +82 -1
  165. package/src/resources/extensions/gsd/doctor-format.ts +20 -0
  166. package/src/resources/extensions/gsd/doctor-providers.ts +30 -9
  167. package/src/resources/extensions/gsd/doctor-types.ts +16 -1
  168. package/src/resources/extensions/gsd/doctor.ts +199 -14
  169. package/src/resources/extensions/gsd/exit-command.ts +2 -2
  170. package/src/resources/extensions/gsd/export.ts +1 -1
  171. package/src/resources/extensions/gsd/files.ts +51 -11
  172. package/src/resources/extensions/gsd/forensics.ts +1 -1
  173. package/src/resources/extensions/gsd/git-service.ts +44 -10
  174. package/src/resources/extensions/gsd/gitignore.ts +17 -3
  175. package/src/resources/extensions/gsd/guided-flow.ts +177 -44
  176. package/src/resources/extensions/gsd/health-widget-core.ts +28 -80
  177. package/src/resources/extensions/gsd/health-widget.ts +3 -89
  178. package/src/resources/extensions/gsd/index.ts +24 -17
  179. package/src/resources/extensions/gsd/migrate/parsers.ts +1 -1
  180. package/src/resources/extensions/gsd/migrate-external.ts +18 -1
  181. package/src/resources/extensions/gsd/native-git-bridge.ts +37 -0
  182. package/src/resources/extensions/gsd/paths.ts +4 -0
  183. package/src/resources/extensions/gsd/preferences-models.ts +0 -12
  184. package/src/resources/extensions/gsd/preferences-types.ts +4 -4
  185. package/src/resources/extensions/gsd/preferences-validation.ts +51 -11
  186. package/src/resources/extensions/gsd/preferences.ts +25 -11
  187. package/src/resources/extensions/gsd/prompt-loader.ts +7 -2
  188. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  189. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  190. package/src/resources/extensions/gsd/prompts/discuss.md +11 -14
  191. package/src/resources/extensions/gsd/prompts/execute-task.md +5 -3
  192. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  193. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +11 -12
  194. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -10
  195. package/src/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  196. package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  197. package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  198. package/src/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  199. package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  200. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  201. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  202. package/src/resources/extensions/gsd/prompts/queue.md +4 -8
  203. package/src/resources/extensions/gsd/prompts/reactive-execute.md +11 -8
  204. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  205. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  206. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  207. package/src/resources/extensions/gsd/prompts/run-uat.md +28 -11
  208. package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -2
  209. package/src/resources/extensions/gsd/repo-identity.ts +23 -4
  210. package/src/resources/extensions/gsd/resource-version.ts +3 -1
  211. package/src/resources/extensions/gsd/roadmap-mutations.ts +29 -0
  212. package/src/resources/extensions/gsd/state.ts +39 -21
  213. package/src/resources/extensions/gsd/templates/runtime.md +21 -0
  214. package/src/resources/extensions/gsd/templates/task-plan.md +3 -0
  215. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +21 -18
  216. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +122 -68
  217. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +4 -3
  218. package/src/resources/extensions/gsd/tests/cmux.test.ts +93 -0
  219. package/src/resources/extensions/gsd/tests/derive-state.test.ts +43 -0
  220. package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +266 -0
  221. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +86 -3
  222. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +50 -0
  223. package/src/resources/extensions/gsd/tests/health-widget.test.ts +16 -54
  224. package/src/resources/extensions/gsd/tests/parsers.test.ts +131 -14
  225. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +209 -0
  226. package/src/resources/extensions/gsd/tests/preferences.test.ts +2 -7
  227. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +59 -0
  228. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +21 -1
  229. package/src/resources/extensions/gsd/tests/run-uat.test.ts +16 -4
  230. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +140 -0
  231. package/src/resources/extensions/gsd/tests/worktree.test.ts +47 -0
  232. package/src/resources/extensions/gsd/types.ts +18 -1
  233. package/src/resources/extensions/gsd/verification-evidence.ts +16 -0
  234. package/src/resources/extensions/gsd/visualizer-data.ts +1 -1
  235. package/src/resources/extensions/gsd/worktree.ts +35 -15
  236. package/src/resources/extensions/mcp-client/index.ts +17 -1
  237. package/src/resources/extensions/remote-questions/status.ts +5 -1
  238. package/src/resources/extensions/remote-questions/store.ts +5 -1
  239. package/src/resources/extensions/search-the-web/provider.ts +2 -1
  240. package/src/resources/extensions/shared/frontmatter.ts +1 -1
  241. package/src/resources/extensions/subagent/index.ts +12 -3
  242. package/src/resources/extensions/subagent/isolation.ts +3 -1
  243. package/src/resources/extensions/ttsr/rule-loader.ts +3 -1
  244. package/dist/resources/extensions/gsd/prompt-compressor.js +0 -393
  245. package/dist/resources/extensions/gsd/semantic-chunker.js +0 -254
  246. package/dist/resources/extensions/gsd/summary-distiller.js +0 -212
  247. package/src/resources/extensions/gsd/prompt-compressor.ts +0 -508
  248. package/src/resources/extensions/gsd/semantic-chunker.ts +0 -336
  249. package/src/resources/extensions/gsd/summary-distiller.ts +0 -258
  250. package/src/resources/extensions/gsd/tests/context-compression.test.ts +0 -193
  251. package/src/resources/extensions/gsd/tests/prompt-compressor.test.ts +0 -529
  252. package/src/resources/extensions/gsd/tests/semantic-chunker.test.ts +0 -426
  253. package/src/resources/extensions/gsd/tests/summary-distiller.test.ts +0 -323
  254. package/src/resources/extensions/gsd/tests/token-optimization-benchmark.test.ts +0 -1272
  255. package/src/resources/extensions/gsd/tests/token-optimization-prefs.test.ts +0 -164
@@ -0,0 +1,93 @@
1
+ /**
2
+ * GitHub Sync extension for GSD.
3
+ *
4
+ * Opt-in extension that syncs GSD lifecycle events to GitHub:
5
+ * milestones → GH Milestones + tracking issues, slices → draft PRs,
6
+ * tasks → sub-issues with auto-close on commit.
7
+ *
8
+ * Integration happens via a single dynamic import in auto-post-unit.ts.
9
+ * This index registers a `/github-sync` command for manual bootstrap
10
+ * and status display.
11
+ */
12
+
13
+ import type { ExtensionAPI } from "@gsd/pi-coding-agent";
14
+ import { bootstrapSync } from "./sync.js";
15
+ import { loadSyncMapping } from "./mapping.js";
16
+ import { ghIsAvailable } from "./cli.js";
17
+
18
+ export default function (pi: ExtensionAPI) {
19
+ pi.registerCommand("github-sync", {
20
+ description: "Bootstrap GitHub sync or show sync status",
21
+ handler: async (args: string, ctx) => {
22
+ const subcommand = args.trim().toLowerCase();
23
+
24
+ if (subcommand === "status") {
25
+ await showStatus(ctx);
26
+ return;
27
+ }
28
+
29
+ if (subcommand === "bootstrap" || subcommand === "") {
30
+ await runBootstrap(ctx);
31
+ return;
32
+ }
33
+
34
+ ctx.ui.notify(
35
+ "Usage: /github-sync [bootstrap|status]",
36
+ "info",
37
+ );
38
+ },
39
+ });
40
+ }
41
+
42
+ async function showStatus(ctx: import("@gsd/pi-coding-agent").ExtensionCommandContext) {
43
+ if (!ghIsAvailable()) {
44
+ ctx.ui.notify("GitHub sync: `gh` CLI not installed or not authenticated.", "warning");
45
+ return;
46
+ }
47
+
48
+ const mapping = loadSyncMapping(ctx.cwd);
49
+ if (!mapping) {
50
+ ctx.ui.notify("GitHub sync: No sync mapping found. Run `/github-sync bootstrap` to initialize.", "info");
51
+ return;
52
+ }
53
+
54
+ const milestoneCount = Object.keys(mapping.milestones).length;
55
+ const sliceCount = Object.keys(mapping.slices).length;
56
+ const taskCount = Object.keys(mapping.tasks).length;
57
+ const openMilestones = Object.values(mapping.milestones).filter(m => m.state === "open").length;
58
+ const openSlices = Object.values(mapping.slices).filter(s => s.state === "open").length;
59
+ const openTasks = Object.values(mapping.tasks).filter(t => t.state === "open").length;
60
+
61
+ ctx.ui.notify(
62
+ [
63
+ `GitHub sync: repo=${mapping.repo}`,
64
+ ` Milestones: ${milestoneCount} (${openMilestones} open)`,
65
+ ` Slices: ${sliceCount} (${openSlices} open)`,
66
+ ` Tasks: ${taskCount} (${openTasks} open)`,
67
+ ].join("\n"),
68
+ "info",
69
+ );
70
+ }
71
+
72
+ async function runBootstrap(ctx: import("@gsd/pi-coding-agent").ExtensionCommandContext) {
73
+ if (!ghIsAvailable()) {
74
+ ctx.ui.notify("GitHub sync: `gh` CLI not installed or not authenticated.", "warning");
75
+ return;
76
+ }
77
+
78
+ ctx.ui.notify("GitHub sync: bootstrapping...", "info");
79
+
80
+ try {
81
+ const counts = await bootstrapSync(ctx.cwd);
82
+ if (counts.milestones === 0 && counts.slices === 0 && counts.tasks === 0) {
83
+ ctx.ui.notify("GitHub sync: everything already synced (or no milestones found).", "info");
84
+ } else {
85
+ ctx.ui.notify(
86
+ `GitHub sync: created ${counts.milestones} milestone(s), ${counts.slices} slice(s), ${counts.tasks} task(s).`,
87
+ "info",
88
+ );
89
+ }
90
+ } catch (err) {
91
+ ctx.ui.notify(`GitHub sync bootstrap failed: ${err}`, "error");
92
+ }
93
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Persistence layer for the GitHub sync mapping.
3
+ *
4
+ * The mapping lives at `.gsd/github-sync.json` and tracks which GSD
5
+ * entities have been synced to which GitHub entities (issues, PRs,
6
+ * milestones) along with their numbers and sync timestamps.
7
+ */
8
+
9
+ import { existsSync, readFileSync } from "node:fs";
10
+ import { join } from "node:path";
11
+ import { atomicWriteSync } from "../gsd/atomic-write.js";
12
+ import type { SyncMapping, MilestoneSyncRecord, SliceSyncRecord, SyncEntityRecord } from "./types.js";
13
+
14
+ const MAPPING_FILENAME = "github-sync.json";
15
+
16
+ function mappingPath(basePath: string): string {
17
+ return join(basePath, ".gsd", MAPPING_FILENAME);
18
+ }
19
+
20
+ // ─── Load / Save ────────────────────────────────────────────────────────────
21
+
22
+ export function loadSyncMapping(basePath: string): SyncMapping | null {
23
+ const path = mappingPath(basePath);
24
+ if (!existsSync(path)) return null;
25
+ try {
26
+ const raw = readFileSync(path, "utf-8");
27
+ const parsed = JSON.parse(raw);
28
+ if (parsed?.version !== 1) return null;
29
+ return parsed as SyncMapping;
30
+ } catch {
31
+ return null;
32
+ }
33
+ }
34
+
35
+ export function saveSyncMapping(basePath: string, mapping: SyncMapping): void {
36
+ const path = mappingPath(basePath);
37
+ atomicWriteSync(path, JSON.stringify(mapping, null, 2) + "\n");
38
+ }
39
+
40
+ export function createEmptyMapping(repo: string): SyncMapping {
41
+ return {
42
+ version: 1,
43
+ repo,
44
+ milestones: {},
45
+ slices: {},
46
+ tasks: {},
47
+ };
48
+ }
49
+
50
+ // ─── Accessors ──────────────────────────────────────────────────────────────
51
+
52
+ export function getMilestoneRecord(mapping: SyncMapping, mid: string): MilestoneSyncRecord | null {
53
+ return mapping.milestones[mid] ?? null;
54
+ }
55
+
56
+ export function getSliceRecord(mapping: SyncMapping, mid: string, sid: string): SliceSyncRecord | null {
57
+ return mapping.slices[`${mid}/${sid}`] ?? null;
58
+ }
59
+
60
+ export function getTaskRecord(mapping: SyncMapping, mid: string, sid: string, tid: string): SyncEntityRecord | null {
61
+ return mapping.tasks[`${mid}/${sid}/${tid}`] ?? null;
62
+ }
63
+
64
+ export function getTaskIssueNumber(mapping: SyncMapping, mid: string, sid: string, tid: string): number | null {
65
+ const record = getTaskRecord(mapping, mid, sid, tid);
66
+ return record?.issueNumber ?? null;
67
+ }
68
+
69
+ // ─── Mutators ───────────────────────────────────────────────────────────────
70
+
71
+ export function setMilestoneRecord(mapping: SyncMapping, mid: string, record: MilestoneSyncRecord): void {
72
+ mapping.milestones[mid] = record;
73
+ }
74
+
75
+ export function setSliceRecord(mapping: SyncMapping, mid: string, sid: string, record: SliceSyncRecord): void {
76
+ mapping.slices[`${mid}/${sid}`] = record;
77
+ }
78
+
79
+ export function setTaskRecord(mapping: SyncMapping, mid: string, sid: string, tid: string, record: SyncEntityRecord): void {
80
+ mapping.tasks[`${mid}/${sid}/${tid}`] = record;
81
+ }