instar 1.3.143 → 1.3.145

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.
@@ -38,6 +38,18 @@ HOOK_INPUT=$(cat)
38
38
  IS_CODEX=0
39
39
  for _arg in "$@"; do [[ "$_arg" == "--codex" ]] && IS_CODEX=1; done
40
40
 
41
+ # hook-capability: codex-stdout-json-safe — see emit() below (migration marker; bumped so
42
+ # existing #28 installs re-deploy this fixed hook even though they already have CODEX_LOOP_ENABLED).
43
+ # emit — human-facing approve/status text. In codex mode the Stop hook's STDOUT must be
44
+ # ONLY valid decision-JSON (the `{"decision":"block",...}` case far below) or empty:
45
+ # codex rejects ANY other stdout as "invalid stop hook JSON output" and reports the stop
46
+ # hook as FAILED (observed live 2026-05-31 — a completion-promise approve echoed plain
47
+ # text to stdout, so codex logged "Stop hook (failed)" on every terminal stop with the
48
+ # loop flag on). So in codex mode these messages go to STDERR; Claude keeps them on
49
+ # STDOUT (unchanged — Claude surfaces approve-path stdout to the user). The block-decision
50
+ # JSON is printed directly (never via emit), so it always reaches stdout.
51
+ emit() { if [[ "$IS_CODEX" == "1" ]]; then printf '%s\n' "$*" >&2; else printf '%s\n' "$*"; fi; }
52
+
41
53
  # ── Anchor to the agent home, NOT the session's CWD ───────────────────
42
54
  # All state paths below are relative (.instar/autonomous/<topic>.local.md, the
43
55
  # registry, the legacy file). The Stop hook inherits the session's working
@@ -359,8 +371,8 @@ if [[ "$DURATION_SECONDS" =~ ^[0-9]+$ ]] && [[ $DURATION_SECONDS -gt 0 ]]; then
359
371
  NOW_EPOCH=$(date +%s)
360
372
  ELAPSED=$(( NOW_EPOCH - START_EPOCH ))
361
373
  if [[ $ELAPSED -ge $DURATION_SECONDS ]]; then
362
- echo "⏰ Autonomous mode: Duration expired ($ELAPSED seconds elapsed)."
363
- echo " Session is free to exit."
374
+ emit "⏰ Autonomous mode: Duration expired ($ELAPSED seconds elapsed)."
375
+ emit " Session is free to exit."
364
376
  notify_terminal_stop "⏰ My autonomous run on \"$(goal_snippet)\" just hit its time limit and stopped. Ask me and I'll pick up where I left off."
365
377
  rm -f "$STATE_FILE"
366
378
  exit 0
@@ -374,7 +386,7 @@ fi
374
386
 
375
387
  # Emergency stop (global — halts every autonomous job on its next fire)
376
388
  if [[ -f ".instar/autonomous-emergency-stop" ]]; then
377
- echo "🛑 Autonomous mode: Emergency stop detected."
389
+ emit "🛑 Autonomous mode: Emergency stop detected."
378
390
  notify_terminal_stop "🛑 My autonomous run on \"$(goal_snippet)\" was stopped (emergency stop)."
379
391
  rm -f "$STATE_FILE"
380
392
  # NOTE: the emergency flag is left in place so OTHER topics' hooks also see it
@@ -405,7 +417,7 @@ if [[ -n "$COMPLETION_CONDITION" ]] && [[ -n "$TRANSCRIPT_PATH" ]] && [[ -f "$TR
405
417
  EVAL_REASON=$(printf '%s' "$EVAL_RESP" | jq -r '.reason // empty' 2>/dev/null || echo "")
406
418
  fi
407
419
  if [[ "$EVAL_MET" == "true" ]]; then
408
- echo "✅ Autonomous mode: completion condition met (independent evaluator): ${EVAL_REASON}"
420
+ emit "✅ Autonomous mode: completion condition met (independent evaluator): ${EVAL_REASON}"
409
421
  notify_terminal_stop "✅ My autonomous run on \"$(goal_snippet)\" finished — the goal was met."
410
422
  rm -f "$STATE_FILE"
411
423
  exit 0
@@ -423,8 +435,8 @@ if [[ -n "$TRANSCRIPT_PATH" ]] && [[ -f "$TRANSCRIPT_PATH" ]]; then
423
435
  if [[ -n "$COMPLETION_PROMISE" ]] && [[ "$COMPLETION_PROMISE" != "null" ]]; then
424
436
  PROMISE_TEXT=$(printf '%s' "$LAST_OUTPUT" | perl -0777 -pe 's/.*?<promise>(.*?)<\/promise>.*/$1/s; s/^\s+|\s+$//g; s/\s+/ /g' 2>/dev/null || echo "")
425
437
  if [[ -n "$PROMISE_TEXT" ]] && [[ "$PROMISE_TEXT" = "$COMPLETION_PROMISE" ]]; then
426
- echo "✅ Autonomous mode: Completion promise detected — <promise>$COMPLETION_PROMISE</promise>"
427
- echo " Session is free to exit. Good work!"
438
+ emit "✅ Autonomous mode: Completion promise detected — <promise>$COMPLETION_PROMISE</promise>"
439
+ emit " Session is free to exit. Good work!"
428
440
  notify_terminal_stop "✅ My autonomous run on \"$(goal_snippet)\" finished — all the work is done."
429
441
  rm -f "$STATE_FILE"
430
442
  exit 0
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAoSH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAwvDD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAqvPtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAoSH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAwvDD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAyvPtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
@@ -8285,7 +8285,7 @@ export async function startServer(options) {
8285
8285
  // inbound-message chokepoint (/internal/telegram-forward).
8286
8286
  const { AgentActivityState } = await import('../monitoring/AgentActivityState.js');
8287
8287
  const agentActivityState = new AgentActivityState();
8288
- const { SleepController, sleepAuditSink } = await import('../monitoring/SleepController.js');
8288
+ const { SleepController, sleepAuditSink, sleepRequestWriter } = await import('../monitoring/SleepController.js');
8289
8289
  const _sleepCfg = config.monitoring?.agentSleep;
8290
8290
  const sleepController = new SleepController({
8291
8291
  sample: () => {
@@ -8298,14 +8298,18 @@ export async function startServer(options) {
8298
8298
  // Lease guard: only relevant when multi-machine coordination is active.
8299
8299
  leaseActive: coordinator.enabled,
8300
8300
  holdsLease: coordinator.enabled ? coordinator.holdsLease() : false,
8301
- // In-flight: an inbound message currently being handled. (The relay/forward
8302
- // in-flight + scheduler-wake signals are wired with the stop mechanism in
8303
- // the next slice — this slice is dry-run, so it never acts on them.)
8301
+ // In-flight: an inbound message currently being handled. (A fuller
8302
+ // relay/forward-queue in-flight signal + the scheduler next-fire wake are
8303
+ // tracked refinements; nextScheduledJobAt stays null until scheduler-wake
8304
+ // lands, so the scheduled-job guard is conservative-off for now.)
8304
8305
  inflightWork: (currentInboundByTopic?.size ?? 0) > 0,
8305
8306
  nextScheduledJobAt: null,
8306
8307
  };
8307
8308
  },
8308
8309
  audit: sleepAuditSink(config.stateDir),
8310
+ // Live-mode only (enabled && !dryRun): writes state/sleep-requested.json
8311
+ // for the ServerSupervisor to honor. Dark/dry-run never invokes this.
8312
+ requestSleep: sleepRequestWriter(config.stateDir),
8309
8313
  }, {
8310
8314
  enabled: _sleepCfg?.enabled ?? false,
8311
8315
  dryRun: _sleepCfg?.dryRun ?? true,