tickmarkr 2.4.0 → 2.4.2
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/dist/adapters/catalog-remote.d.ts +11 -0
- package/dist/adapters/catalog-remote.js +55 -13
- package/dist/adapters/claude-code.js +7 -2
- package/dist/adapters/codex.d.ts +1 -0
- package/dist/adapters/codex.js +68 -8
- package/dist/adapters/qwen.js +3 -3
- package/dist/adapters/registry.js +13 -1
- package/dist/adapters/types.d.ts +4 -0
- package/dist/adapters/types.js +33 -0
- package/dist/cli/commands/compile.d.ts +3 -0
- package/dist/cli/commands/compile.js +77 -46
- package/dist/cli/commands/doctor.js +14 -9
- package/dist/cli/commands/fleet.js +11 -5
- package/dist/cli/commands/init.js +12 -13
- package/dist/cli/commands/plan.js +47 -7
- package/dist/cli/commands/run.js +20 -1
- package/dist/cli/commands/status.js +20 -21
- package/dist/cli/commands/version.js +2 -2
- package/dist/compile/collateral.d.ts +14 -5
- package/dist/compile/collateral.js +32 -26
- package/dist/compile/index.js +17 -6
- package/dist/compile/native.js +10 -2
- package/dist/compile/ownership.js +15 -9
- package/dist/drivers/herdr.d.ts +1 -0
- package/dist/drivers/herdr.js +32 -3
- package/dist/drivers/orca.d.ts +5 -1
- package/dist/drivers/orca.js +51 -2
- package/dist/drivers/types.d.ts +1 -1
- package/dist/gates/baseline.d.ts +26 -2
- package/dist/gates/baseline.js +90 -7
- package/dist/gates/review.d.ts +2 -2
- package/dist/gates/review.js +2 -18
- package/dist/graph/graph.d.ts +20 -0
- package/dist/graph/graph.js +66 -1
- package/dist/route/preference.d.ts +3 -1
- package/dist/route/preference.js +4 -4
- package/dist/run/consult.js +1 -0
- package/dist/run/daemon.d.ts +5 -0
- package/dist/run/daemon.js +151 -22
- package/dist/run/git.d.ts +2 -0
- package/dist/run/git.js +18 -4
- package/dist/run/journal.d.ts +1 -1
- package/dist/run/journal.js +1 -1
- package/dist/run/lock.d.ts +6 -0
- package/dist/run/lock.js +41 -1
- package/package.json +1 -1
- package/skills/tickmarkr-overseer/SKILL.md +39 -4
- package/skills/tickmarkr-overseer/scripts/grade-ci.sh +79 -0
- package/skills/tickmarkr-overseer/scripts/watch-context.sh +90 -4
|
@@ -165,6 +165,21 @@ overseer holds the mission's judgment. A tier collapse is therefore a context le
|
|
|
165
165
|
**The tell, and you will not notice it from inside:** if you are typing `tickmarkr resume`, or reading a
|
|
166
166
|
journal tail to decide what happens next, or sweeping orphans — you have taken the loop. Hand it back.
|
|
167
167
|
|
|
168
|
+
### Pre-run checklist — install these laws in the brief before `compile` / `plan` / `run`
|
|
169
|
+
|
|
170
|
+
1. **Run the files[]-versus-oracle pin sweep (RULING-222-36).** Read every acceptance item and enumerate
|
|
171
|
+
the PINS its satisfaction must move: implementation files, callers, fixtures, tests, snapshots and
|
|
172
|
+
documentation assertions. Put every pin in that task's `files[]` before compile. A criterion that
|
|
173
|
+
forces a file its scope forbids is a plan defect; repair the plan before dispatch, never spend a
|
|
174
|
+
worker's repair ladder on the scope/test catch-22.
|
|
175
|
+
2. **Install the live-run command boundary (RULING-222-28 §5 and 222-29 §3).** While a run is live, run
|
|
176
|
+
no `vitest` probe of any size — the daemon's `suite-wait` guard counts it. During that same window the
|
|
177
|
+
runner's name never enters a shell argv: not reason text, a heredoc, `pgrep -f`, or a commit subject.
|
|
178
|
+
Write records containing the word through an editor, and wait for run-end before probing.
|
|
179
|
+
3. **Gate a mid-run fix at the base, not at a summary (law 47 / OBS-909).** A fix landed on main while a
|
|
180
|
+
run is live is proved with `tickmarkr verify --base <main>`, never with a suite summary copied from a
|
|
181
|
+
different tree. A release proof runs every CI-ordered step — including lint — before its suite.
|
|
182
|
+
|
|
168
183
|
### What the ORCHESTRATOR does, and what you require of it
|
|
169
184
|
|
|
170
185
|
- **The live surface arrives with the run.** `tickmarkr run` is stdout-silent until run-end by design;
|
|
@@ -358,7 +373,7 @@ The protocol, in both directions:
|
|
|
358
373
|
herdr pane run <partner> "I am at <N>%. Clear me: send /clear to <my-pane>, then point me at <my-handoff>."
|
|
359
374
|
# 3. the PARTNER sends the clear, then VERIFIES before pointing:
|
|
360
375
|
herdr pane run <my-pane> "/clear"
|
|
361
|
-
# read the pane back — a cleared claude session shows an empty prompt and a
|
|
376
|
+
# read the pane back — a cleared claude session shows an empty prompt and a LOWER context percentage
|
|
362
377
|
# 4. and only THEN, as a SEPARATE send, the re-orientation:
|
|
363
378
|
herdr pane run <my-pane> "You were cleared at <N>%. Read <handoff> and <brief>. Same-process clear kept
|
|
364
379
|
every background task alive: retire only your recorded watcher pids, verify twice, kill-by-pid, arm,
|
|
@@ -367,7 +382,9 @@ The protocol, in both directions:
|
|
|
367
382
|
|
|
368
383
|
⚠ **Steps 3 and 4 are two sends, never one.** A pointer batched with the clear lands *during* it and is
|
|
369
384
|
lost with the context it was meant to survive. Verify the clear landed by reading the prompt line
|
|
370
|
-
|
|
385
|
+
and re-reading the banner percentage below its pre-clear value before sending the pointer — the same
|
|
386
|
+
read-back every other send in this skill requires. A working seat or a typed prompt defers the act;
|
|
387
|
+
neither authorises a queued `/clear`.
|
|
371
388
|
⚠ **The partner must not clear itself in the same window.** One supervising tier stays live at all
|
|
372
389
|
times; the seat holding the endgame goes second.
|
|
373
390
|
⚠ **Step 4 must state an EXPECTED-RETURN DEADLINE**, e.g. *"confirm you are back within 10 minutes."*
|
|
@@ -451,7 +468,9 @@ The first argument chooses the closed per-seat tier (`orchestrator-context` or `
|
|
|
451
468
|
and every beat names the second argument as that tier's seat. The watcher beats only after reading a
|
|
452
469
|
rendered percentage, keeps beating on the supervision cadence even when its requested poll is slower,
|
|
453
470
|
continues past WARN to ACT, and records a stand-down on each controlled exit. A killed watcher alone
|
|
454
|
-
leaves its last beat to age into `STALE`.
|
|
471
|
+
leaves its last beat to age into `STALE`. Auto-clear waits for `idle` plus an empty or dim-only ANSI
|
|
472
|
+
prompt line, prints `CONTEXT_ACT_DEFERRED` while that gate is closed, and emits `CONTEXT_CLEARED` only
|
|
473
|
+
after a banner read-back proves the percentage dropped; only then does it send the re-brief.
|
|
455
474
|
**Every handoff's re-arm list ends with the announce step from Setup 0** — inform the surviving
|
|
456
475
|
orchestrator the fresh seat is live — or the next seat re-arms silently beside a tier that still
|
|
457
476
|
believes it is alone.
|
|
@@ -545,6 +564,11 @@ they are left implicit:
|
|
|
545
564
|
that discriminates** — text sitting on `❯` is exactly what will not run — and a delivery report
|
|
546
565
|
is prompt-line state alone, or nothing: a decorative check beside a real one reads as
|
|
547
566
|
corroboration (two greens, one of which was never capable of disagreeing).
|
|
567
|
+
**Law 50 applies to every handoff, including `/clear`: a seat-send to a WORKING seat leaves a DRAFT.**
|
|
568
|
+
Send only when the seat is idle and the ANSI prompt line is empty or dim-only (the Esc/SGR discriminator
|
|
569
|
+
separates an autosuggest ghost from typed input), then read back activity or an ACK; presence is not
|
|
570
|
+
delivery. If a stale draft must be replaced, supersede it explicitly with
|
|
571
|
+
`agent prompt " <-- disregard … ACTUAL: …"` instead of stacking another instruction behind it.
|
|
548
572
|
- **A MESSAGE TO A WORKING SEAT IS A QUEUED MESSAGE, AND THE QUEUE DRAINS ONLY AT TURN BOUNDARIES.**
|
|
549
573
|
Delivery is not arrival: `agent prompt` to a `working` claude seat lands in its queue (`Press up to
|
|
550
574
|
edit queued messages` on the seat's prompt line is the tell) and is READ only when the current turn
|
|
@@ -994,10 +1018,21 @@ orchestrator turn boundary.
|
|
|
994
1018
|
- **RUN BOTH RELEASE PROOFS BEFORE STANDING DOWN.** The first is the exported-tree suite, which
|
|
995
1019
|
maintainers run from the private repo with its `verify:export` script — that tooling is deliberately
|
|
996
1020
|
not part of this package, so the command does not exist in a public checkout; it must install,
|
|
997
|
-
build, and run the suite in the exported tree; then
|
|
1021
|
+
build, lint, and only then run the suite in the exported tree; then
|
|
998
1022
|
`TICKMARKR_E2E=1 npx vitest run tests/e2e/orca-smoke.e2e.test.ts` must exercise the installed-Orca
|
|
999
1023
|
smoke. A skipped smoke is not proof. Record both results before declaring the release complete.
|
|
1000
1024
|
|
|
1025
|
+
- **GRADE PUBLIC CI FROM JOB LOGS AT RUN-END ONLY (law 48).** A badge is not the grade, and
|
|
1026
|
+
`gh run view --job --log` is empty while the run is in progress. At run-end execute
|
|
1027
|
+
`scripts/grade-ci.sh <run-id> <expected-count> <tag>` and require GREEN from both jobs; its
|
|
1028
|
+
UNREADABLE state is a hard stop, not a green default. Derive the expected glob pathspec count with
|
|
1029
|
+
`git ls-files ':(glob)tests/**/*.test.ts'` (including the `.tsx` sibling where present), never a bare
|
|
1030
|
+
`tests/**/*.test.ts`: bare `**` is not a git glob (law 49).
|
|
1031
|
+
|
|
1032
|
+
- **RE-READ THE REGISTRY BEFORE RULING (law 51).** A successful Release run and the first
|
|
1033
|
+
`npm view` are separate observations: registry propagation can briefly return the prior version.
|
|
1034
|
+
Read `npm view tickmarkr version` again and verify provenance before recording the publish verdict.
|
|
1035
|
+
|
|
1001
1036
|
- **REWRITE THE MEMORY INDEX FIRST, and read it back.** Minutes after `2.1.1` hit npm, the index line
|
|
1002
1037
|
a fresh session loads still read *"⛔ 2.1.1 CANNOT ship from run …2011"* — true when written, and by
|
|
1003
1038
|
then the exact opposite of the truth. **The index is what everyone loads and the body is what nobody
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# grade-ci.sh <run-id> <expected-count> [tag] — grade both public CI jobs from their JOB LOGS.
|
|
3
|
+
# Grade only at run-end. A missing/in-progress/empty log is UNREADABLE, never evidence of green.
|
|
4
|
+
# Tri-state: exit 0 GREEN, 1 RED, 2 UNREADABLE. UNREADABLE dominates a mixed result.
|
|
5
|
+
set -u
|
|
6
|
+
|
|
7
|
+
run=${1:?run id required}
|
|
8
|
+
expected=${2:?expected tracked test-file count required}
|
|
9
|
+
tag=${3:-$run}
|
|
10
|
+
repo=${TKR_GRADE_CI_REPO:-alzahrani-khalid/tickmarkr}
|
|
11
|
+
out_dir=${TKR_GRADE_CI_DIR:-${TKR_STATE_DIR:-.tickmarkr}/overseer/diag}
|
|
12
|
+
mkdir -p "$out_dir" || { echo "UNREADABLE: cannot create log directory $out_dir"; exit 2; }
|
|
13
|
+
|
|
14
|
+
verdict=0
|
|
15
|
+
mark_unreadable() { verdict=2; }
|
|
16
|
+
mark_red() { [ "$verdict" -eq 0 ] && verdict=1; }
|
|
17
|
+
|
|
18
|
+
jobs=$(gh run view "$run" --repo "$repo" --json jobs \
|
|
19
|
+
--jq '.jobs[] | [.databaseId, .name, .status, (.conclusion // "")] | @tsv') \
|
|
20
|
+
|| { echo "UNREADABLE: job list"; exit 2; }
|
|
21
|
+
[ -n "$jobs" ] || { echo "UNREADABLE: empty job list"; exit 2; }
|
|
22
|
+
|
|
23
|
+
seen_test=0
|
|
24
|
+
seen_macos=0
|
|
25
|
+
while IFS=$'\t' read -r id name status conclusion; do
|
|
26
|
+
case "$name" in
|
|
27
|
+
test) seen_test=1 ;;
|
|
28
|
+
test-macos) seen_macos=1 ;;
|
|
29
|
+
*) continue ;;
|
|
30
|
+
esac
|
|
31
|
+
|
|
32
|
+
echo "$name: status=$status conclusion=${conclusion:-none} job=$id"
|
|
33
|
+
if [ "$status" != "completed" ]; then
|
|
34
|
+
echo "$name: UNREADABLE (job has not reached run-end)"
|
|
35
|
+
mark_unreadable
|
|
36
|
+
continue
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
log="$out_dir/CI-$tag-$name.log"
|
|
40
|
+
gh run view --repo "$repo" --job "$id" --log > "$log" 2>/dev/null
|
|
41
|
+
if [ ! -s "$log" ]; then
|
|
42
|
+
echo "$name: UNREADABLE (empty log)"
|
|
43
|
+
mark_unreadable
|
|
44
|
+
continue
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
oracle=$(grep -oE 'COUNT_ORACLE [A-Z]+ expected=[0-9A-Z]+ actual=[0-9A-Z]+' "$log" | tail -1)
|
|
48
|
+
files=$(grep -oE 'Test Files .*' "$log" | sed 's/[[:space:]]*$//')
|
|
49
|
+
passed=$(printf '%s\n' "$files" | grep -oE '[0-9]+ passed' | awk '{s+=$1} END{print s+0}')
|
|
50
|
+
skipped=$(printf '%s\n' "$files" | grep -oE '[0-9]+ skipped' | awk '{s+=$1} END{print s+0}')
|
|
51
|
+
failed=$(printf '%s\n' "$files" | grep -oE '[0-9]+ failed' | awk '{s+=$1} END{print s+0}')
|
|
52
|
+
timedout=$(grep -cE 'Test timed out|Error: Hook timed out' "$log" || true)
|
|
53
|
+
errors=$(grep -oE '##\[error\].*' "$log" | sort | uniq -c | sed 's/^ *//' | tr '\n' ';')
|
|
54
|
+
|
|
55
|
+
echo "$name: oracle=[${oracle:-MISSING}] files=[$(printf '%s' "$files" | tr '\n' '|')] passed=$passed skipped=$skipped failed=$failed timedout=$timedout errors=[$errors]"
|
|
56
|
+
if [ -z "$oracle" ] || [ -z "$files" ]; then
|
|
57
|
+
echo "$name: UNREADABLE"
|
|
58
|
+
mark_unreadable
|
|
59
|
+
elif [ "$oracle" = "COUNT_ORACLE GREEN expected=$expected actual=$expected" ] \
|
|
60
|
+
&& [ "$failed" -eq 0 ] && [ "$timedout" -eq 0 ] \
|
|
61
|
+
&& [ $((passed + skipped)) -eq "$expected" ]; then
|
|
62
|
+
echo "$name: GREEN"
|
|
63
|
+
else
|
|
64
|
+
echo "$name: RED"
|
|
65
|
+
mark_red
|
|
66
|
+
fi
|
|
67
|
+
done <<< "$jobs"
|
|
68
|
+
|
|
69
|
+
if [ "$seen_test" -ne 1 ]; then
|
|
70
|
+
echo "test: UNREADABLE (job missing from run)"
|
|
71
|
+
mark_unreadable
|
|
72
|
+
fi
|
|
73
|
+
if [ "$seen_macos" -ne 1 ]; then
|
|
74
|
+
echo "test-macos: UNREADABLE (job missing from run)"
|
|
75
|
+
mark_unreadable
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
echo "VERDICT rc=$verdict (0=all GREEN 1=RED 2=UNREADABLE)"
|
|
79
|
+
exit "$verdict"
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
# TKR_AUTO_CLEAR=1 at act-pct WITH a fresh handoff, auto-clear orchestrator/overseer; other roles wake only.
|
|
37
37
|
# TKR_REBRIEF=<path> the file the re-briefed seat is told to read (defaults to the handoff).
|
|
38
38
|
# TKR_HANDOFF_MAX_AGE_S how fresh "fresh" is (default 900).
|
|
39
|
-
# TKR_CLEAR_SETTLE_S seconds
|
|
39
|
+
# TKR_CLEAR_SETTLE_S seconds allowed for the cleared banner percentage to drop (default 6).
|
|
40
40
|
# TKR_BLIND_ALARM_S seconds unreadable before CONTEXT_BLIND alarms (default 120).
|
|
41
41
|
# TKR_CONTEXT_WINDOW context window in tokens. Set it when the banner does not name one;
|
|
42
42
|
# NEVER guessed — a wrong denominator makes every warn and act line wrong.
|
|
@@ -234,6 +234,82 @@ context_pct() {
|
|
|
234
234
|
banner_pct
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
status_of() {
|
|
238
|
+
herdr agent get "$TARGET" 2>/dev/null \
|
|
239
|
+
| sed -n 's/.*"agent_status":"\([a-z_]*\)".*/\1/p' | head -1
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
# A clear is a SEND, so it inherits the verified-send precondition: the target must be between turns
|
|
243
|
+
# and its live prompt line must contain no typed draft. Claude Code's autosuggest is text in the plain
|
|
244
|
+
# rendering but is wrapped in SGR dim in the ANSI rendering; it is decoration, not a draft. Parse the
|
|
245
|
+
# Esc-prefixed SGR bytes instead of treating every visible character after the prompt glyph as state.
|
|
246
|
+
prompt_is_empty_or_dim() {
|
|
247
|
+
herdr agent read "$TARGET" --source visible --lines 14 --format ansi 2>/dev/null | python3 -c '
|
|
248
|
+
import re, sys
|
|
249
|
+
screen = sys.stdin.read().splitlines()
|
|
250
|
+
ansi = re.compile(r"\x1b\[([0-9;]*)m")
|
|
251
|
+
prompt = None
|
|
252
|
+
for line in screen:
|
|
253
|
+
plain = ansi.sub("", line).lstrip()
|
|
254
|
+
if plain.startswith(("❯", "›")):
|
|
255
|
+
prompt = line
|
|
256
|
+
if prompt is None:
|
|
257
|
+
sys.exit(1)
|
|
258
|
+
glyph = min((i for i in (prompt.find("❯"), prompt.find("›")) if i >= 0), default=-1)
|
|
259
|
+
if glyph < 0:
|
|
260
|
+
sys.exit(1)
|
|
261
|
+
payload = prompt[glyph + 1:]
|
|
262
|
+
dim = False
|
|
263
|
+
pos = 0
|
|
264
|
+
for match in ansi.finditer(payload):
|
|
265
|
+
if payload[pos:match.start()].strip() and not dim:
|
|
266
|
+
sys.exit(1)
|
|
267
|
+
codes = [int(c) if c else 0 for c in match.group(1).split(";")]
|
|
268
|
+
if 0 in codes:
|
|
269
|
+
dim = False
|
|
270
|
+
if 2 in codes:
|
|
271
|
+
dim = True
|
|
272
|
+
if 22 in codes:
|
|
273
|
+
dim = False
|
|
274
|
+
pos = match.end()
|
|
275
|
+
if payload[pos:].strip() and not dim:
|
|
276
|
+
sys.exit(1)
|
|
277
|
+
' 2>/dev/null
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
clear_target_ready() {
|
|
281
|
+
CLEAR_STATUS=$(status_of)
|
|
282
|
+
case "$CLEAR_STATUS" in
|
|
283
|
+
idle|done) ;;
|
|
284
|
+
*) CLEAR_REASON="status=${CLEAR_STATUS:-unreadable}"; return 1 ;;
|
|
285
|
+
esac
|
|
286
|
+
if ! prompt_is_empty_or_dim; then
|
|
287
|
+
CLEAR_REASON="status=$CLEAR_STATUS prompt=typed-or-unreadable"
|
|
288
|
+
return 1
|
|
289
|
+
fi
|
|
290
|
+
return 0
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
# `/clear` has landed only when a fresh banner read says its context percentage is lower. The JSONL
|
|
294
|
+
# source deliberately does not participate in this receipt: it names the pre-clear session and can
|
|
295
|
+
# remain at the old fill while the new prompt is already visible. No drop means no re-brief and no
|
|
296
|
+
# CONTEXT_CLEARED claim.
|
|
297
|
+
wait_for_clear_receipt() {
|
|
298
|
+
local before="$1" waited=0 after
|
|
299
|
+
case "$SETTLE" in *[!0-9]*|'') return 1 ;; esac
|
|
300
|
+
while :; do
|
|
301
|
+
after=$(banner_pct 2>/dev/null) || after=""
|
|
302
|
+
if printf '%s\n' "$after" | grep -qE '^[0-9]+$' \
|
|
303
|
+
&& [ "$after" -lt "$before" ] 2>/dev/null; then
|
|
304
|
+
printf '%s\n' "$after"
|
|
305
|
+
return 0
|
|
306
|
+
fi
|
|
307
|
+
[ "$waited" -lt "$SETTLE" ] || return 1
|
|
308
|
+
sleep 1
|
|
309
|
+
waited=$((waited + 1))
|
|
310
|
+
done
|
|
311
|
+
}
|
|
312
|
+
|
|
237
313
|
handoff_fresh() {
|
|
238
314
|
[ -n "$HANDOFF" ] || return 1
|
|
239
315
|
[ -f "$HANDOFF" ] || return 1
|
|
@@ -245,13 +321,23 @@ handoff_fresh() {
|
|
|
245
321
|
}
|
|
246
322
|
|
|
247
323
|
act_on() {
|
|
248
|
-
local P="$1"
|
|
324
|
+
local P="$1" BEFORE AFTER
|
|
249
325
|
if handoff_fresh; then
|
|
250
326
|
if [ "${TKR_AUTO_CLEAR:-0}" = "1" ] && { [ "$ROLE" = "orchestrator" ] || [ "$ROLE" = "overseer" ]; }; then
|
|
327
|
+
if ! clear_target_ready; then
|
|
328
|
+
echo "CONTEXT_ACT_DEFERRED $TARGET at ${P}% — ${CLEAR_REASON}; waiting for idle and an empty/dim-only prompt line"
|
|
329
|
+
return 0
|
|
330
|
+
fi
|
|
331
|
+
BEFORE=$(banner_pct 2>/dev/null) || BEFORE=""
|
|
332
|
+
case "$BEFORE" in ''|*[!0-9]*) echo "CONTEXT_CLEAR_UNVERIFIED $TARGET — no numeric banner baseline; not clearing"; return 0 ;; esac
|
|
251
333
|
herdr agent prompt "$TARGET" "/clear" >/dev/null 2>&1
|
|
252
|
-
|
|
334
|
+
if ! AFTER=$(wait_for_clear_receipt "$BEFORE"); then
|
|
335
|
+
echo "CONTEXT_CLEAR_UNVERIFIED $TARGET at ${P}% — banner did not re-read below ${BEFORE}% within ${SETTLE}s"
|
|
336
|
+
echo " no re-brief sent and CONTEXT_CLEARED withheld; inspect the seat before acting again"
|
|
337
|
+
exit 0
|
|
338
|
+
fi
|
|
253
339
|
herdr agent prompt "$TARGET" "Read ${REBRIEF} and continue exactly where it says. Your context was cleared at ${P}% against that handoff; it is current as of $(date '+%H:%M'). The same-process clear kept every background task alive: kill only this seat's recorded watcher pids first, verify the process table twice, then re-arm. Do not reconstruct from memory — everything you need is on disk." >/dev/null 2>&1
|
|
254
|
-
echo "CONTEXT_CLEARED $TARGET
|
|
340
|
+
echo "CONTEXT_CLEARED $TARGET ${P}% -> ${AFTER}% — banner re-read lower, handoff fresh, re-briefed from ${REBRIEF}"
|
|
255
341
|
exit 0
|
|
256
342
|
fi
|
|
257
343
|
echo "CONTEXT_ACT $TARGET ${P}% (>= ${ACT}) — handoff is FRESH, a clear is SAFE now"
|