pi-harness-runtime 0.10.21 → 0.10.22

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,19 @@
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.22](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.10.14...v0.10.22) (2026-08-09)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * align TS formatting with main (remove 3-line logError) ([2515ad5](https://github.com/ManotLuijiu/pi-harness-runtime/commit/2515ad54f43f0566123c686d3ec4f92ad363ea13))
11
+ * correct import paths for notification-center dist files ([f248722](https://github.com/ManotLuijiu/pi-harness-runtime/commit/f24872240c07bf115f69530a3bdabedf73e3c858))
12
+ * handle array/object content in pi-usage-status build detection ([68b07a8](https://github.com/ManotLuijiu/pi-harness-runtime/commit/68b07a8e8167a95ab1b519782a07ec3a582eec5a))
13
+ * skip publish-time scripts in release workflow ([b385148](https://github.com/ManotLuijiu/pi-harness-runtime/commit/b38514835dc3f6fd717ca8c71dbb6d131de4887f))
14
+ * suppress noisy stack traces in harness agents ([34bbe98](https://github.com/ManotLuijiu/pi-harness-runtime/commit/34bbe98f59e740fcfcd8622f1dcc09c379f6f3df))
15
+ * **todo-bd-sync:** disable auto-injection completely - was causing noisy output ([699d6de](https://github.com/ManotLuijiu/pi-harness-runtime/commit/699d6de5e7f3b062799a0f791b386d1ecd452b00))
16
+ * **todo-bd-sync:** silence all console output - no startup warnings ([2d29bcf](https://github.com/ManotLuijiu/pi-harness-runtime/commit/2d29bcf51b25fe1b1253aa965e370852f3cae289))
17
+
5
18
  ### [0.10.21](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.10.14...v0.10.21) (2026-08-08)
6
19
 
7
20
 
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.22",
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": {
@@ -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