@paysdoc/devplatform 1.0.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 (243) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +122 -0
  3. package/dist/git/bootstrapIdentity.d.ts +50 -0
  4. package/dist/git/bootstrapIdentity.d.ts.map +1 -0
  5. package/dist/git/bootstrapIdentity.js +72 -0
  6. package/dist/git/bootstrapIdentity.js.map +1 -0
  7. package/dist/git/branchOps.d.ts +27 -0
  8. package/dist/git/branchOps.d.ts.map +1 -0
  9. package/dist/git/branchOps.js +91 -0
  10. package/dist/git/branchOps.js.map +1 -0
  11. package/dist/git/claimOps.d.ts +40 -0
  12. package/dist/git/claimOps.d.ts.map +1 -0
  13. package/dist/git/claimOps.js +44 -0
  14. package/dist/git/claimOps.js.map +1 -0
  15. package/dist/git/commitOps.d.ts +35 -0
  16. package/dist/git/commitOps.d.ts.map +1 -0
  17. package/dist/git/commitOps.js +131 -0
  18. package/dist/git/commitOps.js.map +1 -0
  19. package/dist/git/consoleLogger.d.ts +8 -0
  20. package/dist/git/consoleLogger.d.ts.map +1 -0
  21. package/dist/git/consoleLogger.js +9 -0
  22. package/dist/git/consoleLogger.js.map +1 -0
  23. package/dist/git/gitContext.d.ts +150 -0
  24. package/dist/git/gitContext.d.ts.map +1 -0
  25. package/dist/git/gitContext.js +405 -0
  26. package/dist/git/gitContext.js.map +1 -0
  27. package/dist/git/gitReadOps.d.ts +33 -0
  28. package/dist/git/gitReadOps.d.ts.map +1 -0
  29. package/dist/git/gitReadOps.js +38 -0
  30. package/dist/git/gitReadOps.js.map +1 -0
  31. package/dist/git/index.d.ts +49 -0
  32. package/dist/git/index.d.ts.map +1 -0
  33. package/dist/git/index.js +44 -0
  34. package/dist/git/index.js.map +1 -0
  35. package/dist/git/processCleanup.d.ts +7 -0
  36. package/dist/git/processCleanup.d.ts.map +1 -0
  37. package/dist/git/processCleanup.js +45 -0
  38. package/dist/git/processCleanup.js.map +1 -0
  39. package/dist/git/remoteOps.d.ts +25 -0
  40. package/dist/git/remoteOps.d.ts.map +1 -0
  41. package/dist/git/remoteOps.js +30 -0
  42. package/dist/git/remoteOps.js.map +1 -0
  43. package/dist/git/repoWorkspace.d.ts +72 -0
  44. package/dist/git/repoWorkspace.d.ts.map +1 -0
  45. package/dist/git/repoWorkspace.js +85 -0
  46. package/dist/git/repoWorkspace.js.map +1 -0
  47. package/dist/git/types.d.ts +182 -0
  48. package/dist/git/types.d.ts.map +1 -0
  49. package/dist/git/types.js +10 -0
  50. package/dist/git/types.js.map +1 -0
  51. package/dist/git/workingDirectoryGuard.d.ts +39 -0
  52. package/dist/git/workingDirectoryGuard.d.ts.map +1 -0
  53. package/dist/git/workingDirectoryGuard.js +53 -0
  54. package/dist/git/workingDirectoryGuard.js.map +1 -0
  55. package/dist/git/worktreeCreateOps.d.ts +45 -0
  56. package/dist/git/worktreeCreateOps.d.ts.map +1 -0
  57. package/dist/git/worktreeCreateOps.js +208 -0
  58. package/dist/git/worktreeCreateOps.js.map +1 -0
  59. package/dist/git/worktreeProbeOps.d.ts +17 -0
  60. package/dist/git/worktreeProbeOps.d.ts.map +1 -0
  61. package/dist/git/worktreeProbeOps.js +66 -0
  62. package/dist/git/worktreeProbeOps.js.map +1 -0
  63. package/dist/git/worktreeQueryOps.d.ts +45 -0
  64. package/dist/git/worktreeQueryOps.d.ts.map +1 -0
  65. package/dist/git/worktreeQueryOps.js +129 -0
  66. package/dist/git/worktreeQueryOps.js.map +1 -0
  67. package/dist/git/worktreeRemoveOps.d.ts +27 -0
  68. package/dist/git/worktreeRemoveOps.d.ts.map +1 -0
  69. package/dist/git/worktreeRemoveOps.js +132 -0
  70. package/dist/git/worktreeRemoveOps.js.map +1 -0
  71. package/dist/git/worktreeResetOps.d.ts +18 -0
  72. package/dist/git/worktreeResetOps.d.ts.map +1 -0
  73. package/dist/git/worktreeResetOps.js +68 -0
  74. package/dist/git/worktreeResetOps.js.map +1 -0
  75. package/dist/index.d.ts +13 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +13 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/providers/forgeProviders.d.ts +72 -0
  80. package/dist/providers/forgeProviders.d.ts.map +1 -0
  81. package/dist/providers/forgeProviders.js +112 -0
  82. package/dist/providers/forgeProviders.js.map +1 -0
  83. package/dist/providers/github/appAuth.d.ts +70 -0
  84. package/dist/providers/github/appAuth.d.ts.map +1 -0
  85. package/dist/providers/github/appAuth.js +243 -0
  86. package/dist/providers/github/appAuth.js.map +1 -0
  87. package/dist/providers/github/cloneUrl.d.ts +12 -0
  88. package/dist/providers/github/cloneUrl.d.ts.map +1 -0
  89. package/dist/providers/github/cloneUrl.js +20 -0
  90. package/dist/providers/github/cloneUrl.js.map +1 -0
  91. package/dist/providers/github/commands/boardCommands.d.ts +22 -0
  92. package/dist/providers/github/commands/boardCommands.d.ts.map +1 -0
  93. package/dist/providers/github/commands/boardCommands.js +66 -0
  94. package/dist/providers/github/commands/boardCommands.js.map +1 -0
  95. package/dist/providers/github/commands/issueCommands.d.ts +21 -0
  96. package/dist/providers/github/commands/issueCommands.d.ts.map +1 -0
  97. package/dist/providers/github/commands/issueCommands.js +50 -0
  98. package/dist/providers/github/commands/issueCommands.js.map +1 -0
  99. package/dist/providers/github/commands/labelCommands.d.ts +3 -0
  100. package/dist/providers/github/commands/labelCommands.d.ts.map +1 -0
  101. package/dist/providers/github/commands/labelCommands.js +8 -0
  102. package/dist/providers/github/commands/labelCommands.js.map +1 -0
  103. package/dist/providers/github/commands/prCommands.d.ts +14 -0
  104. package/dist/providers/github/commands/prCommands.d.ts.map +1 -0
  105. package/dist/providers/github/commands/prCommands.js +46 -0
  106. package/dist/providers/github/commands/prCommands.js.map +1 -0
  107. package/dist/providers/github/commands/secretCommands.d.ts +2 -0
  108. package/dist/providers/github/commands/secretCommands.d.ts.map +1 -0
  109. package/dist/providers/github/commands/secretCommands.js +5 -0
  110. package/dist/providers/github/commands/secretCommands.js.map +1 -0
  111. package/dist/providers/github/contextBinding.d.ts +11 -0
  112. package/dist/providers/github/contextBinding.d.ts.map +1 -0
  113. package/dist/providers/github/contextBinding.js +15 -0
  114. package/dist/providers/github/contextBinding.js.map +1 -0
  115. package/dist/providers/github/domain/issue.d.ts +94 -0
  116. package/dist/providers/github/domain/issue.d.ts.map +1 -0
  117. package/dist/providers/github/domain/issue.js +7 -0
  118. package/dist/providers/github/domain/issue.js.map +1 -0
  119. package/dist/providers/github/domain/pullRequest.d.ts +55 -0
  120. package/dist/providers/github/domain/pullRequest.d.ts.map +1 -0
  121. package/dist/providers/github/domain/pullRequest.js +9 -0
  122. package/dist/providers/github/domain/pullRequest.js.map +1 -0
  123. package/dist/providers/github/ghAuthToken.d.ts +28 -0
  124. package/dist/providers/github/ghAuthToken.d.ts.map +1 -0
  125. package/dist/providers/github/ghAuthToken.js +39 -0
  126. package/dist/providers/github/ghAuthToken.js.map +1 -0
  127. package/dist/providers/github/ghCommandRunner.d.ts +20 -0
  128. package/dist/providers/github/ghCommandRunner.d.ts.map +1 -0
  129. package/dist/providers/github/ghCommandRunner.js +21 -0
  130. package/dist/providers/github/ghCommandRunner.js.map +1 -0
  131. package/dist/providers/github/ghIssueApi.d.ts +29 -0
  132. package/dist/providers/github/ghIssueApi.d.ts.map +1 -0
  133. package/dist/providers/github/ghIssueApi.js +37 -0
  134. package/dist/providers/github/ghIssueApi.js.map +1 -0
  135. package/dist/providers/github/ghIssueParsers.d.ts +28 -0
  136. package/dist/providers/github/ghIssueParsers.d.ts.map +1 -0
  137. package/dist/providers/github/ghIssueParsers.js +105 -0
  138. package/dist/providers/github/ghIssueParsers.js.map +1 -0
  139. package/dist/providers/github/ghPrApi.d.ts +27 -0
  140. package/dist/providers/github/ghPrApi.d.ts.map +1 -0
  141. package/dist/providers/github/ghPrApi.js +32 -0
  142. package/dist/providers/github/ghPrApi.js.map +1 -0
  143. package/dist/providers/github/ghPrParsers.d.ts +57 -0
  144. package/dist/providers/github/ghPrParsers.d.ts.map +1 -0
  145. package/dist/providers/github/ghPrParsers.js +135 -0
  146. package/dist/providers/github/ghPrParsers.js.map +1 -0
  147. package/dist/providers/github/ghRepoApi.d.ts +33 -0
  148. package/dist/providers/github/ghRepoApi.d.ts.map +1 -0
  149. package/dist/providers/github/ghRepoApi.js +89 -0
  150. package/dist/providers/github/ghRepoApi.js.map +1 -0
  151. package/dist/providers/github/githubBoardManager.d.ts +39 -0
  152. package/dist/providers/github/githubBoardManager.d.ts.map +1 -0
  153. package/dist/providers/github/githubBoardManager.js +166 -0
  154. package/dist/providers/github/githubBoardManager.js.map +1 -0
  155. package/dist/providers/github/githubCodeHost.d.ts +73 -0
  156. package/dist/providers/github/githubCodeHost.d.ts.map +1 -0
  157. package/dist/providers/github/githubCodeHost.js +217 -0
  158. package/dist/providers/github/githubCodeHost.js.map +1 -0
  159. package/dist/providers/github/githubIdentity.d.ts +51 -0
  160. package/dist/providers/github/githubIdentity.d.ts.map +1 -0
  161. package/dist/providers/github/githubIdentity.js +110 -0
  162. package/dist/providers/github/githubIdentity.js.map +1 -0
  163. package/dist/providers/github/githubIssueTracker.d.ts +69 -0
  164. package/dist/providers/github/githubIssueTracker.d.ts.map +1 -0
  165. package/dist/providers/github/githubIssueTracker.js +209 -0
  166. package/dist/providers/github/githubIssueTracker.js.map +1 -0
  167. package/dist/providers/github/githubTokenProvider.d.ts +41 -0
  168. package/dist/providers/github/githubTokenProvider.d.ts.map +1 -0
  169. package/dist/providers/github/githubTokenProvider.js +51 -0
  170. package/dist/providers/github/githubTokenProvider.js.map +1 -0
  171. package/dist/providers/github/index.d.ts +10 -0
  172. package/dist/providers/github/index.d.ts.map +1 -0
  173. package/dist/providers/github/index.js +5 -0
  174. package/dist/providers/github/index.js.map +1 -0
  175. package/dist/providers/github/mappers.d.ts +40 -0
  176. package/dist/providers/github/mappers.d.ts.map +1 -0
  177. package/dist/providers/github/mappers.js +103 -0
  178. package/dist/providers/github/mappers.js.map +1 -0
  179. package/dist/providers/github/tokenResolver.d.ts +37 -0
  180. package/dist/providers/github/tokenResolver.d.ts.map +1 -0
  181. package/dist/providers/github/tokenResolver.js +43 -0
  182. package/dist/providers/github/tokenResolver.js.map +1 -0
  183. package/dist/providers/gitlab/gitlabApiClient.d.ts +45 -0
  184. package/dist/providers/gitlab/gitlabApiClient.d.ts.map +1 -0
  185. package/dist/providers/gitlab/gitlabApiClient.js +95 -0
  186. package/dist/providers/gitlab/gitlabApiClient.js.map +1 -0
  187. package/dist/providers/gitlab/gitlabBoardManager.d.ts +11 -0
  188. package/dist/providers/gitlab/gitlabBoardManager.d.ts.map +1 -0
  189. package/dist/providers/gitlab/gitlabBoardManager.js +27 -0
  190. package/dist/providers/gitlab/gitlabBoardManager.js.map +1 -0
  191. package/dist/providers/gitlab/gitlabCodeHost.d.ts +49 -0
  192. package/dist/providers/gitlab/gitlabCodeHost.d.ts.map +1 -0
  193. package/dist/providers/gitlab/gitlabCodeHost.js +109 -0
  194. package/dist/providers/gitlab/gitlabCodeHost.js.map +1 -0
  195. package/dist/providers/gitlab/gitlabTypes.d.ts +46 -0
  196. package/dist/providers/gitlab/gitlabTypes.d.ts.map +1 -0
  197. package/dist/providers/gitlab/gitlabTypes.js +6 -0
  198. package/dist/providers/gitlab/gitlabTypes.js.map +1 -0
  199. package/dist/providers/gitlab/index.d.ts +5 -0
  200. package/dist/providers/gitlab/index.d.ts.map +1 -0
  201. package/dist/providers/gitlab/index.js +4 -0
  202. package/dist/providers/gitlab/index.js.map +1 -0
  203. package/dist/providers/gitlab/mappers.d.ts +26 -0
  204. package/dist/providers/gitlab/mappers.d.ts.map +1 -0
  205. package/dist/providers/gitlab/mappers.js +63 -0
  206. package/dist/providers/gitlab/mappers.js.map +1 -0
  207. package/dist/providers/index.d.ts +7 -0
  208. package/dist/providers/index.d.ts.map +1 -0
  209. package/dist/providers/index.js +7 -0
  210. package/dist/providers/index.js.map +1 -0
  211. package/dist/providers/jira/adfConverter.d.ts +32 -0
  212. package/dist/providers/jira/adfConverter.d.ts.map +1 -0
  213. package/dist/providers/jira/adfConverter.js +144 -0
  214. package/dist/providers/jira/adfConverter.js.map +1 -0
  215. package/dist/providers/jira/index.d.ts +8 -0
  216. package/dist/providers/jira/index.d.ts.map +1 -0
  217. package/dist/providers/jira/index.js +5 -0
  218. package/dist/providers/jira/index.js.map +1 -0
  219. package/dist/providers/jira/jiraApiClient.d.ts +42 -0
  220. package/dist/providers/jira/jiraApiClient.d.ts.map +1 -0
  221. package/dist/providers/jira/jiraApiClient.js +84 -0
  222. package/dist/providers/jira/jiraApiClient.js.map +1 -0
  223. package/dist/providers/jira/jiraBoardManager.d.ts +11 -0
  224. package/dist/providers/jira/jiraBoardManager.d.ts.map +1 -0
  225. package/dist/providers/jira/jiraBoardManager.js +27 -0
  226. package/dist/providers/jira/jiraBoardManager.js.map +1 -0
  227. package/dist/providers/jira/jiraIssueTracker.d.ts +53 -0
  228. package/dist/providers/jira/jiraIssueTracker.d.ts.map +1 -0
  229. package/dist/providers/jira/jiraIssueTracker.js +231 -0
  230. package/dist/providers/jira/jiraIssueTracker.js.map +1 -0
  231. package/dist/providers/jira/jiraTypes.d.ts +61 -0
  232. package/dist/providers/jira/jiraTypes.d.ts.map +1 -0
  233. package/dist/providers/jira/jiraTypes.js +6 -0
  234. package/dist/providers/jira/jiraTypes.js.map +1 -0
  235. package/dist/providers/types.d.ts +271 -0
  236. package/dist/providers/types.d.ts.map +1 -0
  237. package/dist/providers/types.js +52 -0
  238. package/dist/providers/types.js.map +1 -0
  239. package/dist/providers/workspaceValidation.d.ts +18 -0
  240. package/dist/providers/workspaceValidation.d.ts.map +1 -0
  241. package/dist/providers/workspaceValidation.js +37 -0
  242. package/dist/providers/workspaceValidation.js.map +1 -0
  243. package/package.json +66 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Martin Koster
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,122 @@
1
+ # @paysdoc/devplatform
2
+
3
+ A TypeScript library of forge-neutral git/worktree primitives plus GitHub, GitLab, and Jira adapters for building dev-workflow automation.
4
+
5
+ Extracted from [AI_Dev_Workflow](https://github.com/paysdoc/AI_Dev_Workflow) with history.
6
+ Releases are automated by semantic-release on every push to `main`.
7
+
8
+ ## Install
9
+
10
+ ```
11
+ bun add @paysdoc/devplatform
12
+ # or
13
+ npm i @paysdoc/devplatform
14
+ ```
15
+
16
+ The package ships three entry points:
17
+
18
+ ```ts
19
+ import { BoardStatus, type Issue, type RepoContext } from '@paysdoc/devplatform'; // forge ports + domain model
20
+ import { forgeProviders } from '@paysdoc/devplatform/providers'; // adapter assembly + GitHub/GitLab/Jira adapters
21
+ import { GitContext, consoleLogger } from '@paysdoc/devplatform/git'; // forge-neutral git/worktree core
22
+ ```
23
+
24
+ ## What it does
25
+
26
+ - **Forge-neutral git executor** — `GitContext.exec()` is the single spawn site, env merge, cwd resolution, and ENOENT rewrap for every git command; no forge semantics leak into it.
27
+ - **Identity-bound context construction** — a `GitContext` is built from a mandatory owner/repo/selfHost/tokenProvider/gitIdentity; incomplete identity fails at construction rather than at first use.
28
+ - **Worktree lifecycle management** — create/ensure, list, remove, probe (health: `healthy`/`locked`/`prunable`/`missing`), and reset (takeover) operations for git worktrees under `.worktrees/`.
29
+ - **Branch, commit, and remote operations** — branch creation/switching, commits, and remote push/fetch helpers layered on the shared executor.
30
+ - **Working-directory guard** — turns a spawn ENOENT caused by a missing cwd into a diagnostic naming the path and repo identity, keyed off the OS-independent error `code`.
31
+ - **Distributed-lock claim primitives** — detached-worktree add/remove, empty-commit nonce marking, and a never-forced push used to implement an atomic winner/loser election (e.g. for upgrade claims).
32
+ - **Process cleanup** — kills processes still running inside a worktree directory before it is removed.
33
+ - **Pluggable credential and logging ports** — `TokenProvider` (credential-purpose-scoped) and `Logger` ports let a consumer supply auth and logging without the core depending on either.
34
+ - **Bootstrap-only git reads** — a narrow, structurally-exempt set of pre-context reads (origin remote URL, env/git-config identity) for use before a full `GitContext` exists.
35
+ - **Forge-neutral provider interfaces** — `IssueTracker`, `CodeHost`, and `BoardManager` ports abstract issue tracking, PR/code hosting, and project boards across platforms.
36
+ - **`forgeProviders()` assembly function** — binds one `RepoIdentifier` to a full provider triple, validating identity, token provider shape, and context binding before constructing any adapter; rejects unknown or wrong-port forge names via `UnknownForgeError`.
37
+ - **GitHub adapter** — issue tracker, code host, and Projects V2 board manager built on the `gh` CLI, including issue/PR read and write operations, label management, GitHub App authentication, and token resolution.
38
+ - **GitLab adapter** — code host implementation backed by a `curl`-based API client with injected configuration (no environment reads).
39
+ - **Jira adapter** — issue tracker backed by the Jira REST API v3, including Markdown ↔ Atlassian Document Format (ADF) conversion.
40
+ - **Board status model** — a canonical, ordered set of board columns (`Blocked`/`Todo`/`In Progress`/`Review`/`Done`) with colors and descriptions shared across board-capable adapters.
41
+ - **Injected configuration everywhere** — GitLab, Jira, and GitHub App adapters take configuration as constructor arguments; none reads `process.env` or files directly, keeping the library embeddable in any host.
42
+ - **Compiled ESM + type declarations** — `bun run build` emits `dist/**/*.js` and `dist/**/*.d.ts` via `tsc`, with a three-entry-point `exports` map (`.`, `./providers`, `./git`) and a `files` allow-list so `npm pack` ships only `dist/`, `README.md`, and `LICENSE`.
43
+ - **CI type-check, git/gh guard, unit-test, and package gate** — GitHub Actions runs `bun install`, `bun run typecheck`, `bun run lint:git-guard`, and `bun run test:unit` on every PR and push to `main`, plus a second job that builds, packs, and smoke-tests the tarball under both Node and Bun.
44
+ - **Automated releases via semantic-release** — a `Release` GitHub Actions job runs semantic-release on every push to `main`, using a commit parser that accepts an optional `<agent-name>: ` prefix before the conventional type (`build-agent: feat: …` → minor, `review-patch-agent: fix: …` → patch, `plan-orchestrator: chore: …` → no release), a PR `release-dry-run` job that prints the computed next version before merge, and npm OIDC trusted publishing with an `NPM_TOKEN` fallback.
45
+ - **Git/gh CI guard** — an AST-based check (`bun run lint:git-guard`, `scripts/checkGitGhGuard.ts` + `scripts/guard/`) that fails CI on a direct `git`/`gh` shell-out outside `src/git/` and `src/providers/github/` (the two structurally-exempt packages), or on ad-hoc provider/`GitContext` construction anywhere outside the one-entry `src/providers/forgeProviders.ts` allowlist.
46
+ - **Claude Code agent guardrails** — a hooked `.claude/settings.json` and `.claude/hooks/*` scripts (pre/post-tool-use, notification, stop, subagent-stop) constrain and observe agent tool use in this repo.
47
+
48
+ ## Setup
49
+
50
+ 1. Install dependencies: `bun install`
51
+ 2. Copy the environment template and fill in your own values: `cp .env.sample .env`
52
+ 3. Type-check: `bun run typecheck`
53
+ 4. Run the unit test suite: `bun run test:unit`
54
+ 5. Build: `bun run build`
55
+
56
+ ## Releasing
57
+
58
+ Releases are computed by [semantic-release](https://semantic-release.gitbook.io/) from commit messages on
59
+ every push to `main` — see `release.config.js`. Commit headers must follow the conventional-commits format,
60
+ optionally preceded by a hyphenated agent name:
61
+
62
+ ```
63
+ [<agent-name>: ]<type>[(<scope>)][!]: <subject>
64
+ ```
65
+
66
+ - `feat: …` / `<agent-name>: feat: …` → minor release
67
+ - `fix: …` / `<agent-name>: fix: …` → patch release
68
+ - `feat!: …`, or any commit with a `BREAKING CHANGE:` footer → major release
69
+ - `chore: …`, `docs: …`, and other non-releasing types → no release
70
+
71
+ The agent-name prefix must be a lowercase, hyphenated token (e.g. `build-agent`, `plan-orchestrator`) so it
72
+ can never be confused with a conventional type. Every pull request runs a `release-dry-run` CI job that
73
+ prints the version the merge would compute, without publishing anything.
74
+
75
+ Publishing uses npm OIDC trusted publishing (no long-lived npm credential stored in the repository), falling
76
+ back to an `NPM_TOKEN` secret if one is present. The release baseline is the `v1.0.0` git tag on the commit
77
+ of the first manually published version; the release workflow hard-fails if that tag is not reachable, so it
78
+ can never recompute or republish `1.0.0`.
79
+
80
+ ## Domain glossary
81
+
82
+ See [UBIQUITOUS_LANGUAGE.md](./UBIQUITOUS_LANGUAGE.md) for the canonical terms used across this codebase (identity, forge, provider, worktree, etc.).
83
+
84
+ ## Project Structure
85
+
86
+ ```
87
+ .adw/ ADW-generated project docs (project.md, providers.md, commands.md, conditional_docs.md, review_proof.md, scenarios.md)
88
+ .adw-version ADW template version marker
89
+ .claude/
90
+ commands/ ADW-copied slash commands (gitignored except install.md, prime.md)
91
+ hooks/ Claude Code lifecycle hooks (pre/post-tool-use, notification, stop, subagent-stop)
92
+ skills/ Agent skills (TDD, PRD authoring, architecture review, ubiquitous language, ...)
93
+ settings.json Agent permission/guardrail configuration
94
+ .github/
95
+ workflows/ci.yml Typecheck + git/gh guard + unit test CI gate, build/pack/smoke-test package gate, and a PR-only release-dry-run job
96
+ workflows/release.yml Release automation: semantic-release on push to main (v1.0.0 baseline guard, OIDC + NPM_TOKEN fallback)
97
+ adw.yml ADW guardrails toggle (outside .adw/, survives regeneration)
98
+ app_docs/ Per-module documentation owned by conditional_docs.md routing (ADW-generated)
99
+ UBIQUITOUS_LANGUAGE.md Canonical domain glossary
100
+ features/regression/vocabulary.md Regression test vocabulary
101
+ specs/ Per-issue implementation plans (ADW-generated)
102
+ release.config.js semantic-release configuration: agent-prefix-aware commit parser, branches, plugin list
103
+ scripts/
104
+ smokePackage.ts Builds, packs, and smoke-tests the tarball under Node + Bun (`bun run smoke:package`)
105
+ releaseDryRun.ts Runs `semantic-release --dry-run` and prints the computed next version (`bun run release:dry-run`)
106
+ checkGitGhGuard.ts CI git/gh guard entry point (`bun run lint:git-guard`) — dev-only, excluded from dist/
107
+ guard/ Guard rule modules: shell-out exempt-package set, construction allowlist, stdout report
108
+ src/
109
+ index.ts Root entry point ("."): forge ports + domain model only
110
+ __tests__/ Import-graph, package-exports, and release-config contract tests
111
+ git/ Forge-neutral git/worktree core (GitContext, worktree ops, bootstrap identity, process cleanup) — entry point "./git"
112
+ providers/ Forge provider ports and adapters — entry point "./providers"
113
+ github/ GitHub adapter (issue tracker, code host, board manager, App auth, gh CLI commands)
114
+ gitlab/ GitLab adapter (API client, code host, type mappers)
115
+ jira/ Jira adapter (API client, issue tracker, ADF converter)
116
+ forgeProviders.ts Provider assembly function
117
+ types.ts Platform-agnostic provider interfaces
118
+ dist/ Build output (gitignored) — emitted by `bun run build`
119
+ tsconfig.json TypeScript strict-mode configuration (NodeNext modules/resolution)
120
+ tsconfig.build.json Build config: extends tsconfig.json, emits dist/**/*.js + dist/**/*.d.ts
121
+ vitest.config.ts Vitest configuration (JUnit output via $ADW_UNIT_TEST_REPORT_PATH)
122
+ ```
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Bootstrap identity resolution — absorbed into the gitContext package (issue #700).
3
+ *
4
+ * Pre-context git reads: the one legitimate permanent exception for raw git
5
+ * before a GitContext exists. Lives inside the structurally-exempt package so
6
+ * the guard skips it by directory, not by allowlist.
7
+ *
8
+ * Generic **git** reads only (issue #793) — no forge vocabulary. GitHub
9
+ * remote-URL parsing, App bot-identity derivation, and the `gh` CLI
10
+ * credential read all live in the GitHub forge adapter
11
+ * (`adws/providers/github/`), which composes these readers rather than
12
+ * re-implementing them.
13
+ *
14
+ * No ADW-global imports. All I/O is behind injectable seams for hermetic testing.
15
+ */
16
+ import type { GitIdentity } from './types.js';
17
+ export interface GitConfigIdentityDeps {
18
+ exec?: (cmd: string, opts: {
19
+ encoding: 'utf-8';
20
+ cwd?: string;
21
+ stdio?: unknown;
22
+ }) => string;
23
+ env?: NodeJS.ProcessEnv;
24
+ }
25
+ /**
26
+ * Reads the local git remote URL, trimmed. Throws with the raw git failure —
27
+ * parsing (and the forge-specific error wrapping around it) is the adapter's
28
+ * job, not the core's.
29
+ */
30
+ export declare function readOriginRemoteUrl(cwd?: string): string;
31
+ /**
32
+ * Reads the current branch name, trimmed. Throws with the raw git failure on
33
+ * a detached HEAD or any other git failure — the caller decides how to
34
+ * degrade, the core does not guess.
35
+ */
36
+ export declare function readCurrentBranch(cwd?: string): string;
37
+ /**
38
+ * `GIT_AUTHOR_*` / `GIT_COMMITTER_*` env reads. Pure. Returns a complete
39
+ * identity, or null when the author fields are incomplete — the core
40
+ * supplies no fallback of its own (issue #793: no forge address may
41
+ * originate here).
42
+ */
43
+ export declare function readEnvGitIdentity(env: NodeJS.ProcessEnv): GitIdentity | null;
44
+ /**
45
+ * `git config user.name` / `user.email`. Returns a complete identity, or
46
+ * null on any git failure or incomplete config — the core supplies no
47
+ * fallback of its own.
48
+ */
49
+ export declare function readGitConfigIdentity(deps?: GitConfigIdentityDeps): GitIdentity | null;
50
+ //# sourceMappingURL=bootstrapIdentity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrapIdentity.d.ts","sourceRoot":"","sources":["../../src/git/bootstrapIdentity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM9C,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,MAAM,CAAC;IAC3F,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAMD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAEtD;AAMD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,WAAW,GAAG,IAAI,CAU7E;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,GAAE,qBAA0B,GAAG,WAAW,GAAG,IAAI,CAU1F"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Bootstrap identity resolution — absorbed into the gitContext package (issue #700).
3
+ *
4
+ * Pre-context git reads: the one legitimate permanent exception for raw git
5
+ * before a GitContext exists. Lives inside the structurally-exempt package so
6
+ * the guard skips it by directory, not by allowlist.
7
+ *
8
+ * Generic **git** reads only (issue #793) — no forge vocabulary. GitHub
9
+ * remote-URL parsing, App bot-identity derivation, and the `gh` CLI
10
+ * credential read all live in the GitHub forge adapter
11
+ * (`adws/providers/github/`), which composes these readers rather than
12
+ * re-implementing them.
13
+ *
14
+ * No ADW-global imports. All I/O is behind injectable seams for hermetic testing.
15
+ */
16
+ import { execSync } from 'child_process';
17
+ // ---------------------------------------------------------------------------
18
+ // readOriginRemoteUrl
19
+ // ---------------------------------------------------------------------------
20
+ /**
21
+ * Reads the local git remote URL, trimmed. Throws with the raw git failure —
22
+ * parsing (and the forge-specific error wrapping around it) is the adapter's
23
+ * job, not the core's.
24
+ */
25
+ export function readOriginRemoteUrl(cwd) {
26
+ return execSync('git remote get-url origin', { encoding: 'utf-8', cwd }).trim();
27
+ }
28
+ /**
29
+ * Reads the current branch name, trimmed. Throws with the raw git failure on
30
+ * a detached HEAD or any other git failure — the caller decides how to
31
+ * degrade, the core does not guess.
32
+ */
33
+ export function readCurrentBranch(cwd) {
34
+ return execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf-8', cwd }).trim();
35
+ }
36
+ // ---------------------------------------------------------------------------
37
+ // readEnvGitIdentity / readGitConfigIdentity
38
+ // ---------------------------------------------------------------------------
39
+ /**
40
+ * `GIT_AUTHOR_*` / `GIT_COMMITTER_*` env reads. Pure. Returns a complete
41
+ * identity, or null when the author fields are incomplete — the core
42
+ * supplies no fallback of its own (issue #793: no forge address may
43
+ * originate here).
44
+ */
45
+ export function readEnvGitIdentity(env) {
46
+ const authorName = env['GIT_AUTHOR_NAME'];
47
+ const authorEmail = env['GIT_AUTHOR_EMAIL'];
48
+ const committerName = env['GIT_COMMITTER_NAME'] || authorName;
49
+ const committerEmail = env['GIT_COMMITTER_EMAIL'] || authorEmail;
50
+ if (authorName && authorEmail && committerName && committerEmail) {
51
+ return { authorName, authorEmail, committerName, committerEmail };
52
+ }
53
+ return null;
54
+ }
55
+ /**
56
+ * `git config user.name` / `user.email`. Returns a complete identity, or
57
+ * null on any git failure or incomplete config — the core supplies no
58
+ * fallback of its own.
59
+ */
60
+ export function readGitConfigIdentity(deps = {}) {
61
+ const exec = deps.exec ?? ((cmd, opts) => execSync(cmd, opts));
62
+ try {
63
+ const name = exec('git config user.name', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
64
+ const email = exec('git config user.email', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
65
+ if (name && email) {
66
+ return { authorName: name, authorEmail: email, committerName: name, committerEmail: email };
67
+ }
68
+ }
69
+ catch { /* git config not available */ }
70
+ return null;
71
+ }
72
+ //# sourceMappingURL=bootstrapIdentity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrapIdentity.js","sourceRoot":"","sources":["../../src/git/bootstrapIdentity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAYzC,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAY;IAC9C,OAAO,QAAQ,CAAC,2BAA2B,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAClF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,OAAO,QAAQ,CAAC,iCAAiC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACxF,CAAC;AAED,8EAA8E;AAC9E,6CAA6C;AAC7C,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAsB;IACvD,MAAM,UAAU,GAAG,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAC5C,MAAM,aAAa,GAAG,GAAG,CAAC,oBAAoB,CAAC,IAAI,UAAU,CAAC;IAC9D,MAAM,cAAc,GAAG,GAAG,CAAC,qBAAqB,CAAC,IAAI,WAAW,CAAC;IAEjE,IAAI,UAAU,IAAI,WAAW,IAAI,aAAa,IAAI,cAAc,EAAE,CAAC;QACjE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC;IACpE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAA8B,EAAE;IACpE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAsC,CAAW,CAAC,CAAC;IAC3G,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,sBAAsB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACzG,MAAM,KAAK,GAAG,IAAI,CAAC,uBAAuB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3G,IAAI,IAAI,IAAI,KAAK,EAAE,CAAC;YAClB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;QAC9F,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,8BAA8B,CAAC,CAAC;IAC1C,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Package-private branch operation orchestration for GitContext.
3
+ * Each function takes an injected runner (cmd, cwd) => string so GitContext
4
+ * methods stay thin and this module is testable without a real context.
5
+ */
6
+ export declare const PROTECTED_BRANCHES: readonly ["main", "master", "develop"];
7
+ type Runner = (command: string, cwd: string) => string;
8
+ declare function getCurrentBranch(run: Runner, cwd: string): string;
9
+ declare function mergeLatestFromDefaultBranch(run: Runner, defaultBranch: string, cwd: string): void;
10
+ declare function fetchAndResetToRemote(run: Runner, defaultBranch: string, cwd: string): void;
11
+ declare function deleteLocalBranch(run: Runner, branch: string, cwd: string): boolean;
12
+ declare function deleteRemoteBranch(run: Runner, branch: string, cwd: string): boolean;
13
+ /**
14
+ * Returns local branch names from `git branch --list`.
15
+ * Strips the leading `*`/whitespace marker; returns [] on failure.
16
+ */
17
+ declare function localBranches(run: Runner, cwd: string): string[];
18
+ export declare const branchOps: {
19
+ getCurrentBranch: typeof getCurrentBranch;
20
+ mergeLatestFromDefaultBranch: typeof mergeLatestFromDefaultBranch;
21
+ fetchAndResetToRemote: typeof fetchAndResetToRemote;
22
+ deleteLocalBranch: typeof deleteLocalBranch;
23
+ deleteRemoteBranch: typeof deleteRemoteBranch;
24
+ localBranches: typeof localBranches;
25
+ };
26
+ export {};
27
+ //# sourceMappingURL=branchOps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branchOps.d.ts","sourceRoot":"","sources":["../../src/git/branchOps.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,kBAAkB,wCAAyC,CAAC;AAEzE,KAAK,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;AAMvD,iBAAS,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,iBAAS,4BAA4B,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAY3F;AAED,iBAAS,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAWpF;AAED,iBAAS,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAQ5E;AAED,iBAAS,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAQ7E;AAED;;;GAGG;AACH,iBAAS,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAYzD;AAED,eAAO,MAAM,SAAS;;;;;;;CAOrB,CAAC"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Package-private branch operation orchestration for GitContext.
3
+ * Each function takes an injected runner (cmd, cwd) => string so GitContext
4
+ * methods stay thin and this module is testable without a real context.
5
+ */
6
+ export const PROTECTED_BRANCHES = ['main', 'master', 'develop'];
7
+ function isProtected(branch) {
8
+ return PROTECTED_BRANCHES.includes(branch);
9
+ }
10
+ function getCurrentBranch(run, cwd) {
11
+ return run('git branch --show-current', cwd);
12
+ }
13
+ function mergeLatestFromDefaultBranch(run, defaultBranch, cwd) {
14
+ try {
15
+ run(`git fetch origin "${defaultBranch}"`, cwd);
16
+ }
17
+ catch (_err) {
18
+ // warn-don't-throw: fetch failure should not abort the workflow
19
+ return;
20
+ }
21
+ try {
22
+ run(`git merge "origin/${defaultBranch}" --no-edit`, cwd);
23
+ }
24
+ catch (_err) {
25
+ // warn-don't-throw: merge conflicts are non-fatal here
26
+ }
27
+ }
28
+ function fetchAndResetToRemote(run, defaultBranch, cwd) {
29
+ try {
30
+ run(`git fetch origin "${defaultBranch}"`, cwd);
31
+ }
32
+ catch (error) {
33
+ throw new Error(`Failed to fetch origin/${defaultBranch}: ${error}`);
34
+ }
35
+ try {
36
+ run(`git reset --hard "origin/${defaultBranch}"`, cwd);
37
+ }
38
+ catch (error) {
39
+ throw new Error(`Failed to reset to origin/${defaultBranch}: ${error}`);
40
+ }
41
+ }
42
+ function deleteLocalBranch(run, branch, cwd) {
43
+ if (isProtected(branch))
44
+ return false;
45
+ try {
46
+ run(`git branch -D "${branch}"`, cwd);
47
+ return true;
48
+ }
49
+ catch {
50
+ return false;
51
+ }
52
+ }
53
+ function deleteRemoteBranch(run, branch, cwd) {
54
+ if (isProtected(branch))
55
+ return false;
56
+ try {
57
+ run(`git push origin --delete "${branch}"`, cwd);
58
+ return true;
59
+ }
60
+ catch {
61
+ return false;
62
+ }
63
+ }
64
+ /**
65
+ * Returns local branch names from `git branch --list`.
66
+ * Strips the leading `*`/whitespace marker; returns [] on failure.
67
+ */
68
+ function localBranches(run, cwd) {
69
+ try {
70
+ const output = run('git branch --list', cwd);
71
+ const branches = [];
72
+ for (const line of output.split('\n')) {
73
+ const branch = line.replace(/^\*?\s+/, '').trim();
74
+ if (branch)
75
+ branches.push(branch);
76
+ }
77
+ return branches;
78
+ }
79
+ catch {
80
+ return [];
81
+ }
82
+ }
83
+ export const branchOps = {
84
+ getCurrentBranch,
85
+ mergeLatestFromDefaultBranch,
86
+ fetchAndResetToRemote,
87
+ deleteLocalBranch,
88
+ deleteRemoteBranch,
89
+ localBranches,
90
+ };
91
+ //# sourceMappingURL=branchOps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branchOps.js","sourceRoot":"","sources":["../../src/git/branchOps.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Package-private op module for the upgrade-claim distributed-lock git verbs.
3
+ *
4
+ * These four ops are NOT delegated to the standard GitContext worktree/commit/push
5
+ * methods — doing so would silently break the winner/loser election:
6
+ *
7
+ * - addDetachedWorktree: standard methods create a named local branch; the claim
8
+ * needs DETACHED HEAD at an arbitrary system-temp path with no local branch
9
+ * (a leftover named branch causes "already exists" on the next attempt, bypassing
10
+ * the loser path).
11
+ * - commitAllowEmpty: commitChanges() short-circuits on a clean tree; the claim
12
+ * always needs an empty commit carrying the unique nonce.
13
+ * - pushHeadToBranch: pushBranch() uses --force-with-lease; the claim push must
14
+ * NEVER be forced — the non-fast-forward rejection IS the atomic lock.
15
+ * - removeDetachedWorktree: best-effort cleanup that swallows errors (mirrors
16
+ * remoteOps.abortMerge).
17
+ *
18
+ * All errors except removeDetachedWorktree propagate to the caller.
19
+ */
20
+ type Runner = (command: string, cwd: string) => string;
21
+ declare function addDetachedWorktree(run: Runner, worktreePath: string, ref: string, cwd: string): void;
22
+ declare function commitAllowEmpty(run: Runner, message: string, cwd: string): void;
23
+ /**
24
+ * Pushes HEAD to a remote branch ref WITHOUT any force flag.
25
+ *
26
+ * CRITICAL: This push MUST NOT carry --force or --force-with-lease.
27
+ * The non-fast-forward rejection from the remote IS the distributed lock.
28
+ * A force push would let a second claimant overwrite the winner's branch,
29
+ * collapsing the exactly-one-winner election into a last-writer-wins race.
30
+ */
31
+ declare function pushHeadToBranch(run: Runner, branch: string, cwd: string): void;
32
+ declare function removeDetachedWorktree(run: Runner, worktreePath: string, cwd: string): void;
33
+ export declare const claimOps: {
34
+ addDetachedWorktree: typeof addDetachedWorktree;
35
+ commitAllowEmpty: typeof commitAllowEmpty;
36
+ pushHeadToBranch: typeof pushHeadToBranch;
37
+ removeDetachedWorktree: typeof removeDetachedWorktree;
38
+ };
39
+ export {};
40
+ //# sourceMappingURL=claimOps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claimOps.d.ts","sourceRoot":"","sources":["../../src/git/claimOps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,KAAK,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;AAEvD,iBAAS,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAE9F;AAED,iBAAS,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAEzE;AAED;;;;;;;GAOG;AACH,iBAAS,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAExE;AAED,iBAAS,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAIpF;AAED,eAAO,MAAM,QAAQ;;;;;CAAsF,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Package-private op module for the upgrade-claim distributed-lock git verbs.
3
+ *
4
+ * These four ops are NOT delegated to the standard GitContext worktree/commit/push
5
+ * methods — doing so would silently break the winner/loser election:
6
+ *
7
+ * - addDetachedWorktree: standard methods create a named local branch; the claim
8
+ * needs DETACHED HEAD at an arbitrary system-temp path with no local branch
9
+ * (a leftover named branch causes "already exists" on the next attempt, bypassing
10
+ * the loser path).
11
+ * - commitAllowEmpty: commitChanges() short-circuits on a clean tree; the claim
12
+ * always needs an empty commit carrying the unique nonce.
13
+ * - pushHeadToBranch: pushBranch() uses --force-with-lease; the claim push must
14
+ * NEVER be forced — the non-fast-forward rejection IS the atomic lock.
15
+ * - removeDetachedWorktree: best-effort cleanup that swallows errors (mirrors
16
+ * remoteOps.abortMerge).
17
+ *
18
+ * All errors except removeDetachedWorktree propagate to the caller.
19
+ */
20
+ function addDetachedWorktree(run, worktreePath, ref, cwd) {
21
+ run(`git worktree add --detach "${worktreePath}" "${ref}"`, cwd);
22
+ }
23
+ function commitAllowEmpty(run, message, cwd) {
24
+ run(`git commit --allow-empty -m "${message.replace(/"/g, '\\"')}"`, cwd);
25
+ }
26
+ /**
27
+ * Pushes HEAD to a remote branch ref WITHOUT any force flag.
28
+ *
29
+ * CRITICAL: This push MUST NOT carry --force or --force-with-lease.
30
+ * The non-fast-forward rejection from the remote IS the distributed lock.
31
+ * A force push would let a second claimant overwrite the winner's branch,
32
+ * collapsing the exactly-one-winner election into a last-writer-wins race.
33
+ */
34
+ function pushHeadToBranch(run, branch, cwd) {
35
+ run(`git push origin "HEAD:refs/heads/${branch}"`, cwd);
36
+ }
37
+ function removeDetachedWorktree(run, worktreePath, cwd) {
38
+ try {
39
+ run(`git worktree remove --force "${worktreePath}"`, cwd);
40
+ }
41
+ catch { /* best-effort cleanup */ }
42
+ }
43
+ export const claimOps = { addDetachedWorktree, commitAllowEmpty, pushHeadToBranch, removeDetachedWorktree };
44
+ //# sourceMappingURL=claimOps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claimOps.js","sourceRoot":"","sources":["../../src/git/claimOps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,SAAS,mBAAmB,CAAC,GAAW,EAAE,YAAoB,EAAE,GAAW,EAAE,GAAW;IACtF,GAAG,CAAC,8BAA8B,YAAY,MAAM,GAAG,GAAG,EAAE,GAAG,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW,EAAE,OAAe,EAAE,GAAW;IACjE,GAAG,CAAC,gCAAgC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAC5E,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,gBAAgB,CAAC,GAAW,EAAE,MAAc,EAAE,GAAW;IAChE,GAAG,CAAC,oCAAoC,MAAM,GAAG,EAAE,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,sBAAsB,CAAC,GAAW,EAAE,YAAoB,EAAE,GAAW;IAC5E,IAAI,CAAC;QACH,GAAG,CAAC,gCAAgC,YAAY,GAAG,EAAE,GAAG,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC,CAAC,yBAAyB,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Package-private commit/push operation orchestration for GitContext.
3
+ */
4
+ type Runner = (command: string, cwd: string) => string;
5
+ export declare function isLeaseRejection(error: unknown): boolean;
6
+ declare function commitChanges(run: Runner, message: string, cwd: string, opts?: {
7
+ excludePaths?: readonly string[];
8
+ }): boolean;
9
+ /**
10
+ * Removes `paths` from the index/working tree and, only if that staged something
11
+ * for those exact pathspecs, commits scoped to `paths` — unrelated staged/dirty
12
+ * state elsewhere in the tree is left untouched. `--ignore-unmatch` keeps the
13
+ * removal idempotent when a path is already absent from the index.
14
+ */
15
+ declare function removeAndCommitPaths(run: Runner, paths: readonly string[], message: string, cwd: string): boolean;
16
+ /**
17
+ * Stages and commits `paths` scoped to exactly those pathspecs — the modify
18
+ * counterpart to `removeAndCommitPaths`. Only commits if `git status --porcelain`
19
+ * scoped to `paths` reports something staged for them; unrelated dirty state
20
+ * elsewhere in the tree is never touched (no `git add -A`).
21
+ */
22
+ declare function addAndCommitPaths(run: Runner, paths: readonly string[], message: string, cwd: string): boolean;
23
+ declare function pushBranch(run: Runner, branch: string, cwd: string): void;
24
+ declare function getHeadTreeHash(run: Runner, cwd: string): string;
25
+ declare function hasUncommittedChanges(run: Runner, cwd: string): boolean;
26
+ export declare const commitOps: {
27
+ commitChanges: typeof commitChanges;
28
+ removeAndCommitPaths: typeof removeAndCommitPaths;
29
+ addAndCommitPaths: typeof addAndCommitPaths;
30
+ pushBranch: typeof pushBranch;
31
+ getHeadTreeHash: typeof getHeadTreeHash;
32
+ hasUncommittedChanges: typeof hasUncommittedChanges;
33
+ };
34
+ export {};
35
+ //# sourceMappingURL=commitOps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commitOps.d.ts","sourceRoot":"","sources":["../../src/git/commitOps.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,KAAK,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;AAIvD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAMxD;AAkDD,iBAAS,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAAG,OAAO,CAOtH;AAED;;;;;GAKG;AACH,iBAAS,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAQ1G;AAED;;;;;GAKG;AACH,iBAAS,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAQvG;AAED,iBAAS,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAclE;AAED,iBAAS,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,iBAAS,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED,eAAO,MAAM,SAAS;;;;;;;CAOrB,CAAC"}