@mjasnikovs/pi-task 0.39.3 → 0.39.4

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.
@@ -28,6 +28,16 @@ export interface GuardableTool {
28
28
  /** Provenance shown in the menu, e.g. "built in" or "npm:pi-fable (/path)". */
29
29
  origin: string;
30
30
  }
31
+ /**
32
+ * pi-task's own tools whose child already carries the guard the host watchdog
33
+ * would duplicate — and duplicate WRONGLY. `pi-worker` runs the `adhoc` profile
34
+ * (workers/worker-profiles.ts): no wall clock by decision, bounded on model
35
+ * SILENCE via `stuck reply retry`, plus the loop, churn and dead-backend guards.
36
+ * A host wall clock on top killed healthy workers at the command ceiling while
37
+ * they were still reading. Never armed, never offered as a `watch:` row: the
38
+ * operator should not be handed a switch that is only ever correct one way.
39
+ */
40
+ export declare const SELF_BOUNDED_TOOLS: ReadonlySet<string>;
31
41
  /**
32
42
  * Every tool in the live session, built-ins first and each extension's tools in
33
43
  * registration order after them, so the menu reads owner-by-owner.
@@ -1,5 +1,15 @@
1
1
  /** The `source` pi reports for its own tools rather than an extension's. */
2
2
  const BUILTIN_SOURCE = 'builtin';
3
+ /**
4
+ * pi-task's own tools whose child already carries the guard the host watchdog
5
+ * would duplicate — and duplicate WRONGLY. `pi-worker` runs the `adhoc` profile
6
+ * (workers/worker-profiles.ts): no wall clock by decision, bounded on model
7
+ * SILENCE via `stuck reply retry`, plus the loop, churn and dead-backend guards.
8
+ * A host wall clock on top killed healthy workers at the command ceiling while
9
+ * they were still reading. Never armed, never offered as a `watch:` row: the
10
+ * operator should not be handed a switch that is only ever correct one way.
11
+ */
12
+ export const SELF_BOUNDED_TOOLS = new Set(['pi-worker']);
3
13
  /**
4
14
  * Human provenance for a tool's source metadata. `source` is pi's own word for
5
15
  * where the owner came from ("builtin", "npm:...", "auto", "cli"); the two
@@ -30,7 +40,7 @@ export function toGuardableTools(tools) {
30
40
  // A duplicate name cannot be told apart by the watchdog (it only ever
31
41
  // sees `toolName`), so a second registration must not add a second row
32
42
  // that silently toggles the first one's guard.
33
- if (seen.has(t.name))
43
+ if (seen.has(t.name) || SELF_BOUNDED_TOOLS.has(t.name))
34
44
  continue;
35
45
  seen.add(t.name);
36
46
  const entry = { name: t.name, origin: toolOrigin(t.sourceInfo.source, t.sourceInfo.path) };
@@ -20,9 +20,10 @@ import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';
20
20
  *
21
21
  * Tool-agnostic by default: it arms on every tool except exact names listed in
22
22
  * `commandTimeoutExemptTools`, which /task-config fills from the live tool list
23
- * (config/tool-list.ts). Exemptions are for tools that already own a bounded
24
- * timeout and cancellation contract the guard's whole justification is that
25
- * pi's bash has NO default timeout, which says nothing about a tool that does.
23
+ * (config/tool-list.ts), and pi-task's own SELF_BOUNDED_TOOLS, exempt in code.
24
+ * Exemptions are for tools that already own a bounded timeout and cancellation
25
+ * contract the guard's whole justification is that pi's bash has NO default
26
+ * timeout, which says nothing about a tool that does.
26
27
  *
27
28
  * SCOPE — this covers the main session ONLY, which is where the implementation
28
29
  * turn runs (orchestrator hands the spec off via sendUserMessage). Gate
@@ -1,4 +1,5 @@
1
1
  import { getConfig } from '../config/config.js';
2
+ import { SELF_BOUNDED_TOOLS } from '../config/tool-list.js';
2
3
  import { CommandWatchdog, realTimerDeps, reminderMessage } from '../shared/command-watchdog.js';
3
4
  /**
4
5
  * MAIN-SESSION adapter for the command watchdog.
@@ -21,9 +22,10 @@ import { CommandWatchdog, realTimerDeps, reminderMessage } from '../shared/comma
21
22
  *
22
23
  * Tool-agnostic by default: it arms on every tool except exact names listed in
23
24
  * `commandTimeoutExemptTools`, which /task-config fills from the live tool list
24
- * (config/tool-list.ts). Exemptions are for tools that already own a bounded
25
- * timeout and cancellation contract the guard's whole justification is that
26
- * pi's bash has NO default timeout, which says nothing about a tool that does.
25
+ * (config/tool-list.ts), and pi-task's own SELF_BOUNDED_TOOLS, exempt in code.
26
+ * Exemptions are for tools that already own a bounded timeout and cancellation
27
+ * contract the guard's whole justification is that pi's bash has NO default
28
+ * timeout, which says nothing about a tool that does.
27
29
  *
28
30
  * SCOPE — this covers the main session ONLY, which is where the implementation
29
31
  * turn runs (orchestrator hands the spec off via sendUserMessage). Gate
@@ -73,7 +75,8 @@ export function registerCommandWatchdog(pi) {
73
75
  const ctxByCall = new Map();
74
76
  const watchdog = new CommandWatchdog({
75
77
  getTimeoutMs: () => getConfig().requestTimeoutMs,
76
- shouldWatch: toolName => !getConfig().commandTimeoutExemptTools.includes(toolName),
78
+ shouldWatch: toolName => !SELF_BOUNDED_TOOLS.has(toolName)
79
+ && !getConfig().commandTimeoutExemptTools.includes(toolName),
77
80
  ...realTimerDeps,
78
81
  onFire: (toolCallId, toolName, timeoutMs) => {
79
82
  const ctx = ctxByCall.get(toolCallId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mjasnikovs/pi-task",
3
- "version": "0.39.3",
3
+ "version": "0.39.4",
4
4
  "description": "Deterministic task planning and spec-orchestration for local models — crash-safe /task pipelines with verify/enforce gates, a real-time remote web view, and web/docs/fetch/worker subagent tools.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",