pi-harness-runtime 0.10.21 → 0.10.23

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/CHANGELOG.md CHANGED
@@ -2,6 +2,37 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [0.10.23](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.10.14...v0.10.23) (2026-08-09)
6
+
7
+
8
+ ### Features
9
+
10
+ * **file-copy-helper:** inject cp rule when user asks to mimic/copy files ([f089f0d](https://github.com/ManotLuijiu/pi-harness-runtime/commit/f089f0d5e3e933231c99ee38cf18fa208c8eb8b2))
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * align TS formatting with main (remove 3-line logError) ([2515ad5](https://github.com/ManotLuijiu/pi-harness-runtime/commit/2515ad54f43f0566123c686d3ec4f92ad363ea13))
16
+ * correct import paths for notification-center dist files ([f248722](https://github.com/ManotLuijiu/pi-harness-runtime/commit/f24872240c07bf115f69530a3bdabedf73e3c858))
17
+ * handle array/object content in pi-usage-status build detection ([68b07a8](https://github.com/ManotLuijiu/pi-harness-runtime/commit/68b07a8e8167a95ab1b519782a07ec3a582eec5a))
18
+ * skip publish-time scripts in release workflow ([b385148](https://github.com/ManotLuijiu/pi-harness-runtime/commit/b38514835dc3f6fd717ca8c71dbb6d131de4887f))
19
+ * suppress noisy stack traces in harness agents ([34bbe98](https://github.com/ManotLuijiu/pi-harness-runtime/commit/34bbe98f59e740fcfcd8622f1dcc09c379f6f3df))
20
+ * **todo-bd-sync:** disable auto-injection completely - was causing noisy output ([699d6de](https://github.com/ManotLuijiu/pi-harness-runtime/commit/699d6de5e7f3b062799a0f791b386d1ecd452b00))
21
+ * **todo-bd-sync:** silence all console output - no startup warnings ([2d29bcf](https://github.com/ManotLuijiu/pi-harness-runtime/commit/2d29bcf51b25fe1b1253aa965e370852f3cae289))
22
+
23
+ ### [0.10.22](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.10.14...v0.10.22) (2026-08-09)
24
+
25
+
26
+ ### Bug Fixes
27
+
28
+ * align TS formatting with main (remove 3-line logError) ([2515ad5](https://github.com/ManotLuijiu/pi-harness-runtime/commit/2515ad54f43f0566123c686d3ec4f92ad363ea13))
29
+ * correct import paths for notification-center dist files ([f248722](https://github.com/ManotLuijiu/pi-harness-runtime/commit/f24872240c07bf115f69530a3bdabedf73e3c858))
30
+ * handle array/object content in pi-usage-status build detection ([68b07a8](https://github.com/ManotLuijiu/pi-harness-runtime/commit/68b07a8e8167a95ab1b519782a07ec3a582eec5a))
31
+ * skip publish-time scripts in release workflow ([b385148](https://github.com/ManotLuijiu/pi-harness-runtime/commit/b38514835dc3f6fd717ca8c71dbb6d131de4887f))
32
+ * suppress noisy stack traces in harness agents ([34bbe98](https://github.com/ManotLuijiu/pi-harness-runtime/commit/34bbe98f59e740fcfcd8622f1dcc09c379f6f3df))
33
+ * **todo-bd-sync:** disable auto-injection completely - was causing noisy output ([699d6de](https://github.com/ManotLuijiu/pi-harness-runtime/commit/699d6de5e7f3b062799a0f791b386d1ecd452b00))
34
+ * **todo-bd-sync:** silence all console output - no startup warnings ([2d29bcf](https://github.com/ManotLuijiu/pi-harness-runtime/commit/2d29bcf51b25fe1b1253aa965e370852f3cae289))
35
+
5
36
  ### [0.10.21](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.10.14...v0.10.21) (2026-08-08)
6
37
 
7
38
 
package/index.ts CHANGED
@@ -73,7 +73,7 @@ import { scheduleAutoResume, cancelAutoResume } from "./harness/index.js";
73
73
  async function initTodoBdSync(pi: ExtensionAPI): Promise<void> {
74
74
  try {
75
75
  const mod = await import("./packages/todo-bd-sync/src/extension.js");
76
- mod.registerTodoBdSync(pi, { debug: false });
76
+ mod.registerTodoBdSync(pi);
77
77
  } catch {
78
78
  // todo-bd-sync not available
79
79
  }
@@ -100,6 +100,17 @@ async function initWriteReview(pi: ExtensionAPI): Promise<void> {
100
100
  // write-review not available
101
101
  }
102
102
  }
103
+
104
+ // --- file-copy-helper: Inject cp rule when mimicking files --------------------
105
+ // Lazy import - only loads when packages/file-copy-helper exists
106
+ async function initFileCopyHelper(pi: ExtensionAPI): Promise<void> {
107
+ try {
108
+ const mod = await import("./packages/file-copy-helper/src/extension.js");
109
+ mod.registerFileCopyHelper(pi);
110
+ } catch {
111
+ // file-copy-helper not available
112
+ }
113
+ }
103
114
  import { homedir } from "node:os";
104
115
  import { appendFileSync, existsSync, mkdirSync } from "node:fs";
105
116
  import { join } from "node:path";
@@ -257,6 +268,9 @@ export default function (pi: ExtensionAPI) {
257
268
  // --- write-review: Two-agent write with review loop ----------------------
258
269
  void initWriteReview(pi);
259
270
 
271
+ // --- file-copy-helper: Inject cp rule when mimicking files -------------
272
+ void initFileCopyHelper(pi);
273
+
260
274
  // --- Auto-Invoke rpiv-todo via System Prompt ------------------------
261
275
  // This makes the todo overlay ALWAYS activate at session start
262
276
  const AUTO_TODO_INVOKE_HINT = `
@@ -354,17 +368,23 @@ Run \`bd ready\` to see current tasks.
354
368
  if (typeof rawContent === "string") {
355
369
  content = rawContent;
356
370
  } else if (Array.isArray(rawContent)) {
357
- content = rawContent.map((c) => typeof c === "string" ? c : JSON.stringify(c)).join("\n");
371
+ content = rawContent
372
+ .map((c) => (typeof c === "string" ? c : JSON.stringify(c)))
373
+ .join("\n");
358
374
  } else {
359
375
  content = JSON.stringify(rawContent ?? "");
360
376
  }
361
377
 
362
378
  // Check if this is a build command
363
- const isBuildCommand = BUILD_COMMANDS.some(
364
- (cmd) => content.toLowerCase().includes(cmd.toLowerCase()),
379
+ const isBuildCommand = BUILD_COMMANDS.some((cmd) =>
380
+ content.toLowerCase().includes(cmd.toLowerCase()),
365
381
  );
366
382
 
367
- if (isBuildCommand && !content.includes("bd ready") && !content.includes("TODO UPDATE")) {
383
+ if (
384
+ isBuildCommand &&
385
+ !content.includes("bd ready") &&
386
+ !content.includes("TODO UPDATE")
387
+ ) {
368
388
  // Append todo reminder to build output
369
389
  result.content = content + TODO_BUILD_REMINDER;
370
390
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-harness-runtime",
3
- "version": "0.10.21",
3
+ "version": "0.10.23",
4
4
  "description": "[BETA] Codex-style /usage status + autonomous coding harness for pi. Not production ready — expect breaking changes.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -75,7 +75,7 @@
75
75
  "devDependencies": {
76
76
  "@biomejs/biome": "^2.4.7",
77
77
  "@commitlint/cli": "^20.3.1",
78
- "@commitlint/config-conventional": "^20.3.1",
78
+ "@commitlint/config-conventional": "^21.2.0",
79
79
  "@types/node": "^26.1.0",
80
80
  "@types/ws": "^8.18.1",
81
81
  "husky": "^9.1.7",
@@ -0,0 +1,62 @@
1
+ // packages/file-copy-helper/src/extension.ts
2
+ var COPY_KEYWORDS = [
3
+ "mimic",
4
+ "copy from",
5
+ "copy to",
6
+ "clone from",
7
+ "clone to",
8
+ "replicate",
9
+ "port from",
10
+ "migrate from",
11
+ "bring from",
12
+ "move from"
13
+ ];
14
+ var COPY_RULE = `
15
+ ## File Copy Rule (CRITICAL)
16
+
17
+ When copying files between folders, ALWAYS use \`cp\` or \`sudo cp\` instead of writing from scratch:
18
+
19
+ \`\`\`bash
20
+ # Direct copy (if you have permission)
21
+ cp /path/to/source/file.ts /path/to/dest/file.ts
22
+
23
+ # With sudo (if permission denied)
24
+ sudo cp /path/to/source/file.ts /path/to/dest/file.ts
25
+
26
+ # Copy entire folder
27
+ sudo cp -r /path/to/source/folder /path/to/dest/
28
+ \`\`\`
29
+
30
+ **NEVER write files from scratch when copying is available** - it causes incomplete/imprecise code.
31
+
32
+ The source files already exist. Just copy them directly.
33
+ `;
34
+ function shouldInject(text) {
35
+ const lower = text.toLowerCase();
36
+ return COPY_KEYWORDS.some((keyword) => lower.includes(keyword));
37
+ }
38
+ function registerFileCopyHelper(pi) {
39
+ pi.on("input", (event) => {
40
+ if (event.source !== "interactive") {
41
+ return;
42
+ }
43
+ const text = event.text.trim();
44
+ if (!text || text.length < 10) {
45
+ return;
46
+ }
47
+ if (shouldInject(text)) {
48
+ return {
49
+ action: "transform",
50
+ text: text + COPY_RULE
51
+ };
52
+ }
53
+ return;
54
+ });
55
+ }
56
+ function fileCopyHelperExtension(pi) {
57
+ registerFileCopyHelper(pi);
58
+ }
59
+ export {
60
+ registerFileCopyHelper,
61
+ fileCopyHelperExtension as default
62
+ };
@@ -0,0 +1,87 @@
1
+ /**
2
+ * file-copy-helper extension
3
+ *
4
+ * Injects "use cp instead of writing from scratch" reminder when user
5
+ * asks to mimic, copy, clone, or replicate files/folders between locations.
6
+ */
7
+
8
+ import type {
9
+ ExtensionAPI,
10
+ InputEvent,
11
+ InputEventResult,
12
+ } from "@earendil-works/pi-coding-agent";
13
+
14
+ // Keywords that trigger the copy rule injection
15
+ const COPY_KEYWORDS = [
16
+ "mimic",
17
+ "copy from",
18
+ "copy to",
19
+ "clone from",
20
+ "clone to",
21
+ "replicate",
22
+ "port from",
23
+ "migrate from",
24
+ "bring from",
25
+ "move from",
26
+ ];
27
+
28
+ const COPY_RULE = `
29
+ ## File Copy Rule (CRITICAL)
30
+
31
+ When copying files between folders, ALWAYS use \`cp\` or \`sudo cp\` instead of writing from scratch:
32
+
33
+ \`\`\`bash
34
+ # Direct copy (if you have permission)
35
+ cp /path/to/source/file.ts /path/to/dest/file.ts
36
+
37
+ # With sudo (if permission denied)
38
+ sudo cp /path/to/source/file.ts /path/to/dest/file.ts
39
+
40
+ # Copy entire folder
41
+ sudo cp -r /path/to/source/folder /path/to/dest/
42
+ \`\`\`
43
+
44
+ **NEVER write files from scratch when copying is available** - it causes incomplete/imprecise code.
45
+
46
+ The source files already exist. Just copy them directly.
47
+ `;
48
+
49
+ /**
50
+ * Check if text contains copy-related keywords
51
+ */
52
+ function shouldInject(text: string): boolean {
53
+ const lower = text.toLowerCase();
54
+ return COPY_KEYWORDS.some((keyword) => lower.includes(keyword));
55
+ }
56
+
57
+ /**
58
+ * Register the file-copy-helper extension
59
+ */
60
+ export function registerFileCopyHelper(pi: ExtensionAPI): void {
61
+ pi.on("input", (event: InputEvent): InputEventResult | undefined => {
62
+ // Only process user input (not from extensions or RPC)
63
+ if (event.source !== "interactive") {
64
+ return;
65
+ }
66
+
67
+ const text = event.text.trim();
68
+ if (!text || text.length < 10) {
69
+ return;
70
+ }
71
+
72
+ // Check if this is a copy/mimic request
73
+ if (shouldInject(text)) {
74
+ return {
75
+ action: "transform",
76
+ text: text + COPY_RULE,
77
+ };
78
+ }
79
+
80
+ return;
81
+ });
82
+ }
83
+
84
+ // Default export for pi extension loading
85
+ export default function fileCopyHelperExtension(pi: ExtensionAPI): void {
86
+ registerFileCopyHelper(pi);
87
+ }
@@ -0,0 +1 @@
1
+ export { registerFileCopyHelper, default } from "./extension.js";
@@ -1,372 +1,5 @@
1
- import { createRequire } from "node:module";
2
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
-
4
- // packages/todo-bd-sync/src/detector.js
5
- import { execSync } from "node:child_process";
6
- import { existsSync } from "node:fs";
7
- import { join } from "node:path";
8
- import { homedir } from "node:os";
9
- function isRpivTodoInstalled() {
10
- try {
11
- const output = execSync("npm list -g @juicesharp/rpiv-todo 2>/dev/null || echo 'NOT_FOUND'", {
12
- encoding: "utf8",
13
- timeout: 5000
14
- });
15
- return output.includes("@juicesharp/rpiv-todo") && !output.includes("NOT_FOUND");
16
- } catch {
17
- return false;
18
- }
19
- }
20
- function isRpivTodoLoaded() {
21
- const extensionsDir = join(homedir(), ".pi", "agent", "extensions");
22
- const possiblePaths = [
23
- join(extensionsDir, "rpiv-todo"),
24
- join(extensionsDir, "@juicesharp", "rpiv-todo"),
25
- join(extensionsDir, "node_modules", "@juicesharp", "rpiv-todo")
26
- ];
27
- for (const path of possiblePaths) {
28
- if (existsSync(path)) {
29
- return true;
30
- }
31
- }
32
- try {
33
- __require.resolve("@juicesharp/rpiv-todo");
34
- return true;
35
- } catch {}
36
- return false;
37
- }
38
- function getRpivTodoVersion() {
39
- try {
40
- const output = execSync(`npm list -g @juicesharp/rpiv-todo --json 2>/dev/null | grep '"version"' | head -1`, { encoding: "utf8", timeout: 5000 });
41
- const match = output.match(/"version":\s*"([^"]+)"/);
42
- return match ? match[1] : null;
43
- } catch {
44
- return null;
45
- }
46
- }
47
- function isBdInstalled() {
48
- try {
49
- const output = execSync("which bd 2>/dev/null || echo 'NOT_FOUND'", {
50
- encoding: "utf8",
51
- timeout: 5000
52
- });
53
- return output.includes("bd") && !output.includes("NOT_FOUND");
54
- } catch {
55
- return false;
56
- }
57
- }
58
- function isBdInitialized(cwd) {
59
- const projectDir = cwd || process.cwd();
60
- const beadsDir = join(projectDir, ".beads");
61
- return existsSync(beadsDir);
62
- }
63
- function getBdVersion() {
64
- try {
65
- const output = execSync("bd --version 2>/dev/null || echo 'unknown'", {
66
- encoding: "utf8",
67
- timeout: 5000
68
- });
69
- return output.trim().replace("bd version ", "");
70
- } catch {
71
- return null;
72
- }
73
- }
74
- function getDependencyStatus(cwd) {
75
- const installed = isBdInstalled();
76
- return {
77
- rpivTodo: {
78
- installed: isRpivTodoInstalled(),
79
- version: getRpivTodoVersion(),
80
- loaded: isRpivTodoLoaded()
81
- },
82
- bd: {
83
- installed,
84
- version: installed ? getBdVersion() : null,
85
- initialized: installed ? isBdInitialized(cwd) : false,
86
- installUrl: "https://github.com/gastownhall/beads"
87
- }
88
- };
89
- }
90
-
91
- // packages/todo-bd-sync/src/sync.js
92
- import { execSync as execSync2 } from "node:child_process";
93
-
94
- // packages/todo-bd-sync/src/types.js
95
- class IdMappingRegistry {
96
- mappings = new Map;
97
- bdMappings = new Map;
98
- set(todoId, bdId) {
99
- const now = Date.now();
100
- const mapping = {
101
- todoId,
102
- bdId,
103
- createdAt: now,
104
- lastSync: now
105
- };
106
- this.mappings.set(todoId, mapping);
107
- this.bdMappings.set(bdId, todoId);
108
- }
109
- getByTodoId(todoId) {
110
- return this.mappings.get(todoId);
111
- }
112
- getByBdId(bdId) {
113
- const todoId = this.bdMappings.get(bdId);
114
- return todoId !== undefined ? this.mappings.get(todoId) : undefined;
115
- }
116
- hasTodoId(todoId) {
117
- return this.mappings.has(todoId);
118
- }
119
- hasBdId(bdId) {
120
- return this.bdMappings.has(bdId);
121
- }
122
- updateLastSync(todoId) {
123
- const mapping = this.mappings.get(todoId);
124
- if (mapping) {
125
- mapping.lastSync = Date.now();
126
- }
127
- }
128
- delete(todoId) {
129
- const mapping = this.mappings.get(todoId);
130
- if (mapping) {
131
- this.bdMappings.delete(mapping.bdId);
132
- this.mappings.delete(todoId);
133
- }
134
- }
135
- getAll() {
136
- return Array.from(this.mappings.values());
137
- }
138
- clear() {
139
- this.mappings.clear();
140
- this.bdMappings.clear();
141
- }
142
- }
143
-
144
- // packages/todo-bd-sync/src/sync.js
145
- var mappingRegistry = new IdMappingRegistry;
146
- function execBdCommand(command) {
147
- try {
148
- return execSync2(command, {
149
- encoding: "utf8",
150
- timeout: 1e4,
151
- cwd: process.cwd()
152
- });
153
- } catch (error) {
154
- const err = error;
155
- return err.stderr || err.message || "";
156
- }
157
- }
158
- function getOpenBdIssues() {
159
- try {
160
- const output = execBdCommand("bd ready --json");
161
- const issues = JSON.parse(output);
162
- return issues.map((issue) => ({
163
- id: issue.id,
164
- title: issue.title,
165
- status: issue.status,
166
- priority: issue.priority,
167
- createdAt: issue.created_at,
168
- updatedAt: issue.updated_at
169
- }));
170
- } catch {
171
- return [];
172
- }
173
- }
174
-
175
- // packages/todo-bd-sync/src/task-analyzer.js
176
- var COMPLEX_KEYWORDS = [
177
- "complicated",
178
- "complex",
179
- "tricky",
180
- "difficult",
181
- "refactor",
182
- "architecture",
183
- "design",
184
- "implement from scratch",
185
- "rewrite",
186
- "investigate",
187
- "debug",
188
- "fix the bug",
189
- "performance"
190
- ];
191
- var RESEARCH_KEYWORDS = [
192
- "search",
193
- "look up",
194
- "find",
195
- "research",
196
- "check",
197
- "verify",
198
- "how to",
199
- "best practice",
200
- "compare",
201
- "evaluate",
202
- "review"
203
- ];
204
- var SUBTASK_KEYWORDS = [
205
- "also",
206
- "plus",
207
- "and also",
208
- "while you're at it",
209
- "on top of that",
210
- "additionally",
211
- "another thing",
212
- "don't forget",
213
- "should also"
214
- ];
215
- function analyzeTaskSignals(userMessage) {
216
- const lower = userMessage.toLowerCase();
217
- const actionVerbs = [
218
- "create",
219
- "build",
220
- "implement",
221
- "design",
222
- "setup",
223
- "configure",
224
- "migrate",
225
- "convert",
226
- "refactor",
227
- "optimize",
228
- "fix",
229
- "update",
230
- "add",
231
- "remove",
232
- "delete",
233
- "modify",
234
- "change",
235
- "replace"
236
- ];
237
- const stepCount = Math.max(1, actionVerbs.filter((v) => lower.includes(v)).length);
238
- const filePatterns = /[\w-]+\.(ts|js|py|json|md|yaml|yml|tsx|jsx|html|css|sql)/g;
239
- const fileMatches = userMessage.match(filePatterns) || [];
240
- const explicitFiles = fileMatches.length;
241
- const dirPatterns = /(?:src|lib|packages|apps|components|hooks|utils|api)\/[\w/-]+/g;
242
- const dirMatches = userMessage.match(dirPatterns) || [];
243
- const multiTaskIndicator = (lower.match(/and also|also|\+/g) || []).length;
244
- const estimatedFiles = Math.max(1, explicitFiles + dirMatches.length + multiTaskIndicator);
245
- return {
246
- stepCount,
247
- fileCount: estimatedFiles,
248
- needsResearch: RESEARCH_KEYWORDS.some((k) => lower.includes(k)),
249
- createsFiles: lower.includes("create") || lower.includes("add") || lower.includes("new"),
250
- explicitlyComplex: COMPLEX_KEYWORDS.some((k) => lower.includes(k)),
251
- likelySubtasks: SUBTASK_KEYWORDS.some((k) => lower.includes(k)) || multiTaskIndicator >= 2
252
- };
253
- }
254
- function decideAutoTodo(userMessage, options = {}) {
255
- const signals = analyzeTaskSignals(userMessage);
256
- const pendingTasks = getOpenBdIssues().filter((i) => i.status !== "closed");
257
- const pendingCount = pendingTasks.length;
258
- const simplePatterns = [
259
- /^simply\s/i,
260
- /^just\s/i,
261
- /^quick\s/i,
262
- /^can you\s+(grep|find|cat|ls|echo)/i,
263
- /^(grep|find|cat|ls)\s+[\w.-]+/i,
264
- /^what('s| is) the\s+\w+\s+\?$/i,
265
- /^how do i\s+\w+\s*\?$/i
266
- ];
267
- if (simplePatterns.some((p) => p.test(userMessage.trim()))) {
268
- return {
269
- shouldCreate: false,
270
- reason: "Simple request (lookup/one-liner)",
271
- confidence: "high",
272
- skipReason: "Task is too simple to warrant tracking"
273
- };
274
- }
275
- const isTrivial = signals.stepCount === 1 && signals.fileCount <= 1 && !signals.needsResearch && !signals.createsFiles && !signals.explicitlyComplex && pendingCount === 0 && !signals.likelySubtasks;
276
- if (isTrivial) {
277
- return {
278
- shouldCreate: false,
279
- reason: "Trivial request (single action)",
280
- confidence: "high",
281
- skipReason: "Task is trivial"
282
- };
283
- }
284
- if (options.forceMode) {
285
- return {
286
- shouldCreate: true,
287
- reason: "Force mode enabled",
288
- confidence: "high"
289
- };
290
- }
291
- if (options.skipMode) {
292
- return {
293
- shouldCreate: false,
294
- reason: "Skip mode enabled",
295
- confidence: "high",
296
- skipReason: "User requested skip"
297
- };
298
- }
299
- const reasons = [];
300
- if (signals.explicitlyComplex) {
301
- reasons.push("explicitly complex");
302
- }
303
- if (signals.stepCount >= 2) {
304
- reasons.push(`${signals.stepCount} steps implied`);
305
- }
306
- if (signals.fileCount >= 2) {
307
- reasons.push(`${signals.fileCount} files involved`);
308
- }
309
- if (signals.needsResearch) {
310
- reasons.push("needs research");
311
- }
312
- if (signals.createsFiles) {
313
- reasons.push("creates files");
314
- }
315
- if (signals.likelySubtasks) {
316
- reasons.push("likely has subtasks");
317
- }
318
- if (pendingCount >= 1) {
319
- reasons.push(`${pendingCount} pending tasks`);
320
- }
321
- if (reasons.length === 0) {
322
- reasons.push("multi-step task detected");
323
- }
324
- const shouldCreate = reasons.length >= 1 || pendingCount >= 1;
325
- return {
326
- shouldCreate,
327
- reason: reasons.join(", "),
328
- confidence: reasons.length >= 2 ? "high" : "medium"
329
- };
330
- }
331
-
332
1
  // packages/todo-bd-sync/src/extension.ts
333
- function registerTodoBdSync(pi) {
334
- const deps = getDependencyStatus();
335
- if (!deps.bd.installed || !deps.bd.initialized) {
336
- return;
337
- }
338
- pi.on("input", (event) => {
339
- if (event.source !== "interactive") {
340
- return;
341
- }
342
- const text = event.text.trim();
343
- if (!text || text.length < 5) {
344
- return;
345
- }
346
- const decision = decideAutoTodo(text);
347
- if (decision.shouldCreate) {
348
- const hasExplicitTodo = text.toLowerCase().includes("use the todo") || text.toLowerCase().includes("add to todo") || text.toLowerCase().includes("track as todo") || text.toLowerCase().includes("todo list") || text.toLowerCase().includes("create todo");
349
- if (!hasExplicitTodo) {
350
- const injection = `
351
-
352
- IMPORTANT: Use the \`todo\` tool to track this task:
353
- 1. Create a todo item with subject: "${text.slice(0, 80)}${text.length > 80 ? "..." : ""}"
354
- 2. Mark it as in_progress
355
- 3. Track your progress as you work
356
-
357
- \`\`\`json
358
- {"action": "create", "subject": "${text.slice(0, 80)}${text.length > 80 ? "..." : ""}", "activeForm": "working on task"}
359
- \`\`\`
360
- `;
361
- return {
362
- action: "transform",
363
- text: text + injection
364
- };
365
- }
366
- }
367
- return;
368
- });
369
- }
2
+ function registerTodoBdSync(_pi) {}
370
3
  function todoBdSyncExtension(pi) {
371
4
  registerTodoBdSync(pi);
372
5
  }
@@ -1,85 +1,20 @@
1
1
  /**
2
2
  * todo-bd-sync extension entry point
3
3
  *
4
- * This extension:
5
- * 1. Detects if bd is installed and initialized
6
- * 2. Auto-injects todo tool call when task is complex
7
- * 3. Provides two-way sync between rpiv-todo and bd (via rpiv-todo)
4
+ * NOTE: Auto-injection disabled - was causing noisy output.
5
+ * Only provides dependency detection status.
8
6
  */
9
7
 
10
- import type {
11
- ExtensionAPI,
12
- InputEvent,
13
- InputEventResult,
14
- } from "@earendil-works/pi-coding-agent";
15
- import { getDependencyStatus } from "./detector.js";
16
- import { decideAutoTodo } from "./task-analyzer.js";
8
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
17
9
 
18
10
  /**
19
11
  * Register the todo-bd-sync extension
12
+ *
13
+ * NOTE: Auto-injection disabled - was causing issues with bd working.
14
+ * The todo tool call injection has been removed.
20
15
  */
21
- export function registerTodoBdSync(pi: ExtensionAPI): void {
22
- const deps = getDependencyStatus();
23
-
24
- // Silently skip if bd is not installed or initialized
25
- if (!deps.bd.installed || !deps.bd.initialized) {
26
- return;
27
- }
28
-
29
- // ── Smart Auto-Todo Injection ──────────────────────────────────────────
30
- // Listen to user input and inject todo tool call when task is complex
31
-
32
- pi.on("input", (event: InputEvent): InputEventResult | undefined => {
33
- // Only process user input (not from extensions or RPC)
34
- if (event.source !== "interactive") {
35
- return;
36
- }
37
-
38
- const text = event.text.trim();
39
- if (!text || text.length < 5) {
40
- return; // Skip very short inputs
41
- }
42
-
43
- const decision = decideAutoTodo(text);
44
-
45
- // If should create todo and phrase not already present
46
- if (decision.shouldCreate) {
47
- // Check if already has explicit todo instruction
48
- const hasExplicitTodo =
49
- text.toLowerCase().includes("use the todo") ||
50
- text.toLowerCase().includes("add to todo") ||
51
- text.toLowerCase().includes("track as todo") ||
52
- text.toLowerCase().includes("todo list") ||
53
- text.toLowerCase().includes("create todo");
54
-
55
- if (!hasExplicitTodo) {
56
- // Silently inject - no console noise
57
-
58
- // Clearer instruction that explicitly tells LLM to use todo tool
59
- // This is more direct than just adding text - it tells LLM to CALL the todo tool
60
- const injection = `
61
-
62
- IMPORTANT: Use the \`todo\` tool to track this task:
63
- 1. Create a todo item with subject: "${text.slice(0, 80)}${text.length > 80 ? "..." : ""}"
64
- 2. Mark it as in_progress
65
- 3. Track your progress as you work
66
-
67
- \`\`\`json
68
- {"action": "create", "subject": "${text.slice(0, 80)}${text.length > 80 ? "..." : ""}", "activeForm": "working on task"}
69
- \`\`\`
70
- `;
71
-
72
- return {
73
- action: "transform",
74
- text: text + injection,
75
- };
76
- }
77
- }
78
-
79
- return;
80
- });
81
-
82
- // Silent startup - no console noise
16
+ export function registerTodoBdSync(_pi: ExtensionAPI): void {
17
+ // Silent - no registration, no injection, no console output
83
18
  }
84
19
 
85
20
  // Default export for pi extension loading