@indigoai-us/hq-cli 5.315.0 → 5.317.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.
- package/CHANGELOG.md +13 -0
- package/assets/scaffold/core/scripts/detect-stale-review-base.sh +199 -0
- package/assets/scaffold/core/scripts/repo-run-registry.sh +408 -0
- package/assets/scaffold/core/scripts/session-journal.sh +301 -0
- package/assets/scaffold/core/scripts/session-project.sh +800 -0
- package/assets/scaffold/core/scripts/session-title-config.sh +76 -0
- package/assets/scaffold/core/scripts/session-title.sh +305 -0
- package/assets/scaffold/core/scripts/share-suggestion-state.sh +541 -0
- package/dist/command-catalog.generated.d.ts +97 -0
- package/dist/command-catalog.generated.js +120 -0
- package/dist/commands/bot-jobs.d.ts +5 -1
- package/dist/commands/bot-jobs.js +24 -4
- package/dist/commands/core-detect-stale-review-base-native.d.ts +23 -0
- package/dist/commands/core-detect-stale-review-base-native.js +178 -0
- package/dist/commands/core-hook-state-helpers-native.d.ts +11 -0
- package/dist/commands/core-hook-state-helpers-native.js +74 -0
- package/dist/commands/core-repo-run-registry-native.d.ts +19 -0
- package/dist/commands/core-repo-run-registry-native.js +357 -0
- package/dist/commands/core-session-helper-runtime.d.ts +10 -0
- package/dist/commands/core-session-helper-runtime.js +7 -0
- package/dist/commands/core-session-journal-native.d.ts +4 -0
- package/dist/commands/core-session-journal-native.js +327 -0
- package/dist/commands/core-session-project-native.d.ts +3 -0
- package/dist/commands/core-session-project-native.js +855 -0
- package/dist/commands/core-session-title-config-native.d.ts +4 -0
- package/dist/commands/core-session-title-config-native.js +77 -0
- package/dist/commands/core-session-title-native.d.ts +3 -0
- package/dist/commands/core-session-title-native.js +306 -0
- package/dist/commands/core-share-suggestion-state-native.d.ts +18 -0
- package/dist/commands/core-share-suggestion-state-native.js +445 -0
- package/dist/commands/core.js +66 -0
- package/dist/commands/lanes.js +35 -5
- package/dist/fast-core.d.ts +1 -0
- package/dist/fast-core.js +10 -6
- package/dist/fast-scaffold.js +33 -0
- package/dist/lib/bot/job-quiet-flag.d.ts +4 -0
- package/dist/lib/bot/job-quiet-flag.js +14 -0
- package/dist/lib/bot/job-run.d.ts +5 -0
- package/dist/lib/bot/job-run.js +23 -3
- package/dist/lib/bot/run.d.ts +2 -0
- package/dist/lib/bot/run.js +15 -3
- package/dist/lib/core-utils/common.d.ts +0 -1
- package/dist/lib/core-utils/common.js +0 -9
- package/dist/lib/lanes/autopilot.d.ts +5 -1
- package/dist/lib/lanes/autopilot.js +72 -3
- package/dist/lib/lanes/disk-guard.d.ts +3 -4
- package/dist/lib/lanes/disk-guard.js +2 -2
- package/dist/lib/lanes/flag-keys.d.ts +3 -0
- package/dist/lib/lanes/flag-keys.js +3 -0
- package/dist/lib/lanes/hooks-install.js +78 -2
- package/dist/lib/lanes/keep-alive-audit.d.ts +6 -5
- package/dist/lib/lanes/outpost-dispatch.d.ts +9 -0
- package/dist/lib/lanes/outpost-dispatch.js +22 -0
- package/dist/utils/version-gate.js +8 -7
- package/package.json +1 -1
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# session-journal.sh — minimal helper for session-level journal entries.
|
|
3
|
+
# Spec: core/knowledge/public/hq-core/session-journal-spec.md
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# session-journal.sh write "<title>" [--files f1,f2,...] [--body-file PATH] [--session KEY]
|
|
7
|
+
# session-journal.sh list [--date YYYY-MM-DD]
|
|
8
|
+
# session-journal.sh read <NNN> [--date YYYY-MM-DD]
|
|
9
|
+
# session-journal.sh index-path [--date YYYY-MM-DD] # prints the INDEX.md path
|
|
10
|
+
# session-journal.sh dir-path [--date YYYY-MM-DD] # prints the journal dir
|
|
11
|
+
# session-journal.sh tool-counter increment [--session KEY] # used by PostToolUse hook
|
|
12
|
+
# session-journal.sh tool-counter read [--session KEY] # current count
|
|
13
|
+
# session-journal.sh tool-counter reset [--session KEY]
|
|
14
|
+
#
|
|
15
|
+
# The tool counter is per-session: state lives at
|
|
16
|
+
# workspace/threads/journal/<date>/.tool-count-<session-key>. The key comes from
|
|
17
|
+
# --session, else $HQ_JOURNAL_SESSION, else $HQ_HOOK_SESSION_ID, else
|
|
18
|
+
# "unscoped". A date-global counter let concurrent Claude and Codex tasks
|
|
19
|
+
# trigger and reset each other's journal reminders.
|
|
20
|
+
#
|
|
21
|
+
# All commands fail-soft: warn to stderr, exit 0 — never block the caller.
|
|
22
|
+
|
|
23
|
+
set -uo pipefail
|
|
24
|
+
|
|
25
|
+
HQ_ROOT="${HQ_ROOT:-${CLAUDE_PROJECT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}}"
|
|
26
|
+
|
|
27
|
+
today() { date -u +%Y-%m-%d; }
|
|
28
|
+
now_iso_z() { date -u +%Y-%m-%dT%H:%M:%SZ; }
|
|
29
|
+
now_hhmm_z() { date -u +%H:%MZ; }
|
|
30
|
+
|
|
31
|
+
journal_dir_for() {
|
|
32
|
+
local d="${1:-$(today)}"
|
|
33
|
+
printf '%s/workspace/threads/journal/%s' "$HQ_ROOT" "$d"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
warn() { echo "session-journal: $*" >&2; }
|
|
37
|
+
|
|
38
|
+
slugify() {
|
|
39
|
+
# Lowercase, replace non-alnum with hyphen, collapse hyphens, trim.
|
|
40
|
+
printf '%s' "$1" \
|
|
41
|
+
| tr '[:upper:]' '[:lower:]' \
|
|
42
|
+
| sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//' \
|
|
43
|
+
| cut -c1-40
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
# Counters are per-session. A date-global counter lets concurrent Claude and
|
|
47
|
+
# Codex tasks trip (and reset) each other's journal reminders.
|
|
48
|
+
counter_key() {
|
|
49
|
+
local raw="${1:-}"
|
|
50
|
+
raw="$(printf '%s' "$raw" | tr -c 'A-Za-z0-9._-' '_')"
|
|
51
|
+
raw="${raw#_}"; raw="${raw%_}"
|
|
52
|
+
[ -z "$raw" ] && raw="unscoped"
|
|
53
|
+
[ "${#raw}" -gt 96 ] && raw="${raw:0:96}"
|
|
54
|
+
printf '%s' "$raw"
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
resolve_session_key() {
|
|
58
|
+
counter_key "${1:-${HQ_JOURNAL_SESSION:-${HQ_HOOK_SESSION_ID:-}}}"
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# Read-modify-write on the counter must not interleave across concurrent tasks.
|
|
62
|
+
with_counter_lock() {
|
|
63
|
+
local lockdir="$1"; shift
|
|
64
|
+
local i=0
|
|
65
|
+
while ! mkdir "$lockdir" 2>/dev/null; do
|
|
66
|
+
i=$((i + 1))
|
|
67
|
+
[ "$i" -ge 50 ] && break
|
|
68
|
+
sleep 0.02 2>/dev/null || sleep 1
|
|
69
|
+
done
|
|
70
|
+
"$@"
|
|
71
|
+
rmdir "$lockdir" 2>/dev/null || true
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
counter_read_raw() {
|
|
75
|
+
local counter="$1" n=0
|
|
76
|
+
[ -f "$counter" ] && n=$(tr -dc '0-9' < "$counter" 2>/dev/null)
|
|
77
|
+
[ -z "$n" ] && n=0
|
|
78
|
+
printf '%d' "$n"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
next_seq() {
|
|
82
|
+
local dir="$1"
|
|
83
|
+
# Highest NNN in the dir, +1, zero-padded to 3.
|
|
84
|
+
local hi
|
|
85
|
+
hi=$(ls "$dir" 2>/dev/null \
|
|
86
|
+
| grep -E '^[0-9]{3}-' \
|
|
87
|
+
| sed -E 's/^([0-9]+)-.*/\1/' \
|
|
88
|
+
| sort -n \
|
|
89
|
+
| tail -1)
|
|
90
|
+
if [ -z "$hi" ]; then printf '001'; else printf '%03d' $((10#$hi + 1)); fi
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
acquire_journal_write_lock() {
|
|
94
|
+
local lock="$1/.session-journal-write.lock" owner=0 i=0
|
|
95
|
+
while [ "$i" -lt 250 ]; do
|
|
96
|
+
if mkdir "$lock" 2>/dev/null; then
|
|
97
|
+
printf '%s\n' "$$" > "$lock/pid" || { rm -rf "$lock"; return 1; }
|
|
98
|
+
JOURNAL_WRITE_LOCK="$lock"
|
|
99
|
+
return 0
|
|
100
|
+
fi
|
|
101
|
+
owner="$(cat "$lock/pid" 2>/dev/null || true)"
|
|
102
|
+
if [[ "$owner" =~ ^[0-9]+$ ]] && [ "$owner" -gt 0 ] && ! kill -0 "$owner" 2>/dev/null; then
|
|
103
|
+
if [ "$(cat "$lock/pid" 2>/dev/null || true)" = "$owner" ]; then rm -rf "$lock" 2>/dev/null || true; fi
|
|
104
|
+
fi
|
|
105
|
+
i=$((i + 1))
|
|
106
|
+
sleep 0.02 2>/dev/null || sleep 1
|
|
107
|
+
done
|
|
108
|
+
return 1
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
release_journal_write_lock() {
|
|
112
|
+
[ -n "${JOURNAL_WRITE_LOCK:-}" ] || return 0
|
|
113
|
+
if [ "$(cat "$JOURNAL_WRITE_LOCK/pid" 2>/dev/null || true)" = "$$" ]; then
|
|
114
|
+
rm -rf "$JOURNAL_WRITE_LOCK" 2>/dev/null || true
|
|
115
|
+
fi
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
cmd="${1:-}"; shift || true
|
|
119
|
+
|
|
120
|
+
case "$cmd" in
|
|
121
|
+
write)
|
|
122
|
+
title="${1:-}"; shift || true
|
|
123
|
+
files_csv=""
|
|
124
|
+
body_file=""
|
|
125
|
+
session_arg=""
|
|
126
|
+
while [ $# -gt 0 ]; do
|
|
127
|
+
case "$1" in
|
|
128
|
+
--files) files_csv="${2:-}"; shift 2 || break ;;
|
|
129
|
+
--body-file) body_file="${2:-}"; shift 2 || break ;;
|
|
130
|
+
--session) session_arg="${2:-}"; shift 2 || break ;;
|
|
131
|
+
*) shift ;;
|
|
132
|
+
esac
|
|
133
|
+
done
|
|
134
|
+
|
|
135
|
+
[ -z "$title" ] && { warn "write: title required"; exit 0; }
|
|
136
|
+
|
|
137
|
+
d="$(today)"
|
|
138
|
+
dir="$(journal_dir_for "$d")"
|
|
139
|
+
mkdir -p "$dir" 2>/dev/null || { warn "write: mkdir failed: $dir"; exit 0; }
|
|
140
|
+
|
|
141
|
+
slug="$(slugify "$title")"
|
|
142
|
+
[ -z "$slug" ] && slug="entry"
|
|
143
|
+
JOURNAL_WRITE_LOCK=""
|
|
144
|
+
acquire_journal_write_lock "$dir" || { warn "write: failed to acquire journal lock"; exit 0; }
|
|
145
|
+
trap release_journal_write_lock EXIT
|
|
146
|
+
seq=""
|
|
147
|
+
out=""
|
|
148
|
+
created=false
|
|
149
|
+
attempt=0
|
|
150
|
+
while [ "$attempt" -lt 10000 ]; do
|
|
151
|
+
attempt=$((attempt + 1))
|
|
152
|
+
seq="$(next_seq "$dir")"
|
|
153
|
+
out="$dir/${seq}-${slug}.md"
|
|
154
|
+
write_status=0
|
|
155
|
+
(
|
|
156
|
+
set -o noclobber
|
|
157
|
+
if ! exec 3>"$out" 2>/dev/null; then
|
|
158
|
+
if [ -e "$out" ] || [ -L "$out" ]; then exit 17; fi
|
|
159
|
+
exit 16
|
|
160
|
+
fi
|
|
161
|
+
{
|
|
162
|
+
printf -- '---\n'
|
|
163
|
+
printf 'ts: %s\n' "$(now_iso_z)"
|
|
164
|
+
printf 'title: %s\n' "$title"
|
|
165
|
+
printf 'slug: %s\n' "$slug"
|
|
166
|
+
if [ -n "$files_csv" ]; then
|
|
167
|
+
printf 'files:\n'
|
|
168
|
+
old_ifs="$IFS"
|
|
169
|
+
IFS=','
|
|
170
|
+
set -- $files_csv
|
|
171
|
+
IFS="$old_ifs"
|
|
172
|
+
for f in "$@"; do
|
|
173
|
+
[ -n "$f" ] && printf ' - %s\n' "$f"
|
|
174
|
+
done
|
|
175
|
+
fi
|
|
176
|
+
printf 'status: closed\n'
|
|
177
|
+
printf -- '---\n\n'
|
|
178
|
+
printf '# %s — %s\n\n' "$seq" "$title"
|
|
179
|
+
if [ -n "$body_file" ] && [ -f "$body_file" ]; then
|
|
180
|
+
cat "$body_file"
|
|
181
|
+
else
|
|
182
|
+
printf '## Goal\n\n## Findings\n\n## Decisions\n\n## Next\n'
|
|
183
|
+
fi
|
|
184
|
+
} >&3 || exit 18
|
|
185
|
+
)
|
|
186
|
+
write_status=$?
|
|
187
|
+
if [ "$write_status" -eq 0 ]; then
|
|
188
|
+
created=true
|
|
189
|
+
break
|
|
190
|
+
elif [ "$write_status" -eq 17 ]; then
|
|
191
|
+
continue
|
|
192
|
+
else
|
|
193
|
+
warn "write: failed to write $out"
|
|
194
|
+
exit 0
|
|
195
|
+
fi
|
|
196
|
+
done
|
|
197
|
+
[ "$created" = true ] || { warn "write: failed to write $out"; exit 0; }
|
|
198
|
+
|
|
199
|
+
# Update INDEX.md
|
|
200
|
+
idx="$dir/INDEX.md"
|
|
201
|
+
if [ ! -f "$idx" ]; then
|
|
202
|
+
printf '# Session journal — %s\n\n' "$d" > "$idx"
|
|
203
|
+
fi
|
|
204
|
+
printf -- '- `%s` %s — %s\n' "$seq" "$(now_hhmm_z)" "$title" >> "$idx" \
|
|
205
|
+
|| warn "write: INDEX update failed"
|
|
206
|
+
|
|
207
|
+
# Reset the tool counter for THIS session only — journaling one task's
|
|
208
|
+
# milestone must not clear a concurrent task's progress toward its own.
|
|
209
|
+
"$0" tool-counter reset --session "$(resolve_session_key "$session_arg")" >/dev/null 2>&1 || true
|
|
210
|
+
|
|
211
|
+
printf '%s\n' "$out"
|
|
212
|
+
;;
|
|
213
|
+
|
|
214
|
+
list)
|
|
215
|
+
date_arg="$(today)"
|
|
216
|
+
while [ $# -gt 0 ]; do
|
|
217
|
+
case "$1" in --date) date_arg="${2:-$(today)}"; shift 2 ;; *) shift ;; esac
|
|
218
|
+
done
|
|
219
|
+
dir="$(journal_dir_for "$date_arg")"
|
|
220
|
+
idx="$dir/INDEX.md"
|
|
221
|
+
if [ -f "$idx" ]; then
|
|
222
|
+
cat "$idx"
|
|
223
|
+
else
|
|
224
|
+
echo "(no journal for $date_arg)"
|
|
225
|
+
fi
|
|
226
|
+
;;
|
|
227
|
+
|
|
228
|
+
read)
|
|
229
|
+
seq="${1:-}"; shift || true
|
|
230
|
+
date_arg="$(today)"
|
|
231
|
+
while [ $# -gt 0 ]; do
|
|
232
|
+
case "$1" in --date) date_arg="${2:-$(today)}"; shift 2 ;; *) shift ;; esac
|
|
233
|
+
done
|
|
234
|
+
[ -z "$seq" ] && { warn "read: NNN required"; exit 0; }
|
|
235
|
+
[[ "$seq" =~ ^[0-9]{1,18}$ ]] || { warn "read: NNN required"; exit 0; }
|
|
236
|
+
seq=$(printf '%03d' $((10#$seq)) 2>/dev/null) || seq="$seq"
|
|
237
|
+
dir="$(journal_dir_for "$date_arg")"
|
|
238
|
+
match=$(ls "$dir" 2>/dev/null | grep -E "^${seq}-" | head -1)
|
|
239
|
+
if [ -n "$match" ]; then cat "$dir/$match"; else warn "read: no entry $seq for $date_arg"; fi
|
|
240
|
+
;;
|
|
241
|
+
|
|
242
|
+
index-path)
|
|
243
|
+
date_arg="$(today)"
|
|
244
|
+
while [ $# -gt 0 ]; do
|
|
245
|
+
case "$1" in --date) date_arg="${2:-$(today)}"; shift 2 ;; *) shift ;; esac
|
|
246
|
+
done
|
|
247
|
+
printf '%s/INDEX.md\n' "$(journal_dir_for "$date_arg")"
|
|
248
|
+
;;
|
|
249
|
+
|
|
250
|
+
dir-path)
|
|
251
|
+
date_arg="$(today)"
|
|
252
|
+
while [ $# -gt 0 ]; do
|
|
253
|
+
case "$1" in --date) date_arg="${2:-$(today)}"; shift 2 ;; *) shift ;; esac
|
|
254
|
+
done
|
|
255
|
+
journal_dir_for "$date_arg"
|
|
256
|
+
;;
|
|
257
|
+
|
|
258
|
+
tool-counter)
|
|
259
|
+
sub="${1:-}"; shift || true
|
|
260
|
+
session_arg=""
|
|
261
|
+
while [ $# -gt 0 ]; do
|
|
262
|
+
case "$1" in --session) session_arg="${2:-}"; shift 2 || break ;; *) shift ;; esac
|
|
263
|
+
done
|
|
264
|
+
session_key="$(resolve_session_key "$session_arg")"
|
|
265
|
+
dir="$(journal_dir_for "$(today)")"
|
|
266
|
+
mkdir -p "$dir" 2>/dev/null || true
|
|
267
|
+
counter="$dir/.tool-count-$session_key"
|
|
268
|
+
lockdir="$counter.lock"
|
|
269
|
+
case "$sub" in
|
|
270
|
+
increment)
|
|
271
|
+
do_increment() {
|
|
272
|
+
local n
|
|
273
|
+
n=$(counter_read_raw "$counter")
|
|
274
|
+
echo $((n + 1)) > "$counter" 2>/dev/null || true
|
|
275
|
+
}
|
|
276
|
+
with_counter_lock "$lockdir" do_increment
|
|
277
|
+
;;
|
|
278
|
+
read)
|
|
279
|
+
printf '%d\n' "$(counter_read_raw "$counter")"
|
|
280
|
+
;;
|
|
281
|
+
reset)
|
|
282
|
+
do_reset() { echo 0 > "$counter" 2>/dev/null || true; }
|
|
283
|
+
with_counter_lock "$lockdir" do_reset
|
|
284
|
+
;;
|
|
285
|
+
*) warn "tool-counter: subcommand required (increment|read|reset)" ;;
|
|
286
|
+
esac
|
|
287
|
+
;;
|
|
288
|
+
|
|
289
|
+
*)
|
|
290
|
+
cat >&2 <<'USAGE'
|
|
291
|
+
session-journal.sh: usage:
|
|
292
|
+
session-journal.sh write "<title>" [--files f1,f2,...] [--body-file PATH] [--session KEY]
|
|
293
|
+
session-journal.sh list [--date YYYY-MM-DD]
|
|
294
|
+
session-journal.sh read <NNN> [--date YYYY-MM-DD]
|
|
295
|
+
session-journal.sh index-path [--date YYYY-MM-DD]
|
|
296
|
+
session-journal.sh dir-path [--date YYYY-MM-DD]
|
|
297
|
+
session-journal.sh tool-counter (increment|read|reset) [--session KEY]
|
|
298
|
+
USAGE
|
|
299
|
+
exit 1
|
|
300
|
+
;;
|
|
301
|
+
esac
|