@selesai/code 0.5.12 → 0.5.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +186 -0
  2. package/dist/core/system-prompt.d.ts.map +1 -1
  3. package/dist/core/system-prompt.js +1 -1
  4. package/dist/core/system-prompt.js.map +1 -1
  5. package/dist/extensions/caveman/caveman-instructions.cjs +6 -34
  6. package/dist/extensions/caveman/test/helpers.test.js +7 -13
  7. package/dist/extensions/package.json +4 -3
  8. package/dist/extensions/pi-powerline-footer/README.md +1 -1
  9. package/dist/extensions/pi-powerline-footer/guide.ts +227 -0
  10. package/dist/extensions/pi-powerline-footer/index.ts +88 -55
  11. package/dist/extensions/pi-powerline-footer/tests/editor-responsiveness.test.ts +0 -78
  12. package/dist/extensions/pi-powerline-footer/tests/guide.test.ts +102 -0
  13. package/dist/extensions/pi-powerline-footer/welcome.ts +65 -30
  14. package/dist/extensions/ponytail/index.js +1 -1
  15. package/dist/extensions/ponytail/ponytail-instructions.cjs +15 -1
  16. package/dist/extensions/ponytail/test/extension.test.js +20 -4
  17. package/dist/extensions/ponytail/test/helpers.test.js +32 -0
  18. package/dist/extensions/workflow/adapter.ts +0 -19
  19. package/dist/skills/caveman/SKILL.md +1 -0
  20. package/dist/skills/handoff/SKILL.md +1 -0
  21. package/dist/skills/handoff-text/SKILL.md +1 -0
  22. package/dist/skills/implanger/SKILL.md +1 -0
  23. package/dist/skills/improve-codebase/SKILL.md +1 -0
  24. package/dist/skills/planger/SKILL.md +1 -0
  25. package/dist/skills/ponytail/SKILL.md +1 -0
  26. package/dist/skills/ponytail-audit/SKILL.md +1 -0
  27. package/dist/skills/ponytail-debt/SKILL.md +1 -0
  28. package/dist/skills/ponytail-gain/SKILL.md +1 -0
  29. package/dist/skills/ponytail-help/SKILL.md +1 -0
  30. package/dist/skills/ponytail-review/SKILL.md +1 -0
  31. package/dist/skills/workflow-creation/SKILL.md +1 -0
  32. package/package.json +23 -2
  33. package/dist/agents/architect.md +0 -217
  34. package/dist/agents/builder.md +0 -120
  35. package/dist/agents/commentator.md +0 -130
  36. package/dist/agents/explorer.md +0 -51
  37. package/dist/agents/recapper.md +0 -26
  38. package/dist/extensions/gitignore-guard.ts +0 -132
  39. package/dist/extensions/hooks/claude-codex-hooks.json +0 -44
  40. package/dist/extensions/hooks/copilot-hooks.json +0 -21
  41. package/dist/extensions/hooks/ponytail-activate.js +0 -91
  42. package/dist/extensions/hooks/ponytail-config.js +0 -122
  43. package/dist/extensions/hooks/ponytail-instructions.js +0 -94
  44. package/dist/extensions/hooks/ponytail-mode-tracker.js +0 -55
  45. package/dist/extensions/hooks/ponytail-runtime.js +0 -68
  46. package/dist/extensions/hooks/ponytail-statusline.ps1 +0 -21
  47. package/dist/extensions/hooks/ponytail-statusline.sh +0 -12
  48. package/dist/extensions/hooks/ponytail-subagent.js +0 -22
  49. package/dist/extensions/pi-extension/index.js +0 -189
  50. package/dist/extensions/pi-extension/package.json +0 -8
  51. package/dist/extensions/pi-extension/test/extension.test.js +0 -167
  52. package/dist/extensions/pi-extension/test/helpers.test.js +0 -92
  53. package/dist/extensions/pi-powerline-footer/welcome-dismiss.ts +0 -34
  54. package/dist/extensions/pi-subagents/agents/context-builder.md +0 -46
  55. package/dist/extensions/pi-subagents/agents/delegate.md +0 -12
  56. package/dist/extensions/pi-subagents/agents/oracle.md +0 -73
  57. package/dist/extensions/pi-subagents/agents/planner.md +0 -55
  58. package/dist/extensions/pi-subagents/agents/reviewer.md +0 -79
  59. package/dist/extensions/pi-subagents/agents/scout.md +0 -50
  60. package/dist/extensions/pi-subagents/agents/worker.md +0 -55
  61. package/dist/extensions/pi-subagents/src/runs/shared/spawn-timing.ts +0 -46
  62. package/dist/extensions/pi-subagents/test/unit/spawn-timing.test.ts +0 -45
  63. package/dist/extensions/pi-subagents/tsconfig.runner.json +0 -17
  64. package/dist/extensions/ponytail-pi-extension/index.js +0 -189
  65. package/dist/extensions/ponytail-pi-extension/package.json +0 -8
  66. package/dist/extensions/ponytail-pi-extension/test/extension.test.js +0 -167
  67. package/dist/extensions/ponytail-pi-extension/test/helpers.test.js +0 -92
  68. package/dist/extensions/prototype.ts +0 -713
  69. package/dist/extensions/question.ts +0 -350
  70. package/dist/extensions/quick.ts +0 -630
  71. package/dist/extensions/tps-tracker.ts +0 -280
  72. package/dist/extensions/workflow/task-validators.ts +0 -69
  73. package/dist/skills/selesai-default/SKILL.md +0 -16
@@ -3,8 +3,9 @@ import { join, basename } from "node:path";
3
3
  import { homedir as osHomedir } from "node:os";
4
4
  import { CONFIG_DIR_NAME, getAgentDir, getSettingsPath } from "@selesai/code";
5
5
  import type { Component } from "@earendil-works/pi-tui";
6
- import { truncateToWidth as tuiTruncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
6
+ import { truncateToWidth as tuiTruncateToWidth, visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui";
7
7
  import { ansi, fgOnly, getFgAnsiCode } from "./colors.ts";
8
+ import { GUIDE_COMPACT_LINES, GUIDE_DISMISS_HINT, getGuideFeatureLines, type GuideFeature, type GuideMode } from "./guide.ts";
8
9
 
9
10
  export interface RecentSession {
10
11
  name: string;
@@ -82,11 +83,20 @@ function fitToWidth(str: string, width: number): string {
82
83
  return str + " ".repeat(width - visLen);
83
84
  }
84
85
 
86
+ function wrapLines(lines: string[], width: number): string[] {
87
+ const continuation = " ";
88
+ const contentWidth = Math.max(1, width - continuation.length);
89
+ return lines.flatMap((line) => wrapTextWithAnsi(line, contentWidth)
90
+ .map((wrapped, index) => index === 0 ? wrapped : continuation + wrapped));
91
+ }
92
+
85
93
  interface WelcomeData {
86
94
  modelName: string;
87
95
  providerName: string;
88
96
  recentSessions: RecentSession[];
89
97
  loadedCounts: LoadedCounts;
98
+ guideMode: GuideMode;
99
+ newFeatures: GuideFeature[];
90
100
  }
91
101
 
92
102
  function buildLeftColumn(data: WelcomeData, colWidth: number): string[] {
@@ -107,6 +117,27 @@ function buildRightColumn(data: WelcomeData, colWidth: number): string[] {
107
117
  const hChar = "─";
108
118
  const separator = ` ${dim(hChar.repeat(colWidth - 2))}`;
109
119
 
120
+ const guideLines = data.guideMode === "compact"
121
+ ? [
122
+ ` ${bold(fgOnly("accent", "Guide"))}`,
123
+ ...(data.newFeatures.length > 0
124
+ ? [` ${bold(fgOnly("model", `New: ${data.newFeatures.slice(0, 2).map((feature) => feature.title).join(" · ")}`))}`]
125
+ : []),
126
+ ...GUIDE_COMPACT_LINES.map((line) => ` ${dim(line)}`),
127
+ ]
128
+ : [
129
+ ` ${bold(fgOnly("accent", "Selesai guide"))}`,
130
+ ...(data.newFeatures.length > 0
131
+ ? [
132
+ ` ${bold(fgOnly("model", "New since your last guide"))}`,
133
+ ...data.newFeatures.slice(0, 3).map((feature) => ` ${dim("• ")}${feature.title}`),
134
+ ]
135
+ : []),
136
+ ...getGuideFeatureLines().map((line) => line.kind === "section"
137
+ ? ` ${bold(fgOnly("accent", line.text))}`
138
+ : ` ${dim("• ")}${line.feature.title}: ${dim(line.feature.example)}`),
139
+ ];
140
+
110
141
  // Session lines
111
142
  const sessionLines: string[] = [];
112
143
  if (data.recentSessions.length === 0) {
@@ -141,17 +172,23 @@ function buildRightColumn(data: WelcomeData, colWidth: number): string[] {
141
172
  countLines.push(` ${dim("No extensions loaded")}`);
142
173
  }
143
174
 
175
+ const dashboardLines = data.guideMode === "full"
176
+ ? []
177
+ : [
178
+ separator,
179
+ ` ${bold(fgOnly("accent", "Loaded"))}`,
180
+ ...countLines,
181
+ separator,
182
+ ` ${bold(fgOnly("accent", "Recent sessions"))}`,
183
+ ...sessionLines,
184
+ ];
185
+
144
186
  return [
145
- ` ${bold(fgOnly("accent", "Tips"))}`,
146
- ` ${dim("/")} for commands`,
147
- ` ${dim("!")} to run bash`,
187
+ ` ${bold(fgOnly("accent", "Tips"))}: ${dim("/")} commands · ${dim("/settings")} configure`,
148
188
  ` ${dim("Shift+Tab")} cycle thinking`,
149
189
  separator,
150
- ` ${bold(fgOnly("accent", "Loaded"))}`,
151
- ...countLines,
152
- separator,
153
- ` ${bold(fgOnly("accent", "Recent sessions"))}`,
154
- ...sessionLines,
190
+ ...guideLines,
191
+ ...dashboardLines,
155
192
  "",
156
193
  ];
157
194
  }
@@ -170,8 +207,8 @@ function renderWelcomeBox(
170
207
  }
171
208
 
172
209
  const minWidth = 76;
173
- const maxWidth = 96;
174
- // Clamp to termWidth to prevent crash on narrow terminals
210
+ const maxWidth = data.guideMode === "full" ? 132 : 96;
211
+ // Clamp to termWidth to prevent crash on narrow terminals.
175
212
  const boxWidth = Math.min(termWidth, Math.max(minWidth, Math.min(termWidth - 2, maxWidth)));
176
213
  const leftCol = 26;
177
214
  const rightCol = Math.max(1, boxWidth - leftCol - 3); // Ensure rightCol is at least 1
@@ -184,7 +221,7 @@ function renderWelcomeBox(
184
221
  const br = dim("╯");
185
222
 
186
223
  const leftLines = buildLeftColumn(data, leftCol);
187
- const rightLines = buildRightColumn(data, rightCol);
224
+ const rightLines = wrapLines(buildRightColumn(data, rightCol), rightCol);
188
225
 
189
226
  const lines: string[] = [];
190
227
 
@@ -221,19 +258,16 @@ function renderWelcomeBox(
221
258
  */
222
259
  export class WelcomeComponent implements Component {
223
260
  private data: WelcomeData;
224
- private countdown: number = 30;
225
261
 
226
262
  constructor(
227
263
  modelName: string,
228
264
  providerName: string,
229
265
  recentSessions: RecentSession[] = [],
230
266
  loadedCounts: LoadedCounts = { contextFiles: 0, extensions: 0, skills: 0, promptTemplates: 0 },
267
+ guideMode: GuideMode = "full",
268
+ newFeatures: GuideFeature[] = [],
231
269
  ) {
232
- this.data = { modelName, providerName, recentSessions, loadedCounts };
233
- }
234
-
235
- setCountdown(seconds: number): void {
236
- this.countdown = seconds;
270
+ this.data = { modelName, providerName, recentSessions, loadedCounts, guideMode, newFeatures };
237
271
  }
238
272
 
239
273
  invalidate(): void {}
@@ -246,20 +280,20 @@ export class WelcomeComponent implements Component {
246
280
  }
247
281
 
248
282
  const minWidth = 76;
249
- const maxWidth = 96;
250
- // Clamp to termWidth to prevent crash on narrow terminals
283
+ const maxWidth = 132;
284
+ // Clamp to termWidth to prevent crash on narrow terminals.
251
285
  const boxWidth = Math.min(termWidth, Math.max(minWidth, Math.min(termWidth - 2, maxWidth)));
252
286
 
253
- // Bottom line with countdown
254
- const countdownText = ` Press any key to continue (${this.countdown}s) `;
255
- const countdownStyled = dim(countdownText);
287
+ // The guide is intentionally blocking: no timer or implicit dismissal.
288
+ const promptText = ` ${GUIDE_DISMISS_HINT} `;
289
+ const promptStyled = dim(promptText);
256
290
  const bottomContentWidth = boxWidth - 2;
257
- const countdownVisLen = visibleWidth(countdownText);
258
- const leftPad = Math.floor((bottomContentWidth - countdownVisLen) / 2);
259
- const rightPad = bottomContentWidth - countdownVisLen - leftPad;
291
+ const promptVisLen = visibleWidth(promptText);
292
+ const leftPad = Math.floor((bottomContentWidth - promptVisLen) / 2);
293
+ const rightPad = bottomContentWidth - promptVisLen - leftPad;
260
294
  const hChar = "─";
261
295
  const bottomLine = dim(hChar.repeat(Math.max(0, leftPad))) +
262
- countdownStyled +
296
+ promptStyled +
263
297
  dim(hChar.repeat(Math.max(0, rightPad)));
264
298
 
265
299
  return renderWelcomeBox(this.data, termWidth, bottomLine);
@@ -267,8 +301,7 @@ export class WelcomeComponent implements Component {
267
301
  }
268
302
 
269
303
  /**
270
- * Welcome header - same layout as overlay but persistent (no countdown).
271
- * Used when quietStartup: true.
304
+ * Compact guide header used when the user selects `/guide compact`.
272
305
  */
273
306
  export class WelcomeHeader implements Component {
274
307
  private data: WelcomeData;
@@ -278,8 +311,10 @@ export class WelcomeHeader implements Component {
278
311
  providerName: string,
279
312
  recentSessions: RecentSession[] = [],
280
313
  loadedCounts: LoadedCounts = { contextFiles: 0, extensions: 0, skills: 0, promptTemplates: 0 },
314
+ guideMode: GuideMode = "compact",
315
+ newFeatures: GuideFeature[] = [],
281
316
  ) {
282
- this.data = { modelName, providerName, recentSessions, loadedCounts };
317
+ this.data = { modelName, providerName, recentSessions, loadedCounts, guideMode, newFeatures };
283
318
  }
284
319
 
285
320
  invalidate(): void {}
@@ -184,6 +184,6 @@ export default function ponytailExtension(pi) {
184
184
 
185
185
  pi.on("before_agent_start", async (event) => {
186
186
  if (!currentMode || currentMode === "off") return;
187
- return { systemPrompt: `${event.systemPrompt}\n\n${getPonytailInstructions(currentMode)}` };
187
+ return { systemPrompt: `${event.systemPrompt}\n\n${getPonytailInstructions(currentMode, { compact: true })}` };
188
188
  });
189
189
  }
@@ -7,6 +7,11 @@ const { DEFAULT_MODE, normalizeMode, normalizePersistedMode } = require('./ponyt
7
7
 
8
8
  const INDEPENDENT_MODES = new Set(['review']);
9
9
  const SKILL_PATH = path.join(__dirname, '..', '..', 'skills', 'ponytail', 'SKILL.md');
10
+ const COMPACT_MODE_RULES = {
11
+ lite: 'Build the ask; name a lazier alternative.',
12
+ full: 'Enforce ladder; shortest diff.',
13
+ ultra: 'YAGNI first; delete; challenge the rest.',
14
+ };
10
15
 
11
16
  function filterSkillBodyForMode(body, mode) {
12
17
  const effectiveMode = normalizeMode(mode) || DEFAULT_MODE;
@@ -70,7 +75,15 @@ function getFallbackInstructions(mode) {
70
75
  'Ponytail governs what you build, not how you talk. "stop ponytail" or "normal mode": revert. Level persists until changed or session end.';
71
76
  }
72
77
 
73
- function getPonytailInstructions(mode) {
78
+ function getCompactInstructions(mode) {
79
+ return 'PONYTAIL ' + mode.toUpperCase() + ': persistent every response; off only "stop ponytail"/"normal mode". ' +
80
+ 'Trace first. Ladder: YAGNI -> reuse -> stdlib/native -> installed deps -> minimum diff. ' +
81
+ 'Fix root cause, not caller symptom. No unrequested abstractions/deps/boilerplate; delete first. ' +
82
+ 'Preserve validation, data-loss handling, security, accessibility, explicit asks. ' +
83
+ 'Non-trivial logic: one runnable check. Code first; <=3 lines. ' + COMPACT_MODE_RULES[mode];
84
+ }
85
+
86
+ function getPonytailInstructions(mode, options) {
74
87
  const configuredMode = normalizePersistedMode(mode) || DEFAULT_MODE;
75
88
 
76
89
  if (INDEPENDENT_MODES.has(configuredMode)) {
@@ -78,6 +91,7 @@ function getPonytailInstructions(mode) {
78
91
  }
79
92
 
80
93
  const effectiveMode = normalizeMode(configuredMode) || DEFAULT_MODE;
94
+ if (options?.compact === true) return getCompactInstructions(effectiveMode);
81
95
 
82
96
  try {
83
97
  return 'PONYTAIL MODE ACTIVE — level: ' + effectiveMode + '\n\n' +
@@ -73,8 +73,8 @@ test("/ponytail updates session mode and injects instructions", async () => with
73
73
  });
74
74
 
75
75
  const result = await events.get("before_agent_start")({ systemPrompt: "BASE" }, ctx);
76
- assert.ok(result.systemPrompt.includes("PONYTAIL MODE ACTIVE"));
77
- assert.ok(result.systemPrompt.includes("ultra"));
76
+ assert.match(result.systemPrompt, /^BASE\n\nPONYTAIL ULTRA:/);
77
+ assert.ok(result.systemPrompt.length - "BASE\n\n".length <= 450);
78
78
  }));
79
79
 
80
80
  test("session_start restores latest persisted mode", async () => withTempConfig(async () => {
@@ -90,7 +90,23 @@ test("session_start restores latest persisted mode", async () => withTempConfig(
90
90
  await events.get("session_start")({ reason: "resume" }, ctx);
91
91
  const result = await events.get("before_agent_start")({ systemPrompt: "BASE" }, ctx);
92
92
 
93
- assert.ok(result.systemPrompt.includes("lite"));
93
+ assert.match(result.systemPrompt, /PONYTAIL LITE:/);
94
+ }));
95
+
96
+ test("review mode retains its independent skill prompt", async () => withTempConfig(async () => {
97
+ const { events } = createPiHarness();
98
+ const ctx = createCommandContext({
99
+ sessionManager: {
100
+ getEntries: () => [
101
+ { type: "custom", customType: "ponytail-mode", data: { mode: "review" } },
102
+ ],
103
+ },
104
+ });
105
+
106
+ await events.get("session_start")({ reason: "resume" }, ctx);
107
+ const result = await events.get("before_agent_start")({ systemPrompt: "BASE" }, ctx);
108
+
109
+ assert.equal(result.systemPrompt, "BASE\n\nPONYTAIL MODE ACTIVE — level: review. Behavior defined by /ponytail-review skill.");
94
110
  }));
95
111
 
96
112
  test("skill alias commands delegate to Pi skill commands", async () => {
@@ -133,7 +149,7 @@ test("a request mentioning normal mode stays active", async () => withTempConfig
133
149
  await events.get("input")({ text: "add a normal mode toggle next to dark mode", source: "interactive" }, ctx);
134
150
 
135
151
  const result = await events.get("before_agent_start")({ systemPrompt: "BASE" }, ctx);
136
- assert.match(result.systemPrompt, /PONYTAIL MODE ACTIVE/);
152
+ assert.match(result.systemPrompt, /PONYTAIL ULTRA:/);
137
153
  }));
138
154
 
139
155
  test("status bar renders the mode and flips active on agent_start", async () => withTempConfig(async () => {
@@ -2,8 +2,12 @@ import assert from "node:assert/strict";
2
2
  import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
+ import { createRequire } from "node:module";
5
6
  import test from "node:test";
6
7
 
8
+ const require = createRequire(import.meta.url);
9
+ const { getPonytailInstructions } = require("../ponytail-instructions.cjs");
10
+
7
11
  import {
8
12
  filterSkillBodyForMode,
9
13
  parsePonytailCommand,
@@ -74,6 +78,34 @@ test("filterSkillBodyForMode keeps only requested intensity examples and rows",
74
78
  assert.ok(filtered.includes("Other line"));
75
79
  });
76
80
 
81
+ test("compact Ponytail instructions retain core rules and mode distinctions", () => {
82
+ const compact = Object.fromEntries(
83
+ ["lite", "full", "ultra"].map((mode) => [mode, getPonytailInstructions(mode, { compact: true })]),
84
+ );
85
+
86
+ for (const [mode, instructions] of Object.entries(compact)) {
87
+ assert.match(instructions, new RegExp(`^PONYTAIL ${mode.toUpperCase()}:`));
88
+ assert.ok(instructions.length >= 300 && instructions.length <= 450, `${mode}: ${instructions.length} characters`);
89
+ for (const phrase of ["stop ponytail", "Trace first", "root cause", "validation", "data-loss", "security", "accessibility", "runnable check"]) {
90
+ assert.ok(instructions.includes(phrase), `${mode} lacks ${phrase}`);
91
+ }
92
+ }
93
+
94
+ assert.match(compact.lite, /Build the ask; name a lazier alternative/);
95
+ assert.match(compact.full, /Enforce ladder; shortest diff/);
96
+ assert.match(compact.ultra, /YAGNI first; delete; challenge the rest/);
97
+
98
+ const fullSkill = getPonytailInstructions("full");
99
+ assert.match(fullSkill, /## The ladder/);
100
+ assert.ok(fullSkill.length > compact.full.length);
101
+ });
102
+
103
+ test("review instructions remain independent in compact mode", () => {
104
+ const expected = "PONYTAIL MODE ACTIVE — level: review. Behavior defined by /ponytail-review skill.";
105
+ assert.equal(getPonytailInstructions("review"), expected);
106
+ assert.equal(getPonytailInstructions("review", { compact: true }), expected);
107
+ });
108
+
77
109
  test("filterSkillBodyForMode keeps rule bullets that contain a colon", () => {
78
110
  // Regression: rule bullets outside the Intensity section (e.g. the
79
111
  // "No unrequested abstractions:" rule or the `ponytail:` comment convention)
@@ -472,11 +472,6 @@ function registerSharedArtifactWriter(pi: ExtensionAPI): void {
472
472
  name: WORKFLOW_ARTIFACT_TOOL,
473
473
  label: "Write Workflow Artifact",
474
474
  description: "Write the current workflow phase artifact. The workflow enforces the destination path; provide content only.",
475
- promptSnippet: `${WORKFLOW_ARTIFACT_TOOL}(content) - write the active workflow artifact; path is chosen by the workflow, not the agent.`,
476
- promptGuidelines: [
477
- `During any workflow, use ${WORKFLOW_ARTIFACT_TOOL} instead of write/edit for workflow artifacts.`,
478
- "Provide artifact content only; do not provide a path.",
479
- ],
480
475
  parameters: Type.Object({
481
476
  content: Type.String({ description: "Artifact markdown/text content to save." }),
482
477
  }),
@@ -571,11 +566,6 @@ export function createWorkflowExtension(
571
566
  name: start,
572
567
  label: options.toolLabels.start,
573
568
  description: `Start the ${mode} workflow for the given goal. Sets up ${config.phases[0]} as the first phase and returns its prompt. Do not call if a workflow is already active.`,
574
- promptSnippet: `${start}(goal) - start the ${mode} workflow; goal is what the user wants to build.`,
575
- promptGuidelines: [
576
- `Call ${start} only when the user explicitly asks to start a ${mode} workflow and none is active.`,
577
- "Pass the user's full goal as the goal parameter.",
578
- ],
579
569
  parameters: Type.Object({
580
570
  goal: Type.String({
581
571
  description: `What the user wants the ${mode} workflow to build or accomplish.`,
@@ -650,11 +640,6 @@ export function createWorkflowExtension(
650
640
  name: resume,
651
641
  label: options.toolLabels.resume,
652
642
  description: `Resume an explicitly selected ${mode} workflow run. Pass a run id, artifact directory, or workflow.json path.`,
653
- promptSnippet: `${resume}(run) - resume an explicit ${mode} workflow run; run is its id, artifact directory, or workflow.json path.`,
654
- promptGuidelines: [
655
- `Call ${resume} only when the user explicitly selects a ${mode} workflow run.`,
656
- "Workflow runs never resume automatically after reload.",
657
- ],
658
643
  parameters: Type.Object({ run: Type.String({ description: "Run id, artifact directory, or workflow.json path." }) }),
659
644
  async execute(_id, params, _signal, _onUpdate, ctx) {
660
645
  return resumeController(controller, ctx, params.run, end);
@@ -671,10 +656,6 @@ export function createWorkflowExtension(
671
656
  name: end,
672
657
  label: options.toolLabels.end,
673
658
  description: `Close the ${mode} workflow. Must be called when the final phase is complete. Marks the workflow finished and stops the agent loop.`,
674
- promptSnippet: `${end}() - close the finished ${mode} workflow; no further phase transitions allowed.`,
675
- promptGuidelines: [
676
- `Call ${end} exactly once, from the terminal phase, when all close artifacts are complete.`,
677
- ],
678
659
  parameters: Type.Object({}),
679
660
  async execute(_id, _params, _signal, _onUpdate, ctx) {
680
661
  const before = checkpoint(controller);
@@ -5,6 +5,7 @@ description: >
5
5
  filler, articles, and pleasantries while keeping full technical accuracy.
6
6
  Use when user says "caveman mode", "talk like caveman", "use caveman",
7
7
  "less tokens", "be brief", or invokes /caveman.
8
+ disable-model-invocation: true
8
9
  ---
9
10
 
10
11
  Respond terse like smart caveman. All technical substance stay. Only fluff die.
@@ -2,6 +2,7 @@
2
2
  name: handoff
3
3
  description: Compact the current conversation into a handoff document for another agent to pick up.
4
4
  argument-hint: "What will the next session be used for?"
5
+ disable-model-invocation: true
5
6
  ---
6
7
 
7
8
  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.
@@ -2,6 +2,7 @@
2
2
  name: handoff-text
3
3
  description: Compact the current conversation into a handoff document for another agent to pick up.
4
4
  argument-hint: "What will the next session be used for?"
5
+ disable-model-invocation: true
5
6
  ---
6
7
 
7
8
  Write a handoff document summarising the current conversation so a fresh agent can continue the work. Dont save the handoff, output only.
@@ -2,6 +2,7 @@
2
2
  name: implanger
3
3
  description: Execute the Planger's style planning
4
4
  argument-hint: "For Subagent to be able to understand Planger and can execute it perfectly"
5
+ disable-model-invocation: true
5
6
  ---
6
7
 
7
8
  ## Goal
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: improve-codebase
3
3
  description: improve codebase quality
4
+ disable-model-invocation: true
4
5
  ---
5
6
 
6
7
  # Improve Codebase Architecture
@@ -2,6 +2,7 @@
2
2
  name: planger
3
3
  description: Create decomposed planning for sub agent
4
4
  argument-hint: "How i provide a good plan for subagent"
5
+ disable-model-invocation: true
5
6
  ---
6
7
 
7
8
  # Planning Skill
@@ -12,6 +12,7 @@ description: >
12
12
  dependencies.
13
13
  argument-hint: "[lite|full|ultra]"
14
14
  license: MIT
15
+ disable-model-invocation: true
15
16
  ---
16
17
 
17
18
  # Ponytail
@@ -7,6 +7,7 @@ description: >
7
7
  codebase", "audit for over-engineering", "what can I delete from this repo",
8
8
  "find bloat", "ponytail-audit", or "/ponytail-audit". One-shot report, does
9
9
  not apply fixes.
10
+ disable-model-invocation: true
10
11
  ---
11
12
 
12
13
  ponytail-review, repo-wide. Scan the whole tree instead of a diff. Rank
@@ -6,6 +6,7 @@ description: >
6
6
  of rotting into "later means never". Use when the user says "ponytail debt",
7
7
  "/ponytail-debt", "what did ponytail defer", "list the shortcuts", "ponytail
8
8
  ledger", or "what did we mark to do later". One-shot report, changes nothing.
9
+ disable-model-invocation: true
9
10
  ---
10
11
 
11
12
  Every deliberate ponytail shortcut is marked with a `ponytail:` comment naming
@@ -6,6 +6,7 @@ description: >
6
6
  persistent mode, and not a per-repo number. Trigger: /ponytail-gain,
7
7
  "ponytail gain", "what does ponytail save", "show ponytail impact",
8
8
  "ponytail scoreboard".
9
+ disable-model-invocation: true
9
10
  ---
10
11
 
11
12
  # Ponytail Gain
@@ -4,6 +4,7 @@ description: >
4
4
  Quick-reference card for all ponytail modes, skills, and commands.
5
5
  One-shot display, not a persistent mode. Trigger: /ponytail-help,
6
6
  "ponytail help", "what ponytail commands", "how do I use ponytail".
7
+ disable-model-invocation: true
7
8
  ---
8
9
 
9
10
  # Ponytail Help
@@ -8,6 +8,7 @@ description: >
8
8
  delete", "is this over-engineered", "simplify review", or invokes
9
9
  /ponytail-review. Complements correctness-focused review, this one only
10
10
  hunts complexity.
11
+ disable-model-invocation: true
11
12
  ---
12
13
 
13
14
  Review diffs for unnecessary complexity. One line per finding: location, what
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: workflow-creation
3
3
  description: Creates durable Selesai workflow modes. Use when a user asks to create or change a workflow mode, phased agent flow, or slash-command workflow.
4
+ disable-model-invocation: true
4
5
  ---
5
6
 
6
7
  # Durable Workflows
package/package.json CHANGED
@@ -1,8 +1,28 @@
1
1
  {
2
2
  "name": "@selesai/code",
3
- "version": "0.5.12",
4
- "description": "Selesai coding agent",
3
+ "version": "0.5.14",
4
+ "description": "Maintained, extension-first Pi coding agent with built-in workflows, subagents, web research, questions, skills, and an enhanced terminal UI.",
5
5
  "type": "module",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/SelesaiInTech/selesai-code.git"
9
+ },
10
+ "homepage": "https://github.com/SelesaiInTech/selesai-code#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/SelesaiInTech/selesai-code/issues"
13
+ },
14
+ "keywords": [
15
+ "pi-package",
16
+ "coding-agent",
17
+ "ai-agent",
18
+ "terminal",
19
+ "typescript",
20
+ "llm",
21
+ "subagents",
22
+ "workflow",
23
+ "web-research",
24
+ "tui"
25
+ ],
6
26
  "piConfig": {
7
27
  "name": "selesai",
8
28
  "configDir": ".selesai"
@@ -22,6 +42,7 @@
22
42
  }
23
43
  },
24
44
  "files": [
45
+ "README.md",
25
46
  "dist",
26
47
  "docs",
27
48
  "examples",