@astralyn/pi 0.84.1 → 0.84.3

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 (163) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/dist/cli/args.js +1 -1
  3. package/dist/cli/args.js.map +1 -1
  4. package/dist/cli/config-selector.d.ts.map +1 -1
  5. package/dist/cli/config-selector.js +2 -3
  6. package/dist/cli/config-selector.js.map +1 -1
  7. package/dist/cli/startup-ui.d.ts.map +1 -1
  8. package/dist/cli/startup-ui.js +3 -5
  9. package/dist/cli/startup-ui.js.map +1 -1
  10. package/dist/config.d.ts +5 -0
  11. package/dist/config.d.ts.map +1 -1
  12. package/dist/config.js +8 -1
  13. package/dist/config.js.map +1 -1
  14. package/dist/core/agent-session.d.ts +1 -25
  15. package/dist/core/agent-session.d.ts.map +1 -1
  16. package/dist/core/agent-session.js +29 -408
  17. package/dist/core/agent-session.js.map +1 -1
  18. package/dist/core/compaction-controller.d.ts +89 -0
  19. package/dist/core/compaction-controller.d.ts.map +1 -0
  20. package/dist/core/compaction-controller.js +428 -0
  21. package/dist/core/compaction-controller.js.map +1 -0
  22. package/dist/core/extensions/index.d.ts +1 -1
  23. package/dist/core/extensions/index.d.ts.map +1 -1
  24. package/dist/core/extensions/index.js.map +1 -1
  25. package/dist/core/extensions/loader.js +3 -3
  26. package/dist/core/extensions/loader.js.map +1 -1
  27. package/dist/core/extensions/types.d.ts +1 -15
  28. package/dist/core/extensions/types.d.ts.map +1 -1
  29. package/dist/core/extensions/types.js.map +1 -1
  30. package/dist/core/provider-attribution.js +2 -2
  31. package/dist/core/provider-attribution.js.map +1 -1
  32. package/dist/core/settings-manager.js +1 -1
  33. package/dist/core/settings-manager.js.map +1 -1
  34. package/dist/core/telemetry.d.ts +1 -1
  35. package/dist/core/telemetry.d.ts.map +1 -1
  36. package/dist/core/telemetry.js +1 -1
  37. package/dist/core/telemetry.js.map +1 -1
  38. package/dist/extensions/deepwiki/index.d.ts.map +1 -1
  39. package/dist/extensions/deepwiki/index.js +23 -1
  40. package/dist/extensions/deepwiki/index.js.map +1 -1
  41. package/dist/extensions/deepwiki/render.d.ts +1 -1
  42. package/dist/extensions/deepwiki/render.d.ts.map +1 -1
  43. package/dist/extensions/deepwiki/render.js +4 -2
  44. package/dist/extensions/deepwiki/render.js.map +1 -1
  45. package/dist/extensions/index.d.ts.map +1 -1
  46. package/dist/extensions/index.js +0 -4
  47. package/dist/extensions/index.js.map +1 -1
  48. package/dist/extensions/question/index.d.ts.map +1 -1
  49. package/dist/extensions/question/index.js +0 -1
  50. package/dist/extensions/question/index.js.map +1 -1
  51. package/dist/extensions/subagent/index.d.ts.map +1 -1
  52. package/dist/extensions/subagent/index.js +20 -2
  53. package/dist/extensions/subagent/index.js.map +1 -1
  54. package/dist/extensions/todo/schema.d.ts +1 -1
  55. package/dist/extensions/todo/state.js +5 -5
  56. package/dist/extensions/todo/state.js.map +1 -1
  57. package/dist/modes/interactive/components/extension-selector.d.ts +0 -2
  58. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  59. package/dist/modes/interactive/components/extension-selector.js +1 -1
  60. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  61. package/dist/modes/interactive/components/settings-selector.js +1 -1
  62. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  63. package/dist/modes/interactive/components/tool-chrome.d.ts +28 -0
  64. package/dist/modes/interactive/components/tool-chrome.d.ts.map +1 -0
  65. package/dist/modes/interactive/components/tool-chrome.js +81 -0
  66. package/dist/modes/interactive/components/tool-chrome.js.map +1 -0
  67. package/dist/modes/interactive/components/tool-execution.d.ts +0 -3
  68. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  69. package/dist/modes/interactive/components/tool-execution.js +11 -108
  70. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  71. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  72. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  73. package/dist/modes/interactive/interactive-mode.js +35 -52
  74. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  75. package/docs/bundled/README.md +0 -2
  76. package/docs/bundled/extensions/subagent.md +1 -1
  77. package/docs/bundled/tool-presentation.md +2 -2
  78. package/docs/docs.json +0 -8
  79. package/docs/extensions.md +6 -23
  80. package/docs/settings.md +1 -1
  81. package/docs/usage.md +1 -2
  82. package/examples/extensions/README.md +2 -0
  83. package/examples/extensions/plan-mode/README.md +66 -0
  84. package/examples/extensions/plan-mode/index.ts +390 -0
  85. package/examples/extensions/plan-mode/utils.ts +168 -0
  86. package/examples/extensions/subagent/README.md +175 -0
  87. package/examples/extensions/subagent/agents/planner.md +37 -0
  88. package/examples/extensions/subagent/agents/reviewer.md +35 -0
  89. package/examples/extensions/subagent/agents/scout.md +50 -0
  90. package/examples/extensions/subagent/agents/worker.md +24 -0
  91. package/examples/extensions/subagent/agents.ts +126 -0
  92. package/examples/extensions/subagent/index.ts +1009 -0
  93. package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
  94. package/examples/extensions/subagent/prompts/implement.md +10 -0
  95. package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
  96. package/npm-shrinkwrap.json +2 -2
  97. package/package.json +1 -1
  98. package/dist/extensions/biu/index.d.ts +0 -19
  99. package/dist/extensions/biu/index.d.ts.map +0 -1
  100. package/dist/extensions/biu/index.js +0 -350
  101. package/dist/extensions/biu/index.js.map +0 -1
  102. package/dist/extensions/biu/prompts.d.ts +0 -26
  103. package/dist/extensions/biu/prompts.d.ts.map +0 -1
  104. package/dist/extensions/biu/prompts.js +0 -260
  105. package/dist/extensions/biu/prompts.js.map +0 -1
  106. package/dist/extensions/biu/workspace.d.ts +0 -122
  107. package/dist/extensions/biu/workspace.d.ts.map +0 -1
  108. package/dist/extensions/biu/workspace.js +0 -404
  109. package/dist/extensions/biu/workspace.js.map +0 -1
  110. package/dist/extensions/rewind/anchor.d.ts +0 -29
  111. package/dist/extensions/rewind/anchor.d.ts.map +0 -1
  112. package/dist/extensions/rewind/anchor.js +0 -35
  113. package/dist/extensions/rewind/anchor.js.map +0 -1
  114. package/dist/extensions/rewind/config.d.ts +0 -16
  115. package/dist/extensions/rewind/config.d.ts.map +0 -1
  116. package/dist/extensions/rewind/config.js +0 -69
  117. package/dist/extensions/rewind/config.js.map +0 -1
  118. package/dist/extensions/rewind/engine.d.ts +0 -93
  119. package/dist/extensions/rewind/engine.d.ts.map +0 -1
  120. package/dist/extensions/rewind/engine.js +0 -778
  121. package/dist/extensions/rewind/engine.js.map +0 -1
  122. package/dist/extensions/rewind/gc.d.ts +0 -35
  123. package/dist/extensions/rewind/gc.d.ts.map +0 -1
  124. package/dist/extensions/rewind/gc.js +0 -169
  125. package/dist/extensions/rewind/gc.js.map +0 -1
  126. package/dist/extensions/rewind/index.d.ts +0 -3
  127. package/dist/extensions/rewind/index.d.ts.map +0 -1
  128. package/dist/extensions/rewind/index.js +0 -287
  129. package/dist/extensions/rewind/index.js.map +0 -1
  130. package/dist/extensions/rewind/menu.d.ts +0 -13
  131. package/dist/extensions/rewind/menu.d.ts.map +0 -1
  132. package/dist/extensions/rewind/menu.js +0 -123
  133. package/dist/extensions/rewind/menu.js.map +0 -1
  134. package/dist/extensions/rewind/paths.d.ts +0 -4
  135. package/dist/extensions/rewind/paths.d.ts.map +0 -1
  136. package/dist/extensions/rewind/paths.js +0 -15
  137. package/dist/extensions/rewind/paths.js.map +0 -1
  138. package/dist/extensions/rewind/restore.d.ts +0 -54
  139. package/dist/extensions/rewind/restore.d.ts.map +0 -1
  140. package/dist/extensions/rewind/restore.js +0 -94
  141. package/dist/extensions/rewind/restore.js.map +0 -1
  142. package/dist/extensions/rewind/snapshot.d.ts +0 -45
  143. package/dist/extensions/rewind/snapshot.d.ts.map +0 -1
  144. package/dist/extensions/rewind/snapshot.js +0 -21
  145. package/dist/extensions/rewind/snapshot.js.map +0 -1
  146. package/dist/extensions/rewind/storage.d.ts +0 -12
  147. package/dist/extensions/rewind/storage.d.ts.map +0 -1
  148. package/dist/extensions/rewind/storage.js +0 -33
  149. package/dist/extensions/rewind/storage.js.map +0 -1
  150. package/dist/extensions/rewind/text.d.ts +0 -7
  151. package/dist/extensions/rewind/text.d.ts.map +0 -1
  152. package/dist/extensions/rewind/text.js +0 -19
  153. package/dist/extensions/rewind/text.js.map +0 -1
  154. package/dist/extensions/rewind/tool-path.d.ts +0 -3
  155. package/dist/extensions/rewind/tool-path.d.ts.map +0 -1
  156. package/dist/extensions/rewind/tool-path.js +0 -9
  157. package/dist/extensions/rewind/tool-path.js.map +0 -1
  158. package/dist/utils/coalescing-terminal.d.ts +0 -132
  159. package/dist/utils/coalescing-terminal.d.ts.map +0 -1
  160. package/dist/utils/coalescing-terminal.js +0 -292
  161. package/dist/utils/coalescing-terminal.js.map +0 -1
  162. package/docs/bundled/extensions/biu.md +0 -63
  163. package/docs/bundled/extensions/rewind.md +0 -86
@@ -0,0 +1,10 @@
1
+ ---
2
+ description: Worker implements, reviewer reviews, worker applies feedback
3
+ ---
4
+ Use the subagent tool with the chain parameter to execute this workflow:
5
+
6
+ 1. First, use the "worker" agent to implement: $@
7
+ 2. Then, use the "reviewer" agent to review the implementation from the previous step (use {previous} placeholder)
8
+ 3. Finally, use the "worker" agent to apply the feedback from the review (use {previous} placeholder)
9
+
10
+ Execute this as a chain, passing output between steps via {previous}.
@@ -0,0 +1,10 @@
1
+ ---
2
+ description: Full implementation workflow - scout gathers context, planner creates plan, worker implements
3
+ ---
4
+ Use the subagent tool with the chain parameter to execute this workflow:
5
+
6
+ 1. First, use the "scout" agent to find all code relevant to: $@
7
+ 2. Then, use the "planner" agent to create an implementation plan for "$@" using the context from the previous step (use {previous} placeholder)
8
+ 3. Finally, use the "worker" agent to implement the plan from the previous step (use {previous} placeholder)
9
+
10
+ Execute this as a chain, passing output between steps via {previous}.
@@ -0,0 +1,9 @@
1
+ ---
2
+ description: Scout gathers context, planner creates implementation plan (no implementation)
3
+ ---
4
+ Use the subagent tool with the chain parameter to execute this workflow:
5
+
6
+ 1. First, use the "scout" agent to find all code relevant to: $@
7
+ 2. Then, use the "planner" agent to create an implementation plan for "$@" using the context from the previous step (use {previous} placeholder)
8
+
9
+ Execute this as a chain, passing output between steps via {previous}. Do NOT implement - just return the plan.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@astralyn/pi",
3
- "version": "0.84.1",
3
+ "version": "0.84.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@astralyn/pi",
9
- "version": "0.84.1",
9
+ "version": "0.84.3",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@earendil-works/pi-agent-core": "0.84.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astralyn/pi",
3
- "version": "0.84.1",
3
+ "version": "0.84.3",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -1,19 +0,0 @@
1
- import { Container, Text } from "@earendil-works/pi-tui";
2
- import type { ExtensionAPI, MessageRenderOptions } from "../../core/extensions/types.ts";
3
- import type { CustomMessage } from "../../core/messages.ts";
4
- import type { Theme } from "../../modes/interactive/theme/theme.ts";
5
- import { type BiuStage } from "./workspace.ts";
6
- export declare const BIU_COMMAND_NAME = "biu";
7
- export declare const BIU_MODE_ENTRY_TYPE = "biu-mode";
8
- export declare const BIU_KICKOFF_MESSAGE_TYPE = "biu-kickoff";
9
- export declare const BIU_STATUS_KEY = "biu";
10
- export declare const BIU_MODE_SCHEMA_VERSION = 2;
11
- export interface BiuKickoffDetails {
12
- schemaVersion: number;
13
- stage: BiuStage;
14
- }
15
- /** Replay the latest Biu Mode flag from a session branch. */
16
- export declare function replayBiuMode(entries: Iterable<unknown>): boolean;
17
- export declare function renderBiuKickoffMessage(message: CustomMessage<BiuKickoffDetails>, options: MessageRenderOptions, theme: Theme): Text | Container;
18
- export default function biuExtension(pi: ExtensionAPI): void;
19
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/biu/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EACX,YAAY,EAGZ,oBAAoB,EACpB,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAQpE,OAAO,EAGN,KAAK,QAAQ,EAQb,MAAM,gBAAgB,CAAC;AAExB,eAAO,MAAM,gBAAgB,QAAQ,CAAC;AACtC,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAC9C,eAAO,MAAM,wBAAwB,gBAAgB,CAAC;AACtD,eAAO,MAAM,cAAc,QAAQ,CAAC;AACpC,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAYzC,MAAM,WAAW,iBAAiB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,QAAQ,CAAC;CAChB;AAQD,6DAA6D;AAC7D,wBAAgB,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,OAAO,CAUjE;AAeD,wBAAgB,uBAAuB,CACtC,OAAO,EAAE,aAAa,CAAC,iBAAiB,CAAC,EACzC,OAAO,EAAE,oBAAoB,EAC7B,KAAK,EAAE,KAAK,oBAYZ;AAED,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CA6R3D"}
@@ -1,350 +0,0 @@
1
- /**
2
- * biu — a structured development workflow (plan -> optional decompose ->
3
- * execute -> archive) modeled after Plan Mode.
4
- *
5
- * /biu toggles Biu Mode on; inside the mode, /biu opens the management menu.
6
- * Workflow state lives in the frontmatter of the workspace Markdown files
7
- * under the Pi agent directory; the extension only derives a read-only
8
- * snapshot from them. The model addresses those files through the biu://
9
- * scheme, which a tool_call hook resolves to the real workspace paths, so
10
- * read/write/edit/grep/find/ls work on them with short, stable paths.
11
- * Archiving a cycle is deterministic and menu-driven, never model-driven.
12
- */
13
- import { readFile } from "node:fs/promises";
14
- import { sep } from "node:path";
15
- import { Container, Text } from "@earendil-works/pi-tui";
16
- import { isStaleExtensionContextError } from "../../core/extensions/types.js";
17
- import { keyHint } from "../../modes/interactive/components/keybinding-hints.js";
18
- import { buildBiuKickoffContent, buildBiuResidentPrompt, buildBiuWorkspaceErrorPrompt, describeBiuFocus, formatBiuStatusLine, } from "./prompts.js";
19
- import { archiveBiuCycle, detectSpecReadyTransition, ensureBiuWorkspace, getBiuPaths, isBiuUri, loadBiuSnapshot, resolveBiuUri, sanitizeShortname, } from "./workspace.js";
20
- export const BIU_COMMAND_NAME = "biu";
21
- export const BIU_MODE_ENTRY_TYPE = "biu-mode";
22
- export const BIU_KICKOFF_MESSAGE_TYPE = "biu-kickoff";
23
- export const BIU_STATUS_KEY = "biu";
24
- export const BIU_MODE_SCHEMA_VERSION = 2;
25
- const BIU_TUI_ONLY_MESSAGE = "Biu Mode is available only in interactive TUI mode.";
26
- /** Core tools whose `path` argument understands the biu:// scheme. */
27
- const BIU_PATH_TOOLS = new Set(["read", "write", "edit", "grep", "find", "ls"]);
28
- function isBiuModeEntryData(value) {
29
- if (!value || typeof value !== "object")
30
- return false;
31
- const record = value;
32
- return typeof record.schemaVersion === "number" && typeof record.enabled === "boolean";
33
- }
34
- /** Replay the latest Biu Mode flag from a session branch. */
35
- export function replayBiuMode(entries) {
36
- const branch = Array.from(entries);
37
- for (let index = branch.length - 1; index >= 0; index--) {
38
- const candidate = branch[index];
39
- if (!candidate || typeof candidate !== "object")
40
- continue;
41
- const entry = candidate;
42
- if (entry.type !== "custom" || entry.customType !== BIU_MODE_ENTRY_TYPE)
43
- continue;
44
- if (isBiuModeEntryData(entry.data))
45
- return entry.data.enabled;
46
- }
47
- return false;
48
- }
49
- function truncate(text, maxLength) {
50
- const inline = text.replace(/\s+/g, " ").trim();
51
- return inline.length <= maxLength ? inline : `${inline.slice(0, maxLength - 1)}…`;
52
- }
53
- function isInsideWorkspace(absolutePath, root) {
54
- return absolutePath === root || absolutePath.startsWith(`${root}${sep}`);
55
- }
56
- function expandHint(theme) {
57
- return `${theme.fg("muted", " (")}${keyHint("app.tools.expand", "to expand")}${theme.fg("muted", ")")}`;
58
- }
59
- export function renderBiuKickoffMessage(message, options, theme) {
60
- const content = typeof message.content === "string" ? message.content : "";
61
- const stage = message.details?.stage;
62
- const summary = `Biu · continue${stage ? ` ${stage}` : ""}`;
63
- if (!options.expanded) {
64
- return new Text(`${theme.fg("accent", theme.bold(summary))}${expandHint(theme)}`, options.outputPad, 0);
65
- }
66
- const container = new Container();
67
- container.addChild(new Text(theme.fg("accent", theme.bold(summary)), options.outputPad, 0));
68
- container.addChild(new Text(theme.fg("muted", content), options.outputPad, 0));
69
- return container;
70
- }
71
- export default function biuExtension(pi) {
72
- let enabled = false;
73
- function persistMode(nextEnabled) {
74
- pi.appendEntry(BIU_MODE_ENTRY_TYPE, { schemaVersion: BIU_MODE_SCHEMA_VERSION, enabled: nextEnabled });
75
- }
76
- function setStatus(ctx, snapshot, error) {
77
- if (ctx.mode !== "tui")
78
- return;
79
- if (!enabled) {
80
- ctx.ui.setStatus(BIU_STATUS_KEY, undefined);
81
- return;
82
- }
83
- if (snapshot) {
84
- const color = snapshot.problems.length > 0 ? "warning" : snapshot.stage === "archive" ? "success" : "accent";
85
- ctx.ui.setStatus(BIU_STATUS_KEY, ctx.ui.theme.fg(color, formatBiuStatusLine(snapshot)));
86
- }
87
- else {
88
- ctx.ui.setStatus(BIU_STATUS_KEY, ctx.ui.theme.fg("warning", error ? "Biu · workspace error" : "Biu"));
89
- }
90
- }
91
- async function refreshStatusFromDisk(ctx) {
92
- try {
93
- setStatus(ctx, await loadBiuSnapshot(ctx.cwd));
94
- }
95
- catch (error) {
96
- if (isStaleExtensionContextError(error))
97
- return;
98
- try {
99
- setStatus(ctx, undefined, error instanceof Error ? error.message : String(error));
100
- }
101
- catch (statusError) {
102
- if (!isStaleExtensionContextError(statusError))
103
- throw statusError;
104
- }
105
- }
106
- }
107
- function disableMode(ctx) {
108
- enabled = false;
109
- persistMode(false);
110
- setStatus(ctx, undefined);
111
- ctx.ui.notify("Biu Mode off. Workflow files were kept.", "info");
112
- }
113
- function sendKickoff(snapshot) {
114
- pi.sendMessage({
115
- customType: BIU_KICKOFF_MESSAGE_TYPE,
116
- content: buildBiuKickoffContent(snapshot),
117
- display: true,
118
- details: { schemaVersion: BIU_MODE_SCHEMA_VERSION, stage: snapshot.stage },
119
- }, { triggerTurn: true });
120
- }
121
- /** Menu-driven, deterministic cycle close: confirm, name, move, report. */
122
- async function archiveFromMenu(ctx, snapshot) {
123
- if (!snapshot.spec.exists || !snapshot.summaryExists) {
124
- ctx.ui.notify("Archiving needs both biu://SPEC.md and a confirmed biu://Summary.md. Ask the agent to draft the summary first (archive stage).", "warning");
125
- return;
126
- }
127
- const unfinished = snapshot.tasks.filter((task) => task.status !== "completed");
128
- if (unfinished.length > 0) {
129
- const proceed = await ctx.ui.confirm("Archive with unfinished tasks?", `${unfinished.length} task(s) are not completed: ${truncate(unfinished.map((task) => task.id).join(", "), 200)}`);
130
- if (!proceed)
131
- return;
132
- }
133
- let shortname = snapshot.spec.title ? sanitizeShortname(snapshot.spec.title) : "";
134
- if (!shortname) {
135
- const answer = await ctx.ui.input("Archive name", "short, filesystem-safe name for the archived cycle");
136
- if (!answer?.trim()) {
137
- ctx.ui.notify("Archive cancelled: no name given.", "info");
138
- return;
139
- }
140
- shortname = answer.trim();
141
- }
142
- try {
143
- const result = await archiveBiuCycle(ctx.cwd, shortname);
144
- await refreshStatusFromDisk(ctx);
145
- ctx.ui.notify(`Cycle archived to ${result.archivedPath}. A fresh cycle starts at the plan stage.`, "info");
146
- }
147
- catch (error) {
148
- if (isStaleExtensionContextError(error))
149
- return;
150
- ctx.ui.notify(`Archive failed: ${truncate(error instanceof Error ? error.message : String(error), 300)}`, "error");
151
- }
152
- }
153
- async function openMenu(ctx) {
154
- if (ctx.mode !== "tui") {
155
- ctx.ui.notify(BIU_TUI_ONLY_MESSAGE, "warning");
156
- return;
157
- }
158
- let snapshot;
159
- try {
160
- await ensureBiuWorkspace(ctx.cwd);
161
- snapshot = await loadBiuSnapshot(ctx.cwd);
162
- }
163
- catch (error) {
164
- if (isStaleExtensionContextError(error))
165
- return;
166
- const message = error instanceof Error ? error.message : String(error);
167
- const choice = await ctx.ui.select("Biu Mode", ["Exit Biu Mode"], {
168
- subtitle: truncate(`Workspace error: ${message}`, 120),
169
- cancelHint: "keep Biu Mode active",
170
- });
171
- if (choice === "Exit Biu Mode")
172
- disableMode(ctx);
173
- return;
174
- }
175
- setStatus(ctx, snapshot);
176
- const subtitleParts = [formatBiuStatusLine(snapshot)];
177
- if (snapshot.problems.length > 0)
178
- subtitleParts.push(`${snapshot.problems.length} problem(s)`);
179
- const continueLabel = `Continue · ${snapshot.stage}`;
180
- const choice = await ctx.ui.select("Biu Mode", [
181
- { label: continueLabel, description: truncate(describeBiuFocus(snapshot), 80) },
182
- { label: "Archive cycle", description: "Move SPEC.md, Summary.md, and tasks/ into archived/" },
183
- { label: "Exit Biu Mode", description: "Turn the mode off; workflow files are kept" },
184
- ], { subtitle: subtitleParts.join(" · "), cancelHint: "keep Biu Mode active" });
185
- if (choice === continueLabel) {
186
- sendKickoff(snapshot);
187
- }
188
- else if (choice === "Archive cycle") {
189
- await archiveFromMenu(ctx, snapshot);
190
- }
191
- else if (choice === "Exit Biu Mode") {
192
- disableMode(ctx);
193
- }
194
- }
195
- async function syncFromBranch(ctx) {
196
- try {
197
- if (ctx.mode !== "tui") {
198
- enabled = false;
199
- return;
200
- }
201
- enabled = replayBiuMode(ctx.sessionManager.getBranch());
202
- if (enabled)
203
- await refreshStatusFromDisk(ctx);
204
- else
205
- ctx.ui.setStatus(BIU_STATUS_KEY, undefined);
206
- }
207
- catch (error) {
208
- if (!isStaleExtensionContextError(error))
209
- throw error;
210
- }
211
- }
212
- pi.registerMessageRenderer(BIU_KICKOFF_MESSAGE_TYPE, renderBiuKickoffMessage);
213
- pi.registerCommand(BIU_COMMAND_NAME, {
214
- description: "Toggle Biu Mode; inside the mode, open the Biu menu",
215
- handler: async (args, ctx) => {
216
- if (ctx.mode !== "tui") {
217
- ctx.ui.notify(BIU_TUI_ONLY_MESSAGE, "warning");
218
- return;
219
- }
220
- if (args.trim()) {
221
- ctx.ui.notify("Usage: /biu (no arguments)", "warning");
222
- return;
223
- }
224
- await ctx.waitForIdle();
225
- if (enabled) {
226
- await openMenu(ctx);
227
- return;
228
- }
229
- let snapshot;
230
- try {
231
- await ensureBiuWorkspace(ctx.cwd);
232
- snapshot = await loadBiuSnapshot(ctx.cwd);
233
- }
234
- catch (error) {
235
- if (isStaleExtensionContextError(error))
236
- return;
237
- ctx.ui.notify(`Unable to open the Biu workspace: ${truncate(error instanceof Error ? error.message : String(error), 300)}`, "error");
238
- return;
239
- }
240
- enabled = true;
241
- persistMode(true);
242
- setStatus(ctx, snapshot);
243
- const fresh = !snapshot.spec.exists && snapshot.tasks.length === 0 && !snapshot.summaryExists;
244
- if (fresh) {
245
- ctx.ui.notify("Biu Mode on · plan — describe what you want to build to start the interview.", "info");
246
- }
247
- else {
248
- ctx.ui.notify(`Biu Mode on · ${formatBiuStatusLine(snapshot).replace(/^Biu · /, "")}\n${describeBiuFocus(snapshot)}\nUse /biu for the menu.`, "info");
249
- }
250
- },
251
- });
252
- // Resolve biu:// paths for the core file tools. Always active: the scheme is
253
- // deterministic and harmless outside Biu Mode, and rewriting only happens on
254
- // explicit biu:// arguments. The session keeps the model's original biu://
255
- // arguments; only execution sees the resolved absolute path.
256
- pi.on("tool_call", async (event, ctx) => {
257
- if (!BIU_PATH_TOOLS.has(event.toolName))
258
- return;
259
- const input = event.input;
260
- if (typeof input.path !== "string")
261
- return;
262
- if (isBiuUri(input.path)) {
263
- const resolution = resolveBiuUri(input.path, ctx.cwd);
264
- if (!resolution.ok)
265
- return { block: true, reason: resolution.reason };
266
- input.path = resolution.path;
267
- }
268
- // Approval gate: flipping the SPEC's frontmatter status to ready needs the
269
- // user's explicit sign-off (the Biu analogue of ExitPlanMode approval).
270
- // The gate is a guardrail, not a sandbox: on any internal failure it steps
271
- // aside and lets the write proceed.
272
- if (!enabled || ctx.mode !== "tui")
273
- return;
274
- if (event.toolName !== "write" && event.toolName !== "edit")
275
- return;
276
- try {
277
- if (input.path !== getBiuPaths(ctx.cwd).specFile)
278
- return;
279
- const current = await readFile(input.path, "utf8").catch(() => null);
280
- if (!detectSpecReadyTransition(current, event.toolName, event.input))
281
- return;
282
- const approved = await ctx.ui.confirm("Approve SPEC?", "The agent wants to mark biu://SPEC.md as ready. Approving moves the cycle to the execute stage.");
283
- if (approved)
284
- return;
285
- const feedback = await ctx.ui.input("Feedback", "why it was declined (sent to the agent)");
286
- const feedbackNote = feedback?.trim() ? ` Feedback: ${feedback.trim()}.` : "";
287
- return {
288
- block: true,
289
- reason: `The user declined to approve the SPEC as ready.${feedbackNote} Revise biu://SPEC.md accordingly, keep status: draft, and ask again when ready.`,
290
- };
291
- }
292
- catch {
293
- // A gate failure must never block a legitimate write.
294
- return;
295
- }
296
- });
297
- // Frontmatter edits through write/edit are the only workflow state changes;
298
- // refresh the statusline whenever one lands inside the workspace.
299
- pi.on("tool_result", async (event, ctx) => {
300
- if (!enabled || ctx.mode !== "tui" || event.isError)
301
- return;
302
- if (event.toolName !== "write" && event.toolName !== "edit")
303
- return;
304
- const input = event.input;
305
- if (typeof input.path !== "string")
306
- return;
307
- try {
308
- if (!isInsideWorkspace(input.path, getBiuPaths(ctx.cwd).root))
309
- return;
310
- await refreshStatusFromDisk(ctx);
311
- }
312
- catch (error) {
313
- if (!isStaleExtensionContextError(error))
314
- throw error;
315
- }
316
- });
317
- pi.on("before_agent_start", async (event, ctx) => {
318
- if (!enabled || ctx.mode !== "tui")
319
- return;
320
- let block;
321
- try {
322
- block = buildBiuResidentPrompt(await loadBiuSnapshot(ctx.cwd));
323
- }
324
- catch (error) {
325
- if (isStaleExtensionContextError(error))
326
- return;
327
- block = buildBiuWorkspaceErrorPrompt(error instanceof Error ? error.message : String(error));
328
- }
329
- return { systemPrompt: `${event.systemPrompt}\n\n${block}` };
330
- });
331
- pi.on("session_start", async (_event, ctx) => {
332
- await syncFromBranch(ctx);
333
- });
334
- pi.on("session_tree", async (_event, ctx) => {
335
- await syncFromBranch(ctx);
336
- });
337
- pi.on("session_shutdown", async (_event, ctx) => {
338
- enabled = false;
339
- if (ctx.mode !== "tui")
340
- return;
341
- try {
342
- ctx.ui.setStatus(BIU_STATUS_KEY, undefined);
343
- }
344
- catch (error) {
345
- if (!isStaleExtensionContextError(error))
346
- throw error;
347
- }
348
- });
349
- }
350
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/biu/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * biu — a structured development workflow (plan -> optional decompose ->\n * execute -> archive) modeled after Plan Mode.\n *\n * /biu toggles Biu Mode on; inside the mode, /biu opens the management menu.\n * Workflow state lives in the frontmatter of the workspace Markdown files\n * under the Pi agent directory; the extension only derives a read-only\n * snapshot from them. The model addresses those files through the biu://\n * scheme, which a tool_call hook resolves to the real workspace paths, so\n * read/write/edit/grep/find/ls work on them with short, stable paths.\n * Archiving a cycle is deterministic and menu-driven, never model-driven.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { sep } from \"node:path\";\nimport { Container, Text } from \"@earendil-works/pi-tui\";\nimport type {\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n\tMessageRenderOptions,\n} from \"../../core/extensions/types.ts\";\nimport { isStaleExtensionContextError } from \"../../core/extensions/types.ts\";\nimport type { CustomMessage } from \"../../core/messages.ts\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport {\n\tbuildBiuKickoffContent,\n\tbuildBiuResidentPrompt,\n\tbuildBiuWorkspaceErrorPrompt,\n\tdescribeBiuFocus,\n\tformatBiuStatusLine,\n} from \"./prompts.ts\";\nimport {\n\tarchiveBiuCycle,\n\ttype BiuSnapshot,\n\ttype BiuStage,\n\tdetectSpecReadyTransition,\n\tensureBiuWorkspace,\n\tgetBiuPaths,\n\tisBiuUri,\n\tloadBiuSnapshot,\n\tresolveBiuUri,\n\tsanitizeShortname,\n} from \"./workspace.ts\";\n\nexport const BIU_COMMAND_NAME = \"biu\";\nexport const BIU_MODE_ENTRY_TYPE = \"biu-mode\";\nexport const BIU_KICKOFF_MESSAGE_TYPE = \"biu-kickoff\";\nexport const BIU_STATUS_KEY = \"biu\";\nexport const BIU_MODE_SCHEMA_VERSION = 2;\n\nconst BIU_TUI_ONLY_MESSAGE = \"Biu Mode is available only in interactive TUI mode.\";\n\n/** Core tools whose `path` argument understands the biu:// scheme. */\nconst BIU_PATH_TOOLS = new Set([\"read\", \"write\", \"edit\", \"grep\", \"find\", \"ls\"]);\n\ninterface BiuModeEntryData {\n\tschemaVersion: number;\n\tenabled: boolean;\n}\n\nexport interface BiuKickoffDetails {\n\tschemaVersion: number;\n\tstage: BiuStage;\n}\n\nfunction isBiuModeEntryData(value: unknown): value is BiuModeEntryData {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst record = value as Record<string, unknown>;\n\treturn typeof record.schemaVersion === \"number\" && typeof record.enabled === \"boolean\";\n}\n\n/** Replay the latest Biu Mode flag from a session branch. */\nexport function replayBiuMode(entries: Iterable<unknown>): boolean {\n\tconst branch = Array.from(entries);\n\tfor (let index = branch.length - 1; index >= 0; index--) {\n\t\tconst candidate = branch[index];\n\t\tif (!candidate || typeof candidate !== \"object\") continue;\n\t\tconst entry = candidate as { type?: unknown; customType?: unknown; data?: unknown };\n\t\tif (entry.type !== \"custom\" || entry.customType !== BIU_MODE_ENTRY_TYPE) continue;\n\t\tif (isBiuModeEntryData(entry.data)) return entry.data.enabled;\n\t}\n\treturn false;\n}\n\nfunction truncate(text: string, maxLength: number): string {\n\tconst inline = text.replace(/\\s+/g, \" \").trim();\n\treturn inline.length <= maxLength ? inline : `${inline.slice(0, maxLength - 1)}…`;\n}\n\nfunction isInsideWorkspace(absolutePath: string, root: string): boolean {\n\treturn absolutePath === root || absolutePath.startsWith(`${root}${sep}`);\n}\n\nfunction expandHint(theme: Theme): string {\n\treturn `${theme.fg(\"muted\", \" (\")}${keyHint(\"app.tools.expand\", \"to expand\")}${theme.fg(\"muted\", \")\")}`;\n}\n\nexport function renderBiuKickoffMessage(\n\tmessage: CustomMessage<BiuKickoffDetails>,\n\toptions: MessageRenderOptions,\n\ttheme: Theme,\n) {\n\tconst content = typeof message.content === \"string\" ? message.content : \"\";\n\tconst stage = message.details?.stage;\n\tconst summary = `Biu · continue${stage ? ` ${stage}` : \"\"}`;\n\tif (!options.expanded) {\n\t\treturn new Text(`${theme.fg(\"accent\", theme.bold(summary))}${expandHint(theme)}`, options.outputPad, 0);\n\t}\n\tconst container = new Container();\n\tcontainer.addChild(new Text(theme.fg(\"accent\", theme.bold(summary)), options.outputPad, 0));\n\tcontainer.addChild(new Text(theme.fg(\"muted\", content), options.outputPad, 0));\n\treturn container;\n}\n\nexport default function biuExtension(pi: ExtensionAPI): void {\n\tlet enabled = false;\n\n\tfunction persistMode(nextEnabled: boolean): void {\n\t\tpi.appendEntry(BIU_MODE_ENTRY_TYPE, { schemaVersion: BIU_MODE_SCHEMA_VERSION, enabled: nextEnabled });\n\t}\n\n\tfunction setStatus(ctx: ExtensionContext, snapshot: BiuSnapshot | undefined, error?: string): void {\n\t\tif (ctx.mode !== \"tui\") return;\n\t\tif (!enabled) {\n\t\t\tctx.ui.setStatus(BIU_STATUS_KEY, undefined);\n\t\t\treturn;\n\t\t}\n\t\tif (snapshot) {\n\t\t\tconst color = snapshot.problems.length > 0 ? \"warning\" : snapshot.stage === \"archive\" ? \"success\" : \"accent\";\n\t\t\tctx.ui.setStatus(BIU_STATUS_KEY, ctx.ui.theme.fg(color, formatBiuStatusLine(snapshot)));\n\t\t} else {\n\t\t\tctx.ui.setStatus(BIU_STATUS_KEY, ctx.ui.theme.fg(\"warning\", error ? \"Biu · workspace error\" : \"Biu\"));\n\t\t}\n\t}\n\n\tasync function refreshStatusFromDisk(ctx: ExtensionContext): Promise<void> {\n\t\ttry {\n\t\t\tsetStatus(ctx, await loadBiuSnapshot(ctx.cwd));\n\t\t} catch (error) {\n\t\t\tif (isStaleExtensionContextError(error)) return;\n\t\t\ttry {\n\t\t\t\tsetStatus(ctx, undefined, error instanceof Error ? error.message : String(error));\n\t\t\t} catch (statusError) {\n\t\t\t\tif (!isStaleExtensionContextError(statusError)) throw statusError;\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction disableMode(ctx: ExtensionContext): void {\n\t\tenabled = false;\n\t\tpersistMode(false);\n\t\tsetStatus(ctx, undefined);\n\t\tctx.ui.notify(\"Biu Mode off. Workflow files were kept.\", \"info\");\n\t}\n\n\tfunction sendKickoff(snapshot: BiuSnapshot): void {\n\t\tpi.sendMessage(\n\t\t\t{\n\t\t\t\tcustomType: BIU_KICKOFF_MESSAGE_TYPE,\n\t\t\t\tcontent: buildBiuKickoffContent(snapshot),\n\t\t\t\tdisplay: true,\n\t\t\t\tdetails: { schemaVersion: BIU_MODE_SCHEMA_VERSION, stage: snapshot.stage } satisfies BiuKickoffDetails,\n\t\t\t},\n\t\t\t{ triggerTurn: true },\n\t\t);\n\t}\n\n\t/** Menu-driven, deterministic cycle close: confirm, name, move, report. */\n\tasync function archiveFromMenu(ctx: ExtensionCommandContext, snapshot: BiuSnapshot): Promise<void> {\n\t\tif (!snapshot.spec.exists || !snapshot.summaryExists) {\n\t\t\tctx.ui.notify(\n\t\t\t\t\"Archiving needs both biu://SPEC.md and a confirmed biu://Summary.md. Ask the agent to draft the summary first (archive stage).\",\n\t\t\t\t\"warning\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tconst unfinished = snapshot.tasks.filter((task) => task.status !== \"completed\");\n\t\tif (unfinished.length > 0) {\n\t\t\tconst proceed = await ctx.ui.confirm(\n\t\t\t\t\"Archive with unfinished tasks?\",\n\t\t\t\t`${unfinished.length} task(s) are not completed: ${truncate(unfinished.map((task) => task.id).join(\", \"), 200)}`,\n\t\t\t);\n\t\t\tif (!proceed) return;\n\t\t}\n\t\tlet shortname = snapshot.spec.title ? sanitizeShortname(snapshot.spec.title) : \"\";\n\t\tif (!shortname) {\n\t\t\tconst answer = await ctx.ui.input(\"Archive name\", \"short, filesystem-safe name for the archived cycle\");\n\t\t\tif (!answer?.trim()) {\n\t\t\t\tctx.ui.notify(\"Archive cancelled: no name given.\", \"info\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tshortname = answer.trim();\n\t\t}\n\t\ttry {\n\t\t\tconst result = await archiveBiuCycle(ctx.cwd, shortname);\n\t\t\tawait refreshStatusFromDisk(ctx);\n\t\t\tctx.ui.notify(`Cycle archived to ${result.archivedPath}. A fresh cycle starts at the plan stage.`, \"info\");\n\t\t} catch (error) {\n\t\t\tif (isStaleExtensionContextError(error)) return;\n\t\t\tctx.ui.notify(\n\t\t\t\t`Archive failed: ${truncate(error instanceof Error ? error.message : String(error), 300)}`,\n\t\t\t\t\"error\",\n\t\t\t);\n\t\t}\n\t}\n\n\tasync function openMenu(ctx: ExtensionCommandContext): Promise<void> {\n\t\tif (ctx.mode !== \"tui\") {\n\t\t\tctx.ui.notify(BIU_TUI_ONLY_MESSAGE, \"warning\");\n\t\t\treturn;\n\t\t}\n\n\t\tlet snapshot: BiuSnapshot;\n\t\ttry {\n\t\t\tawait ensureBiuWorkspace(ctx.cwd);\n\t\t\tsnapshot = await loadBiuSnapshot(ctx.cwd);\n\t\t} catch (error) {\n\t\t\tif (isStaleExtensionContextError(error)) return;\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconst choice = await ctx.ui.select(\"Biu Mode\", [\"Exit Biu Mode\"], {\n\t\t\t\tsubtitle: truncate(`Workspace error: ${message}`, 120),\n\t\t\t\tcancelHint: \"keep Biu Mode active\",\n\t\t\t});\n\t\t\tif (choice === \"Exit Biu Mode\") disableMode(ctx);\n\t\t\treturn;\n\t\t}\n\t\tsetStatus(ctx, snapshot);\n\n\t\tconst subtitleParts = [formatBiuStatusLine(snapshot)];\n\t\tif (snapshot.problems.length > 0) subtitleParts.push(`${snapshot.problems.length} problem(s)`);\n\t\tconst continueLabel = `Continue · ${snapshot.stage}`;\n\t\tconst choice = await ctx.ui.select(\n\t\t\t\"Biu Mode\",\n\t\t\t[\n\t\t\t\t{ label: continueLabel, description: truncate(describeBiuFocus(snapshot), 80) },\n\t\t\t\t{ label: \"Archive cycle\", description: \"Move SPEC.md, Summary.md, and tasks/ into archived/\" },\n\t\t\t\t{ label: \"Exit Biu Mode\", description: \"Turn the mode off; workflow files are kept\" },\n\t\t\t],\n\t\t\t{ subtitle: subtitleParts.join(\" · \"), cancelHint: \"keep Biu Mode active\" },\n\t\t);\n\n\t\tif (choice === continueLabel) {\n\t\t\tsendKickoff(snapshot);\n\t\t} else if (choice === \"Archive cycle\") {\n\t\t\tawait archiveFromMenu(ctx, snapshot);\n\t\t} else if (choice === \"Exit Biu Mode\") {\n\t\t\tdisableMode(ctx);\n\t\t}\n\t}\n\n\tasync function syncFromBranch(ctx: ExtensionContext): Promise<void> {\n\t\ttry {\n\t\t\tif (ctx.mode !== \"tui\") {\n\t\t\t\tenabled = false;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tenabled = replayBiuMode(ctx.sessionManager.getBranch());\n\t\t\tif (enabled) await refreshStatusFromDisk(ctx);\n\t\t\telse ctx.ui.setStatus(BIU_STATUS_KEY, undefined);\n\t\t} catch (error) {\n\t\t\tif (!isStaleExtensionContextError(error)) throw error;\n\t\t}\n\t}\n\n\tpi.registerMessageRenderer<BiuKickoffDetails>(BIU_KICKOFF_MESSAGE_TYPE, renderBiuKickoffMessage);\n\n\tpi.registerCommand(BIU_COMMAND_NAME, {\n\t\tdescription: \"Toggle Biu Mode; inside the mode, open the Biu menu\",\n\t\thandler: async (args, ctx) => {\n\t\t\tif (ctx.mode !== \"tui\") {\n\t\t\t\tctx.ui.notify(BIU_TUI_ONLY_MESSAGE, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (args.trim()) {\n\t\t\t\tctx.ui.notify(\"Usage: /biu (no arguments)\", \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tawait ctx.waitForIdle();\n\n\t\t\tif (enabled) {\n\t\t\t\tawait openMenu(ctx);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet snapshot: BiuSnapshot;\n\t\t\ttry {\n\t\t\t\tawait ensureBiuWorkspace(ctx.cwd);\n\t\t\t\tsnapshot = await loadBiuSnapshot(ctx.cwd);\n\t\t\t} catch (error) {\n\t\t\t\tif (isStaleExtensionContextError(error)) return;\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Unable to open the Biu workspace: ${truncate(error instanceof Error ? error.message : String(error), 300)}`,\n\t\t\t\t\t\"error\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tenabled = true;\n\t\t\tpersistMode(true);\n\t\t\tsetStatus(ctx, snapshot);\n\n\t\t\tconst fresh = !snapshot.spec.exists && snapshot.tasks.length === 0 && !snapshot.summaryExists;\n\t\t\tif (fresh) {\n\t\t\t\tctx.ui.notify(\"Biu Mode on · plan — describe what you want to build to start the interview.\", \"info\");\n\t\t\t} else {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Biu Mode on · ${formatBiuStatusLine(snapshot).replace(/^Biu · /, \"\")}\\n${describeBiuFocus(snapshot)}\\nUse /biu for the menu.`,\n\t\t\t\t\t\"info\",\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t});\n\n\t// Resolve biu:// paths for the core file tools. Always active: the scheme is\n\t// deterministic and harmless outside Biu Mode, and rewriting only happens on\n\t// explicit biu:// arguments. The session keeps the model's original biu://\n\t// arguments; only execution sees the resolved absolute path.\n\tpi.on(\"tool_call\", async (event, ctx) => {\n\t\tif (!BIU_PATH_TOOLS.has(event.toolName)) return;\n\t\tconst input = event.input as { path?: unknown };\n\t\tif (typeof input.path !== \"string\") return;\n\t\tif (isBiuUri(input.path)) {\n\t\t\tconst resolution = resolveBiuUri(input.path, ctx.cwd);\n\t\t\tif (!resolution.ok) return { block: true, reason: resolution.reason };\n\t\t\tinput.path = resolution.path;\n\t\t}\n\n\t\t// Approval gate: flipping the SPEC's frontmatter status to ready needs the\n\t\t// user's explicit sign-off (the Biu analogue of ExitPlanMode approval).\n\t\t// The gate is a guardrail, not a sandbox: on any internal failure it steps\n\t\t// aside and lets the write proceed.\n\t\tif (!enabled || ctx.mode !== \"tui\") return;\n\t\tif (event.toolName !== \"write\" && event.toolName !== \"edit\") return;\n\t\ttry {\n\t\t\tif (input.path !== getBiuPaths(ctx.cwd).specFile) return;\n\t\t\tconst current = await readFile(input.path, \"utf8\").catch(() => null);\n\t\t\tif (!detectSpecReadyTransition(current, event.toolName, event.input as Record<string, unknown>)) return;\n\t\t\tconst approved = await ctx.ui.confirm(\n\t\t\t\t\"Approve SPEC?\",\n\t\t\t\t\"The agent wants to mark biu://SPEC.md as ready. Approving moves the cycle to the execute stage.\",\n\t\t\t);\n\t\t\tif (approved) return;\n\t\t\tconst feedback = await ctx.ui.input(\"Feedback\", \"why it was declined (sent to the agent)\");\n\t\t\tconst feedbackNote = feedback?.trim() ? ` Feedback: ${feedback.trim()}.` : \"\";\n\t\t\treturn {\n\t\t\t\tblock: true,\n\t\t\t\treason: `The user declined to approve the SPEC as ready.${feedbackNote} Revise biu://SPEC.md accordingly, keep status: draft, and ask again when ready.`,\n\t\t\t};\n\t\t} catch {\n\t\t\t// A gate failure must never block a legitimate write.\n\t\t\treturn;\n\t\t}\n\t});\n\n\t// Frontmatter edits through write/edit are the only workflow state changes;\n\t// refresh the statusline whenever one lands inside the workspace.\n\tpi.on(\"tool_result\", async (event, ctx) => {\n\t\tif (!enabled || ctx.mode !== \"tui\" || event.isError) return;\n\t\tif (event.toolName !== \"write\" && event.toolName !== \"edit\") return;\n\t\tconst input = event.input as { path?: unknown };\n\t\tif (typeof input.path !== \"string\") return;\n\t\ttry {\n\t\t\tif (!isInsideWorkspace(input.path, getBiuPaths(ctx.cwd).root)) return;\n\t\t\tawait refreshStatusFromDisk(ctx);\n\t\t} catch (error) {\n\t\t\tif (!isStaleExtensionContextError(error)) throw error;\n\t\t}\n\t});\n\n\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\tif (!enabled || ctx.mode !== \"tui\") return;\n\t\tlet block: string;\n\t\ttry {\n\t\t\tblock = buildBiuResidentPrompt(await loadBiuSnapshot(ctx.cwd));\n\t\t} catch (error) {\n\t\t\tif (isStaleExtensionContextError(error)) return;\n\t\t\tblock = buildBiuWorkspaceErrorPrompt(error instanceof Error ? error.message : String(error));\n\t\t}\n\t\treturn { systemPrompt: `${event.systemPrompt}\\n\\n${block}` };\n\t});\n\n\tpi.on(\"session_start\", async (_event, ctx) => {\n\t\tawait syncFromBranch(ctx);\n\t});\n\n\tpi.on(\"session_tree\", async (_event, ctx) => {\n\t\tawait syncFromBranch(ctx);\n\t});\n\n\tpi.on(\"session_shutdown\", async (_event, ctx) => {\n\t\tenabled = false;\n\t\tif (ctx.mode !== \"tui\") return;\n\t\ttry {\n\t\t\tctx.ui.setStatus(BIU_STATUS_KEY, undefined);\n\t\t} catch (error) {\n\t\t\tif (!isStaleExtensionContextError(error)) throw error;\n\t\t}\n\t});\n}\n"]}
@@ -1,26 +0,0 @@
1
- /**
2
- * biu/prompts.ts — model-facing text for the Biu workflow.
3
- *
4
- * Biu has no workflow tool: workflow state lives in the frontmatter of the
5
- * workspace Markdown files, and the full guidance for the derived stage is
6
- * injected into the system prompt each turn while Biu Mode is on. The model
7
- * addresses workspace files exclusively through biu:// paths.
8
- */
9
- import type { BiuSnapshot } from "./workspace.ts";
10
- export declare const BIU_COMMON_RULES = "You are working inside Biu Mode, a structured development workflow: plan -> (optional decompose) -> execute -> archive.\n\nCore rules:\n- Workspace files are addressed with the biu:// scheme: biu://SPEC.md, biu://tasks/TASK-<short-name>.md, biu://Summary.md. Use the read/write/edit/grep/find/ls tools with these exact paths; they resolve to a private workspace outside the project repository. Never operate on these files through bash, never use their real filesystem location, and never create workflow files inside the project.\n- Workflow state lives in the frontmatter of those files: the SPEC's status (draft/ready), each task's status (ready/in_progress/completed) and depends_on. Update frontmatter immediately when state changes; there is no other state store.\n- The <biu_snapshot> block reflects the workspace at the start of the turn. After you edit files, your edits are newer than the snapshot.\n- Investigate code, tests, and documentation directly before asking the user anything answerable from the project. Ask the user only about product intent, preferences, scope boundaries, or risk tolerance.\n- Moving backward is always allowed: for example, reopen the SPEC by setting status: draft when execution reveals a gap.\n- Work in the user's language. Keep user-facing replies concise while keeping the workflow files complete.";
11
- export declare const BIU_SPEC_TEMPLATE = "---\ntitle: <short title>\nstatus: draft\nexecution: direct\nbaseline_commit: <sha or \"none\">\n---\n\n# SPEC: <short title>\n\n## Goal\n<One or two sentences describing the problem and expected outcome.>\n\n## Background & Facts\n<Verified current-state facts, when useful.>\n\n## Scope\n- <What this cycle covers.>\n\n## Non-Goals\n- <What it deliberately does not cover, and why.>\n\n## Constraints\n- <Hard requirements.>\n\n## Architecture\n<Only what reduces implementation ambiguity.>\n\n## Design\n<Important interfaces, data flows, migration, or compatibility details.>\n\n## Decisions\n- **Decision**: <decision>\n - Reasoning: <why>\n - Alternatives considered: <rejected alternatives>\n\n## Risks\n- **Risk**: <risk>\n - Impact: <impact>\n - Mitigation: <mitigation>\n\n## Open Questions\n- [ ] <unresolved question>\n\n## Acceptance Criteria\n- [ ] AC1: <verifiable condition>";
12
- export declare const BIU_TASK_TEMPLATE = "---\ntitle: <short task title>\nstatus: ready\ndepends_on: []\n---\n\n# TASK-<short-name>: <title>\n\n## Objective\n<One clear objective and its boundary.>\n\n## Context\n\n### Critical Files\n- `path/to/file.ts` \u2014 <why it matters>\n\n<Existing code to reuse, conventions, decisions, and constraints.>\n\n## Steps\n- [ ] <meaningful checkpoint>\n\n## Verify\n<Commands and edge/error cases that prove the task works.>\n\n- [ ] <verifiable condition>\n\n## Covers\n- AC1\n\n## Implementation Decisions\n\n## Notes\n- <incremental notes>";
13
- export declare const BIU_SUMMARY_TEMPLATE = "---\ntitle: <title>\nhead_commit: <sha or \"none\">\n---\n\n# Summary: <title>\n\n## Outcome\n<What was actually achieved and how it differs from the SPEC goal.>\n\n## Decisions & Discoveries\n- <Implementation decisions and new domain knowledge not already in SPEC.>\n\n## Deviations\n- <What changed from SPEC and why, or none.>\n\n## Task Results\n| AC | Tasks | Status | Notes |\n|:--:|:-----:|:------:|:-----:|\n| AC1 | TASK-<name> | completed | <result> |\n\n## Gaps & Follow-Ups\n- <Unverified or deferred work, or None.>";
14
- /** Human-readable focus line shared by the snapshot, statusline menus, and kickoff message. */
15
- export declare function describeBiuFocus(snapshot: BiuSnapshot): string;
16
- /** Compact JSON snapshot of the workspace, wrapped for prompt use. */
17
- export declare function buildBiuSnapshotBlock(snapshot: BiuSnapshot): string;
18
- /** The full Biu block injected into the system prompt each turn while the mode is on. */
19
- export declare function buildBiuResidentPrompt(snapshot: BiuSnapshot): string;
20
- /** Short status line, e.g. "Biu · execute 2/5" — shared by the statusline and menus. */
21
- export declare function formatBiuStatusLine(snapshot: BiuSnapshot): string;
22
- /** Fallback resident block when the workspace snapshot cannot be built at all. */
23
- export declare function buildBiuWorkspaceErrorPrompt(message: string): string;
24
- /** Content of the kickoff message sent when the user picks "Continue" from the /biu menu. */
25
- export declare function buildBiuKickoffContent(snapshot: BiuSnapshot): string;
26
- //# sourceMappingURL=prompts.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/extensions/biu/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,eAAO,MAAM,gBAAgB,q0CAQ8E,CAAC;AAE5G,eAAO,MAAM,iBAAiB,m4BA4CI,CAAC;AAEnC,eAAO,MAAM,iBAAiB,iiBAgCR,CAAC;AAEvB,eAAO,MAAM,oBAAoB,qhBAsBS,CAAC;AAwF3C,+FAA+F;AAC/F,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CAM9D;AAED,sEAAsE;AACtE,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CAgBnE;AAWD,yFAAyF;AACzF,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CAQpE;AAED,wFAAwF;AACxF,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CAQjE;AAED,kFAAkF;AAClF,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGpE;AAED,6FAA6F;AAC7F,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CAGpE"}