@indigoai-us/hq-cli 5.345.113 → 5.345.115

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 (61) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/assets/scaffold/core/scripts/hq-delegate-send.sh +5 -1
  3. package/dist/commands/bot-jobs.d.ts +1 -11
  4. package/dist/commands/bot-jobs.js +13 -34
  5. package/dist/commands/capacity.js +2 -0
  6. package/dist/commands/core-audit-log-native.js +1 -1
  7. package/dist/commands/core-checkpoint-native.d.ts +27 -0
  8. package/dist/commands/core-checkpoint-native.js +85 -2
  9. package/dist/commands/core-dm-bind-native.js +1 -1
  10. package/dist/commands/core-git-pack-extension-check-native.js +1 -1
  11. package/dist/commands/core-job-native-utils.d.ts +2 -2
  12. package/dist/commands/core-job-native-utils.js +3 -11
  13. package/dist/commands/core-job-notify-native.js +1 -2
  14. package/dist/commands/core-job-probe-native.d.ts +2 -3
  15. package/dist/commands/core-job-probe-native.js +14 -22
  16. package/dist/commands/core-job-remediate-native.js +1 -2
  17. package/dist/commands/core-job-run-native.js +58 -54
  18. package/dist/commands/core-jobs-native.d.ts +1 -3
  19. package/dist/commands/core-jobs-native.js +16 -271
  20. package/dist/commands/core-jobs-schedule.d.ts +7 -0
  21. package/dist/commands/core-jobs-schedule.js +243 -0
  22. package/dist/commands/core-native-utilities.d.ts +2 -3
  23. package/dist/commands/core-native-utilities.js +2 -19
  24. package/dist/commands/core-pin-native.js +1 -1
  25. package/dist/commands/core-refresh-vault-access-native.js +1 -1
  26. package/dist/commands/core-resolve-company-command.js +2 -17
  27. package/dist/commands/core-work-mesh-bind-trusted-native.js +1 -1
  28. package/dist/commands/core.js +1 -17
  29. package/dist/commands/lanes.js +1 -0
  30. package/dist/fast-scaffold.d.ts +1 -1
  31. package/dist/fast-scaffold.js +0 -38
  32. package/dist/lib/capacity/lane-login.js +73 -6
  33. package/dist/lib/capacity/route.d.ts +1 -1
  34. package/dist/lib/capacity/route.js +5 -1
  35. package/dist/lib/capacity/sign-in.d.ts +12 -0
  36. package/dist/lib/capacity/sign-in.js +65 -16
  37. package/dist/lib/daemon/catalog.d.ts +0 -2
  38. package/dist/lib/daemon/catalog.js +3 -6
  39. package/dist/lib/daemon/run.js +0 -7
  40. package/dist/utils/resident-package-preload.js +2 -7
  41. package/package.json +1 -1
  42. package/assets/scaffold/core/scripts/audit-log.sh +0 -384
  43. package/assets/scaffold/core/scripts/git-pack-extension-check.sh +0 -164
  44. package/assets/scaffold/core/scripts/hq-dm-bind.sh +0 -590
  45. package/assets/scaffold/core/scripts/hq-job-notify.sh +0 -389
  46. package/assets/scaffold/core/scripts/hq-job-probe.sh +0 -865
  47. package/assets/scaffold/core/scripts/hq-job-remediate.sh +0 -359
  48. package/assets/scaffold/core/scripts/hq-job-run.sh +0 -1025
  49. package/assets/scaffold/core/scripts/hq-pin.sh +0 -118
  50. package/assets/scaffold/core/scripts/jobs-schedule-parse.sh +0 -310
  51. package/assets/scaffold/core/scripts/jobs-validate.sh +0 -482
  52. package/assets/scaffold/core/scripts/outpost-jobs-reconcile.sh +0 -836
  53. package/assets/scaffold/core/scripts/refresh-vault-access.sh +0 -188
  54. package/assets/scaffold/core/scripts/resolve-company.sh +0 -331
  55. package/assets/scaffold/core/scripts/work-mesh-live-bind-trusted.sh +0 -184
  56. package/dist/commands/core-job-post-exit-assets.d.ts +0 -8
  57. package/dist/commands/core-job-post-exit-assets.js +0 -37
  58. package/dist/commands/core-native-jobs-flag.d.ts +0 -4
  59. package/dist/commands/core-native-jobs-flag.js +0 -7
  60. package/dist/commands/core-native-utilities-flag.d.ts +0 -4
  61. package/dist/commands/core-native-utilities-flag.js +0 -7
@@ -1,389 +0,0 @@
1
- #!/usr/bin/env bash
2
- # hq-core: public
3
- # hq-job-notify.sh — dm-only remediation alerts for Outpost scheduled jobs (US-006).
4
- #
5
- # Delivers via schedule-alerts profile with v1 channel=dm only (`hq dm` to owner).
6
- # If profile channel is slack|email|outpost-session, still deliver dm and log
7
- # channel_unimplemented. Never targets the original /schedule create session.
8
- #
9
- # Escalation collapse:
10
- # - first failure → DM immediately
11
- # - consecutive failures → at most one failure DM per 24h per job
12
- # - recovery after failures → recovered DM
13
- # - success after success → ok DM (every successful run)
14
- #
15
- # Notify delivery failure is logged and never fails the caller (exit 0).
16
- #
17
- # Usage:
18
- # core/scripts/hq-job-notify.sh \
19
- # --job-id <id> --job-name <name> --outcome <ok|failed|blocked> \
20
- # --summary <one-line> --duration <sec> --log-path <path> \
21
- # [--failure-class <class>] [--next-action <text>] \
22
- # [--owner <email|prs_*>] [--notify <dm|none|profile>] \
23
- # [--hq-root <dir>]
24
- #
25
- # Env / overrides (tests):
26
- # HQ_ROOT, HOME, HQ_JOB_ALERT_DIR, HQ_JOB_NOTIFY_DM_BIN, HQ_JOB_NOTIFY_NOW_EPOCH
27
- # HQ_JOB_NOTIFY_COLLAPSE_SEC (default 86400)
28
- #
29
- # Exit: 0 always (delivery errors logged only); 2 usage.
30
-
31
- set -euo pipefail
32
-
33
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
34
- HQ_ROOT="${HQ_ROOT:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
35
-
36
- JOB_ID=""
37
- JOB_NAME=""
38
- OUTCOME=""
39
- SUMMARY=""
40
- DURATION=""
41
- LOG_PATH=""
42
- FAILURE_CLASS=""
43
- NEXT_ACTION=""
44
- OWNER=""
45
- NOTIFY_MODE=""
46
-
47
- usage() {
48
- sed -n '3,32p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
49
- }
50
-
51
- die() {
52
- echo "hq-job-notify: $*" >&2
53
- exit 2
54
- }
55
-
56
- log() {
57
- echo "hq-job-notify: $*" >&2
58
- }
59
-
60
- while [ $# -gt 0 ]; do
61
- case "$1" in
62
- --hq-root)
63
- HQ_ROOT="${2:-}"
64
- [ -n "$HQ_ROOT" ] || die "--hq-root requires a directory"
65
- shift 2
66
- ;;
67
- --job-id)
68
- JOB_ID="${2:-}"
69
- [ -n "$JOB_ID" ] || die "--job-id requires a value"
70
- shift 2
71
- ;;
72
- --job-name)
73
- JOB_NAME="${2:-}"
74
- shift 2
75
- ;;
76
- --outcome)
77
- OUTCOME="${2:-}"
78
- [ -n "$OUTCOME" ] || die "--outcome requires a value"
79
- shift 2
80
- ;;
81
- --summary)
82
- SUMMARY="${2:-}"
83
- shift 2
84
- ;;
85
- --duration)
86
- DURATION="${2:-}"
87
- shift 2
88
- ;;
89
- --log-path)
90
- LOG_PATH="${2:-}"
91
- shift 2
92
- ;;
93
- --failure-class)
94
- FAILURE_CLASS="${2:-}"
95
- shift 2
96
- ;;
97
- --next-action)
98
- NEXT_ACTION="${2:-}"
99
- shift 2
100
- ;;
101
- --owner)
102
- OWNER="${2:-}"
103
- shift 2
104
- ;;
105
- --notify)
106
- NOTIFY_MODE="${2:-}"
107
- shift 2
108
- ;;
109
- -h|--help)
110
- usage
111
- exit 0
112
- ;;
113
- --)
114
- shift
115
- break
116
- ;;
117
- -*)
118
- die "unknown option: $1"
119
- ;;
120
- *)
121
- die "unexpected argument: $1"
122
- ;;
123
- esac
124
- done
125
-
126
- [ -n "$JOB_ID" ] || die "usage: hq-job-notify.sh --job-id <id> --outcome <ok|failed|blocked> ..."
127
- case "$OUTCOME" in
128
- ok|failed|blocked) ;;
129
- *) die "--outcome must be ok|failed|blocked" ;;
130
- esac
131
-
132
- [ -n "$JOB_NAME" ] || JOB_NAME="$JOB_ID"
133
- [ -n "$SUMMARY" ] || SUMMARY="$OUTCOME"
134
- [ -n "$DURATION" ] || DURATION="0"
135
- [ -n "$LOG_PATH" ] || LOG_PATH=""
136
-
137
- COLLAPSE_SEC="${HQ_JOB_NOTIFY_COLLAPSE_SEC:-86400}"
138
- ALERT_BASE="${HQ_JOB_ALERT_DIR:-${HOME}/.hq/jobs/alerts}"
139
- STATE_DIR="$ALERT_BASE/$JOB_ID"
140
- mkdir -p "$STATE_DIR"
141
- STATE_FILE="$STATE_DIR/state.json"
142
- DELIVERY_LOG="$STATE_DIR/delivery.log"
143
-
144
- epoch_now() {
145
- if [ -n "${HQ_JOB_NOTIFY_NOW_EPOCH:-}" ]; then
146
- printf '%s' "$HQ_JOB_NOTIFY_NOW_EPOCH"
147
- return
148
- fi
149
- date -u +%s 2>/dev/null || date +%s
150
- }
151
-
152
- iso_now() {
153
- date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null \
154
- || date -u +"%Y-%m-%dT%H:%M:%S+00:00"
155
- }
156
-
157
- read_state() {
158
- if [ -f "$STATE_FILE" ]; then
159
- cat "$STATE_FILE"
160
- else
161
- echo '{}'
162
- fi
163
- }
164
-
165
- write_state() {
166
- local json="$1"
167
- printf '%s\n' "$json" >"$STATE_FILE"
168
- chmod 600 "$STATE_FILE" 2>/dev/null || true
169
- }
170
-
171
- # Resolve notify mode + profile channel.
172
- PROFILE_CHANNEL="dm"
173
- PROFILE_PATH="$HQ_ROOT/personal/settings/schedule-alerts.yaml"
174
- if [ -z "$NOTIFY_MODE" ] || [ "$NOTIFY_MODE" = "null" ]; then
175
- NOTIFY_MODE="profile"
176
- fi
177
-
178
- case "$NOTIFY_MODE" in
179
- none)
180
- log "notify=none — skipping delivery for job $JOB_ID"
181
- echo '{"delivered":false,"reason":"notify_none"}'
182
- exit 0
183
- ;;
184
- dm)
185
- PROFILE_CHANNEL="dm"
186
- ;;
187
- profile)
188
- if [ -f "$PROFILE_PATH" ] && command -v yq >/dev/null 2>&1; then
189
- PROFILE_CHANNEL="$(yq -r '.channel // "dm"' "$PROFILE_PATH" 2>/dev/null || echo dm)"
190
- else
191
- PROFILE_CHANNEL="dm"
192
- fi
193
- ;;
194
- *)
195
- log "unknown notify mode '$NOTIFY_MODE' — falling back to dm"
196
- PROFILE_CHANNEL="dm"
197
- ;;
198
- esac
199
-
200
- CHANNEL_UNIMPLEMENTED=0
201
- case "$PROFILE_CHANNEL" in
202
- dm|"")
203
- PROFILE_CHANNEL="dm"
204
- ;;
205
- slack|email|outpost-session)
206
- CHANNEL_UNIMPLEMENTED=1
207
- log "channel_unimplemented=$PROFILE_CHANNEL — delivering dm fallback"
208
- PROFILE_CHANNEL="dm"
209
- ;;
210
- *)
211
- log "channel_unimplemented=$PROFILE_CHANNEL — delivering dm fallback"
212
- CHANNEL_UNIMPLEMENTED=1
213
- PROFILE_CHANNEL="dm"
214
- ;;
215
- esac
216
-
217
- # Resolve owner (recipient). Prefer explicit --owner, else job owner left to caller.
218
- if [ -z "$OWNER" ] || [ "$OWNER" = "null" ]; then
219
- if command -v hq >/dev/null 2>&1; then
220
- OWNER="$(hq whoami 2>/dev/null | awk -F': ' '/^email:/{print $2; exit}' || true)"
221
- fi
222
- fi
223
- # hq dm accepts personUid recipients; keep an explicit owner UID unchanged.
224
- if [ -z "$OWNER" ]; then
225
- log "no owner recipient — cannot dm (logged only); never fails the job"
226
- echo '{"delivered":false,"reason":"missing_owner"}' | tee -a "$DELIVERY_LOG" >/dev/null
227
- # Still update local state so collapse logic stays coherent.
228
- :
229
- fi
230
-
231
- NOW_EPOCH="$(epoch_now)"
232
- PREV="$(read_state)"
233
- PREV_OUTCOME="$(printf '%s' "$PREV" | jq -r '.last_outcome // empty')"
234
- PREV_FAIL_DM="$(printf '%s' "$PREV" | jq -r '.last_failure_dm_epoch // 0')"
235
- case "$PREV_FAIL_DM" in
236
- ''|*[!0-9]*) PREV_FAIL_DM=0 ;;
237
- esac
238
-
239
- SEND_KIND="" # ok | failed | recovered | suppressed
240
- case "$OUTCOME" in
241
- ok)
242
- if [ "$PREV_OUTCOME" = "failed" ] || [ "$PREV_OUTCOME" = "blocked" ]; then
243
- SEND_KIND="recovered"
244
- else
245
- SEND_KIND="ok"
246
- fi
247
- ;;
248
- failed|blocked)
249
- if [ "$PREV_OUTCOME" = "failed" ] || [ "$PREV_OUTCOME" = "blocked" ]; then
250
- elapsed=$((NOW_EPOCH - PREV_FAIL_DM))
251
- if [ "$PREV_FAIL_DM" -gt 0 ] && [ "$elapsed" -lt "$COLLAPSE_SEC" ]; then
252
- SEND_KIND="suppressed"
253
- else
254
- SEND_KIND="failed"
255
- fi
256
- else
257
- SEND_KIND="failed"
258
- fi
259
- ;;
260
- esac
261
-
262
- STATUS_WORD="$OUTCOME"
263
- case "$SEND_KIND" in
264
- recovered) STATUS_WORD="recovered" ;;
265
- suppressed)
266
- log "collapse: suppressing failure dm for job $JOB_ID (within ${COLLAPSE_SEC}s window)"
267
- NEW_STATE="$(jq -nc \
268
- --arg outcome "$OUTCOME" \
269
- --argjson now "$NOW_EPOCH" \
270
- --argjson last_dm "$PREV_FAIL_DM" \
271
- --arg updated "$(iso_now)" \
272
- --arg fc "$FAILURE_CLASS" \
273
- '{
274
- last_outcome: $outcome,
275
- last_failure_dm_epoch: $last_dm,
276
- last_updated_at: $updated,
277
- last_failure_class: $fc,
278
- last_delivery: "suppressed"
279
- }')"
280
- write_state "$NEW_STATE"
281
- jq -nc \
282
- --arg reason "collapsed_24h" \
283
- --argjson channel_unimplemented "$CHANNEL_UNIMPLEMENTED" \
284
- '{delivered:false, reason:$reason, channel_unimplemented:($channel_unimplemented==1)}'
285
- exit 0
286
- ;;
287
- esac
288
-
289
- # Build message body (no create-thread targeting — hq dm only).
290
- CLASS_PART=""
291
- if [ -n "$FAILURE_CLASS" ] && [ "$FAILURE_CLASS" != "null" ]; then
292
- CLASS_PART=" class=$FAILURE_CLASS"
293
- fi
294
- ACTION_PART=""
295
- if [ -n "$NEXT_ACTION" ]; then
296
- ACTION_PART=" next: $NEXT_ACTION"
297
- fi
298
-
299
- case "$SEND_KIND" in
300
- ok)
301
- HEADLINE="Scheduled job '${JOB_NAME}' ok (${DURATION}s)"
302
- ;;
303
- recovered)
304
- HEADLINE="Scheduled job '${JOB_NAME}' recovered (${DURATION}s)"
305
- ;;
306
- failed)
307
- HEADLINE="Scheduled job '${JOB_NAME}' ${STATUS_WORD}${CLASS_PART} (${DURATION}s)"
308
- ;;
309
- *)
310
- HEADLINE="Scheduled job '${JOB_NAME}' ${STATUS_WORD} (${DURATION}s)"
311
- ;;
312
- esac
313
-
314
- DETAILS="$(printf 'job=%s\nstatus=%s\nclassification=%s\nsummary=%s\nduration_seconds=%s\nlog=%s%s\n' \
315
- "$JOB_ID" "$STATUS_WORD" "${FAILURE_CLASS:-none}" "$SUMMARY" "$DURATION" "${LOG_PATH:-none}" "$ACTION_PART")"
316
-
317
- DELIVERED=0
318
- DELIVER_RC=0
319
- DM_BIN="${HQ_JOB_NOTIFY_DM_BIN:-}"
320
- if [ -z "$DM_BIN" ]; then
321
- if command -v hq >/dev/null 2>&1; then
322
- DM_BIN="hq"
323
- fi
324
- fi
325
-
326
- if [ -z "$OWNER" ]; then
327
- log "skip dm send — missing owner"
328
- DELIVER_RC=1
329
- elif [ -z "$DM_BIN" ]; then
330
- log "skip dm send — hq CLI not found"
331
- DELIVER_RC=1
332
- else
333
- set +e
334
- if [ "$DM_BIN" = "hq" ]; then
335
- hq dm "$OWNER" "$HEADLINE" --details "$DETAILS" >>"$DELIVERY_LOG" 2>&1
336
- DELIVER_RC=$?
337
- else
338
- # Custom binary: invoked as <bin> <owner> <headline> <details>
339
- "$DM_BIN" "$OWNER" "$HEADLINE" "$DETAILS" >>"$DELIVERY_LOG" 2>&1
340
- DELIVER_RC=$?
341
- fi
342
- set -e
343
- if [ "$DELIVER_RC" -eq 0 ]; then
344
- DELIVERED=1
345
- log "dm delivered to $OWNER kind=$SEND_KIND job=$JOB_ID"
346
- else
347
- log "dm delivery failed rc=$DELIVER_RC job=$JOB_ID (logged; not failing run)"
348
- fi
349
- fi
350
-
351
- FAIL_DM_EPOCH="$PREV_FAIL_DM"
352
- if [ "$SEND_KIND" = "failed" ] && [ "$DELIVERED" -eq 1 ]; then
353
- FAIL_DM_EPOCH="$NOW_EPOCH"
354
- elif [ "$SEND_KIND" = "ok" ] || [ "$SEND_KIND" = "recovered" ]; then
355
- FAIL_DM_EPOCH=0
356
- fi
357
-
358
- NEW_STATE="$(jq -nc \
359
- --arg outcome "$OUTCOME" \
360
- --argjson now "$NOW_EPOCH" \
361
- --argjson last_dm "$FAIL_DM_EPOCH" \
362
- --arg updated "$(iso_now)" \
363
- --arg fc "$FAILURE_CLASS" \
364
- --arg kind "$SEND_KIND" \
365
- --argjson delivered "$DELIVERED" \
366
- '{
367
- last_outcome: $outcome,
368
- last_failure_dm_epoch: $last_dm,
369
- last_updated_at: $updated,
370
- last_failure_class: $fc,
371
- last_delivery: $kind,
372
- last_delivered: ($delivered == 1)
373
- }')"
374
- write_state "$NEW_STATE"
375
-
376
- jq -nc \
377
- --argjson delivered "$DELIVERED" \
378
- --arg kind "$SEND_KIND" \
379
- --arg owner "$OWNER" \
380
- --argjson channel_unimplemented "$CHANNEL_UNIMPLEMENTED" \
381
- --argjson deliver_rc "$DELIVER_RC" \
382
- '{
383
- delivered: ($delivered == 1),
384
- kind: $kind,
385
- owner: $owner,
386
- channel_unimplemented: ($channel_unimplemented == 1),
387
- deliver_rc: $deliver_rc
388
- }'
389
- exit 0