@xingular/harness 1.1.1 → 1.2.0

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 (223) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +28 -25
  3. package/dist/cli.js +6675 -2501
  4. package/dist/sdk/accounts/accounts.d.ts +27 -3
  5. package/dist/sdk/accounts/accounts.js +78 -24
  6. package/dist/sdk/accounts/secrets.d.ts +12 -0
  7. package/dist/sdk/accounts/secrets.js +114 -7
  8. package/dist/sdk/accounts/store.d.ts +26 -1
  9. package/dist/sdk/accounts/store.js +1 -1
  10. package/dist/sdk/agents/builtin.js +15 -1
  11. package/dist/sdk/agents/planResearch.d.ts +5 -0
  12. package/dist/sdk/agents/planResearch.js +19 -0
  13. package/dist/sdk/agents/profiles.d.ts +2 -1
  14. package/dist/sdk/agents/profiles.js +9 -4
  15. package/dist/sdk/annotations/pageScript.js +349 -48
  16. package/dist/sdk/annotations/part.js +34 -23
  17. package/dist/sdk/annotations/store.d.ts +7 -0
  18. package/dist/sdk/annotations/store.js +13 -5
  19. package/dist/sdk/browser/backend.d.ts +16 -0
  20. package/dist/sdk/browser/backend.js +17 -0
  21. package/dist/sdk/browser/contracts.d.ts +19 -0
  22. package/dist/sdk/browser/contracts.js +116 -0
  23. package/dist/sdk/browser/tools.d.ts +1 -4
  24. package/dist/sdk/browser/tools.js +14 -91
  25. package/dist/sdk/cli.js +5 -4
  26. package/dist/sdk/commands/list.d.ts +3 -0
  27. package/dist/sdk/commands/list.js +75 -0
  28. package/dist/sdk/commands/registry.d.ts +250 -0
  29. package/dist/sdk/commands/registry.js +47 -0
  30. package/dist/sdk/commands/routes.d.ts +16 -0
  31. package/dist/sdk/commands/routes.js +33 -0
  32. package/dist/sdk/core/commandBudget.d.ts +23 -0
  33. package/dist/sdk/core/commandBudget.js +57 -0
  34. package/dist/sdk/core/index.js +17 -1
  35. package/dist/sdk/core/interactiveProfile.d.ts +46 -0
  36. package/dist/sdk/core/interactiveProfile.js +143 -0
  37. package/dist/sdk/core/workspace.d.ts +13 -0
  38. package/dist/sdk/core/workspace.js +88 -0
  39. package/dist/sdk/core/workspaceBashTool.d.ts +4 -0
  40. package/dist/sdk/core/workspaceBashTool.js +36 -0
  41. package/dist/sdk/core/workspaceSandbox.d.ts +31 -0
  42. package/dist/sdk/core/workspaceSandbox.js +320 -0
  43. package/dist/sdk/core/workspaceWriteOperations.d.ts +22 -0
  44. package/dist/sdk/core/workspaceWriteOperations.js +206 -0
  45. package/dist/sdk/doctor/types.d.ts +2 -2
  46. package/dist/sdk/harness.d.ts +7 -0
  47. package/dist/sdk/harness.js +42 -2
  48. package/dist/sdk/index.d.ts +6 -1
  49. package/dist/sdk/index.js +3 -0
  50. package/dist/sdk/pi/runtime.d.ts +2 -1
  51. package/dist/sdk/pi/runtime.js +2 -2
  52. package/dist/sdk/plugins/builtin.js +29 -12
  53. package/dist/sdk/plugins/builtinRegistry.d.ts +10 -3
  54. package/dist/sdk/plugins/builtinRegistry.js +30 -8
  55. package/dist/sdk/plugins/catalogue.js +2 -1
  56. package/dist/sdk/plugins/commandPrefix.d.ts +8 -0
  57. package/dist/sdk/plugins/commandPrefix.js +21 -0
  58. package/dist/sdk/plugins/firstParty.d.ts +1 -1
  59. package/dist/sdk/plugins/firstParty.js +8 -2
  60. package/dist/sdk/plugins/inventory.js +4 -3
  61. package/dist/sdk/plugins/manifest.d.ts +2 -0
  62. package/dist/sdk/plugins/manifest.js +2 -1
  63. package/dist/sdk/plugins/surfaces.d.ts +5 -0
  64. package/dist/sdk/plugins/surfaces.js +11 -0
  65. package/dist/sdk/plugins/types.d.ts +15 -0
  66. package/dist/sdk/prompt/compile.d.ts +14 -0
  67. package/dist/sdk/prompt/compile.js +65 -29
  68. package/dist/sdk/prompt/standard.d.ts +17 -0
  69. package/dist/sdk/prompt/standard.js +21 -0
  70. package/dist/sdk/server/methods.js +18 -0
  71. package/dist/sdk/server/remote.js +36 -11
  72. package/dist/sdk/sessions/compactionCheckpoint.d.ts +11 -0
  73. package/dist/sdk/sessions/compactionCheckpoint.js +79 -0
  74. package/dist/sdk/sessions/continuation.d.ts +3 -0
  75. package/dist/sdk/sessions/continuation.js +5 -1
  76. package/dist/sdk/sessions/contracts.d.ts +168 -0
  77. package/dist/sdk/sessions/contracts.js +59 -1
  78. package/dist/sdk/sessions/control.d.ts +72 -0
  79. package/dist/sdk/sessions/control.js +158 -0
  80. package/dist/sdk/sessions/initialBash.d.ts +7 -0
  81. package/dist/sdk/sessions/initialBash.js +7 -0
  82. package/dist/sdk/sessions/planMode.d.ts +14 -3
  83. package/dist/sdk/sessions/planMode.js +73 -16
  84. package/dist/sdk/sessions/registry.d.ts +1 -1
  85. package/dist/sdk/sessions/registry.js +2 -2
  86. package/dist/sdk/sessions/runStore.d.ts +14 -0
  87. package/dist/sdk/sessions/runStore.js +35 -0
  88. package/dist/sdk/sessions/runner.d.ts +40 -2
  89. package/dist/sdk/sessions/runner.js +161 -13
  90. package/dist/sdk/sessions/sessions.d.ts +23 -3
  91. package/dist/sdk/sessions/sessions.js +202 -17
  92. package/dist/sdk/sessions/subagentService.d.ts +9 -0
  93. package/dist/sdk/sessions/subagentService.js +63 -4
  94. package/dist/sdk/sessions/workSlice.d.ts +103 -0
  95. package/dist/sdk/sessions/workSlice.js +297 -0
  96. package/dist/sdk/sessions/workspaceBoundary.d.ts +15 -0
  97. package/dist/sdk/sessions/workspaceBoundary.js +46 -0
  98. package/dist/sdk/terminal/browserControl.js +2 -1
  99. package/dist/sdk/terminal/controller.d.ts +11 -3
  100. package/dist/sdk/terminal/controller.js +40 -13
  101. package/dist/sdk/terminal/opentui/theme.d.ts +43 -0
  102. package/dist/sdk/terminal/opentui/theme.js +87 -0
  103. package/dist/sdk/terminal/piExtension.d.ts +6 -1
  104. package/dist/sdk/terminal/piExtension.js +154 -54
  105. package/dist/sdk/terminal/standalone.d.ts +7 -0
  106. package/dist/sdk/terminal/standalone.js +72 -13
  107. package/dist/sdk/terminal/subagentMonitor.d.ts +11 -2
  108. package/dist/sdk/terminal/subagentMonitor.js +32 -1
  109. package/dist/sdk/terminal/terminals.d.ts +19 -2
  110. package/dist/sdk/terminal/terminals.js +245 -35
  111. package/dist/sdk/terminal/tui/annotateCommand.d.ts +1 -1
  112. package/dist/sdk/terminal/tui/annotateCommand.js +3 -3
  113. package/dist/sdk/terminal/tui/commandPages.d.ts +3 -1
  114. package/dist/sdk/terminal/tui/commandPages.js +3 -0
  115. package/dist/sdk/terminal/tui/commands.d.ts +2 -0
  116. package/dist/sdk/terminal/tui/commands.js +205 -124
  117. package/dist/sdk/terminal/tui/list.d.ts +14 -1
  118. package/dist/sdk/terminal/tui/list.js +96 -14
  119. package/dist/sdk/terminal/tui/pageOverlay.js +13 -4
  120. package/dist/sdk/terminal/tui/pages/annotatePage.d.ts +1 -1
  121. package/dist/sdk/terminal/tui/pages/notesPage.d.ts +5 -5
  122. package/dist/sdk/terminal/tui/pages/notesPage.js +18 -18
  123. package/dist/sdk/terminal/tui/pages/pluginsPage.d.ts +0 -5
  124. package/dist/sdk/terminal/tui/pages/pluginsPage.js +9 -3
  125. package/dist/sdk/terminal/tui/pages/subagentsPage.d.ts +1 -0
  126. package/dist/sdk/terminal/tui/pages/subagentsPage.js +98 -16
  127. package/dist/sdk/terminal/tui/pages/usagePage.d.ts +43 -0
  128. package/dist/sdk/terminal/tui/pages/usagePage.js +370 -0
  129. package/dist/sdk/terminal/tui/piAdapter.d.ts +1 -2
  130. package/dist/sdk/terminal/tui/piAdapter.js +3 -5
  131. package/dist/sdk/terminal/tui/pluginCommands.d.ts +2 -0
  132. package/dist/sdk/terminal/tui/pluginCommands.js +13 -9
  133. package/dist/sdk/terminal/tui/runtime.js +23 -3
  134. package/dist/sdk/terminal/tui/sessionPicker.d.ts +40 -0
  135. package/dist/sdk/terminal/tui/sessionPicker.js +141 -0
  136. package/dist/sdk/tools/checklist.js +1 -0
  137. package/dist/sdk/tools/checkpoint.d.ts +27 -0
  138. package/dist/sdk/tools/checkpoint.js +154 -0
  139. package/dist/sdk/tools/getCapabilities.d.ts +31 -0
  140. package/dist/sdk/tools/getCapabilities.js +34 -0
  141. package/dist/sdk/tools/spawnSubagent.js +4 -3
  142. package/dist/sdk/usage/analytics.d.ts +20 -0
  143. package/dist/sdk/usage/analytics.js +151 -0
  144. package/dist/sdk/usage/ledger.d.ts +38 -0
  145. package/dist/sdk/usage/ledger.js +142 -0
  146. package/dist/sdk/usage/limits/adapters.d.ts +11 -0
  147. package/dist/sdk/usage/limits/adapters.js +349 -0
  148. package/dist/sdk/usage/limits/capture.d.ts +8 -0
  149. package/dist/sdk/usage/limits/capture.js +47 -0
  150. package/dist/sdk/usage/limits/http.d.ts +12 -0
  151. package/dist/sdk/usage/limits/http.js +51 -0
  152. package/dist/sdk/usage/limits/normalize.d.ts +15 -0
  153. package/dist/sdk/usage/limits/normalize.js +211 -0
  154. package/dist/sdk/usage/limits/service.d.ts +30 -0
  155. package/dist/sdk/usage/limits/service.js +176 -0
  156. package/dist/sdk/usage/limits/types.d.ts +65 -0
  157. package/dist/sdk/usage/limits/types.js +1 -0
  158. package/dist/sdk/usage/serverMethods.d.ts +3 -0
  159. package/dist/sdk/usage/serverMethods.js +22 -0
  160. package/dist/sdk/usage/service.d.ts +32 -0
  161. package/dist/sdk/usage/service.js +66 -0
  162. package/dist/sdk/usage/settings.d.ts +7 -0
  163. package/dist/sdk/usage/settings.js +28 -0
  164. package/dist/sdk/usage/types.d.ts +60 -0
  165. package/dist/sdk/usage/types.js +4 -0
  166. package/dist/terminal-opentui.js +5207 -1883
  167. package/dist/terminal-pi.js +1658 -271
  168. package/docs/architecture/02-sessions-and-runs.md +128 -26
  169. package/docs/architecture/04-prompt.md +50 -12
  170. package/docs/architecture/06-plugins-and-capabilities.md +24 -7
  171. package/docs/architecture/07-tools-and-gate.md +104 -24
  172. package/docs/architecture/08-memory-and-history.md +4 -2
  173. package/docs/architecture/09-accounts-and-connectors.md +31 -1
  174. package/docs/architecture/10-server-protocol.md +58 -3
  175. package/docs/architecture/11-terminal.md +105 -42
  176. package/docs/architecture/12-storage.md +30 -2
  177. package/docs/architecture/13-world-tools.md +22 -1
  178. package/docs/architecture/14-surfaces-and-parity.md +54 -7
  179. package/docs/architecture/README.md +3 -1
  180. package/docs/architecture/proposals/PROP-0017-page-annotations.md +6 -2
  181. package/docs/architecture/proposals/PROP-0018-annotation-queue-and-app-targets.md +1 -1
  182. package/docs/architecture/proposals/PROP-0031-plugin-command-owner-namespaces.md +54 -0
  183. package/docs/architecture/proposals/PROP-0032-planning-quality.md +196 -0
  184. package/docs/architecture/proposals/PROP-0033-compaction-plan-checkpoints.md +75 -0
  185. package/docs/architecture/proposals/PROP-0034-conversation-fast-mode.md +120 -0
  186. package/docs/architecture/proposals/PROP-0035-retain-subagent-status.md +47 -0
  187. package/docs/architecture/proposals/PROP-0036-first-class-harness-commands.md +59 -0
  188. package/docs/architecture/proposals/PROP-0037-workspace-write-boundary.md +63 -0
  189. package/docs/architecture/proposals/PROP-0038-annotate-open-shadow-roots.md +73 -0
  190. package/docs/architecture/proposals/PROP-0039-workspace-boundary-hardening.md +139 -0
  191. package/docs/architecture/proposals/PROP-0040-one-launch-path.md +87 -0
  192. package/docs/architecture/proposals/PROP-0041-bounded-work-slices.md +247 -0
  193. package/docs/architecture/proposals/PROP-0042-usage-and-provider-limits.md +127 -0
  194. package/docs/architecture/proposals/PROP-0043-read-only-plan-bash.md +74 -0
  195. package/docs/architecture/proposals/README.md +14 -0
  196. package/docs/decisions/ADR-0001-owned-terminal.md +1 -1
  197. package/docs/decisions/ADR-0021-required-command-namespaces.md +1 -1
  198. package/docs/decisions/ADR-0031-plugin-command-owner-namespaces.md +37 -0
  199. package/docs/decisions/ADR-0032-compaction-run-checkpoints.md +33 -0
  200. package/docs/decisions/ADR-0033-plan-mode-research-delegation.md +47 -0
  201. package/docs/decisions/ADR-0034-first-class-harness-terminal-commands.md +25 -0
  202. package/docs/decisions/ADR-0035-one-launch-path.md +40 -0
  203. package/docs/decisions/ADR-0036-workspace-write-operation-boundary.md +54 -0
  204. package/docs/decisions/ADR-0037-usage-ledger-and-provider-limits.md +44 -0
  205. package/docs/decisions/ADR-0038-plan-bash-os-read-only.md +29 -0
  206. package/docs/experiments/EXP-0003-performance-audit/data/session-runtime-replication.json +420 -0
  207. package/docs/experiments/EXP-0003-performance-audit/data/session-runtime.json +420 -0
  208. package/docs/experiments/EXP-0003-performance-audit/data/terminal-compact.json +376 -0
  209. package/docs/experiments/EXP-0003-performance-audit/data/terminal-history.json +422 -0
  210. package/docs/experiments/EXP-0003-performance-audit/data/terminal-question.json +95 -0
  211. package/docs/experiments/EXP-0003-performance-audit/data/terminal-wide.json +1036 -0
  212. package/docs/experiments/EXP-0003-performance-audit/plan.md +109 -0
  213. package/docs/experiments/EXP-0003-performance-audit/results.md +151 -0
  214. package/docs/handoff-2026-10-25-app-parity-and-solo-tabs.md +202 -0
  215. package/docs/parity.md +80 -24
  216. package/docs/releases/1.1.1.md +28 -0
  217. package/docs/releases/1.2.0.md +49 -0
  218. package/docs/releases/4.0.0.md +10 -9
  219. package/docs/releases/README.md +35 -30
  220. package/docs/study/00-index.md +3 -0
  221. package/docs/study/STUDY-0003-long-horizon-runs.md +210 -0
  222. package/docs/terminal-tui.md +100 -59
  223. package/package.json +4 -3
@@ -0,0 +1,79 @@
1
+ import { renderCompactionCheckpoint } from "../prompt/compile.js";
2
+ import { CHECKLIST_WRITE } from "../tools/checklist.js";
3
+ import { checklistItemSchema, MAX_CHECKLIST_ITEMS } from "./contracts.js";
4
+ export const COMPACTION_CHECKPOINT_EXTENSION = 'compaction-checkpoint';
5
+ function validatedChecklist(value) {
6
+ if (!Array.isArray(value) || value.length > MAX_CHECKLIST_ITEMS)
7
+ return null;
8
+ const items = [];
9
+ for (const valueItem of value) {
10
+ const item = valueItem;
11
+ const parsed = checklistItemSchema.safeParse({
12
+ text: typeof item?.text === 'string' ? item.text.trim() : item?.text,
13
+ status: item?.status
14
+ });
15
+ if (!parsed.success)
16
+ return null;
17
+ items.push(parsed.data);
18
+ }
19
+ return items;
20
+ }
21
+ /** Adds only the active run's explicit state to requests made after a compaction. */
22
+ export function compactionCheckpoint(options = {}) {
23
+ return (pi) => {
24
+ let goal = '';
25
+ let checklist = validatedChecklist(options.initialChecklist ?? []) ?? [];
26
+ let lastCompactionKey = null;
27
+ let compacted = false;
28
+ const reset = () => {
29
+ goal = '';
30
+ checklist = validatedChecklist(options.initialChecklist ?? []) ?? [];
31
+ lastCompactionKey = null;
32
+ compacted = false;
33
+ };
34
+ pi.on('before_agent_start', (event) => {
35
+ if (event.messageType !== 'user')
36
+ return;
37
+ goal = event.prompt;
38
+ checklist = validatedChecklist(options.initialChecklist ?? []) ?? [];
39
+ lastCompactionKey = null;
40
+ compacted = false;
41
+ });
42
+ pi.on('tool_result', (event) => {
43
+ if (event.toolName !== CHECKLIST_WRITE || event.isError)
44
+ return;
45
+ const items = validatedChecklist(event.input.items);
46
+ if (items)
47
+ checklist = items;
48
+ });
49
+ pi.on('context', (event) => {
50
+ const summary = event.messages.findLast((message) => message.role === 'compactionSummary');
51
+ const compactionKey = summary ? `${summary.timestamp}:${summary.tokensBefore}` : null;
52
+ const planInstructions = options.planInstructions?.() ?? null;
53
+ if (compactionKey && compactionKey !== lastCompactionKey) {
54
+ lastCompactionKey = compactionKey;
55
+ compacted = true;
56
+ }
57
+ else if (!compactionKey) {
58
+ lastCompactionKey = null;
59
+ compacted = false;
60
+ }
61
+ if (!compacted)
62
+ return;
63
+ const content = renderCompactionCheckpoint({ goal, checklist, planInstructions });
64
+ if (!content)
65
+ return;
66
+ return {
67
+ messages: [...event.messages, {
68
+ role: 'custom',
69
+ customType: COMPACTION_CHECKPOINT_EXTENSION,
70
+ content,
71
+ display: false,
72
+ timestamp: Date.now()
73
+ }]
74
+ };
75
+ });
76
+ pi.on('agent_settled', reset);
77
+ pi.on('session_tree', reset);
78
+ };
79
+ }
@@ -1,5 +1,6 @@
1
1
  import type { CapabilitySet } from "../capabilities/types.js";
2
2
  import type { HostSection } from "../prompt/compile.js";
3
+ import type { Checkpoint } from "./contracts.js";
3
4
  import { type ChecklistItem } from "./contracts.js";
4
5
  import { type PendingDecision } from "./runStore.js";
5
6
  export declare const CONTINUATION_SECTION_ID = "continuation";
@@ -28,6 +29,8 @@ export interface Continuation {
28
29
  stoppedAt: string | null;
29
30
  terminalReason: string | null;
30
31
  checklist: ChecklistItem[];
32
+ /** The last work-slice handoff, when the run wrote one (PROP-0041). */
33
+ checkpoint: Checkpoint | null;
31
34
  pending: PendingDecision[];
32
35
  /** The last tool the run started, and whether it finished. */
33
36
  lastTool: {
@@ -3,6 +3,7 @@
3
3
  // run with `continueFrom`, tells the model where the earlier one stopped.
4
4
  import { loadRun as loadCapabilities } from "../capabilities/runSnapshot.js";
5
5
  import { checklistOf, describeChecklist } from "../tools/checklist.js";
6
+ import { checkpointOf, describeCheckpoint } from "../tools/checkpoint.js";
6
7
  import { isActiveStatus } from "./contracts.js";
7
8
  import { findHistory } from "./history.js";
8
9
  import { findRun, pendingDecisions, readEvents, recordedSubagents } from "./runStore.js";
@@ -17,7 +18,7 @@ const CONTINUATION_BUDGET = 2000;
17
18
  export function continuationOf(root, runId, sessionDir) {
18
19
  const record = findRun(root, runId);
19
20
  if (!record) {
20
- return { runId, sessionId: '', status: 'missing', resumable: false, reason: 'not_found', resume: null, accountId: null, variant: null, capabilities: null, stoppedAt: null, terminalReason: null, checklist: [], pending: [], lastTool: null, unfinishedSubagents: [] };
21
+ return { runId, sessionId: '', status: 'missing', resumable: false, reason: 'not_found', resume: null, accountId: null, variant: null, capabilities: null, stoppedAt: null, terminalReason: null, checklist: [], checkpoint: null, pending: [], lastTool: null, unfinishedSubagents: [] };
21
22
  }
22
23
  const events = readEvents(root, runId);
23
24
  const started = events.filter((event) => event.type === 'tool.started').at(-1);
@@ -46,6 +47,7 @@ export function continuationOf(root, runId, sessionDir) {
46
47
  stoppedAt: record.endedAt,
47
48
  terminalReason: record.terminalReason,
48
49
  checklist: checklistOf(events),
50
+ checkpoint: checkpointOf(events),
49
51
  pending: pendingDecisions(events),
50
52
  lastTool,
51
53
  unfinishedSubagents: recordedSubagents(root, runId).filter((id) => {
@@ -69,6 +71,8 @@ export function continuationBody(continuation) {
69
71
  ];
70
72
  if (continuation.lastTool)
71
73
  lines.push(continuation.lastTool.finished ? `Its last tool call, ${continuation.lastTool.name}, finished.` : `Its last tool call, ${continuation.lastTool.name}, did not finish; its effect is unknown.`);
74
+ if (continuation.checkpoint)
75
+ lines.push('', 'The handoff it wrote when it stopped:', describeCheckpoint(continuation.checkpoint));
72
76
  if (continuation.checklist.length)
73
77
  lines.push('', 'Its checklist when it stopped:', describeChecklist(continuation.checklist));
74
78
  if (continuation.pending.length)
@@ -31,6 +31,8 @@ export declare const runEventTypeSchema: z.ZodEnum<{
31
31
  "reaction.added": "reaction.added";
32
32
  "agent.message": "agent.message";
33
33
  "checklist.updated": "checklist.updated";
34
+ checkpoint: "checkpoint";
35
+ heartbeat: "heartbeat";
34
36
  "artifact.added": "artifact.added";
35
37
  "file.changed": "file.changed";
36
38
  "usage.updated": "usage.updated";
@@ -76,6 +78,73 @@ export declare const checklistItemSchema: z.ZodObject<{
76
78
  }, z.core.$strict>;
77
79
  export type ChecklistItem = z.infer<typeof checklistItemSchema>;
78
80
  export declare const MAX_CHECKLIST_ITEMS = 50;
81
+ export declare const MAX_CHECKPOINT_SUMMARY = 1200;
82
+ export declare const MAX_CHECKPOINT_DONE = 20;
83
+ export declare const MAX_CHECKPOINT_EVIDENCE = 5;
84
+ export declare const MAX_CHECKPOINT_FILES = 20;
85
+ export declare const MAX_CHECKPOINT_CHECKS = 8;
86
+ export declare const MAX_CHECKPOINT_DECISIONS = 8;
87
+ /**
88
+ * The handoff a reply writes when it reaches its work-slice budget. The harness validates and
89
+ * records it; the next slice is told where this one stopped from it (PROP-0041).
90
+ */
91
+ export declare const checkpointItemSchema: z.ZodObject<{
92
+ item: z.ZodString;
93
+ evidence: z.ZodDefault<z.ZodArray<z.ZodString>>;
94
+ }, z.core.$strict>;
95
+ export declare const checkpointFileSchema: z.ZodObject<{
96
+ path: z.ZodString;
97
+ why: z.ZodDefault<z.ZodString>;
98
+ }, z.core.$strict>;
99
+ export declare const checkpointCheckSchema: z.ZodObject<{
100
+ command: z.ZodString;
101
+ ok: z.ZodBoolean;
102
+ detail: z.ZodOptional<z.ZodString>;
103
+ }, z.core.$strict>;
104
+ export declare const checkpointDecisionSchema: z.ZodObject<{
105
+ what: z.ZodString;
106
+ why: z.ZodDefault<z.ZodString>;
107
+ }, z.core.$strict>;
108
+ export declare const checkpointReasonSchema: z.ZodEnum<{
109
+ budget: "budget";
110
+ stuck: "stuck";
111
+ "compaction-thrash": "compaction-thrash";
112
+ requested: "requested";
113
+ }>;
114
+ declare const checkpointPayload: z.ZodObject<{
115
+ summary: z.ZodString;
116
+ done: z.ZodDefault<z.ZodArray<z.ZodObject<{
117
+ item: z.ZodString;
118
+ evidence: z.ZodDefault<z.ZodArray<z.ZodString>>;
119
+ }, z.core.$strict>>>;
120
+ next: z.ZodDefault<z.ZodString>;
121
+ blocked: z.ZodOptional<z.ZodString>;
122
+ files: z.ZodDefault<z.ZodArray<z.ZodObject<{
123
+ path: z.ZodString;
124
+ why: z.ZodDefault<z.ZodString>;
125
+ }, z.core.$strict>>>;
126
+ checks: z.ZodDefault<z.ZodArray<z.ZodObject<{
127
+ command: z.ZodString;
128
+ ok: z.ZodBoolean;
129
+ detail: z.ZodOptional<z.ZodString>;
130
+ }, z.core.$strict>>>;
131
+ decisions: z.ZodDefault<z.ZodArray<z.ZodObject<{
132
+ what: z.ZodString;
133
+ why: z.ZodDefault<z.ZodString>;
134
+ }, z.core.$strict>>>;
135
+ slice: z.ZodNumber;
136
+ reason: z.ZodEnum<{
137
+ budget: "budget";
138
+ stuck: "stuck";
139
+ "compaction-thrash": "compaction-thrash";
140
+ requested: "requested";
141
+ }>;
142
+ }, z.core.$strict>;
143
+ export type Checkpoint = z.infer<typeof checkpointPayload>;
144
+ export type CheckpointItem = z.infer<typeof checkpointItemSchema>;
145
+ export type CheckpointFile = z.infer<typeof checkpointFileSchema>;
146
+ export type CheckpointCheck = z.infer<typeof checkpointCheckSchema>;
147
+ export type CheckpointDecision = z.infer<typeof checkpointDecisionSchema>;
79
148
  /** Where a cost figure comes from: Pi reported it, or the tokens were priced at list rates. */
80
149
  export declare const costSourceSchema: z.ZodEnum<{
81
150
  harness: "harness";
@@ -157,9 +226,37 @@ export declare const accountLimitSchema: z.ZodObject<{
157
226
  id: z.ZodString;
158
227
  label: z.ZodString;
159
228
  usedPercent: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
229
+ remainingPercent: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
160
230
  resetsAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
161
231
  windowMinutes: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
162
232
  status: z.ZodOptional<z.ZodNullable<z.ZodString>>;
233
+ provider: z.ZodOptional<z.ZodNullable<z.ZodString>>;
234
+ kind: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
235
+ error: "error";
236
+ window: "window";
237
+ rate: "rate";
238
+ credit: "credit";
239
+ configured: "configured";
240
+ }>>>;
241
+ unit: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
242
+ requests: "requests";
243
+ percent: "percent";
244
+ tokens: "tokens";
245
+ usd: "usd";
246
+ currency: "currency";
247
+ count: "count";
248
+ }>>>;
249
+ used: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
250
+ limit: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
251
+ remaining: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
252
+ source: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
253
+ error: "error";
254
+ headers: "headers";
255
+ estimate: "estimate";
256
+ provider: "provider";
257
+ }>>>;
258
+ observedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
259
+ detail: z.ZodOptional<z.ZodNullable<z.ZodString>>;
163
260
  }, z.core.$strip>;
164
261
  export type AccountLimit = z.infer<typeof accountLimitSchema>;
165
262
  /** Payload schema per discriminant. */
@@ -345,6 +442,43 @@ export declare const runEventPayloadSchemas: {
345
442
  }>;
346
443
  }, z.core.$strict>>;
347
444
  }, z.core.$strict>;
445
+ checkpoint: z.ZodObject<{
446
+ summary: z.ZodString;
447
+ done: z.ZodDefault<z.ZodArray<z.ZodObject<{
448
+ item: z.ZodString;
449
+ evidence: z.ZodDefault<z.ZodArray<z.ZodString>>;
450
+ }, z.core.$strict>>>;
451
+ next: z.ZodDefault<z.ZodString>;
452
+ blocked: z.ZodOptional<z.ZodString>;
453
+ files: z.ZodDefault<z.ZodArray<z.ZodObject<{
454
+ path: z.ZodString;
455
+ why: z.ZodDefault<z.ZodString>;
456
+ }, z.core.$strict>>>;
457
+ checks: z.ZodDefault<z.ZodArray<z.ZodObject<{
458
+ command: z.ZodString;
459
+ ok: z.ZodBoolean;
460
+ detail: z.ZodOptional<z.ZodString>;
461
+ }, z.core.$strict>>>;
462
+ decisions: z.ZodDefault<z.ZodArray<z.ZodObject<{
463
+ what: z.ZodString;
464
+ why: z.ZodDefault<z.ZodString>;
465
+ }, z.core.$strict>>>;
466
+ slice: z.ZodNumber;
467
+ reason: z.ZodEnum<{
468
+ budget: "budget";
469
+ stuck: "stuck";
470
+ "compaction-thrash": "compaction-thrash";
471
+ requested: "requested";
472
+ }>;
473
+ }, z.core.$strict>;
474
+ heartbeat: z.ZodObject<{
475
+ steps: z.ZodNumber;
476
+ elapsedMs: z.ZodNumber;
477
+ lastTool: z.ZodNullable<z.ZodString>;
478
+ compactions: z.ZodNumber;
479
+ slice: z.ZodNumber;
480
+ maxToolCalls: z.ZodNumber;
481
+ }, z.core.$strict>;
348
482
  'artifact.added': z.ZodObject<{
349
483
  artifactId: z.ZodString;
350
484
  name: z.ZodString;
@@ -412,9 +546,37 @@ export declare const runEventPayloadSchemas: {
412
546
  id: z.ZodString;
413
547
  label: z.ZodString;
414
548
  usedPercent: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
549
+ remainingPercent: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
415
550
  resetsAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
416
551
  windowMinutes: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
417
552
  status: z.ZodOptional<z.ZodNullable<z.ZodString>>;
553
+ provider: z.ZodOptional<z.ZodNullable<z.ZodString>>;
554
+ kind: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
555
+ error: "error";
556
+ window: "window";
557
+ rate: "rate";
558
+ credit: "credit";
559
+ configured: "configured";
560
+ }>>>;
561
+ unit: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
562
+ requests: "requests";
563
+ percent: "percent";
564
+ tokens: "tokens";
565
+ usd: "usd";
566
+ currency: "currency";
567
+ count: "count";
568
+ }>>>;
569
+ used: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
570
+ limit: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
571
+ remaining: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
572
+ source: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
573
+ error: "error";
574
+ headers: "headers";
575
+ estimate: "estimate";
576
+ provider: "provider";
577
+ }>>>;
578
+ observedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
579
+ detail: z.ZodOptional<z.ZodNullable<z.ZodString>>;
418
580
  }, z.core.$strip>>>;
419
581
  }, z.core.$strip>;
420
582
  'status.changed': z.ZodObject<{
@@ -463,6 +625,8 @@ export declare const runEventSchema: z.ZodObject<{
463
625
  "reaction.added": "reaction.added";
464
626
  "agent.message": "agent.message";
465
627
  "checklist.updated": "checklist.updated";
628
+ checkpoint: "checkpoint";
629
+ heartbeat: "heartbeat";
466
630
  "artifact.added": "artifact.added";
467
631
  "file.changed": "file.changed";
468
632
  "usage.updated": "usage.updated";
@@ -494,6 +658,8 @@ export interface RunRecord {
494
658
  sessionId: string;
495
659
  nativeSessionId: string | null;
496
660
  workingDirectory: string | null;
661
+ /** Canonical filesystem root whose writes this run may make by default. */
662
+ workspaceRoot?: string | null;
497
663
  worktreeId: string | null;
498
664
  goal: string | null;
499
665
  attachmentCount: number;
@@ -529,6 +695,7 @@ export declare const runRecordSchema: z.ZodObject<{
529
695
  sessionId: z.ZodString;
530
696
  nativeSessionId: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>;
531
697
  workingDirectory: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>;
698
+ workspaceRoot: z.ZodOptional<z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>>;
532
699
  worktreeId: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>;
533
700
  goal: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>;
534
701
  attachmentCount: z.ZodDefault<z.ZodNumber>;
@@ -549,3 +716,4 @@ export declare const runRecordSchema: z.ZodObject<{
549
716
  export declare function upgradeRunRecord(raw: unknown): unknown;
550
717
  export declare const ACTIVE_STATUSES: readonly string[];
551
718
  export declare function isActiveStatus(status: string): boolean;
719
+ export {};
@@ -22,6 +22,8 @@ export const runEventTypeSchema = z.enum([
22
22
  'reaction.added',
23
23
  'agent.message',
24
24
  'checklist.updated',
25
+ 'checkpoint',
26
+ 'heartbeat',
25
27
  'artifact.added',
26
28
  'file.changed',
27
29
  'usage.updated',
@@ -177,6 +179,49 @@ export const checklistItemSchema = z.object({ text: z.string().min(1).max(500),
177
179
  export const MAX_CHECKLIST_ITEMS = 50;
178
180
  /** The whole checklist as the model last wrote it; the latest event replaces every earlier one. */
179
181
  const checklistPayload = z.object({ items: z.array(checklistItemSchema).max(MAX_CHECKLIST_ITEMS) }).strict();
182
+ export const MAX_CHECKPOINT_SUMMARY = 1_200;
183
+ export const MAX_CHECKPOINT_DONE = 20;
184
+ export const MAX_CHECKPOINT_EVIDENCE = 5;
185
+ export const MAX_CHECKPOINT_FILES = 20;
186
+ export const MAX_CHECKPOINT_CHECKS = 8;
187
+ export const MAX_CHECKPOINT_DECISIONS = 8;
188
+ /**
189
+ * The handoff a reply writes when it reaches its work-slice budget. The harness validates and
190
+ * records it; the next slice is told where this one stopped from it (PROP-0041).
191
+ */
192
+ export const checkpointItemSchema = z.object({
193
+ item: z.string().min(1).max(300),
194
+ evidence: z.array(z.string().min(1).max(300)).max(MAX_CHECKPOINT_EVIDENCE).default([])
195
+ }).strict();
196
+ export const checkpointFileSchema = z.object({ path: z.string().min(1).max(300), why: z.string().max(200).default('') }).strict();
197
+ export const checkpointCheckSchema = z.object({
198
+ command: z.string().min(1).max(200),
199
+ ok: z.boolean(),
200
+ detail: z.string().max(300).optional()
201
+ }).strict();
202
+ export const checkpointDecisionSchema = z.object({ what: z.string().min(1).max(200), why: z.string().max(300).default('') }).strict();
203
+ export const checkpointReasonSchema = z.enum(['budget', 'stuck', 'compaction-thrash', 'requested']);
204
+ const checkpointPayload = z.object({
205
+ summary: z.string().max(MAX_CHECKPOINT_SUMMARY),
206
+ done: z.array(checkpointItemSchema).max(MAX_CHECKPOINT_DONE).default([]),
207
+ next: z.string().max(500).default(''),
208
+ blocked: z.string().max(500).optional(),
209
+ files: z.array(checkpointFileSchema).max(MAX_CHECKPOINT_FILES).default([]),
210
+ checks: z.array(checkpointCheckSchema).max(MAX_CHECKPOINT_CHECKS).default([]),
211
+ decisions: z.array(checkpointDecisionSchema).max(MAX_CHECKPOINT_DECISIONS).default([]),
212
+ /** Which slice of the session wrote it, from 1. */
213
+ slice: z.number().int().positive(),
214
+ reason: checkpointReasonSchema
215
+ }).strict();
216
+ /** Counters a live reply reports while it works; a person and the watchdog read liveness from it. */
217
+ const heartbeatPayload = z.object({
218
+ steps: z.number().int().nonnegative(),
219
+ elapsedMs: z.number().nonnegative(),
220
+ lastTool: z.string().max(120).nullable(),
221
+ compactions: z.number().int().nonnegative(),
222
+ slice: z.number().int().positive(),
223
+ maxToolCalls: z.number().int().nonnegative()
224
+ }).strict();
180
225
  const artifactPayload = z.object({ artifactId: z.string(), name: z.string(), file: z.unknown().optional() });
181
226
  const fileChangedPayload = z.object({ path: z.string(), change: z.enum(['added', 'modified', 'deleted']) });
182
227
  /** Where a cost figure comes from: Pi reported it, or the tokens were priced at list rates. */
@@ -228,9 +273,19 @@ export const accountLimitSchema = z.object({
228
273
  id: z.string(),
229
274
  label: z.string(),
230
275
  usedPercent: z.number().nullable().optional(),
276
+ remainingPercent: z.number().nullable().optional(),
231
277
  resetsAt: z.string().nullable().optional(),
232
278
  windowMinutes: z.number().nullable().optional(),
233
- status: z.string().nullable().optional()
279
+ status: z.string().nullable().optional(),
280
+ provider: z.string().nullable().optional(),
281
+ kind: z.enum(['window', 'rate', 'credit', 'configured', 'error']).nullable().optional(),
282
+ unit: z.enum(['percent', 'requests', 'tokens', 'usd', 'currency', 'count']).nullable().optional(),
283
+ used: z.number().nullable().optional(),
284
+ limit: z.number().nullable().optional(),
285
+ remaining: z.number().nullable().optional(),
286
+ source: z.enum(['headers', 'provider', 'estimate', 'error']).nullable().optional(),
287
+ observedAt: z.string().nullable().optional(),
288
+ detail: z.string().nullable().optional()
234
289
  });
235
290
  /** Limit snapshots, plan changes, and classified account failures. */
236
291
  const accountStatusPayload = z.object({
@@ -265,6 +320,8 @@ export const runEventPayloadSchemas = {
265
320
  'reaction.added': reactionAddedPayload,
266
321
  'agent.message': agentMessagePayload,
267
322
  'checklist.updated': checklistPayload,
323
+ checkpoint: checkpointPayload,
324
+ heartbeat: heartbeatPayload,
268
325
  'artifact.added': artifactPayload,
269
326
  'file.changed': fileChangedPayload,
270
327
  'usage.updated': usagePayloadSchema,
@@ -306,6 +363,7 @@ export const runRecordSchema = z.object({
306
363
  sessionId: z.string(),
307
364
  nativeSessionId: text,
308
365
  workingDirectory: text,
366
+ workspaceRoot: text.optional(),
309
367
  worktreeId: text,
310
368
  goal: text,
311
369
  attachmentCount: z.number().int().nonnegative().default(0),
@@ -0,0 +1,72 @@
1
+ /** Which saved history a command acts on: one file in the folder, or the newest there. */
2
+ export interface SessionRef {
3
+ sessionDir: string;
4
+ sessionFile?: string | null;
5
+ /** Recorded in a new history's header. Defaults to the source history's own folder. */
6
+ cwd?: string | null;
7
+ }
8
+ export interface SessionTreeEntry {
9
+ id: string;
10
+ parentId: string | null;
11
+ type: string;
12
+ /** `user`, `assistant`, `toolResult`, ... for a message entry. */
13
+ role?: string;
14
+ /** One line of what the entry says, at most 160 characters. */
15
+ text: string;
16
+ label?: string;
17
+ timestamp: string;
18
+ /** How deep in the tree, for indentation. */
19
+ depth: number;
20
+ }
21
+ export interface SessionTree {
22
+ sessionFile: string;
23
+ leafId: string | null;
24
+ entries: SessionTreeEntry[];
25
+ /** The person's messages on the current branch, newest last: where `/fork` may start. */
26
+ forkPoints: {
27
+ entryId: string;
28
+ text: string;
29
+ }[];
30
+ }
31
+ /** A move without a summary is saved as this entry, so the next turn opens on the chosen branch. */
32
+ export declare const NAVIGATION_ENTRY = "xingular-navigation";
33
+ export declare function tree(ref: SessionRef): SessionTree;
34
+ /**
35
+ * Moves the conversation to another entry without a summary. Choosing one of the person's
36
+ * messages goes to just before it and gives its text back to edit, as the terminal does.
37
+ */
38
+ export declare function navigate(ref: SessionRef & {
39
+ entryId: string;
40
+ }): {
41
+ leafId: string | null;
42
+ editorText?: string;
43
+ };
44
+ /** A new history in `targetDir` that ends just before one of the person's messages. */
45
+ export declare function fork(ref: SessionRef & {
46
+ entryId: string;
47
+ targetDir: string;
48
+ }): {
49
+ sessionFile: string;
50
+ editorText: string;
51
+ };
52
+ /** A new history in `targetDir` with the whole current branch. */
53
+ export declare function clone(ref: SessionRef & {
54
+ targetDir: string;
55
+ }): {
56
+ sessionFile: string;
57
+ };
58
+ export declare function rename(ref: SessionRef & {
59
+ name: string;
60
+ }): {
61
+ name: string;
62
+ };
63
+ /** The text of the last reply on the current branch, or null before the first. */
64
+ export declare function lastReply(ref: SessionRef): {
65
+ text: string | null;
66
+ };
67
+ /** Writes the current branch as JSONL. HTML needs a live session: see `SessionCommand`. */
68
+ export declare function exportJsonl(ref: SessionRef & {
69
+ path: string;
70
+ }): {
71
+ path: string;
72
+ };