@mediadatafusion/pi-workflow-suite 0.0.18 → 0.0.19

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,7 +8,7 @@ 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";
@@ -2680,6 +2680,7 @@ UI Widgets:
2680
2680
  - /workflow-settings set ui showActiveWorkflowSwitchHint true|false
2681
2681
  - /workflow-settings set ui showWidgetShortcutHint true|false
2682
2682
  - /workflow-settings set ui showPresetShortcutHint true|false
2683
+ - /workflow-settings set ui editorHintContrast subtle|normal|bright|high
2683
2684
 
2684
2685
  Sub-agents and parallelism:
2685
2686
  - /workflow-settings set subagents enabled true|false
@@ -3684,7 +3685,7 @@ ${renderPlanModelSettings(settings)}
3684
3685
 
3685
3686
  ${renderMissionModelStrategy(settings)}
3686
3687
 
3687
- ## UI / Footer
3688
+ ## UI / Widgets
3688
3689
  Plan Top Widget: ${widgetVisibilityLabel(settings, "planTop")}
3689
3690
  Plan Bottom Widget: ${widgetVisibilityLabel(settings, "planBottom")}
3690
3691
  Mission Top Widget: ${widgetVisibilityLabel(settings, "missionTop")}
@@ -3695,6 +3696,7 @@ Idle Entry Hint: ${workflowWidgetUi(settings).showIdleWorkflowEntryHint !== fals
3695
3696
  Active Switch Hint: ${workflowWidgetUi(settings).showActiveWorkflowSwitchHint !== false ? "visible" : "hidden"}
3696
3697
  Widget Shortcut Hint: ${workflowWidgetUi(settings).showWidgetShortcutHint !== false ? "visible" : "hidden"}
3697
3698
  Preset Shortcut Hint: ${workflowWidgetUi(settings).showPresetShortcutHint !== false ? "visible" : "hidden"}
3699
+ Editor Hint Contrast: ${workflowEditorHintContrastLabel(workflowEditorHintContrast(settings))}
3698
3700
  Workflow Theme: ${workflowThemeDisplayName(workflowThemeName(settings))}
3699
3701
  Startup Visual: ${startupVisualOrDefault(settings)}
3700
3702
  Startup Logo: ${startupLogoOrDefault(settings)}
@@ -5527,8 +5529,8 @@ class WorkflowSuiteEditor extends CustomEditor {
5527
5529
  try {
5528
5530
  const settings = loadWorkflowSettings(this.workflowCwd);
5529
5531
  const decorate = workflowRoleTextDecoration(settings, "muted");
5530
- let hintStyled = `\x1b[2m\x1b[38;5;240m${workflowEditorHintText}\x1b[0m`;
5531
- if (decorate) hintStyled = decorate(hintStyled);
5532
+ let hintStyled = workflowEditorHintStyledText(settings, workflowEditorHintText);
5533
+ if (workflowEditorHintContrast(settings) === "subtle" && decorate) hintStyled = decorate(hintStyled);
5532
5534
  const innerWidth = width - 2;
5533
5535
  const hintLen = visibleTextWidth(hintStyled);
5534
5536
  const displayHint = hintLen > innerWidth ? truncateVisibleText(hintStyled, innerWidth) : hintStyled;
@@ -6525,6 +6527,13 @@ function isMissionWorkflowMode(state: WorkflowState): boolean {
6525
6527
  }
6526
6528
 
6527
6529
  type WorkflowWidgetSlot = "planTop" | "planBottom" | "missionTop" | "missionBottom" | "standardTop" | "standardBottom";
6530
+ const WORKFLOW_EDITOR_HINT_CONTRASTS: WorkflowEditorHintContrast[] = ["subtle", "normal", "bright", "high"];
6531
+ const WORKFLOW_EDITOR_HINT_CONTRAST_LABELS: Record<WorkflowEditorHintContrast, string> = {
6532
+ subtle: "Subtle",
6533
+ normal: "Normal",
6534
+ bright: "Bright",
6535
+ high: "High Contrast",
6536
+ };
6528
6537
  type WorkflowWidgetUiSettings = ReturnType<typeof loadWorkflowSettings>["ui"] & {
6529
6538
  showPlanModeIndicator?: boolean;
6530
6539
  planModeIndicatorText?: string;
@@ -6538,6 +6547,7 @@ type WorkflowWidgetUiSettings = ReturnType<typeof loadWorkflowSettings>["ui"] &
6538
6547
  showActiveWorkflowSwitchHint?: boolean;
6539
6548
  showWidgetShortcutHint?: boolean;
6540
6549
  showPresetShortcutHint?: boolean;
6550
+ editorHintContrast?: WorkflowEditorHintContrast;
6541
6551
  };
6542
6552
 
6543
6553
  const widgetVisibilityOverrides: Partial<Record<WorkflowWidgetSlot, boolean>> = {};
@@ -6554,6 +6564,38 @@ function workflowWidgetUi(settings: ReturnType<typeof loadWorkflowSettings>): Wo
6554
6564
  return settings.ui as WorkflowWidgetUiSettings;
6555
6565
  }
6556
6566
 
6567
+ function parseEditorHintContrast(value?: string): WorkflowEditorHintContrast | undefined {
6568
+ const input = value?.trim().toLowerCase().replace(/[\s_-]+/g, "");
6569
+ if (!input) return undefined;
6570
+ if (input === "subtle" || input === "muted" || input === "dim") return "subtle";
6571
+ if (input === "normal" || input === "default") return "normal";
6572
+ if (input === "bright") return "bright";
6573
+ if (input === "high" || input === "highcontrast" || input === "maximum") return "high";
6574
+ return undefined;
6575
+ }
6576
+
6577
+ function workflowEditorHintContrast(settings: ReturnType<typeof loadWorkflowSettings>): WorkflowEditorHintContrast {
6578
+ return parseEditorHintContrast(workflowWidgetUi(settings).editorHintContrast) ?? "normal";
6579
+ }
6580
+
6581
+ function workflowEditorHintContrastLabel(contrast: WorkflowEditorHintContrast): string {
6582
+ return WORKFLOW_EDITOR_HINT_CONTRAST_LABELS[contrast];
6583
+ }
6584
+
6585
+ function workflowEditorHintStyledText(settings: ReturnType<typeof loadWorkflowSettings>, text: string): string {
6586
+ switch (workflowEditorHintContrast(settings)) {
6587
+ case "subtle":
6588
+ return `\x1b[2m\x1b[38;5;240m${text}\x1b[0m`;
6589
+ case "bright":
6590
+ return `\x1b[38;5;250m${text}\x1b[0m`;
6591
+ case "high":
6592
+ return `\x1b[1m\x1b[38;5;255m${text}\x1b[0m`;
6593
+ case "normal":
6594
+ default:
6595
+ return `\x1b[38;5;245m${text}\x1b[0m`;
6596
+ }
6597
+ }
6598
+
6557
6599
  function workflowWidgetVisible(settings: ReturnType<typeof loadWorkflowSettings>, slot: WorkflowWidgetSlot): boolean {
6558
6600
  const override = widgetVisibilityOverrides[slot];
6559
6601
  if (override !== undefined) return override;
@@ -9718,7 +9760,7 @@ export default function workflowModes(pi: ExtensionAPI): void {
9718
9760
  const route = await applyModelForRole(pi, ctx, "planner", { cwd: ctx.cwd });
9719
9761
  if (!route) return false;
9720
9762
  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");
9763
+ if (showNotice) workflowUiNotify(ctx, `Active Plan Mode planner route reapplied: ${modelLabel(route)}\n${activeModelDiagnostic(ctx)}`, "info");
9722
9764
  return true;
9723
9765
  };
9724
9766
 
@@ -9727,13 +9769,13 @@ export default function workflowModes(pi: ExtensionAPI): void {
9727
9769
  const settings = loadWorkflowSettings(ctx.cwd);
9728
9770
  const standardRole = effectiveStandardModelRole(settings);
9729
9771
  if (standardRole === "current") {
9730
- if (showNotice) ctx.ui.notify(`Standard Mode keeps the current Pi model.\n${activeModelDiagnostic(ctx)}`, "info");
9772
+ if (showNotice) workflowUiNotify(ctx, `Standard Mode keeps the current Pi model.\n${activeModelDiagnostic(ctx)}`, "info");
9731
9773
  return false;
9732
9774
  }
9733
9775
  const route = await applyStandardModelForRole(pi, ctx, standardRole, { cwd: ctx.cwd });
9734
9776
  if (!route) return false;
9735
9777
  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");
9778
+ if (showNotice) workflowUiNotify(ctx, `Active Standard Mode ${standardRole} route applied: ${modelLabel(route)}\n${activeModelDiagnostic(ctx)}`, "info");
9737
9779
  return true;
9738
9780
  };
9739
9781
 
@@ -9748,7 +9790,7 @@ export default function workflowModes(pi: ExtensionAPI): void {
9748
9790
  const settings = loadWorkflowSettings(ctx.cwd);
9749
9791
  const globalUi = workflowWidgetUi(loadGlobalSettings());
9750
9792
  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"}`;
9793
+ 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
9794
  if (isPlanWorkflowUiMode(state)) {
9753
9795
  const bottom = planBottomRelevant(state) ? widgetVisibilityLabel(settings, "planBottom") : "not applicable";
9754
9796
  return `# Workflow Widgets\n\nPlan Top Widget: ${widgetVisibilityLabel(settings, "planTop")}\nPlan Bottom Widget: ${bottom}\nStatus Line: ${widgetVisibilityStatus(state, settings) ?? "none"}\n${common}`;
@@ -9761,7 +9803,13 @@ export default function workflowModes(pi: ExtensionAPI): void {
9761
9803
  if (isStandardWorkflowMode(state)) {
9762
9804
  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
9805
  }
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}`;
9806
+ 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: 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}`;
9807
+ };
9808
+
9809
+ const renderEditorHintsSettings = (ctx: ExtensionContext): string => {
9810
+ const settings = loadWorkflowSettings(ctx.cwd);
9811
+ const ui = workflowWidgetUi(settings);
9812
+ 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
9813
  };
9766
9814
 
9767
9815
  const setWorkflowWidgetVisibility = (ctx: ExtensionContext, slot: WorkflowWidgetSlot, visible: boolean): string => {
@@ -9814,7 +9862,7 @@ export default function workflowModes(pi: ExtensionAPI): void {
9814
9862
  const messages = (["planTop", "planBottom", "missionTop", "missionBottom", "standardTop", "standardBottom"] as WorkflowWidgetSlot[]).map((slot) => setWorkflowWidgetVisibility(ctx, slot, visible));
9815
9863
  return show(pi, `# Workflow Widgets\n\n${messages.join("\n")}\n\n${renderWorkflowWidgetsStatus(ctx)}`);
9816
9864
  }
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");
9865
+ 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
9866
  };
9819
9867
 
9820
9868
  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 +14443,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14395
14443
  const plannerReapplied = role === "planner" ? await reapplyPlannerRouteIfPlanMode(ctx, true) : false;
14396
14444
  const standardSettings = loadWorkflowSettings(ctx.cwd);
14397
14445
  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");
14446
+ workflowUiNotify(ctx, `${role} model set to ${provider}/${model} in ${result.file}${plannerReapplied || standardReapplied ? `\n${activeModelDiagnostic(ctx)}` : ""}`, "info");
14399
14447
  }
14400
14448
 
14401
14449
  async function configureStandardRoleModel(ctx: ExtensionContext, role: WorkflowRole) {
@@ -14403,14 +14451,14 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14403
14451
  if (!selected) return;
14404
14452
  const result = setStandardModelForRole(role, selected.provider, selected.model, ctx.cwd);
14405
14453
  await reapplyStandardRouteIfStandardMode(ctx, true);
14406
- ctx.ui.notify(`standard ${role} model set to ${selected.provider}/${selected.model} in ${result.file}`, "info");
14454
+ workflowUiNotify(ctx, `standard ${role} model set to ${selected.provider}/${selected.model} in ${result.file}`, "info");
14407
14455
  }
14408
14456
 
14409
14457
  async function configureMissionRoleModel(ctx: ExtensionContext, role: MissionModelRole) {
14410
14458
  const selected = await selectProviderAndModel(ctx, `Mission ${role} model`);
14411
14459
  if (!selected) return;
14412
14460
  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");
14461
+ workflowUiNotify(ctx, `mission ${role} model set to ${selected.provider}/${selected.model} in ${result.file}`, "info");
14414
14462
  }
14415
14463
 
14416
14464
  async function configureStandardThinking(ctx: ExtensionContext) {
@@ -14420,7 +14468,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14420
14468
  if (!level) return;
14421
14469
  const result = setStandardThinkingForRole(role, level, ctx.cwd);
14422
14470
  await reapplyStandardRouteIfStandardMode(ctx, true);
14423
- ctx.ui.notify(`standard ${role} thinking set to ${level} in ${result.file}`, "info");
14471
+ workflowUiNotify(ctx, `standard ${role} thinking set to ${level} in ${result.file}`, "info");
14424
14472
  }
14425
14473
 
14426
14474
  async function configureMissionThinking(ctx: ExtensionContext) {
@@ -14429,7 +14477,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14429
14477
  const level = parseThinkingLevel((await ctx.ui.select("Select mission thinking level:", ["off", "minimal", "low", "medium", "high", "xhigh"])) ?? "");
14430
14478
  if (!level) return;
14431
14479
  const result = setMissionThinkingForRole(role, level, ctx.cwd);
14432
- ctx.ui.notify(`mission ${role} thinking set to ${level} in ${result.file}`, "info");
14480
+ workflowUiNotify(ctx, `mission ${role} thinking set to ${level} in ${result.file}`, "info");
14433
14481
  }
14434
14482
 
14435
14483
  async function configureThinking(ctx: ExtensionContext) {
@@ -14441,7 +14489,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14441
14489
  const plannerReapplied = role === "planner" ? await reapplyPlannerRouteIfPlanMode(ctx, true) : false;
14442
14490
  const standardSettings = loadWorkflowSettings(ctx.cwd);
14443
14491
  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");
14492
+ workflowUiNotify(ctx, `${role} thinking set to ${level} in ${result.file}${plannerReapplied || standardReapplied ? `\n${activeModelDiagnostic(ctx)}` : ""}`, "info");
14445
14493
  }
14446
14494
 
14447
14495
  async function chooseBool(ctx: ExtensionContext, title: string): Promise<boolean | undefined> {
@@ -14449,6 +14497,128 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14449
14497
  return parseBool(choice ?? undefined);
14450
14498
  }
14451
14499
 
14500
+ function humanizeWorkflowSettingSegment(segment: string): string {
14501
+ return segment
14502
+ .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
14503
+ .replace(/[_-]+/g, " ")
14504
+ .replace(/\bui\b/gi, "UI")
14505
+ .replace(/\bapi\b/gi, "API")
14506
+ .replace(/\bto do\b/gi, "To Do")
14507
+ .trim()
14508
+ .replace(/\s+/g, " ")
14509
+ .replace(/\w\S*/g, (word) => word === "UI" || word === "API" ? word : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());
14510
+ }
14511
+
14512
+ function workflowSettingDisplayLabel(setting: string): string {
14513
+ const labels: Record<string, string> = {
14514
+ "ui.editorHintContrast": "Editor hint contrast",
14515
+ "ui.showIdleWorkflowEntryHint": "Idle entry hint",
14516
+ "ui.showActiveWorkflowSwitchHint": "Active switch hint",
14517
+ "ui.showWidgetShortcutHint": "Widget shortcut hint",
14518
+ "ui.showPresetShortcutHint": "Preset shortcut hint",
14519
+ "ui.enableWidgetShortcuts": "Widget shortcuts",
14520
+ "ui.rememberWidgetVisibility": "Remember widget visibility",
14521
+ "ui.workflowTheme": "Workflow theme",
14522
+ "ui.widgetTextStyle": "Widget text style",
14523
+ "ui.startupTextStyle": "Startup text style",
14524
+ "ui.startupVisual": "Startup visual",
14525
+ "ui.startupLogo": "Startup logo",
14526
+ "ui.startupLogoText": "Startup logo text",
14527
+ "ui.startupLogoFont": "Startup logo font",
14528
+ "ui.startupLogoShadowDirection": "Startup logo shadow direction",
14529
+ "ui.startupLogoColorStyle": "Startup logo color style",
14530
+ "ui.startupVisualOnSessionStart": "Startup on session start",
14531
+ "ui.customBrandEnabled": "Custom brand",
14532
+ "ui.customBrandText": "Custom brand text",
14533
+ "ui.customBrandBaseVisual": "Custom brand base visual",
14534
+ "interactiveClarificationEnabled": "Interactive clarification",
14535
+ "maxClarificationQuestions": "Max clarification questions",
14536
+ "planning.depth": "Planning depth",
14537
+ "planning.clarificationMode": "Planning clarification mode",
14538
+ "planning.interactiveClarificationEnabled": "Interactive clarification",
14539
+ "planning.maxClarificationQuestions": "Max clarification questions",
14540
+ "planning.clarificationTiming": "Planning clarification timing",
14541
+ "planning.maxTokens": "Planning token budget",
14542
+ "planning.maxRuntimeHours": "Planning runtime budget",
14543
+ "standard.allowSubagents": "Standard sub-agents",
14544
+ "standard.subagentScope": "Standard sub-agent scope",
14545
+ "standard.todoTriggerMode": "To Do trigger mode",
14546
+ "standard.clarificationMode": "Standard clarification mode",
14547
+ "standard.interactiveClarificationEnabled": "Standard interactive clarification",
14548
+ "standard.maxClarificationQuestions": "Standard max clarification questions",
14549
+ "standard.clarificationTiming": "Standard clarification timing",
14550
+ "standard.maxTokens": "Standard token budget",
14551
+ "standard.enabled": "Standard Mode",
14552
+ "subagents.enabled": "Sub-agents",
14553
+ "subagents.activityIndicatorEnabled": "Sub-agent activity indicator",
14554
+ "subagents.allowBackgroundSubagents": "Background sub-agents",
14555
+ "subagents.editConcurrencyMode": "Sub-agent edit concurrency mode",
14556
+ "subagents.planningOrchestrationPolicy": "Planning orchestration policy",
14557
+ "missions.enabled": "Mission Mode",
14558
+ "missions.defaultAutonomy": "Mission default autonomy",
14559
+ "missions.subagentPolicy": "Mission sub-agent policy",
14560
+ "missions.planningDepth": "Mission planning depth",
14561
+ "missions.clarificationMode": "Mission clarification mode",
14562
+ "missions.interactiveClarificationEnabled": "Mission interactive clarification",
14563
+ "missions.maxClarificationQuestions": "Mission max clarification questions",
14564
+ "missions.clarificationTiming": "Mission clarification timing",
14565
+ "missions.maxTokens": "Mission token budget",
14566
+ "missions.maxRuntimeHours": "Mission runtime budget",
14567
+ "missions.checkpointIntervalMinutes": "Mission checkpoint interval",
14568
+ "missions.heartbeatEnabled": "Mission heartbeat",
14569
+ "missions.watchdogEnabled": "Mission watchdog",
14570
+ "missions.watchdogStaleMinutes": "Mission watchdog stale minutes",
14571
+ "missions.missionHistoryLimit": "Mission history limit",
14572
+ "context.autoCompactionEnabled": "Workflow auto trigger",
14573
+ "context.compactionTriggerPercent": "Workflow trigger percent",
14574
+ "context.compactionCooldownMinutes": "Compaction cooldown",
14575
+ "context.customCompactionReserveTokens": "Custom compaction reserve tokens",
14576
+ "context.customCompactionKeepRecentTokens": "Custom compaction keep-recent tokens",
14577
+ "workflow.validationRetryMode": "Validation retry mode",
14578
+ "workflow.planHistoryLimit": "Plan history limit",
14579
+ "workflow.planShowProgressBar": "Plan progress bar",
14580
+ "safety.repoLockEnabled": "Project Repo Lock",
14581
+ };
14582
+ if (labels[setting]) return labels[setting];
14583
+ const parts = setting.split(".");
14584
+ return humanizeWorkflowSettingSegment(parts[parts.length - 1] || setting);
14585
+ }
14586
+
14587
+ function workflowSettingDisplayValue(setting: string, value: string): string {
14588
+ const clean = value.trim().replace(/\s+/g, " ");
14589
+ if (setting === "ui.editorHintContrast") {
14590
+ return workflowEditorHintContrastLabel(parseEditorHintContrast(clean) ?? "normal");
14591
+ }
14592
+ if (clean === "true") {
14593
+ return /^ui\.show.*Hint$/.test(setting) ? "shown" : "enabled";
14594
+ }
14595
+ if (clean === "false") {
14596
+ return /^ui\.show.*Hint$/.test(setting) ? "hidden" : "disabled";
14597
+ }
14598
+ return clean
14599
+ .replace(/_/g, " ")
14600
+ .replace(/\bpi\b/gi, "Pi")
14601
+ .replace(/\w\S*/g, (word) => word === "Pi" || word.toUpperCase() === "API" ? word : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());
14602
+ }
14603
+
14604
+ function workflowFriendlyNotification(message: string, level?: "info" | "warning" | "error"): string {
14605
+ if (level !== "info") return message;
14606
+ let text = message.replace(/\s+in\s+\/\S+/g, "").replace(/\s+/g, " ").trim();
14607
+ const settingMatch = text.match(/^([A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z0-9_]+)*)\s+set to\s+([^.;]+)([.;]?.*)$/);
14608
+ if (settingMatch) {
14609
+ const [, setting, value, tail = ""] = settingMatch;
14610
+ const label = workflowSettingDisplayLabel(setting);
14611
+ const displayValue = workflowSettingDisplayValue(setting, value);
14612
+ const suffix = tail.replace(/^[.;]\s*/, "").trim();
14613
+ return `${label} set to ${displayValue}.${suffix ? ` ${suffix}` : ""}`;
14614
+ }
14615
+ return text.charAt(0).toUpperCase() + text.slice(1);
14616
+ }
14617
+
14618
+ function workflowUiNotify(ctx: ExtensionContext, message: string, level?: "info" | "warning" | "error"): void {
14619
+ ctx.ui.notify(workflowFriendlyNotification(message, level), level);
14620
+ }
14621
+
14452
14622
  async function showPlanningSettingsMenu(ctx: ExtensionContext) {
14453
14623
  if (!ctx.hasUI) return show(pi, renderFullWorkflowSettings(loadWorkflowSettings(ctx.cwd)));
14454
14624
  while (ctx.hasUI) {
@@ -14456,7 +14626,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14456
14626
  if (!choice || choice === "Back") return;
14457
14627
  if (choice === "Set planning.depth") {
14458
14628
  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"); }
14629
+ 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
14630
  } else if (choice === "List Current Settings") {
14461
14631
  const s = loadWorkflowSettings(ctx.cwd);
14462
14632
  show(pi, `# Planning Settings\n\nplanning.depth: ${s.planning.depth}`);
@@ -14471,13 +14641,13 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14471
14641
  if (!choice || choice === "Back") return;
14472
14642
  if (choice === "Set clarificationMode") {
14473
14643
  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"); }
14644
+ 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
14645
  } else if (choice === "Set interactiveClarificationEnabled") {
14476
14646
  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"); }
14647
+ 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
14648
  } else if (choice === "Set maxClarificationQuestions") {
14479
14649
  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"); }
14650
+ if (count) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxClarificationQuestions = count; }); workflowUiNotify(ctx, `maxClarificationQuestions set to ${count} in ${r.file}`, "info"); }
14481
14651
  } else if (choice === "List Current Settings") {
14482
14652
  const s = loadWorkflowSettings(ctx.cwd);
14483
14653
  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 +14663,11 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14493
14663
  if (!choice || choice === "Back") return;
14494
14664
  if (choice.endsWith("Policy")) {
14495
14665
  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"); }
14666
+ 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
14667
  } else {
14498
14668
  const key = choice.includes("Deep") ? keys.deepKey : keys.maximumKey;
14499
14669
  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"); }
14670
+ 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
14671
  }
14502
14672
  }
14503
14673
  }
@@ -14515,7 +14685,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14515
14685
  const standard = s.standard as typeof s.standard & { subagents?: Record<string, boolean | number | string | undefined> };
14516
14686
  standard.subagents = { ...(standard.subagents ?? {}), [keys.policyKey]: policy };
14517
14687
  });
14518
- ctx.ui.notify(`standard.subagents.${keys.policyKey} set to ${policy} in ${r.file}`, "info");
14688
+ workflowUiNotify(ctx, `standard.subagents.${keys.policyKey} set to ${policy} in ${r.file}`, "info");
14519
14689
  }
14520
14690
  } else {
14521
14691
  const key = choice.includes("Deep") ? keys.deepKey : keys.maximumKey;
@@ -14525,7 +14695,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14525
14695
  const standard = s.standard as typeof s.standard & { subagents?: Record<string, boolean | number | string | undefined> };
14526
14696
  standard.subagents = { ...(standard.subagents ?? {}), [key]: count };
14527
14697
  });
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");
14698
+ workflowUiNotify(ctx, `standard.subagents.${key} set to ${count} in ${r.file}. Forced policy uses this Standard phase's Maximum / Forced worker count.`, "info");
14529
14699
  }
14530
14700
  }
14531
14701
  }
@@ -14544,7 +14714,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14544
14714
  const standard = s.standard as typeof s.standard & { subagents?: Record<string, boolean | number | string | undefined> };
14545
14715
  standard.subagents = { ...(standard.subagents ?? {}), [key]: enabled };
14546
14716
  });
14547
- ctx.ui.notify(`standard.subagents.${key} set to ${enabled} in ${r.file}`, "info");
14717
+ workflowUiNotify(ctx, `standard.subagents.${key} set to ${enabled} in ${r.file}`, "info");
14548
14718
  }
14549
14719
  }
14550
14720
  }
@@ -14561,7 +14731,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14561
14731
  const standard = s.standard as typeof s.standard & { subagents?: Record<string, boolean | number | string | undefined> };
14562
14732
  standard.subagents = { ...(standard.subagents ?? {}), [key]: enabled };
14563
14733
  });
14564
- ctx.ui.notify(`standard.subagents.${key} set to ${enabled} in ${r.file}`, "info");
14734
+ workflowUiNotify(ctx, `standard.subagents.${key} set to ${enabled} in ${r.file}`, "info");
14565
14735
  }
14566
14736
  }
14567
14737
  }
@@ -14573,7 +14743,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14573
14743
  if (!choice || choice === "Back") return;
14574
14744
  if (choice === "Enable / Disable Standard Sub-agents") {
14575
14745
  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"); }
14746
+ 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
14747
  } else if (choice === "Standard Planning / Research Policy / Workers") await showStandardSubagentPhaseSettingsMenu(ctx, "Planning", "Standard Planning / Research");
14578
14748
  else if (choice === "Standard Execution Policy / Workers") await showStandardSubagentPhaseSettingsMenu(ctx, "Execution", "Standard Execution");
14579
14749
  else if (choice === "Standard Repair Policy / Workers") await showStandardSubagentPhaseSettingsMenu(ctx, "Repair", "Standard Repair");
@@ -14581,15 +14751,15 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14581
14751
  else if (choice === "Standard Validation Policy / Workers") await showStandardSubagentPhaseSettingsMenu(ctx, "Validation", "Standard Validation");
14582
14752
  else if (choice === "Agent Scope") {
14583
14753
  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"); }
14754
+ 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
14755
  } else if (choice === "Auto-use Toggles") await showStandardSubagentAutoUseMenu(ctx);
14586
14756
  else if (choice === "Parallel Agent Settings") await showStandardParallelismSettingsMenu(ctx);
14587
14757
  else if (choice === "Activity Indicator") {
14588
14758
  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); }
14759
+ 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
14760
  } else if (choice === "List Current Settings") {
14591
14761
  const s = loadWorkflowSettings(ctx.cwd);
14592
- show(pi, `# Plan Sub-agents / Workers\n\n${renderPlanSubagentWorkerSettings(s)}`);
14762
+ 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
14763
  }
14594
14764
  }
14595
14765
  }
@@ -14601,11 +14771,11 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14601
14771
  if (!choice || choice === "Back") return;
14602
14772
  if (choice === "Mission Planning Policy") {
14603
14773
  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"); }
14774
+ 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
14775
  } else {
14606
14776
  const key = choice.includes("Deep") ? "minWorkersForDeep" : "minWorkersForMaximum";
14607
14777
  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"); }
14778
+ 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
14779
  }
14610
14780
  }
14611
14781
  }
@@ -14618,7 +14788,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14618
14788
  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
14789
  const key = keyMap[choice];
14620
14790
  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"); }
14791
+ 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
14792
  }
14623
14793
  }
14624
14794
 
@@ -14629,7 +14799,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14629
14799
  if (!choice || choice === "Back") return;
14630
14800
  if (choice === "Enable / Disable Sub-agents") {
14631
14801
  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"); }
14802
+ 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
14803
  } else if (choice === "Planning Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Planning", "Shared Planning");
14634
14804
  else if (choice === "Execution Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Execution", "Shared Execution");
14635
14805
  else if (choice === "Repair Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Repair", "Shared Repair");
@@ -14639,10 +14809,10 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14639
14809
  else if (choice === "Parallel Agent Settings") await showParallelismSettingsMenu(ctx);
14640
14810
  else if (choice === "Background Sub-agents") {
14641
14811
  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"); }
14812
+ 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
14813
  } else if (choice === "Activity Indicator") {
14644
14814
  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); }
14815
+ 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
14816
  } else if (choice === "List Current Settings") {
14647
14817
  const s = loadWorkflowSettings(ctx.cwd);
14648
14818
  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 +14827,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14657
14827
  if (!choice || choice === "Back") return;
14658
14828
  if (choice === "Enable / Disable Sub-agents") {
14659
14829
  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"); }
14830
+ 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
14831
  } else if (choice === "Plan Planning Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Planning", "Plan Planning");
14662
14832
  else if (choice === "Plan Execution Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Execution", "Plan Execution");
14663
14833
  else if (choice === "Plan Repair Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Repair", "Plan Repair");
@@ -14667,10 +14837,10 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14667
14837
  else if (choice === "Parallel Agent Settings") await showParallelismSettingsMenu(ctx);
14668
14838
  else if (choice === "Activity Indicator") {
14669
14839
  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); }
14840
+ 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
14841
  } else if (choice === "List Current Settings") {
14672
14842
  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"}`);
14843
+ show(pi, `# Plan Sub-agents / Workers\n\n${renderPlanSubagentWorkerSettings(s)}`);
14674
14844
  }
14675
14845
  }
14676
14846
  }
@@ -14682,7 +14852,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14682
14852
  if (!choice || choice === "Back") return;
14683
14853
  if (choice === "Enable / Disable Sub-agents") {
14684
14854
  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"); }
14855
+ 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
14856
  } else if (choice === "Mission Planning Policy / Workers") await showMissionPlanningSubagentSettingsMenu(ctx);
14687
14857
  else if (choice === "Mission Execution Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Execution", "Mission Execution");
14688
14858
  else if (choice === "Mission Repair Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Repair", "Mission Repair");
@@ -14692,7 +14862,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14692
14862
  else if (choice === "Parallel Agent Settings") await showParallelismSettingsMenu(ctx);
14693
14863
  else if (choice === "Activity Indicator") {
14694
14864
  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); }
14865
+ 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
14866
  } else if (choice === "List Current Settings") {
14697
14867
  const s = loadWorkflowSettings(ctx.cwd);
14698
14868
  show(pi, `# Mission Sub-agents / Workers\n\n${renderMissionSubagentWorkerSettings(s)}`);
@@ -14708,10 +14878,10 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14708
14878
  if (choice?.startsWith("Set allow") || choice === "Set requireParallelEditConflictProtection") {
14709
14879
  const key = choice.replace("Set ", "");
14710
14880
  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"); }
14881
+ 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
14882
  } else if (choice === "Set editConcurrencyMode") {
14713
14883
  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"); }
14884
+ 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
14885
  } else if (choice === "List Current Settings") {
14716
14886
  const s = loadWorkflowSettings(ctx.cwd);
14717
14887
  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 +14893,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14723
14893
  const models = ctx.modelRegistry.getAll();
14724
14894
  const providers = [...new Set(models.map((m) => m.provider))].sort();
14725
14895
  if (providers.length === 0) {
14726
- ctx.ui.notify("No models are available in the model registry.", "error");
14896
+ workflowUiNotify(ctx, "No models are available in the model registry.", "error");
14727
14897
  return undefined;
14728
14898
  }
14729
14899
  const providerChoice = await ctx.ui.select(`${title}: select provider`, [...providers, "Custom provider name"]);
@@ -14737,7 +14907,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14737
14907
  }
14738
14908
  const providerModels = models.filter((m) => m.provider === providerChoice).map((m) => m.id).sort();
14739
14909
  if (providerModels.length === 0) {
14740
- ctx.ui.notify(`No models found for provider ${providerChoice}.`, "error");
14910
+ workflowUiNotify(ctx, `No models found for provider ${providerChoice}.`, "error");
14741
14911
  return undefined;
14742
14912
  }
14743
14913
  const modelChoice = await ctx.ui.select(`${title}: select model`, providerModels.map((model) => `${providerChoice}/${model}`));
@@ -14764,7 +14934,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14764
14934
  s.context.compactionModelProvider = provider;
14765
14935
  s.context.compactionModel = "";
14766
14936
  });
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");
14937
+ 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
14938
  }
14769
14939
 
14770
14940
  async function selectCompactionModel(ctx: ExtensionContext) {
@@ -14777,7 +14947,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14777
14947
  s.context.compactionModelProvider = "";
14778
14948
  s.context.compactionModel = "";
14779
14949
  });
14780
- ctx.ui.notify(`Compaction summary model reset to Pi default in ${result.file}. Trigger behavior was not changed.`, "info");
14950
+ workflowUiNotify(ctx, `Compaction summary model reset to Pi default in ${result.file}. Trigger behavior was not changed.`, "info");
14781
14951
  return;
14782
14952
  }
14783
14953
 
@@ -14788,7 +14958,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14788
14958
  selectedProvider = chosen;
14789
14959
  }
14790
14960
  if (!selectedProvider) {
14791
- ctx.ui.notify("Select a custom compaction provider before selecting a custom model.", "warning");
14961
+ workflowUiNotify(ctx, "Select a custom compaction provider before selecting a custom model.", "warning");
14792
14962
  return;
14793
14963
  }
14794
14964
  const providerModels = ctx.modelRegistry.getAll().filter((m) => m.provider === selectedProvider).map((m) => m.id).sort();
@@ -14800,7 +14970,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14800
14970
  s.context.compactionModelProvider = selectedProvider;
14801
14971
  s.context.compactionModel = model;
14802
14972
  });
14803
- ctx.ui.notify(`Compaction model preference stored as ${selectedProvider}/${model} in ${result.file}. Trigger behavior was not changed.`, "info");
14973
+ workflowUiNotify(ctx, `Compaction model preference stored as ${selectedProvider}/${model} in ${result.file}. Trigger behavior was not changed.`, "info");
14804
14974
  }
14805
14975
 
14806
14976
  async function selectCompactionAgent(ctx: ExtensionContext) {
@@ -14814,7 +14984,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14814
14984
  s.context.compactionAgent = agent;
14815
14985
  s.context.customCompactionEnabled = true;
14816
14986
  });
14817
- ctx.ui.notify(`Compaction agent stored as ${agent} in ${result.file}. Current releases keep Pi default fallback behavior for agent-routed compaction.`, "info");
14987
+ workflowUiNotify(ctx, `Compaction agent stored as ${agent} in ${result.file}. Current releases keep Pi default fallback behavior for agent-routed compaction.`, "info");
14818
14988
  }
14819
14989
 
14820
14990
  async function showCompactionSettingsMenu(ctx: ExtensionContext) {
@@ -14833,53 +15003,53 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14833
15003
  if (trigger === "Pi default") delete s.context.autoCompactionEnabled;
14834
15004
  else s.context.autoCompactionEnabled = trigger === "Enabled";
14835
15005
  });
14836
- ctx.ui.notify(`Workflow auto trigger set to ${trigger.toLowerCase()} in ${r.file}.`, "info");
15006
+ workflowUiNotify(ctx, `Workflow auto trigger set to ${trigger.toLowerCase()} in ${r.file}.`, "info");
14837
15007
  } else if (choice === "Workflow Trigger Percent") {
14838
15008
  const mode = await ctx.ui.select("Workflow Trigger Percent", ["Pi default", "Custom percent", "Back"]);
14839
15009
  if (!mode || mode === "Back") continue;
14840
15010
  if (mode === "Pi default") {
14841
15011
  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");
15012
+ workflowUiNotify(ctx, `Workflow compaction trigger percent override removed in ${r.file}; Pi native trigger formula remains in control.`, "info");
14843
15013
  } else {
14844
15014
  const raw = String((await ctx.ui.input("Workflow compaction trigger percent (50-95)", String(compactionTriggerPercentOverride(loadWorkflowSettings(ctx.cwd)) ?? 85))) ?? "").trim();
14845
15015
  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");
15016
+ 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"); }
15017
+ else workflowUiNotify(ctx, "Trigger percent must be an integer from 50 to 95.", "error");
14848
15018
  }
14849
15019
  } else if (choice === "Workflow Trigger Cooldown") {
14850
15020
  const mode = await ctx.ui.select("Workflow Trigger Cooldown", ["Pi default", "Custom cooldown", "Back"]);
14851
15021
  if (!mode || mode === "Back") continue;
14852
15022
  if (mode === "Pi default") {
14853
15023
  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");
15024
+ workflowUiNotify(ctx, `Compaction cooldown reset to Pi default (5 minutes) in ${r.file}.`, "info");
14855
15025
  } else {
14856
15026
  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");
15027
+ 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"); }
15028
+ else workflowUiNotify(ctx, "Cooldown must be an integer from 0 to 240 minutes.", "error");
14859
15029
  }
14860
15030
  } else if (choice === "Custom Reserve Tokens") {
14861
15031
  const mode = await ctx.ui.select("Custom Reserve Tokens", ["Pi default", "Custom reserve tokens", "Back"]);
14862
15032
  if (!mode || mode === "Back") continue;
14863
15033
  if (mode === "Pi default") {
14864
15034
  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");
15035
+ workflowUiNotify(ctx, `Custom compaction reserve tokens reset to Pi default (${DEFAULT_PI_COMPACTION_RESERVE_TOKENS.toLocaleString()}) in ${r.file}`, "info");
14866
15036
  } else {
14867
15037
  const raw = String((await ctx.ui.input("Custom compaction reserve tokens (4096-65536)", String(customCompactionReserveTokens(loadWorkflowSettings(ctx.cwd)))) ?? "")).trim();
14868
15038
  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");
15039
+ 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"); }
15040
+ else workflowUiNotify(ctx, "Reserve tokens must be an integer from 4096 to 65536.", "error");
14871
15041
  }
14872
15042
  } else if (choice === "Custom Keep Recent Tokens") {
14873
15043
  const mode = await ctx.ui.select("Custom Keep Recent Tokens", ["Pi default", "Custom keep-recent tokens", "Back"]);
14874
15044
  if (!mode || mode === "Back") continue;
14875
15045
  if (mode === "Pi default") {
14876
15046
  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");
15047
+ workflowUiNotify(ctx, `Custom compaction keep-recent tokens reset to Pi default (${DEFAULT_PI_COMPACTION_KEEP_RECENT_TOKENS.toLocaleString()}) in ${r.file}`, "info");
14878
15048
  } else {
14879
15049
  const raw = String((await ctx.ui.input("Custom compaction keep-recent tokens (1000-200000)", String(customCompactionKeepRecentTokens(loadWorkflowSettings(ctx.cwd)))) ?? "")).trim();
14880
15050
  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");
15051
+ 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"); }
15052
+ else workflowUiNotify(ctx, "Keep-recent tokens must be an integer from 1000 to 200000.", "error");
14883
15053
  }
14884
15054
  } else if (choice === "List Current Settings") {
14885
15055
  const s = loadWorkflowSettings(ctx.cwd);
@@ -14930,7 +15100,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14930
15100
  }
14931
15101
  });
14932
15102
  await reapplyStandardRouteIfStandardMode(ctx, true);
14933
- ctx.ui.notify(`Standard model source set to ${source} in ${result.file}`, "info");
15103
+ workflowUiNotify(ctx, `Standard model source set to ${source} in ${result.file}`, "info");
14934
15104
  } else if (choice === "Standard Model Role") {
14935
15105
  const role = parseStandardModelRole((await ctx.ui.select("Standard model role", ["Current Pi model", "Planner", "Executor", "Reviewer", "Validator"])) ?? "");
14936
15106
  if (!role) continue;
@@ -14944,7 +15114,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14944
15114
  }
14945
15115
  });
14946
15116
  await reapplyStandardRouteIfStandardMode(ctx, true);
14947
- ctx.ui.notify(`Standard model role set to ${workflowRoleLabel(role)} in ${result.file}`, "info");
15117
+ workflowUiNotify(ctx, `Standard model role set to ${workflowRoleLabel(role)} in ${result.file}`, "info");
14948
15118
  } else if (choice === "Configure Standard Planner") await configureStandardRoleModel(ctx, "planner");
14949
15119
  else if (choice === "Configure Standard Executor") await configureStandardRoleModel(ctx, "executor");
14950
15120
  else if (choice === "Configure Standard Reviewer") await configureStandardRoleModel(ctx, "reviewer");
@@ -14965,10 +15135,10 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14965
15135
  const options = key === "maxValidationRetriesPerPlan" ? ["0", "1", "2", "3", "4", "5", "10"] : ["0", "1", "2", "4", "8", "12", "20", "50", "100"];
14966
15136
  const raw = await ctx.ui.select(setting, options);
14967
15137
  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"); }
15138
+ 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
15139
  } else if (setting === "Validation Retry Mode") {
14970
15140
  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"); }
15141
+ 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
15142
  } else {
14973
15143
  const keyMap: Record<string, keyof ReturnType<typeof loadWorkflowSettings>["workflow"]> = {
14974
15144
  "Auto Repair Validation Failures": "autoRepairValidationFailures",
@@ -14978,7 +15148,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14978
15148
  };
14979
15149
  const key = keyMap[setting];
14980
15150
  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"); }
15151
+ 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
15152
  }
14983
15153
  }
14984
15154
  }
@@ -14992,26 +15162,26 @@ ${renderMissionStatus(activeMission ?? paused)}`);
14992
15162
  await showModelSettingsMenu(ctx);
14993
15163
  } else if (choice === "Planning Depth") {
14994
15164
  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"); }
15165
+ 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
15166
  } else if (choice === "Plan Clarification") {
14997
15167
  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
15168
  if (!setting || setting === "Back") continue;
14999
15169
  if (setting === "Clarification Mode") {
15000
15170
  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"); }
15171
+ 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
15172
  } else if (setting === "Interactive Clarification") {
15003
15173
  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"); }
15174
+ 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
15175
  } else if (setting === "Max Clarification Questions") {
15006
15176
  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"); }
15177
+ 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
15178
  } else if (setting === "Timing") {
15009
15179
  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"); }
15180
+ 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
15181
  } else {
15012
15182
  const key = setting === "Quality Gate" ? "clarificationQualityGate" : setting === "Allow Without Analysis" ? "allowClarificationWithoutAnalysis" : "useSubagentsBeforeClarification";
15013
15183
  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"); }
15184
+ 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
15185
  }
15016
15186
  } else if (choice === "Plan Sub-agents / Workers") {
15017
15187
  await showPlanSubagentWorkerSettingsMenu(ctx);
@@ -15020,16 +15190,16 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15020
15190
  if (!setting || setting === "Back") continue;
15021
15191
  const enabled = await chooseBool(ctx, `${setting}?`);
15022
15192
  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"); }
15193
+ if (setting === "Reviewer Enabled") { const r = setRoleEnabled("reviewer", enabled, ctx.cwd); workflowUiNotify(ctx, `reviewer.enabled set to ${enabled} in ${r.file}`, "info"); }
15194
+ else if (setting === "Validator Enabled") { const r = setRoleEnabled("validator", enabled, ctx.cwd); workflowUiNotify(ctx, `validator.enabled set to ${enabled} in ${r.file}`, "info"); }
15195
+ 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"); }
15196
+ 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"); }
15197
+ 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"); }
15198
+ 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"); }
15199
+ 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"); }
15200
+ 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"); }
15201
+ 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"); }
15202
+ 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
15203
  } else if (choice === "Repair / Validation Retry") {
15034
15204
  await showWorkflowRepairRetrySettingsMenu(ctx);
15035
15205
  } else if (choice === "Plan Progress / Runtime") {
@@ -15045,28 +15215,28 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15045
15215
  const choice = await ctx.ui.select("Plan Token Budget", ["Default (unlimited)", "Custom..."]);
15046
15216
  if (choice === "Default (unlimited)") {
15047
15217
  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");
15218
+ workflowUiNotify(ctx, `planning.maxTokens set to default (unlimited) in ${r.file}`, "info");
15049
15219
  } else if (choice === "Custom...") {
15050
15220
  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"); }
15221
+ 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
15222
  }
15053
15223
  } else if (setting === "Runtime Budget") {
15054
15224
  const current = loadWorkflowSettings(ctx.cwd).planning.maxRuntimeHours ?? 0;
15055
15225
  const choice = await ctx.ui.select("Plan Runtime Budget", ["Default (unlimited)", "Custom..."]);
15056
15226
  if (choice === "Default (unlimited)") {
15057
15227
  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");
15228
+ workflowUiNotify(ctx, `planning.maxRuntimeHours set to default (unlimited) in ${r.file}`, "info");
15059
15229
  } else if (choice === "Custom...") {
15060
15230
  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"); }
15231
+ 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
15232
  }
15063
15233
  } else if (setting === "Progress Bar Display") {
15064
15234
  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"); }
15235
+ 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
15236
  } else {
15067
15237
  const key = setting === "Progress Tracking" ? "planProgressEnabled" : "planRuntimeEnabled";
15068
15238
  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"); }
15239
+ 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
15240
  }
15071
15241
  } else if (choice === "Plan History") {
15072
15242
  const setting = await ctx.ui.select("Plan History", ["Save Plans", "Save Plan History", "Plan History Limit", "Back"]);
@@ -15074,11 +15244,11 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15074
15244
  if (!setting || setting === "Back") continue;
15075
15245
  if (setting === "Plan History Limit") {
15076
15246
  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"); }
15247
+ 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
15248
  } else {
15079
15249
  const key = setting === "Save Plans" ? "savePlans" : "savePlanHistory";
15080
15250
  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"); }
15251
+ 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
15252
  }
15083
15253
  } else if (choice === "List Current Settings") {
15084
15254
  const s = loadWorkflowSettings(ctx.cwd);
@@ -15094,11 +15264,11 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15094
15264
  if (!setting || setting === "Back") return;
15095
15265
  if (setting === "To Do Trigger Mode") {
15096
15266
  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"); }
15267
+ 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
15268
  } else {
15099
15269
  const key = setting === "Automatic To Do Enabled" ? "autoTodoEnabled" : "todoProgressVisible";
15100
15270
  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"); }
15271
+ 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
15272
  }
15103
15273
  }
15104
15274
  }
@@ -15110,20 +15280,20 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15110
15280
  if (!setting || setting === "Back") return;
15111
15281
  if (setting === "Clarification Mode") {
15112
15282
  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"); }
15283
+ 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
15284
  } else if (setting === "Interactive Clarification") {
15115
15285
  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"); }
15286
+ 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
15287
  } else if (setting === "Max Clarification Questions") {
15118
15288
  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"); }
15289
+ 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
15290
  } else if (setting === "Timing") {
15121
15291
  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"); }
15292
+ 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
15293
  } else {
15124
15294
  const key = setting === "Quality Gate" ? "clarificationQualityGate" : setting === "Allow Without Analysis" ? "allowClarificationWithoutAnalysis" : "useSubagentsBeforeClarification";
15125
15295
  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"); }
15296
+ 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
15297
  }
15128
15298
  }
15129
15299
  }
@@ -15143,15 +15313,15 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15143
15313
  const choice = await ctx.ui.select("Standard Token Budget", ["Default (unlimited)", "Custom..."]);
15144
15314
  if (choice === "Default (unlimited)") {
15145
15315
  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");
15316
+ workflowUiNotify(ctx, `standard.maxTokens set to default (unlimited) in ${r.file}`, "info");
15147
15317
  } else if (choice === "Custom...") {
15148
15318
  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"); }
15319
+ 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
15320
  }
15151
15321
  } else {
15152
15322
  const key = setting === "Status Widget Visible" ? "statusWidgetVisible" : "todoProgressVisible";
15153
15323
  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"); }
15324
+ 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
15325
  }
15156
15326
  }
15157
15327
  }
@@ -15168,7 +15338,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15168
15338
  }
15169
15339
  if (choice === "Enable / Disable Standard Mode") {
15170
15340
  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"); }
15341
+ 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
15342
  } else if (choice === "Standard To Do" || choice === "To Do Behavior") {
15173
15343
  await showStandardTodoSettingsMenu(ctx);
15174
15344
  } else if (choice === "Standard Clarification" || choice === "Clarification") {
@@ -15197,7 +15367,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15197
15367
  if (!source) continue;
15198
15368
  const enabled = source === "Mission-Specific Models";
15199
15369
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.useMissionSpecificModels = enabled; });
15200
- ctx.ui.notify(`missions.useMissionSpecificModels set to ${enabled} in ${r.file}`, "info");
15370
+ workflowUiNotify(ctx, `missions.useMissionSpecificModels set to ${enabled} in ${r.file}`, "info");
15201
15371
  } else if (choice === "Configure Mission Planner") await configureMissionRoleModel(ctx, "planner");
15202
15372
  else if (choice === "Configure Mission Executor") await configureMissionRoleModel(ctx, "executor");
15203
15373
  else if (choice === "Configure Mission Reviewer") await configureMissionRoleModel(ctx, "reviewer");
@@ -15218,13 +15388,13 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15218
15388
  show(pi, renderHeartbeatWatchdogStatus(loadWorkflowSettings(ctx.cwd), activeMission ?? loadMissionState()));
15219
15389
  } else if (choice === "Enable / Disable Heartbeat") {
15220
15390
  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"); }
15391
+ 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
15392
  } else if (choice === "Enable / Disable Watchdog") {
15223
15393
  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"); }
15394
+ 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
15395
  } else if (choice === "Set Watchdog Stale Minutes") {
15226
15396
  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"); }
15397
+ 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
15398
  }
15229
15399
  }
15230
15400
  }
@@ -15237,11 +15407,11 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15237
15407
  const enabled = await chooseBool(ctx, `${setting}?`);
15238
15408
  if (enabled === undefined) continue;
15239
15409
  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"); }
15410
+ 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"); }
15411
+ else { const r = setRoleEnabled("reviewer", enabled, ctx.cwd); workflowUiNotify(ctx, `reviewer.enabled set to ${enabled} in ${r.file}`, "info"); }
15242
15412
  } 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"); }
15413
+ 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"); }
15414
+ else { const r = setRoleEnabled("validator", enabled, ctx.cwd); workflowUiNotify(ctx, `validator.enabled set to ${enabled} in ${r.file}`, "info"); }
15245
15415
  } else {
15246
15416
  const keyMap: Record<string, string> = {
15247
15417
  "Offer Reviewer Before Approval": "offerReviewerBeforeApprove",
@@ -15259,7 +15429,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15259
15429
  s.missions.reviewRetryMode = "safe_only";
15260
15430
  }
15261
15431
  });
15262
- ctx.ui.notify(`missions.${key} set to ${enabled} in ${r.file}`, "info");
15432
+ workflowUiNotify(ctx, `missions.${key} set to ${enabled} in ${r.file}`, "info");
15263
15433
  }
15264
15434
  }
15265
15435
  }
@@ -15272,18 +15442,18 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15272
15442
  if (setting === "Max Review Retries Per Mission") {
15273
15443
  const raw = await ctx.ui.select(setting, ["0", "1", "2", "3", "4", "5", "10"]);
15274
15444
  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"); }
15445
+ 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
15446
  } else if (setting === "Max Retries Per Milestone" || setting === "Max Retries Per Mission" || setting === "Max Final Validation Retries") {
15277
15447
  const key = setting === "Max Retries Per Milestone" ? "maxValidationRetriesPerMilestone" : setting === "Max Retries Per Mission" ? "maxValidationRetriesPerMission" : "maxFinalValidationRetries";
15278
15448
  const max = key === "maxValidationRetriesPerMission" ? 100 : 10;
15279
15449
  const options = key === "maxValidationRetriesPerMission" ? ["0", "1", "2", "4", "8", "12", "20", "50", "100"] : ["0", "1", "2", "3", "4", "5", "10"];
15280
15450
  const raw = await ctx.ui.select(setting, options);
15281
15451
  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"); }
15452
+ 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
15453
  } else if (setting === "Validation Retry Mode" || setting === "Review Retry Mode") {
15284
15454
  const key = setting === "Validation Retry Mode" ? "validationRetryMode" : "reviewRetryMode";
15285
15455
  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"); }
15456
+ 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
15457
  } else {
15288
15458
  const keyMap: Record<string, string> = {
15289
15459
  "Auto Repair Review Failures": "autoRepairReviewFailures",
@@ -15296,7 +15466,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15296
15466
  };
15297
15467
  const key = keyMap[setting];
15298
15468
  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"); }
15469
+ 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
15470
  }
15301
15471
  }
15302
15472
  }
@@ -15309,12 +15479,12 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15309
15479
  if (setting === "Max Final Validation Retries") {
15310
15480
  const raw = await ctx.ui.select(setting, ["0", "1", "2", "3", "4", "5", "10"]);
15311
15481
  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"); }
15482
+ 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
15483
  } else {
15314
15484
  const keyMap: Record<string, string> = { "Final Comprehensive Validation": "finalValidationEnabled", "Final Validation Requires Pass": "finalValidationRequiresPass", "Auto Repair Final Validation Failures": "autoRepairFinalValidationFailures" };
15315
15485
  const key = keyMap[setting];
15316
15486
  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"); }
15487
+ 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
15488
  }
15319
15489
  }
15320
15490
  }
@@ -15329,12 +15499,12 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15329
15499
  const count = parsePositiveInt((await ctx.ui.input("Mission history limit", String(current))) ?? "");
15330
15500
  if (count !== undefined && count >= 1 && count <= 500) {
15331
15501
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.missionHistoryLimit = count; });
15332
- ctx.ui.notify(`missions.missionHistoryLimit set to ${count} in ${r.file}`, "info");
15502
+ workflowUiNotify(ctx, `missions.missionHistoryLimit set to ${count} in ${r.file}`, "info");
15333
15503
  }
15334
15504
  } else if (setting === "Cleanup Saved Missions") {
15335
15505
  const settings = loadWorkflowSettings(ctx.cwd);
15336
15506
  const removed = clearOldMissionStates(settings.missions.missionHistoryLimit ?? 50);
15337
- ctx.ui.notify(`Removed ${removed} old mission file${removed === 1 ? "" : "s"}.`, "info");
15507
+ workflowUiNotify(ctx, `Removed ${removed} old mission file${removed === 1 ? "" : "s"}.`, "info");
15338
15508
  } else if (setting === "List Current Settings") {
15339
15509
  const settings = loadWorkflowSettings(ctx.cwd);
15340
15510
  show(pi, `# Mission History\n\nMission History Limit: ${settings.missions.missionHistoryLimit ?? 50}\nMissions Directory: ${MISSION_HISTORY_DIR}`);
@@ -15351,48 +15521,48 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15351
15521
  await showMissionModelBehaviorMenu(ctx);
15352
15522
  } else if (choice === "Enable / Disable Mission Mode") {
15353
15523
  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"); }
15524
+ 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
15525
  } else if (choice === "Mission Autonomy") {
15356
15526
  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
15527
  if (!setting || setting === "Back") continue;
15358
15528
  if (setting === "Default Autonomy") {
15359
15529
  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"); }
15530
+ 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
15531
  } else {
15362
15532
  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
15533
  const key = keyMap[setting];
15364
15534
  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"); }
15535
+ 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
15536
  }
15367
15537
  } else if (choice === "Default Autonomy") {
15368
15538
  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"); }
15539
+ 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
15540
  } else if (choice === "Mission Clarification") {
15371
15541
  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
15542
  if (!setting || setting === "Back") continue;
15373
15543
  if (setting === "Clarification Mode") {
15374
15544
  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"); }
15545
+ 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
15546
  } else if (setting === "Interactive Clarification") {
15377
15547
  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"); }
15548
+ 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
15549
  } else if (setting === "Max Clarification Questions") {
15380
15550
  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"); }
15551
+ 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
15552
  } else if (setting === "Timing") {
15383
15553
  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"); }
15554
+ 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
15555
  } else {
15386
15556
  const key = setting === "Quality Gate" ? "clarificationQualityGate" : setting === "Allow Without Analysis" ? "allowClarificationWithoutAnalysis" : "useSubagentsBeforeClarification";
15387
15557
  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"); }
15558
+ 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
15559
  }
15390
15560
  } else if (choice === "Mission Planning Depth") {
15391
15561
  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"); }
15562
+ 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
15563
  } else if (choice === "Mission Sub-Agent Policy") {
15394
15564
  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"); }
15565
+ 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
15566
  } else if (choice === "Mission Sub-agents / Workers" || choice === "Mission Worker Targets") {
15397
15567
  await showMissionSubagentWorkerSettingsMenu(ctx);
15398
15568
  } else if (choice === "Mission History") {
@@ -15408,50 +15578,50 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15408
15578
  if (setting === "Progress Widget" || setting === "Progress Bar Display") {
15409
15579
  const key = setting === "Progress Widget" ? "progressWidgetEnabled" : "showProgressBar";
15410
15580
  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"); }
15581
+ 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
15582
  } else if (setting === "Heartbeat / Watchdog") await showHeartbeatWatchdogMenu(ctx);
15413
15583
  else if (setting === "Token Budget") {
15414
15584
  const current = loadWorkflowSettings(ctx.cwd).missions.maxTokens ?? 0;
15415
15585
  const choice = await ctx.ui.select("Mission Token Budget", ["Default (unlimited)", "Custom..."]);
15416
15586
  if (choice === "Default (unlimited)") {
15417
15587
  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");
15588
+ workflowUiNotify(ctx, `missions.maxTokens set to default (unlimited) in ${r.file}`, "info");
15419
15589
  } else if (choice === "Custom...") {
15420
15590
  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"); }
15591
+ 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
15592
  }
15423
15593
  } else if (setting === "Runtime Budget") {
15424
15594
  const current = loadWorkflowSettings(ctx.cwd).missions.maxRuntimeHours;
15425
15595
  const choice = await ctx.ui.select("Mission Runtime Budget", ["Default (13 hours)", "Custom..."]);
15426
15596
  if (choice === "Default (13 hours)") {
15427
15597
  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");
15598
+ workflowUiNotify(ctx, `missions.maxRuntimeHours set to default (13 hours) in ${r.file}`, "info");
15429
15599
  } else if (choice === "Custom...") {
15430
15600
  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"); }
15601
+ 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
15602
  }
15433
15603
  } else {
15434
15604
  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"); }
15605
+ 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
15606
  }
15437
15607
  } else if (choice === "Runtime Budget") {
15438
15608
  const current = loadWorkflowSettings(ctx.cwd).missions.maxRuntimeHours;
15439
15609
  const choice2 = await ctx.ui.select("Mission Runtime Budget", ["Default (13 hours)", "Custom..."]);
15440
15610
  if (choice2 === "Default (13 hours)") {
15441
15611
  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");
15612
+ workflowUiNotify(ctx, `missions.maxRuntimeHours set to default (13 hours) in ${r.file}`, "info");
15443
15613
  } else if (choice2 === "Custom...") {
15444
15614
  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"); }
15615
+ 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
15616
  }
15447
15617
  } else if (choice === "Checkpoint Interval") {
15448
15618
  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"); }
15619
+ 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
15620
  } else if (choice === "Approval Safety" || choice === "Validation Per Milestone" || choice === "Full Auto Safety" || choice === "Auto Resume") {
15451
15621
  const keyMap: Record<string, keyof ReturnType<typeof loadWorkflowSettings>["missions"]> = { "Validation Per Milestone": "requireValidationPerMilestone", "Approval Safety": "requireApprovalForDestructiveActions", "Full Auto Safety": "allowFullAuto", "Auto Resume": "autoResume" };
15452
15622
  const key = keyMap[choice];
15453
15623
  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"); }
15624
+ 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
15625
  } else if (choice === "Review / Validation Behavior") {
15456
15626
  await showMissionReviewValidationBehaviorMenu(ctx);
15457
15627
  } else if (choice === "Repair / Validation Retry" || choice === "Mission Repair / Validation" || choice === "Repair / Validation Retry Settings") {
@@ -15484,18 +15654,18 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15484
15654
  const enabled = await chooseBool(ctx, "safety.repoLockEnabled for this project only?");
15485
15655
  if (enabled !== undefined) {
15486
15656
  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");
15657
+ 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
15658
  }
15489
15659
  } else {
15490
15660
  const key = keyMap[choice];
15491
15661
  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"); }
15662
+ 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
15663
  }
15494
15664
  }
15495
15665
  }
15496
15666
 
15497
- async function showFooterHintsSettingsMenu(ctx: ExtensionContext) {
15498
- if (!ctx.hasUI) return show(pi, renderWorkflowWidgetsStatus(ctx));
15667
+ async function showEditorHintsSettingsMenu(ctx: ExtensionContext) {
15668
+ if (!ctx.hasUI) return show(pi, renderEditorHintsSettings(ctx));
15499
15669
  const options = [
15500
15670
  { label: "Idle Entry Hint", key: "showIdleWorkflowEntryHint" as const },
15501
15671
  { label: "Active Switch Hint", key: "showActiveWorkflowSwitchHint" as const },
@@ -15506,17 +15676,31 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15506
15676
  const settings = loadWorkflowSettings(ctx.cwd);
15507
15677
  const ui = workflowWidgetUi(settings);
15508
15678
  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"]);
15679
+ const contrastLabel = `Hint Contrast: ${workflowEditorHintContrastLabel(workflowEditorHintContrast(settings))}`;
15680
+ const choice = await ctx.ui.select("Editor Hints", [...labels, contrastLabel, "List Current Settings", "Back"]);
15510
15681
  if (!choice || choice === "Back") return;
15511
- if (choice === "List Current Settings") { show(pi, renderWorkflowWidgetsStatus(ctx)); continue; }
15682
+ if (choice === "List Current Settings") { show(pi, renderEditorHintsSettings(ctx)); continue; }
15683
+ if (choice === contrastLabel) {
15684
+ const current = workflowEditorHintContrast(settings);
15685
+ const contrastChoice = await ctx.ui.select("Editor Hint Contrast", WORKFLOW_EDITOR_HINT_CONTRASTS.map((contrast) => `${workflowEditorHintContrastLabel(contrast)}${contrast === current ? " (current)" : ""}`).concat("Back"));
15686
+ if (!contrastChoice || contrastChoice === "Back") continue;
15687
+ const contrast = parseEditorHintContrast(contrastChoice.replace(/\s+\(current\)$/, ""));
15688
+ if (contrast) {
15689
+ updateSettings(ctx.cwd, "global", (s) => { workflowWidgetUi(s).editorHintContrast = contrast; });
15690
+ setWorkflowUi(ctx, state, activeSubagents);
15691
+ workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd));
15692
+ workflowUiNotify(ctx, `Editor hint contrast set to ${workflowEditorHintContrastLabel(contrast)}.`, "info");
15693
+ }
15694
+ continue;
15695
+ }
15512
15696
  const index = labels.indexOf(choice);
15513
15697
  const option = options[index];
15514
15698
  if (!option) continue;
15515
15699
  const enabled = await chooseBool(ctx, `ui.${option.key}?`);
15516
15700
  if (enabled !== undefined) {
15517
- const r = updateSettings(ctx.cwd, "global", (s) => { workflowWidgetUi(s)[option.key] = enabled; });
15701
+ updateSettings(ctx.cwd, "global", (s) => { workflowWidgetUi(s)[option.key] = enabled; });
15518
15702
  setWorkflowUi(ctx, state, activeSubagents);
15519
- ctx.ui.notify(`ui.${option.key} set to ${enabled} in ${r.file}`, "info");
15703
+ workflowUiNotify(ctx, `${option.label} ${enabled ? "shown" : "hidden"}.`, "info");
15520
15704
  }
15521
15705
  }
15522
15706
  }
@@ -15524,22 +15708,22 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15524
15708
  async function showUiWidgetsSettingsMenu(ctx: ExtensionContext) {
15525
15709
  if (!ctx.hasUI) return show(pi, renderWorkflowWidgetsStatus(ctx));
15526
15710
  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"]);
15711
+ 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
15712
  if (!choice || choice === "Back") return;
15529
15713
  if (choice === "List Current Settings") show(pi, renderWorkflowWidgetsStatus(ctx));
15530
- else if (choice === "Footer Hints") await showFooterHintsSettingsMenu(ctx);
15714
+ else if (choice === "Editor Hints") await showEditorHintsSettingsMenu(ctx);
15531
15715
  else if (choice === "Enable Widget Shortcuts" || choice === "Remember Widget Visibility") {
15532
15716
  const key = choice === "Enable Widget Shortcuts" ? "enableWidgetShortcuts" : "rememberWidgetVisibility";
15533
15717
  const enabled = await chooseBool(ctx, `ui.${key}?`);
15534
15718
  if (enabled !== undefined) {
15535
- const r = updateSettings(ctx.cwd, "global", (s) => { workflowWidgetUi(s)[key] = enabled; });
15719
+ updateSettings(ctx.cwd, "global", (s) => { workflowWidgetUi(s)[key] = enabled; });
15536
15720
  setWorkflowUi(ctx, state, activeSubagents);
15537
- ctx.ui.notify(`ui.${key} set to ${enabled} in ${r.file}`, "info");
15721
+ workflowUiNotify(ctx, `${choice} ${enabled ? "enabled" : "disabled"}.`, "info");
15538
15722
  }
15539
15723
  } else {
15540
15724
  const slot: WorkflowWidgetSlot = choice === "Plan Top Widget" ? "planTop" : choice === "Plan Bottom Widget" ? "planBottom" : choice === "Mission Top Widget" ? "missionTop" : "missionBottom";
15541
15725
  const visible = await chooseBool(ctx, `${widgetSlotLabel(slot)} visible?`);
15542
- if (visible !== undefined) ctx.ui.notify(setWorkflowWidgetVisibility(ctx, slot, visible), "info");
15726
+ if (visible !== undefined) workflowUiNotify(ctx, setWorkflowWidgetVisibility(ctx, slot, visible), "info");
15543
15727
  }
15544
15728
  }
15545
15729
  }
@@ -15591,14 +15775,14 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15591
15775
  const result = applyWorkflowPreset(ctx.cwd, undefined, resolved);
15592
15776
  setWorkflowUi(ctx, state, activeSubagents);
15593
15777
  const label = workflowPresetLabel(resolved, workflowPresetCatalog(result.settings)[resolved]);
15594
- if (notifyOnly) ctx.ui.notify(`Workflow preset active: ${label}`, "info");
15778
+ if (notifyOnly) workflowUiNotify(ctx, `Workflow preset active: ${label}`, "info");
15595
15779
  else show(pi, presetActionMessage("Workflow Preset Applied", label, result.file, result.scope));
15596
15780
  }
15597
15781
 
15598
15782
  async function markWorkflowPresetCustom(ctx: ExtensionContext): Promise<void> {
15599
15783
  const result = updateSettings(ctx.cwd, undefined, (s) => { s.presets = { ...(s.presets ?? {}), activePreset: WORKFLOW_CUSTOM_PRESET_MARKER, items: { ...(s.presets?.items ?? {}) } }; });
15600
15784
  setWorkflowUi(ctx, state, activeSubagents);
15601
- ctx.ui.notify(`Workflow preset marker cleared in ${result.file}; workflow settings unchanged.`, "info");
15785
+ workflowUiNotify(ctx, `Workflow preset marker cleared in ${result.file}; workflow settings unchanged.`, "info");
15602
15786
  }
15603
15787
 
15604
15788
  async function cycleWorkflowPreset(ctx: ExtensionContext, direction: 1 | -1): Promise<void> {
@@ -15666,7 +15850,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15666
15850
  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
15851
  }
15668
15852
  setWorkflowUi(ctx, state, activeSubagents);
15669
- ctx.ui.notify(`Preset ${name} updated in ${r.file}`, "info");
15853
+ workflowUiNotify(ctx, `Preset ${name} updated in ${r.file}`, "info");
15670
15854
  } catch (e) { show(pi, `# Workflow Preset Error\n\n${e instanceof Error ? e.message : String(e)}`); }
15671
15855
  }
15672
15856
  }
@@ -15761,7 +15945,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15761
15945
  async function showCustomBrandStartupVisualMenu(ctx: ExtensionContext): Promise<boolean | undefined> {
15762
15946
  if (!ctx.hasUI) return undefined;
15763
15947
  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");
15948
+ workflowUiNotify(ctx, `ui.startupVisual set to custom_brand in ${saved.file}`, "info");
15765
15949
  while (ctx.hasUI) {
15766
15950
  const choice = await ctx.ui.select("Custom Brand Startup Visual", ["Set Text", "Choose Base Template", "Preview", "List Theme Settings", "Back"]);
15767
15951
  if (!choice || choice === "Back") return undefined;
@@ -15770,13 +15954,13 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15770
15954
  } else if (choice === "Set Text") {
15771
15955
  const text = sanitizeCustomBrandText(await ctx.ui.input("Custom brand text", sanitizeCustomBrandText(loadWorkflowSettings(ctx.cwd).ui.customBrandText) || "WORKFLOW SUITE"));
15772
15956
  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");
15957
+ workflowUiNotify(ctx, `ui.customBrandText set in ${r.file}`, "info");
15774
15958
  void showStartupVisual(ctx, { intent: "manual" });
15775
15959
  } else if (choice === "Choose Base Template") {
15776
15960
  const base = parseCustomBrandBaseVisual((await ctx.ui.select("Custom brand base template", WORKFLOW_CUSTOM_BRAND_BASE_VISUALS)) ?? "");
15777
15961
  if (base) {
15778
15962
  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");
15963
+ workflowUiNotify(ctx, `ui.customBrandBaseVisual set to ${base} in ${r.file}`, "info");
15780
15964
  void showStartupVisual(ctx, { intent: "manual" });
15781
15965
  }
15782
15966
  } else if (choice === "Preview") {
@@ -15798,27 +15982,27 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15798
15982
  const text = startupLogoText(loadWorkflowSettings(ctx.cwd)) || "WFS";
15799
15983
  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
15984
  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");
15985
+ workflowUiNotify(ctx, `ui.startupLogoText set to ${value || "(empty)"} in ${r.file}`, "info");
15802
15986
  void showStartupVisual(ctx, { intent: "manual" });
15803
15987
  } else if (choice === "Choose Font") {
15804
15988
  const font = parseStartupLogoFont((await ctx.ui.select("Custom logo font", WORKFLOW_STARTUP_LOGO_FONTS)) ?? "");
15805
15989
  if (font) {
15806
15990
  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");
15991
+ workflowUiNotify(ctx, `ui.startupLogoFont set to ${font} in ${r.file}`, "info");
15808
15992
  void showStartupVisual(ctx, { intent: "manual" });
15809
15993
  }
15810
15994
  } else if (choice === "Choose Shadow Direction") {
15811
15995
  const direction = parseStartupLogoShadowDirection((await ctx.ui.select("Custom logo shadow direction", WORKFLOW_STARTUP_LOGO_SHADOW_DIRECTIONS)) ?? "");
15812
15996
  if (direction) {
15813
15997
  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");
15998
+ workflowUiNotify(ctx, `ui.startupLogoShadowDirection set to ${direction} in ${r.file}`, "info");
15815
15999
  void showStartupVisual(ctx, { intent: "manual" });
15816
16000
  }
15817
16001
  } else if (choice === "Choose Color Style") {
15818
16002
  const colorStyle = parseStartupLogoColorStyle((await ctx.ui.select("Custom logo color style", WORKFLOW_STARTUP_LOGO_COLOR_STYLES)) ?? "");
15819
16003
  if (colorStyle) {
15820
16004
  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");
16005
+ workflowUiNotify(ctx, `ui.startupLogoColorStyle set to ${colorStyle} in ${r.file}`, "info");
15822
16006
  void showStartupVisual(ctx, { intent: "manual" });
15823
16007
  }
15824
16008
  } else if (choice === "Preview") {
@@ -15843,7 +16027,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15843
16027
  } else {
15844
16028
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupVisual = visual; });
15845
16029
  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");
16030
+ workflowUiNotify(ctx, canPreview ? `Startup visual set to ${visual} in ${r.file}` : `Startup visual set to ${visual} (disabled) in ${r.file}`, "info");
15847
16031
  if (canPreview) void showStartupVisual(ctx, { intent: "manual" });
15848
16032
  }
15849
16033
  }
@@ -15851,14 +16035,14 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15851
16035
  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
16036
  if (name) {
15853
16037
  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");
16038
+ workflowUiNotify(ctx, `Startup text style set to ${WORKFLOW_WIDGET_TEXT_PRESET_LABELS[name]} in ${r.file}.`, "info");
15855
16039
  void showStartupVisual(ctx, { intent: "manual" });
15856
16040
  }
15857
16041
  } else if (choice === "Turn On" || choice === "Turn Off") {
15858
16042
  const visual: WorkflowStartupVisual = choice === "Turn On" ? "mission_control" : "none";
15859
16043
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupVisual = visual; });
15860
16044
  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");
16045
+ workflowUiNotify(ctx, canPreview ? `Startup visual turned on (${visual}) in ${r.file}` : `Startup visual turned off in ${r.file}`, "info");
15862
16046
  if (canPreview) void showStartupVisual(ctx, { intent: "manual" });
15863
16047
  } else if (choice === "On Session Start") {
15864
16048
  const enabled = await chooseBool(ctx, "Show startup visual on session start?");
@@ -15867,12 +16051,12 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15867
16051
  s.ui.startupVisualOnSessionStart = enabled;
15868
16052
  if (enabled === true && (parseStartupVisual(s.ui.startupVisual) ?? "none") === "none") s.ui.startupVisual = "minimal";
15869
16053
  });
15870
- ctx.ui.notify(`Startup on session start ${enabled ? "enabled" : "disabled"} in ${r.file}`, "info");
16054
+ workflowUiNotify(ctx, `Startup on session start ${enabled ? "enabled" : "disabled"} in ${r.file}`, "info");
15871
16055
  void showStartupVisual(ctx, { intent: "manual" });
15872
16056
  }
15873
16057
  } else if (choice === "Preview") {
15874
16058
  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");
16059
+ if (!previewed) workflowUiNotify(ctx, "Startup visual is disabled. Choose a visual or turn it on to preview.", "info");
15876
16060
  }
15877
16061
  }
15878
16062
  return undefined;
@@ -15901,7 +16085,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15901
16085
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.workflowTheme = name; });
15902
16086
  applyWorkflowEditorTheme(ctx);
15903
16087
  setWorkflowUi(ctx, state, activeSubagents);
15904
- ctx.ui.notify(`ui.workflowTheme set to ${workflowThemeDisplayName(name)} in ${r.file}`, "info");
16088
+ workflowUiNotify(ctx, `ui.workflowTheme set to ${workflowThemeDisplayName(name)} in ${r.file}`, "info");
15905
16089
  void showStartupVisual(ctx, { intent: "manual" });
15906
16090
  }
15907
16091
  } else if (choice === "Startup Visual") {
@@ -15910,7 +16094,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
15910
16094
  const logo = parseStartupLogo((await ctx.ui.select("Startup logo", WORKFLOW_STARTUP_LOGOS)) ?? "");
15911
16095
  if (logo) {
15912
16096
  const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupLogo = logo; });
15913
- ctx.ui.notify(`ui.startupLogo set to ${logo} in ${r.file}`, "info");
16097
+ workflowUiNotify(ctx, `ui.startupLogo set to ${logo} in ${r.file}`, "info");
15914
16098
  if (logo === "custom") await showCustomStartupLogoMenu(ctx);
15915
16099
  else void showStartupVisual(ctx, { intent: "manual" });
15916
16100
  }
@@ -16070,20 +16254,20 @@ Pi Version: v${VERSION}
16070
16254
  workflowLastAutoCompactionAt = Date.now();
16071
16255
  clearDeferredWorkflowCompaction();
16072
16256
  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 */ }
16257
+ try { workflowUiNotify(ctx, `Workflow auto-compaction triggered at ${percent.toFixed(1)}% context usage.`, "info"); } catch { /* UI may be unavailable */ }
16074
16258
  ctx.compact({
16075
16259
  customInstructions,
16076
16260
  onComplete: () => {
16077
16261
  workflowAutoCompactionRunning = false;
16078
16262
  workflowLastAutoCompactionAt = Date.now();
16079
16263
  rememberWorkflowCompactionCheck(`${checkpoint} boundary compaction completed`);
16080
- try { ctx.ui.notify("Workflow auto-compaction complete.", "info"); } catch { /* UI may be unavailable */ }
16264
+ try { workflowUiNotify(ctx, "Workflow auto-compaction complete.", "info"); } catch { /* UI may be unavailable */ }
16081
16265
  },
16082
16266
  onError: (error: Error) => {
16083
16267
  workflowAutoCompactionRunning = false;
16084
16268
  rememberWorkflowCompactionCheck(`${checkpoint} boundary compaction failed — ${error.message}`);
16085
16269
  rememberCustomCompactionStatus(`proactive compaction request failed: ${error.message}`);
16086
- try { ctx.ui.notify(`Workflow auto-compaction skipped: ${error.message}`, "warning"); } catch { /* UI may be unavailable */ }
16270
+ try { workflowUiNotify(ctx, `Workflow auto-compaction skipped: ${error.message}`, "warning"); } catch { /* UI may be unavailable */ }
16087
16271
  },
16088
16272
  });
16089
16273
  }
@@ -16136,7 +16320,7 @@ Pi Version: v${VERSION}
16136
16320
  const model = ctx.modelRegistry.find(provider, modelId);
16137
16321
  if (!model) {
16138
16322
  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");
16323
+ workflowUiNotify(ctx, `Custom compaction model not found: ${provider}/${modelId}; using Pi default compaction.`, "warning");
16140
16324
  return;
16141
16325
  }
16142
16326
 
@@ -16144,12 +16328,12 @@ Pi Version: v${VERSION}
16144
16328
  if (auth.ok === false) {
16145
16329
  const authError = auth.error;
16146
16330
  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");
16331
+ workflowUiNotify(ctx, `Custom compaction auth failed for ${provider}/${modelId}: ${authError}; using Pi default compaction.`, "warning");
16148
16332
  return;
16149
16333
  }
16150
16334
  if (!auth.apiKey) {
16151
16335
  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");
16336
+ workflowUiNotify(ctx, `No API key for custom compaction model ${provider}/${modelId}; using Pi default compaction.`, "warning");
16153
16337
  return;
16154
16338
  }
16155
16339
 
@@ -16161,14 +16345,14 @@ Pi Version: v${VERSION}
16161
16345
  const fitNote = fitted.adjusted && fitted.safeInputTokens
16162
16346
  ? ` Adaptive fit: summarizing about ${Math.round(fitted.inputTokens).toLocaleString()} tokens within ${Math.round(fitted.safeInputTokens).toLocaleString()} safe input tokens for the compaction model.`
16163
16347
  : "";
16164
- ctx.ui.notify(`Custom compaction using ${provider}/${modelId}. Keep recent: ${customCompactionKeepRecentTokens(settings).toLocaleString()} tokens; reserve: ${customCompactionReserveTokens(settings).toLocaleString()} tokens.${fitNote}`, "info");
16348
+ workflowUiNotify(ctx, `Custom compaction using ${provider}/${modelId}. Keep recent: ${customCompactionKeepRecentTokens(settings).toLocaleString()} tokens; reserve: ${customCompactionReserveTokens(settings).toLocaleString()} tokens.${fitNote}`, "info");
16165
16349
  const result = await compactionApi.compact(fitted.preparation, model, auth.apiKey, auth.headers, event.customInstructions, event.signal);
16166
16350
  rememberCustomCompactionStatus(`custom compaction succeeded using ${provider}/${modelId}${fitted.adjusted ? " with adaptive context fit" : ""}`);
16167
16351
  return { compaction: result };
16168
16352
  } catch (error) {
16169
16353
  const message = error instanceof Error ? error.message : String(error);
16170
16354
  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");
16355
+ if (!event.signal.aborted) workflowUiNotify(ctx, `Custom compaction failed: ${message}; using Pi default compaction.`, "warning");
16172
16356
  return;
16173
16357
  }
16174
16358
  });
@@ -17025,6 +17209,14 @@ Pi Version: v${VERSION}
17025
17209
  setWorkflowUi(ctx, state, activeSubagents);
17026
17210
  return show(pi, updatedMessage(result.scope, result.file, `ui.${key}`, String(bool)));
17027
17211
  }
17212
+ if (subject === "ui" && key === "editorHintContrast") {
17213
+ const contrast = parseEditorHintContrast(value);
17214
+ if (!contrast) return show(pi, "# Error\n\nUsage: `/workflow-settings set ui editorHintContrast <subtle|normal|bright|high>`");
17215
+ const result = updateSettings(ctx.cwd, scope ?? "global", (s) => { workflowWidgetUi(s).editorHintContrast = contrast; });
17216
+ setWorkflowUi(ctx, state, activeSubagents);
17217
+ workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd));
17218
+ return show(pi, updatedMessage(result.scope, result.file, "ui.editorHintContrast", contrast));
17219
+ }
17028
17220
  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
17221
  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
17222
  const result = updateSettings(ctx.cwd, scope, (s) => {