@phi-code-admin/phi-code 0.73.0 → 0.74.1

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.
package/agents/test.md CHANGED
@@ -33,6 +33,9 @@ Use implementation results to know which files were created/modified and what be
33
33
  - **Realistic assertions**: Test what matters, not trivial details
34
34
  - **Match conventions**: Use the project's test framework, directory structure, and naming patterns
35
35
  - **Clean test code**: Tests are documentation — use descriptive names that explain expected behavior
36
+ - Prefer targeted `edit` calls over full file rewrites. When a test fails, fix ONLY the failing test function, not the entire file
37
+ - Maximum 1 full file rewrite per test file. After that, use `edit` for surgical fixes
38
+ - When debugging test failures: read the error → locate the exact failing assertion → fix that specific line
36
39
 
37
40
  ## Test Writing
38
41
 
@@ -43,9 +43,10 @@ export default function memoryExtension(pi: ExtensionAPI) {
43
43
  description: "Search for content in memory using unified search (notes + ontology + vector search)",
44
44
  promptSnippet: "Search project memory (notes, ontology, vector search). ALWAYS call before answering questions about prior work, decisions, or project context.",
45
45
  promptGuidelines: [
46
- "Before answering questions about prior work, architecture, decisions, or project context: call memory_search first.",
46
+ "MANDATORY: Before starting ANY task, call memory_search with relevant keywords. This is not optional.",
47
47
  "When starting work on a topic, search memory for existing notes and learnings.",
48
48
  "After completing important work or learning something new, use memory_write to save it.",
49
+ "MANDATORY: After completing any significant work, call memory_write to save what you did and what you learned.",
49
50
  "When a command fails or produces an unexpected error, document the error and fix in memory_write (self-improvement).",
50
51
  "When the user corrects you, save the correction in memory_write so you never repeat the mistake.",
51
52
  "After a significant debugging session, write a summary of root cause and solution to memory.",
@@ -21,7 +21,6 @@ import type { ExtensionAPI } from "phi-code";
21
21
  import { writeFile, mkdir, readdir, readFile } from "node:fs/promises";
22
22
  import { join } from "node:path";
23
23
  import { existsSync, readFileSync } from "node:fs";
24
- // execFile removed — tasks now execute in-session, no subprocess
25
24
  import { homedir } from "node:os";
26
25
 
27
26
  // ─── Types ───────────────────────────────────────────────────────────────
@@ -35,22 +34,6 @@ interface TaskDef {
35
34
  subtasks?: string[];
36
35
  }
37
36
 
38
- interface TaskResult {
39
- taskIndex: number;
40
- title: string;
41
- agent: string;
42
- status: "success" | "error" | "skipped";
43
- output: string;
44
- durationMs: number;
45
- }
46
-
47
- interface AgentDef {
48
- name: string;
49
- description: string;
50
- tools: string;
51
- systemPrompt: string;
52
- }
53
-
54
37
  // ─── Extension ───────────────────────────────────────────────────────────
55
38
 
56
39
  export default function orchestratorExtension(pi: ExtensionAPI) {
@@ -64,218 +47,7 @@ export default function orchestratorExtension(pi: ExtensionAPI) {
64
47
  return new Date().toISOString().replace(/[:.]/g, "-").replace("T", "_").slice(0, 19);
65
48
  }
66
49
 
67
- // ─── Agent Discovery ─────────────────────────────────────────────
68
-
69
- function loadAgentDefs(): Map<string, AgentDef> {
70
- const agents = new Map<string, AgentDef>();
71
- const dirs = [
72
- join(process.cwd(), ".phi", "agents"),
73
- join(homedir(), ".phi", "agent", "agents"),
74
- join(__dirname, "..", "..", "..", "agents"),
75
- ];
76
-
77
- for (const dir of dirs) {
78
- if (!existsSync(dir)) continue;
79
- try {
80
- const files = require("fs").readdirSync(dir) as string[];
81
- for (const file of files) {
82
- if (!file.endsWith(".md")) continue;
83
- const name = file.replace(".md", "");
84
- if (agents.has(name)) continue;
85
-
86
- try {
87
- const content = readFileSync(join(dir, file), "utf-8");
88
- const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/);
89
- if (!fmMatch) continue;
90
-
91
- const frontmatter = fmMatch[1];
92
- const body = fmMatch[2].trim();
93
- const desc = frontmatter.match(/description:\s*(.+)/)?.[1] || "";
94
- const tools = frontmatter.match(/tools:\s*(.+)/)?.[1] || "";
95
-
96
- agents.set(name, { name, description: desc, tools, systemPrompt: body });
97
- } catch { /* skip */ }
98
- }
99
- } catch { /* skip */ }
100
- }
101
-
102
- return agents;
103
- }
104
-
105
- function resolveAgentModel(agentType: string): string | null {
106
- const routingPath = join(homedir(), ".phi", "agent", "routing.json");
107
- try {
108
- const config = JSON.parse(readFileSync(routingPath, "utf-8"));
109
- for (const [_cat, route] of Object.entries(config.routes || {})) {
110
- const r = route as any;
111
- if (r.agent === agentType) return r.preferredModel || null;
112
- }
113
- // Map agent type to route category
114
- const categoryMap: Record<string, string> = {
115
- code: "code", explore: "explore", plan: "plan",
116
- test: "test", review: "review", debug: "debug",
117
- };
118
- const category = categoryMap[agentType];
119
- if (category && config.routes?.[category]) {
120
- return config.routes[category].preferredModel || null;
121
- }
122
- return config.default?.model || null;
123
- } catch {
124
- return null;
125
- }
126
- }
127
-
128
- function findPhiBinary(): string {
129
- // Try the bundled CLI relative to extensions dir
130
- const bundledCli = join(__dirname, "..", "..", "..", "dist", "cli.js");
131
- if (existsSync(bundledCli)) return bundledCli;
132
-
133
- // Try npm global install paths
134
- const npmGlobalPaths = [
135
- join(homedir(), "AppData", "Roaming", "npm", "node_modules", "@phi-code-admin", "phi-code", "dist", "cli.js"), // Windows
136
- join(homedir(), ".npm-global", "lib", "node_modules", "@phi-code-admin", "phi-code", "dist", "cli.js"), // Linux custom
137
- "/usr/local/lib/node_modules/@phi-code-admin/phi-code/dist/cli.js", // Linux/Mac default
138
- "/usr/lib/node_modules/@phi-code-admin/phi-code/dist/cli.js", // Some Linux
139
- ];
140
- for (const p of npmGlobalPaths) {
141
- if (existsSync(p)) return p;
142
- }
143
-
144
- // Try `which phi` (Linux/Mac) or `where phi` (Windows)
145
- try {
146
- const isWin = process.platform === "win32";
147
- const cmd = isWin ? "where" : "which";
148
- const result = require("child_process").execSync(`${cmd} phi 2>${isWin ? "NUL" : "/dev/null"}`, { encoding: "utf-8" }).trim();
149
- if (result) {
150
- const firstLine = result.split("\n")[0].trim();
151
- // On Windows, `where phi` returns the .cmd shim; we need the actual JS
152
- if (isWin && firstLine.endsWith(".cmd")) {
153
- const npmPrefix = require("child_process").execSync("npm prefix -g", { encoding: "utf-8" }).trim();
154
- const jsPath = join(npmPrefix, "node_modules", "@phi-code-admin", "phi-code", "dist", "cli.js");
155
- if (existsSync(jsPath)) return jsPath;
156
- }
157
- return firstLine;
158
- }
159
- } catch { /* not in PATH */ }
160
-
161
- // Last resort: assume phi is in PATH (works with shell:true on Windows)
162
- return "phi";
163
- }
164
-
165
- // ─── Task Execution (in-session, no subprocess) ─────────────────
166
-
167
- /**
168
- * Execute a task by sending it as a user message to the current session.
169
- * The LLM handles it directly — no subprocess spawning, no cold boot.
170
- * Much faster and more reliable than spawning phi --print processes.
171
- */
172
- function executeTaskInSession(
173
- task: TaskDef,
174
- sharedContext: {
175
- projectTitle: string;
176
- projectDescription: string;
177
- specSummary: string;
178
- completedTasks: Array<{ index: number; title: string; agent: string; output: string }>;
179
- },
180
- ): { taskPrompt: string } {
181
- const agentType = task.agent || "code";
182
-
183
- // Build prompt with shared context
184
- let taskPrompt = `## 🔧 Task: ${task.title} [${agentType}]\n\n`;
185
-
186
- taskPrompt += `**Project:** ${sharedContext.projectTitle}\n\n`;
187
-
188
- if (sharedContext.specSummary) {
189
- taskPrompt += `**Spec:** ${sharedContext.specSummary}\n\n`;
190
- }
191
-
192
- // Inject results from dependency tasks
193
- const deps = task.dependencies || [];
194
- if (deps.length > 0) {
195
- const depResults = sharedContext.completedTasks.filter(ct => deps.includes(ct.index));
196
- if (depResults.length > 0) {
197
- taskPrompt += `**Previous results:**\n`;
198
- for (const dep of depResults) {
199
- const truncated = dep.output.length > 500 ? dep.output.slice(0, 500) + "..." : dep.output;
200
- taskPrompt += `- Task ${dep.index} (${dep.title}): ${truncated}\n`;
201
- }
202
- taskPrompt += "\n";
203
- }
204
- }
205
-
206
- // The actual task
207
- taskPrompt += `### What to do\n\n${task.description}\n`;
208
- if (task.subtasks && task.subtasks.length > 0) {
209
- taskPrompt += "\n**Sub-tasks:**\n" + task.subtasks.map((st, i) => `${i + 1}. ${st}`).join("\n") + "\n";
210
- }
211
- taskPrompt += `\n**Instructions:** Execute this task completely. Create/edit all necessary files. Report what you did.\n`;
212
-
213
- return { taskPrompt };
214
- }
215
-
216
- // ─── Execute All Tasks (parallel with dependency resolution) ─────
217
-
218
- async function executePlan(
219
- tasks: TaskDef[],
220
- todoFile: string,
221
- notify: (msg: string, type: "info" | "error" | "warning") => void,
222
- projectContext?: { title: string; description: string; specSummary: string },
223
- ): Promise<{ results: TaskResult[]; progressFile: string }> {
224
- const progressFile = todoFile.replace("todo-", "progress-");
225
- const progressPath = join(plansDir, progressFile);
226
- const totalTasks = tasks.length;
227
-
228
- const sharedContext = {
229
- projectTitle: projectContext?.title || "Project",
230
- projectDescription: projectContext?.description || "",
231
- specSummary: projectContext?.specSummary || "",
232
- completedTasks: [] as Array<{ index: number; title: string; agent: string; output: string }>,
233
- };
234
-
235
- notify(`🚀 Executing ${totalTasks} tasks in-session...`, "info");
236
-
237
- // Build a single comprehensive prompt with ALL tasks
238
- let megaPrompt = `# 📋 Project: ${sharedContext.projectTitle}\n\n`;
239
- megaPrompt += `${sharedContext.projectDescription}\n\n`;
240
- if (sharedContext.specSummary) {
241
- megaPrompt += `## Spec\n${sharedContext.specSummary}\n\n`;
242
- }
243
- megaPrompt += `## Tasks (execute ALL in order)\n\n`;
244
-
245
- const results: TaskResult[] = [];
246
-
247
- for (let i = 0; i < tasks.length; i++) {
248
- const task = tasks[i];
249
- const { taskPrompt } = executeTaskInSession(task, sharedContext);
250
- megaPrompt += `---\n\n${taskPrompt}\n\n`;
251
- results.push({
252
- taskIndex: i + 1, title: task.title,
253
- agent: task.agent || "code", status: "success",
254
- output: "(in-session)", durationMs: 0,
255
- });
256
- }
257
-
258
- megaPrompt += `---\n\n## ⚠️ Instructions\n\n`;
259
- megaPrompt += `Execute ALL ${totalTasks} tasks above **sequentially**. For each task:\n`;
260
- megaPrompt += `1. Create/edit the required files using your tools\n`;
261
- megaPrompt += `2. Report what you did briefly\n`;
262
- megaPrompt += `3. Move to the next task\n\n`;
263
- megaPrompt += `Do NOT skip any task. Complete the entire project.\n`;
264
-
265
- // Write progress file
266
- let progress = `# Progress: ${todoFile}\n\n`;
267
- progress += `**Started:** ${new Date().toLocaleString()}\n`;
268
- progress += `**Tasks:** ${totalTasks} | **Mode:** in-session\n\n`;
269
- for (const r of results) {
270
- progress += `- Task ${r.taskIndex}: ${r.title} [${r.agent}]\n`;
271
- }
272
- await writeFile(progressPath, progress, "utf-8");
273
-
274
- // Return the mega-prompt as tool result — LLM sees it and executes
275
- return { results, progressFile, megaPrompt };
276
- }
277
-
278
- // ─── Generate Plan Files ─────────────────────────────────────────
50
+ // ─── Plan File Generators ────────────────────────────────────────
279
51
 
280
52
  function generateSpec(p: {
281
53
  title: string; description: string; goals: string[]; requirements: string[];
@@ -331,20 +103,21 @@ export default function orchestratorExtension(pi: ExtensionAPI) {
331
103
  return todo;
332
104
  }
333
105
 
334
- // ─── Orchestrate Tool (plan + auto-execute) ──────────────────────
106
+ // ─── Orchestrate Tool Structured planning with prompt-architect pattern ───
335
107
 
336
108
  pi.registerTool({
337
109
  name: "orchestrate",
338
110
  label: "Project Orchestrator",
339
- description: "Create a project plan AND automatically execute all tasks with sub-agents in parallel. Each agent gets its own isolated context, model, and system prompt. Tasks without dependencies run simultaneously.",
340
- promptSnippet: "Plan + execute projects in parallel waves. Each sub-agent gets isolated context + model. Use prompt-architect patterns for structured task descriptions.",
111
+ description: "Create a structured project plan with spec, todo, and task breakdown. Forces the model to decompose the project into goals, requirements, architecture, constraints, and success criteria before execution.",
112
+ promptSnippet: "Plan + structure projects using the prompt-architect pattern. Each task gets [CONTEXT] [TASK] [FORMAT] [CONSTRAINTS].",
341
113
  promptGuidelines: [
342
- "When asked to plan or build a project: analyze the request thoroughly, then call the orchestrate tool. It plans AND executes automatically.",
343
- "CRITICAL: Each task description must be SELF-CONTAINED. The sub-agent has NO access to this conversation. It receives: (1) project context (title, description, spec summary) automatically, (2) outputs from its dependency tasks automatically, (3) your task description. So include specific details: file paths, expected behavior, code patterns, success criteria. Don't repeat the project description — that's injected automatically.",
114
+ // NOTE: The old guideline "When asked to plan or build a project, call the orchestrate tool"
115
+ // was REMOVED because it hijacked the /plan command flow. The orchestrate tool is now
116
+ // only called explicitly or when the model decides structured planning is needed outside of /plan.
117
+ "IMPORTANT: Do NOT call orchestrate during /plan orchestration phases. The /plan command handles its own workflow.",
344
118
  "Structure each task description using the prompt-architect pattern: [CONTEXT] what exists and why → [TASK] what to do specifically → [FORMAT] expected output → [CONSTRAINTS] rules and limitations.",
345
- "Assign agent types strategically: 'explore' (read-only analysis, codebase understanding), 'plan' (architecture, design decisions), 'code' (implementation, file creation/modification), 'test' (write + run tests, validate behavior), 'review' (security audit, quality check, read-only).",
346
- "Set dependencies to maximize parallelism: tasks without dependencies run simultaneously in the same wave. Only add dependencies when a task truly needs another task's output.",
347
- "Order tasks logically: explore → plan → code → test → review. But allow independent tasks at each stage to run in parallel.",
119
+ "Assign agent types strategically: 'explore' (read-only analysis), 'plan' (architecture), 'code' (implementation), 'test' (write+run tests), 'review' (quality audit).",
120
+ "Set dependencies to maximize parallelism: tasks without dependencies run simultaneously.",
348
121
  "Set priority=high for critical-path tasks, medium for standard work, low for nice-to-haves.",
349
122
  ],
350
123
  parameters: Type.Object({
@@ -356,22 +129,29 @@ export default function orchestratorExtension(pi: ExtensionAPI) {
356
129
  tasks: Type.Array(
357
130
  Type.Object({
358
131
  title: Type.String({ description: "Clear, action-oriented task title" }),
359
- description: Type.String({ description: "SELF-CONTAINED task description. Include ALL context the sub-agent needs: file paths, expected behavior, code patterns, conventions. The agent has NO shared history." }),
360
- agent: Type.Optional(Type.String({ description: "Agent type: explore (read-only analysis), plan (architecture), code (implementation), test (write+run tests), review (quality audit)" })),
361
- priority: Type.Optional(Type.String({ description: "high (critical path), medium (standard), low (nice-to-have)" })),
362
- dependencies: Type.Optional(Type.Array(Type.Number(), { description: "Task numbers this depends on (1-indexed). Only add when truly needed — fewer dependencies = more parallelism" })),
132
+ description: Type.String({ description: "SELF-CONTAINED task description. Include ALL context the sub-agent needs." }),
133
+ agent: Type.Optional(Type.String({ description: "Agent type: explore, plan, code, test, review" })),
134
+ priority: Type.Optional(Type.String({ description: "high, medium, low" })),
135
+ dependencies: Type.Optional(Type.Array(Type.Number(), { description: "Task numbers this depends on (1-indexed)" })),
363
136
  subtasks: Type.Optional(Type.Array(Type.String(), { description: "Specific sub-steps within this task" })),
364
137
  }),
365
- { description: "Ordered list of tasks. Independent tasks run in parallel. Dependent tasks wait for prerequisites." }
138
+ { description: "Ordered list of tasks" }
366
139
  ),
367
- constraints: Type.Optional(Type.Union([Type.Array(Type.String()), Type.String()], { description: "Hard constraints: frameworks, patterns, rules, things to avoid" })),
368
- successCriteria: Type.Optional(Type.Union([Type.Array(Type.String()), Type.String()], { description: "How to verify the project is complete and correct" })),
140
+ constraints: Type.Optional(Type.Union([Type.Array(Type.String()), Type.String()], { description: "Hard constraints: things to avoid, rules" })),
141
+ successCriteria: Type.Optional(Type.Union([Type.Array(Type.String()), Type.String()], { description: "How to verify the project is complete" })),
369
142
  }),
370
143
 
371
- async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
144
+ async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
145
+ // Block if /plan orchestration is active — prevent hijacking
146
+ if (orchestrationActive) {
147
+ return {
148
+ content: [{ type: "text", text: "⚠️ Orchestration is already active via /plan. Do NOT call orchestrate during /plan phases. Follow the phase instructions instead." }],
149
+ };
150
+ }
151
+
372
152
  const raw = params as any;
373
153
 
374
- // Normalize string fields to arrays (some models send strings instead of arrays)
154
+ // Normalize string fields to arrays
375
155
  const toArray = (v: any): string[] => {
376
156
  if (!v) return [];
377
157
  if (Array.isArray(v)) return v;
@@ -396,48 +176,22 @@ export default function orchestratorExtension(pi: ExtensionAPI) {
396
176
  const specFile = `spec-${ts}.md`;
397
177
  const todoFile = `todo-${ts}.md`;
398
178
 
399
- // Generate and write plan files
179
+ // Generate and write structured plan files
400
180
  const spec = generateSpec(p);
401
181
  const todo = generateTodo(p.title, p.tasks);
402
182
  await writeFile(join(plansDir, specFile), spec, "utf-8");
403
183
  await writeFile(join(plansDir, todoFile), todo, "utf-8");
404
184
 
405
- // Notify plan created
406
- const notify = (msg: string, type: "info" | "error" | "warning") => {
407
- // Use onUpdate for streaming progress to the user
408
- if (_onUpdate) {
409
- _onUpdate({ content: [{ type: "text", text: msg }] });
410
- }
411
- };
412
-
413
- notify(`📋 Plan created: **${p.title}** (${p.tasks.length} tasks)\nNow executing with sub-agents...`, "info");
185
+ const summary = `📋 **Project "${p.title}" — Structured plan created!**\n\n` +
186
+ `**Spec:** \`${specFile}\` | **Todo:** \`${todoFile}\`\n\n` +
187
+ `**Goals:** ${p.goals.length} | **Requirements:** ${p.requirements.length} | **Tasks:** ${p.tasks.length}\n\n` +
188
+ `The spec and todo files are ready in \`.phi/plans/\`. ` +
189
+ `Use \`/plan ${p.description.slice(0, 100)}\` to execute with the 5-phase orchestrator, ` +
190
+ `or work through the tasks manually.`;
414
191
 
415
- // Auto-execute all tasks
416
- // Build spec summary for shared context
417
- const specSummary = [
418
- `Goals: ${p.goals.join("; ")}`,
419
- `Requirements: ${p.requirements.join("; ")}`,
420
- p.architecture?.length ? `Architecture: ${p.architecture.join("; ")}` : "",
421
- p.constraints?.length ? `Constraints: ${p.constraints.join("; ")}` : "",
422
- ].filter(Boolean).join("\n");
423
-
424
- const { results, progressFile, megaPrompt } = await executePlan(
425
- p.tasks, todoFile, notify,
426
- { title: p.title, description: p.description, specSummary },
427
- );
428
-
429
- const header = `**📋 Project "${p.title}" — ${p.tasks.length} tasks planned!**\n` +
430
- `Plan: \`${specFile}\`, \`${todoFile}\` | Progress: \`${progressFile}\`\n\n` +
431
- `---\n\n`;
432
-
433
- // Return the mega-prompt as tool result
434
- // The LLM sees this and executes all tasks in its current turn
435
192
  return {
436
- content: [{ type: "text", text: header + megaPrompt }],
437
- details: {
438
- specFile, todoFile, progressFile,
439
- taskCount: p.tasks.length,
440
- },
193
+ content: [{ type: "text", text: summary }],
194
+ details: { specFile, todoFile, taskCount: p.tasks.length },
441
195
  };
442
196
  } catch (error) {
443
197
  return {
@@ -1089,61 +843,12 @@ Tag the note with relevant keywords for vector search.
1089
843
  // ─── /run Command — Re-execute existing plan ─────────────────────
1090
844
 
1091
845
  pi.registerCommand("run", {
1092
- description: "Re-execute an existing plan's tasks with sub-agents",
1093
- handler: async (args, ctx) => {
1094
- if (!existsSync(plansDir)) {
1095
- ctx.ui.notify("No plans found. Use `/plan <description>` to create and execute one.", "warning");
1096
- return;
1097
- }
1098
-
1099
- const files = (await readdir(plansDir)).sort().reverse();
1100
- const todoFiles = files.filter(f => f.startsWith("todo-") && f.endsWith(".md"));
1101
-
1102
- if (todoFiles.length === 0) {
1103
- ctx.ui.notify("No todo files found. Use `/plan <description>` first.", "warning");
1104
- return;
1105
- }
1106
-
1107
- const todoFile = todoFiles[0];
1108
- const todoContent = await readFile(join(plansDir, todoFile), "utf-8");
1109
-
1110
- // Parse tasks
1111
- const tasks: TaskDef[] = [];
1112
- const sections = todoContent.split(/## Task \d+:/);
1113
- for (let i = 1; i < sections.length; i++) {
1114
- const section = sections[i];
1115
- const titleMatch = section.match(/^(.+?)(?:\s*🔴|\s*🟡|\s*🟢)/);
1116
- const agentMatch = section.match(/\[(\w+)\]/);
1117
- const descMatch = section.match(/- \[ \] (.+)/);
1118
- const subtasks: string[] = [];
1119
- const stMatches = section.matchAll(/ - \[ \] (.+)/g);
1120
- for (const m of stMatches) subtasks.push(m[1]);
1121
-
1122
- if (titleMatch && descMatch) {
1123
- tasks.push({
1124
- title: titleMatch[1].trim(),
1125
- agent: agentMatch?.[1] || "code",
1126
- description: descMatch[1].trim(),
1127
- subtasks: subtasks.length > 0 ? subtasks : undefined,
1128
- });
1129
- }
1130
- }
1131
-
1132
- if (tasks.length === 0) {
1133
- ctx.ui.notify("Could not parse tasks from todo file.", "error");
1134
- return;
1135
- }
1136
-
1137
- const confirmed = await ctx.ui.confirm(
1138
- "Re-execute Plan",
1139
- `${tasks.length} tasks found in \`${todoFile}\`.\nEach will spawn an isolated sub-agent.\n\nProceed?`
846
+ description: "Re-execute an existing plan (deprecated use /plan instead)",
847
+ handler: async (_args, ctx) => {
848
+ ctx.ui.notify(
849
+ "⚠️ `/run` is deprecated. Use `/plan <description>` to create and execute a new plan with the 5-phase orchestrator.",
850
+ "warning",
1140
851
  );
1141
- if (!confirmed) {
1142
- ctx.ui.notify("Cancelled.", "info");
1143
- return;
1144
- }
1145
-
1146
- await executePlan(tasks, todoFile, (msg, type) => ctx.ui.notify(msg, type));
1147
852
  },
1148
853
  });
1149
854
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phi-code-admin/phi-code",
3
- "version": "0.73.0",
3
+ "version": "0.74.1",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {