@selesai/code 0.3.10 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/dist/core/agent-session-auto-handoff.test.d.ts +2 -0
  2. package/dist/core/agent-session-auto-handoff.test.d.ts.map +1 -0
  3. package/dist/core/agent-session-auto-handoff.test.js +161 -0
  4. package/dist/core/agent-session-auto-handoff.test.js.map +1 -0
  5. package/dist/core/agent-session.d.ts +4 -0
  6. package/dist/core/agent-session.d.ts.map +1 -1
  7. package/dist/core/agent-session.js +43 -0
  8. package/dist/core/agent-session.js.map +1 -1
  9. package/dist/core/settings-manager-auto-handoff.test.d.ts +2 -0
  10. package/dist/core/settings-manager-auto-handoff.test.d.ts.map +1 -0
  11. package/dist/core/settings-manager-auto-handoff.test.js +29 -0
  12. package/dist/core/settings-manager-auto-handoff.test.js.map +1 -0
  13. package/dist/core/settings-manager.d.ts +9 -0
  14. package/dist/core/settings-manager.d.ts.map +1 -1
  15. package/dist/core/settings-manager.js +22 -0
  16. package/dist/core/settings-manager.js.map +1 -1
  17. package/dist/defaults/models.json +2 -3
  18. package/dist/extensions/caveman/index.js +16 -1
  19. package/dist/extensions/caveman/test/extension.test.js +7 -4
  20. package/dist/extensions/caveman/test/helpers.test.js +12 -1
  21. package/dist/extensions/context-compaction-reminder.test.ts +82 -0
  22. package/dist/extensions/context-compaction-reminder.ts +28 -0
  23. package/dist/extensions/handoff-new.test.ts +2 -13
  24. package/dist/extensions/handoff-new.ts +16 -25
  25. package/dist/extensions/package.json +1 -0
  26. package/dist/extensions/pi-powerline-footer/index.ts +43 -2
  27. package/dist/extensions/pi-powerline-footer/session-usage.ts +44 -0
  28. package/dist/extensions/pi-powerline-footer/tests/session-usage.test.ts +47 -0
  29. package/dist/extensions/pi-subagents/README.md +1 -1
  30. package/dist/extensions/pi-subagents/agents/architect.md +9 -29
  31. package/dist/extensions/pi-subagents/agents/builder.md +17 -106
  32. package/dist/extensions/pi-subagents/agents/commentator.md +20 -117
  33. package/dist/extensions/pi-subagents/agents/explorer.md +14 -35
  34. package/dist/extensions/pi-subagents/agents/recapper.md +20 -12
  35. package/dist/extensions/pi-subagents/agents/researcher.md +11 -34
  36. package/dist/extensions/pi-subagents/src/agents/agents.ts +46 -0
  37. package/dist/extensions/pi-subagents/src/extension/index.ts +2 -1
  38. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +2 -0
  39. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +24 -0
  40. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +25 -1
  41. package/dist/extensions/question/constants.ts +0 -7
  42. package/dist/extensions/question/index.ts +11 -108
  43. package/dist/extensions/question/schemas.ts +1 -26
  44. package/dist/extensions/question/shortcuts.ts +5 -14
  45. package/dist/extensions/question/tests/question-list.test.ts +8 -0
  46. package/dist/extensions/question/tests/ui-protocol.test.ts +1 -7
  47. package/dist/extensions/question/tui-adapter.ts +3 -20
  48. package/dist/extensions/question/types.ts +0 -6
  49. package/dist/extensions/question/ui-protocol.ts +2 -17
  50. package/dist/extensions/workflow/adapter.ts +395 -275
  51. package/dist/extensions/workflow/extension.ts +2 -1
  52. package/dist/extensions/workflow/modes/prototype.ts +17 -19
  53. package/dist/extensions/workflow/modes/quick.ts +17 -19
  54. package/dist/extensions/workflow/modes/task.ts +82 -0
  55. package/dist/extensions/workflow/run-state.ts +124 -0
  56. package/dist/extensions/workflow/state-machine.ts +7 -8
  57. package/dist/extensions/workflow/task-validators.ts +69 -0
  58. package/dist/index.d.ts +1 -1
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js.map +1 -1
  61. package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
  62. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  63. package/dist/modes/interactive/components/settings-selector.js +20 -0
  64. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  65. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  66. package/dist/modes/interactive/interactive-mode.js +8 -0
  67. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  68. package/dist/modes/rpc/rpc-client.d.ts +8 -0
  69. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  70. package/dist/modes/rpc/rpc-client.js +12 -0
  71. package/dist/modes/rpc/rpc-client.js.map +1 -1
  72. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  73. package/dist/modes/rpc/rpc-mode.js +14 -0
  74. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  75. package/dist/modes/rpc/rpc-types.d.ts +20 -0
  76. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  77. package/dist/modes/rpc/rpc-types.js.map +1 -1
  78. package/dist/skills/workflow-creation/SKILL.md +72 -0
  79. package/docs/workflows.md +46 -7
  80. package/package.json +1 -1
@@ -28,11 +28,10 @@ function createPiHarness() {
28
28
  return { commands };
29
29
  }
30
30
 
31
- test("registers both handoff-new and handover-new commands", () => {
31
+ test("registers handoff-new only", () => {
32
32
  const { commands } = createPiHarness();
33
33
  assert.ok(commands.has("handoff-new"));
34
- assert.ok(commands.has("handover-new"));
35
- assert.equal(commands.get("handoff-new")?.handler, commands.get("handover-new")?.handler);
34
+ assert.equal(commands.has("handover-new"), false);
36
35
  });
37
36
 
38
37
  // ---- pure helpers ----
@@ -106,7 +105,6 @@ test("buildAiContext: embeds conversation + goal into one user turn", () => {
106
105
  function createCtx(opts: {
107
106
  branch?: SessionEntry[];
108
107
  model?: any;
109
- editorResult?: string;
110
108
  customResult?: string | null;
111
109
  mode?: string;
112
110
  } = {}) {
@@ -130,7 +128,6 @@ function createCtx(opts: {
130
128
  ui: {
131
129
  notify: (msg: string, kind: string) => calls.notify.push({ msg, kind }),
132
130
  custom: async <T>(_factory: any): Promise<T> => (opts.customResult === undefined ? "HANDOFF PROMPT" : opts.customResult) as unknown as T,
133
- editor: async (_title: string, prefill?: string) => ("editorResult" in opts ? opts.editorResult : prefill),
134
131
  setEditorText: (text: string) => {
135
132
  calls.editorText = text;
136
133
  },
@@ -196,14 +193,6 @@ test("custom null (cancelled) does not open new session", async () => {
196
193
  assert.ok(calls.notify.some((n) => /Cancelled/.test(n.msg)));
197
194
  });
198
195
 
199
- test("editor cancel does not open new session", async () => {
200
- const { commands } = createPiHarness();
201
- const { ctx, calls } = createCtx({ editorResult: undefined });
202
- await commands.get("handoff-new")!.handler("goal", ctx);
203
- assert.equal(calls.newSession, null);
204
- assert.ok(calls.notify.some((n) => /Cancelled/.test(n.msg)));
205
- });
206
-
207
196
  // sanity: DEFAULT_GOAL exported and non-empty (used by handler)
208
197
  test("DEFAULT_GOAL is non-empty", () => {
209
198
  assert.ok(DEFAULT_GOAL.length > 0);
@@ -1,15 +1,14 @@
1
1
  /**
2
2
  * /handoff-new — generate a handoff prompt and open a clean new session with
3
- * that content as the editable first prompt (editor text, not hidden system
3
+ * that content as the first unsent prompt (editor text, not hidden system
4
4
  * prompt). Sibling of examples/extensions/handoff.ts, adapted to this repo's
5
5
  * import conventions and reduced to the one thing that ships.
6
6
  *
7
7
  * Usage:
8
8
  * /handoff-new continue implementing the workflow fix
9
- * /handover-new ship plan 2
10
9
  *
11
- * If no goal argument is given, a default goal is used. The generated text is
12
- * shown in the editor for review before the user submits it.
10
+ * If no goal argument is given, a default goal is used. The new session opens
11
+ * with the generated text in its editor; the user can change it before submit.
13
12
  */
14
13
 
15
14
  import type { AgentMessage } from "@earendil-works/pi-agent-core";
@@ -17,14 +16,15 @@ import { complete, type Context } from "@earendil-works/pi-ai/compat";
17
16
  import type { ExtensionAPI, ExtensionCommandContext, SessionEntry } from "@selesai/code";
18
17
  import { BorderedLoader, convertToLlm, serializeConversation } from "@selesai/code";
19
18
 
20
- const SYSTEM_PROMPT = `You are a context transfer assistant. Given a conversation history and the user's goal for a new thread, generate a focused prompt that:
19
+ const SYSTEM_PROMPT = `Write a handoff document summarising the current conversation so a fresh agent can continue the work. Save to the temporary directory of the user's OS - not the current workspace.
21
20
 
22
- 1. Summarizes relevant context from the conversation (decisions made, approaches taken, key findings)
23
- 2. Lists any relevant files that were discussed or modified
24
- 3. Clearly states the next task based on the user's goal
25
- 4. Is self-contained - the new thread should be able to proceed without the old conversation
21
+ Include a "suggested skills" section in the document, which suggests skills that the agent should invoke.
26
22
 
27
- Format your response as a prompt the user can send to start the new thread. Be concise but include all necessary context. Do not include any preamble like "Here's the prompt" - just output the prompt itself.`;
23
+ Do not duplicate content already captured in other artifacts (PRDs, plans, ADRs, issues, commits, diffs). Reference them by path or URL instead.
24
+
25
+ Redact any sensitive information, such as API keys, passwords, or personally identifiable information.
26
+
27
+ If the user passed arguments, treat them as a description of what the next session will focus on and tailor the doc accordingly.`;
28
28
 
29
29
  export const DEFAULT_GOAL = "Continue the previous session from this handoff.";
30
30
 
@@ -85,13 +85,10 @@ export function buildAiContext(conversationText: string, goal: string): Context
85
85
  }
86
86
 
87
87
  export default function (pi: ExtensionAPI) {
88
- // ponytail: single handler behind two command names; no separate config.
89
- for (const name of ["handoff-new", "handover-new"]) {
90
- pi.registerCommand(name, {
91
- description: "Generate a handoff prompt and open a clean new session with it as the first draft",
92
- handler: handoffNew,
93
- });
94
- }
88
+ pi.registerCommand("handoff-new", {
89
+ description: "Generate a handoff prompt and open a clean new session with it as the first draft",
90
+ handler: handoffNew,
91
+ });
95
92
  }
96
93
 
97
94
  async function handoffNew(args: string, ctx: ExtensionCommandContext) {
@@ -151,17 +148,11 @@ async function handoffNew(args: string, ctx: ExtensionCommandContext) {
151
148
  return;
152
149
  }
153
150
 
154
- const editedPrompt = await ctx.ui.editor("Edit handoff prompt", result);
155
- if (editedPrompt === undefined) {
156
- ctx.ui.notify("Cancelled", "info");
157
- return;
158
- }
159
-
160
- // Editor text, NOT a hidden system prompt: the user reviews and submits.
151
+ // Editor text, NOT a hidden system prompt: the user can edit before submit.
161
152
  const newSessionResult = await ctx.newSession({
162
153
  parentSession: currentSessionFile,
163
154
  withSession: async (replacementCtx) => {
164
- replacementCtx.ui.setEditorText(editedPrompt);
155
+ replacementCtx.ui.setEditorText(result);
165
156
  replacementCtx.ui.notify("Handoff ready. Submit when ready.", "info");
166
157
  },
167
158
  });
@@ -6,6 +6,7 @@
6
6
  "pi": {
7
7
  "extensions": [
8
8
  "./copy-turn.ts",
9
+ "./context-compaction-reminder.ts",
9
10
  "./tool-error-autofix.ts",
10
11
  "./question",
11
12
  "./handoff-new.ts",
@@ -62,6 +62,7 @@ import {
62
62
  generateVibesBatch,
63
63
  } from "./working-vibes.ts";
64
64
  import { setupTpsTracker } from "./tps.ts";
65
+ import { readAsyncSubagentUsage, readSubagentToolResultUsage } from "./session-usage.ts";
65
66
 
66
67
  // ═══════════════════════════════════════════════════════════════════════════
67
68
  // Configuration
@@ -928,6 +929,7 @@ export default function powerlineFooter(pi: ExtensionAPI) {
928
929
  let getThinkingLevelFn: (() => string) | null = null;
929
930
  let currentThinkingLevel: string | null = null;
930
931
  let liveAssistantUsage: SessionAssistantUsage | null = null;
932
+ const completedAsyncSubagentUsage = new Map<string, { input: number; output: number; cacheRead: number; cacheWrite: number; cost: number }>();
931
933
  let isStreaming = false;
932
934
  let tuiRef: any = null;
933
935
  let restoreFooterStatusRepaintHook: (() => void) | null = null;
@@ -1181,6 +1183,7 @@ export default function powerlineFooter(pi: ExtensionAPI) {
1181
1183
  lastUserPrompt = "";
1182
1184
  isStreaming = false;
1183
1185
  liveAssistantUsage = null;
1186
+ completedAsyncSubagentUsage.clear();
1184
1187
  stashedEditorText = null;
1185
1188
 
1186
1189
  const settings = readSettings(ctx.cwd);
@@ -1222,6 +1225,7 @@ export default function powerlineFooter(pi: ExtensionAPI) {
1222
1225
 
1223
1226
  pi.on("session_shutdown", async () => {
1224
1227
  sessionGeneration++;
1228
+ completedAsyncSubagentUsage.clear();
1225
1229
  dismissWelcomeOverlay?.();
1226
1230
  dismissWelcomeOverlay = null;
1227
1231
  welcomeHeaderActive = false;
@@ -1246,6 +1250,16 @@ export default function powerlineFooter(pi: ExtensionAPI) {
1246
1250
  resetLayoutCache();
1247
1251
  });
1248
1252
 
1253
+ pi.events.on("subagent:async-complete", (event) => {
1254
+ const completed = readAsyncSubagentUsage(event);
1255
+ const sessionId = currentCtx?.sessionManager?.getSessionId?.();
1256
+ if (!completed || !sessionId || completed.sessionId !== sessionId) return;
1257
+
1258
+ completedAsyncSubagentUsage.set(completed.runId, completed.usage);
1259
+ layoutDirty = true;
1260
+ requestImmediateStatusRender({ deferDuringTyping: false });
1261
+ });
1262
+
1249
1263
  // Check if a bash command might change git branch
1250
1264
  const mightChangeGitBranch = (cmd: string): boolean => {
1251
1265
  const gitBranchPatterns = [
@@ -1256,7 +1270,12 @@ export default function powerlineFooter(pi: ExtensionAPI) {
1256
1270
  };
1257
1271
 
1258
1272
  // Invalidate git status on file changes, trigger re-render on potential branch changes
1259
- pi.on("tool_result", async (event) => {
1273
+ pi.on("tool_result", async (event, ctx) => {
1274
+ if (event.toolName === "subagent") {
1275
+ currentCtx = ctx;
1276
+ layoutDirty = true;
1277
+ requestImmediateStatusRender({ deferDuringTyping: false });
1278
+ }
1260
1279
  if (event.toolName === "write" || event.toolName === "edit") {
1261
1280
  invalidateGitStatus();
1262
1281
  }
@@ -2051,7 +2070,21 @@ export default function powerlineFooter(pi: ExtensionAPI) {
2051
2070
  thinkingLevelFromSession = e.thinkingLevel;
2052
2071
  }
2053
2072
 
2054
- if (e.type !== "message" || !isSessionAssistantMessage(e.message)) {
2073
+ if (e.type !== "message") {
2074
+ continue;
2075
+ }
2076
+
2077
+ const subagentUsage = readSubagentToolResultUsage(e.message);
2078
+ if (subagentUsage) {
2079
+ input += subagentUsage.input;
2080
+ output += subagentUsage.output;
2081
+ cacheRead += subagentUsage.cacheRead;
2082
+ cacheWrite += subagentUsage.cacheWrite;
2083
+ cost += subagentUsage.cost;
2084
+ continue;
2085
+ }
2086
+
2087
+ if (!isSessionAssistantMessage(e.message)) {
2055
2088
  continue;
2056
2089
  }
2057
2090
 
@@ -2069,6 +2102,14 @@ export default function powerlineFooter(pi: ExtensionAPI) {
2069
2102
  }
2070
2103
  }
2071
2104
 
2105
+ for (const subagentUsage of completedAsyncSubagentUsage.values()) {
2106
+ input += subagentUsage.input;
2107
+ output += subagentUsage.output;
2108
+ cacheRead += subagentUsage.cacheRead;
2109
+ cacheWrite += subagentUsage.cacheWrite;
2110
+ cost += subagentUsage.cost;
2111
+ }
2112
+
2072
2113
  // Calculate context percentage.
2073
2114
  const latestUsage = isStreaming ? liveAssistantUsage ?? lastAssistant?.usage : lastAssistant?.usage;
2074
2115
  const coreContextUsage = isStreaming && liveAssistantUsage ? null : readCoreContextUsage(ctx);
@@ -0,0 +1,44 @@
1
+ import type { UsageStats } from "./types.ts";
2
+
3
+ type RecordLike = Record<string, unknown>;
4
+
5
+ function isRecord(value: unknown): value is RecordLike {
6
+ return value !== null && typeof value === "object" && !Array.isArray(value);
7
+ }
8
+
9
+ function finiteNumber(value: unknown): value is number {
10
+ return typeof value === "number" && Number.isFinite(value);
11
+ }
12
+
13
+ /**
14
+ * Extract the aggregate usage reported by a completed foreground subagent run.
15
+ * Child agents use separate sessions, so their assistant messages are not in
16
+ * the parent session branch. The parent records this aggregate on its
17
+ * `subagent` tool result instead.
18
+ */
19
+ function readUsage(value: unknown): UsageStats | null {
20
+ if (!isRecord(value)) return null;
21
+
22
+ const { input, output, cacheRead, cacheWrite, cost } = value;
23
+ if (![input, output, cacheRead, cacheWrite, cost].every(finiteNumber)) return null;
24
+
25
+ return { input, output, cacheRead, cacheWrite, cost };
26
+ }
27
+
28
+ export function readSubagentToolResultUsage(message: unknown): UsageStats | null {
29
+ if (!isRecord(message) || message.role !== "toolResult" || message.toolName !== "subagent") {
30
+ return null;
31
+ }
32
+
33
+ const details = isRecord(message.details) ? message.details : null;
34
+ return readUsage(details?.totalChildUsage);
35
+ }
36
+
37
+ /** Read usage emitted when an asynchronous subagent run completes. */
38
+ export function readAsyncSubagentUsage(event: unknown): { runId: string; sessionId: string; usage: UsageStats } | null {
39
+ if (!isRecord(event) || typeof event.sessionId !== "string") return null;
40
+
41
+ const runId = typeof event.runId === "string" ? event.runId : typeof event.id === "string" ? event.id : null;
42
+ const usage = readUsage(event.totalChildUsage);
43
+ return runId && usage ? { runId, sessionId: event.sessionId, usage } : null;
44
+ }
@@ -0,0 +1,47 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { readAsyncSubagentUsage, readSubagentToolResultUsage } from "../session-usage.ts";
4
+
5
+ test("reads all completed subagent usage from a parent tool result", () => {
6
+ assert.deepEqual(
7
+ readSubagentToolResultUsage({
8
+ role: "toolResult",
9
+ toolName: "subagent",
10
+ details: {
11
+ totalChildUsage: {
12
+ input: 120,
13
+ output: 34,
14
+ cacheRead: 56,
15
+ cacheWrite: 7,
16
+ cost: 0.123,
17
+ turns: 2,
18
+ },
19
+ },
20
+ }),
21
+ { input: 120, output: 34, cacheRead: 56, cacheWrite: 7, cost: 0.123 },
22
+ );
23
+ });
24
+
25
+ test("reads asynchronous completion usage", () => {
26
+ assert.deepEqual(
27
+ readAsyncSubagentUsage({
28
+ id: "async-123",
29
+ sessionId: "parent-session",
30
+ totalChildUsage: { input: 20, output: 8, cacheRead: 13, cacheWrite: 0, cost: 0.02 },
31
+ }),
32
+ {
33
+ runId: "async-123",
34
+ sessionId: "parent-session",
35
+ usage: { input: 20, output: 8, cacheRead: 13, cacheWrite: 0, cost: 0.02 },
36
+ },
37
+ );
38
+ });
39
+
40
+ test("does not treat other tool results or malformed usage as child usage", () => {
41
+ assert.equal(readSubagentToolResultUsage({ role: "toolResult", toolName: "bash", details: {} }), null);
42
+ assert.equal(readSubagentToolResultUsage({
43
+ role: "toolResult",
44
+ toolName: "subagent",
45
+ details: { totalChildUsage: { input: 1, output: 2 } },
46
+ }), null);
47
+ });
@@ -155,7 +155,7 @@ For a persistent override, edit settings. This example pins the reviewer everywh
155
155
  }
156
156
  ```
157
157
 
158
- Use `~/.pi/agent/settings.json` for a user override or the project config settings file (`.pi/settings.json` in standard Pi) for a project override. `subagents.defaultModel` applies to builtin, package, user, and project agents that do not set `model` in frontmatter. Per-run model overrides and `agentOverrides.<name>.model` still win, and explicit agent frontmatter still wins over the global default. The same `agentOverrides` block can change `tools`, `skills`, inherited context, prompt text, or disable a builtin. Matching user and project agents also receive override fields that their frontmatter leaves unset, so a shared project config agent can keep the persona while local settings choose the model.
158
+ Use `~/.selesai/agent/settings.json` for a user override or the project config settings file (`.selesai/settings.json`) for a project override. On a Selesai session start, if either `subagents.defaultModel` or `subagents.agentOverrides` is missing from user settings, pi-subagents adds it without replacing any existing settings. The seeded default is the current session's `provider/model`, and every bundled agent is prefilled in `agentOverrides` with that model so its setting is visible and editable. `subagents.defaultModel` applies to builtin, package, user, and project agents that do not set `model` in frontmatter. Per-run model overrides and `agentOverrides.<name>.model` still win, and explicit agent frontmatter still wins over the global default. The same `agentOverrides` block can change `tools`, `skills`, inherited context, prompt text, or disable a builtin. Matching user and project agents also receive override fields that their frontmatter leaves unset, so a shared project config agent can keep the persona while local settings choose the model.
159
159
 
160
160
  If your provider rejects model IDs with thinking suffixes, set `subagents.disableThinking: true` in user or project settings. That clears bundled builtin thinking defaults in one place; an explicit higher-precedence `agentOverrides.<name>.thinking` value can opt a role back in.
161
161
 
@@ -1,34 +1,14 @@
1
1
  ---
2
2
  name: architect
3
- model: tokenin/glm-5.2
4
- thinking: high
5
- description: Creates implementation plans from context and requirements
6
- tools: read, grep, find, ls, write, intercom
7
- systemPromptMode: replace
8
- inheritProjectContext: true
9
- inheritSkills: true
10
- skill: ponytail, planger
11
- output: plan.md
12
- defaultReads: context.md
13
- defaultContext: fork
3
+ description: Creates implementation plans from context and requirements
4
+ tools: read, grep, find, ls
5
+ systemPromptMode: replace
6
+ inheritProjectContext: true
7
+ inheritSkills: false
8
+ skill: ponytail, caveman, planger
9
+ defaultContext: fork
14
10
  ---
15
11
 
16
- You are a planning subagent.
17
-
18
- Your job is to turn requirements and code context into a concrete implementation plan. Do not make code changes. Read, analyze, and write the plan only.
19
-
20
- Working rules:
21
- - Read the provided context before planning.
22
- - Read any additional code you need in order to make the plan concrete.
23
- - Name exact files whenever you can.
24
- - Prefer small, ordered, actionable tasks over vague phases.
25
- - Call out risks, dependencies, and anything that needs explicit validation.
26
- - If the task is underspecified, surface the ambiguity in the plan instead of guessing.
27
-
28
- Output format (`plan.md`):
29
-
30
- # Implementation Plan
31
-
32
12
  ## Goal
33
13
 
34
14
  Create implementation plans that can be executed by a small coding model with:
@@ -39,7 +19,7 @@ Create implementation plans that can be executed by a small coding model with:
39
19
  - Weak architectural understanding
40
20
  - No ability to infer missing steps
41
21
 
42
- Assume the executor only knows what is written in the plan.
22
+ Assume the executor only knows what is written in the plan. Return the complete plan in your final response; do not write an output file.
43
23
 
44
24
  # Core Principles
45
25
 
@@ -54,7 +34,7 @@ Never assume:
54
34
  - Existing utilities
55
35
 
56
36
  If the code has not been inspected, the plan must begin with discovery.
57
- You research the codebase (using explorer agent) → clarify with the user (using questions tool) → capture findings and decisions into a comprehensive plan. This iterative approach catches edge cases and non-obvious requirements BEFORE implementation begins.
37
+ You research the codebase (using explore agent) → clarify with the user (using questions tool) → capture findings and decisions into a comprehensive plan. This iterative approach catches edge cases and non-obvious requirements BEFORE implementation begins.
58
38
 
59
39
  ## Simplicity First
60
40
 
@@ -1,120 +1,31 @@
1
1
  ---
2
2
  name: builder
3
- model: tokenin/qwen3.6-35b
3
+ description: Implementation agent for normal task handoffs
4
4
  thinking: high
5
- description: Implementation agent for normal tasks handoffs
6
5
  systemPromptMode: replace
7
6
  tools: read, grep, find, ls, bash, edit, write, contact_supervisor
8
- inheritSkills: true
9
- skill: ponytail, implanger
7
+ inheritSkills: false
8
+ skill: ponytail, caveman, implanger
10
9
  inheritProjectContext: true
11
10
  defaultContext: fresh
12
- defaultReads: context.md, plan.md, handoff.md
13
- defaultProgress: true
14
11
  ---
15
12
 
16
- You are `builder` the implementation subagent.
13
+ You are `builder`, the sole writer for the delegated task. The main agent and user remain the decision authority.
17
14
 
18
- You are the single writer thread. Your job is to execute the assigned task or approved direction with narrow, coherent edits. The main agent and user remain the decision authority.
15
+ Read the supplied task, artifacts, and relevant code before changing anything. Implement the smallest correct change in the active workspace, follow existing patterns, and run focused validation.
19
16
 
20
- Use the provided tools directly. First understand the inherited context, supplied files, plan, and explicit task. Then implement carefully and minimally.
17
+ Rules:
18
+ - Make only approved, in-scope changes. Do not add speculative scaffolding, placeholders, wrappers, fallback paths, or unrelated refactors.
19
+ - Trace callers when changing shared behavior; fix the shared cause rather than patching one path.
20
+ - If a required product, architecture, or scope decision is not approved, use `contact_supervisor` with `reason: "need_decision"` and wait. Do not guess.
21
+ - Do not launch subagents. Do not send routine completion handoffs.
22
+ - Do not claim success without making the requested edits, unless you are blocked and report why.
21
23
 
22
- If the task is framed as an approved direction, oracle handoff, or execution plan, treat that direction as the contract. Validate it against the actual code, but do not silently make new product, architecture, or scope decisions.
24
+ Before finishing, verify the requirement, changed files, and relevant tests/checks.
23
25
 
24
- If the implementation reveals a decision that was not approved and is required to continue safely, pause and escalate through the live coordination channel. If runtime bridge instructions are present, use them as the source of truth for which supervisor session to contact and how to coordinate. Use `contact_supervisor` with `reason: "need_decision"` when a new decision is needed, and stay alive to receive the reply before continuing. Use `reason: "progress_update"` only for concise non-blocking progress updates when that extra coordination is helpful or explicitly requested. Fall back to generic `intercom` only if `contact_supervisor` is unavailable. Do not finish your final response with a question that requires the supervisor to choose before you can continue.
26
+ Final response:
25
27
 
26
- Default responsibilities:
27
- - validate the task or approved direction against the actual code
28
- - implement the smallest correct change
29
- - follow existing patterns in the codebase
30
- - verify the result with appropriate checks when possible
31
- - keep `progress.md` accurate when asked to maintain it
32
- - report back clearly with changes, validation, risks, and next steps
33
-
34
- Working rules:
35
- - Prefer narrow, correct changes over broad rewrites.
36
- - Do not add speculative scaffolding or future-proofing unless explicitly required.
37
- - Do not leave placeholder code, TODOs, or silent scope changes.
38
- - Use `bash` for inspection, validation, and relevant tests.
39
- - If there is supplied context or a plan, read it first.
40
- - If implementation reveals a gap in the approved direction, pause and escalate with `contact_supervisor` and `reason: "need_decision"` instead of silently patching around it with an implicit decision.
41
- - If implementation reveals an unapproved product or architecture choice, use `contact_supervisor` with `reason: "need_decision"` and wait for the reply instead of deciding it yourself or returning a final choose-one answer.
42
- - If your delegated task expects code or file edits and you have not made those edits, do not return a success summary. Make the edits, contact the supervisor if blocked, or explicitly report that no edits were made.
43
- - If you send a blocked/progress update through `contact_supervisor`, keep it short and still return the full structured task result normally.
44
- - Do not send routine completion handoffs. Return the completed implementation summary normally when no coordination is needed.
45
-
46
- ## Goal
47
-
48
- Implement the requested change with the smallest correct modification.
49
-
50
- ## Before Changing Code
51
-
52
- - Read surrounding code
53
- - Follow existing patterns
54
- - Verify assumptions
55
- - Trace usages when needed
56
-
57
- Never assume behavior that can be inspected.
58
-
59
- ## Implementation Rules
60
-
61
- - Prefer consistency over preference
62
- - Make the smallest correct change
63
- - Reuse existing code before creating new code
64
- - Do not solve future problems
65
- - Do not refactor unrelated areas
66
- - Do not introduce abstractions for one use case
67
-
68
- ## Backward Compatibility
69
-
70
- Do not add:
71
-
72
- - Wrappers
73
- - Adapters
74
- - Fallbacks
75
- - Feature flags
76
- - Dual execution paths
77
-
78
- unless explicitly required.
79
-
80
- When replacing behavior:
81
-
82
- 1. Find usages
83
- 2. Update usages
84
- 3. Remove obsolete code
85
-
86
- Prefer one source of truth.
87
-
88
- ## Comments
89
-
90
- Only explain:
91
-
92
- - Business rules
93
- - External constraints
94
- - Vendor quirks
95
- - Non-obvious decisions
96
-
97
- Do not narrate code.
98
-
99
- ## Validation
100
-
101
- Before completion verify:
102
-
103
- - Requirement satisfied
104
- - Scope remained limited
105
- - Existing patterns followed
106
- - No unnecessary complexity added
107
- - No dead code remains
108
-
109
- When running in a chain, expect instructions about:
110
- - which files to read first
111
- - where to maintain progress tracking
112
- - where to write output if a file target is provided
113
-
114
- Your final response should follow this shape:
115
-
116
- Implemented X.
117
- Changed files: Y.
118
- Validation: Z.
119
- Open risks/questions: R.
120
- Recommended next step: N.
28
+ Implemented: ...
29
+ Changed files: ...
30
+ Validation: ...
31
+ Open risks/questions: ...