pushary 1.9.90 → 1.9.92

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 (128) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/data/cursor-plugin/scripts/pushary-gate.mjs +34 -9
  3. package/data/vscode-plugin/scripts/pushary-gate.mjs +34 -9
  4. package/dist/{api-ORGHXO4N.js → api-QUARGXSY.js} +10 -10
  5. package/dist/bin/pushary-bell-hook.js +26 -26
  6. package/dist/bin/pushary-bell.js +10 -10
  7. package/dist/bin/pushary-claude.js +30 -29
  8. package/dist/bin/pushary-clean.js +34 -34
  9. package/dist/bin/pushary-codex-bridge.js +21 -21
  10. package/dist/bin/pushary-codex-hook.js +35 -34
  11. package/dist/bin/pushary-codex-session.js +8 -8
  12. package/dist/bin/pushary-codex.js +14 -14
  13. package/dist/bin/pushary-connect.js +27 -27
  14. package/dist/bin/pushary-cowork.js +5 -5
  15. package/dist/bin/pushary-daemon.js +39 -39
  16. package/dist/bin/pushary-disconnect.js +26 -26
  17. package/dist/bin/pushary-display-hook.js +17 -17
  18. package/dist/bin/pushary-doctor.js +45 -48
  19. package/dist/bin/pushary-elicitation-hook.js +26 -26
  20. package/dist/bin/pushary-gemini-bridge.js +15 -15
  21. package/dist/bin/pushary-gemini-hook.js +28 -28
  22. package/dist/bin/pushary-hook.js +30 -30
  23. package/dist/bin/pushary-login.js +20 -20
  24. package/dist/bin/pushary-logout.js +25 -25
  25. package/dist/bin/pushary-mcp.js +11 -11
  26. package/dist/bin/pushary-mode.js +15 -15
  27. package/dist/bin/pushary-notification-hook.js +25 -25
  28. package/dist/bin/pushary-opencode-hook.js +27 -27
  29. package/dist/bin/pushary-permission-denied-hook.js +30 -30
  30. package/dist/bin/pushary-permission-hook.js +30 -30
  31. package/dist/bin/pushary-post-hook.js +25 -25
  32. package/dist/bin/pushary-prompt-hook.js +25 -25
  33. package/dist/bin/pushary-session-end-hook.js +27 -27
  34. package/dist/bin/pushary-session-start-hook.js +35 -35
  35. package/dist/bin/pushary-setup.js +50 -49
  36. package/dist/bin/pushary-stats.js +5 -5
  37. package/dist/bin/pushary-status.js +32 -32
  38. package/dist/bin/pushary-stop-hook.js +25 -25
  39. package/dist/bin/pushary-stopfailure-hook.js +25 -25
  40. package/dist/bin/pushary-suggestions.js +15 -15
  41. package/dist/bin/pushary-transcript-register.js +18 -18
  42. package/dist/bin/pushary-transcripts.js +26 -26
  43. package/dist/bin/pushary-upgrade.js +40 -40
  44. package/dist/bin/pushary-wait.js +15 -15
  45. package/dist/bin/pushary.js +7 -7
  46. package/dist/{chunk-FAM2TLFC.js → chunk-2BVVMWVF.js} +47 -8
  47. package/dist/{chunk-NMDWW3EY.js → chunk-2BXWBKVN.js} +3 -3
  48. package/dist/{chunk-2RUJIPNN.js → chunk-2FL5PLA4.js} +2 -2
  49. package/dist/{chunk-KT25MC57.js → chunk-373552A3.js} +4 -4
  50. package/dist/{chunk-G7GVI5RL.js → chunk-3CJFBWID.js} +3 -3
  51. package/dist/{chunk-WGBW66IO.js → chunk-3JVV6PMG.js} +5 -5
  52. package/dist/{chunk-TOPXBWUN.js → chunk-4HQTZQ4D.js} +2 -2
  53. package/dist/{chunk-XO3UJDJE.js → chunk-4PD7FP55.js} +2 -2
  54. package/dist/{chunk-EFQQLEWW.js → chunk-5TQC2LS6.js} +4 -4
  55. package/dist/{chunk-K2NIENKY.js → chunk-66VEUAN5.js} +1 -1
  56. package/dist/{chunk-V4ZLZYQ4.js → chunk-6QH4MWCW.js} +3 -3
  57. package/dist/{chunk-OGR5WSHI.js → chunk-76ROCOWD.js} +7 -7
  58. package/dist/{chunk-OODEIR3Z.js → chunk-7DOSRSRU.js} +38 -20
  59. package/dist/{chunk-TTXUWHBL.js → chunk-7PQ66CB3.js} +1 -1
  60. package/dist/{chunk-53YQO4HL.js → chunk-7S3LH5AX.js} +11 -11
  61. package/dist/{chunk-2EOTXWFK.js → chunk-7YB2XRY7.js} +3 -3
  62. package/dist/{chunk-APT7KJ5I.js → chunk-ANDG4PUV.js} +6 -6
  63. package/dist/{chunk-VMUBIBHQ.js → chunk-B6WYXY32.js} +7 -7
  64. package/dist/{chunk-GKDVI6WX.js → chunk-BETKU76V.js} +3 -3
  65. package/dist/{chunk-ALT4KW5M.js → chunk-CA4PS7XT.js} +5 -5
  66. package/dist/{chunk-HT5WOP2M.js → chunk-CFD3IESN.js} +6 -6
  67. package/dist/{chunk-7EGNVZLK.js → chunk-CHVXLS7U.js} +2 -2
  68. package/dist/{chunk-I567L2KG.js → chunk-CI6VDIHW.js} +10 -10
  69. package/dist/{chunk-QCSPLJL6.js → chunk-CO6TQ44W.js} +3 -3
  70. package/dist/{chunk-CNFM6JEV.js → chunk-CSUO5YJG.js} +2 -2
  71. package/dist/{chunk-AF3OHGKE.js → chunk-DV7LLH25.js} +1 -1
  72. package/dist/{chunk-3EVOYLXQ.js → chunk-DYNMKVNO.js} +5 -5
  73. package/dist/{chunk-OEPP5VUW.js → chunk-F2CWT6Y6.js} +6 -6
  74. package/dist/{chunk-CE2ISNPN.js → chunk-FCBFWXPE.js} +5 -5
  75. package/dist/{chunk-5DTOMJVD.js → chunk-FTJ5DQL7.js} +2 -2
  76. package/dist/{chunk-ALTGRWSO.js → chunk-GDVS6J4R.js} +1 -1
  77. package/dist/{chunk-MWXX34K4.js → chunk-GLA6MCOG.js} +1 -1
  78. package/dist/{chunk-XBXBX7YF.js → chunk-H4MIOBC6.js} +2 -2
  79. package/dist/{chunk-CDBGZWPY.js → chunk-HUNGCBCF.js} +3 -3
  80. package/dist/{chunk-OH67LB2U.js → chunk-INSLGCGD.js} +18 -17
  81. package/dist/{chunk-LJFITB6T.js → chunk-ITGPUTFV.js} +4 -4
  82. package/dist/{chunk-DADN6GJO.js → chunk-JJWZIPDL.js} +4 -4
  83. package/dist/{chunk-2U6FPMXG.js → chunk-JZ2MRWC4.js} +3 -3
  84. package/dist/{chunk-HKGGENVU.js → chunk-KJ752DUH.js} +6 -6
  85. package/dist/{chunk-LGQQUQDZ.js → chunk-LANGH7UF.js} +4 -4
  86. package/dist/{chunk-7BEQB3X4.js → chunk-LTMMFZHG.js} +1 -1
  87. package/dist/{chunk-6P4II3ZL.js → chunk-N7CPX5S5.js} +5 -5
  88. package/dist/{chunk-E4XGV5UG.js → chunk-NDPOESVW.js} +1 -1
  89. package/dist/{chunk-ASTOMXHJ.js → chunk-NHGOCUX7.js} +1 -1
  90. package/dist/{chunk-32F3BWRY.js → chunk-NPZ5L2WQ.js} +1 -1
  91. package/dist/{chunk-NIZ6ITRH.js → chunk-NZKH2RMQ.js} +1 -1
  92. package/dist/{chunk-7MN3KPHM.js → chunk-OC47FGOY.js} +1 -1
  93. package/dist/{chunk-INNH7EUK.js → chunk-OFQJHWAS.js} +12 -10
  94. package/dist/{chunk-VE333PL5.js → chunk-OMN5UCMW.js} +120 -69
  95. package/dist/{chunk-Y5BPNOJI.js → chunk-PFHU3CW4.js} +1 -1
  96. package/dist/{chunk-6B4O7XNC.js → chunk-PS2K6ZQ3.js} +12 -11
  97. package/dist/{chunk-P4OZVK2B.js → chunk-R3EUVK3A.js} +4 -4
  98. package/dist/{chunk-XRSE2PAM.js → chunk-RXAQOAZI.js} +3 -3
  99. package/dist/{chunk-K6QLKUCT.js → chunk-RXQT5FTX.js} +52 -11
  100. package/dist/{chunk-6LJOCQBB.js → chunk-SPPMPM7F.js} +1 -1
  101. package/dist/{chunk-FSJYYZ3G.js → chunk-SR44ZNZF.js} +5 -5
  102. package/dist/{chunk-QUKDNQ4L.js → chunk-UGGACQMD.js} +3 -3
  103. package/dist/{chunk-3N4GETIW.js → chunk-UHS3JZLN.js} +2 -2
  104. package/dist/{chunk-4V25M4X5.js → chunk-UNPDFIPQ.js} +2 -2
  105. package/dist/{chunk-JJNO3ACZ.js → chunk-UZRKR6NZ.js} +3 -3
  106. package/dist/{chunk-URJHH72Z.js → chunk-V3LBQFQM.js} +1 -1
  107. package/dist/{chunk-E3EJARHF.js → chunk-V7TNHTHH.js} +1 -1
  108. package/dist/{chunk-72UCLJJW.js → chunk-VMIWR724.js} +1 -1
  109. package/dist/{chunk-VTF6EYVB.js → chunk-VTCSUU4R.js} +5 -5
  110. package/dist/{chunk-SJCPI4WT.js → chunk-WW4OMRZX.js} +1 -1
  111. package/dist/{chunk-XIPP777K.js → chunk-X3AHEUQ5.js} +3 -3
  112. package/dist/{chunk-NWSGMYX7.js → chunk-XTNCXIYR.js} +4 -4
  113. package/dist/{chunk-I7UZODYO.js → chunk-Y7AX6BS4.js} +3 -3
  114. package/dist/{chunk-G7MVZHMM.js → chunk-YLCNW7YN.js} +2 -2
  115. package/dist/{chunk-JQUMX7YZ.js → chunk-YT3ENXBT.js} +2 -2
  116. package/dist/{codex-app-cards-switch-UQ7TGFYV.js → codex-app-cards-switch-XP2H2CZO.js} +11 -11
  117. package/dist/{codex-desktop-launch-O5FWONZ7.js → codex-desktop-launch-QRFE2GHZ.js} +1 -1
  118. package/dist/{codex-session-launch-MTKJC2RH.js → codex-session-launch-EUUWALWW.js} +18 -18
  119. package/dist/{config-EGBMIS5K.js → config-WBDMUTD4.js} +3 -3
  120. package/dist/{global-upgrade-QOAUUHZ6.js → global-upgrade-ZXFLRGGV.js} +10 -10
  121. package/dist/{identity-Z5TRRQL5.js → identity-NUQ75BP7.js} +4 -4
  122. package/dist/{live-capabilities-M4HOY7EM.js → live-capabilities-SIQ25SSK.js} +5 -5
  123. package/dist/{paths-ZOS6Y3PS.js → paths-BGO6PZFZ.js} +3 -3
  124. package/dist/{reapply-PYDRWYKU.js → reapply-QOXNSRFA.js} +28 -28
  125. package/dist/src/index.js +29 -29
  126. package/dist/{upgrade-lock-QZOSOFK5.js → upgrade-lock-B5HTMEWT.js} +4 -4
  127. package/dist/{usage-4FVOG3QN.js → usage-YHFALPKW.js} +3 -3
  128. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.9.92
4
+
5
+ - Team workspaces can connect reported tool actions to the corresponding human decision when the agent supplies that evidence. Missing outcomes stay unknown.
6
+ - Reported repository branch and commit evidence appears in the optional engineering sprint record.
7
+
8
+ - In a repository with no git remote, "Always allow ... in this repository" now also covers that repository's linked git worktrees, such as the ones Claude Code creates for parallel subagents under `.claude/worktrees/`. Pushary named each worktree, or the folder inside it the agent was working in, as a repository of its own, so allowing edits for one subagent did not reach the others and they kept asking. Rules saved in the main checkout, denies included, now apply in its worktrees.
9
+ - Existing worktree-specific denies remain enforced. Existing worktree-specific allows do not expand to the whole repository; you may be asked again. New repository grants apply across its linked worktrees.
10
+ - A repository checked out inside a folder named `worktrees`, or itself named `worktrees`, is now identified by its git remote, so a rule saved for that repository from another checkout applies there. Existing denies saved under its folder name remain enforced; existing allows do not expand silently.
11
+ - A submodule inside a linked worktree is identified as its own repository instead of as the superproject.
12
+ - With no git remote, worktrees of a bare repository named like `project.git`, or of one made with `--separate-git-dir`, are still identified one by one.
13
+ - The Cursor and VS Code gates name repositories the same way, and on Windows they now recognise the worktrees Git for Windows creates by default. An installed gate is replaced when you run `npx pushary@latest setup` again; `pushary upgrade` does not replace it.
14
+
15
+ ## 1.9.91
16
+
17
+ - `pushary setup` no longer fails just because Stop all agents is on. The stop used to hold back setup's test notification, so for that hour every setup said your phone was unreachable. The stop no longer holds it back. In setup and `pushary doctor --roundtrip`, the test question now says the agents are stopped and when the stop lifts, instead of saying nobody answered.
18
+ - When approvals are set to In agent, setup and doctor no longer wait 55 seconds and then report that nobody answered a test question that never went to your phone. They say where the question went and how to get approvals on your phone again. The same goes for a mute set from your phone.
19
+
3
20
  ## 1.9.90
4
21
 
5
22
  - Gemini, Cursor and Hermes history read from their session files no longer trusts a new phone key on first use when this computer already trusts a phone for its Claude and Codex history. A session started after the phone moved uploads nothing until you verify the new phone with `pushary transcripts trust --fingerprint <fingerprint-from-phone-settings>`, then follows it. A computer that has never trusted a phone still trusts the first one it is offered.
@@ -104,7 +104,7 @@ const normalizeRepoRemote = (remoteUrl) => {
104
104
  return `${host}/${path}`.replace(/\.git$/i, '').toLowerCase().slice(0, REPO_KEY_MAX_LENGTH)
105
105
  }
106
106
 
107
- const findGitDir = (startDir) => {
107
+ const findGitDir = (startDir, legacy = false) => {
108
108
  let current = startDir
109
109
  for (let depth = 0; depth < MAX_PARENT_WALK; depth += 1) {
110
110
  const candidate = join(current, '.git')
@@ -114,7 +114,7 @@ const findGitDir = (startDir) => {
114
114
  // A directory read throws EISDIR, which is the ordinary-clone case.
115
115
  if (pointer.startsWith('gitdir:')) {
116
116
  const target = pointer.slice('gitdir:'.length).trim()
117
- return target.startsWith('/') ? target : join(current, target)
117
+ return (legacy ? target.startsWith('/') : isAbsolute(target)) ? target : join(current, target)
118
118
  }
119
119
  }
120
120
  } catch (error) {
@@ -127,7 +127,23 @@ const findGitDir = (startDir) => {
127
127
  return undefined
128
128
  }
129
129
 
130
- const deriveRepoKey = (cwd) => {
130
+ const mainGitDirOf = (gitDir) => {
131
+ try {
132
+ const pointer = readFileSync(join(gitDir, 'commondir'), 'utf-8').trim()
133
+ if (!pointer) return gitDir
134
+ return isAbsolute(pointer) ? pointer : resolve(gitDir, pointer)
135
+ } catch {
136
+ return gitDir
137
+ }
138
+ }
139
+
140
+ const projectRootOf = (gitDir, cwd) => {
141
+ const mainGitDir = mainGitDirOf(gitDir)
142
+ if (basename(mainGitDir) === '.git') return dirname(mainGitDir)
143
+ return gitDir.endsWith('.git') ? dirname(gitDir) : cwd
144
+ }
145
+
146
+ const deriveRepoKey = (cwd, legacy = false) => {
131
147
  const override = process.env.PUSHARY_REPO_KEY
132
148
  if (typeof override === 'string') {
133
149
  const trimmed = override.trim()
@@ -136,11 +152,13 @@ const deriveRepoKey = (cwd) => {
136
152
  }
137
153
  const dir = cwd || process.cwd()
138
154
  try {
139
- const gitDir = findGitDir(dir)
155
+ const gitDir = findGitDir(dir, legacy)
140
156
  if (gitDir) {
141
157
  // A worktree's config lives in the main git directory.
142
- const wt = gitDir.replace(/\\/g, '/').indexOf('/worktrees/')
143
- const configPath = wt === -1 ? join(gitDir, 'config') : join(gitDir.slice(0, wt), 'config')
158
+ const oldIndex = gitDir.replace(/\\/g, '/').indexOf('/worktrees/')
159
+ const configPath = legacy
160
+ ? join(oldIndex === -1 ? gitDir : gitDir.slice(0, oldIndex), 'config')
161
+ : join(mainGitDirOf(gitDir), 'config')
144
162
  if (existsSync(configPath)) {
145
163
  let inOrigin = false
146
164
  for (const rawLine of readFileSync(configPath, 'utf-8').split('\n')) {
@@ -154,7 +172,7 @@ const deriveRepoKey = (cwd) => {
154
172
  }
155
173
  }
156
174
  }
157
- const root = gitDir.endsWith('.git') ? dirname(gitDir) : dir
175
+ const root = legacy ? (gitDir.endsWith('.git') ? dirname(gitDir) : dir) : projectRootOf(gitDir, dir)
158
176
  return `local/${basename(root).toLowerCase()}`.slice(0, REPO_KEY_MAX_LENGTH)
159
177
  }
160
178
  return `local/${basename(dir).toLowerCase()}`.slice(0, REPO_KEY_MAX_LENGTH)
@@ -163,6 +181,13 @@ const deriveRepoKey = (cwd) => {
163
181
  }
164
182
  }
165
183
 
184
+ const repositoryScopeFor = (cwd) => {
185
+ const repoKey = deriveRepoKey(cwd, true)
186
+ const sharedRepoKey = deriveRepoKey(cwd)
187
+ return { repoKey, ...(sharedRepoKey && sharedRepoKey !== repoKey ? { sharedRepoKey } : {}) }
188
+ }
189
+
190
+
166
191
  // Env first. CLI installs inject the key into the sibling mcp.json, so fall back to
167
192
  // that. This lets the gate work even when Cursor's GUI does not pass the shell env.
168
193
  const resolveApiKey = () => {
@@ -254,7 +279,7 @@ const decide = async (apiKey, request, cwd, sessionId) => {
254
279
  toolName: request.toolName,
255
280
  toolInputs: request.toolInputs,
256
281
  cwd,
257
- repoKey: deriveRepoKey(cwd),
282
+ ...repositoryScopeFor(cwd),
258
283
  sessionId,
259
284
  }),
260
285
  signal: AbortSignal.timeout(GATE_TIMEOUT_MS),
@@ -720,7 +745,7 @@ setTimeout(async () => {
720
745
 
721
746
  // Exported for scripts/pushary-gate.test.mjs. main() only runs when the gate is
722
747
  // executed directly, so importing this file for a test does not read stdin.
723
- export { normalizeRepoRemote, deriveRepoKey, describeRequest, handlePushOnly, handlePushFirst, withdraw, approvalModeWithoutLocalPrompt, timeoutActionWithoutLocalPrompt }
748
+ export { normalizeRepoRemote, deriveRepoKey, repositoryScopeFor, describeRequest, handlePushOnly, handlePushFirst, withdraw, approvalModeWithoutLocalPrompt, timeoutActionWithoutLocalPrompt }
724
749
 
725
750
  const isDirectRun = process.argv[1] && import.meta.url === `file://${process.argv[1]}`
726
751
  if (!isDirectRun) {
@@ -227,7 +227,7 @@ const decide = async (apiKey, command, cwd, sessionId, ident = {}) => {
227
227
  source: 'vscode',
228
228
  toolName: ident.toolName ?? 'Bash',
229
229
  toolInputs: ident.toolInputs ?? [{ command }],
230
- repoKey: deriveRepoKey(cwd),
230
+ ...repositoryScopeFor(cwd),
231
231
  cwd,
232
232
  sessionId,
233
233
  }),
@@ -267,7 +267,7 @@ const normalizeRepoRemote = (remoteUrl) => {
267
267
  return `${host}/${path}`.replace(/\.git$/i, '').toLowerCase().slice(0, REPO_KEY_MAX_LENGTH)
268
268
  }
269
269
 
270
- const findGitDir = (startDir) => {
270
+ const findGitDir = (startDir, legacy = false) => {
271
271
  let current = startDir
272
272
  for (let depth = 0; depth < MAX_PARENT_WALK; depth += 1) {
273
273
  const candidate = join(current, '.git')
@@ -277,7 +277,7 @@ const findGitDir = (startDir) => {
277
277
  // A directory read throws EISDIR, which is the ordinary-clone case.
278
278
  if (pointer.startsWith('gitdir:')) {
279
279
  const target = pointer.slice('gitdir:'.length).trim()
280
- return target.startsWith('/') ? target : join(current, target)
280
+ return (legacy ? target.startsWith('/') : isAbsolute(target)) ? target : join(current, target)
281
281
  }
282
282
  }
283
283
  } catch (error) {
@@ -290,7 +290,23 @@ const findGitDir = (startDir) => {
290
290
  return undefined
291
291
  }
292
292
 
293
- const deriveRepoKey = (cwd) => {
293
+ const mainGitDirOf = (gitDir) => {
294
+ try {
295
+ const pointer = readFileSync(join(gitDir, 'commondir'), 'utf-8').trim()
296
+ if (!pointer) return gitDir
297
+ return isAbsolute(pointer) ? pointer : resolve(gitDir, pointer)
298
+ } catch {
299
+ return gitDir
300
+ }
301
+ }
302
+
303
+ const projectRootOf = (gitDir, cwd) => {
304
+ const mainGitDir = mainGitDirOf(gitDir)
305
+ if (basename(mainGitDir) === '.git') return dirname(mainGitDir)
306
+ return gitDir.endsWith('.git') ? dirname(gitDir) : cwd
307
+ }
308
+
309
+ const deriveRepoKey = (cwd, legacy = false) => {
294
310
  const override = process.env.PUSHARY_REPO_KEY
295
311
  if (typeof override === 'string') {
296
312
  const trimmed = override.trim()
@@ -299,11 +315,13 @@ const deriveRepoKey = (cwd) => {
299
315
  }
300
316
  const dir = cwd || process.cwd()
301
317
  try {
302
- const gitDir = findGitDir(dir)
318
+ const gitDir = findGitDir(dir, legacy)
303
319
  if (gitDir) {
304
320
  // A worktree's config lives in the main git directory.
305
- const wt = gitDir.replace(/\\/g, '/').indexOf('/worktrees/')
306
- const configPath = wt === -1 ? join(gitDir, 'config') : join(gitDir.slice(0, wt), 'config')
321
+ const oldIndex = gitDir.replace(/\\/g, '/').indexOf('/worktrees/')
322
+ const configPath = legacy
323
+ ? join(oldIndex === -1 ? gitDir : gitDir.slice(0, oldIndex), 'config')
324
+ : join(mainGitDirOf(gitDir), 'config')
307
325
  if (existsSync(configPath)) {
308
326
  let inOrigin = false
309
327
  for (const rawLine of readFileSync(configPath, 'utf-8').split('\n')) {
@@ -317,7 +335,7 @@ const deriveRepoKey = (cwd) => {
317
335
  }
318
336
  }
319
337
  }
320
- const root = gitDir.endsWith('.git') ? dirname(gitDir) : dir
338
+ const root = legacy ? (gitDir.endsWith('.git') ? dirname(gitDir) : dir) : projectRootOf(gitDir, dir)
321
339
  return `local/${basename(root).toLowerCase()}`.slice(0, REPO_KEY_MAX_LENGTH)
322
340
  }
323
341
  return `local/${basename(dir).toLowerCase()}`.slice(0, REPO_KEY_MAX_LENGTH)
@@ -326,6 +344,13 @@ const deriveRepoKey = (cwd) => {
326
344
  }
327
345
  }
328
346
 
347
+ const repositoryScopeFor = (cwd) => {
348
+ const repoKey = deriveRepoKey(cwd, true)
349
+ const sharedRepoKey = deriveRepoKey(cwd)
350
+ return { repoKey, ...(sharedRepoKey && sharedRepoKey !== repoKey ? { sharedRepoKey } : {}) }
351
+ }
352
+
353
+
329
354
  // ── action body capture + redaction (inlined mirror of describe.ts, since this
330
355
  // dependency-free hook cannot import the workspace) ───────────────────────────
331
356
  const ACTION_BODY_MAX = 4000
@@ -625,7 +650,7 @@ const handlePushFirst = async (apiKey, command, project, ident, pushFirstSeconds
625
650
  return ask('No answer from your phone in time, so the request was withdrawn there. Approve here.')
626
651
  }
627
652
 
628
- export { handlePushOnly, handlePushFirst, withdrawQuestion }
653
+ export { handlePushOnly, handlePushFirst, withdrawQuestion, deriveRepoKey, repositoryScopeFor }
629
654
 
630
655
  // notify_only: fire an awareness notification, let VS Code's prompt decide.
631
656
  const handleNotifyOnly = async (apiKey, command, project, ident) => {
@@ -17,23 +17,23 @@ import {
17
17
  waitForQuestion,
18
18
  waitsForThePhone,
19
19
  withdrawQuestion
20
- } from "./chunk-FSJYYZ3G.js";
20
+ } from "./chunk-SR44ZNZF.js";
21
21
  import "./chunk-POFBE6ZY.js";
22
- import "./chunk-NWSGMYX7.js";
23
- import "./chunk-JJNO3ACZ.js";
24
- import "./chunk-QCSPLJL6.js";
25
- import "./chunk-CNFM6JEV.js";
26
- import "./chunk-7EGNVZLK.js";
27
- import "./chunk-I7UZODYO.js";
28
- import "./chunk-32F3BWRY.js";
22
+ import "./chunk-XTNCXIYR.js";
23
+ import "./chunk-UZRKR6NZ.js";
24
+ import "./chunk-CO6TQ44W.js";
25
+ import "./chunk-CSUO5YJG.js";
26
+ import "./chunk-CHVXLS7U.js";
27
+ import "./chunk-Y7AX6BS4.js";
28
+ import "./chunk-NPZ5L2WQ.js";
29
29
  import "./chunk-PPY5N2E6.js";
30
30
  import "./chunk-KZERVKTD.js";
31
- import "./chunk-E4XGV5UG.js";
31
+ import "./chunk-NDPOESVW.js";
32
32
  import "./chunk-ZVU6WMMU.js";
33
33
  import {
34
34
  DECISION_STOP_REASON,
35
35
  UNVERIFIABLE_APPROVAL_REASON
36
- } from "./chunk-VE333PL5.js";
36
+ } from "./chunk-OMN5UCMW.js";
37
37
  import "./chunk-MLKGABMK.js";
38
38
  export {
39
39
  ABANDONED_WAIT,
@@ -1,41 +1,41 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleBell
4
- } from "../chunk-7BEQB3X4.js";
4
+ } from "../chunk-LTMMFZHG.js";
5
5
  import {
6
6
  readHookInput
7
- } from "../chunk-VMUBIBHQ.js";
8
- import "../chunk-53YQO4HL.js";
9
- import "../chunk-7MN3KPHM.js";
10
- import "../chunk-ALT4KW5M.js";
11
- import "../chunk-HT5WOP2M.js";
12
- import "../chunk-LJFITB6T.js";
13
- import "../chunk-ALTGRWSO.js";
14
- import "../chunk-Y5BPNOJI.js";
7
+ } from "../chunk-B6WYXY32.js";
8
+ import "../chunk-7S3LH5AX.js";
9
+ import "../chunk-OC47FGOY.js";
10
+ import "../chunk-CA4PS7XT.js";
11
+ import "../chunk-CFD3IESN.js";
12
+ import "../chunk-ITGPUTFV.js";
13
+ import "../chunk-GDVS6J4R.js";
14
+ import "../chunk-PFHU3CW4.js";
15
15
  import "../chunk-NMUI3ZWG.js";
16
- import "../chunk-XO3UJDJE.js";
16
+ import "../chunk-4PD7FP55.js";
17
17
  import "../chunk-XMSDA5WA.js";
18
- import "../chunk-72UCLJJW.js";
18
+ import "../chunk-VMIWR724.js";
19
19
  import "../chunk-XHKBHWLX.js";
20
- import "../chunk-LGQQUQDZ.js";
21
- import "../chunk-INNH7EUK.js";
22
- import "../chunk-FAM2TLFC.js";
23
- import "../chunk-K6QLKUCT.js";
24
- import "../chunk-FSJYYZ3G.js";
20
+ import "../chunk-LANGH7UF.js";
21
+ import "../chunk-OFQJHWAS.js";
22
+ import "../chunk-2BVVMWVF.js";
23
+ import "../chunk-RXQT5FTX.js";
24
+ import "../chunk-SR44ZNZF.js";
25
25
  import "../chunk-POFBE6ZY.js";
26
- import "../chunk-NWSGMYX7.js";
27
- import "../chunk-JJNO3ACZ.js";
28
- import "../chunk-QCSPLJL6.js";
29
- import "../chunk-CNFM6JEV.js";
30
- import "../chunk-G7MVZHMM.js";
31
- import "../chunk-7EGNVZLK.js";
32
- import "../chunk-I7UZODYO.js";
33
- import "../chunk-32F3BWRY.js";
26
+ import "../chunk-XTNCXIYR.js";
27
+ import "../chunk-UZRKR6NZ.js";
28
+ import "../chunk-CO6TQ44W.js";
29
+ import "../chunk-CSUO5YJG.js";
30
+ import "../chunk-YLCNW7YN.js";
31
+ import "../chunk-CHVXLS7U.js";
32
+ import "../chunk-Y7AX6BS4.js";
33
+ import "../chunk-NPZ5L2WQ.js";
34
34
  import "../chunk-PPY5N2E6.js";
35
35
  import "../chunk-KZERVKTD.js";
36
- import "../chunk-E4XGV5UG.js";
36
+ import "../chunk-NDPOESVW.js";
37
37
  import "../chunk-ZVU6WMMU.js";
38
- import "../chunk-VE333PL5.js";
38
+ import "../chunk-OMN5UCMW.js";
39
39
  import "../chunk-MLKGABMK.js";
40
40
 
41
41
  // bin/pushary-bell-hook.ts
@@ -5,40 +5,40 @@ import {
5
5
  liveAgentCount,
6
6
  ring,
7
7
  upgradeThreshold
8
- } from "../chunk-7BEQB3X4.js";
8
+ } from "../chunk-LTMMFZHG.js";
9
9
  import {
10
10
  createIo
11
11
  } from "../chunk-FO3MDD26.js";
12
12
  import {
13
13
  exitOnHelpFlag
14
- } from "../chunk-E3EJARHF.js";
14
+ } from "../chunk-V7TNHTHH.js";
15
15
  import {
16
16
  addBellHooks,
17
17
  bellInstalled,
18
18
  removeBellHooks
19
- } from "../chunk-Y5BPNOJI.js";
19
+ } from "../chunk-PFHU3CW4.js";
20
20
  import {
21
21
  parseFlags
22
22
  } from "../chunk-NMUI3ZWG.js";
23
- import "../chunk-LGQQUQDZ.js";
24
- import "../chunk-G7MVZHMM.js";
23
+ import "../chunk-LANGH7UF.js";
24
+ import "../chunk-YLCNW7YN.js";
25
25
  import {
26
26
  claudeSettings
27
- } from "../chunk-7EGNVZLK.js";
27
+ } from "../chunk-CHVXLS7U.js";
28
28
  import {
29
29
  readJsonSafe,
30
30
  writeJsonAtomic
31
- } from "../chunk-I7UZODYO.js";
32
- import "../chunk-32F3BWRY.js";
31
+ } from "../chunk-Y7AX6BS4.js";
32
+ import "../chunk-NPZ5L2WQ.js";
33
33
  import "../chunk-PPY5N2E6.js";
34
34
  import {
35
35
  EXIT
36
36
  } from "../chunk-KZERVKTD.js";
37
- import "../chunk-E4XGV5UG.js";
37
+ import "../chunk-NDPOESVW.js";
38
38
  import "../chunk-ZVU6WMMU.js";
39
39
  import {
40
40
  isRecord
41
- } from "../chunk-VE333PL5.js";
41
+ } from "../chunk-OMN5UCMW.js";
42
42
  import "../chunk-MLKGABMK.js";
43
43
 
44
44
  // bin/pushary-bell.ts
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  WRAPPER_ACTIVE_ENV,
4
4
  findClaudeBinary
5
- } from "../chunk-2RUJIPNN.js";
5
+ } from "../chunk-2FL5PLA4.js";
6
6
  import {
7
7
  CommandReceipts,
8
8
  controllerCommandSchema
@@ -12,39 +12,39 @@ import {
12
12
  describeIdleWindow,
13
13
  startProcessOwnership,
14
14
  withSpawnProcessOwnership
15
- } from "../chunk-NMDWW3EY.js";
16
- import "../chunk-K2NIENKY.js";
15
+ } from "../chunk-2BXWBKVN.js";
16
+ import "../chunk-66VEUAN5.js";
17
17
  import {
18
18
  announceSubscriptionRequired,
19
19
  isDeferAnswer
20
- } from "../chunk-URJHH72Z.js";
20
+ } from "../chunk-V3LBQFQM.js";
21
21
  import {
22
22
  claudeTranscriptPath,
23
23
  redactDraft,
24
24
  registerTranscript,
25
25
  registeredTranscriptEnabled,
26
26
  startDraftPublisher
27
- } from "../chunk-53YQO4HL.js";
28
- import "../chunk-7MN3KPHM.js";
27
+ } from "../chunk-7S3LH5AX.js";
28
+ import "../chunk-OC47FGOY.js";
29
29
  import {
30
30
  ensureDaemonRunning
31
- } from "../chunk-HT5WOP2M.js";
32
- import "../chunk-LJFITB6T.js";
33
- import "../chunk-ALTGRWSO.js";
34
- import "../chunk-Y5BPNOJI.js";
31
+ } from "../chunk-CFD3IESN.js";
32
+ import "../chunk-ITGPUTFV.js";
33
+ import "../chunk-GDVS6J4R.js";
34
+ import "../chunk-PFHU3CW4.js";
35
35
  import "../chunk-NMUI3ZWG.js";
36
- import "../chunk-XO3UJDJE.js";
36
+ import "../chunk-4PD7FP55.js";
37
37
  import {
38
38
  external_exports
39
39
  } from "../chunk-XMSDA5WA.js";
40
40
  import {
41
41
  transcriptsEnabled
42
- } from "../chunk-72UCLJJW.js";
42
+ } from "../chunk-VMIWR724.js";
43
43
  import {
44
44
  needsShell,
45
45
  spawnClaude
46
46
  } from "../chunk-XHKBHWLX.js";
47
- import "../chunk-LGQQUQDZ.js";
47
+ import "../chunk-LANGH7UF.js";
48
48
  import {
49
49
  DEFAULT_SESSION,
50
50
  fetchModeState,
@@ -57,16 +57,17 @@ import {
57
57
  removePendingCommand,
58
58
  reportEvent,
59
59
  savePendingCommand
60
- } from "../chunk-INNH7EUK.js";
60
+ } from "../chunk-OFQJHWAS.js";
61
61
  import {
62
62
  UNNAMED_ACTION,
63
63
  deriveToolTarget,
64
64
  describeToolCall,
65
65
  scopePathFor
66
- } from "../chunk-FAM2TLFC.js";
66
+ } from "../chunk-2BVVMWVF.js";
67
67
  import {
68
- repoKeyFor
69
- } from "../chunk-K6QLKUCT.js";
68
+ repoKeyFor,
69
+ repositoryScopeFor
70
+ } from "../chunk-RXQT5FTX.js";
70
71
  import {
71
72
  askUser,
72
73
  cancelQuestion,
@@ -78,30 +79,30 @@ import {
78
79
  waitForAnswer,
79
80
  waitsForThePhone,
80
81
  withdrawQuestion
81
- } from "../chunk-FSJYYZ3G.js";
82
+ } from "../chunk-SR44ZNZF.js";
82
83
  import "../chunk-POFBE6ZY.js";
83
84
  import {
84
85
  SubscriptionRequiredError
85
- } from "../chunk-NWSGMYX7.js";
86
- import "../chunk-JJNO3ACZ.js";
87
- import "../chunk-QCSPLJL6.js";
86
+ } from "../chunk-XTNCXIYR.js";
87
+ import "../chunk-UZRKR6NZ.js";
88
+ import "../chunk-CO6TQ44W.js";
88
89
  import {
89
90
  getMachineId
90
- } from "../chunk-CNFM6JEV.js";
91
- import "../chunk-G7MVZHMM.js";
91
+ } from "../chunk-CSUO5YJG.js";
92
+ import "../chunk-YLCNW7YN.js";
92
93
  import {
93
94
  claudeConfigDir
94
- } from "../chunk-7EGNVZLK.js";
95
- import "../chunk-I7UZODYO.js";
95
+ } from "../chunk-CHVXLS7U.js";
96
+ import "../chunk-Y7AX6BS4.js";
96
97
  import {
97
98
  getApiKey,
98
99
  getBaseUrl
99
- } from "../chunk-32F3BWRY.js";
100
+ } from "../chunk-NPZ5L2WQ.js";
100
101
  import "../chunk-PPY5N2E6.js";
101
102
  import "../chunk-KZERVKTD.js";
102
103
  import {
103
104
  NPX_LATEST_COMMAND
104
- } from "../chunk-E4XGV5UG.js";
105
+ } from "../chunk-NDPOESVW.js";
105
106
  import "../chunk-ZVU6WMMU.js";
106
107
  import {
107
108
  DECISION_STOP_REASON,
@@ -114,7 +115,7 @@ import {
114
115
  refusesWhenUnanswered,
115
116
  resolveGate,
116
117
  timeoutActionWithoutLocalPrompt
117
- } from "../chunk-VE333PL5.js";
118
+ } from "../chunk-OMN5UCMW.js";
118
119
  import "../chunk-MLKGABMK.js";
119
120
 
120
121
  // src/wrapper/localPassthrough.ts
@@ -547,7 +548,7 @@ var createRemoteApprover = (deps) => {
547
548
  toolInputs: [input],
548
549
  scopePaths: scopePath ? [scopePath] : [],
549
550
  cwd: deps.cwd,
550
- repoKey: repoKeyFor(deps.cwd),
551
+ ...repositoryScopeFor(deps.cwd),
551
552
  sessionId
552
553
  });
553
554
  if (verdict.kind === "kill") return deny(KILL_REASON);