@mediadatafusion/pi-workflow-suite 0.0.18 → 0.0.20

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.
@@ -8,11 +8,12 @@ import { StringEnum } from "@earendil-works/pi-ai";
8
8
  import type { AssistantMessage, TextContent } from "@earendil-works/pi-ai";
9
9
  import { CustomEditor, VERSION, compact as piCompact, estimateTokens as piEstimateTokens, findCutPoint as piFindCutPoint, getAgentDir, getMarkdownTheme, type ExtensionAPI, type ExtensionContext, type FileOperations, type SessionEntry, type ToolDefinition } from "@earendil-works/pi-coding-agent";
10
10
  import { Type } from "typebox";
11
- import { activeWorkflowPresetLabel, applyMissionModelForRole, applyModelForRole, applyStandardModelForRole, applyWorkflowPreset, compactionModeLabel, createProjectSettingsOverride, createWorkflowPreset, defaultWorkflowSettings, deleteWorkflowPreset, effectivePlanApprovalRequired, effectiveReviewAutoRun, effectiveValidateAfterExecution, effectiveValidationAutoRun, effectiveRepairGate, formatRole, getDefaultWriteTarget, loadEffectiveSettings, loadGlobalSettings, loadWorkflowSettings, normalizeWorkflowPresetName, parseMissionModelRole, parseRole, parseThinkingLevel, renameWorkflowPreset, renderActiveWorkflowPresetSummary, renderStandardModelStrategy, renderWorkflowModels, renderWorkflowPresets, resolveWorkflowPresetName, roleIsConfigured, saveCurrentWorkflowPreset, setMissionModelForRole, setMissionThinkingForRole, setModelForRole, setRoleEnabled, setStandardModelForRole, setStandardThinkingForRole, setThinkingForRole, standardModelSource, standardModelSourceLabel, standardTodoTriggerModeLabel, updateSettings, workflowCompactionCheckModeLabel, workflowPresetCatalog, workflowPresetLabel, workflowPresetNames, workflowPresetPickerLabel, workflowRoleLabel, workflowSettingsConsistencyDiagnostics, WORKFLOW_CUSTOM_PRESET_MARKER, WORKFLOW_SETTINGS_FILE, type MissionModelRole, type RoleModelSettings, type WorkflowRole, type WorkflowSettingsScope, type WorkflowStartupLogo, type WorkflowStartupLogoColorStyle, type WorkflowStartupLogoFont, type WorkflowStartupLogoShadowDirection, type WorkflowStartupVisual, type CustomBrandBaseVisual, type StandardClarificationMode, type StandardModelRole, type StandardTodoTriggerMode, type WorkflowAgentScope } from "./workflow-model-router.js";
11
+ import { activeWorkflowPresetLabel, applyMissionModelForRole, applyModelForRole, applyStandardModelForRole, applyWorkflowPreset, compactionModeLabel, createProjectSettingsOverride, createWorkflowPreset, defaultWorkflowSettings, deleteWorkflowPreset, effectivePlanApprovalRequired, effectiveReviewAutoRun, effectiveValidateAfterExecution, effectiveValidationAutoRun, effectiveRepairGate, formatRole, getDefaultWriteTarget, loadEffectiveSettings, loadGlobalSettings, loadWorkflowSettings, normalizeWorkflowPresetName, parseMissionModelRole, parseRole, parseThinkingLevel, renameWorkflowPreset, renderActiveWorkflowPresetSummary, renderStandardModelStrategy, renderWorkflowModels, renderWorkflowPresets, resolveWorkflowPresetName, roleIsConfigured, saveCurrentWorkflowPreset, setMissionModelForRole, setMissionThinkingForRole, setModelForRole, setRoleEnabled, setStandardModelForRole, setStandardThinkingForRole, setThinkingForRole, standardModelSource, standardModelSourceLabel, standardTodoTriggerModeLabel, updateSettings, workflowCompactionCheckModeLabel, workflowPresetCatalog, workflowPresetLabel, workflowPresetNames, workflowPresetPickerLabel, workflowRoleLabel, workflowSettingsConsistencyDiagnostics, WORKFLOW_CUSTOM_PRESET_MARKER, WORKFLOW_SETTINGS_FILE, type MissionModelRole, type RoleModelSettings, type WorkflowRole, type WorkflowSettingsScope, type WorkflowStartupLogo, type WorkflowStartupLogoColorStyle, type WorkflowStartupLogoFont, type WorkflowStartupLogoShadowDirection, type WorkflowStartupVisual, type WorkflowEditorHintContrast, type CustomBrandBaseVisual, type StandardClarificationMode, type StandardModelRole, type StandardTodoTriggerMode, type WorkflowAgentScope } from "./workflow-model-router.js";
12
12
  import { renderHandoffProjectContext, renderWorkflowStatus, renderWorkflowSummary } from "./workflow-summary.js";
13
13
  import { BASE_EXECUTE_TOOLS, EXECUTE_TOOLS, PLAN_TOOLS, REVIEW_TOOLS, WORKFLOW_DIAGRAM_TOOL, WORKFLOW_PLAN_RESULT_TOOL, WORKFLOW_REVIEW_RESULT_TOOL, WORKFLOW_EXECUTION_RESULT_TOOL, WORKFLOW_VALIDATION_RESULT_TOOL, WORKFLOW_REPAIR_RESULT_TOOL, WORKFLOW_PROGRESS_TOOL, MISSION_PLAN_RESULT_TOOL, MISSION_MILESTONE_RESULT_TOOL, STANDARD_HANDOFF_RESULT_TOOL, isBlockedExecuteCommand, registerToolGuard, standardSafeReadOnlyBash, VALIDATOR_TOOLS } from "./workflow-tool-guard.js";
14
14
  import { refreshRuntimeWebTools, registerWorkflowWebTools, runtimeWebResearchGuidance, webSafePlanTools, withRuntimeWebTools } from "./workflow-web-tools.js";
15
15
  import { addMissionCheckpoint, applyPlanRuntimeAccounting, applyStandardRuntimeAccounting, clearOldMissionStates, clearOldWorkflowPlans, compact, createMissionState, createStandardRuntimeId, createWorkflowPlanId, emptyState, extractVerdict, isMissionRuntimeActiveStatus, isPlanRuntimeActiveMode, listMissionStates, listWorkflowPlans, loadMissionState, loadState, loadWorkflowPlan, missionActiveRuntimeMs, missionRuntimeCounterState, missionWallClockAgeMs, planActiveRuntimeMs, planRuntimeCounterState, planWallClockAgeMs, saveMissionState, saveState, saveWorkflowPlan, standardActiveRuntimeMs, standardRuntimeCounterState, standardWallClockAgeMs, PLAN_HISTORY_DIR, MISSION_HISTORY_DIR, type ClarificationAnswer, type ClarificationQuestion, type MissionAutonomy, type MissionMilestone, type MissionState, type PlanProgressState, type PlanStepStatus, type PlanValidationStatus, type SavedWorkflowPlan, type StandardTodoItemStatus, type StandardTodoState, type WorkflowState, type WorkflowTypedHandoffType } from "./workflow-state.js";
16
+ import { WORKFLOW_SHORTCUTS, workflowEntryShortcutLabel as workflowRegistryEntryShortcutLabel, workflowPresetCycleShortcutLabel, workflowSettingsShortcutLines, workflowShortcutKey, workflowWidgetShortcutLabel, type WorkflowShortcutActionId } from "./workflow-shortcuts.js";
16
17
  import { cleanupOrphanProcesses, clearSubagentResultCache, runWorkflowSubagents, workflowSubagentResultOutput, type WorkflowSubagentResult, type WorkflowSubagentTask } from "./subagent/runner.js";
17
18
  import { parseScope, parseBool, parsePlanningDepth, parseClarificationMode, parseStandardTodoTriggerMode, parseStandardClarificationMode, parseStandardModelRole, parseWorkflowAgentScope, parseClarificationTiming, parseSubagentPolicy, parseSubagentPlanningPolicy, parseEditConcurrencyMode, parsePlanningOrchestrationPolicy, parseCompactionMode, parseWorkflowCompactionCheckMode, parseMissionAutonomy, parseValidationRetryMode, parsePositiveInt, updatedMessage, parseClarifyingQuestions, parseShorthandAnswers, formatAnswersForPlanner, planValidationStatusForVerdict } from "./workflow-parsers.js";
18
19
  import { classifyValidationFailure, normalizeValidationVerdict, validationReportHasRepairableIssue } from "./workflow-validation-classifier.js";
@@ -2561,13 +2562,13 @@ Themes:
2561
2562
  - /workflow-settings theme brand base minimal|workflow_duo|mission_control|diagnostic_center|data_stream|neural_grid
2562
2563
 
2563
2564
  Workflow entry shortcuts:
2564
- - Ctrl+Shift+S toggles Standard Mode
2565
- - Ctrl+Shift+L enters Plan Mode
2566
- - Ctrl+Shift+M enters Mission Mode
2567
- - In the opposite active mode, Ctrl+Shift+L/M switches directly to that mode
2565
+ - ${workflowEntryShortcutLabel("standard").replace(/^Standard:/, "")} toggles Standard Mode
2566
+ - ${workflowEntryShortcutLabel("plan").replace(/^Plan:/, "")} enters Plan Mode
2567
+ - ${workflowEntryShortcutLabel("mission").replace(/^Mission:/, "")} enters Mission Mode
2568
+ - In the opposite active mode, ${workflowEntryShortcutLabel("plan").replace(/^Plan:/, "")}/${workflowEntryShortcutLabel("mission").replace(/^Mission:/, "")} switches directly to that mode
2568
2569
 
2569
2570
  Presets:
2570
- - Ctrl+Shift+U cycles workflow presets from the active Plan/Mission/Standard footer/status line
2571
+ - ${workflowPresetCycleShortcutLabel()} cycles workflow presets from the active Plan/Mission/Standard footer/status line
2571
2572
  - /workflow presets opens the preset selector
2572
2573
  - /workflow presets list
2573
2574
  - /workflow presets apply <name>
@@ -2680,6 +2681,7 @@ UI Widgets:
2680
2681
  - /workflow-settings set ui showActiveWorkflowSwitchHint true|false
2681
2682
  - /workflow-settings set ui showWidgetShortcutHint true|false
2682
2683
  - /workflow-settings set ui showPresetShortcutHint true|false
2684
+ - /workflow-settings set ui editorHintContrast subtle|normal|bright|high
2683
2685
 
2684
2686
  Sub-agents and parallelism:
2685
2687
  - /workflow-settings set subagents enabled true|false
@@ -3684,7 +3686,7 @@ ${renderPlanModelSettings(settings)}
3684
3686
 
3685
3687
  ${renderMissionModelStrategy(settings)}
3686
3688
 
3687
- ## UI / Footer
3689
+ ## UI / Widgets
3688
3690
  Plan Top Widget: ${widgetVisibilityLabel(settings, "planTop")}
3689
3691
  Plan Bottom Widget: ${widgetVisibilityLabel(settings, "planBottom")}
3690
3692
  Mission Top Widget: ${widgetVisibilityLabel(settings, "missionTop")}
@@ -3695,6 +3697,7 @@ Idle Entry Hint: ${workflowWidgetUi(settings).showIdleWorkflowEntryHint !== fals
3695
3697
  Active Switch Hint: ${workflowWidgetUi(settings).showActiveWorkflowSwitchHint !== false ? "visible" : "hidden"}
3696
3698
  Widget Shortcut Hint: ${workflowWidgetUi(settings).showWidgetShortcutHint !== false ? "visible" : "hidden"}
3697
3699
  Preset Shortcut Hint: ${workflowWidgetUi(settings).showPresetShortcutHint !== false ? "visible" : "hidden"}
3700
+ Editor Hint Contrast: ${workflowEditorHintContrastLabel(workflowEditorHintContrast(settings))}
3698
3701
  Workflow Theme: ${workflowThemeDisplayName(workflowThemeName(settings))}
3699
3702
  Startup Visual: ${startupVisualOrDefault(settings)}
3700
3703
  Startup Logo: ${startupLogoOrDefault(settings)}
@@ -3706,11 +3709,7 @@ Startup On Session Start: ${settings.ui.startupVisualOnSessionStart === true ? "
3706
3709
  Custom Brand: ${settings.ui.customBrandEnabled === true ? "enabled" : "disabled"}
3707
3710
  Custom Brand Text: ${sanitizeCustomBrandText(settings.ui.customBrandText) || "(empty)"}
3708
3711
  Custom Brand Base Template: ${customBrandBaseVisualOrDefault(settings)}
3709
- Standard Shortcut: Ctrl+Shift+S toggles Standard Mode
3710
- Plan Shortcut: Ctrl+Shift+L enters Plan Mode
3711
- Mission Shortcut: Ctrl+Shift+M enters Mission Mode
3712
- Widget Shortcuts: Ctrl+Shift+T/B while Plan/Mission/Standard Mode is active
3713
- Preset Cycle Shortcut: Ctrl+Shift+U while Plan/Mission/Standard Mode is active
3712
+ ${workflowSettingsShortcutLines().join("\n")}
3714
3713
  Footer Line: idle displays Plan/Mission entry hints only; active workflows display compact widget/preset hints and workflow switch hints by default
3715
3714
  Fallback Commands: /workflow widgets status, /workflow presets, /standard, /plan, /mission
3716
3715
 
@@ -5030,15 +5029,10 @@ function planProgressWidget(state: WorkflowState, settings: ReturnType<typeof lo
5030
5029
  return lines;
5031
5030
  }
5032
5031
 
5033
- const STANDARD_MODE_SHORTCUT = "Ctrl+Shift+S";
5034
- const PLAN_MODE_SHORTCUT = "Ctrl+Shift+L";
5035
- const MISSION_MODE_SHORTCUT = "Ctrl+Shift+M";
5036
-
5037
5032
  type WorkflowEntryMode = "standard" | "plan" | "mission";
5038
5033
 
5039
5034
  function workflowEntryShortcutLabel(mode: WorkflowEntryMode): string {
5040
- if (mode === "standard") return `Standard:${STANDARD_MODE_SHORTCUT}`;
5041
- return mode === "plan" ? `Plan:${PLAN_MODE_SHORTCUT}` : `Mission:${MISSION_MODE_SHORTCUT}`;
5035
+ return workflowRegistryEntryShortcutLabel(mode);
5042
5036
  }
5043
5037
 
5044
5038
  function workflowFooterShortcutsEnabled(): boolean {
@@ -5051,10 +5045,10 @@ function workflowActiveShortcutSummary(mode: WorkflowEntryMode, state: WorkflowS
5051
5045
  const parts: string[] = [];
5052
5046
  if (shortcuts && ui.showWidgetShortcutHint !== false) {
5053
5047
  const bottomRelevant = mode === "plan" ? planBottomRelevant(state) : mode === "mission" ? missionBottomRelevant(state, activeMissionForUi(state)) : Boolean(state.standardTodo?.items.length);
5054
- parts.push(bottomRelevant ? "Widgets:Ctrl+Shift+T/B" : "Widget:Ctrl+Shift+T");
5048
+ parts.push(workflowWidgetShortcutLabel(bottomRelevant));
5055
5049
  }
5056
5050
  if (ui.showPresetShortcutHint !== false) {
5057
- parts.push(`Preset:${activeWorkflowPresetLabel(settings)}${shortcuts ? " Ctrl+Shift+U" : ""}`);
5051
+ parts.push(`Preset:${activeWorkflowPresetLabel(settings)}${shortcuts ? ` ${workflowPresetCycleShortcutLabel()}` : ""}`);
5058
5052
  }
5059
5053
  if (ui.showActiveWorkflowSwitchHint !== false) {
5060
5054
  const switchHints = (["standard", "plan", "mission"] as WorkflowEntryMode[])
@@ -5414,7 +5408,7 @@ function renderWorkflowThemePreview(settings: ReturnType<typeof loadWorkflowSett
5414
5408
  }
5415
5409
 
5416
5410
  function renderWorkflowFooterThemePreview(settings: ReturnType<typeof loadWorkflowSettings>): string {
5417
- const suffix = ` ${workflowShortcutStatusText(settings, "Widgets:Ctrl+Shift+T/B Preset:simple Mission:Ctrl+Shift+M")}`;
5411
+ const suffix = ` ${workflowShortcutStatusText(settings, `${workflowWidgetShortcutLabel(true)} Preset:simple ${workflowPresetCycleShortcutLabel()} ${workflowEntryShortcutLabel("mission")}`)}`;
5418
5412
  return [
5419
5413
  `${workflowWidgetRgb(settings, "title", "workflow:")}${workflowWidgetRgb(settings, "emphasis", "planning")}${suffix}`,
5420
5414
  `${workflowWidgetRgb(settings, "title", "workflow:")}${workflowWidgetRgb(settings, "progress", "executing")}${suffix}`,
@@ -5527,8 +5521,8 @@ class WorkflowSuiteEditor extends CustomEditor {
5527
5521
  try {
5528
5522
  const settings = loadWorkflowSettings(this.workflowCwd);
5529
5523
  const decorate = workflowRoleTextDecoration(settings, "muted");
5530
- let hintStyled = `\x1b[2m\x1b[38;5;240m${workflowEditorHintText}\x1b[0m`;
5531
- if (decorate) hintStyled = decorate(hintStyled);
5524
+ let hintStyled = workflowEditorHintStyledText(settings, workflowEditorHintText);
5525
+ if (workflowEditorHintContrast(settings) === "subtle" && decorate) hintStyled = decorate(hintStyled);
5532
5526
  const innerWidth = width - 2;
5533
5527
  const hintLen = visibleTextWidth(hintStyled);
5534
5528
  const displayHint = hintLen > innerWidth ? truncateVisibleText(hintStyled, innerWidth) : hintStyled;
@@ -6525,6 +6519,13 @@ function isMissionWorkflowMode(state: WorkflowState): boolean {
6525
6519
  }
6526
6520
 
6527
6521
  type WorkflowWidgetSlot = "planTop" | "planBottom" | "missionTop" | "missionBottom" | "standardTop" | "standardBottom";
6522
+ const WORKFLOW_EDITOR_HINT_CONTRASTS: WorkflowEditorHintContrast[] = ["subtle", "normal", "bright", "high"];
6523
+ const WORKFLOW_EDITOR_HINT_CONTRAST_LABELS: Record<WorkflowEditorHintContrast, string> = {
6524
+ subtle: "Subtle",
6525
+ normal: "Normal",
6526
+ bright: "Bright",
6527
+ high: "High Contrast",
6528
+ };
6528
6529
  type WorkflowWidgetUiSettings = ReturnType<typeof loadWorkflowSettings>["ui"] & {
6529
6530
  showPlanModeIndicator?: boolean;
6530
6531
  planModeIndicatorText?: string;
@@ -6538,6 +6539,7 @@ type WorkflowWidgetUiSettings = ReturnType<typeof loadWorkflowSettings>["ui"] &
6538
6539
  showActiveWorkflowSwitchHint?: boolean;
6539
6540
  showWidgetShortcutHint?: boolean;
6540
6541
  showPresetShortcutHint?: boolean;
6542
+ editorHintContrast?: WorkflowEditorHintContrast;
6541
6543
  };
6542
6544
 
6543
6545
  const widgetVisibilityOverrides: Partial<Record<WorkflowWidgetSlot, boolean>> = {};
@@ -6554,6 +6556,38 @@ function workflowWidgetUi(settings: ReturnType<typeof loadWorkflowSettings>): Wo
6554
6556
  return settings.ui as WorkflowWidgetUiSettings;
6555
6557
  }
6556
6558
 
6559
+ function parseEditorHintContrast(value?: string): WorkflowEditorHintContrast | undefined {
6560
+ const input = value?.trim().toLowerCase().replace(/[\s_-]+/g, "");
6561
+ if (!input) return undefined;
6562
+ if (input === "subtle" || input === "muted" || input === "dim") return "subtle";
6563
+ if (input === "normal" || input === "default") return "normal";
6564
+ if (input === "bright") return "bright";
6565
+ if (input === "high" || input === "highcontrast" || input === "maximum") return "high";
6566
+ return undefined;
6567
+ }
6568
+
6569
+ function workflowEditorHintContrast(settings: ReturnType<typeof loadWorkflowSettings>): WorkflowEditorHintContrast {
6570
+ return parseEditorHintContrast(workflowWidgetUi(settings).editorHintContrast) ?? "normal";
6571
+ }
6572
+
6573
+ function workflowEditorHintContrastLabel(contrast: WorkflowEditorHintContrast): string {
6574
+ return WORKFLOW_EDITOR_HINT_CONTRAST_LABELS[contrast];
6575
+ }
6576
+
6577
+ function workflowEditorHintStyledText(settings: ReturnType<typeof loadWorkflowSettings>, text: string): string {
6578
+ switch (workflowEditorHintContrast(settings)) {
6579
+ case "subtle":
6580
+ return `\x1b[2m\x1b[38;5;240m${text}\x1b[0m`;
6581
+ case "bright":
6582
+ return `\x1b[38;5;250m${text}\x1b[0m`;
6583
+ case "high":
6584
+ return `\x1b[1m\x1b[38;5;255m${text}\x1b[0m`;
6585
+ case "normal":
6586
+ default:
6587
+ return `\x1b[38;5;245m${text}\x1b[0m`;
6588
+ }
6589
+ }
6590
+
6557
6591
  function workflowWidgetVisible(settings: ReturnType<typeof loadWorkflowSettings>, slot: WorkflowWidgetSlot): boolean {
6558
6592
  const override = widgetVisibilityOverrides[slot];
6559
6593
  if (override !== undefined) return override;
@@ -7137,7 +7171,7 @@ function renderSavedPlan(plan: SavedWorkflowPlan): string {
7137
7171
  }
7138
7172
 
7139
7173
  function missionHelp(): string {
7140
- return `# Mission Mode Help\n\nMission Mode is a persistent milestone workflow for longer-running work. It runs alongside Plan Mode and does not replace /p.\n\nCommands:\n- /mission enters Mission Mode and waits for a goal\n- /mission help\n- /mission start <goal>\n- /mission <goal>\n- /mission clarify\n- /mission clarify answer 1A 2C\n- /mission clarify skip 1\n- /mission plan\n- /mission review\n- /mission approve\n- /mission run\n- /mission continue\n- /mission next\n- /mission pause\n- /mission resume\n- /mission retry\n- /mission repair\n- /mission revalidate\n- /mission set autonomy manual|approval_gated|supervised_auto|full_auto\n- /mission sync-settings\n- /mission status\n- /mission checkpoints\n- /mission stop\n- /mission list\n- /mission latest\n- /mission cleanup [limit]\n\nShortcuts:\n- Ctrl+Shift+M enters Mission Mode\n- Ctrl+Shift+L switches from Mission Mode to Plan Mode\n\nSafety:\n- Mission plans require approval before /mission run.\n- full_auto never runs unless missions.allowFullAuto=true.\n- Destructive actions, push, deploy, database mutation, and secret edits require explicit approval.\n- Mission run uses executor, validator/final-validator, safety, sub-agent, and repair gates and records stop or block reasons.\n- Validation failures attempt safe repair/revalidation within configured retry limits, then block for approval if limits or safety gates are hit.`;
7174
+ return `# Mission Mode Help\n\nMission Mode is a persistent milestone workflow for longer-running work. It runs alongside Plan Mode and does not replace /p.\n\nCommands:\n- /mission enters Mission Mode and waits for a goal\n- /mission help\n- /mission start <goal>\n- /mission <goal>\n- /mission clarify\n- /mission clarify answer 1A 2C\n- /mission clarify skip 1\n- /mission plan\n- /mission review\n- /mission approve\n- /mission run\n- /mission continue\n- /mission next\n- /mission pause\n- /mission resume\n- /mission retry\n- /mission repair\n- /mission revalidate\n- /mission set autonomy manual|approval_gated|supervised_auto|full_auto\n- /mission sync-settings\n- /mission status\n- /mission checkpoints\n- /mission stop\n- /mission list\n- /mission latest\n- /mission cleanup [limit]\n\nShortcuts:\n- ${workflowEntryShortcutLabel("mission").replace(/^Mission:/, "")} enters Mission Mode\n- ${workflowEntryShortcutLabel("plan").replace(/^Plan:/, "")} switches from Mission Mode to Plan Mode\n\nSafety:\n- Mission plans require approval before /mission run.\n- full_auto never runs unless missions.allowFullAuto=true.\n- Destructive actions, push, deploy, database mutation, and secret edits require explicit approval.\n- Mission run uses executor, validator/final-validator, safety, sub-agent, and repair gates and records stop or block reasons.\n- Validation failures attempt safe repair/revalidation within configured retry limits, then block for approval if limits or safety gates are hit.`;
7141
7175
  }
7142
7176
 
7143
7177
  function promptCandidateFiles(name: string): string[] {
@@ -9718,7 +9752,7 @@ export default function workflowModes(pi: ExtensionAPI): void {
9718
9752
  const route = await applyModelForRole(pi, ctx, "planner", { cwd: ctx.cwd });
9719
9753
  if (!route) return false;
9720
9754
  updateState({ modelsUsed: { ...(state.modelsUsed ?? {}), planner: modelLabel(route) } }, ctx);
9721
- if (showNotice) ctx.ui.notify(`Active Plan Mode planner route reapplied: ${modelLabel(route)}\n${activeModelDiagnostic(ctx)}`, "info");
9755
+ if (showNotice) workflowUiNotify(ctx, `Active Plan Mode planner route reapplied: ${modelLabel(route)}\n${activeModelDiagnostic(ctx)}`, "info");
9722
9756
  return true;
9723
9757
  };
9724
9758
 
@@ -9727,13 +9761,13 @@ export default function workflowModes(pi: ExtensionAPI): void {
9727
9761
  const settings = loadWorkflowSettings(ctx.cwd);
9728
9762
  const standardRole = effectiveStandardModelRole(settings);
9729
9763
  if (standardRole === "current") {
9730
- if (showNotice) ctx.ui.notify(`Standard Mode keeps the current Pi model.\n${activeModelDiagnostic(ctx)}`, "info");
9764
+ if (showNotice) workflowUiNotify(ctx, `Standard Mode keeps the current Pi model.\n${activeModelDiagnostic(ctx)}`, "info");
9731
9765
  return false;
9732
9766
  }
9733
9767
  const route = await applyStandardModelForRole(pi, ctx, standardRole, { cwd: ctx.cwd });
9734
9768
  if (!route) return false;
9735
9769
  updateState({ modelsUsed: { ...(state.modelsUsed ?? {}), [standardRole]: modelLabel(route) } }, ctx);
9736
- if (showNotice) ctx.ui.notify(`Active Standard Mode ${standardRole} route applied: ${modelLabel(route)}\n${activeModelDiagnostic(ctx)}`, "info");
9770
+ if (showNotice) workflowUiNotify(ctx, `Active Standard Mode ${standardRole} route applied: ${modelLabel(route)}\n${activeModelDiagnostic(ctx)}`, "info");
9737
9771
  return true;
9738
9772
  };
9739
9773
 
@@ -9748,7 +9782,7 @@ export default function workflowModes(pi: ExtensionAPI): void {
9748
9782
  const settings = loadWorkflowSettings(ctx.cwd);
9749
9783
  const globalUi = workflowWidgetUi(loadGlobalSettings());
9750
9784
  const ui = workflowWidgetUi(settings);
9751
- const common = `Active Mode: ${state.mode}\nShortcuts: ${globalUi.enableWidgetShortcuts !== false ? "enabled" : "disabled"}\nRemember Visibility: ${globalUi.rememberWidgetVisibility !== false ? "enabled" : "disabled"}\nStorage: ${globalUi.rememberWidgetVisibility !== false ? "global settings" : "current Pi session"}\nFooter Hints: idle entry ${ui.showIdleWorkflowEntryHint !== false ? "visible" : "hidden"}, active switch ${ui.showActiveWorkflowSwitchHint !== false ? "visible" : "hidden"}, widgets ${ui.showWidgetShortcutHint !== false ? "visible" : "hidden"}, preset ${ui.showPresetShortcutHint !== false ? "visible" : "hidden"}`;
9785
+ const common = `Active Mode: ${state.mode}\nShortcuts: ${globalUi.enableWidgetShortcuts !== false ? "enabled" : "disabled"}\nRemember Visibility: ${globalUi.rememberWidgetVisibility !== false ? "enabled" : "disabled"}\nStorage: ${globalUi.rememberWidgetVisibility !== false ? "global settings" : "current Pi session"}\nEditor Hints: idle entry ${ui.showIdleWorkflowEntryHint !== false ? "visible" : "hidden"}, active switch ${ui.showActiveWorkflowSwitchHint !== false ? "visible" : "hidden"}, widgets ${ui.showWidgetShortcutHint !== false ? "visible" : "hidden"}, preset ${ui.showPresetShortcutHint !== false ? "visible" : "hidden"}, contrast ${workflowEditorHintContrastLabel(workflowEditorHintContrast(settings))}`;
9752
9786
  if (isPlanWorkflowUiMode(state)) {
9753
9787
  const bottom = planBottomRelevant(state) ? widgetVisibilityLabel(settings, "planBottom") : "not applicable";
9754
9788
  return `# Workflow Widgets\n\nPlan Top Widget: ${widgetVisibilityLabel(settings, "planTop")}\nPlan Bottom Widget: ${bottom}\nStatus Line: ${widgetVisibilityStatus(state, settings) ?? "none"}\n${common}`;
@@ -9761,7 +9795,13 @@ export default function workflowModes(pi: ExtensionAPI): void {
9761
9795
  if (isStandardWorkflowMode(state)) {
9762
9796
  return `# Workflow Widgets\n\nStandard Top Widget: ${widgetVisibilityLabel(settings, "standardTop")}\nStandard To Do Widget: ${widgetVisibilityLabel(settings, "standardBottom")}\nStatus Line: ${widgetVisibilityStatus(state, settings) ?? "none"}\n${common}`;
9763
9797
  }
9764
- return `# Workflow Widgets\n\nNo active Plan/Mission/Standard widget is currently visible.\nStatus Line: ${widgetVisibilityStatus(state, settings) ?? "none"}\n\nEntry Shortcuts:\n- ${workflowEntryShortcutLabel("standard")}\n- ${workflowEntryShortcutLabel("plan")}\n- ${workflowEntryShortcutLabel("mission")}\n\nActive-mode footer uses compact hints such as: Widgets:Ctrl+Shift+T/B Preset:${activeWorkflowPresetLabel(settings)} Ctrl+Shift+U Standard:Ctrl+Shift+S Mission:Ctrl+Shift+M\nWidget toggles and preset cycling are visible only while Plan/Mission/Standard Mode is active.\n\n${common}`;
9798
+ return `# Workflow Widgets\n\nNo active Plan/Mission/Standard widget is currently visible.\nStatus Line: ${widgetVisibilityStatus(state, settings) ?? "none"}\n\nEntry Shortcuts:\n- ${workflowEntryShortcutLabel("standard")}\n- ${workflowEntryShortcutLabel("plan")}\n- ${workflowEntryShortcutLabel("mission")}\n\nActive-mode editor hints use compact text such as: ${workflowWidgetShortcutLabel(true)} Preset:${activeWorkflowPresetLabel(settings)} ${workflowPresetCycleShortcutLabel()} ${workflowEntryShortcutLabel("standard")} ${workflowEntryShortcutLabel("mission")}\nWidget toggles and preset cycling are visible only while Plan/Mission/Standard Mode is active.\n\n${common}`;
9799
+ };
9800
+
9801
+ const renderEditorHintsSettings = (ctx: ExtensionContext): string => {
9802
+ const settings = loadWorkflowSettings(ctx.cwd);
9803
+ const ui = workflowWidgetUi(settings);
9804
+ return `# Editor Hints\n\nThese hints render inline in the editor/input box.\n\nIdle Entry Hint: ${ui.showIdleWorkflowEntryHint !== false ? "visible" : "hidden"}\nActive Switch Hint: ${ui.showActiveWorkflowSwitchHint !== false ? "visible" : "hidden"}\nWidget Shortcut Hint: ${ui.showWidgetShortcutHint !== false ? "visible" : "hidden"}\nPreset Shortcut Hint: ${ui.showPresetShortcutHint !== false ? "visible" : "hidden"}\nHint Contrast: ${workflowEditorHintContrastLabel(workflowEditorHintContrast(settings))}`;
9765
9805
  };
9766
9806
 
9767
9807
  const setWorkflowWidgetVisibility = (ctx: ExtensionContext, slot: WorkflowWidgetSlot, visible: boolean): string => {
@@ -9814,7 +9854,7 @@ export default function workflowModes(pi: ExtensionAPI): void {
9814
9854
  const messages = (["planTop", "planBottom", "missionTop", "missionBottom", "standardTop", "standardBottom"] as WorkflowWidgetSlot[]).map((slot) => setWorkflowWidgetVisibility(ctx, slot, visible));
9815
9855
  return show(pi, `# Workflow Widgets\n\n${messages.join("\n")}\n\n${renderWorkflowWidgetsStatus(ctx)}`);
9816
9856
  }
9817
- return show(pi, "# Workflow Widgets\n\nUsage:\n- /workflow widgets status\n- /workflow widgets list\n- /workflow widgets configure\n- /workflow widgets toggle top\n- /workflow widgets toggle bottom\n- /workflow widgets on\n- /workflow widgets off\n\nFooter behavior:\n- Idle: Plan/Mission entry shortcuts only\n- Active modes: compact widget/preset hints plus Plan/Mission switch hints by default\n- Active switch hints can be configured in /workflow-settings configure widgets Footer Hints");
9857
+ return show(pi, "# Workflow Widgets\n\nUsage:\n- /workflow widgets status\n- /workflow widgets list\n- /workflow widgets configure\n- /workflow widgets toggle top\n- /workflow widgets toggle bottom\n- /workflow widgets on\n- /workflow widgets off\n\nEditor hint behavior:\n- Idle: Plan/Mission entry shortcuts only\n- Active modes: compact widget/preset hints plus Plan/Mission switch hints by default\n- Active switch hints can be configured in /workflow-settings configure widgets -> Editor Hints");
9818
9858
  };
9819
9859
 
9820
9860
  const persistCurrentPlan = (ctx: ExtensionContext, approvalStatus: "draft" | "approved" | "revised" | "completed" | "archived", saveReason: string, handoff: { executionSummary?: string; reviewerReport?: string; validationReport?: string; repairAttempt?: string; finalReport?: string } = {}): string | undefined => {
@@ -14395,7 +14435,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14395
14435
  const plannerReapplied = role === "planner" ? await reapplyPlannerRouteIfPlanMode(ctx, true) : false;
14396
14436
  const standardSettings = loadWorkflowSettings(ctx.cwd);
14397
14437
  const standardReapplied = effectiveStandardModelRole(standardSettings) === role ? await reapplyStandardRouteIfStandardMode(ctx, true) : false;
14398
- ctx.ui.notify(`${role} model set to ${provider}/${model} in ${result.file}${plannerReapplied || standardReapplied ? `\n${activeModelDiagnostic(ctx)}` : ""}`, "info");
14438
+ workflowUiNotify(ctx, `${role} model set to ${provider}/${model} in ${result.file}${plannerReapplied || standardReapplied ? `\n${activeModelDiagnostic(ctx)}` : ""}`, "info");
14399
14439
  }
14400
14440
 
14401
14441
  async function configureStandardRoleModel(ctx: ExtensionContext, role: WorkflowRole) {
@@ -14403,14 +14443,14 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14403
14443
  if (!selected) return;
14404
14444
  const result = setStandardModelForRole(role, selected.provider, selected.model, ctx.cwd);
14405
14445
  await reapplyStandardRouteIfStandardMode(ctx, true);
14406
- ctx.ui.notify(`standard ${role} model set to ${selected.provider}/${selected.model} in ${result.file}`, "info");
14446
+ workflowUiNotify(ctx, `standard ${role} model set to ${selected.provider}/${selected.model} in ${result.file}`, "info");
14407
14447
  }
14408
14448
 
14409
14449
  async function configureMissionRoleModel(ctx: ExtensionContext, role: MissionModelRole) {
14410
14450
  const selected = await selectProviderAndModel(ctx, `Mission ${role} model`);
14411
14451
  if (!selected) return;
14412
14452
  const result = setMissionModelForRole(role, selected.provider, selected.model, ctx.cwd);
14413
- ctx.ui.notify(`mission ${role} model set to ${selected.provider}/${selected.model} in ${result.file}`, "info");
14453
+ workflowUiNotify(ctx, `mission ${role} model set to ${selected.provider}/${selected.model} in ${result.file}`, "info");
14414
14454
  }
14415
14455
 
14416
14456
  async function configureStandardThinking(ctx: ExtensionContext) {
@@ -14420,7 +14460,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14420
14460
  if (!level) return;
14421
14461
  const result = setStandardThinkingForRole(role, level, ctx.cwd);
14422
14462
  await reapplyStandardRouteIfStandardMode(ctx, true);
14423
- ctx.ui.notify(`standard ${role} thinking set to ${level} in ${result.file}`, "info");
14463
+ workflowUiNotify(ctx, `standard ${role} thinking set to ${level} in ${result.file}`, "info");
14424
14464
  }
14425
14465
 
14426
14466
  async function configureMissionThinking(ctx: ExtensionContext) {
@@ -14429,7 +14469,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14429
14469
  const level = parseThinkingLevel((await ctx.ui.select("Select mission thinking level:", ["off", "minimal", "low", "medium", "high", "xhigh"])) ?? "");
14430
14470
  if (!level) return;
14431
14471
  const result = setMissionThinkingForRole(role, level, ctx.cwd);
14432
- ctx.ui.notify(`mission ${role} thinking set to ${level} in ${result.file}`, "info");
14472
+ workflowUiNotify(ctx, `mission ${role} thinking set to ${level} in ${result.file}`, "info");
14433
14473
  }
14434
14474
 
14435
14475
  async function configureThinking(ctx: ExtensionContext) {
@@ -14441,7 +14481,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14441
14481
  const plannerReapplied = role === "planner" ? await reapplyPlannerRouteIfPlanMode(ctx, true) : false;
14442
14482
  const standardSettings = loadWorkflowSettings(ctx.cwd);
14443
14483
  const standardReapplied = effectiveStandardModelRole(standardSettings) === role ? await reapplyStandardRouteIfStandardMode(ctx, true) : false;
14444
- ctx.ui.notify(`${role} thinking set to ${level} in ${result.file}${plannerReapplied || standardReapplied ? `\n${activeModelDiagnostic(ctx)}` : ""}`, "info");
14484
+ workflowUiNotify(ctx, `${role} thinking set to ${level} in ${result.file}${plannerReapplied || standardReapplied ? `\n${activeModelDiagnostic(ctx)}` : ""}`, "info");
14445
14485
  }
14446
14486
 
14447
14487
  async function chooseBool(ctx: ExtensionContext, title: string): Promise<boolean | undefined> {
@@ -14449,6 +14489,128 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14449
14489
  return parseBool(choice ?? undefined);
14450
14490
  }
14451
14491
 
14492
+ function humanizeWorkflowSettingSegment(segment: string): string {
14493
+ return segment
14494
+ .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
14495
+ .replace(/[_-]+/g, " ")
14496
+ .replace(/\bui\b/gi, "UI")
14497
+ .replace(/\bapi\b/gi, "API")
14498
+ .replace(/\bto do\b/gi, "To Do")
14499
+ .trim()
14500
+ .replace(/\s+/g, " ")
14501
+ .replace(/\w\S*/g, (word) => word === "UI" || word === "API" ? word : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());
14502
+ }
14503
+
14504
+ function workflowSettingDisplayLabel(setting: string): string {
14505
+ const labels: Record<string, string> = {
14506
+ "ui.editorHintContrast": "Editor hint contrast",
14507
+ "ui.showIdleWorkflowEntryHint": "Idle entry hint",
14508
+ "ui.showActiveWorkflowSwitchHint": "Active switch hint",
14509
+ "ui.showWidgetShortcutHint": "Widget shortcut hint",
14510
+ "ui.showPresetShortcutHint": "Preset shortcut hint",
14511
+ "ui.enableWidgetShortcuts": "Widget shortcuts",
14512
+ "ui.rememberWidgetVisibility": "Remember widget visibility",
14513
+ "ui.workflowTheme": "Workflow theme",
14514
+ "ui.widgetTextStyle": "Widget text style",
14515
+ "ui.startupTextStyle": "Startup text style",
14516
+ "ui.startupVisual": "Startup visual",
14517
+ "ui.startupLogo": "Startup logo",
14518
+ "ui.startupLogoText": "Startup logo text",
14519
+ "ui.startupLogoFont": "Startup logo font",
14520
+ "ui.startupLogoShadowDirection": "Startup logo shadow direction",
14521
+ "ui.startupLogoColorStyle": "Startup logo color style",
14522
+ "ui.startupVisualOnSessionStart": "Startup on session start",
14523
+ "ui.customBrandEnabled": "Custom brand",
14524
+ "ui.customBrandText": "Custom brand text",
14525
+ "ui.customBrandBaseVisual": "Custom brand base visual",
14526
+ "interactiveClarificationEnabled": "Interactive clarification",
14527
+ "maxClarificationQuestions": "Max clarification questions",
14528
+ "planning.depth": "Planning depth",
14529
+ "planning.clarificationMode": "Planning clarification mode",
14530
+ "planning.interactiveClarificationEnabled": "Interactive clarification",
14531
+ "planning.maxClarificationQuestions": "Max clarification questions",
14532
+ "planning.clarificationTiming": "Planning clarification timing",
14533
+ "planning.maxTokens": "Planning token budget",
14534
+ "planning.maxRuntimeHours": "Planning runtime budget",
14535
+ "standard.allowSubagents": "Standard sub-agents",
14536
+ "standard.subagentScope": "Standard sub-agent scope",
14537
+ "standard.todoTriggerMode": "To Do trigger mode",
14538
+ "standard.clarificationMode": "Standard clarification mode",
14539
+ "standard.interactiveClarificationEnabled": "Standard interactive clarification",
14540
+ "standard.maxClarificationQuestions": "Standard max clarification questions",
14541
+ "standard.clarificationTiming": "Standard clarification timing",
14542
+ "standard.maxTokens": "Standard token budget",
14543
+ "standard.enabled": "Standard Mode",
14544
+ "subagents.enabled": "Sub-agents",
14545
+ "subagents.activityIndicatorEnabled": "Sub-agent activity indicator",
14546
+ "subagents.allowBackgroundSubagents": "Background sub-agents",
14547
+ "subagents.editConcurrencyMode": "Sub-agent edit concurrency mode",
14548
+ "subagents.planningOrchestrationPolicy": "Planning orchestration policy",
14549
+ "missions.enabled": "Mission Mode",
14550
+ "missions.defaultAutonomy": "Mission default autonomy",
14551
+ "missions.subagentPolicy": "Mission sub-agent policy",
14552
+ "missions.planningDepth": "Mission planning depth",
14553
+ "missions.clarificationMode": "Mission clarification mode",
14554
+ "missions.interactiveClarificationEnabled": "Mission interactive clarification",
14555
+ "missions.maxClarificationQuestions": "Mission max clarification questions",
14556
+ "missions.clarificationTiming": "Mission clarification timing",
14557
+ "missions.maxTokens": "Mission token budget",
14558
+ "missions.maxRuntimeHours": "Mission runtime budget",
14559
+ "missions.checkpointIntervalMinutes": "Mission checkpoint interval",
14560
+ "missions.heartbeatEnabled": "Mission heartbeat",
14561
+ "missions.watchdogEnabled": "Mission watchdog",
14562
+ "missions.watchdogStaleMinutes": "Mission watchdog stale minutes",
14563
+ "missions.missionHistoryLimit": "Mission history limit",
14564
+ "context.autoCompactionEnabled": "Workflow auto trigger",
14565
+ "context.compactionTriggerPercent": "Workflow trigger percent",
14566
+ "context.compactionCooldownMinutes": "Compaction cooldown",
14567
+ "context.customCompactionReserveTokens": "Custom compaction reserve tokens",
14568
+ "context.customCompactionKeepRecentTokens": "Custom compaction keep-recent tokens",
14569
+ "workflow.validationRetryMode": "Validation retry mode",
14570
+ "workflow.planHistoryLimit": "Plan history limit",
14571
+ "workflow.planShowProgressBar": "Plan progress bar",
14572
+ "safety.repoLockEnabled": "Project Repo Lock",
14573
+ };
14574
+ if (labels[setting]) return labels[setting];
14575
+ const parts = setting.split(".");
14576
+ return humanizeWorkflowSettingSegment(parts[parts.length - 1] || setting);
14577
+ }
14578
+
14579
+ function workflowSettingDisplayValue(setting: string, value: string): string {
14580
+ const clean = value.trim().replace(/\s+/g, " ");
14581
+ if (setting === "ui.editorHintContrast") {
14582
+ return workflowEditorHintContrastLabel(parseEditorHintContrast(clean) ?? "normal");
14583
+ }
14584
+ if (clean === "true") {
14585
+ return /^ui\.show.*Hint$/.test(setting) ? "shown" : "enabled";
14586
+ }
14587
+ if (clean === "false") {
14588
+ return /^ui\.show.*Hint$/.test(setting) ? "hidden" : "disabled";
14589
+ }
14590
+ return clean
14591
+ .replace(/_/g, " ")
14592
+ .replace(/\bpi\b/gi, "Pi")
14593
+ .replace(/\w\S*/g, (word) => word === "Pi" || word.toUpperCase() === "API" ? word : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());
14594
+ }
14595
+
14596
+ function workflowFriendlyNotification(message: string, level?: "info" | "warning" | "error"): string {
14597
+ if (level !== "info") return message;
14598
+ let text = message.replace(/\s+in\s+\/\S+/g, "").replace(/\s+/g, " ").trim();
14599
+ const settingMatch = text.match(/^([A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z0-9_]+)*)\s+set to\s+([^.;]+)([.;]?.*)$/);
14600
+ if (settingMatch) {
14601
+ const [, setting, value, tail = ""] = settingMatch;
14602
+ const label = workflowSettingDisplayLabel(setting);
14603
+ const displayValue = workflowSettingDisplayValue(setting, value);
14604
+ const suffix = tail.replace(/^[.;]\s*/, "").trim();
14605
+ return `${label} set to ${displayValue}.${suffix ? ` ${suffix}` : ""}`;
14606
+ }
14607
+ return text.charAt(0).toUpperCase() + text.slice(1);
14608
+ }
14609
+
14610
+ function workflowUiNotify(ctx: ExtensionContext, message: string, level?: "info" | "warning" | "error"): void {
14611
+ ctx.ui.notify(workflowFriendlyNotification(message, level), level);
14612
+ }
14613
+
14452
14614
  async function showPlanningSettingsMenu(ctx: ExtensionContext) {
14453
14615
  if (!ctx.hasUI) return show(pi, renderFullWorkflowSettings(loadWorkflowSettings(ctx.cwd)));
14454
14616
  while (ctx.hasUI) {
@@ -14456,7 +14618,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14456
14618
  if (!choice || choice === "Back") return;
14457
14619
  if (choice === "Set planning.depth") {
14458
14620
  const depth = parsePlanningDepth((await ctx.ui.select("Planning depth", ["fast", "standard", "deep", "maximum"])) ?? "");
14459
- if (depth) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.depth = depth; }); ctx.ui.notify(`planning.depth set to ${depth} in ${r.file}`, "info"); }
14621
+ if (depth) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.depth = depth; }); workflowUiNotify(ctx, `planning.depth set to ${depth} in ${r.file}`, "info"); }
14460
14622
  } else if (choice === "List Current Settings") {
14461
14623
  const s = loadWorkflowSettings(ctx.cwd);
14462
14624
  show(pi, `# Planning Settings\n\nplanning.depth: ${s.planning.depth}`);
@@ -14471,13 +14633,13 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14471
14633
  if (!choice || choice === "Back") return;
14472
14634
  if (choice === "Set clarificationMode") {
14473
14635
  const mode = parseClarificationMode((await ctx.ui.select("Clarification mode", ["auto", "always_for_nontrivial", "never"])) ?? "");
14474
- if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.clarificationMode = mode; }); ctx.ui.notify(`planning.clarificationMode set to ${mode} in ${r.file}`, "info"); }
14636
+ if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.clarificationMode = mode; }); workflowUiNotify(ctx, `planning.clarificationMode set to ${mode} in ${r.file}`, "info"); }
14475
14637
  } else if (choice === "Set interactiveClarificationEnabled") {
14476
14638
  const enabled = await chooseBool(ctx, "Interactive clarification enabled?");
14477
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.interactiveClarificationEnabled = enabled; }); ctx.ui.notify(`interactiveClarificationEnabled set to ${enabled} in ${r.file}`, "info"); }
14639
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.interactiveClarificationEnabled = enabled; }); workflowUiNotify(ctx, `interactiveClarificationEnabled set to ${enabled} in ${r.file}`, "info"); }
14478
14640
  } else if (choice === "Set maxClarificationQuestions") {
14479
14641
  const count = parsePositiveInt((await ctx.ui.select("Max clarification questions", ["1", "2", "3", "4", "5"])) ?? "");
14480
- if (count) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxClarificationQuestions = count; }); ctx.ui.notify(`maxClarificationQuestions set to ${count} in ${r.file}`, "info"); }
14642
+ if (count) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxClarificationQuestions = count; }); workflowUiNotify(ctx, `maxClarificationQuestions set to ${count} in ${r.file}`, "info"); }
14481
14643
  } else if (choice === "List Current Settings") {
14482
14644
  const s = loadWorkflowSettings(ctx.cwd);
14483
14645
  show(pi, `# Clarification Settings\n\nClarification Mode: ${s.planning.clarificationMode}\nInteractive Clarification: ${s.planning.interactiveClarificationEnabled !== false ? "enabled" : "disabled"}\nMax Clarification Questions: ${s.planning.maxClarificationQuestions}`);
@@ -14493,11 +14655,11 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14493
14655
  if (!choice || choice === "Back") return;
14494
14656
  if (choice.endsWith("Policy")) {
14495
14657
  const policy = parseSubagentPolicy((await ctx.ui.select(`${label} policy`, ["off", "auto", "deep", "maximum", "forced"])) ?? "");
14496
- if (policy) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.subagents as typeof s.subagents & Record<string, string>)[keys.policyKey] = policy; }); ctx.ui.notify(`subagents.${keys.policyKey} set to ${policy} in ${r.file}`, "info"); }
14658
+ if (policy) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.subagents as typeof s.subagents & Record<string, string>)[keys.policyKey] = policy; }); workflowUiNotify(ctx, `subagents.${keys.policyKey} set to ${policy} in ${r.file}`, "info"); }
14497
14659
  } else {
14498
14660
  const key = choice.includes("Deep") ? keys.deepKey : keys.maximumKey;
14499
14661
  const count = parsePositiveInt((await ctx.ui.select(`${label} ${choice.includes("Deep") ? "deep" : "maximum / forced"} workers`, ["0", "1", "2", "3", "4", "5", "6", "7", "8"])) ?? "");
14500
- if (count !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.subagents as typeof s.subagents & Record<string, number>)[key] = count; }); ctx.ui.notify(`subagents.${key} set to ${count} in ${r.file}. Forced policy uses this phase's Maximum / Forced worker count.`, "info"); }
14662
+ if (count !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.subagents as typeof s.subagents & Record<string, number>)[key] = count; }); workflowUiNotify(ctx, `subagents.${key} set to ${count} in ${r.file}. Forced policy uses this phase's Maximum / Forced worker count.`, "info"); }
14501
14663
  }
14502
14664
  }
14503
14665
  }
@@ -14515,7 +14677,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14515
14677
  const standard = s.standard as typeof s.standard & { subagents?: Record<string, boolean | number | string | undefined> };
14516
14678
  standard.subagents = { ...(standard.subagents ?? {}), [keys.policyKey]: policy };
14517
14679
  });
14518
- ctx.ui.notify(`standard.subagents.${keys.policyKey} set to ${policy} in ${r.file}`, "info");
14680
+ workflowUiNotify(ctx, `standard.subagents.${keys.policyKey} set to ${policy} in ${r.file}`, "info");
14519
14681
  }
14520
14682
  } else {
14521
14683
  const key = choice.includes("Deep") ? keys.deepKey : keys.maximumKey;
@@ -14525,7 +14687,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14525
14687
  const standard = s.standard as typeof s.standard & { subagents?: Record<string, boolean | number | string | undefined> };
14526
14688
  standard.subagents = { ...(standard.subagents ?? {}), [key]: count };
14527
14689
  });
14528
- ctx.ui.notify(`standard.subagents.${key} set to ${count} in ${r.file}. Forced policy uses this Standard phase's Maximum / Forced worker count.`, "info");
14690
+ workflowUiNotify(ctx, `standard.subagents.${key} set to ${count} in ${r.file}. Forced policy uses this Standard phase's Maximum / Forced worker count.`, "info");
14529
14691
  }
14530
14692
  }
14531
14693
  }
@@ -14544,7 +14706,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14544
14706
  const standard = s.standard as typeof s.standard & { subagents?: Record<string, boolean | number | string | undefined> };
14545
14707
  standard.subagents = { ...(standard.subagents ?? {}), [key]: enabled };
14546
14708
  });
14547
- ctx.ui.notify(`standard.subagents.${key} set to ${enabled} in ${r.file}`, "info");
14709
+ workflowUiNotify(ctx, `standard.subagents.${key} set to ${enabled} in ${r.file}`, "info");
14548
14710
  }
14549
14711
  }
14550
14712
  }
@@ -14561,7 +14723,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14561
14723
  const standard = s.standard as typeof s.standard & { subagents?: Record<string, boolean | number | string | undefined> };
14562
14724
  standard.subagents = { ...(standard.subagents ?? {}), [key]: enabled };
14563
14725
  });
14564
- ctx.ui.notify(`standard.subagents.${key} set to ${enabled} in ${r.file}`, "info");
14726
+ workflowUiNotify(ctx, `standard.subagents.${key} set to ${enabled} in ${r.file}`, "info");
14565
14727
  }
14566
14728
  }
14567
14729
  }
@@ -14573,7 +14735,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14573
14735
  if (!choice || choice === "Back") return;
14574
14736
  if (choice === "Enable / Disable Standard Sub-agents") {
14575
14737
  const enabled = await chooseBool(ctx, "standard.allowSubagents?");
14576
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.allowSubagents = enabled; }); ctx.ui.notify(`standard.allowSubagents set to ${enabled} in ${r.file}`, "info"); }
14738
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.allowSubagents = enabled; }); workflowUiNotify(ctx, `standard.allowSubagents set to ${enabled} in ${r.file}`, "info"); }
14577
14739
  } else if (choice === "Standard Planning / Research Policy / Workers") await showStandardSubagentPhaseSettingsMenu(ctx, "Planning", "Standard Planning / Research");
14578
14740
  else if (choice === "Standard Execution Policy / Workers") await showStandardSubagentPhaseSettingsMenu(ctx, "Execution", "Standard Execution");
14579
14741
  else if (choice === "Standard Repair Policy / Workers") await showStandardSubagentPhaseSettingsMenu(ctx, "Repair", "Standard Repair");
@@ -14581,15 +14743,15 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14581
14743
  else if (choice === "Standard Validation Policy / Workers") await showStandardSubagentPhaseSettingsMenu(ctx, "Validation", "Standard Validation");
14582
14744
  else if (choice === "Agent Scope") {
14583
14745
  const scope = parseWorkflowAgentScope((await ctx.ui.select("Standard agent scope", ["user", "project", "both"])) ?? "");
14584
- if (scope) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.subagentScope = scope; }); ctx.ui.notify(`standard.subagentScope set to ${scope} in ${r.file}`, "info"); }
14746
+ if (scope) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.subagentScope = scope; }); workflowUiNotify(ctx, `standard.subagentScope set to ${scope} in ${r.file}`, "info"); }
14585
14747
  } else if (choice === "Auto-use Toggles") await showStandardSubagentAutoUseMenu(ctx);
14586
14748
  else if (choice === "Parallel Agent Settings") await showStandardParallelismSettingsMenu(ctx);
14587
14749
  else if (choice === "Activity Indicator") {
14588
14750
  const enabled = await chooseBool(ctx, "subagents.activityIndicatorEnabled?");
14589
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.activityIndicatorEnabled = enabled; }); ctx.ui.notify(`subagents.activityIndicatorEnabled set to ${enabled} in ${r.file}`, "info"); renderWorkflowSubagentActivity(ctx); }
14751
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.activityIndicatorEnabled = enabled; }); workflowUiNotify(ctx, `subagents.activityIndicatorEnabled set to ${enabled} in ${r.file}`, "info"); renderWorkflowSubagentActivity(ctx); }
14590
14752
  } else if (choice === "List Current Settings") {
14591
14753
  const s = loadWorkflowSettings(ctx.cwd);
14592
- show(pi, `# Plan Sub-agents / Workers\n\n${renderPlanSubagentWorkerSettings(s)}`);
14754
+ show(pi, `# Standard Sub-agents / Workers\n\nSub-agents: ${s.standard.allowSubagents !== false ? "enabled" : "disabled"}\nAgent Scope: ${s.standard.subagentScope ?? "user"}\nActivity Indicator: ${s.subagents.activityIndicatorEnabled !== false ? "enabled" : "disabled"}\nAuto-use Planning: ${s.standard.subagents?.autoUseDuringPlanning !== false ? "on" : "off"}\nAuto-use Execution: ${s.standard.subagents?.autoUseDuringExecution !== false ? "on" : "off"}\nAuto-use Repair: ${s.standard.subagents?.autoUseDuringRepair !== false ? "on" : "off"}\nAuto-use Review: ${s.standard.subagents?.autoUseDuringReview !== false ? "on" : "off"}\nAuto-use Validation: ${s.standard.subagents?.autoUseDuringValidation !== false ? "on" : "off"}`);
14593
14755
  }
14594
14756
  }
14595
14757
  }
@@ -14601,11 +14763,11 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14601
14763
  if (!choice || choice === "Back") return;
14602
14764
  if (choice === "Mission Planning Policy") {
14603
14765
  const policy = parseSubagentPolicy((await ctx.ui.select("Mission planning policy", ["off", "auto", "deep", "maximum", "forced"])) ?? "");
14604
- if (policy) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.subagentPolicy = policy; }); ctx.ui.notify(`missions.subagentPolicy set to ${policy} in ${r.file}`, "info"); }
14766
+ if (policy) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.subagentPolicy = policy; }); workflowUiNotify(ctx, `missions.subagentPolicy set to ${policy} in ${r.file}`, "info"); }
14605
14767
  } else {
14606
14768
  const key = choice.includes("Deep") ? "minWorkersForDeep" : "minWorkersForMaximum";
14607
14769
  const count = parsePositiveInt((await ctx.ui.select(choice, ["0", "1", "2", "3", "4", "5", "6", "7", "8"])) ?? "");
14608
- if (count !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, number>)[key] = count; }); ctx.ui.notify(`missions.${key} set to ${count} in ${r.file}. Forced mission planning uses Mission Planning Maximum / Forced Workers.`, "info"); }
14770
+ if (count !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, number>)[key] = count; }); workflowUiNotify(ctx, `missions.${key} set to ${count} in ${r.file}. Forced mission planning uses Mission Planning Maximum / Forced Workers.`, "info"); }
14609
14771
  }
14610
14772
  }
14611
14773
  }
@@ -14618,7 +14780,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14618
14780
  const keyMap: Record<string, string> = { "Planning Auto-use": "autoUseDuringPlanning", "Execution Auto-use": "autoUseDuringExecution", "Repair Auto-use": "autoUseDuringRepair", "Review Auto-use": "autoUseDuringReview", "Validation Auto-use": "autoUseDuringValidation" };
14619
14781
  const key = keyMap[choice];
14620
14782
  const enabled = await chooseBool(ctx, `${key}?`);
14621
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.subagents as typeof s.subagents & Record<string, boolean>)[key] = enabled; }); ctx.ui.notify(`subagents.${key} set to ${enabled} in ${r.file}`, "info"); }
14783
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.subagents as typeof s.subagents & Record<string, boolean>)[key] = enabled; }); workflowUiNotify(ctx, `subagents.${key} set to ${enabled} in ${r.file}`, "info"); }
14622
14784
  }
14623
14785
  }
14624
14786
 
@@ -14629,7 +14791,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14629
14791
  if (!choice || choice === "Back") return;
14630
14792
  if (choice === "Enable / Disable Sub-agents") {
14631
14793
  const enabled = await chooseBool(ctx, "subagents.enabled?");
14632
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.enabled = enabled; }); ctx.ui.notify(`subagents.enabled set to ${enabled} in ${r.file}`, "info"); }
14794
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.enabled = enabled; }); workflowUiNotify(ctx, `subagents.enabled set to ${enabled} in ${r.file}`, "info"); }
14633
14795
  } else if (choice === "Planning Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Planning", "Shared Planning");
14634
14796
  else if (choice === "Execution Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Execution", "Shared Execution");
14635
14797
  else if (choice === "Repair Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Repair", "Shared Repair");
@@ -14639,10 +14801,10 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14639
14801
  else if (choice === "Parallel Agent Settings") await showParallelismSettingsMenu(ctx);
14640
14802
  else if (choice === "Background Sub-agents") {
14641
14803
  const enabled = await chooseBool(ctx, "subagents.allowBackgroundSubagents?");
14642
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.allowBackgroundSubagents = enabled; }); ctx.ui.notify(`subagents.allowBackgroundSubagents set to ${enabled} in ${r.file}. Background sub-agents run in Planning/Review/Validation phases without blocking the parent.`, "info"); }
14804
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.allowBackgroundSubagents = enabled; }); workflowUiNotify(ctx, `subagents.allowBackgroundSubagents set to ${enabled} in ${r.file}. Background sub-agents run in Planning/Review/Validation phases without blocking the parent.`, "info"); }
14643
14805
  } else if (choice === "Activity Indicator") {
14644
14806
  const enabled = await chooseBool(ctx, "subagents.activityIndicatorEnabled?");
14645
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.activityIndicatorEnabled = enabled; }); ctx.ui.notify(`subagents.activityIndicatorEnabled set to ${enabled} in ${r.file}`, "info"); renderWorkflowSubagentActivity(ctx); }
14807
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.activityIndicatorEnabled = enabled; }); workflowUiNotify(ctx, `subagents.activityIndicatorEnabled set to ${enabled} in ${r.file}`, "info"); renderWorkflowSubagentActivity(ctx); }
14646
14808
  } else if (choice === "List Current Settings") {
14647
14809
  const s = loadWorkflowSettings(ctx.cwd);
14648
14810
  show(pi, `# Shared Sub-agents / Workers\n\nSub-agents: ${s.subagents.enabled !== false ? "enabled" : "disabled"}\nBackground Sub-agents: ${s.subagents.allowBackgroundSubagents === true ? "enabled" : "disabled"}\nActivity Indicator: ${s.subagents.activityIndicatorEnabled !== false ? "enabled" : "disabled"}\nAuto-use Planning: ${s.subagents.autoUseDuringPlanning !== false ? "on" : "off"}\nAuto-use Execution: ${s.subagents.autoUseDuringExecution !== false ? "on" : "off"}\nAuto-use Repair: ${s.subagents.autoUseDuringRepair !== false ? "on" : "off"}\nAuto-use Review: ${s.subagents.autoUseDuringReview !== false ? "on" : "off"}\nAuto-use Validation: ${s.subagents.autoUseDuringValidation !== false ? "on" : "off"}`);
@@ -14657,7 +14819,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14657
14819
  if (!choice || choice === "Back") return;
14658
14820
  if (choice === "Enable / Disable Sub-agents") {
14659
14821
  const enabled = await chooseBool(ctx, "subagents.enabled?");
14660
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.enabled = enabled; }); ctx.ui.notify(`subagents.enabled set to ${enabled} in ${r.file}`, "info"); }
14822
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.enabled = enabled; }); workflowUiNotify(ctx, `subagents.enabled set to ${enabled} in ${r.file}`, "info"); }
14661
14823
  } else if (choice === "Plan Planning Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Planning", "Plan Planning");
14662
14824
  else if (choice === "Plan Execution Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Execution", "Plan Execution");
14663
14825
  else if (choice === "Plan Repair Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Repair", "Plan Repair");
@@ -14667,10 +14829,10 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14667
14829
  else if (choice === "Parallel Agent Settings") await showParallelismSettingsMenu(ctx);
14668
14830
  else if (choice === "Activity Indicator") {
14669
14831
  const enabled = await chooseBool(ctx, "subagents.activityIndicatorEnabled?");
14670
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.activityIndicatorEnabled = enabled; }); ctx.ui.notify(`subagents.activityIndicatorEnabled set to ${enabled} in ${r.file}`, "info"); renderWorkflowSubagentActivity(ctx); }
14832
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.activityIndicatorEnabled = enabled; }); workflowUiNotify(ctx, `subagents.activityIndicatorEnabled set to ${enabled} in ${r.file}`, "info"); renderWorkflowSubagentActivity(ctx); }
14671
14833
  } else if (choice === "List Current Settings") {
14672
14834
  const s = loadWorkflowSettings(ctx.cwd);
14673
- show(pi, `# Standard Sub-agents / Workers\n\nSub-agents: ${s.standard.allowSubagents !== false ? "enabled" : "disabled"}\nAgent Scope: ${s.standard.subagentScope ?? "user"}\nActivity Indicator: ${s.subagents.activityIndicatorEnabled !== false ? "enabled" : "disabled"}\nAuto-use Planning: ${s.subagents.autoUseDuringPlanning !== false ? "on" : "off"}\nAuto-use Execution: ${s.subagents.autoUseDuringExecution !== false ? "on" : "off"}\nAuto-use Repair: ${s.subagents.autoUseDuringRepair !== false ? "on" : "off"}\nAuto-use Review: ${s.subagents.autoUseDuringReview !== false ? "on" : "off"}\nAuto-use Validation: ${s.subagents.autoUseDuringValidation !== false ? "on" : "off"}`);
14835
+ show(pi, `# Plan Sub-agents / Workers\n\n${renderPlanSubagentWorkerSettings(s)}`);
14674
14836
  }
14675
14837
  }
14676
14838
  }
@@ -14682,7 +14844,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14682
14844
  if (!choice || choice === "Back") return;
14683
14845
  if (choice === "Enable / Disable Sub-agents") {
14684
14846
  const enabled = await chooseBool(ctx, "subagents.enabled?");
14685
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.enabled = enabled; }); ctx.ui.notify(`subagents.enabled set to ${enabled} in ${r.file}`, "info"); }
14847
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.enabled = enabled; }); workflowUiNotify(ctx, `subagents.enabled set to ${enabled} in ${r.file}`, "info"); }
14686
14848
  } else if (choice === "Mission Planning Policy / Workers") await showMissionPlanningSubagentSettingsMenu(ctx);
14687
14849
  else if (choice === "Mission Execution Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Execution", "Mission Execution");
14688
14850
  else if (choice === "Mission Repair Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Repair", "Mission Repair");
@@ -14692,7 +14854,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14692
14854
  else if (choice === "Parallel Agent Settings") await showParallelismSettingsMenu(ctx);
14693
14855
  else if (choice === "Activity Indicator") {
14694
14856
  const enabled = await chooseBool(ctx, "subagents.activityIndicatorEnabled?");
14695
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.activityIndicatorEnabled = enabled; }); ctx.ui.notify(`subagents.activityIndicatorEnabled set to ${enabled} in ${r.file}`, "info"); renderWorkflowSubagentActivity(ctx); }
14857
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.activityIndicatorEnabled = enabled; }); workflowUiNotify(ctx, `subagents.activityIndicatorEnabled set to ${enabled} in ${r.file}`, "info"); renderWorkflowSubagentActivity(ctx); }
14696
14858
  } else if (choice === "List Current Settings") {
14697
14859
  const s = loadWorkflowSettings(ctx.cwd);
14698
14860
  show(pi, `# Mission Sub-agents / Workers\n\n${renderMissionSubagentWorkerSettings(s)}`);
@@ -14708,10 +14870,10 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14708
14870
  if (choice?.startsWith("Set allow") || choice === "Set requireParallelEditConflictProtection") {
14709
14871
  const key = choice.replace("Set ", "");
14710
14872
  const enabled = await chooseBool(ctx, `${key}?`);
14711
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.subagents as typeof s.subagents & Record<string, boolean>)[key] = enabled; }); ctx.ui.notify(`subagents.${key} set to ${enabled} in ${r.file}`, "info"); }
14873
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.subagents as typeof s.subagents & Record<string, boolean>)[key] = enabled; }); workflowUiNotify(ctx, `subagents.${key} set to ${enabled} in ${r.file}`, "info"); }
14712
14874
  } else if (choice === "Set editConcurrencyMode") {
14713
14875
  const mode = parseEditConcurrencyMode((await ctx.ui.select("Edit concurrency mode", ["sequential", "scoped", "blocked"])) ?? "");
14714
- if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.editConcurrencyMode = mode; }); ctx.ui.notify(`subagents.editConcurrencyMode set to ${mode} in ${r.file}`, "info"); }
14876
+ if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.editConcurrencyMode = mode; }); workflowUiNotify(ctx, `subagents.editConcurrencyMode set to ${mode} in ${r.file}`, "info"); }
14715
14877
  } else if (choice === "List Current Settings") {
14716
14878
  const s = loadWorkflowSettings(ctx.cwd);
14717
14879
  show(pi, `# Parallelism Settings\n\nParallel Read-Only: ${s.subagents.allowParallelReadOnly !== false ? "enabled" : "disabled"}\nParallel Planning: ${s.subagents.allowParallelPlanning !== false ? "enabled" : "disabled"}\nParallel Execution: ${s.subagents.allowParallelExecution !== false ? "enabled" : "disabled"}\nParallel Repair: ${s.subagents.allowParallelRepair !== false ? "enabled" : "disabled"}\nParallel Review: ${s.subagents.allowParallelReview !== false ? "enabled" : "disabled"}\nParallel Validation: ${s.subagents.allowParallelValidation !== false ? "enabled" : "disabled"}\nParallel File Edits: ${s.subagents.allowParallelEdits !== false ? "enabled" : "disabled"}\nEdit Concurrency Mode: ${s.subagents.editConcurrencyMode ?? "sequential"}\nConflict Protection: ${s.subagents.requireParallelEditConflictProtection !== false ? "enabled" : "disabled"}`);
@@ -14723,7 +14885,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14723
14885
  const models = ctx.modelRegistry.getAll();
14724
14886
  const providers = [...new Set(models.map((m) => m.provider))].sort();
14725
14887
  if (providers.length === 0) {
14726
- ctx.ui.notify("No models are available in the model registry.", "error");
14888
+ workflowUiNotify(ctx, "No models are available in the model registry.", "error");
14727
14889
  return undefined;
14728
14890
  }
14729
14891
  const providerChoice = await ctx.ui.select(`${title}: select provider`, [...providers, "Custom provider name"]);
@@ -14737,7 +14899,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14737
14899
  }
14738
14900
  const providerModels = models.filter((m) => m.provider === providerChoice).map((m) => m.id).sort();
14739
14901
  if (providerModels.length === 0) {
14740
- ctx.ui.notify(`No models found for provider ${providerChoice}.`, "error");
14902
+ workflowUiNotify(ctx, `No models found for provider ${providerChoice}.`, "error");
14741
14903
  return undefined;
14742
14904
  }
14743
14905
  const modelChoice = await ctx.ui.select(`${title}: select model`, providerModels.map((model) => `${providerChoice}/${model}`));
@@ -14764,7 +14926,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14764
14926
  s.context.compactionModelProvider = provider;
14765
14927
  s.context.compactionModel = "";
14766
14928
  });
14767
- ctx.ui.notify(provider ? `Compaction provider preference stored as ${provider} in ${result.file}. Trigger behavior was not changed.` : `Compaction provider reset to Pi default in ${result.file}. Trigger behavior was not changed.`, "info");
14929
+ workflowUiNotify(ctx, provider ? `Compaction provider preference stored as ${provider} in ${result.file}. Trigger behavior was not changed.` : `Compaction provider reset to Pi default in ${result.file}. Trigger behavior was not changed.`, "info");
14768
14930
  }
14769
14931
 
14770
14932
  async function selectCompactionModel(ctx: ExtensionContext) {
@@ -14777,7 +14939,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14777
14939
  s.context.compactionModelProvider = "";
14778
14940
  s.context.compactionModel = "";
14779
14941
  });
14780
- ctx.ui.notify(`Compaction summary model reset to Pi default in ${result.file}. Trigger behavior was not changed.`, "info");
14942
+ workflowUiNotify(ctx, `Compaction summary model reset to Pi default in ${result.file}. Trigger behavior was not changed.`, "info");
14781
14943
  return;
14782
14944
  }
14783
14945
 
@@ -14788,7 +14950,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14788
14950
  selectedProvider = chosen;
14789
14951
  }
14790
14952
  if (!selectedProvider) {
14791
- ctx.ui.notify("Select a custom compaction provider before selecting a custom model.", "warning");
14953
+ workflowUiNotify(ctx, "Select a custom compaction provider before selecting a custom model.", "warning");
14792
14954
  return;
14793
14955
  }
14794
14956
  const providerModels = ctx.modelRegistry.getAll().filter((m) => m.provider === selectedProvider).map((m) => m.id).sort();
@@ -14800,7 +14962,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14800
14962
  s.context.compactionModelProvider = selectedProvider;
14801
14963
  s.context.compactionModel = model;
14802
14964
  });
14803
- ctx.ui.notify(`Compaction model preference stored as ${selectedProvider}/${model} in ${result.file}. Trigger behavior was not changed.`, "info");
14965
+ workflowUiNotify(ctx, `Compaction model preference stored as ${selectedProvider}/${model} in ${result.file}. Trigger behavior was not changed.`, "info");
14804
14966
  }
14805
14967
 
14806
14968
  async function selectCompactionAgent(ctx: ExtensionContext) {
@@ -14814,7 +14976,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14814
14976
  s.context.compactionAgent = agent;
14815
14977
  s.context.customCompactionEnabled = true;
14816
14978
  });
14817
- ctx.ui.notify(`Compaction agent stored as ${agent} in ${result.file}. Current releases keep Pi default fallback behavior for agent-routed compaction.`, "info");
14979
+ workflowUiNotify(ctx, `Compaction agent stored as ${agent} in ${result.file}. Current releases keep Pi default fallback behavior for agent-routed compaction.`, "info");
14818
14980
  }
14819
14981
 
14820
14982
  async function showCompactionSettingsMenu(ctx: ExtensionContext) {
@@ -14833,53 +14995,53 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14833
14995
  if (trigger === "Pi default") delete s.context.autoCompactionEnabled;
14834
14996
  else s.context.autoCompactionEnabled = trigger === "Enabled";
14835
14997
  });
14836
- ctx.ui.notify(`Workflow auto trigger set to ${trigger.toLowerCase()} in ${r.file}.`, "info");
14998
+ workflowUiNotify(ctx, `Workflow auto trigger set to ${trigger.toLowerCase()} in ${r.file}.`, "info");
14837
14999
  } else if (choice === "Workflow Trigger Percent") {
14838
15000
  const mode = await ctx.ui.select("Workflow Trigger Percent", ["Pi default", "Custom percent", "Back"]);
14839
15001
  if (!mode || mode === "Back") continue;
14840
15002
  if (mode === "Pi default") {
14841
15003
  const r = updateSettings(ctx.cwd, undefined, (s) => { delete s.context.compactionTriggerPercent; });
14842
- ctx.ui.notify(`Workflow compaction trigger percent override removed in ${r.file}; Pi native trigger formula remains in control.`, "info");
15004
+ workflowUiNotify(ctx, `Workflow compaction trigger percent override removed in ${r.file}; Pi native trigger formula remains in control.`, "info");
14843
15005
  } else {
14844
15006
  const raw = String((await ctx.ui.input("Workflow compaction trigger percent (50-95)", String(compactionTriggerPercentOverride(loadWorkflowSettings(ctx.cwd)) ?? 85))) ?? "").trim();
14845
15007
  const count = Number(raw);
14846
- if (Number.isInteger(count) && count >= 50 && count <= 95) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.compactionTriggerPercent = count; }); ctx.ui.notify(`Workflow compaction trigger percent set to ${count}% in ${r.file}`, "info"); }
14847
- else ctx.ui.notify("Trigger percent must be an integer from 50 to 95.", "error");
15008
+ if (Number.isInteger(count) && count >= 50 && count <= 95) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.compactionTriggerPercent = count; }); workflowUiNotify(ctx, `Workflow compaction trigger percent set to ${count}% in ${r.file}`, "info"); }
15009
+ else workflowUiNotify(ctx, "Trigger percent must be an integer from 50 to 95.", "error");
14848
15010
  }
14849
15011
  } else if (choice === "Workflow Trigger Cooldown") {
14850
15012
  const mode = await ctx.ui.select("Workflow Trigger Cooldown", ["Pi default", "Custom cooldown", "Back"]);
14851
15013
  if (!mode || mode === "Back") continue;
14852
15014
  if (mode === "Pi default") {
14853
15015
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.compactionCooldownMinutes = 5; });
14854
- ctx.ui.notify(`Compaction cooldown reset to Pi default (5 minutes) in ${r.file}.`, "info");
15016
+ workflowUiNotify(ctx, `Compaction cooldown reset to Pi default (5 minutes) in ${r.file}.`, "info");
14855
15017
  } else {
14856
15018
  const count = Number((await ctx.ui.input("Minimum minutes between Workflow Suite proactive compaction attempts", String(compactionCooldownMinutes(loadWorkflowSettings(ctx.cwd)))) ?? ""));
14857
- if (Number.isInteger(count) && count >= 0 && count <= 240) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.compactionCooldownMinutes = count; }); ctx.ui.notify(`Compaction cooldown set to ${count} minute(s) in ${r.file}. This is the minimum wait between proactive compaction attempts, not a delay before compaction starts.`, "info"); }
14858
- else ctx.ui.notify("Cooldown must be an integer from 0 to 240 minutes.", "error");
15019
+ if (Number.isInteger(count) && count >= 0 && count <= 240) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.compactionCooldownMinutes = count; }); workflowUiNotify(ctx, `Compaction cooldown set to ${count} minute(s) in ${r.file}. This is the minimum wait between proactive compaction attempts, not a delay before compaction starts.`, "info"); }
15020
+ else workflowUiNotify(ctx, "Cooldown must be an integer from 0 to 240 minutes.", "error");
14859
15021
  }
14860
15022
  } else if (choice === "Custom Reserve Tokens") {
14861
15023
  const mode = await ctx.ui.select("Custom Reserve Tokens", ["Pi default", "Custom reserve tokens", "Back"]);
14862
15024
  if (!mode || mode === "Back") continue;
14863
15025
  if (mode === "Pi default") {
14864
15026
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.customCompactionReserveTokens = DEFAULT_PI_COMPACTION_RESERVE_TOKENS; });
14865
- ctx.ui.notify(`Custom compaction reserve tokens reset to Pi default (${DEFAULT_PI_COMPACTION_RESERVE_TOKENS.toLocaleString()}) in ${r.file}`, "info");
15027
+ workflowUiNotify(ctx, `Custom compaction reserve tokens reset to Pi default (${DEFAULT_PI_COMPACTION_RESERVE_TOKENS.toLocaleString()}) in ${r.file}`, "info");
14866
15028
  } else {
14867
15029
  const raw = String((await ctx.ui.input("Custom compaction reserve tokens (4096-65536)", String(customCompactionReserveTokens(loadWorkflowSettings(ctx.cwd)))) ?? "")).trim();
14868
15030
  const count = Number(raw);
14869
- if (Number.isInteger(count) && count >= 4096 && count <= 65536) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.customCompactionReserveTokens = count; }); ctx.ui.notify(`Custom compaction reserve tokens set to ${count.toLocaleString()} in ${r.file}`, "info"); }
14870
- else ctx.ui.notify("Reserve tokens must be an integer from 4096 to 65536.", "error");
15031
+ if (Number.isInteger(count) && count >= 4096 && count <= 65536) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.customCompactionReserveTokens = count; }); workflowUiNotify(ctx, `Custom compaction reserve tokens set to ${count.toLocaleString()} in ${r.file}`, "info"); }
15032
+ else workflowUiNotify(ctx, "Reserve tokens must be an integer from 4096 to 65536.", "error");
14871
15033
  }
14872
15034
  } else if (choice === "Custom Keep Recent Tokens") {
14873
15035
  const mode = await ctx.ui.select("Custom Keep Recent Tokens", ["Pi default", "Custom keep-recent tokens", "Back"]);
14874
15036
  if (!mode || mode === "Back") continue;
14875
15037
  if (mode === "Pi default") {
14876
15038
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.customCompactionKeepRecentTokens = DEFAULT_PI_COMPACTION_KEEP_RECENT_TOKENS; });
14877
- ctx.ui.notify(`Custom compaction keep-recent tokens reset to Pi default (${DEFAULT_PI_COMPACTION_KEEP_RECENT_TOKENS.toLocaleString()}) in ${r.file}`, "info");
15039
+ workflowUiNotify(ctx, `Custom compaction keep-recent tokens reset to Pi default (${DEFAULT_PI_COMPACTION_KEEP_RECENT_TOKENS.toLocaleString()}) in ${r.file}`, "info");
14878
15040
  } else {
14879
15041
  const raw = String((await ctx.ui.input("Custom compaction keep-recent tokens (1000-200000)", String(customCompactionKeepRecentTokens(loadWorkflowSettings(ctx.cwd)))) ?? "")).trim();
14880
15042
  const count = Number(raw);
14881
- if (Number.isInteger(count) && count >= 1000 && count <= 200000) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.customCompactionKeepRecentTokens = count; }); ctx.ui.notify(`Custom compaction keep-recent tokens set to ${count.toLocaleString()} in ${r.file}`, "info"); }
14882
- else ctx.ui.notify("Keep-recent tokens must be an integer from 1000 to 200000.", "error");
15043
+ if (Number.isInteger(count) && count >= 1000 && count <= 200000) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.customCompactionKeepRecentTokens = count; }); workflowUiNotify(ctx, `Custom compaction keep-recent tokens set to ${count.toLocaleString()} in ${r.file}`, "info"); }
15044
+ else workflowUiNotify(ctx, "Keep-recent tokens must be an integer from 1000 to 200000.", "error");
14883
15045
  }
14884
15046
  } else if (choice === "List Current Settings") {
14885
15047
  const s = loadWorkflowSettings(ctx.cwd);
@@ -14930,7 +15092,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14930
15092
  }
14931
15093
  });
14932
15094
  await reapplyStandardRouteIfStandardMode(ctx, true);
14933
- ctx.ui.notify(`Standard model source set to ${source} in ${result.file}`, "info");
15095
+ workflowUiNotify(ctx, `Standard model source set to ${source} in ${result.file}`, "info");
14934
15096
  } else if (choice === "Standard Model Role") {
14935
15097
  const role = parseStandardModelRole((await ctx.ui.select("Standard model role", ["Current Pi model", "Planner", "Executor", "Reviewer", "Validator"])) ?? "");
14936
15098
  if (!role) continue;
@@ -14944,7 +15106,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14944
15106
  }
14945
15107
  });
14946
15108
  await reapplyStandardRouteIfStandardMode(ctx, true);
14947
- ctx.ui.notify(`Standard model role set to ${workflowRoleLabel(role)} in ${result.file}`, "info");
15109
+ workflowUiNotify(ctx, `Standard model role set to ${workflowRoleLabel(role)} in ${result.file}`, "info");
14948
15110
  } else if (choice === "Configure Standard Planner") await configureStandardRoleModel(ctx, "planner");
14949
15111
  else if (choice === "Configure Standard Executor") await configureStandardRoleModel(ctx, "executor");
14950
15112
  else if (choice === "Configure Standard Reviewer") await configureStandardRoleModel(ctx, "reviewer");
@@ -14965,10 +15127,10 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14965
15127
  const options = key === "maxValidationRetriesPerPlan" ? ["0", "1", "2", "3", "4", "5", "10"] : ["0", "1", "2", "4", "8", "12", "20", "50", "100"];
14966
15128
  const raw = await ctx.ui.select(setting, options);
14967
15129
  const count = raw === undefined ? undefined : Number(raw);
14968
- if (Number.isInteger(count) && count >= 0 && count <= max) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.workflow as typeof s.workflow & Record<string, number>)[key] = count; }); ctx.ui.notify(`workflow.${key} set to ${count} in ${r.file}`, "info"); }
15130
+ if (Number.isInteger(count) && count >= 0 && count <= max) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.workflow as typeof s.workflow & Record<string, number>)[key] = count; }); workflowUiNotify(ctx, `workflow.${key} set to ${count} in ${r.file}`, "info"); }
14969
15131
  } else if (setting === "Validation Retry Mode") {
14970
15132
  const mode = parseValidationRetryMode((await ctx.ui.select("Validation retry mode", ["off", "safe_only", "aggressive_within_scope"])) ?? "");
14971
- if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.validationRetryMode = mode; }); ctx.ui.notify(`workflow.validationRetryMode set to ${mode} in ${r.file}`, "info"); }
15133
+ if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.validationRetryMode = mode; }); workflowUiNotify(ctx, `workflow.validationRetryMode set to ${mode} in ${r.file}`, "info"); }
14972
15134
  } else {
14973
15135
  const keyMap: Record<string, keyof ReturnType<typeof loadWorkflowSettings>["workflow"]> = {
14974
15136
  "Auto Repair Validation Failures": "autoRepairValidationFailures",
@@ -14978,7 +15140,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14978
15140
  };
14979
15141
  const key = keyMap[setting];
14980
15142
  const enabled = await chooseBool(ctx, `${String(key)}?`);
14981
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.workflow as Record<string, unknown>)[String(key)] = enabled; }); ctx.ui.notify(`workflow.${String(key)} set to ${enabled} in ${r.file}`, "info"); }
15143
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.workflow as Record<string, unknown>)[String(key)] = enabled; }); workflowUiNotify(ctx, `workflow.${String(key)} set to ${enabled} in ${r.file}`, "info"); }
14982
15144
  }
14983
15145
  }
14984
15146
  }
@@ -14992,26 +15154,26 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14992
15154
  await showModelSettingsMenu(ctx);
14993
15155
  } else if (choice === "Planning Depth") {
14994
15156
  const depth = parsePlanningDepth((await ctx.ui.select("Planning depth", ["fast", "standard", "deep", "maximum"])) ?? "");
14995
- if (depth) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.depth = depth; }); ctx.ui.notify(`planning.depth set to ${depth} in ${r.file}`, "info"); }
15157
+ if (depth) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.depth = depth; }); workflowUiNotify(ctx, `planning.depth set to ${depth} in ${r.file}`, "info"); }
14996
15158
  } else if (choice === "Plan Clarification") {
14997
15159
  const setting = await ctx.ui.select("Plan Clarification", ["Clarification Mode", "Interactive Clarification", "Max Clarification Questions", "Timing", "Quality Gate", "Allow Without Analysis", "Use Sub-agents Before Clarification", "Back"]);
14998
15160
  if (!setting || setting === "Back") continue;
14999
15161
  if (setting === "Clarification Mode") {
15000
15162
  const mode = parseClarificationMode((await ctx.ui.select("Plan clarification mode", ["auto", "always_for_nontrivial", "never"])) ?? "");
15001
- if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.clarificationMode = mode; }); ctx.ui.notify(`planning.clarificationMode set to ${mode} in ${r.file}`, "info"); }
15163
+ if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.clarificationMode = mode; }); workflowUiNotify(ctx, `planning.clarificationMode set to ${mode} in ${r.file}`, "info"); }
15002
15164
  } else if (setting === "Interactive Clarification") {
15003
15165
  const enabled = await chooseBool(ctx, "Interactive clarification enabled?");
15004
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.interactiveClarificationEnabled = enabled; }); ctx.ui.notify(`planning.interactiveClarificationEnabled set to ${enabled} in ${r.file}`, "info"); }
15166
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.interactiveClarificationEnabled = enabled; }); workflowUiNotify(ctx, `planning.interactiveClarificationEnabled set to ${enabled} in ${r.file}`, "info"); }
15005
15167
  } else if (setting === "Max Clarification Questions") {
15006
15168
  const count = parsePositiveInt((await ctx.ui.select("Max clarification questions", ["1", "2", "3", "4", "5"])) ?? "");
15007
- if (count) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxClarificationQuestions = count; }); ctx.ui.notify(`planning.maxClarificationQuestions set to ${count} in ${r.file}`, "info"); }
15169
+ if (count) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxClarificationQuestions = count; }); workflowUiNotify(ctx, `planning.maxClarificationQuestions set to ${count} in ${r.file}`, "info"); }
15008
15170
  } else if (setting === "Timing") {
15009
15171
  const timing = parseClarificationTiming((await ctx.ui.select("Plan clarification timing", ["after_initial_analysis", "immediate"])) ?? "");
15010
- if (timing) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.clarificationTiming = timing; }); ctx.ui.notify(`planning.clarificationTiming set to ${timing} in ${r.file}`, "info"); }
15172
+ if (timing) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.clarificationTiming = timing; }); workflowUiNotify(ctx, `planning.clarificationTiming set to ${timing} in ${r.file}`, "info"); }
15011
15173
  } else {
15012
15174
  const key = setting === "Quality Gate" ? "clarificationQualityGate" : setting === "Allow Without Analysis" ? "allowClarificationWithoutAnalysis" : "useSubagentsBeforeClarification";
15013
15175
  const enabled = await chooseBool(ctx, `planning.${key}?`);
15014
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.planning as typeof s.planning & Record<string, boolean | string | number | undefined>)[key] = enabled; }); ctx.ui.notify(`planning.${key} set to ${enabled} in ${r.file}`, "info"); }
15176
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.planning as typeof s.planning & Record<string, boolean | string | number | undefined>)[key] = enabled; }); workflowUiNotify(ctx, `planning.${key} set to ${enabled} in ${r.file}`, "info"); }
15015
15177
  }
15016
15178
  } else if (choice === "Plan Sub-agents / Workers") {
15017
15179
  await showPlanSubagentWorkerSettingsMenu(ctx);
@@ -15020,16 +15182,16 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15020
15182
  if (!setting || setting === "Back") continue;
15021
15183
  const enabled = await chooseBool(ctx, `${setting}?`);
15022
15184
  if (enabled === undefined) continue;
15023
- if (setting === "Reviewer Enabled") { const r = setRoleEnabled("reviewer", enabled, ctx.cwd); ctx.ui.notify(`reviewer.enabled set to ${enabled} in ${r.file}`, "info"); }
15024
- else if (setting === "Validator Enabled") { const r = setRoleEnabled("validator", enabled, ctx.cwd); ctx.ui.notify(`validator.enabled set to ${enabled} in ${r.file}`, "info"); }
15025
- else if (setting === "Auto Run Reviewer") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.autoRunReviewerBeforeExecute = enabled; }); ctx.ui.notify(`workflow.autoRunReviewerBeforeExecute set to ${enabled} in ${r.file}`, "info"); }
15026
- else if (setting === "Auto Run Validation") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.autoRunValidationAfterExecute = enabled; }); ctx.ui.notify(`workflow.autoRunValidationAfterExecute set to ${enabled} in ${r.file}`, "info"); }
15027
- else if (setting === "Auto Repair Review Failures") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.autoRepairReviewFailures = enabled; }); ctx.ui.notify(`workflow.autoRepairReviewFailures set to ${enabled} in ${r.file}`, "info"); }
15028
- else if (setting === "Pause After Review Failure") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.pauseAfterReviewFailure = enabled; }); ctx.ui.notify(`workflow.pauseAfterReviewFailure set to ${enabled} in ${r.file}`, "info"); }
15029
- else if (setting === "Approval Before Execution") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.requireApprovalBeforeExecution = enabled; s.workflow.requirePlanApprovalBeforeExecute = enabled; }); ctx.ui.notify(`workflow.requireApprovalBeforeExecution set to ${enabled} in ${r.file}`, "info"); }
15030
- else if (setting === "Approval Per Step") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.requireApprovalPerStep = enabled; }); ctx.ui.notify(`workflow.requireApprovalPerStep set to ${enabled} in ${r.file}`, "info"); }
15031
- else if (setting === "Validate After Each Step") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.validateAfterEachStep = enabled; }); ctx.ui.notify(`workflow.validateAfterEachStep set to ${enabled} in ${r.file}`, "info"); }
15032
- else if (setting === "Validate After Full Execution") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.validateAfterExecution = enabled; s.workflow.autoRunValidationAfterExecute = enabled; }); ctx.ui.notify(`workflow.validateAfterExecution set to ${enabled} in ${r.file}`, "info"); }
15185
+ if (setting === "Reviewer Enabled") { const r = setRoleEnabled("reviewer", enabled, ctx.cwd); workflowUiNotify(ctx, `reviewer.enabled set to ${enabled} in ${r.file}`, "info"); }
15186
+ else if (setting === "Validator Enabled") { const r = setRoleEnabled("validator", enabled, ctx.cwd); workflowUiNotify(ctx, `validator.enabled set to ${enabled} in ${r.file}`, "info"); }
15187
+ else if (setting === "Auto Run Reviewer") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.autoRunReviewerBeforeExecute = enabled; }); workflowUiNotify(ctx, `workflow.autoRunReviewerBeforeExecute set to ${enabled} in ${r.file}`, "info"); }
15188
+ else if (setting === "Auto Run Validation") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.autoRunValidationAfterExecute = enabled; }); workflowUiNotify(ctx, `workflow.autoRunValidationAfterExecute set to ${enabled} in ${r.file}`, "info"); }
15189
+ else if (setting === "Auto Repair Review Failures") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.autoRepairReviewFailures = enabled; }); workflowUiNotify(ctx, `workflow.autoRepairReviewFailures set to ${enabled} in ${r.file}`, "info"); }
15190
+ else if (setting === "Pause After Review Failure") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.pauseAfterReviewFailure = enabled; }); workflowUiNotify(ctx, `workflow.pauseAfterReviewFailure set to ${enabled} in ${r.file}`, "info"); }
15191
+ else if (setting === "Approval Before Execution") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.requireApprovalBeforeExecution = enabled; s.workflow.requirePlanApprovalBeforeExecute = enabled; }); workflowUiNotify(ctx, `workflow.requireApprovalBeforeExecution set to ${enabled} in ${r.file}`, "info"); }
15192
+ else if (setting === "Approval Per Step") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.requireApprovalPerStep = enabled; }); workflowUiNotify(ctx, `workflow.requireApprovalPerStep set to ${enabled} in ${r.file}`, "info"); }
15193
+ else if (setting === "Validate After Each Step") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.validateAfterEachStep = enabled; }); workflowUiNotify(ctx, `workflow.validateAfterEachStep set to ${enabled} in ${r.file}`, "info"); }
15194
+ else if (setting === "Validate After Full Execution") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.validateAfterExecution = enabled; s.workflow.autoRunValidationAfterExecute = enabled; }); workflowUiNotify(ctx, `workflow.validateAfterExecution set to ${enabled} in ${r.file}`, "info"); }
15033
15195
  } else if (choice === "Repair / Validation Retry") {
15034
15196
  await showWorkflowRepairRetrySettingsMenu(ctx);
15035
15197
  } else if (choice === "Plan Progress / Runtime") {
@@ -15045,28 +15207,28 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15045
15207
  const choice = await ctx.ui.select("Plan Token Budget", ["Default (unlimited)", "Custom..."]);
15046
15208
  if (choice === "Default (unlimited)") {
15047
15209
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxTokens = 0; });
15048
- ctx.ui.notify(`planning.maxTokens set to default (unlimited) in ${r.file}`, "info");
15210
+ workflowUiNotify(ctx, `planning.maxTokens set to default (unlimited) in ${r.file}`, "info");
15049
15211
  } else if (choice === "Custom...") {
15050
15212
  const count = parsePositiveInt((await ctx.ui.input("Enter custom plan token budget", String(current > 0 ? current : ""))) ?? "");
15051
- if (count !== undefined && count >= 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxTokens = count; }); ctx.ui.notify(`planning.maxTokens set to ${count === 0 ? "unlimited" : count.toLocaleString()} in ${r.file}`, "info"); }
15213
+ if (count !== undefined && count >= 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxTokens = count; }); workflowUiNotify(ctx, `planning.maxTokens set to ${count === 0 ? "unlimited" : count.toLocaleString()} in ${r.file}`, "info"); }
15052
15214
  }
15053
15215
  } else if (setting === "Runtime Budget") {
15054
15216
  const current = loadWorkflowSettings(ctx.cwd).planning.maxRuntimeHours ?? 0;
15055
15217
  const choice = await ctx.ui.select("Plan Runtime Budget", ["Default (unlimited)", "Custom..."]);
15056
15218
  if (choice === "Default (unlimited)") {
15057
15219
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxRuntimeHours = 0; });
15058
- ctx.ui.notify(`planning.maxRuntimeHours set to default (unlimited) in ${r.file}`, "info");
15220
+ workflowUiNotify(ctx, `planning.maxRuntimeHours set to default (unlimited) in ${r.file}`, "info");
15059
15221
  } else if (choice === "Custom...") {
15060
15222
  const count = parsePositiveInt((await ctx.ui.input("Enter custom plan runtime budget (hours)", String(current > 0 ? current : ""))) ?? "");
15061
- if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxRuntimeHours = count; }); ctx.ui.notify(`planning.maxRuntimeHours set to ${count} hours in ${r.file}`, "info"); }
15223
+ if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxRuntimeHours = count; }); workflowUiNotify(ctx, `planning.maxRuntimeHours set to ${count} hours in ${r.file}`, "info"); }
15062
15224
  }
15063
15225
  } else if (setting === "Progress Bar Display") {
15064
15226
  const enabled = await chooseBool(ctx, "workflow.planShowProgressBar?");
15065
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.planShowProgressBar = enabled; }); ctx.ui.notify(`workflow.planShowProgressBar set to ${enabled} in ${r.file}`, "info"); }
15227
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.planShowProgressBar = enabled; }); workflowUiNotify(ctx, `workflow.planShowProgressBar set to ${enabled} in ${r.file}`, "info"); }
15066
15228
  } else {
15067
15229
  const key = setting === "Progress Tracking" ? "planProgressEnabled" : "planRuntimeEnabled";
15068
15230
  const enabled = await chooseBool(ctx, `workflow.${key}?`);
15069
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.workflow as typeof s.workflow & Record<string, boolean>)[key] = enabled; }); ctx.ui.notify(`workflow.${key} set to ${enabled} in ${r.file}`, "info"); }
15231
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.workflow as typeof s.workflow & Record<string, boolean>)[key] = enabled; }); workflowUiNotify(ctx, `workflow.${key} set to ${enabled} in ${r.file}`, "info"); }
15070
15232
  }
15071
15233
  } else if (choice === "Plan History") {
15072
15234
  const setting = await ctx.ui.select("Plan History", ["Save Plans", "Save Plan History", "Plan History Limit", "Back"]);
@@ -15074,11 +15236,11 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15074
15236
  if (!setting || setting === "Back") continue;
15075
15237
  if (setting === "Plan History Limit") {
15076
15238
  const count = parsePositiveInt((await ctx.ui.input("Plan history limit", String(workflow.planHistoryLimit ?? 50))) ?? "");
15077
- if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.planHistoryLimit = count; }); ctx.ui.notify(`workflow.planHistoryLimit set to ${count} in ${r.file}`, "info"); }
15239
+ if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.planHistoryLimit = count; }); workflowUiNotify(ctx, `workflow.planHistoryLimit set to ${count} in ${r.file}`, "info"); }
15078
15240
  } else {
15079
15241
  const key = setting === "Save Plans" ? "savePlans" : "savePlanHistory";
15080
15242
  const enabled = await chooseBool(ctx, `${key}?`);
15081
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.workflow as typeof s.workflow & Record<string, boolean>)[key] = enabled; }); ctx.ui.notify(`workflow.${key} set to ${enabled} in ${r.file}`, "info"); }
15243
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.workflow as typeof s.workflow & Record<string, boolean>)[key] = enabled; }); workflowUiNotify(ctx, `workflow.${key} set to ${enabled} in ${r.file}`, "info"); }
15082
15244
  }
15083
15245
  } else if (choice === "List Current Settings") {
15084
15246
  const s = loadWorkflowSettings(ctx.cwd);
@@ -15094,11 +15256,11 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15094
15256
  if (!setting || setting === "Back") return;
15095
15257
  if (setting === "To Do Trigger Mode") {
15096
15258
  const mode = parseStandardTodoTriggerMode((await ctx.ui.select("To Do Trigger Mode", ["Disabled", "On request", "Automatic when useful", "Required"])) ?? "");
15097
- if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.todoTriggerMode = mode; s.standard.autoTodoEnabled = mode !== "off"; }); ctx.ui.notify(`To Do Trigger Mode set to ${standardTodoTriggerModeLabel(mode)} in ${r.file}`, "info"); }
15259
+ if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.todoTriggerMode = mode; s.standard.autoTodoEnabled = mode !== "off"; }); workflowUiNotify(ctx, `To Do Trigger Mode set to ${standardTodoTriggerModeLabel(mode)} in ${r.file}`, "info"); }
15098
15260
  } else {
15099
15261
  const key = setting === "Automatic To Do Enabled" ? "autoTodoEnabled" : "todoProgressVisible";
15100
15262
  const enabled = await chooseBool(ctx, `standard.${key}?`);
15101
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.standard as typeof s.standard & Record<string, boolean>)[key] = enabled; }); ctx.ui.notify(`standard.${key} set to ${enabled} in ${r.file}`, "info"); }
15263
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.standard as typeof s.standard & Record<string, boolean>)[key] = enabled; }); workflowUiNotify(ctx, `standard.${key} set to ${enabled} in ${r.file}`, "info"); }
15102
15264
  }
15103
15265
  }
15104
15266
  }
@@ -15110,20 +15272,20 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15110
15272
  if (!setting || setting === "Back") return;
15111
15273
  if (setting === "Clarification Mode") {
15112
15274
  const mode = parseStandardClarificationMode((await ctx.ui.select("Standard clarification mode", ["auto", "always_for_nontrivial", "never"])) ?? "");
15113
- if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.clarificationMode = mode; s.standard.clarificationEnabled = mode !== "never"; }); ctx.ui.notify(`standard.clarificationMode set to ${mode} in ${r.file}`, "info"); }
15275
+ if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.clarificationMode = mode; s.standard.clarificationEnabled = mode !== "never"; }); workflowUiNotify(ctx, `standard.clarificationMode set to ${mode} in ${r.file}`, "info"); }
15114
15276
  } else if (setting === "Interactive Clarification") {
15115
15277
  const enabled = await chooseBool(ctx, "Standard interactive clarification enabled?");
15116
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.interactiveClarificationEnabled = enabled; }); ctx.ui.notify(`standard.interactiveClarificationEnabled set to ${enabled} in ${r.file}`, "info"); }
15278
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.interactiveClarificationEnabled = enabled; }); workflowUiNotify(ctx, `standard.interactiveClarificationEnabled set to ${enabled} in ${r.file}`, "info"); }
15117
15279
  } else if (setting === "Max Clarification Questions") {
15118
15280
  const count = parsePositiveInt((await ctx.ui.select("Max Standard clarification questions", ["0", "1", "2"])) ?? "");
15119
- if (count !== undefined && count >= 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.maxClarificationQuestions = count; }); ctx.ui.notify(`standard.maxClarificationQuestions set to ${count} in ${r.file}`, "info"); }
15281
+ if (count !== undefined && count >= 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.maxClarificationQuestions = count; }); workflowUiNotify(ctx, `standard.maxClarificationQuestions set to ${count} in ${r.file}`, "info"); }
15120
15282
  } else if (setting === "Timing") {
15121
15283
  const timing = parseClarificationTiming((await ctx.ui.select("Standard clarification timing", ["after_initial_analysis", "immediate"])) ?? "");
15122
- if (timing) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.clarificationTiming = timing; }); ctx.ui.notify(`standard.clarificationTiming set to ${timing} in ${r.file}`, "info"); }
15284
+ if (timing) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.clarificationTiming = timing; }); workflowUiNotify(ctx, `standard.clarificationTiming set to ${timing} in ${r.file}`, "info"); }
15123
15285
  } else {
15124
15286
  const key = setting === "Quality Gate" ? "clarificationQualityGate" : setting === "Allow Without Analysis" ? "allowClarificationWithoutAnalysis" : "useSubagentsBeforeClarification";
15125
15287
  const enabled = await chooseBool(ctx, `standard.${key}?`);
15126
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.standard as typeof s.standard & Record<string, boolean | string | number | undefined>)[key] = enabled; }); ctx.ui.notify(`standard.${key} set to ${enabled} in ${r.file}`, "info"); }
15288
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.standard as typeof s.standard & Record<string, boolean | string | number | undefined>)[key] = enabled; }); workflowUiNotify(ctx, `standard.${key} set to ${enabled} in ${r.file}`, "info"); }
15127
15289
  }
15128
15290
  }
15129
15291
  }
@@ -15143,15 +15305,15 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15143
15305
  const choice = await ctx.ui.select("Standard Token Budget", ["Default (unlimited)", "Custom..."]);
15144
15306
  if (choice === "Default (unlimited)") {
15145
15307
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.maxTokens = 0; });
15146
- ctx.ui.notify(`standard.maxTokens set to default (unlimited) in ${r.file}`, "info");
15308
+ workflowUiNotify(ctx, `standard.maxTokens set to default (unlimited) in ${r.file}`, "info");
15147
15309
  } else if (choice === "Custom...") {
15148
15310
  const count = parsePositiveInt((await ctx.ui.input("Enter custom standard token budget", String(current > 0 ? current : ""))) ?? "");
15149
- if (count !== undefined && count >= 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.maxTokens = count; }); ctx.ui.notify(`standard.maxTokens set to ${count === 0 ? "unlimited" : count.toLocaleString()} in ${r.file}`, "info"); }
15311
+ if (count !== undefined && count >= 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.maxTokens = count; }); workflowUiNotify(ctx, `standard.maxTokens set to ${count === 0 ? "unlimited" : count.toLocaleString()} in ${r.file}`, "info"); }
15150
15312
  }
15151
15313
  } else {
15152
15314
  const key = setting === "Status Widget Visible" ? "statusWidgetVisible" : "todoProgressVisible";
15153
15315
  const enabled = await chooseBool(ctx, `standard.${key}?`);
15154
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.standard as typeof s.standard & Record<string, boolean>)[key] = enabled; }); ctx.ui.notify(`standard.${key} set to ${enabled} in ${r.file}`, "info"); }
15316
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.standard as typeof s.standard & Record<string, boolean>)[key] = enabled; }); workflowUiNotify(ctx, `standard.${key} set to ${enabled} in ${r.file}`, "info"); }
15155
15317
  }
15156
15318
  }
15157
15319
  }
@@ -15168,7 +15330,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15168
15330
  }
15169
15331
  if (choice === "Enable / Disable Standard Mode") {
15170
15332
  const enabled = await chooseBool(ctx, "standard.enabled?");
15171
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.enabled = enabled; }); ctx.ui.notify(`standard.enabled set to ${enabled} in ${r.file}`, "info"); }
15333
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.enabled = enabled; }); workflowUiNotify(ctx, `standard.enabled set to ${enabled} in ${r.file}`, "info"); }
15172
15334
  } else if (choice === "Standard To Do" || choice === "To Do Behavior") {
15173
15335
  await showStandardTodoSettingsMenu(ctx);
15174
15336
  } else if (choice === "Standard Clarification" || choice === "Clarification") {
@@ -15197,7 +15359,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15197
15359
  if (!source) continue;
15198
15360
  const enabled = source === "Mission-Specific Models";
15199
15361
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.useMissionSpecificModels = enabled; });
15200
- ctx.ui.notify(`missions.useMissionSpecificModels set to ${enabled} in ${r.file}`, "info");
15362
+ workflowUiNotify(ctx, `missions.useMissionSpecificModels set to ${enabled} in ${r.file}`, "info");
15201
15363
  } else if (choice === "Configure Mission Planner") await configureMissionRoleModel(ctx, "planner");
15202
15364
  else if (choice === "Configure Mission Executor") await configureMissionRoleModel(ctx, "executor");
15203
15365
  else if (choice === "Configure Mission Reviewer") await configureMissionRoleModel(ctx, "reviewer");
@@ -15218,13 +15380,13 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15218
15380
  show(pi, renderHeartbeatWatchdogStatus(loadWorkflowSettings(ctx.cwd), activeMission ?? loadMissionState()));
15219
15381
  } else if (choice === "Enable / Disable Heartbeat") {
15220
15382
  const enabled = await chooseBool(ctx, "missions.heartbeatEnabled?");
15221
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.heartbeatEnabled = enabled; }); ctx.ui.notify(`missions.heartbeatEnabled set to ${enabled} in ${r.file}`, "info"); }
15383
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.heartbeatEnabled = enabled; }); workflowUiNotify(ctx, `missions.heartbeatEnabled set to ${enabled} in ${r.file}`, "info"); }
15222
15384
  } else if (choice === "Enable / Disable Watchdog") {
15223
15385
  const enabled = await chooseBool(ctx, "missions.watchdogEnabled? (warning only; no auto-recovery)");
15224
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.watchdogEnabled = enabled; }); ctx.ui.notify(`missions.watchdogEnabled set to ${enabled} in ${r.file}`, "info"); }
15386
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.watchdogEnabled = enabled; }); workflowUiNotify(ctx, `missions.watchdogEnabled set to ${enabled} in ${r.file}`, "info"); }
15225
15387
  } else if (choice === "Set Watchdog Stale Minutes") {
15226
15388
  const count = parsePositiveInt((await ctx.ui.input("watchdogStaleMinutes", String(loadWorkflowSettings(ctx.cwd).missions.watchdogStaleMinutes ?? 30))) ?? "");
15227
- if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.watchdogStaleMinutes = count; }); ctx.ui.notify(`missions.watchdogStaleMinutes set to ${count} in ${r.file}`, "info"); }
15389
+ if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.watchdogStaleMinutes = count; }); workflowUiNotify(ctx, `missions.watchdogStaleMinutes set to ${count} in ${r.file}`, "info"); }
15228
15390
  }
15229
15391
  }
15230
15392
  }
@@ -15237,11 +15399,11 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15237
15399
  const enabled = await chooseBool(ctx, `${setting}?`);
15238
15400
  if (enabled === undefined) continue;
15239
15401
  if (setting === "Mission Reviewer Enabled") {
15240
- if (loadWorkflowSettings(ctx.cwd).missions.useMissionSpecificModels) { const r = updateSettings(ctx.cwd, undefined, (s) => { setMissionRoleEnabled(s, "reviewer", enabled); }); ctx.ui.notify(`missions.models.reviewer.enabled set to ${enabled} in ${r.file}`, "info"); }
15241
- else { const r = setRoleEnabled("reviewer", enabled, ctx.cwd); ctx.ui.notify(`reviewer.enabled set to ${enabled} in ${r.file}`, "info"); }
15402
+ if (loadWorkflowSettings(ctx.cwd).missions.useMissionSpecificModels) { const r = updateSettings(ctx.cwd, undefined, (s) => { setMissionRoleEnabled(s, "reviewer", enabled); }); workflowUiNotify(ctx, `missions.models.reviewer.enabled set to ${enabled} in ${r.file}`, "info"); }
15403
+ else { const r = setRoleEnabled("reviewer", enabled, ctx.cwd); workflowUiNotify(ctx, `reviewer.enabled set to ${enabled} in ${r.file}`, "info"); }
15242
15404
  } else if (setting === "Mission Validator Enabled") {
15243
- if (loadWorkflowSettings(ctx.cwd).missions.useMissionSpecificModels) { const r = updateSettings(ctx.cwd, undefined, (s) => { setMissionRoleEnabled(s, "validator", enabled); }); ctx.ui.notify(`missions.models.validator.enabled set to ${enabled} in ${r.file}`, "info"); }
15244
- else { const r = setRoleEnabled("validator", enabled, ctx.cwd); ctx.ui.notify(`validator.enabled set to ${enabled} in ${r.file}`, "info"); }
15405
+ if (loadWorkflowSettings(ctx.cwd).missions.useMissionSpecificModels) { const r = updateSettings(ctx.cwd, undefined, (s) => { setMissionRoleEnabled(s, "validator", enabled); }); workflowUiNotify(ctx, `missions.models.validator.enabled set to ${enabled} in ${r.file}`, "info"); }
15406
+ else { const r = setRoleEnabled("validator", enabled, ctx.cwd); workflowUiNotify(ctx, `validator.enabled set to ${enabled} in ${r.file}`, "info"); }
15245
15407
  } else {
15246
15408
  const keyMap: Record<string, string> = {
15247
15409
  "Offer Reviewer Before Approval": "offerReviewerBeforeApprove",
@@ -15259,7 +15421,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15259
15421
  s.missions.reviewRetryMode = "safe_only";
15260
15422
  }
15261
15423
  });
15262
- ctx.ui.notify(`missions.${key} set to ${enabled} in ${r.file}`, "info");
15424
+ workflowUiNotify(ctx, `missions.${key} set to ${enabled} in ${r.file}`, "info");
15263
15425
  }
15264
15426
  }
15265
15427
  }
@@ -15272,18 +15434,18 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15272
15434
  if (setting === "Max Review Retries Per Mission") {
15273
15435
  const raw = await ctx.ui.select(setting, ["0", "1", "2", "3", "4", "5", "10"]);
15274
15436
  const count = raw === undefined ? undefined : Number(raw);
15275
- if (Number.isInteger(count) && count >= 0 && count <= 10) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxReviewRetriesPerMission = count; }); ctx.ui.notify(`missions.maxReviewRetriesPerMission set to ${count} in ${r.file}`, "info"); }
15437
+ if (Number.isInteger(count) && count >= 0 && count <= 10) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxReviewRetriesPerMission = count; }); workflowUiNotify(ctx, `missions.maxReviewRetriesPerMission set to ${count} in ${r.file}`, "info"); }
15276
15438
  } else if (setting === "Max Retries Per Milestone" || setting === "Max Retries Per Mission" || setting === "Max Final Validation Retries") {
15277
15439
  const key = setting === "Max Retries Per Milestone" ? "maxValidationRetriesPerMilestone" : setting === "Max Retries Per Mission" ? "maxValidationRetriesPerMission" : "maxFinalValidationRetries";
15278
15440
  const max = key === "maxValidationRetriesPerMission" ? 100 : 10;
15279
15441
  const options = key === "maxValidationRetriesPerMission" ? ["0", "1", "2", "4", "8", "12", "20", "50", "100"] : ["0", "1", "2", "3", "4", "5", "10"];
15280
15442
  const raw = await ctx.ui.select(setting, options);
15281
15443
  const count = raw === undefined ? undefined : Number(raw);
15282
- if (Number.isInteger(count) && count >= 0 && count <= max) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, number>)[key] = count; }); ctx.ui.notify(`missions.${key} set to ${count} in ${r.file}`, "info"); }
15444
+ if (Number.isInteger(count) && count >= 0 && count <= max) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, number>)[key] = count; }); workflowUiNotify(ctx, `missions.${key} set to ${count} in ${r.file}`, "info"); }
15283
15445
  } else if (setting === "Validation Retry Mode" || setting === "Review Retry Mode") {
15284
15446
  const key = setting === "Validation Retry Mode" ? "validationRetryMode" : "reviewRetryMode";
15285
15447
  const mode = parseValidationRetryMode((await ctx.ui.select(`${key}`, ["off", "safe_only", "aggressive_within_scope"])) ?? "");
15286
- if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, string | undefined>)[key] = mode; }); ctx.ui.notify(`missions.${key} set to ${mode} in ${r.file}`, "info"); }
15448
+ if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, string | undefined>)[key] = mode; }); workflowUiNotify(ctx, `missions.${key} set to ${mode} in ${r.file}`, "info"); }
15287
15449
  } else {
15288
15450
  const keyMap: Record<string, string> = {
15289
15451
  "Auto Repair Review Failures": "autoRepairReviewFailures",
@@ -15296,7 +15458,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15296
15458
  };
15297
15459
  const key = keyMap[setting];
15298
15460
  const enabled = await chooseBool(ctx, `${String(key)}?`);
15299
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as Record<string, unknown>)[String(key)] = enabled; if (key === "autoRepairReviewFailures" && enabled && s.missions.reviewRetryMode === "off") { s.missions.reviewRetryMode = "safe_only"; } }); ctx.ui.notify(`missions.${String(key)} set to ${enabled} in ${r.file}`, "info"); }
15461
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as Record<string, unknown>)[String(key)] = enabled; if (key === "autoRepairReviewFailures" && enabled && s.missions.reviewRetryMode === "off") { s.missions.reviewRetryMode = "safe_only"; } }); workflowUiNotify(ctx, `missions.${String(key)} set to ${enabled} in ${r.file}`, "info"); }
15300
15462
  }
15301
15463
  }
15302
15464
  }
@@ -15309,12 +15471,12 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15309
15471
  if (setting === "Max Final Validation Retries") {
15310
15472
  const raw = await ctx.ui.select(setting, ["0", "1", "2", "3", "4", "5", "10"]);
15311
15473
  const count = raw === undefined ? undefined : Number(raw);
15312
- if (Number.isInteger(count) && count >= 0 && count <= 10) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxFinalValidationRetries = count; }); ctx.ui.notify(`missions.maxFinalValidationRetries set to ${count} in ${r.file}`, "info"); }
15474
+ if (Number.isInteger(count) && count >= 0 && count <= 10) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxFinalValidationRetries = count; }); workflowUiNotify(ctx, `missions.maxFinalValidationRetries set to ${count} in ${r.file}`, "info"); }
15313
15475
  } else {
15314
15476
  const keyMap: Record<string, string> = { "Final Comprehensive Validation": "finalValidationEnabled", "Final Validation Requires Pass": "finalValidationRequiresPass", "Auto Repair Final Validation Failures": "autoRepairFinalValidationFailures" };
15315
15477
  const key = keyMap[setting];
15316
15478
  const enabled = await chooseBool(ctx, `${String(key)}?`);
15317
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as Record<string, unknown>)[String(key)] = enabled; }); ctx.ui.notify(`missions.${String(key)} set to ${enabled} in ${r.file}`, "info"); }
15479
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as Record<string, unknown>)[String(key)] = enabled; }); workflowUiNotify(ctx, `missions.${String(key)} set to ${enabled} in ${r.file}`, "info"); }
15318
15480
  }
15319
15481
  }
15320
15482
  }
@@ -15329,12 +15491,12 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15329
15491
  const count = parsePositiveInt((await ctx.ui.input("Mission history limit", String(current))) ?? "");
15330
15492
  if (count !== undefined && count >= 1 && count <= 500) {
15331
15493
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.missionHistoryLimit = count; });
15332
- ctx.ui.notify(`missions.missionHistoryLimit set to ${count} in ${r.file}`, "info");
15494
+ workflowUiNotify(ctx, `missions.missionHistoryLimit set to ${count} in ${r.file}`, "info");
15333
15495
  }
15334
15496
  } else if (setting === "Cleanup Saved Missions") {
15335
15497
  const settings = loadWorkflowSettings(ctx.cwd);
15336
15498
  const removed = clearOldMissionStates(settings.missions.missionHistoryLimit ?? 50);
15337
- ctx.ui.notify(`Removed ${removed} old mission file${removed === 1 ? "" : "s"}.`, "info");
15499
+ workflowUiNotify(ctx, `Removed ${removed} old mission file${removed === 1 ? "" : "s"}.`, "info");
15338
15500
  } else if (setting === "List Current Settings") {
15339
15501
  const settings = loadWorkflowSettings(ctx.cwd);
15340
15502
  show(pi, `# Mission History\n\nMission History Limit: ${settings.missions.missionHistoryLimit ?? 50}\nMissions Directory: ${MISSION_HISTORY_DIR}`);
@@ -15351,48 +15513,48 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15351
15513
  await showMissionModelBehaviorMenu(ctx);
15352
15514
  } else if (choice === "Enable / Disable Mission Mode") {
15353
15515
  const enabled = await chooseBool(ctx, "Missions enabled?");
15354
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.enabled = enabled; }); ctx.ui.notify(`missions.enabled set to ${enabled} in ${r.file}`, "info"); }
15516
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.enabled = enabled; }); workflowUiNotify(ctx, `missions.enabled set to ${enabled} in ${r.file}`, "info"); }
15355
15517
  } else if (choice === "Mission Autonomy") {
15356
15518
  const setting = await ctx.ui.select("Mission Autonomy", ["Default Autonomy", "Allow Full Auto", "Auto Run After Approval", "Continue Across Milestones", "Pause Between Milestones", "Auto Resume", "Back"]);
15357
15519
  if (!setting || setting === "Back") continue;
15358
15520
  if (setting === "Default Autonomy") {
15359
15521
  const autonomy = parseMissionAutonomy((await ctx.ui.select("Mission default autonomy", ["manual", "approval_gated", "supervised_auto", "full_auto"])) ?? "");
15360
- if (autonomy) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.defaultAutonomy = autonomy; }); ctx.ui.notify(`missions.defaultAutonomy set to ${autonomy} in ${r.file}${autonomy === "full_auto" && !r.settings.missions.allowFullAuto ? "; full_auto will be blocked until allowFullAuto=true" : ""}`, "info"); }
15522
+ if (autonomy) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.defaultAutonomy = autonomy; }); workflowUiNotify(ctx, `missions.defaultAutonomy set to ${autonomy} in ${r.file}${autonomy === "full_auto" && !r.settings.missions.allowFullAuto ? "; full_auto will be blocked until allowFullAuto=true" : ""}`, "info"); }
15361
15523
  } else {
15362
15524
  const keyMap: Record<string, keyof ReturnType<typeof loadWorkflowSettings>["missions"]> = { "Allow Full Auto": "allowFullAuto", "Auto Run After Approval": "autoRunAfterApproval", "Continue Across Milestones": "continueAcrossMilestones", "Pause Between Milestones": "pauseBetweenMilestones", "Auto Resume": "autoResume" };
15363
15525
  const key = keyMap[setting];
15364
15526
  const enabled = await chooseBool(ctx, `${String(key)}?`);
15365
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as Record<string, unknown>)[String(key)] = enabled; }); ctx.ui.notify(`missions.${String(key)} set to ${enabled} in ${r.file}${key === "allowFullAuto" && enabled === false && r.settings.missions.defaultAutonomy === "full_auto" ? "; full_auto default is retained but blocked" : ""}`, "info"); }
15527
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as Record<string, unknown>)[String(key)] = enabled; }); workflowUiNotify(ctx, `missions.${String(key)} set to ${enabled} in ${r.file}${key === "allowFullAuto" && enabled === false && r.settings.missions.defaultAutonomy === "full_auto" ? "; full_auto default is retained but blocked" : ""}`, "info"); }
15366
15528
  }
15367
15529
  } else if (choice === "Default Autonomy") {
15368
15530
  const autonomy = parseMissionAutonomy((await ctx.ui.select("Mission default autonomy", ["manual", "approval_gated", "supervised_auto", "full_auto"])) ?? "");
15369
- if (autonomy) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.defaultAutonomy = autonomy; }); ctx.ui.notify(`missions.defaultAutonomy set to ${autonomy} in ${r.file}${autonomy === "full_auto" && !r.settings.missions.allowFullAuto ? "; full_auto will be blocked until allowFullAuto=true" : ""}`, "info"); }
15531
+ if (autonomy) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.defaultAutonomy = autonomy; }); workflowUiNotify(ctx, `missions.defaultAutonomy set to ${autonomy} in ${r.file}${autonomy === "full_auto" && !r.settings.missions.allowFullAuto ? "; full_auto will be blocked until allowFullAuto=true" : ""}`, "info"); }
15370
15532
  } else if (choice === "Mission Clarification") {
15371
15533
  const setting = await ctx.ui.select("Mission Clarification", ["Clarification Mode", "Interactive Clarification", "Max Clarification Questions", "Timing", "Quality Gate", "Allow Without Analysis", "Use Sub-agents Before Clarification", "Back"]);
15372
15534
  if (!setting || setting === "Back") continue;
15373
15535
  if (setting === "Clarification Mode") {
15374
15536
  const mode = parseClarificationMode((await ctx.ui.select("Mission clarification mode", ["auto", "always_for_nontrivial", "never"])) ?? "");
15375
- if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.clarificationMode = mode; }); ctx.ui.notify(`missions.clarificationMode set to ${mode} in ${r.file}`, "info"); }
15537
+ if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.clarificationMode = mode; }); workflowUiNotify(ctx, `missions.clarificationMode set to ${mode} in ${r.file}`, "info"); }
15376
15538
  } else if (setting === "Interactive Clarification") {
15377
15539
  const enabled = await chooseBool(ctx, "Mission interactive clarification enabled?");
15378
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.interactiveClarificationEnabled = enabled; }); ctx.ui.notify(`missions.interactiveClarificationEnabled set to ${enabled} in ${r.file}`, "info"); }
15540
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.interactiveClarificationEnabled = enabled; }); workflowUiNotify(ctx, `missions.interactiveClarificationEnabled set to ${enabled} in ${r.file}`, "info"); }
15379
15541
  } else if (setting === "Max Clarification Questions") {
15380
15542
  const count = parsePositiveInt((await ctx.ui.select("Mission max clarification questions", ["1", "2", "3", "4", "5", "6"])) ?? "");
15381
- if (count) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxClarificationQuestions = count; }); ctx.ui.notify(`missions.maxClarificationQuestions set to ${count} in ${r.file}`, "info"); }
15543
+ if (count) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxClarificationQuestions = count; }); workflowUiNotify(ctx, `missions.maxClarificationQuestions set to ${count} in ${r.file}`, "info"); }
15382
15544
  } else if (setting === "Timing") {
15383
15545
  const timing = parseClarificationTiming((await ctx.ui.select("Mission clarification timing", ["after_initial_analysis", "immediate"])) ?? "");
15384
- if (timing) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.clarificationTiming = timing; }); ctx.ui.notify(`missions.clarificationTiming set to ${timing} in ${r.file}`, "info"); }
15546
+ if (timing) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.clarificationTiming = timing; }); workflowUiNotify(ctx, `missions.clarificationTiming set to ${timing} in ${r.file}`, "info"); }
15385
15547
  } else {
15386
15548
  const key = setting === "Quality Gate" ? "clarificationQualityGate" : setting === "Allow Without Analysis" ? "allowClarificationWithoutAnalysis" : "useSubagentsBeforeClarification";
15387
15549
  const enabled = await chooseBool(ctx, `missions.${key}?`);
15388
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, boolean | string | number | undefined>)[key] = enabled; }); ctx.ui.notify(`missions.${key} set to ${enabled} in ${r.file}`, "info"); }
15550
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, boolean | string | number | undefined>)[key] = enabled; }); workflowUiNotify(ctx, `missions.${key} set to ${enabled} in ${r.file}`, "info"); }
15389
15551
  }
15390
15552
  } else if (choice === "Mission Planning Depth") {
15391
15553
  const depth = parsePlanningDepth((await ctx.ui.select("Mission planning depth", ["fast", "standard", "deep", "maximum"])) ?? "");
15392
- if (depth) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.planningDepth = depth; }); ctx.ui.notify(`missions.planningDepth set to ${depth} in ${r.file}`, "info"); }
15554
+ if (depth) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.planningDepth = depth; }); workflowUiNotify(ctx, `missions.planningDepth set to ${depth} in ${r.file}`, "info"); }
15393
15555
  } else if (choice === "Mission Sub-Agent Policy") {
15394
15556
  const policy = parseSubagentPolicy((await ctx.ui.select("Mission sub-agent policy", ["off", "auto", "deep", "maximum", "forced"])) ?? "");
15395
- if (policy) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.subagentPolicy = policy; }); ctx.ui.notify(`missions.subagentPolicy set to ${policy} in ${r.file}`, "info"); }
15557
+ if (policy) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.subagentPolicy = policy; }); workflowUiNotify(ctx, `missions.subagentPolicy set to ${policy} in ${r.file}`, "info"); }
15396
15558
  } else if (choice === "Mission Sub-agents / Workers" || choice === "Mission Worker Targets") {
15397
15559
  await showMissionSubagentWorkerSettingsMenu(ctx);
15398
15560
  } else if (choice === "Mission History") {
@@ -15408,50 +15570,50 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15408
15570
  if (setting === "Progress Widget" || setting === "Progress Bar Display") {
15409
15571
  const key = setting === "Progress Widget" ? "progressWidgetEnabled" : "showProgressBar";
15410
15572
  const enabled = await chooseBool(ctx, `missions.${key}?`);
15411
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, boolean>)[key] = enabled; }); ctx.ui.notify(`missions.${key} set to ${enabled} in ${r.file}`, "info"); }
15573
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, boolean>)[key] = enabled; }); workflowUiNotify(ctx, `missions.${key} set to ${enabled} in ${r.file}`, "info"); }
15412
15574
  } else if (setting === "Heartbeat / Watchdog") await showHeartbeatWatchdogMenu(ctx);
15413
15575
  else if (setting === "Token Budget") {
15414
15576
  const current = loadWorkflowSettings(ctx.cwd).missions.maxTokens ?? 0;
15415
15577
  const choice = await ctx.ui.select("Mission Token Budget", ["Default (unlimited)", "Custom..."]);
15416
15578
  if (choice === "Default (unlimited)") {
15417
15579
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxTokens = 0; });
15418
- ctx.ui.notify(`missions.maxTokens set to default (unlimited) in ${r.file}`, "info");
15580
+ workflowUiNotify(ctx, `missions.maxTokens set to default (unlimited) in ${r.file}`, "info");
15419
15581
  } else if (choice === "Custom...") {
15420
15582
  const count = parsePositiveInt((await ctx.ui.input("Enter custom mission token budget", String(current > 0 ? current : ""))) ?? "");
15421
- if (count !== undefined && count >= 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxTokens = count; }); ctx.ui.notify(`missions.maxTokens set to ${count === 0 ? "unlimited" : count.toLocaleString()} in ${r.file}`, "info"); }
15583
+ if (count !== undefined && count >= 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxTokens = count; }); workflowUiNotify(ctx, `missions.maxTokens set to ${count === 0 ? "unlimited" : count.toLocaleString()} in ${r.file}`, "info"); }
15422
15584
  }
15423
15585
  } else if (setting === "Runtime Budget") {
15424
15586
  const current = loadWorkflowSettings(ctx.cwd).missions.maxRuntimeHours;
15425
15587
  const choice = await ctx.ui.select("Mission Runtime Budget", ["Default (13 hours)", "Custom..."]);
15426
15588
  if (choice === "Default (13 hours)") {
15427
15589
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxRuntimeHours = 13; });
15428
- ctx.ui.notify(`missions.maxRuntimeHours set to default (13 hours) in ${r.file}`, "info");
15590
+ workflowUiNotify(ctx, `missions.maxRuntimeHours set to default (13 hours) in ${r.file}`, "info");
15429
15591
  } else if (choice === "Custom...") {
15430
15592
  const count = parsePositiveInt((await ctx.ui.input("Enter custom runtime budget (hours)", String(current !== 13 ? current : ""))) ?? "");
15431
- if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxRuntimeHours = count; }); ctx.ui.notify(`missions.maxRuntimeHours set to ${count} hours in ${r.file}`, "info"); }
15593
+ if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxRuntimeHours = count; }); workflowUiNotify(ctx, `missions.maxRuntimeHours set to ${count} hours in ${r.file}`, "info"); }
15432
15594
  }
15433
15595
  } else {
15434
15596
  const count = parsePositiveInt((await ctx.ui.input("checkpointIntervalMinutes", "30")) ?? "");
15435
- if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.checkpointIntervalMinutes = count; }); ctx.ui.notify(`missions.checkpointIntervalMinutes set to ${count} in ${r.file}`, "info"); }
15597
+ if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.checkpointIntervalMinutes = count; }); workflowUiNotify(ctx, `missions.checkpointIntervalMinutes set to ${count} in ${r.file}`, "info"); }
15436
15598
  }
15437
15599
  } else if (choice === "Runtime Budget") {
15438
15600
  const current = loadWorkflowSettings(ctx.cwd).missions.maxRuntimeHours;
15439
15601
  const choice2 = await ctx.ui.select("Mission Runtime Budget", ["Default (13 hours)", "Custom..."]);
15440
15602
  if (choice2 === "Default (13 hours)") {
15441
15603
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxRuntimeHours = 13; });
15442
- ctx.ui.notify(`missions.maxRuntimeHours set to default (13 hours) in ${r.file}`, "info");
15604
+ workflowUiNotify(ctx, `missions.maxRuntimeHours set to default (13 hours) in ${r.file}`, "info");
15443
15605
  } else if (choice2 === "Custom...") {
15444
15606
  const count = parsePositiveInt((await ctx.ui.input("Enter custom runtime budget (hours)", String(current !== 13 ? current : ""))) ?? "");
15445
- if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxRuntimeHours = count; }); ctx.ui.notify(`missions.maxRuntimeHours set to ${count} hours in ${r.file}`, "info"); }
15607
+ if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxRuntimeHours = count; }); workflowUiNotify(ctx, `missions.maxRuntimeHours set to ${count} hours in ${r.file}`, "info"); }
15446
15608
  }
15447
15609
  } else if (choice === "Checkpoint Interval") {
15448
15610
  const count = parsePositiveInt((await ctx.ui.input("checkpointIntervalMinutes", "30")) ?? "");
15449
- if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.checkpointIntervalMinutes = count; }); ctx.ui.notify(`missions.checkpointIntervalMinutes set to ${count} in ${r.file}`, "info"); }
15611
+ if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.checkpointIntervalMinutes = count; }); workflowUiNotify(ctx, `missions.checkpointIntervalMinutes set to ${count} in ${r.file}`, "info"); }
15450
15612
  } else if (choice === "Approval Safety" || choice === "Validation Per Milestone" || choice === "Full Auto Safety" || choice === "Auto Resume") {
15451
15613
  const keyMap: Record<string, keyof ReturnType<typeof loadWorkflowSettings>["missions"]> = { "Validation Per Milestone": "requireValidationPerMilestone", "Approval Safety": "requireApprovalForDestructiveActions", "Full Auto Safety": "allowFullAuto", "Auto Resume": "autoResume" };
15452
15614
  const key = keyMap[choice];
15453
15615
  const enabled = await chooseBool(ctx, `${String(key)}?`);
15454
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as Record<string, unknown>)[String(key)] = enabled; }); ctx.ui.notify(`missions.${String(key)} set to ${enabled} in ${r.file}${key === "allowFullAuto" && enabled === false && r.settings.missions.defaultAutonomy === "full_auto" ? "; full_auto default is retained but blocked" : ""}`, "info"); }
15616
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as Record<string, unknown>)[String(key)] = enabled; }); workflowUiNotify(ctx, `missions.${String(key)} set to ${enabled} in ${r.file}${key === "allowFullAuto" && enabled === false && r.settings.missions.defaultAutonomy === "full_auto" ? "; full_auto default is retained but blocked" : ""}`, "info"); }
15455
15617
  } else if (choice === "Review / Validation Behavior") {
15456
15618
  await showMissionReviewValidationBehaviorMenu(ctx);
15457
15619
  } else if (choice === "Repair / Validation Retry" || choice === "Mission Repair / Validation" || choice === "Repair / Validation Retry Settings") {
@@ -15484,18 +15646,18 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15484
15646
  const enabled = await chooseBool(ctx, "safety.repoLockEnabled for this project only?");
15485
15647
  if (enabled !== undefined) {
15486
15648
  const r = updateSettings(ctx.cwd, "project", (s) => { s.safety.repoLockEnabled = enabled; });
15487
- ctx.ui.notify(`Project Repo Lock set to ${enabled} in ${r.file}. This project override wins over global settings and does not apply to other repos.`, "info");
15649
+ workflowUiNotify(ctx, `Project Repo Lock set to ${enabled} in ${r.file}. This project override wins over global settings and does not apply to other repos.`, "info");
15488
15650
  }
15489
15651
  } else {
15490
15652
  const key = keyMap[choice];
15491
15653
  const enabled = await chooseBool(ctx, `${String(key)}?`);
15492
- if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.safety[key] = enabled; }); ctx.ui.notify(`safety.${String(key)} set to ${enabled} in ${r.file}`, "info"); }
15654
+ if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.safety[key] = enabled; }); workflowUiNotify(ctx, `safety.${String(key)} set to ${enabled} in ${r.file}`, "info"); }
15493
15655
  }
15494
15656
  }
15495
15657
  }
15496
15658
 
15497
- async function showFooterHintsSettingsMenu(ctx: ExtensionContext) {
15498
- if (!ctx.hasUI) return show(pi, renderWorkflowWidgetsStatus(ctx));
15659
+ async function showEditorHintsSettingsMenu(ctx: ExtensionContext) {
15660
+ if (!ctx.hasUI) return show(pi, renderEditorHintsSettings(ctx));
15499
15661
  const options = [
15500
15662
  { label: "Idle Entry Hint", key: "showIdleWorkflowEntryHint" as const },
15501
15663
  { label: "Active Switch Hint", key: "showActiveWorkflowSwitchHint" as const },
@@ -15506,17 +15668,31 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15506
15668
  const settings = loadWorkflowSettings(ctx.cwd);
15507
15669
  const ui = workflowWidgetUi(settings);
15508
15670
  const labels = options.map((option) => `${option.label}: ${ui[option.key] !== false ? "visible" : "hidden"}`);
15509
- const choice = await ctx.ui.select("Footer Hints", [...labels, "List Current Settings", "Back"]);
15671
+ const contrastLabel = `Hint Contrast: ${workflowEditorHintContrastLabel(workflowEditorHintContrast(settings))}`;
15672
+ const choice = await ctx.ui.select("Editor Hints", [...labels, contrastLabel, "List Current Settings", "Back"]);
15510
15673
  if (!choice || choice === "Back") return;
15511
- if (choice === "List Current Settings") { show(pi, renderWorkflowWidgetsStatus(ctx)); continue; }
15674
+ if (choice === "List Current Settings") { show(pi, renderEditorHintsSettings(ctx)); continue; }
15675
+ if (choice === contrastLabel) {
15676
+ const current = workflowEditorHintContrast(settings);
15677
+ const contrastChoice = await ctx.ui.select("Editor Hint Contrast", WORKFLOW_EDITOR_HINT_CONTRASTS.map((contrast) => `${workflowEditorHintContrastLabel(contrast)}${contrast === current ? " (current)" : ""}`).concat("Back"));
15678
+ if (!contrastChoice || contrastChoice === "Back") continue;
15679
+ const contrast = parseEditorHintContrast(contrastChoice.replace(/\s+\(current\)$/, ""));
15680
+ if (contrast) {
15681
+ updateSettings(ctx.cwd, "global", (s) => { workflowWidgetUi(s).editorHintContrast = contrast; });
15682
+ setWorkflowUi(ctx, state, activeSubagents);
15683
+ workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd));
15684
+ workflowUiNotify(ctx, `Editor hint contrast set to ${workflowEditorHintContrastLabel(contrast)}.`, "info");
15685
+ }
15686
+ continue;
15687
+ }
15512
15688
  const index = labels.indexOf(choice);
15513
15689
  const option = options[index];
15514
15690
  if (!option) continue;
15515
15691
  const enabled = await chooseBool(ctx, `ui.${option.key}?`);
15516
15692
  if (enabled !== undefined) {
15517
- const r = updateSettings(ctx.cwd, "global", (s) => { workflowWidgetUi(s)[option.key] = enabled; });
15693
+ updateSettings(ctx.cwd, "global", (s) => { workflowWidgetUi(s)[option.key] = enabled; });
15518
15694
  setWorkflowUi(ctx, state, activeSubagents);
15519
- ctx.ui.notify(`ui.${option.key} set to ${enabled} in ${r.file}`, "info");
15695
+ workflowUiNotify(ctx, `${option.label} ${enabled ? "shown" : "hidden"}.`, "info");
15520
15696
  }
15521
15697
  }
15522
15698
  }
@@ -15524,32 +15700,32 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15524
15700
  async function showUiWidgetsSettingsMenu(ctx: ExtensionContext) {
15525
15701
  if (!ctx.hasUI) return show(pi, renderWorkflowWidgetsStatus(ctx));
15526
15702
  while (ctx.hasUI) {
15527
- const choice = await ctx.ui.select("UI Widgets", ["Plan Top Widget", "Plan Bottom Widget", "Mission Top Widget", "Mission Bottom Widget", "Enable Widget Shortcuts", "Remember Widget Visibility", "Footer Hints", "List Current Settings", "Back"]);
15703
+ const choice = await ctx.ui.select("UI Widgets", ["Plan Top Widget", "Plan Bottom Widget", "Mission Top Widget", "Mission Bottom Widget", "Enable Widget Shortcuts", "Remember Widget Visibility", "Editor Hints", "List Current Settings", "Back"]);
15528
15704
  if (!choice || choice === "Back") return;
15529
15705
  if (choice === "List Current Settings") show(pi, renderWorkflowWidgetsStatus(ctx));
15530
- else if (choice === "Footer Hints") await showFooterHintsSettingsMenu(ctx);
15706
+ else if (choice === "Editor Hints") await showEditorHintsSettingsMenu(ctx);
15531
15707
  else if (choice === "Enable Widget Shortcuts" || choice === "Remember Widget Visibility") {
15532
15708
  const key = choice === "Enable Widget Shortcuts" ? "enableWidgetShortcuts" : "rememberWidgetVisibility";
15533
15709
  const enabled = await chooseBool(ctx, `ui.${key}?`);
15534
15710
  if (enabled !== undefined) {
15535
- const r = updateSettings(ctx.cwd, "global", (s) => { workflowWidgetUi(s)[key] = enabled; });
15711
+ updateSettings(ctx.cwd, "global", (s) => { workflowWidgetUi(s)[key] = enabled; });
15536
15712
  setWorkflowUi(ctx, state, activeSubagents);
15537
- ctx.ui.notify(`ui.${key} set to ${enabled} in ${r.file}`, "info");
15713
+ workflowUiNotify(ctx, `${choice} ${enabled ? "enabled" : "disabled"}.`, "info");
15538
15714
  }
15539
15715
  } else {
15540
15716
  const slot: WorkflowWidgetSlot = choice === "Plan Top Widget" ? "planTop" : choice === "Plan Bottom Widget" ? "planBottom" : choice === "Mission Top Widget" ? "missionTop" : "missionBottom";
15541
15717
  const visible = await chooseBool(ctx, `${widgetSlotLabel(slot)} visible?`);
15542
- if (visible !== undefined) ctx.ui.notify(setWorkflowWidgetVisibility(ctx, slot, visible), "info");
15718
+ if (visible !== undefined) workflowUiNotify(ctx, setWorkflowWidgetVisibility(ctx, slot, visible), "info");
15543
15719
  }
15544
15720
  }
15545
15721
  }
15546
15722
 
15547
15723
  function presetUsage(): string {
15548
- return "# Workflow Presets\n\nQuick use:\n- /workflow presets opens the selector\n- Ctrl+Shift+U cycles saved presets from the footer only while Plan/Mission/Standard Mode is active\n- /workflow presets list\n- /workflow presets apply <name>\n- /workflow presets next\n- /workflow presets prev\n- /workflow presets save <name>\n- /workflow presets create <name> from simple|standard|deep|maximum\n- /workflow presets edit <name>\n- /workflow presets rename <old> to <new>\n- /workflow presets delete <name>";
15724
+ return `# Workflow Presets\n\nQuick use:\n- /workflow presets opens the selector\n- ${workflowPresetCycleShortcutLabel()} cycles saved presets from the footer only while Plan/Mission/Standard Mode is active\n- /workflow presets list\n- /workflow presets apply <name>\n- /workflow presets next\n- /workflow presets prev\n- /workflow presets save <name>\n- /workflow presets create <name> from simple|standard|deep|maximum\n- /workflow presets edit <name>\n- /workflow presets rename <old> to <new>\n- /workflow presets delete <name>`;
15549
15725
  }
15550
15726
 
15551
15727
  function presetActionMessage(title: string, name: string, resultFile?: string, scope?: string): string {
15552
- return `# ${title}\n\nPreset: ${name}\n${scope ? `Scope: ${scope}\n` : ""}${resultFile ? `File: ${resultFile}\n` : ""}\nScope note: presets apply across Standard Mode, Plan Mode, Mission Mode, shared sub-agents, and selected UI settings.\nUse selector: /workflow presets\nCycle saved presets: Ctrl+Shift+U while Plan/Mission/Standard Mode is active\nFooter: idle displays Plan/Mission entry shortcuts only; active workflows display compact widget/preset hints and workflow switch hints by default.\n\nModel/provider choices and shared compaction settings are preserved.`;
15728
+ return `# ${title}\n\nPreset: ${name}\n${scope ? `Scope: ${scope}\n` : ""}${resultFile ? `File: ${resultFile}\n` : ""}\nScope note: presets apply across Standard Mode, Plan Mode, Mission Mode, shared sub-agents, and selected UI settings.\nUse selector: /workflow presets\nCycle saved presets: ${workflowPresetCycleShortcutLabel()} while Plan/Mission/Standard Mode is active\nFooter: idle displays Plan/Mission entry shortcuts only; active workflows display compact widget/preset hints and workflow switch hints by default.\n\nModel/provider choices and shared compaction settings are preserved.`;
15553
15729
  }
15554
15730
 
15555
15731
  function parsePresetCreate(rest: string): { name: string; template?: string } {
@@ -15577,7 +15753,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15577
15753
  const { names, options } = presetDisplayOptions(settings);
15578
15754
  if (!ctx.hasUI) return show(pi, renderWorkflowPresets(settings));
15579
15755
  if (names.length === 0) return show(pi, "# Workflow Presets\n\nNo presets available.");
15580
- const choice = await ctx.ui.select(`Workflow Presets — active: ${activeWorkflowPresetLabel(settings)} — Ctrl+Shift+U cycles during Plan/Mission`, options);
15756
+ const choice = await ctx.ui.select(`Workflow Presets — active: ${activeWorkflowPresetLabel(settings)} — ${workflowPresetCycleShortcutLabel()} cycles during Plan/Mission`, options);
15581
15757
  if (!choice) return;
15582
15758
  const selected = names[options.indexOf(choice)];
15583
15759
  if (!selected) return;
@@ -15591,14 +15767,14 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15591
15767
  const result = applyWorkflowPreset(ctx.cwd, undefined, resolved);
15592
15768
  setWorkflowUi(ctx, state, activeSubagents);
15593
15769
  const label = workflowPresetLabel(resolved, workflowPresetCatalog(result.settings)[resolved]);
15594
- if (notifyOnly) ctx.ui.notify(`Workflow preset active: ${label}`, "info");
15770
+ if (notifyOnly) workflowUiNotify(ctx, `Workflow preset active: ${label}`, "info");
15595
15771
  else show(pi, presetActionMessage("Workflow Preset Applied", label, result.file, result.scope));
15596
15772
  }
15597
15773
 
15598
15774
  async function markWorkflowPresetCustom(ctx: ExtensionContext): Promise<void> {
15599
15775
  const result = updateSettings(ctx.cwd, undefined, (s) => { s.presets = { ...(s.presets ?? {}), activePreset: WORKFLOW_CUSTOM_PRESET_MARKER, items: { ...(s.presets?.items ?? {}) } }; });
15600
15776
  setWorkflowUi(ctx, state, activeSubagents);
15601
- ctx.ui.notify(`Workflow preset marker cleared in ${result.file}; workflow settings unchanged.`, "info");
15777
+ workflowUiNotify(ctx, `Workflow preset marker cleared in ${result.file}; workflow settings unchanged.`, "info");
15602
15778
  }
15603
15779
 
15604
15780
  async function cycleWorkflowPreset(ctx: ExtensionContext, direction: 1 | -1): Promise<void> {
@@ -15666,7 +15842,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15666
15842
  if (policy) updateSettings(ctx.cwd, undefined, (s) => { const item = (s.presets!.items![name] ??= { planning: {}, workflow: {}, missions: {}, subagents: {} }); item.subagents = { ...(item.subagents ?? {}), planningPolicy: policy, executionPolicy: policy, repairPolicy: policy, reviewPolicy: policy, validationPolicy: policy }; });
15667
15843
  }
15668
15844
  setWorkflowUi(ctx, state, activeSubagents);
15669
- ctx.ui.notify(`Preset ${name} updated in ${r.file}`, "info");
15845
+ workflowUiNotify(ctx, `Preset ${name} updated in ${r.file}`, "info");
15670
15846
  } catch (e) { show(pi, `# Workflow Preset Error\n\n${e instanceof Error ? e.message : String(e)}`); }
15671
15847
  }
15672
15848
  }
@@ -15706,7 +15882,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15706
15882
  const r = createWorkflowPreset(ctx.cwd, undefined, parsed.name, parsed.template);
15707
15883
  setWorkflowUi(ctx, state, activeSubagents);
15708
15884
  const safe = normalizeWorkflowPresetName(parsed.name);
15709
- return show(pi, `# Workflow Preset Created\n\nPreset: ${parsed.name}\nSaved As: ${safe}\n${parsed.template ? `Template: ${parsed.template}\n` : ""}Scope: ${r.scope}\nFile: ${r.file}\n\nThe preset was saved but not applied.\nScope note: presets apply across Standard Mode, Plan Mode, Mission Mode, shared sub-agents, and selected UI settings.\nApply now: /workflow presets apply ${safe}\nOpen selector: /workflow presets\nCycle saved presets: Ctrl+Shift+U while Plan/Mission/Standard Mode is active`);
15885
+ return show(pi, `# Workflow Preset Created\n\nPreset: ${parsed.name}\nSaved As: ${safe}\n${parsed.template ? `Template: ${parsed.template}\n` : ""}Scope: ${r.scope}\nFile: ${r.file}\n\nThe preset was saved but not applied.\nScope note: presets apply across Standard Mode, Plan Mode, Mission Mode, shared sub-agents, and selected UI settings.\nApply now: /workflow presets apply ${safe}\nOpen selector: /workflow presets\nCycle saved presets: ${workflowPresetCycleShortcutLabel()} while Plan/Mission/Standard Mode is active`);
15710
15886
  }
15711
15887
  if (action === "configure" || action === "edit") {
15712
15888
  if (!rest) return show(pi, "# Workflow Presets\n\nUsage: /workflow presets edit <name>");
@@ -15761,7 +15937,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15761
15937
  async function showCustomBrandStartupVisualMenu(ctx: ExtensionContext): Promise<boolean | undefined> {
15762
15938
  if (!ctx.hasUI) return undefined;
15763
15939
  const saved = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupVisual = "custom_brand"; });
15764
- ctx.ui.notify(`ui.startupVisual set to custom_brand in ${saved.file}`, "info");
15940
+ workflowUiNotify(ctx, `ui.startupVisual set to custom_brand in ${saved.file}`, "info");
15765
15941
  while (ctx.hasUI) {
15766
15942
  const choice = await ctx.ui.select("Custom Brand Startup Visual", ["Set Text", "Choose Base Template", "Preview", "List Theme Settings", "Back"]);
15767
15943
  if (!choice || choice === "Back") return undefined;
@@ -15770,13 +15946,13 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15770
15946
  } else if (choice === "Set Text") {
15771
15947
  const text = sanitizeCustomBrandText(await ctx.ui.input("Custom brand text", sanitizeCustomBrandText(loadWorkflowSettings(ctx.cwd).ui.customBrandText) || "WORKFLOW SUITE"));
15772
15948
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.customBrandEnabled = true; s.ui.customBrandText = text; s.ui.startupVisual = "custom_brand"; });
15773
- ctx.ui.notify(`ui.customBrandText set in ${r.file}`, "info");
15949
+ workflowUiNotify(ctx, `ui.customBrandText set in ${r.file}`, "info");
15774
15950
  void showStartupVisual(ctx, { intent: "manual" });
15775
15951
  } else if (choice === "Choose Base Template") {
15776
15952
  const base = parseCustomBrandBaseVisual((await ctx.ui.select("Custom brand base template", WORKFLOW_CUSTOM_BRAND_BASE_VISUALS)) ?? "");
15777
15953
  if (base) {
15778
15954
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.customBrandBaseVisual = base; s.ui.startupVisual = "custom_brand"; });
15779
- ctx.ui.notify(`ui.customBrandBaseVisual set to ${base} in ${r.file}`, "info");
15955
+ workflowUiNotify(ctx, `ui.customBrandBaseVisual set to ${base} in ${r.file}`, "info");
15780
15956
  void showStartupVisual(ctx, { intent: "manual" });
15781
15957
  }
15782
15958
  } else if (choice === "Preview") {
@@ -15798,27 +15974,27 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15798
15974
  const text = startupLogoText(loadWorkflowSettings(ctx.cwd)) || "WFS";
15799
15975
  const value = sanitizeCustomBrandText(await ctx.ui.input("Custom logo letters (max 6 A-Z/0-9)", text)).toUpperCase().replace(/[^A-Z0-9]/g, "").slice(0, 6);
15800
15976
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupLogo = "custom"; s.ui.startupLogoText = value; });
15801
- ctx.ui.notify(`ui.startupLogoText set to ${value || "(empty)"} in ${r.file}`, "info");
15977
+ workflowUiNotify(ctx, `ui.startupLogoText set to ${value || "(empty)"} in ${r.file}`, "info");
15802
15978
  void showStartupVisual(ctx, { intent: "manual" });
15803
15979
  } else if (choice === "Choose Font") {
15804
15980
  const font = parseStartupLogoFont((await ctx.ui.select("Custom logo font", WORKFLOW_STARTUP_LOGO_FONTS)) ?? "");
15805
15981
  if (font) {
15806
15982
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupLogo = "custom"; s.ui.startupLogoFont = font; });
15807
- ctx.ui.notify(`ui.startupLogoFont set to ${font} in ${r.file}`, "info");
15983
+ workflowUiNotify(ctx, `ui.startupLogoFont set to ${font} in ${r.file}`, "info");
15808
15984
  void showStartupVisual(ctx, { intent: "manual" });
15809
15985
  }
15810
15986
  } else if (choice === "Choose Shadow Direction") {
15811
15987
  const direction = parseStartupLogoShadowDirection((await ctx.ui.select("Custom logo shadow direction", WORKFLOW_STARTUP_LOGO_SHADOW_DIRECTIONS)) ?? "");
15812
15988
  if (direction) {
15813
15989
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupLogo = "custom"; s.ui.startupLogoShadowDirection = direction; });
15814
- ctx.ui.notify(`ui.startupLogoShadowDirection set to ${direction} in ${r.file}`, "info");
15990
+ workflowUiNotify(ctx, `ui.startupLogoShadowDirection set to ${direction} in ${r.file}`, "info");
15815
15991
  void showStartupVisual(ctx, { intent: "manual" });
15816
15992
  }
15817
15993
  } else if (choice === "Choose Color Style") {
15818
15994
  const colorStyle = parseStartupLogoColorStyle((await ctx.ui.select("Custom logo color style", WORKFLOW_STARTUP_LOGO_COLOR_STYLES)) ?? "");
15819
15995
  if (colorStyle) {
15820
15996
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupLogo = "custom"; s.ui.startupLogoColorStyle = colorStyle; });
15821
- ctx.ui.notify(`ui.startupLogoColorStyle set to ${colorStyle} in ${r.file}`, "info");
15997
+ workflowUiNotify(ctx, `ui.startupLogoColorStyle set to ${colorStyle} in ${r.file}`, "info");
15822
15998
  void showStartupVisual(ctx, { intent: "manual" });
15823
15999
  }
15824
16000
  } else if (choice === "Preview") {
@@ -15843,7 +16019,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15843
16019
  } else {
15844
16020
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupVisual = visual; });
15845
16021
  const canPreview = startupVisualOrDefault(r.settings) !== "none";
15846
- ctx.ui.notify(canPreview ? `Startup visual set to ${visual} in ${r.file}` : `Startup visual set to ${visual} (disabled) in ${r.file}`, "info");
16022
+ workflowUiNotify(ctx, canPreview ? `Startup visual set to ${visual} in ${r.file}` : `Startup visual set to ${visual} (disabled) in ${r.file}`, "info");
15847
16023
  if (canPreview) void showStartupVisual(ctx, { intent: "manual" });
15848
16024
  }
15849
16025
  }
@@ -15851,14 +16027,14 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15851
16027
  const name = parseWidgetTextPreset((await ctx.ui.select("Startup text style", (WORKFLOW_WIDGET_TEXT_PRESETS as readonly string[]).map((p) => WORKFLOW_WIDGET_TEXT_PRESET_LABELS[p]))) ?? "");
15852
16028
  if (name) {
15853
16029
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupTextStyle = name; });
15854
- ctx.ui.notify(`Startup text style set to ${WORKFLOW_WIDGET_TEXT_PRESET_LABELS[name]} in ${r.file}.`, "info");
16030
+ workflowUiNotify(ctx, `Startup text style set to ${WORKFLOW_WIDGET_TEXT_PRESET_LABELS[name]} in ${r.file}.`, "info");
15855
16031
  void showStartupVisual(ctx, { intent: "manual" });
15856
16032
  }
15857
16033
  } else if (choice === "Turn On" || choice === "Turn Off") {
15858
16034
  const visual: WorkflowStartupVisual = choice === "Turn On" ? "mission_control" : "none";
15859
16035
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupVisual = visual; });
15860
16036
  const canPreview = startupVisualOrDefault(r.settings) !== "none";
15861
- ctx.ui.notify(canPreview ? `Startup visual turned on (${visual}) in ${r.file}` : `Startup visual turned off in ${r.file}`, "info");
16037
+ workflowUiNotify(ctx, canPreview ? `Startup visual turned on (${visual}) in ${r.file}` : `Startup visual turned off in ${r.file}`, "info");
15862
16038
  if (canPreview) void showStartupVisual(ctx, { intent: "manual" });
15863
16039
  } else if (choice === "On Session Start") {
15864
16040
  const enabled = await chooseBool(ctx, "Show startup visual on session start?");
@@ -15867,12 +16043,12 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15867
16043
  s.ui.startupVisualOnSessionStart = enabled;
15868
16044
  if (enabled === true && (parseStartupVisual(s.ui.startupVisual) ?? "none") === "none") s.ui.startupVisual = "minimal";
15869
16045
  });
15870
- ctx.ui.notify(`Startup on session start ${enabled ? "enabled" : "disabled"} in ${r.file}`, "info");
16046
+ workflowUiNotify(ctx, `Startup on session start ${enabled ? "enabled" : "disabled"} in ${r.file}`, "info");
15871
16047
  void showStartupVisual(ctx, { intent: "manual" });
15872
16048
  }
15873
16049
  } else if (choice === "Preview") {
15874
16050
  const previewed = await showStartupVisual(ctx, { intent: "manual" });
15875
- if (!previewed) ctx.ui.notify("Startup visual is disabled. Choose a visual or turn it on to preview.", "info");
16051
+ if (!previewed) workflowUiNotify(ctx, "Startup visual is disabled. Choose a visual or turn it on to preview.", "info");
15876
16052
  }
15877
16053
  }
15878
16054
  return undefined;
@@ -15901,7 +16077,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15901
16077
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.workflowTheme = name; });
15902
16078
  applyWorkflowEditorTheme(ctx);
15903
16079
  setWorkflowUi(ctx, state, activeSubagents);
15904
- ctx.ui.notify(`ui.workflowTheme set to ${workflowThemeDisplayName(name)} in ${r.file}`, "info");
16080
+ workflowUiNotify(ctx, `ui.workflowTheme set to ${workflowThemeDisplayName(name)} in ${r.file}`, "info");
15905
16081
  void showStartupVisual(ctx, { intent: "manual" });
15906
16082
  }
15907
16083
  } else if (choice === "Startup Visual") {
@@ -15910,7 +16086,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15910
16086
  const logo = parseStartupLogo((await ctx.ui.select("Startup logo", WORKFLOW_STARTUP_LOGOS)) ?? "");
15911
16087
  if (logo) {
15912
16088
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupLogo = logo; });
15913
- ctx.ui.notify(`ui.startupLogo set to ${logo} in ${r.file}`, "info");
16089
+ workflowUiNotify(ctx, `ui.startupLogo set to ${logo} in ${r.file}`, "info");
15914
16090
  if (logo === "custom") await showCustomStartupLogoMenu(ctx);
15915
16091
  else void showStartupVisual(ctx, { intent: "manual" });
15916
16092
  }
@@ -16070,20 +16246,20 @@ Pi Version: v${VERSION}
16070
16246
  workflowLastAutoCompactionAt = Date.now();
16071
16247
  clearDeferredWorkflowCompaction();
16072
16248
  rememberWorkflowCompactionCheck(`${checkpoint} boundary triggered at ${percent.toFixed(1)}% context`);
16073
- try { ctx.ui.notify(`Workflow auto-compaction triggered at ${percent.toFixed(1)}% context usage.`, "info"); } catch { /* UI may be unavailable */ }
16249
+ try { workflowUiNotify(ctx, `Workflow auto-compaction triggered at ${percent.toFixed(1)}% context usage.`, "info"); } catch { /* UI may be unavailable */ }
16074
16250
  ctx.compact({
16075
16251
  customInstructions,
16076
16252
  onComplete: () => {
16077
16253
  workflowAutoCompactionRunning = false;
16078
16254
  workflowLastAutoCompactionAt = Date.now();
16079
16255
  rememberWorkflowCompactionCheck(`${checkpoint} boundary compaction completed`);
16080
- try { ctx.ui.notify("Workflow auto-compaction complete.", "info"); } catch { /* UI may be unavailable */ }
16256
+ try { workflowUiNotify(ctx, "Workflow auto-compaction complete.", "info"); } catch { /* UI may be unavailable */ }
16081
16257
  },
16082
16258
  onError: (error: Error) => {
16083
16259
  workflowAutoCompactionRunning = false;
16084
16260
  rememberWorkflowCompactionCheck(`${checkpoint} boundary compaction failed — ${error.message}`);
16085
16261
  rememberCustomCompactionStatus(`proactive compaction request failed: ${error.message}`);
16086
- try { ctx.ui.notify(`Workflow auto-compaction skipped: ${error.message}`, "warning"); } catch { /* UI may be unavailable */ }
16262
+ try { workflowUiNotify(ctx, `Workflow auto-compaction skipped: ${error.message}`, "warning"); } catch { /* UI may be unavailable */ }
16087
16263
  },
16088
16264
  });
16089
16265
  }
@@ -16136,7 +16312,7 @@ Pi Version: v${VERSION}
16136
16312
  const model = ctx.modelRegistry.find(provider, modelId);
16137
16313
  if (!model) {
16138
16314
  rememberCustomCompactionStatus(`fallback to Pi default: model not found ${provider}/${modelId}`);
16139
- ctx.ui.notify(`Custom compaction model not found: ${provider}/${modelId}; using Pi default compaction.`, "warning");
16315
+ workflowUiNotify(ctx, `Custom compaction model not found: ${provider}/${modelId}; using Pi default compaction.`, "warning");
16140
16316
  return;
16141
16317
  }
16142
16318
 
@@ -16144,12 +16320,12 @@ Pi Version: v${VERSION}
16144
16320
  if (auth.ok === false) {
16145
16321
  const authError = auth.error;
16146
16322
  rememberCustomCompactionStatus(`fallback to Pi default: auth failed for ${provider}/${modelId}: ${authError}`);
16147
- ctx.ui.notify(`Custom compaction auth failed for ${provider}/${modelId}: ${authError}; using Pi default compaction.`, "warning");
16323
+ workflowUiNotify(ctx, `Custom compaction auth failed for ${provider}/${modelId}: ${authError}; using Pi default compaction.`, "warning");
16148
16324
  return;
16149
16325
  }
16150
16326
  if (!auth.apiKey) {
16151
16327
  rememberCustomCompactionStatus(`fallback to Pi default: no API key for ${provider}/${modelId}`);
16152
- ctx.ui.notify(`No API key for custom compaction model ${provider}/${modelId}; using Pi default compaction.`, "warning");
16328
+ workflowUiNotify(ctx, `No API key for custom compaction model ${provider}/${modelId}; using Pi default compaction.`, "warning");
16153
16329
  return;
16154
16330
  }
16155
16331
 
@@ -16161,14 +16337,14 @@ Pi Version: v${VERSION}
16161
16337
  const fitNote = fitted.adjusted && fitted.safeInputTokens
16162
16338
  ? ` Adaptive fit: summarizing about ${Math.round(fitted.inputTokens).toLocaleString()} tokens within ${Math.round(fitted.safeInputTokens).toLocaleString()} safe input tokens for the compaction model.`
16163
16339
  : "";
16164
- ctx.ui.notify(`Custom compaction using ${provider}/${modelId}. Keep recent: ${customCompactionKeepRecentTokens(settings).toLocaleString()} tokens; reserve: ${customCompactionReserveTokens(settings).toLocaleString()} tokens.${fitNote}`, "info");
16340
+ workflowUiNotify(ctx, `Custom compaction using ${provider}/${modelId}. Keep recent: ${customCompactionKeepRecentTokens(settings).toLocaleString()} tokens; reserve: ${customCompactionReserveTokens(settings).toLocaleString()} tokens.${fitNote}`, "info");
16165
16341
  const result = await compactionApi.compact(fitted.preparation, model, auth.apiKey, auth.headers, event.customInstructions, event.signal);
16166
16342
  rememberCustomCompactionStatus(`custom compaction succeeded using ${provider}/${modelId}${fitted.adjusted ? " with adaptive context fit" : ""}`);
16167
16343
  return { compaction: result };
16168
16344
  } catch (error) {
16169
16345
  const message = error instanceof Error ? error.message : String(error);
16170
16346
  rememberCustomCompactionStatus(`fallback to Pi default: custom compaction failed for ${provider}/${modelId}: ${message}`);
16171
- if (!event.signal.aborted) ctx.ui.notify(`Custom compaction failed: ${message}; using Pi default compaction.`, "warning");
16347
+ if (!event.signal.aborted) workflowUiNotify(ctx, `Custom compaction failed: ${message}; using Pi default compaction.`, "warning");
16172
16348
  return;
16173
16349
  }
16174
16350
  });
@@ -16607,48 +16783,55 @@ Pi Version: v${VERSION}
16607
16783
  pi.registerCommand("m retry", { description: "Retry validation repair flow for current mission.", handler: async (_args, ctx) => handleMissionCommand("retry", ctx) });
16608
16784
  pi.registerCommand("m revalidate", { description: "Revalidate current mission milestone.", handler: async (_args, ctx) => handleMissionCommand("revalidate", ctx) });
16609
16785
 
16786
+ const workflowShortcutHandlers: Record<WorkflowShortcutActionId, (ctx: ExtensionContext) => Promise<void> | void> = {
16787
+ "workflow.widget.top.toggle": async (ctx) => {
16788
+ if (workflowWidgetUi(loadGlobalSettings()).enableWidgetShortcuts === false) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd), "Top:disabled"); return; }
16789
+ const slot = activeTopWidgetSlot();
16790
+ if (!slot) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd)); return; }
16791
+ toggleWorkflowWidget(ctx, slot);
16792
+ setWorkflowWidgetShortcutStatus(ctx, slot);
16793
+ },
16794
+ "workflow.widget.bottom.toggle": async (ctx) => {
16795
+ if (workflowWidgetUi(loadGlobalSettings()).enableWidgetShortcuts === false) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd), "Bottom:disabled"); return; }
16796
+ if (isPlanWorkflowUiMode(state) && planBottomRelevant(state)) {
16797
+ toggleWorkflowWidget(ctx, "planBottom");
16798
+ return setWorkflowWidgetShortcutStatus(ctx, "planBottom");
16799
+ }
16800
+ if (isMissionWorkflowMode(state) && missionBottomRelevant(state, activeMissionForUi(state))) {
16801
+ toggleWorkflowWidget(ctx, "missionBottom");
16802
+ return setWorkflowWidgetShortcutStatus(ctx, "missionBottom");
16803
+ }
16804
+ if (isStandardWorkflowMode(state)) {
16805
+ toggleWorkflowWidget(ctx, "standardBottom");
16806
+ return setWorkflowWidgetShortcutStatus(ctx, "standardBottom");
16807
+ }
16808
+ workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd)); return;
16809
+ },
16810
+ "workflow.presets.cycle": async (ctx) => {
16811
+ if (workflowWidgetUi(loadGlobalSettings()).enableWidgetShortcuts === false) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd), "Preset:disabled"); return; }
16812
+ if (!isPlanWorkflowUiMode(state) && !isMissionWorkflowMode(state) && !isStandardWorkflowMode(state)) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd)); return; }
16813
+ await cycleWorkflowPreset(ctx, 1);
16814
+ },
16815
+ "workflow.standard.toggle": async (ctx) => {
16816
+ if (isStandardWorkflowMode(state)) return exitStandardModeToIdle(ctx);
16817
+ await enterStandardMode(ctx);
16818
+ },
16819
+ "workflow.plan.toggle": async (ctx) => {
16820
+ if (isPlanWorkflowUiMode(state)) return exitPlanModeToIdle(ctx);
16821
+ await enterPlanModeAwaitingInput(ctx);
16822
+ },
16823
+ "workflow.mission.toggle": async (ctx) => {
16824
+ if (isMissionWorkflowMode(state)) return exitMissionModeToIdle(ctx);
16825
+ await enterMissionModeAwaitingInput(ctx);
16826
+ },
16827
+ };
16610
16828
 
16611
-
16612
- pi.registerShortcut("ctrl+shift+t", { description: "Toggle active Plan/Mission/Standard top workflow widget", handler: async (ctx) => {
16613
- if (workflowWidgetUi(loadGlobalSettings()).enableWidgetShortcuts === false) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd), "Top:disabled"); return; }
16614
- const slot = activeTopWidgetSlot();
16615
- if (!slot) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd)); return; }
16616
- toggleWorkflowWidget(ctx, slot);
16617
- setWorkflowWidgetShortcutStatus(ctx, slot);
16618
- }});
16619
- pi.registerShortcut("ctrl+shift+b", { description: "Toggle active Plan/Mission/Standard bottom workflow widget", handler: async (ctx) => {
16620
- if (workflowWidgetUi(loadGlobalSettings()).enableWidgetShortcuts === false) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd), "Bottom:disabled"); return; }
16621
- if (isPlanWorkflowUiMode(state) && planBottomRelevant(state)) {
16622
- toggleWorkflowWidget(ctx, "planBottom");
16623
- return setWorkflowWidgetShortcutStatus(ctx, "planBottom");
16624
- }
16625
- if (isMissionWorkflowMode(state) && missionBottomRelevant(state, activeMissionForUi(state))) {
16626
- toggleWorkflowWidget(ctx, "missionBottom");
16627
- return setWorkflowWidgetShortcutStatus(ctx, "missionBottom");
16628
- }
16629
- if (isStandardWorkflowMode(state)) {
16630
- toggleWorkflowWidget(ctx, "standardBottom");
16631
- return setWorkflowWidgetShortcutStatus(ctx, "standardBottom");
16632
- }
16633
- workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd)); return;
16634
- }});
16635
- pi.registerShortcut("ctrl+shift+u", { description: "Cycle workflow presets during Plan/Mission/Standard Mode", handler: async (ctx) => {
16636
- if (workflowWidgetUi(loadGlobalSettings()).enableWidgetShortcuts === false) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd), "Preset:disabled"); return; }
16637
- if (!isPlanWorkflowUiMode(state) && !isMissionWorkflowMode(state) && !isStandardWorkflowMode(state)) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd)); return; }
16638
- await cycleWorkflowPreset(ctx, 1);
16639
- }});
16640
- pi.registerShortcut("ctrl+shift+s", { description: "Toggle Standard Mode", handler: async (ctx) => {
16641
- if (isStandardWorkflowMode(state)) return exitStandardModeToIdle(ctx);
16642
- await enterStandardMode(ctx);
16643
- }});
16644
- pi.registerShortcut("ctrl+shift+l", { description: "Enter Plan Mode", handler: async (ctx) => {
16645
- if (isPlanWorkflowUiMode(state)) return exitPlanModeToIdle(ctx);
16646
- await enterPlanModeAwaitingInput(ctx);
16647
- }});
16648
- pi.registerShortcut("ctrl+shift+m", { description: "Toggle Mission Mode", handler: async (ctx) => {
16649
- if (isMissionWorkflowMode(state)) return exitMissionModeToIdle(ctx);
16650
- await enterMissionModeAwaitingInput(ctx);
16651
- }});
16829
+ for (const shortcut of WORKFLOW_SHORTCUTS) {
16830
+ pi.registerShortcut(workflowShortcutKey(shortcut.id), {
16831
+ description: shortcut.description,
16832
+ handler: workflowShortcutHandlers[shortcut.id],
16833
+ });
16834
+ }
16652
16835
 
16653
16836
  const handleWorkflowPlansCommand = async (args: string, _ctx: ExtensionContext): Promise<void> => {
16654
16837
  const parts = args.trim().split(/\s+/).filter(Boolean);
@@ -17025,6 +17208,14 @@ Pi Version: v${VERSION}
17025
17208
  setWorkflowUi(ctx, state, activeSubagents);
17026
17209
  return show(pi, updatedMessage(result.scope, result.file, `ui.${key}`, String(bool)));
17027
17210
  }
17211
+ if (subject === "ui" && key === "editorHintContrast") {
17212
+ const contrast = parseEditorHintContrast(value);
17213
+ if (!contrast) return show(pi, "# Error\n\nUsage: `/workflow-settings set ui editorHintContrast <subtle|normal|bright|high>`");
17214
+ const result = updateSettings(ctx.cwd, scope ?? "global", (s) => { workflowWidgetUi(s).editorHintContrast = contrast; });
17215
+ setWorkflowUi(ctx, state, activeSubagents);
17216
+ workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd));
17217
+ return show(pi, updatedMessage(result.scope, result.file, "ui.editorHintContrast", contrast));
17218
+ }
17028
17219
  if (subject === "subagents" && (key === "enabled" || key === "activityIndicatorEnabled" || key === "autoUseDuringPlanning" || key === "autoUseDuringExecution" || key === "autoUseDuringRepair" || key === "autoUseDuringReview" || key === "autoUseDuringValidation" || key === "allowParallelReadOnly" || key === "allowParallelPlanning" || key === "allowParallelExecution" || key === "allowParallelRepair" || key === "allowParallelReview" || key === "allowParallelValidation" || key === "allowParallelEdits" || key === "requireParallelEditConflictProtection" || key === "allowBackgroundSubagents")) {
17029
17220
  if (bool === undefined) return show(pi, "# Error\n\nUsage: `/workflow-settings set subagents <enabled|activityIndicatorEnabled|autoUseDuringPlanning|autoUseDuringExecution|autoUseDuringRepair|autoUseDuringReview|autoUseDuringValidation|allowParallelReadOnly|allowParallelPlanning|allowParallelExecution|allowParallelRepair|allowParallelReview|allowParallelValidation|allowParallelEdits|requireParallelEditConflictProtection> <true|false>`");
17030
17221
  const result = updateSettings(ctx.cwd, scope, (s) => {