@caupulican/pi-adaptative 0.81.29 → 0.81.30

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 (147) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/bundled-resources/skills/harness-self-adaptation/SKILL.md +327 -0
  3. package/dist/bundled-resources/skills/harness-self-adaptation/references/adaptation-layers.md +89 -0
  4. package/dist/core/agent-session.d.ts +11 -1
  5. package/dist/core/agent-session.d.ts.map +1 -1
  6. package/dist/core/agent-session.js +16 -14
  7. package/dist/core/agent-session.js.map +1 -1
  8. package/dist/core/autonomy/approval-gate.d.ts +1 -1
  9. package/dist/core/autonomy/approval-gate.d.ts.map +1 -1
  10. package/dist/core/autonomy/approval-gate.js +5 -1
  11. package/dist/core/autonomy/approval-gate.js.map +1 -1
  12. package/dist/core/autonomy/lane-tool-surface.d.ts +4 -0
  13. package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
  14. package/dist/core/autonomy/lane-tool-surface.js +31 -4
  15. package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
  16. package/dist/core/autonomy/lane-tracker.d.ts +1 -0
  17. package/dist/core/autonomy/lane-tracker.d.ts.map +1 -1
  18. package/dist/core/autonomy/lane-tracker.js +11 -0
  19. package/dist/core/autonomy/lane-tracker.js.map +1 -1
  20. package/dist/core/autonomy/risk-assessment.d.ts.map +1 -1
  21. package/dist/core/autonomy/risk-assessment.js +1 -1
  22. package/dist/core/autonomy/risk-assessment.js.map +1 -1
  23. package/dist/core/background-lane-controller.d.ts +12 -0
  24. package/dist/core/background-lane-controller.d.ts.map +1 -1
  25. package/dist/core/background-lane-controller.js +114 -19
  26. package/dist/core/background-lane-controller.js.map +1 -1
  27. package/dist/core/context/context-artifacts.d.ts.map +1 -1
  28. package/dist/core/context/context-artifacts.js +7 -6
  29. package/dist/core/context/context-artifacts.js.map +1 -1
  30. package/dist/core/context/context-store-retention.d.ts +12 -0
  31. package/dist/core/context/context-store-retention.d.ts.map +1 -0
  32. package/dist/core/context/context-store-retention.js +161 -0
  33. package/dist/core/context/context-store-retention.js.map +1 -0
  34. package/dist/core/context-gc.d.ts.map +1 -1
  35. package/dist/core/context-gc.js +19 -4
  36. package/dist/core/context-gc.js.map +1 -1
  37. package/dist/core/context-pipeline.d.ts +13 -12
  38. package/dist/core/context-pipeline.d.ts.map +1 -1
  39. package/dist/core/context-pipeline.js +128 -33
  40. package/dist/core/context-pipeline.js.map +1 -1
  41. package/dist/core/cost/cost-summary.d.ts +7 -1
  42. package/dist/core/cost/cost-summary.d.ts.map +1 -1
  43. package/dist/core/cost/cost-summary.js +28 -17
  44. package/dist/core/cost/cost-summary.js.map +1 -1
  45. package/dist/core/cost/daily-usage.d.ts +7 -3
  46. package/dist/core/cost/daily-usage.d.ts.map +1 -1
  47. package/dist/core/cost/daily-usage.js +10 -5
  48. package/dist/core/cost/daily-usage.js.map +1 -1
  49. package/dist/core/delegation/worker-runner.d.ts.map +1 -1
  50. package/dist/core/delegation/worker-runner.js +25 -9
  51. package/dist/core/delegation/worker-runner.js.map +1 -1
  52. package/dist/core/export-html/template.js +2 -1
  53. package/dist/core/extensions/loader.d.ts.map +1 -1
  54. package/dist/core/extensions/loader.js +52 -2
  55. package/dist/core/extensions/loader.js.map +1 -1
  56. package/dist/core/extensions/runner.d.ts.map +1 -1
  57. package/dist/core/extensions/runner.js +21 -19
  58. package/dist/core/extensions/runner.js.map +1 -1
  59. package/dist/core/extensions/types.d.ts +5 -0
  60. package/dist/core/extensions/types.d.ts.map +1 -1
  61. package/dist/core/extensions/types.js.map +1 -1
  62. package/dist/core/failure-corpus.d.ts.map +1 -1
  63. package/dist/core/failure-corpus.js +36 -13
  64. package/dist/core/failure-corpus.js.map +1 -1
  65. package/dist/core/local-runtime-controller.d.ts.map +1 -1
  66. package/dist/core/local-runtime-controller.js +20 -2
  67. package/dist/core/local-runtime-controller.js.map +1 -1
  68. package/dist/core/memory-controller.d.ts +2 -0
  69. package/dist/core/memory-controller.d.ts.map +1 -1
  70. package/dist/core/memory-controller.js +18 -0
  71. package/dist/core/memory-controller.js.map +1 -1
  72. package/dist/core/models/local-runtime.d.ts.map +1 -1
  73. package/dist/core/models/local-runtime.js +15 -10
  74. package/dist/core/models/local-runtime.js.map +1 -1
  75. package/dist/core/reflection-controller.d.ts +3 -1
  76. package/dist/core/reflection-controller.d.ts.map +1 -1
  77. package/dist/core/reflection-controller.js +8 -5
  78. package/dist/core/reflection-controller.js.map +1 -1
  79. package/dist/core/runtime-builder.d.ts +2 -0
  80. package/dist/core/runtime-builder.d.ts.map +1 -1
  81. package/dist/core/runtime-builder.js.map +1 -1
  82. package/dist/core/sdk.d.ts.map +1 -1
  83. package/dist/core/sdk.js +1 -1
  84. package/dist/core/sdk.js.map +1 -1
  85. package/dist/core/session-analytics.d.ts +13 -7
  86. package/dist/core/session-analytics.d.ts.map +1 -1
  87. package/dist/core/session-analytics.js +155 -112
  88. package/dist/core/session-analytics.js.map +1 -1
  89. package/dist/core/tool-recovery-log-records.d.ts.map +1 -1
  90. package/dist/core/tool-recovery-log-records.js +54 -9
  91. package/dist/core/tool-recovery-log-records.js.map +1 -1
  92. package/dist/core/tool-recovery-logger.d.ts +2 -0
  93. package/dist/core/tool-recovery-logger.d.ts.map +1 -1
  94. package/dist/core/tool-recovery-logger.js +32 -13
  95. package/dist/core/tool-recovery-logger.js.map +1 -1
  96. package/dist/core/tool-recovery-stats.d.ts +15 -0
  97. package/dist/core/tool-recovery-stats.d.ts.map +1 -0
  98. package/dist/core/tool-recovery-stats.js +206 -0
  99. package/dist/core/tool-recovery-stats.js.map +1 -0
  100. package/dist/core/tools/delegate-status.d.ts.map +1 -1
  101. package/dist/core/tools/delegate-status.js +15 -6
  102. package/dist/core/tools/delegate-status.js.map +1 -1
  103. package/dist/core/tools/delegate.d.ts +3 -0
  104. package/dist/core/tools/delegate.d.ts.map +1 -1
  105. package/dist/core/tools/delegate.js +7 -2
  106. package/dist/core/tools/delegate.js.map +1 -1
  107. package/dist/main.d.ts.map +1 -1
  108. package/dist/main.js +1 -1
  109. package/dist/main.js.map +1 -1
  110. package/dist/modes/interactive/components/bash-execution.d.ts +2 -1
  111. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  112. package/dist/modes/interactive/components/bash-execution.js +12 -1
  113. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  114. package/dist/modes/interactive/components/footer.d.ts +1 -0
  115. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  116. package/dist/modes/interactive/components/footer.js +19 -9
  117. package/dist/modes/interactive/components/footer.js.map +1 -1
  118. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  119. package/dist/modes/interactive/components/tool-execution.js +12 -2
  120. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  121. package/dist/modes/interactive/components/tool-panel-registry.d.ts +1 -0
  122. package/dist/modes/interactive/components/tool-panel-registry.d.ts.map +1 -1
  123. package/dist/modes/interactive/components/tool-panel-registry.js +18 -2
  124. package/dist/modes/interactive/components/tool-panel-registry.js.map +1 -1
  125. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  126. package/dist/modes/interactive/interactive-mode.js +9 -3
  127. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  128. package/dist/modes/rpc/jsonl.d.ts.map +1 -1
  129. package/dist/modes/rpc/jsonl.js +9 -28
  130. package/dist/modes/rpc/jsonl.js.map +1 -1
  131. package/dist/utils/streaming-lines.d.ts +20 -0
  132. package/dist/utils/streaming-lines.d.ts.map +1 -0
  133. package/dist/utils/streaming-lines.js +79 -0
  134. package/dist/utils/streaming-lines.js.map +1 -0
  135. package/docs/extensions.md +2 -0
  136. package/docs/index.md +1 -1
  137. package/docs/self-adaptation.md +7 -0
  138. package/docs/settings.md +5 -1
  139. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  140. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  141. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  142. package/examples/extensions/sandbox/package-lock.json +2 -2
  143. package/examples/extensions/sandbox/package.json +1 -1
  144. package/examples/extensions/with-deps/package-lock.json +2 -2
  145. package/examples/extensions/with-deps/package.json +1 -1
  146. package/npm-shrinkwrap.json +12 -12
  147. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"jsonl.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/jsonl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG5C;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAExD;AAaD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAoDlG","sourcesContent":["import type { Readable } from \"node:stream\";\nimport { StringDecoder } from \"node:string_decoder\";\n\n/**\n * Serialize a single strict JSONL record.\n *\n * Framing is LF-only. Payload strings may contain other Unicode separators such as\n * U+2028 and U+2029. Clients must split records on `\\n` only.\n */\nexport function serializeJsonLine(value: unknown): string {\n\treturn `${JSON.stringify(value)}\\n`;\n}\n\n/**\n * Attach an LF-only JSONL reader to a stream.\n *\n * This intentionally does not use Node readline. Readline splits on additional\n * Unicode separators that are valid inside JSON strings and therefore does not\n * implement strict JSONL framing.\n */\n// A non-compliant peer streaming without newlines would otherwise grow the\n// line buffer without bound; one line can never legitimately exceed this.\nconst MAX_JSONL_LINE_CHARS = 64 * 1024 * 1024;\n\nexport function attachJsonlLineReader(stream: Readable, onLine: (line: string) => void): () => void {\n\tconst decoder = new StringDecoder(\"utf8\");\n\tlet buffer = \"\";\n\tlet discardingOversizedLine = false;\n\n\tconst emitLine = (line: string) => {\n\t\tonLine(line.endsWith(\"\\r\") ? line.slice(0, -1) : line);\n\t};\n\n\tconst onData = (chunk: string | Buffer) => {\n\t\tbuffer += typeof chunk === \"string\" ? chunk : decoder.write(chunk);\n\n\t\tif (discardingOversizedLine) {\n\t\t\tconst resumeIndex = buffer.indexOf(\"\\n\");\n\t\t\tif (resumeIndex === -1) {\n\t\t\t\tbuffer = \"\";\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tbuffer = buffer.slice(resumeIndex + 1);\n\t\t\tdiscardingOversizedLine = false;\n\t\t}\n\n\t\twhile (true) {\n\t\t\tconst newlineIndex = buffer.indexOf(\"\\n\");\n\t\t\tif (newlineIndex === -1) {\n\t\t\t\tif (buffer.length > MAX_JSONL_LINE_CHARS) {\n\t\t\t\t\tdiscardingOversizedLine = true;\n\t\t\t\t\tbuffer = \"\";\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\temitLine(buffer.slice(0, newlineIndex));\n\t\t\tbuffer = buffer.slice(newlineIndex + 1);\n\t\t}\n\t};\n\n\tconst onEnd = () => {\n\t\tbuffer += decoder.end();\n\t\tif (buffer.length > 0) {\n\t\t\temitLine(buffer);\n\t\t\tbuffer = \"\";\n\t\t}\n\t};\n\n\tstream.on(\"data\", onData);\n\tstream.on(\"end\", onEnd);\n\n\treturn () => {\n\t\tstream.off(\"data\", onData);\n\t\tstream.off(\"end\", onEnd);\n\t};\n}\n"]}
1
+ {"version":3,"file":"jsonl.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/jsonl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAI5C;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAExD;AAaD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CA2BlG","sourcesContent":["import type { Readable } from \"node:stream\";\nimport { StringDecoder } from \"node:string_decoder\";\nimport { StreamingLineDecoder } from \"../../utils/streaming-lines.ts\";\n\n/**\n * Serialize a single strict JSONL record.\n *\n * Framing is LF-only. Payload strings may contain other Unicode separators such as\n * U+2028 and U+2029. Clients must split records on `\\n` only.\n */\nexport function serializeJsonLine(value: unknown): string {\n\treturn `${JSON.stringify(value)}\\n`;\n}\n\n/**\n * Attach an LF-only JSONL reader to a stream.\n *\n * This intentionally does not use Node readline. Readline splits on additional\n * Unicode separators that are valid inside JSON strings and therefore does not\n * implement strict JSONL framing.\n */\n// A non-compliant peer streaming without newlines would otherwise grow the\n// line buffer without bound; one line can never legitimately exceed this.\nconst MAX_JSONL_LINE_CHARS = 64 * 1024 * 1024;\n\nexport function attachJsonlLineReader(stream: Readable, onLine: (line: string) => void): () => void {\n\tconst decoder = new StringDecoder(\"utf8\");\n\tconst lines = new StreamingLineDecoder(MAX_JSONL_LINE_CHARS, { overflow: \"skip\", lineEndings: \"lf\" });\n\n\tconst emitLine = (line: string) => {\n\t\tonLine(line.endsWith(\"\\r\") ? line.slice(0, -1) : line);\n\t};\n\n\tconst onData = (chunk: string | Buffer) => {\n\t\tfor (const line of lines.push(typeof chunk === \"string\" ? chunk : decoder.write(chunk))) {\n\t\t\temitLine(line);\n\t\t}\n\t};\n\n\tconst onEnd = () => {\n\t\tfor (const line of lines.push(decoder.end())) emitLine(line);\n\t\tconst finalLine = lines.finish();\n\t\tif (finalLine !== undefined) emitLine(finalLine);\n\t};\n\n\tstream.on(\"data\", onData);\n\tstream.on(\"end\", onEnd);\n\n\treturn () => {\n\t\tstream.off(\"data\", onData);\n\t\tstream.off(\"end\", onEnd);\n\t};\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { StringDecoder } from "node:string_decoder";
2
+ import { StreamingLineDecoder } from "../../utils/streaming-lines.js";
2
3
  /**
3
4
  * Serialize a single strict JSONL record.
4
5
  *
@@ -20,41 +21,21 @@ export function serializeJsonLine(value) {
20
21
  const MAX_JSONL_LINE_CHARS = 64 * 1024 * 1024;
21
22
  export function attachJsonlLineReader(stream, onLine) {
22
23
  const decoder = new StringDecoder("utf8");
23
- let buffer = "";
24
- let discardingOversizedLine = false;
24
+ const lines = new StreamingLineDecoder(MAX_JSONL_LINE_CHARS, { overflow: "skip", lineEndings: "lf" });
25
25
  const emitLine = (line) => {
26
26
  onLine(line.endsWith("\r") ? line.slice(0, -1) : line);
27
27
  };
28
28
  const onData = (chunk) => {
29
- buffer += typeof chunk === "string" ? chunk : decoder.write(chunk);
30
- if (discardingOversizedLine) {
31
- const resumeIndex = buffer.indexOf("\n");
32
- if (resumeIndex === -1) {
33
- buffer = "";
34
- return;
35
- }
36
- buffer = buffer.slice(resumeIndex + 1);
37
- discardingOversizedLine = false;
38
- }
39
- while (true) {
40
- const newlineIndex = buffer.indexOf("\n");
41
- if (newlineIndex === -1) {
42
- if (buffer.length > MAX_JSONL_LINE_CHARS) {
43
- discardingOversizedLine = true;
44
- buffer = "";
45
- }
46
- return;
47
- }
48
- emitLine(buffer.slice(0, newlineIndex));
49
- buffer = buffer.slice(newlineIndex + 1);
29
+ for (const line of lines.push(typeof chunk === "string" ? chunk : decoder.write(chunk))) {
30
+ emitLine(line);
50
31
  }
51
32
  };
52
33
  const onEnd = () => {
53
- buffer += decoder.end();
54
- if (buffer.length > 0) {
55
- emitLine(buffer);
56
- buffer = "";
57
- }
34
+ for (const line of lines.push(decoder.end()))
35
+ emitLine(line);
36
+ const finalLine = lines.finish();
37
+ if (finalLine !== undefined)
38
+ emitLine(finalLine);
58
39
  };
59
40
  stream.on("data", onData);
60
41
  stream.on("end", onEnd);
@@ -1 +1 @@
1
- {"version":3,"file":"jsonl.js","sourceRoot":"","sources":["../../../src/modes/rpc/jsonl.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAc,EAAU;IACzD,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;AAAA,CACpC;AAED;;;;;;GAMG;AACH,2EAA2E;AAC3E,0EAA0E;AAC1E,MAAM,oBAAoB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAE9C,MAAM,UAAU,qBAAqB,CAAC,MAAgB,EAAE,MAA8B,EAAc;IACnG,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,uBAAuB,GAAG,KAAK,CAAC;IAEpC,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAAA,CACvD,CAAC;IAEF,MAAM,MAAM,GAAG,CAAC,KAAsB,EAAE,EAAE,CAAC;QAC1C,MAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAEnE,IAAI,uBAAuB,EAAE,CAAC;YAC7B,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACzC,IAAI,WAAW,KAAK,CAAC,CAAC,EAAE,CAAC;gBACxB,MAAM,GAAG,EAAE,CAAC;gBACZ,OAAO;YACR,CAAC;YACD,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;YACvC,uBAAuB,GAAG,KAAK,CAAC;QACjC,CAAC;QAED,OAAO,IAAI,EAAE,CAAC;YACb,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,YAAY,KAAK,CAAC,CAAC,EAAE,CAAC;gBACzB,IAAI,MAAM,CAAC,MAAM,GAAG,oBAAoB,EAAE,CAAC;oBAC1C,uBAAuB,GAAG,IAAI,CAAC;oBAC/B,MAAM,GAAG,EAAE,CAAC;gBACb,CAAC;gBACD,OAAO;YACR,CAAC;YAED,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC;YACxC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC;QACzC,CAAC;IAAA,CACD,CAAC;IAEF,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC;QACnB,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACxB,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,QAAQ,CAAC,MAAM,CAAC,CAAC;YACjB,MAAM,GAAG,EAAE,CAAC;QACb,CAAC;IAAA,CACD,CAAC;IAEF,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1B,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAExB,OAAO,GAAG,EAAE,CAAC;QACZ,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC3B,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAAA,CACzB,CAAC;AAAA,CACF","sourcesContent":["import type { Readable } from \"node:stream\";\nimport { StringDecoder } from \"node:string_decoder\";\n\n/**\n * Serialize a single strict JSONL record.\n *\n * Framing is LF-only. Payload strings may contain other Unicode separators such as\n * U+2028 and U+2029. Clients must split records on `\\n` only.\n */\nexport function serializeJsonLine(value: unknown): string {\n\treturn `${JSON.stringify(value)}\\n`;\n}\n\n/**\n * Attach an LF-only JSONL reader to a stream.\n *\n * This intentionally does not use Node readline. Readline splits on additional\n * Unicode separators that are valid inside JSON strings and therefore does not\n * implement strict JSONL framing.\n */\n// A non-compliant peer streaming without newlines would otherwise grow the\n// line buffer without bound; one line can never legitimately exceed this.\nconst MAX_JSONL_LINE_CHARS = 64 * 1024 * 1024;\n\nexport function attachJsonlLineReader(stream: Readable, onLine: (line: string) => void): () => void {\n\tconst decoder = new StringDecoder(\"utf8\");\n\tlet buffer = \"\";\n\tlet discardingOversizedLine = false;\n\n\tconst emitLine = (line: string) => {\n\t\tonLine(line.endsWith(\"\\r\") ? line.slice(0, -1) : line);\n\t};\n\n\tconst onData = (chunk: string | Buffer) => {\n\t\tbuffer += typeof chunk === \"string\" ? chunk : decoder.write(chunk);\n\n\t\tif (discardingOversizedLine) {\n\t\t\tconst resumeIndex = buffer.indexOf(\"\\n\");\n\t\t\tif (resumeIndex === -1) {\n\t\t\t\tbuffer = \"\";\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tbuffer = buffer.slice(resumeIndex + 1);\n\t\t\tdiscardingOversizedLine = false;\n\t\t}\n\n\t\twhile (true) {\n\t\t\tconst newlineIndex = buffer.indexOf(\"\\n\");\n\t\t\tif (newlineIndex === -1) {\n\t\t\t\tif (buffer.length > MAX_JSONL_LINE_CHARS) {\n\t\t\t\t\tdiscardingOversizedLine = true;\n\t\t\t\t\tbuffer = \"\";\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\temitLine(buffer.slice(0, newlineIndex));\n\t\t\tbuffer = buffer.slice(newlineIndex + 1);\n\t\t}\n\t};\n\n\tconst onEnd = () => {\n\t\tbuffer += decoder.end();\n\t\tif (buffer.length > 0) {\n\t\t\temitLine(buffer);\n\t\t\tbuffer = \"\";\n\t\t}\n\t};\n\n\tstream.on(\"data\", onData);\n\tstream.on(\"end\", onEnd);\n\n\treturn () => {\n\t\tstream.off(\"data\", onData);\n\t\tstream.off(\"end\", onEnd);\n\t};\n}\n"]}
1
+ {"version":3,"file":"jsonl.js","sourceRoot":"","sources":["../../../src/modes/rpc/jsonl.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAEtE;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAc,EAAU;IACzD,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;AAAA,CACpC;AAED;;;;;;GAMG;AACH,2EAA2E;AAC3E,0EAA0E;AAC1E,MAAM,oBAAoB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAE9C,MAAM,UAAU,qBAAqB,CAAC,MAAgB,EAAE,MAA8B,EAAc;IACnG,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,IAAI,oBAAoB,CAAC,oBAAoB,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;IAEtG,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAAA,CACvD,CAAC;IAEF,MAAM,MAAM,GAAG,CAAC,KAAsB,EAAE,EAAE,CAAC;QAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YACzF,QAAQ,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC;IAAA,CACD,CAAC;IAEF,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC;QACnB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC7D,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QACjC,IAAI,SAAS,KAAK,SAAS;YAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAAA,CACjD,CAAC;IAEF,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1B,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAExB,OAAO,GAAG,EAAE,CAAC;QACZ,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC3B,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAAA,CACzB,CAAC;AAAA,CACF","sourcesContent":["import type { Readable } from \"node:stream\";\nimport { StringDecoder } from \"node:string_decoder\";\nimport { StreamingLineDecoder } from \"../../utils/streaming-lines.ts\";\n\n/**\n * Serialize a single strict JSONL record.\n *\n * Framing is LF-only. Payload strings may contain other Unicode separators such as\n * U+2028 and U+2029. Clients must split records on `\\n` only.\n */\nexport function serializeJsonLine(value: unknown): string {\n\treturn `${JSON.stringify(value)}\\n`;\n}\n\n/**\n * Attach an LF-only JSONL reader to a stream.\n *\n * This intentionally does not use Node readline. Readline splits on additional\n * Unicode separators that are valid inside JSON strings and therefore does not\n * implement strict JSONL framing.\n */\n// A non-compliant peer streaming without newlines would otherwise grow the\n// line buffer without bound; one line can never legitimately exceed this.\nconst MAX_JSONL_LINE_CHARS = 64 * 1024 * 1024;\n\nexport function attachJsonlLineReader(stream: Readable, onLine: (line: string) => void): () => void {\n\tconst decoder = new StringDecoder(\"utf8\");\n\tconst lines = new StreamingLineDecoder(MAX_JSONL_LINE_CHARS, { overflow: \"skip\", lineEndings: \"lf\" });\n\n\tconst emitLine = (line: string) => {\n\t\tonLine(line.endsWith(\"\\r\") ? line.slice(0, -1) : line);\n\t};\n\n\tconst onData = (chunk: string | Buffer) => {\n\t\tfor (const line of lines.push(typeof chunk === \"string\" ? chunk : decoder.write(chunk))) {\n\t\t\temitLine(line);\n\t\t}\n\t};\n\n\tconst onEnd = () => {\n\t\tfor (const line of lines.push(decoder.end())) emitLine(line);\n\t\tconst finalLine = lines.finish();\n\t\tif (finalLine !== undefined) emitLine(finalLine);\n\t};\n\n\tstream.on(\"data\", onData);\n\tstream.on(\"end\", onEnd);\n\n\treturn () => {\n\t\tstream.off(\"data\", onData);\n\t\tstream.off(\"end\", onEnd);\n\t};\n}\n"]}
@@ -0,0 +1,20 @@
1
+ /** Incremental line decoder that joins a fragmented line only once, when it completes. */
2
+ export declare class StreamingLineDecoder {
3
+ private readonly maxLineChars;
4
+ private readonly overflow;
5
+ private readonly lineEndings;
6
+ private parts;
7
+ private length;
8
+ private skipLeadingLf;
9
+ private skippingOversizedLine;
10
+ constructor(maxLineChars: number, options?: {
11
+ overflow?: "throw" | "skip";
12
+ lineEndings?: "lf" | "any";
13
+ });
14
+ push(text: string): string[];
15
+ finish(): string | undefined;
16
+ private append;
17
+ private takeLine;
18
+ private resetLine;
19
+ }
20
+ //# sourceMappingURL=streaming-lines.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming-lines.d.ts","sourceRoot":"","sources":["../../src/utils/streaming-lines.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,qBAAa,oBAAoB;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAe;IAC3C,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,qBAAqB,CAAS;IAEtC,YAAY,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,IAAI,GAAG,KAAK,CAAA;KAAE,EAItG;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAqB3B;IAED,MAAM,IAAI,MAAM,GAAG,SAAS,CAQ3B;IAED,OAAO,CAAC,MAAM;IAed,OAAO,CAAC,QAAQ;IAMhB,OAAO,CAAC,SAAS;CAKjB","sourcesContent":["/** Incremental line decoder that joins a fragmented line only once, when it completes. */\nexport class StreamingLineDecoder {\n\tprivate readonly maxLineChars: number;\n\tprivate readonly overflow: \"throw\" | \"skip\";\n\tprivate readonly lineEndings: \"lf\" | \"any\";\n\tprivate parts: string[] = [];\n\tprivate length = 0;\n\tprivate skipLeadingLf = false;\n\tprivate skippingOversizedLine = false;\n\n\tconstructor(maxLineChars: number, options?: { overflow?: \"throw\" | \"skip\"; lineEndings?: \"lf\" | \"any\" }) {\n\t\tthis.maxLineChars = maxLineChars;\n\t\tthis.overflow = options?.overflow ?? \"throw\";\n\t\tthis.lineEndings = options?.lineEndings ?? \"any\";\n\t}\n\n\tpush(text: string): string[] {\n\t\tconst lines: string[] = [];\n\t\tlet start = 0;\n\t\tif (this.skipLeadingLf) {\n\t\t\tthis.skipLeadingLf = false;\n\t\t\tif (text.startsWith(\"\\n\")) start = 1;\n\t\t}\n\t\tfor (let index = start; index < text.length; index++) {\n\t\t\tconst char = text[index];\n\t\t\tif (char !== \"\\n\" && (this.lineEndings === \"lf\" || char !== \"\\r\")) continue;\n\t\t\tthis.append(text.slice(start, index));\n\t\t\tif (this.skippingOversizedLine) this.resetLine();\n\t\t\telse lines.push(this.takeLine());\n\t\t\tif (char === \"\\r\") {\n\t\t\t\tif (text[index + 1] === \"\\n\") index++;\n\t\t\t\telse if (index + 1 === text.length) this.skipLeadingLf = true;\n\t\t\t}\n\t\t\tstart = index + 1;\n\t\t}\n\t\tthis.append(text.slice(start));\n\t\treturn lines;\n\t}\n\n\tfinish(): string | undefined {\n\t\tthis.skipLeadingLf = false;\n\t\tif (this.skippingOversizedLine) {\n\t\t\tthis.resetLine();\n\t\t\treturn undefined;\n\t\t}\n\t\tif (this.length === 0 && this.parts.length === 0) return undefined;\n\t\treturn this.takeLine();\n\t}\n\n\tprivate append(part: string): void {\n\t\tif (part.length === 0 || this.skippingOversizedLine) return;\n\t\tthis.length += part.length;\n\t\tif (this.length > this.maxLineChars) {\n\t\t\tif (this.overflow === \"throw\") {\n\t\t\t\tthrow new Error(`Stream exceeded the ${this.maxLineChars} character line limit`);\n\t\t\t}\n\t\t\tthis.parts = [];\n\t\t\tthis.length = 0;\n\t\t\tthis.skippingOversizedLine = true;\n\t\t\treturn;\n\t\t}\n\t\tthis.parts.push(part);\n\t}\n\n\tprivate takeLine(): string {\n\t\tconst line = this.parts.length === 0 ? \"\" : this.parts.length === 1 ? this.parts[0] : this.parts.join(\"\");\n\t\tthis.resetLine();\n\t\treturn line;\n\t}\n\n\tprivate resetLine(): void {\n\t\tthis.parts = [];\n\t\tthis.length = 0;\n\t\tthis.skippingOversizedLine = false;\n\t}\n}\n"]}
@@ -0,0 +1,79 @@
1
+ /** Incremental line decoder that joins a fragmented line only once, when it completes. */
2
+ export class StreamingLineDecoder {
3
+ maxLineChars;
4
+ overflow;
5
+ lineEndings;
6
+ parts = [];
7
+ length = 0;
8
+ skipLeadingLf = false;
9
+ skippingOversizedLine = false;
10
+ constructor(maxLineChars, options) {
11
+ this.maxLineChars = maxLineChars;
12
+ this.overflow = options?.overflow ?? "throw";
13
+ this.lineEndings = options?.lineEndings ?? "any";
14
+ }
15
+ push(text) {
16
+ const lines = [];
17
+ let start = 0;
18
+ if (this.skipLeadingLf) {
19
+ this.skipLeadingLf = false;
20
+ if (text.startsWith("\n"))
21
+ start = 1;
22
+ }
23
+ for (let index = start; index < text.length; index++) {
24
+ const char = text[index];
25
+ if (char !== "\n" && (this.lineEndings === "lf" || char !== "\r"))
26
+ continue;
27
+ this.append(text.slice(start, index));
28
+ if (this.skippingOversizedLine)
29
+ this.resetLine();
30
+ else
31
+ lines.push(this.takeLine());
32
+ if (char === "\r") {
33
+ if (text[index + 1] === "\n")
34
+ index++;
35
+ else if (index + 1 === text.length)
36
+ this.skipLeadingLf = true;
37
+ }
38
+ start = index + 1;
39
+ }
40
+ this.append(text.slice(start));
41
+ return lines;
42
+ }
43
+ finish() {
44
+ this.skipLeadingLf = false;
45
+ if (this.skippingOversizedLine) {
46
+ this.resetLine();
47
+ return undefined;
48
+ }
49
+ if (this.length === 0 && this.parts.length === 0)
50
+ return undefined;
51
+ return this.takeLine();
52
+ }
53
+ append(part) {
54
+ if (part.length === 0 || this.skippingOversizedLine)
55
+ return;
56
+ this.length += part.length;
57
+ if (this.length > this.maxLineChars) {
58
+ if (this.overflow === "throw") {
59
+ throw new Error(`Stream exceeded the ${this.maxLineChars} character line limit`);
60
+ }
61
+ this.parts = [];
62
+ this.length = 0;
63
+ this.skippingOversizedLine = true;
64
+ return;
65
+ }
66
+ this.parts.push(part);
67
+ }
68
+ takeLine() {
69
+ const line = this.parts.length === 0 ? "" : this.parts.length === 1 ? this.parts[0] : this.parts.join("");
70
+ this.resetLine();
71
+ return line;
72
+ }
73
+ resetLine() {
74
+ this.parts = [];
75
+ this.length = 0;
76
+ this.skippingOversizedLine = false;
77
+ }
78
+ }
79
+ //# sourceMappingURL=streaming-lines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming-lines.js","sourceRoot":"","sources":["../../src/utils/streaming-lines.ts"],"names":[],"mappings":"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","sourcesContent":["/** Incremental line decoder that joins a fragmented line only once, when it completes. */\nexport class StreamingLineDecoder {\n\tprivate readonly maxLineChars: number;\n\tprivate readonly overflow: \"throw\" | \"skip\";\n\tprivate readonly lineEndings: \"lf\" | \"any\";\n\tprivate parts: string[] = [];\n\tprivate length = 0;\n\tprivate skipLeadingLf = false;\n\tprivate skippingOversizedLine = false;\n\n\tconstructor(maxLineChars: number, options?: { overflow?: \"throw\" | \"skip\"; lineEndings?: \"lf\" | \"any\" }) {\n\t\tthis.maxLineChars = maxLineChars;\n\t\tthis.overflow = options?.overflow ?? \"throw\";\n\t\tthis.lineEndings = options?.lineEndings ?? \"any\";\n\t}\n\n\tpush(text: string): string[] {\n\t\tconst lines: string[] = [];\n\t\tlet start = 0;\n\t\tif (this.skipLeadingLf) {\n\t\t\tthis.skipLeadingLf = false;\n\t\t\tif (text.startsWith(\"\\n\")) start = 1;\n\t\t}\n\t\tfor (let index = start; index < text.length; index++) {\n\t\t\tconst char = text[index];\n\t\t\tif (char !== \"\\n\" && (this.lineEndings === \"lf\" || char !== \"\\r\")) continue;\n\t\t\tthis.append(text.slice(start, index));\n\t\t\tif (this.skippingOversizedLine) this.resetLine();\n\t\t\telse lines.push(this.takeLine());\n\t\t\tif (char === \"\\r\") {\n\t\t\t\tif (text[index + 1] === \"\\n\") index++;\n\t\t\t\telse if (index + 1 === text.length) this.skipLeadingLf = true;\n\t\t\t}\n\t\t\tstart = index + 1;\n\t\t}\n\t\tthis.append(text.slice(start));\n\t\treturn lines;\n\t}\n\n\tfinish(): string | undefined {\n\t\tthis.skipLeadingLf = false;\n\t\tif (this.skippingOversizedLine) {\n\t\t\tthis.resetLine();\n\t\t\treturn undefined;\n\t\t}\n\t\tif (this.length === 0 && this.parts.length === 0) return undefined;\n\t\treturn this.takeLine();\n\t}\n\n\tprivate append(part: string): void {\n\t\tif (part.length === 0 || this.skippingOversizedLine) return;\n\t\tthis.length += part.length;\n\t\tif (this.length > this.maxLineChars) {\n\t\t\tif (this.overflow === \"throw\") {\n\t\t\t\tthrow new Error(`Stream exceeded the ${this.maxLineChars} character line limit`);\n\t\t\t}\n\t\t\tthis.parts = [];\n\t\t\tthis.length = 0;\n\t\t\tthis.skippingOversizedLine = true;\n\t\t\treturn;\n\t\t}\n\t\tthis.parts.push(part);\n\t}\n\n\tprivate takeLine(): string {\n\t\tconst line = this.parts.length === 0 ? \"\" : this.parts.length === 1 ? this.parts[0] : this.parts.join(\"\");\n\t\tthis.resetLine();\n\t\treturn line;\n\t}\n\n\tprivate resetLine(): void {\n\t\tthis.parts = [];\n\t\tthis.length = 0;\n\t\tthis.skippingOversizedLine = false;\n\t}\n}\n"]}
@@ -202,6 +202,8 @@ Extensions are loaded via [jiti](https://github.com/unjs/jiti), so TypeScript wo
202
202
 
203
203
  If the factory returns a `Promise`, pi awaits it before continuing startup. That means async initialization completes before `session_start`, before `resources_discover`, and before provider registrations queued via `pi.registerProvider()` are flushed.
204
204
 
205
+ > **Confirmed lifecycle:** Use the factory for registrations and subscriptions. Methods that require a bound session runtime, such as `pi.sendMessage()`, `pi.sendUserMessage()`, `pi.appendEntry()`, and `pi.setActiveTools()`, must run from `session_start`, a command/tool handler, or another later event. If an eagerly loaded module or factory throws or rejects, pi reports the extension as a startup warning, discards its partial registrations and subscriptions, and continues with the remaining extensions. A failed `/reload` remains transactional and keeps the current working runtime.
206
+
205
207
  ### Async factory functions
206
208
 
207
209
  Use an async factory for one-time startup work such as fetching remote configuration or dynamically discovering available models.
package/docs/index.md CHANGED
@@ -53,7 +53,7 @@ For the full first-run flow, see [Quickstart](quickstart.md).
53
53
  - [Extensions](extensions.md) - TypeScript modules for tools, commands, events, and custom UI.
54
54
  - [Skills](skills.md) - Agent Skills for reusable on-demand capabilities.
55
55
  - [Resource profiles & library](resources.md) - curate extensions, skills, and agents per project or situation; share a catalog; install and back up.
56
- - [Self-adaptation](self-adaptation.md) - draft new skills and extensions from a session and make them live.
56
+ - [Self-adaptation](self-adaptation.md) - draft live skills/extensions and run evidence-backed Pi harness improvement loops.
57
57
  - [Prompt templates](prompt-templates.md) - reusable prompts that expand from slash commands.
58
58
  - [Themes](themes.md) - built-in and custom terminal themes.
59
59
  - [Pi packages](packages.md) - bundle and share extensions, skills, prompts, and themes.
@@ -11,6 +11,7 @@ This keeps a human on the edge of the loop: Pi proposes, you confirm, then it ac
11
11
  - [Skillify](#skillify)
12
12
  - [Extensionify](#extensionify)
13
13
  - [Learn](#learn)
14
+ - [Harness self-adaptation](#harness-self-adaptation)
14
15
  - [Duplicate detection](#duplicate-detection)
15
16
  - [Going live](#going-live)
16
17
 
@@ -57,6 +58,12 @@ Before anything is offered for activation, the candidate is **smoke-tested in is
57
58
 
58
59
  `/learn` orchestrates; it never writes or activates on its own. Long-term memory storage is handled outside Pi; `/learn` routes to it rather than implementing it.
59
60
 
61
+ ## Harness self-adaptation
62
+
63
+ For work on Pi itself, the bundled `harness-self-adaptation` skill keeps the active task primary and wraps it in a bounded improvement loop: define an observable oracle, capture a baseline or correctness invariant, diagnose the owning mechanism, choose the smallest enforcing layer, validate a focused intervention, then retain or roll it back. A task with no reusable evidence ends with no durable adaptation rather than a speculative change.
64
+
65
+ The skill treats tests, benchmarks, telemetry, and before/after measurements as retention evidence. It keeps code defects in their owning code, routes procedures to skills or prompts, and reserves extensions or core changes for behavior lower layers cannot enforce. It composes with `pi-harness-learning` for after-action capture and `skill-architect` for instruction authoring. Pi can load it when the task description matches, or you can force it with `/skill:harness-self-adaptation`.
66
+
60
67
  ## Duplicate detection
61
68
 
62
69
  The `skill_audit` tool guards against accumulating near-identical skills. Given a draft's name, description, and body, it scans your loaded skills and scores keyword overlap. Matches above the similarity threshold are flagged so you can **merge or refine** an existing skill instead of adding a redundant one.
package/docs/settings.md CHANGED
@@ -148,7 +148,11 @@ Fitness applicability is intentionally split by autonomy level:
148
148
 
149
149
  ### Worker Delegation
150
150
 
151
- Delegation is available by default when the active model and UAC tool surface support it. Ultra reinforces proactive use but does not own or unlock the capability. Each worker gets a fresh classified tool surface (`read`, `grep`, `find`, and `ls`); its shipped profile filters those names with the same glob semantics as foreground UAC. `delegate`, shell, memory/lifecycle tools, and opaque extension tools are never inherited into the child. Workers remain read-only unless the write toggle, a non-empty path scope, and the shipped profile all grant `write` or `edit`.
151
+ Delegation is available by default when the active model and UAC tool surface support it. Ultra reinforces proactive use but does not own or unlock the capability. Each worker gets a fresh classified tool surface (`read`, `grep`, `find`, and `ls`); its shipped profile filters those names with the same glob semantics as foreground UAC. `delegate`, shell, foreground memory/lifecycle tools, and opaque extension tools are never inherited into the child. The orchestrator may set `memoryRead: true` for a relevant task; if global memory retrieval remains enabled and the lane profile also grants `memory`, the worker receives a separate bounded query-only memory tool. Generic file tools cannot bypass that decision by reading private memory/auth/settings files. Memory writes remain unavailable. Workers are otherwise read-only unless the write toggle, a non-empty path scope, and the shipped profile all grant `write` or `edit`.
152
+
153
+ The worker model is provider-independent: when `workerDelegation.model` is unset it inherits the active model; an explicit pattern may select any authenticated, capability-eligible model, including subscription, API-key, or local providers. The isolated worker resolves auth and text-tool fallback from that selected model rather than inheriting the foreground model's protocol. Local workers that contend with a local foreground are queued and drained at the configured running concurrency. `delegate_status` preserves bounded non-JSON read-only results and labels output that ended at a provider limit as incomplete instead of discarding it as unparseable.
154
+
155
+ **Confirmed behavior:** `delegate` returns a lane id immediately instead of waiting for the worker. `delegate_status` shows queued, running, and terminal workers and retrieves bounded terminal output by lane id. Completion emits a session notification with the completed lane id and status; the interactive footer shows running/queued counts or the latest terminal lane. Late worker output is stored separately and is never injected into an active foreground transcript.
152
156
 
153
157
  Worker writes use **review-after-apply** semantics: a gate-authorized direct `write`/`edit` call or an envelope/path-validated structured action may mutate the scoped workspace before the parent reviews the result. The parent review is therefore a post-mutation acceptance step and receives changed files, blockers, the usage report id, and `parent_review_required` for an in-scope changed result. Denied or out-of-scope actions are refused before filesystem mutation; partial application is reported as `blocked`, never clean success.
154
158
 
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider",
3
- "version": "0.81.29",
3
+ "version": "0.81.30",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-custom-provider",
9
- "version": "0.81.29",
9
+ "version": "0.81.30",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sdk": "^0.52.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-anthropic",
3
3
  "private": true,
4
- "version": "0.81.29",
4
+ "version": "0.81.30",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-gitlab-duo",
3
3
  "private": true,
4
- "version": "0.81.29",
4
+ "version": "0.81.30",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-sandbox",
3
- "version": "0.81.29",
3
+ "version": "0.81.30",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-sandbox",
9
- "version": "0.81.29",
9
+ "version": "0.81.30",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sandbox-runtime": "^0.0.26"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-sandbox",
3
3
  "private": true,
4
- "version": "0.81.29",
4
+ "version": "0.81.30",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
- "version": "0.81.29",
3
+ "version": "0.81.30",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-with-deps",
9
- "version": "0.81.29",
9
+ "version": "0.81.30",
10
10
  "dependencies": {
11
11
  "ms": "^2.1.3"
12
12
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
3
  "private": true,
4
- "version": "0.81.29",
4
+ "version": "0.81.30",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@caupulican/pi-adaptative",
3
- "version": "0.81.29",
3
+ "version": "0.81.30",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@caupulican/pi-adaptative",
9
- "version": "0.81.29",
9
+ "version": "0.81.30",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "@caupulican/pi-agent-core": "^0.81.29",
13
- "@caupulican/pi-ai": "^0.81.29",
14
- "@caupulican/pi-tui": "^0.81.29",
12
+ "@caupulican/pi-agent-core": "^0.81.30",
13
+ "@caupulican/pi-ai": "^0.81.30",
14
+ "@caupulican/pi-tui": "^0.81.30",
15
15
  "@ff-labs/fff-node": "0.9.6",
16
16
  "@silvia-odwyer/photon-node": "0.3.4",
17
17
  "chalk": "5.6.2",
@@ -475,11 +475,11 @@
475
475
  }
476
476
  },
477
477
  "node_modules/@caupulican/pi-agent-core": {
478
- "version": "0.81.29",
479
- "resolved": "https://registry.npmjs.org/@caupulican/pi-agent-core/-/pi-agent-core-0.81.29.tgz",
478
+ "version": "0.81.30",
479
+ "resolved": "https://registry.npmjs.org/@caupulican/pi-agent-core/-/pi-agent-core-0.81.30.tgz",
480
480
  "license": "MIT",
481
481
  "dependencies": {
482
- "@caupulican/pi-ai": "^0.81.29",
482
+ "@caupulican/pi-ai": "^0.81.30",
483
483
  "ignore": "7.0.5",
484
484
  "typebox": "1.1.38",
485
485
  "yaml": "2.9.0"
@@ -489,8 +489,8 @@
489
489
  }
490
490
  },
491
491
  "node_modules/@caupulican/pi-ai": {
492
- "version": "0.81.29",
493
- "resolved": "https://registry.npmjs.org/@caupulican/pi-ai/-/pi-ai-0.81.29.tgz",
492
+ "version": "0.81.30",
493
+ "resolved": "https://registry.npmjs.org/@caupulican/pi-ai/-/pi-ai-0.81.30.tgz",
494
494
  "license": "MIT",
495
495
  "dependencies": {
496
496
  "@anthropic-ai/sdk": "0.91.1",
@@ -512,8 +512,8 @@
512
512
  }
513
513
  },
514
514
  "node_modules/@caupulican/pi-tui": {
515
- "version": "0.81.29",
516
- "resolved": "https://registry.npmjs.org/@caupulican/pi-tui/-/pi-tui-0.81.29.tgz",
515
+ "version": "0.81.30",
516
+ "resolved": "https://registry.npmjs.org/@caupulican/pi-tui/-/pi-tui-0.81.30.tgz",
517
517
  "license": "MIT",
518
518
  "dependencies": {
519
519
  "get-east-asian-width": "1.6.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caupulican/pi-adaptative",
3
- "version": "0.81.29",
3
+ "version": "0.81.30",
4
4
  "description": "Adaptive fork of Pi coding agent for self-evolving agent harness experiments",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -73,9 +73,9 @@
73
73
  "prepublishOnly": "npm run clean && npm run build && npm run shrinkwrap"
74
74
  },
75
75
  "dependencies": {
76
- "@caupulican/pi-agent-core": "^0.81.29",
77
- "@caupulican/pi-ai": "^0.81.29",
78
- "@caupulican/pi-tui": "^0.81.29",
76
+ "@caupulican/pi-agent-core": "^0.81.30",
77
+ "@caupulican/pi-ai": "^0.81.30",
78
+ "@caupulican/pi-tui": "^0.81.30",
79
79
  "@ff-labs/fff-node": "0.9.6",
80
80
  "@silvia-odwyer/photon-node": "0.3.4",
81
81
  "chalk": "5.6.2",