@indigoai-us/hq-cloud 6.14.50 → 6.15.1

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 (340) hide show
  1. package/dist/bin/sync-mutation.d.ts +14 -0
  2. package/dist/bin/sync-mutation.d.ts.map +1 -0
  3. package/dist/bin/sync-mutation.js +60 -0
  4. package/dist/bin/sync-mutation.js.map +1 -0
  5. package/dist/bin/sync-mutation.test.d.ts +2 -0
  6. package/dist/bin/sync-mutation.test.d.ts.map +1 -0
  7. package/dist/bin/sync-mutation.test.js +64 -0
  8. package/dist/bin/sync-mutation.test.js.map +1 -0
  9. package/dist/bin/sync-runner-company.d.ts +8 -0
  10. package/dist/bin/sync-runner-company.d.ts.map +1 -1
  11. package/dist/bin/sync-runner-company.js +16 -0
  12. package/dist/bin/sync-runner-company.js.map +1 -1
  13. package/dist/bin/sync-runner-company.test.d.ts +2 -0
  14. package/dist/bin/sync-runner-company.test.d.ts.map +1 -0
  15. package/dist/bin/sync-runner-company.test.js +36 -0
  16. package/dist/bin/sync-runner-company.test.js.map +1 -0
  17. package/dist/bin/sync-runner-watch-loop.d.ts.map +1 -1
  18. package/dist/bin/sync-runner-watch-loop.js +98 -8
  19. package/dist/bin/sync-runner-watch-loop.js.map +1 -1
  20. package/dist/bin/sync-runner.d.ts +17 -0
  21. package/dist/bin/sync-runner.d.ts.map +1 -1
  22. package/dist/bin/sync-runner.js.map +1 -1
  23. package/dist/bin/sync-runner.test.js +109 -0
  24. package/dist/bin/sync-runner.test.js.map +1 -1
  25. package/dist/cli/conflict-recovery.test.d.ts +2 -0
  26. package/dist/cli/conflict-recovery.test.d.ts.map +1 -0
  27. package/dist/cli/conflict-recovery.test.js +201 -0
  28. package/dist/cli/conflict-recovery.test.js.map +1 -0
  29. package/dist/cli/conflict.d.ts +60 -0
  30. package/dist/cli/conflict.d.ts.map +1 -1
  31. package/dist/cli/conflict.js +333 -0
  32. package/dist/cli/conflict.js.map +1 -1
  33. package/dist/cli/reindex-knowledge.d.ts +7 -0
  34. package/dist/cli/reindex-knowledge.d.ts.map +1 -0
  35. package/dist/cli/reindex-knowledge.js +389 -0
  36. package/dist/cli/reindex-knowledge.js.map +1 -0
  37. package/dist/cli/reindex-knowledge.test.d.ts +12 -0
  38. package/dist/cli/reindex-knowledge.test.d.ts.map +1 -0
  39. package/dist/cli/reindex-knowledge.test.js +260 -0
  40. package/dist/cli/reindex-knowledge.test.js.map +1 -0
  41. package/dist/cli/reindex.d.ts.map +1 -1
  42. package/dist/cli/reindex.js +8 -0
  43. package/dist/cli/reindex.js.map +1 -1
  44. package/dist/cli/rescue-settings-reconcile.test.js +47 -0
  45. package/dist/cli/rescue-settings-reconcile.test.js.map +1 -1
  46. package/dist/cli/sync.d.ts +27 -0
  47. package/dist/cli/sync.d.ts.map +1 -1
  48. package/dist/cli/sync.js +52 -0
  49. package/dist/cli/sync.js.map +1 -1
  50. package/dist/cli/sync.test.js +31 -1
  51. package/dist/cli/sync.test.js.map +1 -1
  52. package/dist/index.d.ts +2 -0
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +1 -0
  55. package/dist/index.js.map +1 -1
  56. package/dist/skill-telemetry.d.ts +6 -0
  57. package/dist/skill-telemetry.d.ts.map +1 -1
  58. package/dist/skill-telemetry.js +14 -2
  59. package/dist/skill-telemetry.js.map +1 -1
  60. package/dist/skill-telemetry.test.js +79 -0
  61. package/dist/skill-telemetry.test.js.map +1 -1
  62. package/dist/sync/candidate-uploader.d.ts +88 -0
  63. package/dist/sync/candidate-uploader.d.ts.map +1 -0
  64. package/dist/sync/candidate-uploader.js +212 -0
  65. package/dist/sync/candidate-uploader.js.map +1 -0
  66. package/dist/sync/candidate-uploader.test.d.ts +2 -0
  67. package/dist/sync/candidate-uploader.test.d.ts.map +1 -0
  68. package/dist/sync/candidate-uploader.test.js +132 -0
  69. package/dist/sync/candidate-uploader.test.js.map +1 -0
  70. package/dist/sync/delta-client.d.ts +73 -0
  71. package/dist/sync/delta-client.d.ts.map +1 -0
  72. package/dist/sync/delta-client.js +201 -0
  73. package/dist/sync/delta-client.js.map +1 -0
  74. package/dist/sync/delta-client.test.d.ts +2 -0
  75. package/dist/sync/delta-client.test.d.ts.map +1 -0
  76. package/dist/sync/delta-client.test.js +97 -0
  77. package/dist/sync/delta-client.test.js.map +1 -0
  78. package/dist/sync/durable-apply.d.ts +76 -0
  79. package/dist/sync/durable-apply.d.ts.map +1 -0
  80. package/dist/sync/durable-apply.js +530 -0
  81. package/dist/sync/durable-apply.js.map +1 -0
  82. package/dist/sync/durable-apply.test.d.ts +2 -0
  83. package/dist/sync/durable-apply.test.d.ts.map +1 -0
  84. package/dist/sync/durable-apply.test.js +180 -0
  85. package/dist/sync/durable-apply.test.js.map +1 -0
  86. package/dist/sync/event-sync.d.ts +33 -1
  87. package/dist/sync/event-sync.d.ts.map +1 -1
  88. package/dist/sync/event-sync.js +149 -1
  89. package/dist/sync/event-sync.js.map +1 -1
  90. package/dist/sync/event-sync.test.js +142 -1
  91. package/dist/sync/event-sync.test.js.map +1 -1
  92. package/dist/sync/index.d.ts +2 -0
  93. package/dist/sync/index.d.ts.map +1 -1
  94. package/dist/sync/index.js +1 -0
  95. package/dist/sync/index.js.map +1 -1
  96. package/dist/sync/multipart-uploader.d.ts +99 -0
  97. package/dist/sync/multipart-uploader.d.ts.map +1 -0
  98. package/dist/sync/multipart-uploader.js +447 -0
  99. package/dist/sync/multipart-uploader.js.map +1 -0
  100. package/dist/sync/multipart-uploader.test.d.ts +2 -0
  101. package/dist/sync/multipart-uploader.test.d.ts.map +1 -0
  102. package/dist/sync/multipart-uploader.test.js +119 -0
  103. package/dist/sync/multipart-uploader.test.js.map +1 -0
  104. package/dist/sync/mutation-client.d.ts +82 -0
  105. package/dist/sync/mutation-client.d.ts.map +1 -0
  106. package/dist/sync/mutation-client.js +221 -0
  107. package/dist/sync/mutation-client.js.map +1 -0
  108. package/dist/sync/mutation-client.test.d.ts +2 -0
  109. package/dist/sync/mutation-client.test.d.ts.map +1 -0
  110. package/dist/sync/mutation-client.test.js +51 -0
  111. package/dist/sync/mutation-client.test.js.map +1 -0
  112. package/dist/sync/push-receiver.d.ts +45 -0
  113. package/dist/sync/push-receiver.d.ts.map +1 -1
  114. package/dist/sync/push-receiver.js +101 -0
  115. package/dist/sync/push-receiver.js.map +1 -1
  116. package/dist/sync/push-receiver.test.js +54 -2
  117. package/dist/sync/push-receiver.test.js.map +1 -1
  118. package/dist/sync/scope-inventory-client.d.ts +69 -0
  119. package/dist/sync/scope-inventory-client.d.ts.map +1 -0
  120. package/dist/sync/scope-inventory-client.js +210 -0
  121. package/dist/sync/scope-inventory-client.js.map +1 -0
  122. package/dist/sync/scope-inventory-client.test.d.ts +2 -0
  123. package/dist/sync/scope-inventory-client.test.d.ts.map +1 -0
  124. package/dist/sync/scope-inventory-client.test.js +94 -0
  125. package/dist/sync/scope-inventory-client.test.js.map +1 -0
  126. package/dist/sync/snapshot-client.d.ts +98 -0
  127. package/dist/sync/snapshot-client.d.ts.map +1 -0
  128. package/dist/sync/snapshot-client.js +402 -0
  129. package/dist/sync/snapshot-client.js.map +1 -0
  130. package/dist/sync/snapshot-client.test.d.ts +2 -0
  131. package/dist/sync/snapshot-client.test.d.ts.map +1 -0
  132. package/dist/sync/snapshot-client.test.js +169 -0
  133. package/dist/sync/snapshot-client.test.js.map +1 -0
  134. package/dist/sync/uploader-finalization.d.ts +97 -0
  135. package/dist/sync/uploader-finalization.d.ts.map +1 -0
  136. package/dist/sync/uploader-finalization.js +273 -0
  137. package/dist/sync/uploader-finalization.js.map +1 -0
  138. package/dist/sync/uploader-finalization.test.d.ts +2 -0
  139. package/dist/sync/uploader-finalization.test.d.ts.map +1 -0
  140. package/dist/sync/uploader-finalization.test.js +92 -0
  141. package/dist/sync/uploader-finalization.test.js.map +1 -0
  142. package/dist/telemetry.d.ts +11 -1
  143. package/dist/telemetry.d.ts.map +1 -1
  144. package/dist/telemetry.js +21 -2
  145. package/dist/telemetry.js.map +1 -1
  146. package/dist/telemetry.test.js +80 -0
  147. package/dist/telemetry.test.js.map +1 -1
  148. package/package.json +6 -1
  149. package/.claude/policies/hq-cloud-esm-cannot-spy-fs-builtins.md +0 -30
  150. package/.claude/policies/hq-cloud-strip-types-no-parameter-properties.md +0 -22
  151. package/.github/workflows/ci.yml +0 -84
  152. package/.github/workflows/publish.yml +0 -56
  153. package/.github/workflows/unreleased-commits-nag.yml +0 -256
  154. package/eslint.config.js +0 -67
  155. package/pnpm-workspace.yaml +0 -2
  156. package/scripts/presign-transport-e2e.mjs +0 -250
  157. package/scripts/vault-rebaseline.sh +0 -323
  158. package/scripts/vault-rescue.sh +0 -332
  159. package/src/active-company.test.ts +0 -188
  160. package/src/active-company.ts +0 -168
  161. package/src/agent-codex-instructions.test.ts +0 -332
  162. package/src/agent-codex-instructions.ts +0 -309
  163. package/src/auth.ts +0 -146
  164. package/src/backup-prune.test.ts +0 -98
  165. package/src/backup-prune.ts +0 -182
  166. package/src/bin/backup-prune-runner.ts +0 -33
  167. package/src/bin/rescue-runner.ts +0 -25
  168. package/src/bin/sync-runner-company.ts +0 -695
  169. package/src/bin/sync-runner-events.test.ts +0 -143
  170. package/src/bin/sync-runner-events.ts +0 -55
  171. package/src/bin/sync-runner-planning.test.ts +0 -311
  172. package/src/bin/sync-runner-planning.ts +0 -258
  173. package/src/bin/sync-runner-rollup.test.ts +0 -37
  174. package/src/bin/sync-runner-rollup.ts +0 -97
  175. package/src/bin/sync-runner-telemetry.ts +0 -15
  176. package/src/bin/sync-runner-watch-loop.ts +0 -1235
  177. package/src/bin/sync-runner-watch-routes.test.ts +0 -71
  178. package/src/bin/sync-runner-watch-routes.ts +0 -184
  179. package/src/bin/sync-runner.test.ts +0 -8767
  180. package/src/bin/sync-runner.ts +0 -2190
  181. package/src/cli/accept.ts +0 -124
  182. package/src/cli/conflict.ts +0 -119
  183. package/src/cli/doctor.test.ts +0 -581
  184. package/src/cli/doctor.ts +0 -642
  185. package/src/cli/index.ts +0 -49
  186. package/src/cli/invite.test.ts +0 -250
  187. package/src/cli/invite.ts +0 -214
  188. package/src/cli/promote.ts +0 -157
  189. package/src/cli/reindex.test.ts +0 -957
  190. package/src/cli/reindex.ts +0 -970
  191. package/src/cli/rescue-classify-ordering.test.ts +0 -548
  192. package/src/cli/rescue-clone-diagnostics.test.ts +0 -120
  193. package/src/cli/rescue-core.ts +0 -3011
  194. package/src/cli/rescue-drift-reconcile.test.ts +0 -179
  195. package/src/cli/rescue-drop-dir-symlink.test.ts +0 -224
  196. package/src/cli/rescue-exec-bit-preserve.test.ts +0 -187
  197. package/src/cli/rescue-hq-root-guard.test.ts +0 -232
  198. package/src/cli/rescue-journal-reconcile.test.ts +0 -215
  199. package/src/cli/rescue-mtime-preserve.test.ts +0 -203
  200. package/src/cli/rescue-settings-reconcile.test.ts +0 -583
  201. package/src/cli/rescue-snapshot.test.ts +0 -57
  202. package/src/cli/rescue-snapshot.ts +0 -51
  203. package/src/cli/rescue.reindex.test.ts +0 -63
  204. package/src/cli/rescue.test.ts +0 -131
  205. package/src/cli/rescue.ts +0 -182
  206. package/src/cli/share.test.ts +0 -7843
  207. package/src/cli/share.ts +0 -3663
  208. package/src/cli/sync-scope.test.ts +0 -652
  209. package/src/cli/sync.test.ts +0 -5207
  210. package/src/cli/sync.ts +0 -3470
  211. package/src/cli/tombstones.ts +0 -106
  212. package/src/cli/watch-event-push-conflict.test.ts +0 -234
  213. package/src/client-info.test.ts +0 -214
  214. package/src/client-info.ts +0 -121
  215. package/src/cognito-auth.test.ts +0 -712
  216. package/src/cognito-auth.ts +0 -1422
  217. package/src/company-resolver.test.ts +0 -618
  218. package/src/company-resolver.ts +0 -521
  219. package/src/context.test.ts +0 -583
  220. package/src/context.ts +0 -378
  221. package/src/daemon-worker.ts +0 -26
  222. package/src/daemon.ts +0 -99
  223. package/src/entity-resolver.test.ts +0 -315
  224. package/src/entity-resolver.ts +0 -180
  225. package/src/ignore.test.ts +0 -466
  226. package/src/ignore.ts +0 -469
  227. package/src/index.ts +0 -439
  228. package/src/journal.test.ts +0 -968
  229. package/src/journal.ts +0 -765
  230. package/src/lib/cloud-authoritative.test.ts +0 -45
  231. package/src/lib/cloud-authoritative.ts +0 -59
  232. package/src/lib/conflict-file.ts +0 -86
  233. package/src/lib/conflict-index.ts +0 -289
  234. package/src/lib/conflict.test.ts +0 -348
  235. package/src/lib/describe-error.test.ts +0 -100
  236. package/src/lib/describe-error.ts +0 -58
  237. package/src/lib/exit-codes.ts +0 -24
  238. package/src/lib/machine-id.test.ts +0 -231
  239. package/src/lib/machine-id.ts +0 -175
  240. package/src/lib/net-errors.test.ts +0 -65
  241. package/src/lib/net-errors.ts +0 -86
  242. package/src/lib/readlink-safe.test.ts +0 -43
  243. package/src/lib/readlink-safe.ts +0 -29
  244. package/src/local-path-codec.test.ts +0 -138
  245. package/src/local-path-codec.ts +0 -161
  246. package/src/machine-auth.test.ts +0 -1323
  247. package/src/manifest-reconcile.test.ts +0 -1123
  248. package/src/manifest-reconcile.ts +0 -518
  249. package/src/object-io.test.ts +0 -1221
  250. package/src/object-io.ts +0 -1306
  251. package/src/operation-lock.test.ts +0 -484
  252. package/src/operation-lock.ts +0 -680
  253. package/src/outcome-telemetry.test.ts +0 -498
  254. package/src/outcome-telemetry.ts +0 -639
  255. package/src/personal-vault-exclusions.test.ts +0 -308
  256. package/src/personal-vault-exclusions.ts +0 -354
  257. package/src/personal-vault.test.ts +0 -756
  258. package/src/personal-vault.ts +0 -496
  259. package/src/prefix-coalesce.test.ts +0 -240
  260. package/src/prefix-coalesce.ts +0 -273
  261. package/src/public-surface.test.ts +0 -117
  262. package/src/qmd-reindex.test.ts +0 -877
  263. package/src/qmd-reindex.ts +0 -842
  264. package/src/read-only-state-dir.test.ts +0 -188
  265. package/src/remote-pull.test.ts +0 -1130
  266. package/src/remote-pull.ts +0 -618
  267. package/src/s3.symlink-materialize.test.ts +0 -492
  268. package/src/s3.test.ts +0 -1789
  269. package/src/s3.ts +0 -1532
  270. package/src/schemas/signal-types.test.ts +0 -82
  271. package/src/schemas/signal-types.ts +0 -38
  272. package/src/schemas/source-channels.test.ts +0 -82
  273. package/src/schemas/source-channels.ts +0 -53
  274. package/src/scope-shrink.test.ts +0 -633
  275. package/src/scope-shrink.ts +0 -481
  276. package/src/signals/get.test.ts +0 -310
  277. package/src/signals/get.ts +0 -75
  278. package/src/signals/internals.ts +0 -195
  279. package/src/signals/list.test.ts +0 -420
  280. package/src/signals/list.ts +0 -79
  281. package/src/signals/parse.ts +0 -8
  282. package/src/signals/types.ts +0 -91
  283. package/src/skill-telemetry.test.ts +0 -1825
  284. package/src/skill-telemetry.ts +0 -1439
  285. package/src/sources/get.test.ts +0 -293
  286. package/src/sources/get.ts +0 -66
  287. package/src/sources/internals.ts +0 -198
  288. package/src/sources/list.test.ts +0 -402
  289. package/src/sources/list.ts +0 -84
  290. package/src/sources/parse.ts +0 -43
  291. package/src/sources/types.ts +0 -84
  292. package/src/sync/event-sync.test.ts +0 -594
  293. package/src/sync/event-sync.ts +0 -545
  294. package/src/sync/feature-flags.test.ts +0 -378
  295. package/src/sync/feature-flags.ts +0 -62
  296. package/src/sync/index.ts +0 -76
  297. package/src/sync/lease-client.test.ts +0 -128
  298. package/src/sync/lease-client.ts +0 -207
  299. package/src/sync/logger.test.ts +0 -242
  300. package/src/sync/logger.ts +0 -79
  301. package/src/sync/metrics.test.ts +0 -462
  302. package/src/sync/metrics.ts +0 -213
  303. package/src/sync/pull-scope.ts +0 -265
  304. package/src/sync/push-event.test.ts +0 -266
  305. package/src/sync/push-event.ts +0 -224
  306. package/src/sync/push-receiver.test.ts +0 -566
  307. package/src/sync/push-receiver.ts +0 -1048
  308. package/src/sync/push-transport.ts +0 -231
  309. package/src/sync/realtime-rollout.test.ts +0 -86
  310. package/src/sync/realtime-rollout.ts +0 -262
  311. package/src/sync/state-store.test.ts +0 -194
  312. package/src/sync/state-store.ts +0 -727
  313. package/src/sync-core.ts +0 -58
  314. package/src/sync-progress.test.ts +0 -94
  315. package/src/sync-progress.ts +0 -140
  316. package/src/telemetry-events.test.ts +0 -88
  317. package/src/telemetry-events.ts +0 -205
  318. package/src/telemetry.test.ts +0 -1280
  319. package/src/telemetry.ts +0 -1109
  320. package/src/types.ts +0 -314
  321. package/src/vault-client.test.ts +0 -1380
  322. package/src/vault-client.ts +0 -1694
  323. package/src/version.ts +0 -24
  324. package/src/watch-roots.test.ts +0 -278
  325. package/src/watch-roots.ts +0 -162
  326. package/src/watcher-event-gate.test.ts +0 -212
  327. package/src/watcher.test.ts +0 -1079
  328. package/src/watcher.ts +0 -1741
  329. package/test/e2e/sync/cross-tenant-isolation.test.ts +0 -630
  330. package/test/e2e/sync/skill-telemetry-oversized-transcript.test.ts +0 -124
  331. package/test/e2e/sync/transient-company-leg.test.ts +0 -384
  332. package/test/e2e/sync/windows-unreadable-link-leg.test.ts +0 -191
  333. package/test/e2e/watcher-real-chokidar.test.ts +0 -165
  334. package/test/e2e/watcher-recursive-backend.test.ts +0 -181
  335. package/test/e2e/watcher-scoped-coverage.test.ts +0 -381
  336. package/test/invite-flow.integration.test.ts +0 -244
  337. package/test/joiner-manifest-reconcile.integration.test.ts +0 -322
  338. package/test/share-sync.integration.test.ts +0 -213
  339. package/tsconfig.json +0 -19
  340. package/vitest.config.ts +0 -22
@@ -1,256 +0,0 @@
1
- name: Nag unreleased commits on main
2
-
3
- # Two weekly release nags for hq-cloud:
4
- #
5
- # nag — `main` is carrying work nobody has released (below).
6
- # pin-lag — the latest hq-cloud release is not pinned by hq-cli and
7
- # hq-desktop-app `main`. See that job's own header.
8
- #
9
- # A commit counts as UNRELEASED when it is reachable from `main` but not from
10
- # any STABLE tag. Stable means `vMAJOR.MINOR.PATCH` with no prerelease suffix —
11
- # `-rc.N`, `-beta.N` and `-alpha.N` tags deliberately do NOT silence the nag,
12
- # because a prerelease is not a release.
13
- #
14
- # Release sync-back commits (`chore(release): …`) are ignored. The publish
15
- # workflow pushes them to `main` *after* cutting the tag, so they are
16
- # unreachable from that tag by construction and would nag forever otherwise.
17
- #
18
- # Releasing this repo is one command — `git push origin v<next>` — so the fix
19
- # for a nag is always to cut the tag (or to say out loud why you are holding).
20
- #
21
- # Requires repo secret SLACK_BOT_TOKEN_RELEASE_MANAGER (the same release-manager
22
- # bot hq-core's `release-pr-nag.yml` uses). The bot MUST be a member of #hq-dev.
23
- # Without the secret the job logs a warning and exits 0 rather than failing.
24
-
25
- on:
26
- schedule:
27
- # Mondays 15:00 UTC (~08:00 PT). Staggered against the sibling repos'
28
- # nags so all four do not land in #hq-dev in the same second.
29
- - cron: '10 15 * * 1'
30
- workflow_dispatch:
31
- inputs:
32
- threshold_hours:
33
- description: 'Age of the OLDEST unreleased commit, in hours, before nagging (default 24)'
34
- required: false
35
- default: '24'
36
-
37
- permissions:
38
- contents: read
39
-
40
- jobs:
41
- nag:
42
- name: Nag when main has unreleased commits
43
- if: github.repository == 'indigoai-us/hq-cloud'
44
- runs-on: ubuntu-latest
45
- env:
46
- SLACK_TOKEN: ${{ secrets.SLACK_BOT_TOKEN_RELEASE_MANAGER }}
47
- SLACK_CHANNEL: '#hq-dev'
48
- THRESHOLD: ${{ github.event.inputs.threshold_hours || '24' }}
49
- steps:
50
- - name: Check out full history and tags
51
- uses: actions/checkout@v4
52
- with:
53
- ref: main
54
- fetch-depth: 0
55
-
56
- - name: Find unreleased commits on main and nag
57
- run: |
58
- set -euo pipefail
59
-
60
- if [ -z "${SLACK_TOKEN:-}" ]; then
61
- echo "::warning::SLACK_BOT_TOKEN_RELEASE_MANAGER is not set on this repository; cannot post the nag."
62
- exit 0
63
- fi
64
-
65
- git fetch --force --tags --quiet origin main
66
-
67
- # Newest stable tag reachable from main — display only.
68
- LAST_TAG="$(git tag --list 'v*' --merged origin/main --sort=-v:refname \
69
- | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1 || true)"
70
-
71
- # Commits on main not reachable from ANY stable tag. `--exclude` applies
72
- # to the `--tags` glob that follows it, so `v*-*` drops every prerelease.
73
- git log origin/main --format='%H%x09%ct%x09%s' \
74
- --not --exclude='v*-*' --tags='v*' > /tmp/unreleased_all.tsv
75
-
76
- # Drop the post-tag release sync-back commits.
77
- awk -F'\t' '$3 !~ /^chore\(release\)/' /tmp/unreleased_all.tsv > /tmp/unreleased.tsv
78
-
79
- COUNT="$(wc -l < /tmp/unreleased.tsv | tr -d ' ')"
80
- echo "Last stable tag: ${LAST_TAG:-<none>}"
81
- echo "Unreleased commits on main: ${COUNT}"
82
-
83
- if [ "$COUNT" -eq 0 ]; then
84
- echo "main is fully released. Nothing to nag about."
85
- exit 0
86
- fi
87
-
88
- OLDEST_TS="$(tail -1 /tmp/unreleased.tsv | cut -f2)"
89
- NOW="$(date -u +%s)"
90
- AGE_H=$(( (NOW - OLDEST_TS) / 3600 ))
91
- echo "Oldest unreleased commit age: ${AGE_H}h (threshold ${THRESHOLD}h)"
92
-
93
- if [ "$AGE_H" -lt "$THRESHOLD" ]; then
94
- echo "Under threshold. Skipping."
95
- exit 0
96
- fi
97
-
98
- REPO_NAME="${GITHUB_REPOSITORY##*/}"
99
- DAYS=$(( AGE_H / 24 ))
100
- if [ -n "$LAST_TAG" ]; then
101
- LINK="https://github.com/${GITHUB_REPOSITORY}/compare/${LAST_TAG}...main"
102
- TAG_LABEL="\`${LAST_TAG}\`"
103
- else
104
- LINK="https://github.com/${GITHUB_REPOSITORY}/commits/main"
105
- TAG_LABEL="_never released_"
106
- fi
107
-
108
- # Oldest-first sample of what is waiting, capped at 5 lines.
109
- SAMPLE="$(tail -5 /tmp/unreleased.tsv | tac | cut -f3 | sed 's/^/• /')"
110
- if [ "$COUNT" -gt 5 ]; then
111
- SAMPLE="${SAMPLE}"$'\n'"• …and $(( COUNT - 5 )) more"
112
- fi
113
-
114
- TEXT=":package: *\`${REPO_NAME}\`: ${COUNT} commit(s) have been sitting unreleased on \`main\` for ~${AGE_H}h (${DAYS}d).* Last stable release: ${TAG_LABEL} — prereleases don't count. Shipping is one command: \`git push origin v<next>\`. <${LINK}|See what's waiting>."$'\n'"${SAMPLE}"
115
-
116
- RESP="$(curl -s -X POST \
117
- -H "Authorization: Bearer ${SLACK_TOKEN}" \
118
- -H 'Content-type: application/json; charset=utf-8' \
119
- --data "$(jq -nc --arg c "$SLACK_CHANNEL" --arg t "$TEXT" '{channel:$c,text:$t,unfurl_links:false}')" \
120
- https://slack.com/api/chat.postMessage)"
121
- OK="$(echo "$RESP" | jq -r '.ok')"
122
- echo "Slack post ok=${OK} err=$(echo "$RESP" | jq -r '.error // "-"')"
123
- if [ "$OK" != "true" ]; then
124
- echo "::error::Slack rejected the nag: $(echo "$RESP" | jq -r '.error // "unknown"')"
125
- exit 1
126
- fi
127
-
128
- pin-lag:
129
- name: Nag when consumers lag the latest hq-cloud release
130
- # hq-cloud ships the sync runner that hq-cli and hq-desktop-app spawn. A
131
- # release nobody has pinned is a release nobody is running, so this job
132
- # compares the newest STABLE hq-cloud tag against the version each
133
- # consumer's `main` actually declares:
134
- #
135
- # hq-cli pnpm-lock.yaml -> resolved @indigoai-us/hq-cloud version
136
- # hq-desktop-app crates/hq-desktop-core/src/hq_cloud.rs -> HQ_CLOUD_VERSION
137
- #
138
- # Comparison is EXACT on the version string (the desktop pin's leading `~`
139
- # is stripped first). A tilde range like `~6.14.47` does resolve to 6.14.48
140
- # at npx spawn time, so this will flag a pin that is already functionally
141
- # current — that is deliberate: the written pin is kept literally in step
142
- # with the latest release.
143
- #
144
- # Reading the two sibling repos needs a cross-repo token, so this mints an
145
- # installation token from the hq-audit-bot App (same pattern as
146
- # hq-core's promote-to-hq-core.yml). The App must be installed on
147
- # indigoai-us/hq-cli and indigoai-us/hq-desktop-app with `contents: read`.
148
- if: github.repository == 'indigoai-us/hq-cloud'
149
- runs-on: ubuntu-latest
150
- env:
151
- SLACK_TOKEN: ${{ secrets.SLACK_BOT_TOKEN_RELEASE_MANAGER }}
152
- SLACK_CHANNEL: '#hq-dev'
153
- HQ_AUDIT_BOT_APP_ID: ${{ secrets.HQ_AUDIT_BOT_APP_ID }}
154
- HQ_AUDIT_BOT_PRIVATE_KEY: ${{ secrets.HQ_AUDIT_BOT_PRIVATE_KEY }}
155
- steps:
156
- - name: Check out full history and tags
157
- uses: actions/checkout@v4
158
- with:
159
- ref: main
160
- fetch-depth: 0
161
-
162
- - name: Preflight credentials
163
- id: pre
164
- run: |
165
- set -euo pipefail
166
- if [ -z "${SLACK_TOKEN:-}" ]; then
167
- echo "::warning::SLACK_BOT_TOKEN_RELEASE_MANAGER is not set on this repository; cannot post the nag."
168
- echo "ready=false" >> "$GITHUB_OUTPUT"
169
- exit 0
170
- fi
171
- if [ -z "${HQ_AUDIT_BOT_APP_ID:-}" ] || [ -z "${HQ_AUDIT_BOT_PRIVATE_KEY:-}" ]; then
172
- echo "::warning::hq-audit-bot App credentials are not set; cannot read hq-cli / hq-desktop-app main."
173
- echo "ready=false" >> "$GITHUB_OUTPUT"
174
- exit 0
175
- fi
176
- echo "ready=true" >> "$GITHUB_OUTPUT"
177
-
178
- - name: Mint installation token for the consumer repos
179
- id: app-token
180
- if: steps.pre.outputs.ready == 'true'
181
- uses: actions/create-github-app-token@v1
182
- with:
183
- app-id: ${{ env.HQ_AUDIT_BOT_APP_ID }}
184
- private-key: ${{ env.HQ_AUDIT_BOT_PRIVATE_KEY }}
185
- owner: indigoai-us
186
- repositories: |
187
- hq-cli
188
- hq-desktop-app
189
-
190
- - name: Compare consumer pins against the latest hq-cloud release
191
- if: steps.pre.outputs.ready == 'true'
192
- env:
193
- GH_TOKEN: ${{ steps.app-token.outputs.token }}
194
- run: |
195
- set -euo pipefail
196
-
197
- git fetch --force --tags --quiet origin main
198
-
199
- LATEST_TAG="$(git tag --list 'v*' --merged origin/main --sort=-v:refname \
200
- | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1 || true)"
201
- if [ -z "$LATEST_TAG" ]; then
202
- echo "No stable hq-cloud release yet; nothing to compare against."
203
- exit 0
204
- fi
205
- LATEST="${LATEST_TAG#v}"
206
- echo "Latest stable hq-cloud release: ${LATEST}"
207
-
208
- # --- hq-cli: resolved version in the lockfile's importers section ---
209
- gh api "repos/indigoai-us/hq-cli/contents/pnpm-lock.yaml?ref=main" \
210
- -H 'Accept: application/vnd.github.raw' > /tmp/hq-cli-lock.yaml
211
- CLI_PIN="$(grep -A2 "^ '@indigoai-us/hq-cloud':" /tmp/hq-cli-lock.yaml \
212
- | awk '/^ version:/{print $2; exit}' | sed 's/(.*//')"
213
- if [ -z "$CLI_PIN" ]; then
214
- echo "::error::Could not read the resolved @indigoai-us/hq-cloud version from hq-cli's pnpm-lock.yaml. The lockfile layout changed — fix this parser rather than letting the check pass silently."
215
- exit 1
216
- fi
217
- echo "hq-cli pins: ${CLI_PIN}"
218
-
219
- # --- hq-desktop-app: HQ_CLOUD_VERSION constant, tilde stripped ---
220
- gh api "repos/indigoai-us/hq-desktop-app/contents/crates/hq-desktop-core/src/hq_cloud.rs?ref=main" \
221
- -H 'Accept: application/vnd.github.raw' > /tmp/hq_cloud.rs
222
- DESK_RAW="$(grep -oP 'HQ_CLOUD_VERSION\s*:\s*&str\s*=\s*"\K[^"]+' /tmp/hq_cloud.rs | head -1)"
223
- if [ -z "$DESK_RAW" ]; then
224
- echo "::error::Could not read HQ_CLOUD_VERSION from hq-desktop-app's crates/hq-desktop-core/src/hq_cloud.rs. The constant moved or was renamed — fix this parser rather than letting the check pass silently."
225
- exit 1
226
- fi
227
- DESK_PIN="${DESK_RAW#\~}"
228
- DESK_PIN="${DESK_PIN#^}"
229
- echo "hq-desktop-app pins: ${DESK_RAW} (compared as ${DESK_PIN})"
230
-
231
- LAGGARDS=""
232
- if [ "$CLI_PIN" != "$LATEST" ]; then
233
- LAGGARDS="${LAGGARDS}"$'\n'"• \`hq-cli\` is on \`${CLI_PIN}\` (pnpm-lock.yaml)"
234
- fi
235
- if [ "$DESK_PIN" != "$LATEST" ]; then
236
- LAGGARDS="${LAGGARDS}"$'\n'"• \`hq-desktop-app\` is on \`${DESK_RAW}\` (HQ_CLOUD_VERSION)"
237
- fi
238
-
239
- if [ -z "$LAGGARDS" ]; then
240
- echo "Both consumers are pinned to ${LATEST}. Nothing to nag about."
241
- exit 0
242
- fi
243
-
244
- TEXT=":link: *hq-cloud \`${LATEST}\` is released but not pinned everywhere.* A runner nobody pins is a runner nobody runs:${LAGGARDS}"$'\n'"Bump the pin(s) to \`${LATEST}\` and ship. <https://github.com/indigoai-us/hq-cloud/releases/tag/${LATEST_TAG}|Release ${LATEST_TAG}>."
245
-
246
- RESP="$(curl -s -X POST \
247
- -H "Authorization: Bearer ${SLACK_TOKEN}" \
248
- -H 'Content-type: application/json; charset=utf-8' \
249
- --data "$(jq -nc --arg c "$SLACK_CHANNEL" --arg t "$TEXT" '{channel:$c,text:$t,unfurl_links:false}')" \
250
- https://slack.com/api/chat.postMessage)"
251
- OK="$(echo "$RESP" | jq -r '.ok')"
252
- echo "Slack post ok=${OK} err=$(echo "$RESP" | jq -r '.error // "-"')"
253
- if [ "$OK" != "true" ]; then
254
- echo "::error::Slack rejected the nag: $(echo "$RESP" | jq -r '.error // "unknown"')"
255
- exit 1
256
- fi
package/eslint.config.js DELETED
@@ -1,67 +0,0 @@
1
- import js from "@eslint/js";
2
- import tseslint from "typescript-eslint";
3
-
4
- const nodeGlobals = {
5
- AbortController: "readonly",
6
- Buffer: "readonly",
7
- clearInterval: "readonly",
8
- clearTimeout: "readonly",
9
- console: "readonly",
10
- fetch: "readonly",
11
- process: "readonly",
12
- setInterval: "readonly",
13
- setTimeout: "readonly",
14
- structuredClone: "readonly",
15
- URL: "readonly",
16
- };
17
-
18
- const vitestGlobals = {
19
- afterEach: "readonly",
20
- beforeEach: "readonly",
21
- describe: "readonly",
22
- expect: "readonly",
23
- it: "readonly",
24
- vi: "readonly",
25
- };
26
-
27
- export default tseslint.config(
28
- {
29
- ignores: [
30
- "coverage/**",
31
- "dist/**",
32
- "node_modules/**",
33
- "pnpm-lock.yaml",
34
- "*.config.js",
35
- "*.config.mjs",
36
- "*.config.cjs",
37
- "generated/**",
38
- "**/*.generated.*",
39
- ],
40
- },
41
- {
42
- files: ["src/**/*.ts", "test/**/*.ts"],
43
- extends: [js.configs.recommended, ...tseslint.configs.recommended],
44
- languageOptions: {
45
- ecmaVersion: 2022,
46
- sourceType: "module",
47
- globals: {
48
- ...nodeGlobals,
49
- ...vitestGlobals,
50
- },
51
- },
52
- rules: {
53
- "@typescript-eslint/no-explicit-any": "warn",
54
- "@typescript-eslint/no-unused-vars": [
55
- "error",
56
- {
57
- argsIgnorePattern: "^_",
58
- caughtErrorsIgnorePattern: "^_",
59
- destructuredArrayIgnorePattern: "^_",
60
- varsIgnorePattern: "^_",
61
- },
62
- ],
63
- "no-useless-assignment": "off",
64
- "preserve-caught-error": "off",
65
- },
66
- },
67
- );
@@ -1,2 +0,0 @@
1
- allowBuilds:
2
- esbuild: true
@@ -1,250 +0,0 @@
1
- /**
2
- * Live E2E for the presigned-URL transport (hq-cloud feat/presign-transport).
3
- *
4
- * Drives the real s3.ts primitives through the PRESIGN factory against
5
- * production (hqapi.hq.computer), exercising the exact code path that
6
- * @getindigo.ai sync sessions will use: VaultClient.presign/listFiles +
7
- * PresignObjectIO + fetch. Creates a scratch object under a clearly-marked
8
- * prefix, round-trips it (put → list → head → get → symlink → delete), and
9
- * deletes everything it created. Read-only on all real vault data.
10
- *
11
- * Run from the worktree root after `pnpm build`:
12
- * node scripts/presign-transport-e2e.mjs
13
- */
14
- import * as fs from "fs";
15
- import * as os from "os";
16
- import * as path from "path";
17
- import { VaultClient } from "../dist/vault-client.js";
18
- import {
19
- setObjectIOFactory,
20
- presignObjectIOFactory,
21
- } from "../dist/object-io.js";
22
- import {
23
- uploadFile,
24
- uploadSymlink,
25
- downloadFile,
26
- listRemoteFiles,
27
- headRemoteFile,
28
- deleteRemoteFile,
29
- } from "../dist/s3.js";
30
-
31
- const API = process.env.HQ_VAULT_API_URL ?? "https://hqapi.hq.computer";
32
-
33
- const results = [];
34
- function check(name, cond, detail = "") {
35
- results.push({ name, ok: !!cond, detail });
36
- console.log(`${cond ? "✓" : "✗"} ${name}${detail ? ` — ${detail}` : ""}`);
37
- }
38
-
39
- function loadAccessToken() {
40
- const p = path.join(os.homedir(), ".hq", "cognito-tokens.json");
41
- const t = JSON.parse(fs.readFileSync(p, "utf-8"));
42
- const at = t.accessToken;
43
- if (!at) throw new Error("no accessToken in cognito-tokens.json");
44
- return at;
45
- }
46
-
47
- async function main() {
48
- const token = loadAccessToken();
49
- const vault = new VaultClient({ apiUrl: API, authToken: token });
50
-
51
- // Resolve a company the caller can write to (owner/admin role).
52
- const memberships = await vault.listMyMemberships();
53
- const writable = memberships.find(
54
- (m) => m.role === "owner" || m.role === "admin",
55
- );
56
- if (!writable) {
57
- throw new Error(
58
- `no owner/admin membership found (roles: ${memberships.map((m) => m.role).join(",") || "none"})`,
59
- );
60
- }
61
- const companyUid = writable.companyUid;
62
- let slug = companyUid;
63
- try {
64
- slug = (await vault.entity.get(companyUid)).slug ?? companyUid;
65
- } catch {
66
- /* display only */
67
- }
68
- console.log(`\nTarget: ${slug} (${companyUid}), role=${writable.role}\n`);
69
-
70
- // Install the presign transport — the same selection runRunner makes for a
71
- // @getindigo.ai session. ctx.credentials/bucketName/region are UNUSED on the
72
- // presign path (only ctx.uid → companyUid matters), so dummy values are fine.
73
- setObjectIOFactory(presignObjectIOFactory(vault));
74
- const ctx = {
75
- uid: companyUid,
76
- slug,
77
- bucketName: "(presign-unused)",
78
- region: "us-east-1",
79
- credentials: { accessKeyId: "x", secretAccessKey: "x", sessionToken: "x" },
80
- expiresAt: "2099-01-01T00:00:00.000Z",
81
- };
82
-
83
- const stamp = Date.now().toString(36);
84
- const prefix = `shared/_presign_e2e_${stamp}/`;
85
- const fileKey = `${prefix}hooks/presign-e2e-hook.sh`;
86
- const legacyKey = `${prefix}hooks/legacy-e2e-hook.sh`;
87
- const linkKey = `${prefix}link`;
88
- const author = { userSub: "e2e-probe-sub", email: "hassaan@getindigo.ai" };
89
-
90
- const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "presign-e2e-"));
91
- const localUp = path.join(tmp, "presign-e2e-hook.sh");
92
- const localDown = path.join(tmp, "downloaded-hook.sh");
93
- const legacyDown = path.join(tmp, "legacy-hook.sh");
94
- const localLink = path.join(tmp, "link");
95
- const content = `#!/usr/bin/env bash\n# presign-transport probe ${stamp}\n${"x".repeat(2000)}`;
96
- fs.writeFileSync(localUp, content);
97
- fs.chmodSync(localUp, 0o755);
98
-
99
- let allCreated = [];
100
- try {
101
- // ---- PUT (presigned, with metadata signed in) -----------------------
102
- const up = await uploadFile(ctx, localUp, fileKey, author);
103
- allCreated.push(fileKey);
104
- check("uploadFile returns an etag", !!up.etag, up.etag);
105
-
106
- // ---- LIST (presigned list, etag is load-bearing) --------------------
107
- const listed = await listRemoteFiles(ctx, prefix);
108
- const row = listed.find((o) => o.key === fileKey);
109
- check("listRemoteFiles finds the uploaded key", !!row);
110
- check(
111
- "listed object carries a non-empty etag (#269)",
112
- !!row && typeof row.etag === "string" && row.etag.length > 0,
113
- row?.etag,
114
- );
115
- check(
116
- "listed size matches uploaded bytes",
117
- !!row && row.size === Buffer.byteLength(content),
118
- `${row?.size} vs ${Buffer.byteLength(content)}`,
119
- );
120
-
121
- // ---- HEAD (presigned GET + header read) -----------------------------
122
- const head = await headRemoteFile(ctx, fileKey);
123
- check("headRemoteFile returns metadata", !!head && !!head.metadata);
124
- check(
125
- "metadata.created-by round-trips (signed PUT meta)",
126
- head?.metadata?.["created-by"] === author.email,
127
- head?.metadata?.["created-by"],
128
- );
129
- check(
130
- "metadata.hq-mode round-trips as 755",
131
- head?.metadata?.["hq-mode"] === "755",
132
- head?.metadata?.["hq-mode"],
133
- );
134
- check(
135
- "head etag matches list etag",
136
- !!head && !!row && head.etag === row.etag,
137
- `${head?.etag} vs ${row?.etag}`,
138
- );
139
-
140
- // ---- GET (presigned download to an empty destination, bytes + mode) --
141
- const dl = await downloadFile(ctx, fileKey, localDown);
142
- const got = fs.readFileSync(localDown, "utf-8");
143
- check("downloadFile bytes match upload", got === content);
144
- check(
145
- "downloaded hook mode is 0755 (hq-mode applied)",
146
- (fs.lstatSync(localDown).mode & 0o777) === 0o755,
147
- "0" + (fs.lstatSync(localDown).mode & 0o777).toString(8),
148
- );
149
- check(
150
- "downloadFile surfaces created-by metadata",
151
- dl?.metadata?.["created-by"] === author.email,
152
- );
153
-
154
- // ---- Legacy hq-mode fallback ----------------------------------------
155
- // Create a pre-hq-mode object through the same real presigned PUT
156
- // endpoint, deliberately omitting metadata. A legacy remote overwrite
157
- // must retain the known-good local executable mode instead of silently
158
- // replacing the hook with the receiver's usual 0644 umask default.
159
- const legacyPresign = await vault.presign({
160
- companyUid,
161
- op: "put",
162
- keys: [{ key: legacyKey, op: "put", contentType: "text/x-shellscript" }],
163
- });
164
- const legacyPut = legacyPresign.results[0];
165
- if (!legacyPut?.url) throw new Error("legacy PUT presign was not returned");
166
- const legacyPutResponse = await fetch(legacyPut.url, {
167
- method: "PUT",
168
- headers: legacyPut.headers,
169
- body: "#!/usr/bin/env bash\necho legacy hook\n",
170
- });
171
- if (!legacyPutResponse.ok) {
172
- throw new Error(`legacy presigned PUT failed: ${legacyPutResponse.status}`);
173
- }
174
- allCreated.push(legacyKey);
175
- const legacyHead = await headRemoteFile(ctx, legacyKey);
176
- check(
177
- "legacy object deliberately has no hq-mode metadata",
178
- legacyHead?.metadata?.["hq-mode"] === undefined,
179
- legacyHead?.metadata?.["hq-mode"],
180
- );
181
- fs.writeFileSync(legacyDown, "#!/usr/bin/env bash\necho prior hook\n");
182
- fs.chmodSync(legacyDown, 0o755);
183
- const legacyDownload = await downloadFile(ctx, legacyKey, legacyDown);
184
- check(
185
- "legacy hook fallback retains existing 0755 mode (not 0644)",
186
- (fs.lstatSync(legacyDown).mode & 0o777) === 0o755,
187
- "0" + (fs.lstatSync(legacyDown).mode & 0o777).toString(8),
188
- );
189
- check(
190
- "legacy hq-mode fallback is surfaced for repair telemetry",
191
- legacyDownload.modeWarnings?.some(
192
- (warning) =>
193
- warning.reason === "missing-hq-mode" &&
194
- warning.fallback === "preserved-local-mode",
195
- ) === true,
196
- );
197
-
198
- // ---- SYMLINK round-trip --------------------------------------------
199
- const ln = await uploadSymlink(ctx, "../target/path.txt", linkKey, author);
200
- allCreated.push(linkKey);
201
- check("uploadSymlink returns an etag", !!ln.etag);
202
- await downloadFile(ctx, linkKey, localLink);
203
- const st = fs.lstatSync(localLink);
204
- check("downloaded symlink is a symlink", st.isSymbolicLink());
205
- check(
206
- "symlink target round-trips",
207
- st.isSymbolicLink() && fs.readlinkSync(localLink) === "../target/path.txt",
208
- st.isSymbolicLink() ? fs.readlinkSync(localLink) : "(not a link)",
209
- );
210
-
211
- // ---- DELETE (presigned) --------------------------------------------
212
- await deleteRemoteFile(ctx, fileKey);
213
- await deleteRemoteFile(ctx, legacyKey);
214
- await deleteRemoteFile(ctx, linkKey);
215
- allCreated = [];
216
- const afterFile = await headRemoteFile(ctx, fileKey);
217
- check("headRemoteFile is null after delete", afterFile === null);
218
- const afterList = await listRemoteFiles(ctx, prefix);
219
- check(
220
- "listRemoteFiles empty after delete",
221
- afterList.filter((o) => o.key.startsWith(prefix)).length === 0,
222
- `${afterList.length} remaining`,
223
- );
224
- } finally {
225
- // Best-effort cleanup of anything left if an assertion threw mid-run.
226
- for (const k of allCreated) {
227
- try {
228
- await deleteRemoteFile(ctx, k);
229
- } catch {
230
- /* ignore */
231
- }
232
- }
233
- fs.rmSync(tmp, { recursive: true, force: true });
234
- }
235
-
236
- const failed = results.filter((r) => !r.ok);
237
- console.log(
238
- `\n${results.length - failed.length}/${results.length} checks passed`,
239
- );
240
- if (failed.length > 0) {
241
- console.log("FAILED:", failed.map((f) => f.name).join("; "));
242
- process.exit(1);
243
- }
244
- console.log("ALL GREEN");
245
- }
246
-
247
- main().catch((err) => {
248
- console.error("E2E error:", err);
249
- process.exit(2);
250
- });