@selesai/code 0.13.12 → 0.13.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/extensions/pi-subagents/CHANGELOG.md +77 -1
  3. package/dist/extensions/pi-subagents/VISION.md +12 -1
  4. package/dist/extensions/pi-subagents/docs/agents.md +13 -6
  5. package/dist/extensions/pi-subagents/docs/configuration.md +35 -9
  6. package/dist/extensions/pi-subagents/docs/extension-api.md +1 -1
  7. package/dist/extensions/pi-subagents/docs/missions.md +1 -1
  8. package/dist/extensions/pi-subagents/docs/models.md +6 -6
  9. package/dist/extensions/pi-subagents/docs/observability.md +6 -3
  10. package/dist/extensions/pi-subagents/docs/tool-reference.md +3 -3
  11. package/dist/extensions/pi-subagents/docs/watchdog.md +92 -114
  12. package/dist/extensions/pi-subagents/docs/workflows.md +1 -1
  13. package/dist/extensions/pi-subagents/install.mjs +1 -2
  14. package/dist/extensions/pi-subagents/package.json +1 -1
  15. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +1 -1
  16. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +6 -6
  17. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
  18. package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +1 -1
  19. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +4 -4
  20. package/dist/extensions/pi-subagents/skills/pi-subagents/references/review-and-validation.md +1 -1
  21. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +41 -4
  22. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +3 -0
  23. package/dist/extensions/pi-subagents/src/agents/agents.ts +120 -124
  24. package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +5 -1
  25. package/dist/extensions/pi-subagents/src/api/preflight.ts +4 -0
  26. package/dist/extensions/pi-subagents/src/api/shared-types.ts +3 -0
  27. package/dist/extensions/pi-subagents/src/extension/config.ts +20 -0
  28. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +1 -0
  29. package/dist/extensions/pi-subagents/src/extension/schemas.ts +6 -2
  30. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +1 -1
  31. package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +19 -13
  32. package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +26 -8
  33. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +103 -23
  34. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +6 -2
  35. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -2
  36. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +54 -3
  37. package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +16 -0
  38. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +22 -2
  39. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +63 -6
  40. package/dist/extensions/pi-subagents/src/runs/background/steering.ts +4 -1
  41. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +69 -12
  42. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +13 -0
  43. package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +3 -1
  44. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +21 -8
  45. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +59 -6
  46. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +95 -18
  47. package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +11 -43
  48. package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +1 -0
  49. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +1 -1
  50. package/dist/extensions/pi-subagents/src/runs/shared/lane-metadata.ts +24 -3
  51. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +4 -0
  52. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +2 -6
  53. package/dist/extensions/pi-subagents/src/runs/shared/permissions.ts +1 -0
  54. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +33 -18
  55. package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +73 -37
  56. package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +33 -6
  57. package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +4 -2
  58. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +20 -3
  59. package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +21 -7
  60. package/dist/extensions/pi-subagents/src/runs/shared/tool-timeout.ts +1 -1
  61. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +467 -63
  62. package/dist/extensions/pi-subagents/src/shared/atomic-json.ts +3 -1
  63. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +0 -12
  64. package/dist/extensions/pi-subagents/src/shared/fork-session-cwd.ts +27 -0
  65. package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +3 -0
  66. package/dist/extensions/pi-subagents/src/shared/types.ts +42 -4
  67. package/dist/extensions/pi-subagents/src/shared/utils.ts +18 -7
  68. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +1 -1
  69. package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +26 -12
  70. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +61 -2
  71. package/dist/extensions/pi-subagents/src/tui/fleet.ts +12 -7
  72. package/dist/extensions/pi-subagents/src/tui/render.ts +227 -14
  73. package/dist/extensions/pi-subagents/src/watchdog/child-status.ts +56 -34
  74. package/dist/extensions/pi-subagents/src/watchdog/diff-tool.ts +77 -0
  75. package/dist/extensions/pi-subagents/src/watchdog/emission-guard.ts +5 -3
  76. package/dist/extensions/pi-subagents/src/watchdog/guidance.ts +20 -0
  77. package/dist/extensions/pi-subagents/src/watchdog/register-child.ts +16 -13
  78. package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +10 -9
  79. package/dist/extensions/pi-subagents/src/watchdog/render.ts +4 -5
  80. package/dist/extensions/pi-subagents/src/watchdog/review.ts +15 -4
  81. package/dist/extensions/pi-subagents/src/watchdog/rules.ts +70 -0
  82. package/dist/extensions/pi-subagents/src/watchdog/runtime.ts +75 -92
  83. package/dist/extensions/pi-subagents/src/watchdog/scope.ts +2 -1
  84. package/dist/extensions/pi-subagents/src/watchdog/settings.ts +48 -104
  85. package/dist/extensions/pi-subagents/src/watchdog/types.ts +18 -32
  86. package/dist/extensions/pi-subagents/src/watchdog/warning-format.ts +0 -1
  87. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +3 -2
  88. package/dist/extensions/pi-subagents/src/workflows/workflow-checklist.ts +439 -0
  89. package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +28 -1
  90. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +335 -21
  91. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +4 -1
  92. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +1 -1
  93. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +22 -18
  94. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +0 -1
  95. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +21 -18
  96. package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +307 -22
  97. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +1 -0
  98. package/dist/extensions/pi-subagents/test/support/helpers.ts +25 -0
  99. package/dist/extensions/pi-subagents/test/support/isolated-temp-root.mjs +15 -4
  100. package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +17 -2
  101. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +96 -15
  102. package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +53 -5
  103. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +20 -0
  104. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +221 -8
  105. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +45 -24
  106. package/dist/extensions/pi-subagents/test/unit/agent-scan-dirs.test.ts +133 -0
  107. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +28 -2
  108. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +1 -1
  109. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +2 -0
  110. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +4 -1
  111. package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +18 -4
  112. package/dist/extensions/pi-subagents/test/unit/atomic-json.test.ts +16 -0
  113. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +38 -0
  114. package/dist/extensions/pi-subagents/test/unit/default-extensions.test.ts +2 -2
  115. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +21 -0
  116. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +19 -6
  117. package/dist/extensions/pi-subagents/test/unit/get-final-output.test.ts +26 -0
  118. package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +22 -1
  119. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +2 -6
  120. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +66 -1
  121. package/dist/extensions/pi-subagents/test/unit/pi-args-permission-system.test.ts +1 -1
  122. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +116 -10
  123. package/dist/extensions/pi-subagents/test/unit/pi-spawn.test.ts +136 -18
  124. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +20 -0
  125. package/dist/extensions/pi-subagents/test/unit/process-terminal.test.ts +22 -0
  126. package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +1 -0
  127. package/dist/extensions/pi-subagents/test/unit/project-panes-public-api.test.ts +8 -0
  128. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +127 -48
  129. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +68 -0
  130. package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +17 -0
  131. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +88 -0
  132. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +4 -2
  133. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +9 -9
  134. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +2 -2
  135. package/dist/extensions/pi-subagents/test/unit/steering.test.ts +9 -3
  136. package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +22 -9
  137. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +91 -8
  138. package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +27 -0
  139. package/dist/extensions/pi-subagents/test/unit/temp-paths.test.ts +50 -0
  140. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +0 -1
  141. package/dist/extensions/pi-subagents/test/unit/tool-timeout.test.ts +2 -2
  142. package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +34 -0
  143. package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +1 -2
  144. package/dist/extensions/pi-subagents/test/unit/watchdog-child-status.test.ts +73 -13
  145. package/dist/extensions/pi-subagents/test/unit/watchdog-diff-tool.test.ts +79 -0
  146. package/dist/extensions/pi-subagents/test/unit/watchdog-permission-arbiter.test.ts +2 -4
  147. package/dist/extensions/pi-subagents/test/unit/watchdog-render.test.ts +7 -8
  148. package/dist/extensions/pi-subagents/test/unit/watchdog-review.test.ts +48 -3
  149. package/dist/extensions/pi-subagents/test/unit/watchdog-rules.test.ts +37 -0
  150. package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +36 -118
  151. package/dist/extensions/pi-subagents/test/unit/watchdog-scope.test.ts +1 -1
  152. package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +37 -14
  153. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +45 -26
  154. package/dist/extensions/pi-subagents/test/unit/workflow-checklist.test.ts +223 -0
  155. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +50 -1
  156. package/dist/extensions/pi-subagents/test/unit/workflow-preflight.test.ts +22 -0
  157. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +136 -4
  158. package/dist/extensions/pi-zentui/README.md +19 -5
  159. package/dist/extensions/pi-zentui/docs/configuration.md +37 -9
  160. package/dist/extensions/pi-zentui/extensions/zentui/config.ts +29 -0
  161. package/dist/extensions/pi-zentui/extensions/zentui/index.ts +31 -2
  162. package/dist/extensions/pi-zentui/extensions/zentui/prototype-patch-registry.ts +55 -11
  163. package/dist/extensions/pi-zentui/extensions/zentui/settings-command.ts +115 -3
  164. package/dist/extensions/pi-zentui/extensions/zentui/settings-previews.ts +119 -2
  165. package/dist/extensions/pi-zentui/extensions/zentui/thinking-experimental.ts +1768 -0
  166. package/dist/extensions/pi-zentui/extensions/zentui/thinking-status.ts +69 -0
  167. package/dist/extensions/pi-zentui/extensions/zentui/thinking-steps.ts +155 -0
  168. package/dist/extensions/pi-zentui/extensions/zentui/ui.ts +2 -1
  169. package/dist/extensions/pi-zentui/extensions/zentui/user-message-osc.ts +16 -2
  170. package/dist/extensions/pi-zentui/extensions/zentui/user-message-styles.ts +1 -1
  171. package/dist/extensions/pi-zentui/test/config-load-lifecycle.test.ts +124 -0
  172. package/dist/extensions/pi-zentui/test/config.test.ts +82 -2
  173. package/dist/extensions/pi-zentui/test/editor-viewport-indicators.test.ts +19 -4
  174. package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +58 -9
  175. package/dist/extensions/pi-zentui/test/package-contents.mjs +33 -0
  176. package/dist/extensions/pi-zentui/test/prototype-patch-registry.test.ts +131 -0
  177. package/dist/extensions/pi-zentui/test/responsive-dependencies.test.ts +4 -4
  178. package/dist/extensions/pi-zentui/test/settings-command.test.ts +289 -7
  179. package/dist/extensions/pi-zentui/test/settings-previews.test.ts +106 -0
  180. package/dist/extensions/pi-zentui/test/thinking-experimental-docs.test.ts +51 -0
  181. package/dist/extensions/pi-zentui/test/thinking-experimental-loader-diagnostics.mjs +54 -0
  182. package/dist/extensions/pi-zentui/test/thinking-experimental-missing-export.test.ts +44 -0
  183. package/dist/extensions/pi-zentui/test/thinking-experimental-rows.test.ts +297 -0
  184. package/dist/extensions/pi-zentui/test/thinking-experimental-tui.mjs +2329 -0
  185. package/dist/extensions/pi-zentui/test/thinking-experimental.test.ts +1668 -0
  186. package/dist/extensions/pi-zentui/test/thinking-status.test.ts +85 -0
  187. package/dist/extensions/pi-zentui/test/thinking-steps.test.ts +122 -0
  188. package/dist/extensions/pi-zentui/test/user-message-osc.test.ts +58 -0
  189. package/dist/skills/brandkit/SKILL.md +0 -2
  190. package/dist/skills/{industrial-brutalist-ui → brutalist}/SKILL.md +1 -3
  191. package/dist/skills/gpt-taste/SKILL.md +0 -2
  192. package/dist/skills/image-to-code/SKILL.md +0 -2
  193. package/dist/skills/imagegen-frontend-mobile/SKILL.md +0 -2
  194. package/dist/skills/imagegen-frontend-web/SKILL.md +0 -2
  195. package/dist/skills/{minimalist-ui → minimalist}/SKILL.md +1 -3
  196. package/dist/skills/{full-output-enforcement → output}/SKILL.md +1 -3
  197. package/dist/skills/{redesign-existing-projects → redesign}/SKILL.md +1 -3
  198. package/dist/skills/{high-end-visual-design → soft}/SKILL.md +1 -3
  199. package/dist/skills/stitch/DESIGN.md +121 -0
  200. package/dist/skills/{stitch-design-taste → stitch}/SKILL.md +1 -3
  201. package/dist/skills/{design-taste-frontend → taste}/SKILL.md +1 -3
  202. package/dist/skills/{design-taste-frontend-v1 → taste-v1}/SKILL.md +2 -4
  203. package/package.json +1 -1
@@ -12,6 +12,7 @@ import { tmpdir } from "node:os";
12
12
  import { dirname, join } from "node:path";
13
13
  import type { Theme } from "@earendil-works/pi-coding-agent";
14
14
  import {
15
+ AssistantMessageComponent,
15
16
  initTheme,
16
17
  ModelSelectorComponent,
17
18
  SettingsSelectorComponent,
@@ -113,6 +114,8 @@ const settingsCommandDefaults: SettingsCommandDeps = {
113
114
  setAccentRail() {},
114
115
  setMinimalist() {},
115
116
  setUserMessagesComponent() {},
117
+ thinkingStepsCapability: { available: false },
118
+ setThinkingStepsComponent: () => ({ applied: true }),
116
119
  setWorkingLineComponent: () => ({ applied: true }),
117
120
  setSelectorBordersComponent() {},
118
121
  setFooterComponent() {},
@@ -180,6 +183,7 @@ function canonicalizeTestConfig(config: PolishedTuiConfig): PolishedTuiConfig {
180
183
  : messages.colorSource,
181
184
  styles: { ...messages.styles },
182
185
  },
186
+ thinkingSteps: { ...config.components.thinkingSteps },
183
187
  workingLine: {
184
188
  ...config.components.workingLine,
185
189
  messages: {
@@ -559,7 +563,7 @@ function loadExtension(options: { thinkingLevel?: string; commands?: Map<string,
559
563
  })}\n`,
560
564
  );
561
565
  const handlers = new Map<string, Handler[]>();
562
- zentui({
566
+ const api = {
563
567
  on(eventName: string, handler: Handler) {
564
568
  handlers.set(eventName, [...(handlers.get(eventName) ?? []), handler]);
565
569
  },
@@ -569,7 +573,8 @@ function loadExtension(options: { thinkingLevel?: string; commands?: Map<string,
569
573
  getThinkingLevel() {
570
574
  return options.thinkingLevel ?? "off";
571
575
  },
572
- } as never);
576
+ } as Record<string, unknown>;
577
+ zentui(api as never);
573
578
  return handlers;
574
579
  }
575
580
 
@@ -757,6 +762,48 @@ describe("fixed-editor retirement contract", () => {
757
762
  });
758
763
 
759
764
  describe("Pi docs compliance", () => {
765
+ it("does not register a public Thinking Markdown transformer or command", async () => {
766
+ writeFileSync(
767
+ join(isolatedAgentDir.path, "zentui.json"),
768
+ JSON.stringify({ components: { thinkingSteps: { enabled: false, mode: "tree" } } }),
769
+ );
770
+ const commands = new Map<string, unknown>();
771
+ const handlers = loadExtension({ commands });
772
+ const indexSource = readFileSync(
773
+ join(import.meta.dirname, "../extensions/zentui/index.ts"),
774
+ "utf8",
775
+ );
776
+ expect(indexSource).not.toContain("registerMarkdown" + "Transformer");
777
+ const ctx = makeContext();
778
+ await emit(handlers, "session_start", ctx);
779
+ await emit(handlers, "session_shutdown", ctx);
780
+ expect(commands.has("thinking-steps")).toBe(false);
781
+ });
782
+
783
+ it("reloads external Thinking configuration synchronously for each session startup", async () => {
784
+ const configPath = join(isolatedAgentDir.path, "zentui.json");
785
+ writeFileSync(
786
+ configPath,
787
+ JSON.stringify({ components: { thinkingSteps: { enabled: false, mode: "tree" } } }),
788
+ );
789
+ const nativeUpdate = AssistantMessageComponent.prototype.updateContent;
790
+ const handlers = loadExtension();
791
+ const ctx = makeContext();
792
+
793
+ await emit(handlers, "session_start", ctx);
794
+ expect(AssistantMessageComponent.prototype.updateContent).toBe(nativeUpdate);
795
+ await emit(handlers, "session_shutdown", ctx);
796
+
797
+ writeFileSync(
798
+ configPath,
799
+ JSON.stringify({ components: { thinkingSteps: { enabled: true, mode: "rail" } } }),
800
+ );
801
+ await emit(handlers, "session_start", ctx);
802
+ expect(AssistantMessageComponent.prototype.updateContent).not.toBe(nativeUpdate);
803
+ await emit(handlers, "session_shutdown", ctx);
804
+ expect(AssistantMessageComponent.prototype.updateContent).toBe(nativeUpdate);
805
+ });
806
+
760
807
  it("derives lazy data requirements from only the active wide and compact candidates", () => {
761
808
  const starship = defaultConfig.components.footer.styles.starship;
762
809
  const customWide = {
@@ -5733,7 +5780,7 @@ describe("Pi docs compliance", () => {
5733
5780
  const themeLines = await renderSettings(defaultConfig);
5734
5781
  expect(themeLines[0]).toContain("[borderMuted]────");
5735
5782
  expect(themeLines.join("\n")).toContain("Appearance");
5736
- expect(themeLines.join("\n")).toContain("(1/8)");
5783
+ expect(themeLines.join("\n")).toContain("(1/9)");
5737
5784
  expect(themeLines.join("\n")).toContain("Tab/Shift+Tab to switch sections");
5738
5785
  expect(themeLines.at(-1)).toContain("[borderMuted]────");
5739
5786
  expect(themeLines.every((line) => visibleWidth(stripTestTags(line)) <= settingsWidth)).toBe(
@@ -5851,7 +5898,7 @@ describe("Pi docs compliance", () => {
5851
5898
  const component = factory({ requestRender() {} }, makeTheme(), {}, () => {}) as {
5852
5899
  handleInput?: (data: string) => void;
5853
5900
  };
5854
- for (let index = 0; index < 4; index += 1) component.handleInput?.("\t");
5901
+ for (let index = 0; index < 5; index += 1) component.handleInput?.("\t");
5855
5902
  for (let index = 0; index < 3; index += 1) component.handleInput?.("\x1b[B");
5856
5903
  component.handleInput?.(" ");
5857
5904
  component.handleInput?.("\x1b[B");
@@ -5923,7 +5970,7 @@ describe("Pi docs compliance", () => {
5923
5970
  {},
5924
5971
  () => {},
5925
5972
  ) as { handleInput?: (data: string) => void };
5926
- for (let index = 0; index < 4; index += 1) component.handleInput?.("\t");
5973
+ for (let index = 0; index < 5; index += 1) component.handleInput?.("\t");
5927
5974
  for (let index = 0; index < 6; index += 1) component.handleInput?.("\x1b[B");
5928
5975
  component.handleInput?.(" ");
5929
5976
  component.handleInput?.(" ");
@@ -5941,7 +5988,7 @@ describe("Pi docs compliance", () => {
5941
5988
  "Separator: pipe",
5942
5989
  ]);
5943
5990
  expect(dependencyRenderRequests).toBe(4);
5944
- expect(tuiRenderRequests).toBe(8);
5991
+ expect(tuiRenderRequests).toBe(9);
5945
5992
  });
5946
5993
 
5947
5994
  it("cycles branch length presets and returns custom JSON values to full", async () => {
@@ -5992,7 +6039,7 @@ describe("Pi docs compliance", () => {
5992
6039
  const component = factory({ requestRender() {} }, makeTheme(), {}, () => {}) as {
5993
6040
  handleInput?: (data: string) => void;
5994
6041
  };
5995
- for (let index = 0; index < 6; index += 1) component.handleInput?.("\t");
6042
+ for (let index = 0; index < 7; index += 1) component.handleInput?.("\t");
5996
6043
  component.handleInput?.("\x1b[B");
5997
6044
  for (let index = 0; index < presses; index += 1) component.handleInput?.(" ");
5998
6045
  },
@@ -6149,6 +6196,7 @@ describe("Pi docs compliance", () => {
6149
6196
  | "Appearance"
6150
6197
  | "Editor"
6151
6198
  | "User messages"
6199
+ | "Thinking"
6152
6200
  | "Working line"
6153
6201
  | "Footer"
6154
6202
  | "Segments"
@@ -6159,6 +6207,7 @@ describe("Pi docs compliance", () => {
6159
6207
  "Appearance",
6160
6208
  "Editor",
6161
6209
  "User messages",
6210
+ "Thinking",
6162
6211
  "Working line",
6163
6212
  "Footer",
6164
6213
  "Segments",
@@ -6417,7 +6466,7 @@ describe("Pi docs compliance", () => {
6417
6466
 
6418
6467
  expect(placements).toEqual([{ key: "alpha", placement: "off" }]);
6419
6468
  expect(dependencyRenderRequests).toBe(1);
6420
- expect(tuiRenderRequests).toBe(8);
6469
+ expect(tuiRenderRequests).toBe(9);
6421
6470
  });
6422
6471
 
6423
6472
  it("does not show inactive saved placements in the extension segments tab", async () => {
@@ -7172,7 +7221,7 @@ describe("three-state Footer lifecycle", () => {
7172
7221
  const settings = factory({ requestRender() {} }, makeTheme(), {}, () => {}) as {
7173
7222
  handleInput(data: string): void;
7174
7223
  };
7175
- for (let index = 0; index < 4; index++) settings.handleInput("\t");
7224
+ for (let index = 0; index < 5; index++) settings.handleInput("\t");
7176
7225
  settings.handleInput(" ");
7177
7226
  };
7178
7227
  const ctx = makeContext({ ui: harness.ui });
@@ -0,0 +1,33 @@
1
+ import assert from "node:assert/strict";
2
+ import { execFileSync } from "node:child_process";
3
+ import { readFileSync } from "node:fs";
4
+
5
+ const npmCli = process.env.npm_execpath;
6
+ const reportJson = execFileSync(
7
+ npmCli ? process.execPath : "npm",
8
+ [...(npmCli ? [npmCli] : []), "pack", "--dry-run", "--json"],
9
+ { encoding: "utf8" },
10
+ );
11
+ const report = JSON.parse(reportJson);
12
+ const packages = Array.isArray(report) ? report : Object.values(report);
13
+ assert.equal(packages.length, 1, "npm pack must report exactly one package");
14
+
15
+ const files = packages[0]?.files;
16
+ assert.ok(Array.isArray(files), "npm pack must report its package file list");
17
+ for (const required of [
18
+ "extensions/zentui/thinking-steps.ts",
19
+ "extensions/zentui/thinking-experimental.ts",
20
+ "extensions/zentui/thinking-status.ts",
21
+ ]) {
22
+ assert.ok(
23
+ files.some(({ path }) => path === required),
24
+ `npm pack must include ${required}`,
25
+ );
26
+ }
27
+
28
+ const renderer = readFileSync("extensions/zentui/thinking-experimental.ts", "utf8");
29
+ assert.match(renderer, /Copyright \(c\) 2026 Zach Yuen/);
30
+ assert.match(renderer, /Copyright \(c\) 2026 Marc Mironescu \/ FluxGear/);
31
+ assert.equal((renderer.match(/Permission is hereby granted, free of charge/g) ?? []).length, 2);
32
+
33
+ console.log(`Package and license assertions passed (${files.length} files total)`);
@@ -0,0 +1,131 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import {
3
+ installPrototypePatch,
4
+ isPrototypePatchCurrent,
5
+ ZENTUI_PROTOTYPE_PATCH_REGISTRY,
6
+ } from "../extensions/zentui/prototype-patch-registry";
7
+
8
+ describe("prototype patch registry updateContent ownership", () => {
9
+ it("forwards every argument, reuses its wrapper, and restores an inherited predecessor", () => {
10
+ const predecessor = vi.fn(function (this: { value: number }, ...args: unknown[]) {
11
+ return [this.value, ...args];
12
+ });
13
+ const parent = { updateContent: predecessor };
14
+ const target = Object.create(parent) as object & {
15
+ updateContent: (...args: unknown[]) => unknown;
16
+ };
17
+ const behavior = vi.fn(({ predecessor: previous, receiver, args }) =>
18
+ Reflect.apply(previous, receiver, args),
19
+ );
20
+ const cleanupFirst = installPrototypePatch(
21
+ target,
22
+ "updateContent",
23
+ "thinking-experimental-update-content",
24
+ behavior,
25
+ );
26
+ const wrapper = target.updateContent;
27
+ expect(target.updateContent.call({ value: 7 }, "message", true, "future-argument")).toEqual([
28
+ 7,
29
+ "message",
30
+ true,
31
+ "future-argument",
32
+ ]);
33
+ expect(behavior.mock.calls[0]?.[0].args).toEqual(["message", true, "future-argument"]);
34
+ const cleanupSecond = installPrototypePatch(
35
+ target,
36
+ "updateContent",
37
+ "thinking-experimental-update-content",
38
+ behavior,
39
+ );
40
+ expect(target.updateContent).toBe(wrapper);
41
+ expect(cleanupFirst.token).not.toBe(cleanupSecond.token);
42
+ expect(
43
+ isPrototypePatchCurrent(
44
+ target,
45
+ "updateContent",
46
+ "thinking-experimental-update-content",
47
+ cleanupFirst.token,
48
+ ),
49
+ ).toBe(false);
50
+ expect(
51
+ isPrototypePatchCurrent(
52
+ target,
53
+ "updateContent",
54
+ "thinking-experimental-update-content",
55
+ cleanupSecond.token,
56
+ ),
57
+ ).toBe(true);
58
+ cleanupFirst();
59
+ expect(target.updateContent).toBe(wrapper);
60
+ expect(target.updateContent.call({ value: 8 }, "newest")).toEqual([8, "newest"]);
61
+ cleanupSecond();
62
+ expect(Object.hasOwn(target, "updateContent")).toBe(false);
63
+ expect(target.updateContent).toBe(predecessor);
64
+ expect(
65
+ (target as unknown as Record<PropertyKey, unknown>)[ZENTUI_PROTOTYPE_PATCH_REGISTRY],
66
+ ).toBeUndefined();
67
+ });
68
+
69
+ it("preserves an exact own descriptor and never restores over a foreign successor", () => {
70
+ const target = {} as { updateContent: (...args: unknown[]) => unknown };
71
+ const predecessor = function predecessor() {};
72
+ const descriptor = {
73
+ value: predecessor,
74
+ writable: false,
75
+ enumerable: false,
76
+ configurable: true,
77
+ };
78
+ Object.defineProperty(target, "updateContent", descriptor);
79
+ const cleanup = installPrototypePatch(
80
+ target,
81
+ "updateContent",
82
+ "thinking-experimental-update-content",
83
+ ({ predecessor: previous, receiver, args }) => Reflect.apply(previous, receiver, args),
84
+ );
85
+ expect(Object.getOwnPropertyDescriptor(target, "updateContent")).toMatchObject({
86
+ writable: false,
87
+ enumerable: false,
88
+ configurable: true,
89
+ });
90
+ const foreign = function foreign() {};
91
+ Object.defineProperty(target, "updateContent", { ...descriptor, value: foreign });
92
+ expect(
93
+ isPrototypePatchCurrent(target, "updateContent", "thinking-experimental-update-content"),
94
+ ).toBe(false);
95
+ cleanup();
96
+ expect(target.updateContent).toBe(foreign);
97
+ });
98
+
99
+ it("rejects missing, noncallable, and nonconfigurable targets without leaving registry state", () => {
100
+ for (const target of [{}, { updateContent: 1 }]) {
101
+ expect(() =>
102
+ installPrototypePatch(
103
+ target,
104
+ "updateContent",
105
+ "thinking-experimental-update-content",
106
+ () => undefined,
107
+ ),
108
+ ).toThrow(/predecessor is not a function/);
109
+ expect(
110
+ (target as Record<PropertyKey, unknown>)[ZENTUI_PROTOTYPE_PATCH_REGISTRY],
111
+ ).toBeUndefined();
112
+ }
113
+ const fixed = {} as { updateContent: () => void };
114
+ Object.defineProperty(fixed, "updateContent", {
115
+ value: () => {},
116
+ writable: false,
117
+ configurable: false,
118
+ });
119
+ expect(() =>
120
+ installPrototypePatch(
121
+ fixed,
122
+ "updateContent",
123
+ "thinking-experimental-update-content",
124
+ () => undefined,
125
+ ),
126
+ ).toThrow();
127
+ expect(
128
+ (fixed as unknown as Record<PropertyKey, unknown>)[ZENTUI_PROTOTYPE_PATCH_REGISTRY],
129
+ ).toBeUndefined();
130
+ });
131
+ });
@@ -693,7 +693,7 @@ describe("responsive footer dependency reconciliation", () => {
693
693
  const component = factory({ requestRender() {} }, makeTheme(), {}, () => {}) as {
694
694
  handleInput?: (data: string) => void;
695
695
  };
696
- for (let index = 0; index < 4; index++) component.handleInput?.("\t");
696
+ for (let index = 0; index < 5; index++) component.handleInput?.("\t");
697
697
  for (let index = 0; index < 3; index++) component.handleInput?.("\x1b[B");
698
698
  component.handleInput?.(" ");
699
699
  });
@@ -737,7 +737,7 @@ describe("responsive footer dependency reconciliation", () => {
737
737
  render(width: number): string[];
738
738
  handleInput(data: string): void;
739
739
  };
740
- for (let index = 0; index < 6; index++) component.handleInput("\t");
740
+ for (let index = 0; index < 7; index++) component.handleInput("\t");
741
741
  const label = target === "showTag" ? "Show exact-match tag" : "Ignore submodules";
742
742
  for (let attempts = 0; attempts < 12; attempts++) {
743
743
  if (component.render(140).some((line) => line.includes(`> ${label}`))) break;
@@ -768,7 +768,7 @@ describe("responsive footer dependency reconciliation", () => {
768
768
  const component = factory({ requestRender() {} }, makeTheme(), {}, () => {}) as {
769
769
  handleInput?: (data: string) => void;
770
770
  };
771
- for (let index = 0; index < 5; index++) component.handleInput?.("\t");
771
+ for (let index = 0; index < 6; index++) component.handleInput?.("\t");
772
772
  for (let index = 0; index < 11; index++) component.handleInput?.("\x1b[B");
773
773
  component.handleInput?.(" ");
774
774
  });
@@ -788,7 +788,7 @@ describe("responsive footer dependency reconciliation", () => {
788
788
  const component = factory({ requestRender() {} }, makeTheme(), {}, () => {}) as {
789
789
  handleInput?: (data: string) => void;
790
790
  };
791
- for (let index = 0; index < 4; index++) component.handleInput?.("\t");
791
+ for (let index = 0; index < 5; index++) component.handleInput?.("\t");
792
792
  for (let index = 0; index < 4; index++) component.handleInput?.("\x1b[B");
793
793
  component.handleInput?.(" ");
794
794
  });