@namzu/cli 33.0.0 → 33.1.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.
Files changed (78) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/commands/archive.d.ts.map +1 -1
  3. package/dist/commands/archive.js +4 -1
  4. package/dist/commands/archive.js.map +1 -1
  5. package/dist/commands/drain.js +3 -3
  6. package/dist/commands/drain.js.map +1 -1
  7. package/dist/commands/exec.js +1 -1
  8. package/dist/commands/exec.js.map +1 -1
  9. package/dist/commands/schedule.d.ts.map +1 -1
  10. package/dist/commands/schedule.js +5 -2
  11. package/dist/commands/schedule.js.map +1 -1
  12. package/dist/commands/worktree.d.ts.map +1 -1
  13. package/dist/commands/worktree.js +2 -1
  14. package/dist/commands/worktree.js.map +1 -1
  15. package/dist/integrations/sessions/display-title.d.ts +3 -0
  16. package/dist/integrations/sessions/display-title.d.ts.map +1 -0
  17. package/dist/integrations/sessions/display-title.js +5 -0
  18. package/dist/integrations/sessions/display-title.js.map +1 -0
  19. package/dist/schedule/build.d.ts +2 -0
  20. package/dist/schedule/build.d.ts.map +1 -1
  21. package/dist/schedule/build.js +11 -2
  22. package/dist/schedule/build.js.map +1 -1
  23. package/dist/schedule/commands/add.d.ts +1 -1
  24. package/dist/schedule/commands/add.d.ts.map +1 -1
  25. package/dist/schedule/commands/add.js +12 -2
  26. package/dist/schedule/commands/add.js.map +1 -1
  27. package/dist/schedule/commands/list.d.ts.map +1 -1
  28. package/dist/schedule/commands/list.js +10 -1
  29. package/dist/schedule/commands/list.js.map +1 -1
  30. package/dist/schedule/daemon/daemon.js +1 -1
  31. package/dist/schedule/daemon/daemon.js.map +1 -1
  32. package/dist/schedule/fire/fire.d.ts.map +1 -1
  33. package/dist/schedule/fire/fire.js +1 -1
  34. package/dist/schedule/fire/fire.js.map +1 -1
  35. package/dist/schedule/script-check.d.ts.map +1 -1
  36. package/dist/schedule/script-check.js +2 -1
  37. package/dist/schedule/script-check.js.map +1 -1
  38. package/dist/tui/App.d.ts.map +1 -1
  39. package/dist/tui/App.js +112 -53
  40. package/dist/tui/App.js.map +1 -1
  41. package/dist/tui/BrandHeader.js +1 -1
  42. package/dist/tui/BrandHeader.js.map +1 -1
  43. package/dist/tui/Composer.d.ts.map +1 -1
  44. package/dist/tui/Composer.js +6 -11
  45. package/dist/tui/Composer.js.map +1 -1
  46. package/dist/tui/ResumePicker.d.ts.map +1 -1
  47. package/dist/tui/ResumePicker.js +2 -1
  48. package/dist/tui/ResumePicker.js.map +1 -1
  49. package/dist/tui/SaveSkillOverlay.js +1 -1
  50. package/dist/tui/SaveSkillOverlay.js.map +1 -1
  51. package/dist/tui/ScheduleReviewOverlay.d.ts +27 -0
  52. package/dist/tui/ScheduleReviewOverlay.d.ts.map +1 -0
  53. package/dist/tui/ScheduleReviewOverlay.js +166 -0
  54. package/dist/tui/ScheduleReviewOverlay.js.map +1 -0
  55. package/dist/tui/Transcript.js +2 -2
  56. package/dist/tui/Transcript.js.map +1 -1
  57. package/dist/tui/agent.d.ts +1 -1
  58. package/dist/tui/agent.d.ts.map +1 -1
  59. package/dist/tui/agent.js +1 -1
  60. package/dist/tui/agent.js.map +1 -1
  61. package/dist/tui/schedule/host-commands.d.ts +3 -0
  62. package/dist/tui/schedule/host-commands.d.ts.map +1 -1
  63. package/dist/tui/schedule/host-commands.js +72 -15
  64. package/dist/tui/schedule/host-commands.js.map +1 -1
  65. package/dist/tui/schedule/integration.d.ts +2 -0
  66. package/dist/tui/schedule/integration.d.ts.map +1 -1
  67. package/dist/tui/schedule/integration.js +3 -0
  68. package/dist/tui/schedule/integration.js.map +1 -1
  69. package/dist/tui/schedule/resume.js +2 -2
  70. package/dist/tui/schedule/resume.js.map +1 -1
  71. package/dist/tui/schedule/tool-host.d.ts +3 -0
  72. package/dist/tui/schedule/tool-host.d.ts.map +1 -1
  73. package/dist/tui/schedule/tool-host.js +34 -9
  74. package/dist/tui/schedule/tool-host.js.map +1 -1
  75. package/dist/tui/slashCommands.js +1 -1
  76. package/dist/tui/slashCommands.js.map +1 -1
  77. package/package.json +4 -4
  78. package/skills/schedule-task/SKILL.md +41 -15
@@ -133,9 +133,10 @@ export function verifyScheduledScript(body, shell, policy) {
133
133
  commandDialect: shell,
134
134
  });
135
135
  if (result.decision === 'deny') {
136
+ const blanketBashDeny = result.reason.includes('denied by name (bash)');
136
137
  return {
137
138
  ok: false,
138
- reason: `the command ${shown(command.text)} is denied: ${result.reason}`,
139
+ reason: `the command ${shown(command.text)} is denied: ${result.reason}${blanketBashDeny ? '; a bash deny rule blocks every script command, so changing the script text cannot fix it' : ''}`,
139
140
  };
140
141
  }
141
142
  }
@@ -1 +1 @@
1
- {"version":3,"file":"script-check.js","sourceRoot":"","sources":["../../src/schedule/script-check.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"script-check.js","sourceRoot":"","sources":["../../src/schedule/script-check.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/tui/App.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAON,KAAK,OAAO,EAmBZ,MAAM,YAAY,CAAA;AA8NnB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AA+DvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAa/D,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAA;IACxB,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;IAC1D,0EAA0E;IAC1E,QAAQ,CAAC,cAAc,CAAC,EAAE,qBAAqB,CAAA;IAC/C;;;;OAIG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE;QAAE,OAAO,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;KAAE,CAAA;CAC3D;AASD,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,EAAE;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAC5B,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;AAuSrB,6EAA6E;AAC7E,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,SAAS,MAAM,EAAE,CAM7F;AAED,sEAAsE;AACtE,wBAAgB,mBAAmB,CAClC,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,MAAM,EAAE,MAAM,MAAM,EACpB,iBAAiB,GAAE,SAAS,MAAM,EAAO,GACvC,SAAS,iBAAiB,EAAE,CAqE9B;AA2HD,wBAAgB,GAAG,CAAC,EACnB,GAAG,EAAE,UAAU,EACf,aAAa,EACb,cAAsC,EACtC,eAAe,GACf,EAAE,QAAQ,2CAosRV"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/tui/App.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAON,KAAK,OAAO,EAmBZ,MAAM,YAAY,CAAA;AAoOnB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AA+DvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAa/D,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAA;IACxB,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;IAC1D,0EAA0E;IAC1E,QAAQ,CAAC,cAAc,CAAC,EAAE,qBAAqB,CAAA;IAC/C;;;;OAIG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE;QAAE,OAAO,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;KAAE,CAAA;CAC3D;AASD,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,EAAE;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAC5B,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;AAuSrB,6EAA6E;AAC7E,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,SAAS,MAAM,EAAE,CAM7F;AAED,sEAAsE;AACtE,wBAAgB,mBAAmB,CAClC,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,MAAM,EAAE,MAAM,MAAM,EACpB,iBAAiB,GAAE,SAAS,MAAM,EAAO,GACvC,SAAS,iBAAiB,EAAE,CAqE9B;AA2HD,wBAAgB,GAAG,CAAC,EACnB,GAAG,EAAE,UAAU,EACf,aAAa,EACb,cAAsC,EACtC,eAAe,GACf,EAAE,QAAQ,2CAgxRV"}
package/dist/tui/App.js CHANGED
@@ -19,7 +19,7 @@ import { ToolOutputViewer } from './ToolOutputViewer.js';
19
19
  import { join, relative } from 'node:path';
20
20
  import { DEFAULT_MAX_GOAL_ROUNDS, DiskMessageFeedbackStore, GoalRoundLimitError, HostCommandRegistry, SessionGoalActivation, StaleGoalError, TurnCancelled, asSessionId, createAssistantMessage, createUserMessage, generateSessionId, generateTurnId, isCompactionMessage, kernelHostCommands, SKILL_TOOL_NAME, } from '@namzu/sdk';
21
21
  import { Box, Text, useApp, useInput, useStdout, useWindowSize } from 'ink';
22
- import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
22
+ import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
23
23
  import { pinTrustedProjectPath, resolveTrustedProjectContext, } from '../config/trusted-project-context.js';
24
24
  import { visibleProjectInstructionPath } from '../context/project-path.js';
25
25
  import { runtimeContextLabel } from '../context/runtime-message.js';
@@ -28,6 +28,7 @@ import { terminalNotificationEnabled, writeTerminalNotification, } from '../inte
28
28
  import { beginCodexDeviceLogin, beginSubscriptionLogin, clearAllStoredCredentials, clearStoredCodexCredential, clearStoredGeminiApiKey as clearStoredGoogleApiKey, clearStoredSubscriptionCredential, credentialsPath, googleApiKeyPath, parsePastedInput, primaryProvider, readStoredCodexCredential, readStoredGeminiApiKey as readStoredGoogleApiKey, readStoredSubscriptionCredential, signedInSubscriptionProviders, writePreferences, writeStoredGeminiApiKey as writeStoredGoogleApiKey, } from '../integrations/providers/index.js';
29
29
  import { ConversationIndexRefreshError, activeConversationTurn, archiveConversation, forkConversation, forkConversationBeforeUser, listArchived, listRecent, loadConversation, loadResumableConversation, openSessions, requireWritableConversation, setTitle, startConversation, titleOf, unarchiveConversation, } from '../integrations/sessions/store.js';
30
30
  import { conversationMarkdown, writeConversationExport, } from '../integrations/sessions/transcript-export.js';
31
+ import { displayConversationTitle } from '../integrations/sessions/display-title.js';
31
32
  import { openManagedWorktrees, worktreeOpenHint } from '../integrations/worktrees/managed.js';
32
33
  import { NARRATION_TOOL_NAME } from '../integrations/subagents/runtime.js';
33
34
  import { agentsSlashCommand } from '../integrations/subagents/slash.js';
@@ -62,6 +63,7 @@ import { Picker } from './Picker.js';
62
63
  import { ResumePicker } from './ResumePicker.js';
63
64
  import { resolveNamzuHome } from '../integrations/state/home.js';
64
65
  import { createScheduleIntegration } from './schedule/integration.js';
66
+ import { ScheduleReviewOverlay, } from './ScheduleReviewOverlay.js';
65
67
  import { SaveSkillOverlay } from './SaveSkillOverlay.js';
66
68
  import { SKILL_CREATOR_SKILL, buildSaveSkillTool, learnSkillPrompt, newSkillPrompt, } from '../skills/save.js';
67
69
  import { SUGGESTIONS_STOPPED_NOTICE, createTurnActivity, judgeSkillSuggestion, observeTurnEvent, skillSuggestionNotice, } from './skills/learning.js';
@@ -490,7 +492,7 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
490
492
  ...(job.signal ? { signal: job.signal } : {}),
491
493
  });
492
494
  idleJobNoticesRef.current.push(text);
493
- pushMessage('system', text, false, '⚙');
495
+ pushMessage('system', text, false, 'J');
494
496
  });
495
497
  }, [session]);
496
498
  const [usage, setUsage] = useState(null);
@@ -624,7 +626,9 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
624
626
  choicePickerCommittedRef.current = null;
625
627
  setChoicePickerState(next);
626
628
  }, []);
627
- useEffect(() => {
629
+ // A painted menu must already accept its first key. A passive effect can
630
+ // run after Ink flushes that frame, leaving the ownership fence closed.
631
+ useLayoutEffect(() => {
628
632
  choicePickerCommittedRef.current = choicePicker;
629
633
  }, [choicePicker]);
630
634
  /** Host-owned text decision; its value never enters model prompt history. */
@@ -990,6 +994,7 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
990
994
  isIdle: () => stateRef.current === 'idle' && abortRef.current === null,
991
995
  say: (text) => scheduleLiveRef.current?.say(text),
992
996
  ask: (question, signal) => scheduleLiveRef.current?.ask(question, signal) ?? Promise.resolve({ kind: 'skip' }),
997
+ review: (request, signal) => scheduleLiveRef.current?.review(request, signal) ?? Promise.resolve('cancel'),
993
998
  askPermission: (request) => scheduleLiveRef.current?.askPermission(request) ??
994
999
  Promise.resolve({ kind: 'reject', feedback: 'Nobody can answer yet.' }),
995
1000
  submit: (text, createdBy) => scheduleLiveRef.current?.submit(text, createdBy),
@@ -1006,6 +1011,13 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
1006
1011
  saveSkillPromptRef.current = next;
1007
1012
  setSaveSkillPromptState(next);
1008
1013
  }, []);
1014
+ const [scheduleReviewPrompt, setScheduleReviewPromptState] = useState(null);
1015
+ const scheduleReviewTokenRef = useRef(0);
1016
+ const scheduleReviewPromptRef = useRef(null);
1017
+ const setScheduleReviewPrompt = useCallback((next) => {
1018
+ scheduleReviewPromptRef.current = next;
1019
+ setScheduleReviewPromptState(next);
1020
+ }, []);
1009
1021
  const saveSkillNotifyRef = useRef(null);
1010
1022
  const saveSkillToolRef = useRef(null);
1011
1023
  if (saveSkillToolRef.current === null) {
@@ -1039,7 +1051,7 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
1039
1051
  setSaveSkillPrompt(entry);
1040
1052
  saveSkillNotifyRef.current?.();
1041
1053
  }),
1042
- saved: ({ name, path }) => scheduleLiveRef.current?.say(`✎ Saved skill ${name} to ${path}. The model is offered it from the next turn; /skills ${name} activates it now.`),
1054
+ saved: ({ name, path }) => scheduleLiveRef.current?.say(`Saved skill ${name} to ${path}. The model is offered it from the next turn; /skills ${name} activates it now.`),
1043
1055
  });
1044
1056
  }
1045
1057
  /**
@@ -3090,9 +3102,11 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
3090
3102
  // settling in the background prints through the child screen. Returning
3091
3103
  // advances the floor once and emits those finalized rows exactly once.
3092
3104
  const nextSettled = settledBeforeStreaming(messages, window.settled, settledRef.current);
3093
- if (agentSurface === null && outputViewer === null)
3105
+ if (agentSurface === null && outputViewer === null && scheduleReviewPrompt === null)
3094
3106
  settledRef.current = nextSettled;
3095
- const renderedSettled = agentSurface === null && outputViewer === null ? nextSettled : settledRef.current;
3107
+ const renderedSettled = agentSurface === null && outputViewer === null && scheduleReviewPrompt === null
3108
+ ? nextSettled
3109
+ : settledRef.current;
3096
3110
  // One merged vocabulary for the session: this host's own commands plus
3097
3111
  // whatever the kernel's registry reports. Built here so `/help`, the
3098
3112
  // autocomplete and the dispatcher all answer from the same list — three
@@ -3269,7 +3283,7 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
3269
3283
  }
3270
3284
  // Said once the turn really continues: a scheduled park can still
3271
3285
  // be left waiting or abandoned above.
3272
- pushMessage('system', PAUSED_TURN_LINES.resuming, false, '▶');
3286
+ pushMessage('system', PAUSED_TURN_LINES.resuming);
3273
3287
  for await (const event of session.resumePaused({
3274
3288
  turnId: active.turnId,
3275
3289
  signal: ac.signal,
@@ -3621,7 +3635,7 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
3621
3635
  // would have nothing to find.
3622
3636
  void hydrateSavedChildren();
3623
3637
  conversationMaterializedRef.current = true;
3624
- pushMessage('system', `Resumed: ${conv.title}`);
3638
+ pushMessage('system', `Resumed: ${displayConversationTitle(conv.title)}`);
3625
3639
  if (discardedQueued > 0) {
3626
3640
  pushMessage('system', `Discarded ${discardedQueued} queued prompt${discardedQueued === 1 ? '' : 's'} from the conversation you left.`);
3627
3641
  }
@@ -3674,7 +3688,7 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
3674
3688
  : `Could not restore: ${err instanceof Error ? err.message : String(err)}`);
3675
3689
  return;
3676
3690
  }
3677
- pushMessage('system', `Restored: ${conv.title}`);
3691
+ pushMessage('system', `Restored: ${displayConversationTitle(conv.title)}`);
3678
3692
  try {
3679
3693
  await resumeConversation(conv);
3680
3694
  }
@@ -3916,7 +3930,7 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
3916
3930
  session?.resetTaskStore?.();
3917
3931
  goalActivation.clear();
3918
3932
  wakeGoalDriver();
3919
- pushMessage('system', `Forked into "${forked.title}" — ${forked.copied} message(s) copied. This screen continues in the copy; ${original} is unchanged and still in /resume.`);
3933
+ pushMessage('system', `Forked into "${displayConversationTitle(forked.title)}" — ${forked.copied} message(s) copied. This screen continues in the copy; ${original} is unchanged and still in /resume.`);
3920
3934
  }
3921
3935
  catch (err) {
3922
3936
  pushMessage('system', `Could not fork: ${err instanceof Error ? err.message : String(err)}`);
@@ -4043,7 +4057,7 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
4043
4057
  });
4044
4058
  setEditList([]);
4045
4059
  setPhase('ready');
4046
- pushMessage('system', `Forked into "${forked.title}" before the selected prompt. Edit it below; ${source} is unchanged and remains in /resume.`);
4060
+ pushMessage('system', `Forked into "${displayConversationTitle(forked.title)}" before the selected prompt. Edit it below; ${source} is unchanged and remains in /resume.`);
4047
4061
  }
4048
4062
  catch (err) {
4049
4063
  setPhase('ready');
@@ -4155,6 +4169,39 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
4155
4169
  setChoicePicker(picker);
4156
4170
  sendTerminalNotification({ kind: 'approval-required' });
4157
4171
  }), [closeLiveReply, sendTerminalNotification, setChoicePicker, setSelectedChoice, resolveQuestion]);
4172
+ const reviewSchedule = useCallback((request, signal) => new Promise((resolve) => {
4173
+ if (signal?.aborted) {
4174
+ resolve('cancel');
4175
+ return;
4176
+ }
4177
+ closeLiveReply();
4178
+ // A second tool call must not replace an open review and leave its
4179
+ // Promise waiting forever. Each decision still belongs to its own
4180
+ // captured proposal.
4181
+ scheduleReviewPromptRef.current?.resolve('cancel');
4182
+ let settled = false;
4183
+ const entry = {
4184
+ token: ++scheduleReviewTokenRef.current,
4185
+ request,
4186
+ resolve: (answer) => {
4187
+ if (settled)
4188
+ return;
4189
+ settled = true;
4190
+ signal?.removeEventListener('abort', onAbort);
4191
+ // Let the overlay's key dispatch finish before App regains its
4192
+ // keyboard handler, so Esc cannot interrupt this same turn.
4193
+ queueMicrotask(() => {
4194
+ if (scheduleReviewPromptRef.current === entry)
4195
+ setScheduleReviewPrompt(null);
4196
+ });
4197
+ resolve(answer);
4198
+ },
4199
+ };
4200
+ const onAbort = () => entry.resolve('cancel');
4201
+ signal?.addEventListener('abort', onAbort, { once: true });
4202
+ setScheduleReviewPrompt(entry);
4203
+ sendTerminalNotification({ kind: 'approval-required' });
4204
+ }), [closeLiveReply, sendTerminalNotification, setScheduleReviewPrompt]);
4158
4205
  /**
4159
4206
  * Grow this turn's open task block, or open one. The whole plan rides along
4160
4207
  * so the block shows the checklist as it stood after the operation; a
@@ -4546,7 +4593,7 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
4546
4593
  case 'job':
4547
4594
  // The kernel saw it end during a turn; the model reads the notice
4548
4595
  // on its next tool result, the operator reads this row.
4549
- pushMessage('system', describeJobExit(event), false, '⚙');
4596
+ pushMessage('system', describeJobExit(event), false, 'J');
4550
4597
  break;
4551
4598
  case 'context':
4552
4599
  // Into the TRANSCRIPT, not a status line. A status indicator is
@@ -6153,7 +6200,7 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
6153
6200
  throw new Error('Conversation history is unavailable in this folder.');
6154
6201
  await persistenceTailRef.current;
6155
6202
  const forked = await manager.fork(scope.sessionId, label);
6156
- notice(`Forked ${forked.copied} messages into ${forked.title}. Open the new checkout in a new terminal: ${worktreeOpenHint(forked.path, forked.conversationId)}${forked.sourceDirty ? '\nUncommitted files stayed in this checkout.' : ''}`);
6203
+ notice(`Forked ${forked.copied} messages into ${displayConversationTitle(forked.title)}. Open the new checkout in a new terminal: ${worktreeOpenHint(forked.path, forked.conversationId)}${forked.sourceDirty ? '\nUncommitted files stayed in this checkout.' : ''}`);
6157
6204
  }
6158
6205
  else if (label) {
6159
6206
  const target = await manager.resume(label);
@@ -6705,6 +6752,7 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
6705
6752
  pushMessage('system', text);
6706
6753
  },
6707
6754
  ask: askQuestion,
6755
+ review: reviewSchedule,
6708
6756
  askPermission: onPermission,
6709
6757
  submit: (text, createdBy) => handleSubmit(text, undefined, 'submit', {
6710
6758
  source: createdBy === 'operator' ? 'operator-loop' : 'model-loop',
@@ -6943,7 +6991,7 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
6943
6991
  if (ups.length === 0)
6944
6992
  return;
6945
6993
  const lines = ups.map((u) => ` • ${u.name} ${u.current} → ${u.latest} (${u.how})`);
6946
- pushMessage('system', `⬆ Update available:\n${lines.join('\n')}`);
6994
+ pushMessage('system', `Update available:\n${lines.join('\n')}`);
6947
6995
  });
6948
6996
  }, [phase, ctx.version, pushMessage]);
6949
6997
  const hydrateFromPicker = useCallback(async (prefs, detectedNow, signal, options = {}) => {
@@ -7064,7 +7112,7 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
7064
7112
  // The save-skill screen owns its keys, Esc and Ctrl+C included: neither
7065
7113
  // may interrupt the turn that is waiting on its answer. A permission
7066
7114
  // request (an agent's, say) takes the screen over it and gets the keys.
7067
- if (saveSkillPromptRef.current && permission === null)
7115
+ if ((saveSkillPromptRef.current || scheduleReviewPromptRef.current) && permission === null)
7068
7116
  return;
7069
7117
  // Startup has refused admission, so there is no draft or active turn to
7070
7118
  // protect with the ready screen's two-press exit ladder.
@@ -7655,6 +7703,7 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
7655
7703
  ? subagents.find((agent) => agent.viewId === agentSurface.selectedId)
7656
7704
  : undefined;
7657
7705
  const lifecycleOwnsViewport = outputViewer !== null ||
7706
+ scheduleReviewPrompt !== null ||
7658
7707
  phase === 'trust' ||
7659
7708
  phase === 'resume' ||
7660
7709
  phase === 'unarchive' ||
@@ -7669,6 +7718,7 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
7669
7718
  textPrompt === null &&
7670
7719
  choicePicker === null &&
7671
7720
  copyPicker === null &&
7721
+ scheduleReviewPrompt === null &&
7672
7722
  agentSurface === null
7673
7723
  ? goalStatusLabel(goalStatus, goalStatus ? goalActivation.isArmed(goalStatus.sessionId, goalStatus) : false)
7674
7724
  : null;
@@ -7687,33 +7737,35 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
7687
7737
  ? 'starting a fresh conversation — input is paused'
7688
7738
  : compacting
7689
7739
  ? 'compacting conversation — input is paused'
7690
- : saveSkillPrompt
7691
- ? 'save skill — ←/→ choose · enter apply · esc cancel'
7692
- : permission
7693
- ? hintForPhase(phase, state, session?.hasProvider === true)
7694
- : agentSurface?.kind === 'cockpit'
7695
- ? agentSurface.focus === 'workflows'
7696
- ? 'workflows — enter select · esc return'
7697
- : agentSurface.focus === 'phases'
7698
- ? 'agent phases — enter agents · esc return'
7699
- : 'agents — enter inspect · left phases · esc return'
7700
- : agentSurface?.kind === 'transcript'
7701
- ? 'observing agent — esc agents · q parent'
7702
- : textPrompt
7703
- ? 'editor open · enter apply · esc cancel'
7704
- : choicePicker
7705
- ? choicePickerSearchable(choicePicker)
7706
- ? 'type to filter · ↑↓ select · enter apply · esc back'
7707
- : effortSlider
7708
- ? '←/→ adjust · 1–9 select · enter apply · esc back'
7709
- : '↑↓ / 1–9 select · enter apply · esc back'
7710
- : copyPicker
7711
- ? 'copy target open — ↑↓ / 1–9 select · esc cancel'
7712
- : handoffPark && phase === 'ready' && state === 'idle' && !composerHasDraft
7713
- ? 'enter continue · esc stop'
7714
- : goalStatus && phase === 'ready' && state === 'idle'
7715
- ? undefined
7716
- : hintForPhase(phase, state, session?.hasProvider === true, composerHasDraft);
7740
+ : permission
7741
+ ? hintForPhase(phase, state, session?.hasProvider === true)
7742
+ : scheduleReviewPrompt
7743
+ ? 'review schedule — ↑/↓ scroll · ←/→ choose · enter apply · esc cancel'
7744
+ : saveSkillPrompt
7745
+ ? 'save skill — ←/→ choose · enter apply · esc cancel'
7746
+ : agentSurface?.kind === 'cockpit'
7747
+ ? agentSurface.focus === 'workflows'
7748
+ ? 'workflows — enter select · esc return'
7749
+ : agentSurface.focus === 'phases'
7750
+ ? 'agent phases — enter agents · esc return'
7751
+ : 'agents — enter inspect · left phases · esc return'
7752
+ : agentSurface?.kind === 'transcript'
7753
+ ? 'observing agent — esc agents · q parent'
7754
+ : textPrompt
7755
+ ? 'editor open · enter apply · esc cancel'
7756
+ : choicePicker
7757
+ ? choicePickerSearchable(choicePicker)
7758
+ ? 'type to filter · ↑↓ select · enter apply · esc back'
7759
+ : effortSlider
7760
+ ? '←/→ adjust · 1–9 select · enter apply · esc back'
7761
+ : '↑↓ / 1–9 select · enter apply · esc back'
7762
+ : copyPicker
7763
+ ? 'copy target open — ↑↓ / 1–9 select · esc cancel'
7764
+ : handoffPark && phase === 'ready' && state === 'idle' && !composerHasDraft
7765
+ ? 'enter continue · esc stop'
7766
+ : goalStatus && phase === 'ready' && state === 'idle'
7767
+ ? undefined
7768
+ : hintForPhase(phase, state, session?.hasProvider === true, composerHasDraft);
7717
7769
  const permissionSource = reviewSource(permission, scopeRef.current?.sessionId);
7718
7770
  const permissionOwner = permissionSource
7719
7771
  ? subagents.find((agent) => agent.sessionId === permissionSource)
@@ -7770,19 +7822,21 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
7770
7822
  // where it is decided rather than guessed on the screen: with no
7771
7823
  // session behind the picker, esc exits namzu and the footer says
7772
7824
  // so instead of offering a cancel nobody will see.
7773
- cancelExits: !session?.hasProvider })) : (_jsxs(_Fragment, { children: [agentSurface === null && outputViewer === null ? (_jsx(LiveActivity, { compact: compactWork, activeTools: visibleActiveTools, working: state === 'thinking' || state === 'tool', interruptible: abortRef.current !== null, animate: stdout.isTTY === true &&
7825
+ cancelExits: !session?.hasProvider })) : (_jsxs(_Fragment, { children: [agentSurface === null && outputViewer === null && scheduleReviewPrompt === null ? (_jsx(LiveActivity, { compact: compactWork, activeTools: visibleActiveTools, working: state === 'thinking' || state === 'tool', interruptible: abortRef.current !== null, animate: stdout.isTTY === true &&
7774
7826
  permission === null &&
7775
7827
  textPrompt === null &&
7776
- saveSkillPrompt === null, thinking: thinking, tokens: turnTokens, waitingForYou: choicePicker !== null ||
7828
+ saveSkillPrompt === null &&
7829
+ scheduleReviewPrompt === null, thinking: thinking, tokens: turnTokens, waitingForYou: choicePicker !== null ||
7777
7830
  permission !== null ||
7778
7831
  textPrompt !== null ||
7779
- saveSkillPrompt !== null })) : null, agentSurface === null && outputViewer === null && permission === null ? (_jsx(TaskList, { tasks: liveTasks })) : null, permission ? (_jsx(PermissionOverlay, { toolCalls: permission.toolCalls, review: permission.review, summary: permission.summary, detailsOpen: permissionDetailsOpen, reviewOffset: permissionReviewOffset, choice: permissionChoice, queuedCount: queuedPermissionCount, sourceLabel: permissionSourceLabel, columns: terminal.columns, rows: terminal.rows, batchOnly: permission.batchOnly === true, siteNotes: permission.siteNotes, ...(permission.screenConsent === true
7832
+ saveSkillPrompt !== null ||
7833
+ scheduleReviewPrompt !== null })) : null, agentSurface === null && outputViewer === null && permission === null && scheduleReviewPrompt === null ? (_jsx(TaskList, { tasks: liveTasks })) : null, permission ? (_jsx(PermissionOverlay, { toolCalls: permission.toolCalls, review: permission.review, summary: permission.summary, detailsOpen: permissionDetailsOpen, reviewOffset: permissionReviewOffset, choice: permissionChoice, queuedCount: queuedPermissionCount, sourceLabel: permissionSourceLabel, columns: terminal.columns, rows: terminal.rows, batchOnly: permission.batchOnly === true, siteNotes: permission.siteNotes, ...(permission.screenConsent === true
7780
7834
  ? { screenConsent: { provider: session?.providerSummary ?? null } }
7781
- : {}) })) : null, saveSkillPrompt && permission === null ? (_jsx(SaveSkillOverlay, { request: saveSkillPrompt.request, cwd: ctx.cwd, columns: Math.max(1, (terminal.columns ?? 80) - 2), rows: terminal.rows, onAnswer: saveSkillPrompt.resolve }, saveSkillPrompt.request.markdown)) : null, textPrompt ? (_jsx(TextPrompt, { columns: Math.max(1, (terminal.columns ?? 80) - 2), title: textPrompt.title, placeholder: textPrompt.placeholder, initialValue: textPrompt.initialValue, emptyNotice: textPrompt.emptyNotice, hidden: permission !== null || (agentSurface !== null || outputViewer !== null), onSubmit: submitTextPrompt, onCancel: cancelTextPrompt }, textPrompt.token)) : permission === null &&
7835
+ : {}) })) : null, saveSkillPrompt && permission === null && scheduleReviewPrompt === null ? (_jsx(SaveSkillOverlay, { request: saveSkillPrompt.request, cwd: ctx.cwd, columns: Math.max(1, (terminal.columns ?? 80) - 2), rows: terminal.rows, onAnswer: saveSkillPrompt.resolve }, saveSkillPrompt.request.markdown)) : null, scheduleReviewPrompt && permission === null ? (_jsx(ScheduleReviewOverlay, { request: scheduleReviewPrompt.request, columns: Math.max(1, (terminal.columns ?? 80) - 2), rows: Math.max(1, (terminal.rows ?? 24) - 2), onAnswer: scheduleReviewPrompt.resolve }, scheduleReviewPrompt.token)) : null, textPrompt ? (_jsx(TextPrompt, { columns: Math.max(1, (terminal.columns ?? 80) - 2), title: textPrompt.title, placeholder: textPrompt.placeholder, initialValue: textPrompt.initialValue, emptyNotice: textPrompt.emptyNotice, hidden: permission !== null || scheduleReviewPrompt !== null || (agentSurface !== null || outputViewer !== null), onSubmit: submitTextPrompt, onCancel: cancelTextPrompt }, textPrompt.token)) : permission === null && scheduleReviewPrompt === null &&
7782
7836
  agentSurface === null &&
7783
7837
  outputViewer === null &&
7784
7838
  choicePicker?.kind === 'reasoning-effort' &&
7785
- effortSlider ? (_jsx(EffortSlider, { title: choicePicker.title, notice: choicePicker.notice, options: choicePicker.options, selected: selectedChoice, layout: effortSlider, columns: Math.max(1, (terminal.columns ?? 80) - 2) })) : permission === null && agentSurface === null && outputViewer === null && choicePicker ? (_jsx(ChoicePicker, { busy: 'busy' in choicePicker && choicePicker.busy === true, columns: Math.max(1, (terminal.columns ?? 80) - 2), title: choicePicker.title, notice: choicePicker.notice, options: filterChoiceOptions(choicePicker.options, choiceQuery), query: choicePickerSearchable(choicePicker) ? choiceQuery : undefined, selected: selectedChoice, windowSize: choicePicker.kind === 'command' ? choicePicker.windowSize : undefined })) : permission === null && agentSurface === null && outputViewer === null && copyPicker ? (_jsx(CopyPicker, { targets: copyPicker.targets, selected: selectedCopy })) : null, _jsxs(ComposerFrame, { working: state === 'thinking' || state === 'tool' || visibleActiveTools.length > 0, ...(hypermode ? { mode: HYPERMODE } : {}), focus: phase === 'ready' &&
7839
+ effortSlider ? (_jsx(EffortSlider, { title: choicePicker.title, notice: choicePicker.notice, options: choicePicker.options, selected: selectedChoice, layout: effortSlider, columns: Math.max(1, (terminal.columns ?? 80) - 2) })) : permission === null && scheduleReviewPrompt === null && agentSurface === null && outputViewer === null && choicePicker ? (_jsx(ChoicePicker, { busy: 'busy' in choicePicker && choicePicker.busy === true, columns: Math.max(1, (terminal.columns ?? 80) - 2), title: choicePicker.title, notice: choicePicker.notice, options: filterChoiceOptions(choicePicker.options, choiceQuery), query: choicePickerSearchable(choicePicker) ? choiceQuery : undefined, selected: selectedChoice, windowSize: choicePicker.kind === 'command' ? choicePicker.windowSize : undefined })) : permission === null && scheduleReviewPrompt === null && agentSurface === null && outputViewer === null && copyPicker ? (_jsx(CopyPicker, { targets: copyPicker.targets, selected: selectedCopy })) : null, _jsxs(ComposerFrame, { working: state === 'thinking' || state === 'tool' || visibleActiveTools.length > 0, ...(hypermode ? { mode: HYPERMODE } : {}), focus: phase === 'ready' &&
7786
7840
  state !== 'awaiting-permission' &&
7787
7841
  !compacting &&
7788
7842
  externalEditorRequest === null &&
@@ -7791,8 +7845,10 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
7791
7845
  choicePicker === null &&
7792
7846
  copyPicker === null &&
7793
7847
  saveSkillPrompt === null &&
7848
+ scheduleReviewPrompt === null &&
7794
7849
  agentSurface === null && outputViewer === null, hidden: permission !== null ||
7795
7850
  saveSkillPrompt !== null ||
7851
+ scheduleReviewPrompt !== null ||
7796
7852
  textPrompt !== null ||
7797
7853
  choicePicker !== null ||
7798
7854
  copyPicker !== null ||
@@ -7818,6 +7874,7 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
7818
7874
  externalEditorRequest !== null ||
7819
7875
  (agentSurface !== null || outputViewer !== null), hidden: permission !== null ||
7820
7876
  saveSkillPrompt !== null ||
7877
+ scheduleReviewPrompt !== null ||
7821
7878
  textPrompt !== null ||
7822
7879
  choicePicker !== null ||
7823
7880
  copyPicker !== null ||
@@ -7834,17 +7891,19 @@ export function App({ ctx: initialCtx, onExitSummary, externalEditor = defaultEx
7834
7891
  })), mentionCandidates: mentionCandidates, history: history, ...(composerTriggers ? { triggers: composerTriggers } : {}), turnActive: !compacting && (state === 'thinking' || state === 'tool') })] })] })), _jsx(StatusBar, { cwd: ctx.cwd, provider: session?.providerSummary ?? null, model: session?.modelSummary ?? null, effort: reasoningEffort, hypermode: hypermode, goal: statusGoal, state: state, hint: statusHint, permissionMode: displayedPermissionMode, canCycleMode: true }), showComposerSurface &&
7835
7892
  permission === null &&
7836
7893
  agentSurface === null &&
7837
- outputViewer === null ? (_jsx(AgentNarrationBand, { lines: narration })) : null, showComposerSurface &&
7894
+ outputViewer === null &&
7895
+ scheduleReviewPrompt === null ? (_jsx(AgentNarrationBand, { lines: narration })) : null, showComposerSurface &&
7838
7896
  agentSurface === null &&
7839
7897
  outputViewer === null &&
7898
+ scheduleReviewPrompt === null &&
7840
7899
  liveSubagents.length > 0 ? (
7841
- // Still drawn while a review is open, reduced to its header line:
7842
- // the work already approved keeps moving, and the operator
7843
- // deciding the next launch should be able to see that it does.
7844
- _jsx(AgentTaskPanel, { agents: liveSubagents, terminalRows: terminal.rows, terminalColumns: terminal.columns, compact: permission !== null })) : showComposerSurface && permission === null && agentSurface?.kind === 'cockpit' ? (_jsx(AgentCockpit, { agents: subagents, selectedPhaseId: agentSurface.selectedPhaseId, selectedId: agentSurface.selectedId, focus: agentSurface.focus, terminalRows: terminal.rows, terminalColumns: terminal.columns })) : showComposerSurface &&
7900
+ // The active agents remain in memory while the schedule review
7901
+ // owns the available rows; the panel returns after the decision.
7902
+ _jsx(AgentTaskPanel, { agents: liveSubagents, terminalRows: terminal.rows, terminalColumns: terminal.columns, compact: permission !== null })) : showComposerSurface && permission === null && scheduleReviewPrompt === null && agentSurface?.kind === 'cockpit' ? (_jsx(AgentCockpit, { agents: subagents, selectedPhaseId: agentSurface.selectedPhaseId, selectedId: agentSurface.selectedId, focus: agentSurface.focus, terminalRows: terminal.rows, terminalColumns: terminal.columns })) : showComposerSurface &&
7845
7903
  permission === null &&
7904
+ scheduleReviewPrompt === null &&
7846
7905
  agentSurface?.kind === 'transcript' &&
7847
- selectedSubagent ? (_jsx(AgentTranscript, { agent: selectedSubagent, tailOffset: agentSurface.tailOffset, terminalRows: terminal.rows, terminalColumns: terminal.columns })) : null, outputViewer && permission === null ? (_jsx(ToolOutputViewer, { onPrevious: () => {
7906
+ selectedSubagent ? (_jsx(AgentTranscript, { agent: selectedSubagent, tailOffset: agentSurface.tailOffset, terminalRows: terminal.rows, terminalColumns: terminal.columns })) : null, outputViewer && permission === null && scheduleReviewPrompt === null ? (_jsx(ToolOutputViewer, { onPrevious: () => {
7848
7907
  if (outputIndex > 0)
7849
7908
  setOutputViewer(outputBlocks[outputIndex - 1]);
7850
7909
  }, onNext: () => {