@skrr-ai/cli 0.1.118 → 0.1.120

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 (285) hide show
  1. package/dist/base-command.d.ts +32 -0
  2. package/dist/base-command.js +113 -5
  3. package/dist/commands/commands.js +11 -0
  4. package/dist/commands/commitments/action-proposal.d.ts +13 -0
  5. package/dist/commands/commitments/action-proposal.js +39 -0
  6. package/dist/commands/commitments/action-proposals/decide.js +8 -1
  7. package/dist/commands/commitments/action-proposals/execute.js +11 -1
  8. package/dist/commands/commitments/create.js +2 -2
  9. package/dist/commands/commitments/doctor.d.ts +8 -0
  10. package/dist/commands/commitments/doctor.js +22 -0
  11. package/dist/commands/commitments/execute-remediation.js +12 -1
  12. package/dist/commands/commitments/observations.js +2 -2
  13. package/dist/commands/commitments/pack/bind.d.ts +18 -1
  14. package/dist/commands/commitments/pack/bind.js +66 -8
  15. package/dist/commands/commitments/pack/plan.d.ts +4 -1
  16. package/dist/commands/commitments/pack/plan.js +30 -2
  17. package/dist/commands/commitments/update.js +8 -2
  18. package/dist/commands/completion/index.js +1 -1
  19. package/dist/commands/completion/values.js +1 -1
  20. package/dist/commands/computer-use/audio.d.ts +1 -0
  21. package/dist/commands/computer-use/audio.js +1 -0
  22. package/dist/commands/computer-use/browser.d.ts +1 -0
  23. package/dist/commands/computer-use/browser.js +1 -0
  24. package/dist/commands/computer-use/disable.d.ts +1 -0
  25. package/dist/commands/computer-use/disable.js +1 -0
  26. package/dist/commands/computer-use/enable.d.ts +1 -0
  27. package/dist/commands/computer-use/enable.js +1 -0
  28. package/dist/commands/computer-use/index.d.ts +1 -0
  29. package/dist/commands/computer-use/index.js +1 -0
  30. package/dist/commands/computer-use/install.d.ts +1 -0
  31. package/dist/commands/computer-use/install.js +1 -0
  32. package/dist/commands/computer-use/recover.d.ts +1 -0
  33. package/dist/commands/computer-use/recover.js +1 -0
  34. package/dist/commands/computer-use/status.d.ts +1 -0
  35. package/dist/commands/computer-use/status.js +1 -0
  36. package/dist/commands/computer-use/stop.d.ts +1 -0
  37. package/dist/commands/computer-use/stop.js +1 -0
  38. package/dist/commands/context.js +16 -11
  39. package/dist/commands/convos/recovery.js +1 -1
  40. package/dist/commands/daemon/diagnostics.d.ts +9 -0
  41. package/dist/commands/daemon/diagnostics.js +53 -0
  42. package/dist/commands/daemon/index.js +2 -0
  43. package/dist/commands/daemon/maintenance/attest.d.ts +15 -0
  44. package/dist/commands/daemon/maintenance/attest.js +52 -0
  45. package/dist/commands/daemon/maintenance/hold.d.ts +17 -0
  46. package/dist/commands/daemon/maintenance/hold.js +70 -0
  47. package/dist/commands/daemon/maintenance/index.d.ts +12 -0
  48. package/dist/commands/daemon/maintenance/index.js +30 -0
  49. package/dist/commands/daemon/maintenance/resume.d.ts +13 -0
  50. package/dist/commands/daemon/maintenance/resume.js +36 -0
  51. package/dist/commands/daemon/maintenance/status.d.ts +13 -0
  52. package/dist/commands/daemon/maintenance/status.js +36 -0
  53. package/dist/commands/doctor.d.ts +4 -1
  54. package/dist/commands/doctor.js +50 -6
  55. package/dist/commands/followups/plans/cancel-batch.js +6 -3
  56. package/dist/commands/followups/plans/capacity.js +7 -3
  57. package/dist/commands/followups/plans/observability.js +11 -3
  58. package/dist/commands/followups/plans/preferences/set.js +26 -8
  59. package/dist/commands/followups/plans/preferences.js +1 -1
  60. package/dist/commands/followups/plans/show.js +1 -1
  61. package/dist/commands/goals/key-results/assess.d.ts +36 -0
  62. package/dist/commands/goals/key-results/assess.js +110 -0
  63. package/dist/commands/goals/key-results/history.d.ts +30 -0
  64. package/dist/commands/goals/key-results/history.js +104 -0
  65. package/dist/commands/goals/key-results/list.d.ts +5 -4
  66. package/dist/commands/goals/key-results/list.js +12 -6
  67. package/dist/commands/goals/key-results/show.d.ts +4 -2
  68. package/dist/commands/goals/key-results/show.js +25 -4
  69. package/dist/commands/goals/key-results/update.d.ts +4 -0
  70. package/dist/commands/goals/key-results/update.js +18 -24
  71. package/dist/commands/goals/plan-now.js +12 -1
  72. package/dist/commands/goals/planner-compare.d.ts +30 -0
  73. package/dist/commands/goals/planner-compare.js +136 -0
  74. package/dist/commands/machines/dedicated/service/exec.d.ts +3 -0
  75. package/dist/commands/machines/dedicated/service/exec.js +70 -11
  76. package/dist/commands/machines/hosted/destroy.d.ts +1 -0
  77. package/dist/commands/machines/hosted/destroy.js +11 -1
  78. package/dist/commands/machines/hosted/exec.d.ts +1 -0
  79. package/dist/commands/machines/hosted/exec.js +12 -1
  80. package/dist/commands/machines/hosted/index.js +1 -0
  81. package/dist/commands/machines/hosted/operation.d.ts +14 -0
  82. package/dist/commands/machines/hosted/operation.js +51 -0
  83. package/dist/commands/machines/hosted/pull.js +1 -1
  84. package/dist/commands/machines/hosted/start.js +6 -2
  85. package/dist/commands/memory/versions/list.d.ts +2 -0
  86. package/dist/commands/memory/versions/list.js +3 -2
  87. package/dist/commands/memory/versions/show.d.ts +2 -0
  88. package/dist/commands/memory/versions/show.js +3 -2
  89. package/dist/commands/spaces/auto-executor/compare.d.ts +18 -0
  90. package/dist/commands/spaces/auto-executor/compare.js +139 -0
  91. package/dist/commands/spaces/auto-executor/runs.d.ts +3 -0
  92. package/dist/commands/spaces/auto-executor/runs.js +13 -1
  93. package/dist/commands/spaces/charter/create-from-description.d.ts +21 -0
  94. package/dist/commands/spaces/charter/create-from-description.js +77 -0
  95. package/dist/commands/spaces/charter/show.d.ts +22 -0
  96. package/dist/commands/spaces/charter/show.js +61 -0
  97. package/dist/commands/spaces/heartbeats/list.d.ts +1 -16
  98. package/dist/commands/spaces/heartbeats/list.js +13 -0
  99. package/dist/commands/spaces/install-template.js +3 -0
  100. package/dist/commands/spaces/loops/migrate.d.ts +32 -0
  101. package/dist/commands/spaces/loops/migrate.js +103 -0
  102. package/dist/commands/spaces/loops/release.d.ts +14 -0
  103. package/dist/commands/spaces/loops/release.js +59 -0
  104. package/dist/commands/spaces/notebook.d.ts +25 -0
  105. package/dist/commands/spaces/notebook.js +75 -0
  106. package/dist/commands/spaces/proposals/discard.d.ts +17 -0
  107. package/dist/commands/spaces/proposals/discard.js +17 -0
  108. package/dist/commands/spaces/proposals/keep.d.ts +17 -0
  109. package/dist/commands/spaces/proposals/keep.js +17 -0
  110. package/dist/commands/spaces/proposals/list.d.ts +24 -0
  111. package/dist/commands/spaces/proposals/list.js +89 -0
  112. package/dist/commands/spaces/skills/propose.d.ts +29 -0
  113. package/dist/commands/spaces/skills/propose.js +82 -0
  114. package/dist/commands/spaces/templates/fork.js +3 -0
  115. package/dist/commands/spaces/triggers/show.js +6 -0
  116. package/dist/commands/spaces/workflows/retry.d.ts +1 -0
  117. package/dist/commands/spaces/workflows/retry.js +8 -1
  118. package/dist/commands/spaces/workflows/triggers/create.js +3 -2
  119. package/dist/commands/spaces/workflows/triggers/fire.js +4 -0
  120. package/dist/commands/spaces/workflows/triggers/update.js +2 -1
  121. package/dist/commands/spaces/write-policy/set.d.ts +22 -0
  122. package/dist/commands/spaces/write-policy/set.js +82 -0
  123. package/dist/commands/spaces/write-policy/show.d.ts +19 -0
  124. package/dist/commands/spaces/write-policy/show.js +49 -0
  125. package/dist/commands/store/artifacts/receipt.d.ts +14 -0
  126. package/dist/commands/store/artifacts/receipt.js +34 -0
  127. package/dist/commands/store/artifacts/release.d.ts +2 -0
  128. package/dist/commands/store/artifacts/release.js +11 -0
  129. package/dist/commands/store/governance/publish-release.d.ts +2 -0
  130. package/dist/commands/store/governance/publish-release.js +30 -1
  131. package/dist/commands/store/governance/release-receipt.d.ts +12 -0
  132. package/dist/commands/store/governance/release-receipt.js +32 -0
  133. package/dist/commands/tasks/approvals/list.d.ts +11 -5
  134. package/dist/commands/tasks/approvals/list.js +13 -6
  135. package/dist/commands/tasks/attachments/facts.d.ts +12 -0
  136. package/dist/commands/tasks/attachments/facts.js +29 -0
  137. package/dist/commands/tasks/attachments/upload.d.ts +1 -0
  138. package/dist/commands/tasks/attachments/upload.js +16 -0
  139. package/dist/commands/tasks/bulk-update.js +35 -1
  140. package/dist/commands/tasks/context.d.ts +15 -0
  141. package/dist/commands/tasks/context.js +69 -0
  142. package/dist/commands/tasks/copy.d.ts +18 -0
  143. package/dist/commands/tasks/copy.js +85 -0
  144. package/dist/commands/tasks/create-tree.js +97 -23
  145. package/dist/commands/tasks/create.js +9 -1
  146. package/dist/commands/tasks/deliverable/add.js +20 -10
  147. package/dist/commands/tasks/move.js +8 -1
  148. package/dist/commands/tasks/operations/show.d.ts +16 -0
  149. package/dist/commands/tasks/operations/show.js +98 -0
  150. package/dist/commands/tasks/operations/wait.d.ts +22 -0
  151. package/dist/commands/tasks/operations/wait.js +114 -0
  152. package/dist/commands/tasks/preflight.d.ts +1 -0
  153. package/dist/commands/tasks/preflight.js +11 -1
  154. package/dist/commands/tasks/rearm-recurrence.js +4 -0
  155. package/dist/commands/tasks/result/show.js +22 -0
  156. package/dist/commands/tasks/result/submit.d.ts +1 -0
  157. package/dist/commands/tasks/result/submit.js +3 -0
  158. package/dist/commands/tasks/retry-receipt.d.ts +15 -0
  159. package/dist/commands/tasks/retry-receipt.js +89 -0
  160. package/dist/commands/tasks/retry-review.d.ts +16 -0
  161. package/dist/commands/tasks/retry-review.js +66 -0
  162. package/dist/commands/tasks/retry.d.ts +4 -8
  163. package/dist/commands/tasks/retry.js +34 -68
  164. package/dist/commands/tasks/runs.d.ts +21 -0
  165. package/dist/commands/tasks/runs.js +95 -0
  166. package/dist/commands/tasks/show.d.ts +2 -0
  167. package/dist/commands/tasks/show.js +15 -1
  168. package/dist/commands/tasks/start-receipt.d.ts +15 -0
  169. package/dist/commands/tasks/start-receipt.js +95 -0
  170. package/dist/commands/tasks/start.d.ts +4 -0
  171. package/dist/commands/tasks/start.js +49 -3
  172. package/dist/commands/tasks/update.js +3 -0
  173. package/dist/commands/tasks/upsert.js +17 -3
  174. package/dist/commands/tasks/watch.d.ts +3 -0
  175. package/dist/commands/tasks/watch.js +85 -20
  176. package/dist/commands/wiki/history.d.ts +33 -0
  177. package/dist/commands/wiki/history.js +134 -0
  178. package/dist/commands/wiki/ls.d.ts +2 -0
  179. package/dist/commands/wiki/ls.js +8 -0
  180. package/dist/commands/wiki/update.d.ts +3 -1
  181. package/dist/commands/wiki/update.js +24 -2
  182. package/dist/commands/wiki/write.d.ts +22 -0
  183. package/dist/commands/wiki/write.js +144 -6
  184. package/dist/generated/agent-guides.json +81 -81
  185. package/dist/generated/managed-instruction-guides.json +1 -1
  186. package/dist/lib/agent-guides.d.ts +9 -0
  187. package/dist/lib/agent-guides.js +23 -1
  188. package/dist/lib/agentic-stream.d.ts +5 -0
  189. package/dist/lib/agentic-stream.js +122 -3
  190. package/dist/lib/api-fetch.d.ts +4 -0
  191. package/dist/lib/api-fetch.js +25 -7
  192. package/dist/lib/auth-diagnostics.d.ts +39 -0
  193. package/dist/lib/auth-diagnostics.js +71 -0
  194. package/dist/lib/cli-client-identity.d.ts +6 -0
  195. package/dist/lib/cli-client-identity.js +16 -0
  196. package/dist/lib/cli-installation-diagnostics.d.ts +52 -0
  197. package/dist/lib/cli-installation-diagnostics.js +254 -0
  198. package/dist/lib/command-hygiene.d.ts +45 -0
  199. package/dist/lib/command-hygiene.js +413 -0
  200. package/dist/lib/commitments.d.ts +64 -3
  201. package/dist/lib/commitments.js +34 -6
  202. package/dist/lib/completion-index.d.ts +16 -4
  203. package/dist/lib/completion-index.js +50 -14
  204. package/dist/lib/config.js +7 -1
  205. package/dist/lib/daemon-maintenance-command.d.ts +22 -0
  206. package/dist/lib/daemon-maintenance-command.js +39 -0
  207. package/dist/lib/daemon-maintenance.d.ts +275 -0
  208. package/dist/lib/daemon-maintenance.js +1035 -0
  209. package/dist/lib/dedicated-service.d.ts +3 -2
  210. package/dist/lib/dedicated-service.js +11 -3
  211. package/dist/lib/governed-store.d.ts +8 -0
  212. package/dist/lib/governed-store.js +5 -0
  213. package/dist/lib/hosted-machines.d.ts +33 -2
  214. package/dist/lib/hosted-machines.js +19 -1
  215. package/dist/lib/json-output.d.ts +1 -1
  216. package/dist/lib/machines.d.ts +9 -1
  217. package/dist/lib/machines.js +15 -1
  218. package/dist/lib/memory-history-session.d.ts +14 -0
  219. package/dist/lib/memory-history-session.js +60 -0
  220. package/dist/lib/node-adapter.js +13 -0
  221. package/dist/lib/record-output.d.ts +22 -0
  222. package/dist/lib/record-output.js +78 -0
  223. package/dist/lib/roles.d.ts +3 -3
  224. package/dist/lib/scoped-memory-command.d.ts +24 -0
  225. package/dist/lib/scoped-memory-command.js +87 -5
  226. package/dist/lib/space-charter.d.ts +49 -0
  227. package/dist/lib/space-charter.js +78 -0
  228. package/dist/lib/space-loop-migration.d.ts +18 -0
  229. package/dist/lib/space-loop-migration.js +128 -0
  230. package/dist/lib/space-notebook.d.ts +22 -0
  231. package/dist/lib/space-notebook.js +140 -0
  232. package/dist/lib/space-proposal-decision-command.d.ts +36 -0
  233. package/dist/lib/space-proposal-decision-command.js +108 -0
  234. package/dist/lib/space-proposals.d.ts +44 -0
  235. package/dist/lib/space-proposals.js +186 -0
  236. package/dist/lib/space-templates.d.ts +8 -0
  237. package/dist/lib/space-templates.js +17 -0
  238. package/dist/lib/space-write-policy.d.ts +24 -0
  239. package/dist/lib/space-write-policy.js +103 -0
  240. package/dist/lib/task-agent-context-capabilities.d.ts +10 -0
  241. package/dist/lib/task-agent-context-capabilities.js +22 -0
  242. package/dist/lib/task-agent-context-compatibility.d.ts +9 -0
  243. package/dist/lib/task-agent-context-compatibility.js +30 -0
  244. package/dist/lib/task-asset-upload.d.ts +22 -0
  245. package/dist/lib/task-asset-upload.js +257 -29
  246. package/dist/lib/task-batch.d.ts +15 -1
  247. package/dist/lib/task-batch.js +35 -2
  248. package/dist/lib/task-operation-watch.d.ts +66 -0
  249. package/dist/lib/task-operation-watch.js +159 -0
  250. package/dist/lib/task-resolver.d.ts +1 -1
  251. package/dist/lib/task-resolver.js +4 -3
  252. package/dist/lib/task-runtime-headers.js +13 -3
  253. package/dist/lib/task-work.d.ts +1 -1
  254. package/dist/lib/task-work.js +35 -1
  255. package/dist/lib/task-write-attribution.d.ts +14 -0
  256. package/dist/lib/task-write-attribution.js +35 -2
  257. package/dist/lib/triggers.d.ts +11 -0
  258. package/dist/lib/triggers.js +7 -0
  259. package/dist/lib/wiki-update.d.ts +1 -0
  260. package/dist/lib/wiki-update.js +10 -1
  261. package/dist/lib/wiki.js +4 -1
  262. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.d.ts +9 -1
  263. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.js +31 -15
  264. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonToolApproval.js +1 -0
  265. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonWire.js +13 -7
  266. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/guidedUpdate.d.ts +370 -0
  267. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/guidedUpdate.js +315 -0
  268. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/maintenanceReportWire.d.ts +178 -0
  269. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/maintenanceReportWire.js +262 -0
  270. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/toolApprovalSignature.d.ts +51 -0
  271. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/toolApprovalSignature.js +106 -0
  272. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.d.ts +9 -1
  273. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.js +32 -5
  274. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonToolApproval.js +1 -0
  275. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonWire.js +33 -14
  276. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/guidedUpdate.d.ts +370 -0
  277. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/guidedUpdate.js +404 -0
  278. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/maintenanceReportWire.d.ts +178 -0
  279. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/maintenanceReportWire.js +342 -0
  280. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/toolApprovalSignature.d.ts +51 -0
  281. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/toolApprovalSignature.js +138 -0
  282. package/dist/node_modules/@skrr-ai/auth-core/package.json +20 -0
  283. package/dist/node_modules/@skrr-ai/data-provider/index.js +27085 -20250
  284. package/oclif.manifest.json +10570 -7247
  285. package/package.json +20 -2
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ScopedMemoryCommand = exports.versionedMutationFlags = exports.mutationFlags = exports.scopedMemoryFlags = void 0;
4
4
  exports.parseMemoryStoreResolutions = parseMemoryStoreResolutions;
5
5
  exports.memoryStoreResolutionLines = memoryStoreResolutionLines;
6
+ exports.memoryNotMountedDiagnostic = memoryNotMountedDiagnostic;
6
7
  exports.parseMemoryMount = parseMemoryMount;
7
8
  exports.parseMountedMemoryStore = parseMountedMemoryStore;
8
9
  exports.parseMemoryApiError = parseMemoryApiError;
@@ -10,6 +11,7 @@ const core_1 = require("@oclif/core");
10
11
  const node_crypto_1 = require("node:crypto");
11
12
  const base_command_1 = require("../base-command");
12
13
  const api_fetch_1 = require("./api-fetch");
14
+ const memory_history_session_1 = require("./memory-history-session");
13
15
  function parseMemoryStoreResolutions(value) {
14
16
  if (value === undefined)
15
17
  return undefined;
@@ -44,6 +46,43 @@ function memoryStoreResolutionLines(resolutions) {
44
46
  };
45
47
  return resolutions.map((resolution) => `${labels[resolution.outcome]}: ${resolution.storeId}`);
46
48
  }
49
+ /**
50
+ * A Space on a command is context for the request; it is not evidence that
51
+ * this session mounted the Space's Memory Store. Keeping that distinction in
52
+ * one diagnostic prevents every Memory verb from inventing a different (and
53
+ * often unsafe) recovery path.
54
+ *
55
+ * `stores` has already passed the server's mount visibility check. We expose
56
+ * only those scopes, never a guessed Store or an inaccessible Space.
57
+ */
58
+ function memoryNotMountedDiagnostic({ requestedScope, agentId, spaceId, stores, }) {
59
+ const availableScopes = [...new Set(stores.map((store) => `${store.owner.kind}:${store.owner.id}`))].sort();
60
+ const agentScope = `agent:${agentId}`;
61
+ const writableAgentStore = stores.some((store) => store.owner.kind === 'agent' &&
62
+ store.owner.id === agentId &&
63
+ store.mount.access === 'read_write');
64
+ const requestedSpaceId = requestedScope.startsWith('space:')
65
+ ? requestedScope.slice('space:'.length)
66
+ : undefined;
67
+ const resolve = `skrr memory mounts resolve --agent ${agentId}${spaceId ? ` --space ${spaceId}` : requestedSpaceId ? ` --space ${requestedSpaceId}` : ''} --json`;
68
+ const remedy = [
69
+ `Run \`${resolve}\` and select a writable mounted Store.`,
70
+ writableAgentStore
71
+ ? `To file Agent-owned Memory, retry with \`--scope ${agentScope}\`; Task or Space placement does not change that ownership.`
72
+ : 'A Space Store can be selected only after the session has mounted it; do not infer a mount from `--space` alone.',
73
+ ].join(' ');
74
+ return {
75
+ message: `MEMORY_NOT_MOUNTED: ${requestedScope} is not mounted for this session. ` +
76
+ '`--space` selects request context; it does not mount Space Memory. ' +
77
+ `→ ${remedy}`,
78
+ details: {
79
+ requestedScope,
80
+ ...(spaceId ? { spaceContext: spaceId } : {}),
81
+ availableScopes,
82
+ remedy,
83
+ },
84
+ };
85
+ }
47
86
  // The public CLI must not load the private data-schemas package at runtime.
48
87
  // The API validates the full wire contract; check the fields used by CLI commands
49
88
  // before treating a response as a mounted Store or mount.
@@ -120,6 +159,9 @@ const ERROR_EXITS = {
120
159
  MEMORY_AUTHORIZATION_STALE: 8,
121
160
  };
122
161
  function parseMemoryApiError(error) {
162
+ if (error.code === 'MEMORY_HISTORY_API_UNSUPPORTED') {
163
+ return { code: error.code, message: error.message, retryable: false };
164
+ }
123
165
  try {
124
166
  const body = JSON.parse(error.body || '{}');
125
167
  const details = {
@@ -136,7 +178,7 @@ function parseMemoryApiError(error) {
136
178
  };
137
179
  return {
138
180
  code: String(body.code || body.error || error.code || 'MEMORY_API_ERROR').toUpperCase(),
139
- message: [body.message || error.message, body.remedy].filter(Boolean).join(' '),
181
+ message: [body.message || error.message, body.remedy, error.recoveryHint].filter(Boolean).join(' '),
140
182
  retryable: body.retryable === true,
141
183
  ...(Object.keys(details).length ? { details } : {}),
142
184
  };
@@ -144,7 +186,7 @@ function parseMemoryApiError(error) {
144
186
  catch {
145
187
  return {
146
188
  code: error.code || 'MEMORY_API_ERROR',
147
- message: error.message,
189
+ message: [error.message, error.recoveryHint].filter(Boolean).join(' '),
148
190
  retryable: false,
149
191
  };
150
192
  }
@@ -154,8 +196,35 @@ class ScopedMemoryCommand extends base_command_1.BaseCommand {
154
196
  return `/api/agents/${encodeURIComponent(agentId)}/memories/workspace${suffix}`;
155
197
  }
156
198
  async memoryApi(agentId, suffix, options = {}) {
199
+ return this.memoryRequest(this.endpoint(agentId, suffix), options);
200
+ }
201
+ async memoryHistoryApi(flags, options) {
202
+ const suffix = options.versionId ? `/${encodeURIComponent(options.versionId)}` : '';
203
+ const query = { memoryId: options.memoryId, limit: options.limit };
204
+ if (!(0, memory_history_session_1.hasMemoryHistoryRuntime)()) {
205
+ const store = await this.resolveStore(flags);
206
+ return this.memoryApi(flags.agent, `/stores/${store.id}/versions${suffix}${this.query(flags, query)}`);
207
+ }
208
+ const { sessionId } = (0, memory_history_session_1.memoryHistorySession)();
209
+ if (Boolean(flags.store) === Boolean(flags.scope)) {
210
+ this.error('Pass exactly one of --store <id> or --scope agent:<id>|space:<id>.', { exit: 2 });
211
+ }
212
+ if (flags.scope && !/^(agent|space):[^:]+$/.test(flags.scope)) {
213
+ this.error('--scope must be agent:<id> or space:<id>.', { exit: 2 });
214
+ }
215
+ if (flags.scope?.startsWith('space:') && !flags.space) {
216
+ this.error(`MEMORY_SPACE_CONTEXT_REQUIRED: --space ${flags.scope.slice(6)} is required when selecting ${flags.scope}.`, { exit: 2, code: 'MEMORY_SPACE_CONTEXT_REQUIRED' });
217
+ }
218
+ // Mount resolution belongs to the admitted session facade. A generic Store
219
+ // preflight would require an owner credential before the session-only read.
220
+ const path = `/api/agentic/sessions/${encodeURIComponent(sessionId)}/memory/agents/${encodeURIComponent(flags.agent)}/versions${suffix}`;
221
+ return this.memoryRequest(`${path}${this.query(flags, {
222
+ ...query, ...(flags.store ? { storeId: flags.store } : { scope: flags.scope }),
223
+ })}`, { sessionRead: 'memory-history-v1' });
224
+ }
225
+ async memoryRequest(path, options) {
157
226
  try {
158
- return await (0, api_fetch_1.apiFetch)(this.endpoint(agentId, suffix), options);
227
+ return await (0, api_fetch_1.apiFetch)(path, options);
159
228
  }
160
229
  catch (error) {
161
230
  if (error instanceof api_fetch_1.ApiFetchError) {
@@ -205,8 +274,21 @@ class ScopedMemoryCommand extends base_command_1.BaseCommand {
205
274
  const response = await this.memoryApi(flags.agent, `/stores${this.query(flags)}`);
206
275
  const stores = response.stores.map(parseMountedMemoryStore);
207
276
  const store = stores.find((candidate) => candidate.owner.kind === kind && candidate.owner.id === id);
208
- if (!store)
209
- this.error(`MEMORY_NOT_MOUNTED: ${flags.scope}`, { exit: 5 });
277
+ if (!store) {
278
+ const diagnostic = memoryNotMountedDiagnostic({
279
+ requestedScope: flags.scope,
280
+ agentId: flags.agent,
281
+ spaceId: flags.space,
282
+ stores,
283
+ });
284
+ this.failWithCliError({
285
+ message: diagnostic.message,
286
+ code: 'MEMORY_NOT_MOUNTED',
287
+ exit: 5,
288
+ retryable: false,
289
+ details: diagnostic.details,
290
+ });
291
+ }
210
292
  if (write && store.mount?.access !== 'read_write') {
211
293
  this.error('MEMORY_STORE_READ_ONLY: selected Store is read-only', { exit: 5 });
212
294
  }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Shared helpers for `skrr spaces charter …` and the wiki commands that can
3
+ * meet the one-charter rule (OSK-17985).
4
+ *
5
+ * A Space's charter is its one live `kind: 'charter'` wiki page. Its LEAD
6
+ * SECTION — everything before the first `##` heading — is what every agent
7
+ * turn in the Space receives; the rest is read on demand. The server computes
8
+ * the lead (`leadSection` on the charter read) with the same function the
9
+ * Space context builder uses, so these helpers print it rather than
10
+ * re-deriving it.
11
+ */
12
+ import type { WikiCharterPage } from '@skrr-ai/data-provider';
13
+ export type CharterConflictHint = {
14
+ message: string;
15
+ details: {
16
+ pageId?: string;
17
+ path?: string;
18
+ };
19
+ };
20
+ /**
21
+ * A `409 WIKI_CHARTER_EXISTS` turned into a message that names the charter
22
+ * already there and the command that frees the slot. `undefined` for anything
23
+ * else, so the caller falls through to its ordinary error handling.
24
+ */
25
+ export declare function charterConflictHint(err: unknown, { binName, spaceId }: {
26
+ binName: string;
27
+ spaceId: string;
28
+ }): CharterConflictHint | undefined;
29
+ /**
30
+ * The lines `charter show` prints: where the charter is, then its lead section
31
+ * marked as what every agent reads, then either the whole page (`full`) or the
32
+ * command that reads it.
33
+ *
34
+ * An EMPTY lead is said in words, because it is the one charter state that
35
+ * changes what agents see without anything looking wrong: a page that opens
36
+ * with a `##` heading gives them no charter lead at all.
37
+ */
38
+ export declare function charterLines(charter: WikiCharterPage & {
39
+ url?: string | null;
40
+ }, { binName, spaceId, full }: {
41
+ binName: string;
42
+ spaceId: string;
43
+ full?: boolean;
44
+ }): string[];
45
+ /** What `charter show` prints for a Space that has no charter page yet. */
46
+ export declare function noCharterLines({ binName, spaceId, }: {
47
+ binName: string;
48
+ spaceId: string;
49
+ }): string[];
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.charterConflictHint = charterConflictHint;
4
+ exports.charterLines = charterLines;
5
+ exports.noCharterLines = noCharterLines;
6
+ const http_error_1 = require("./http-error");
7
+ /**
8
+ * A `409 WIKI_CHARTER_EXISTS` turned into a message that names the charter
9
+ * already there and the command that frees the slot. `undefined` for anything
10
+ * else, so the caller falls through to its ordinary error handling.
11
+ */
12
+ function charterConflictHint(err, { binName, spaceId }) {
13
+ if (!(0, http_error_1.hasHttpStatus)(err, 409))
14
+ return undefined;
15
+ const body = (0, http_error_1.httpBodyOf)(err);
16
+ if (body?.code !== 'WIKI_CHARTER_EXISTS')
17
+ return undefined;
18
+ const pageId = typeof body.pageId === 'string' && body.pageId ? body.pageId : undefined;
19
+ const path = typeof body.path === 'string' && body.path ? body.path : undefined;
20
+ let where = 'another page';
21
+ if (path)
22
+ where = `'${path}'`;
23
+ else if (pageId)
24
+ where = `page ${pageId}`;
25
+ return {
26
+ message: `This Space already has a charter page: ${where}. A Space holds at most one live charter. ` +
27
+ `Change that page to another kind first (\`${binName} wiki update ${spaceId} ${path ?? '<path>'} ` +
28
+ `--kind doc\`) or archive it, then try again. Show it with \`${binName} spaces charter show ${spaceId}\`.`,
29
+ details: { ...(pageId ? { pageId } : {}), ...(path ? { path } : {}) },
30
+ };
31
+ }
32
+ /**
33
+ * The lines `charter show` prints: where the charter is, then its lead section
34
+ * marked as what every agent reads, then either the whole page (`full`) or the
35
+ * command that reads it.
36
+ *
37
+ * An EMPTY lead is said in words, because it is the one charter state that
38
+ * changes what agents see without anything looking wrong: a page that opens
39
+ * with a `##` heading gives them no charter lead at all.
40
+ */
41
+ function charterLines(charter, { binName, spaceId, full = false }) {
42
+ const path = charter.path ?? charter.slug;
43
+ const lines = [`Charter: ${path} (${charter.pageId})`];
44
+ if (charter.title && charter.title !== path)
45
+ lines.push(`Title: ${charter.title}`);
46
+ if (charter.url)
47
+ lines.push(`URL: ${charter.url}`);
48
+ lines.push('');
49
+ lines.push('Lead section (everything before the first ## heading; read by every agent in this Space):');
50
+ const lead = typeof charter.leadSection === 'string' ? charter.leadSection : '';
51
+ if (lead) {
52
+ for (const line of lead.split('\n'))
53
+ lines.push(` ${line}`);
54
+ }
55
+ else {
56
+ lines.push(' (empty: the page opens with a ## heading, so agents receive no charter lead. ' +
57
+ 'Put the essentials before the first ## heading.)');
58
+ }
59
+ lines.push('');
60
+ if (full) {
61
+ lines.push('Full page:');
62
+ for (const line of String(charter.content ?? '').split('\n'))
63
+ lines.push(` ${line}`);
64
+ }
65
+ else {
66
+ lines.push(`The rest of the page is read on demand: \`${binName} spaces charter show ${spaceId} --full\` ` +
67
+ `or \`${binName} wiki cat ${spaceId} ${path}\`.`);
68
+ }
69
+ return lines;
70
+ }
71
+ /** What `charter show` prints for a Space that has no charter page yet. */
72
+ function noCharterLines({ binName, spaceId, }) {
73
+ return [
74
+ 'This Space has no charter page yet.',
75
+ `Create one from the Space description: \`${binName} spaces charter create-from-description ${spaceId}\``,
76
+ `Or make an existing page the charter: \`${binName} wiki update ${spaceId} <path> --kind charter\``,
77
+ ];
78
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Converting a Space's older periodic agent turns into Space loops on the CLI
3
+ * (OSK-18009, design §5.11): how `skrr spaces loops migrate` prints a plan and
4
+ * what applying it did.
5
+ *
6
+ * The vocabulary (dispositions, reasons, outcomes) and every sentence that
7
+ * explains a code are `@skrr-ai/data-provider`'s (`spaces/loopMigration.ts`),
8
+ * and the server sends each code's sentence beside it; this file only lays
9
+ * them out. A label, a prompt or a note was written by a person or an agent
10
+ * and is printed as data, on one line.
11
+ */
12
+ import type { SpaceLoopMigrationApplyResponse, SpaceLoopMigrationPlan } from '@skrr-ai/data-provider';
13
+ /** The plan, as a person reviews it before applying. */
14
+ export declare function planLines(plan: SpaceLoopMigrationPlan, { binName }?: {
15
+ binName?: string;
16
+ }): string[];
17
+ /** What applying did, one line per entry. */
18
+ export declare function applyLines(response: SpaceLoopMigrationApplyResponse): string[];
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.planLines = planLines;
4
+ exports.applyLines = applyLines;
5
+ const space_notebook_1 = require("./space-notebook");
6
+ const SHAPE_WORD = {
7
+ space_loop: "the Space's loop",
8
+ member_automation: "its owner's own Commitment, delivering into the Space",
9
+ };
10
+ const OUTCOME_WORD = {
11
+ handed_over: 'handed over',
12
+ awaiting_activation: 'loop made, not active yet',
13
+ already_handed_over: 'already handed over',
14
+ not_converted: 'not converted',
15
+ not_yours: 'not yours to convert',
16
+ abandoned: 'its loop ended before taking over',
17
+ failed: 'failed',
18
+ };
19
+ function perDay(value) {
20
+ if (value >= 1)
21
+ return `${Math.round(value * 100) / 100}/day`;
22
+ return `1 every ${Math.round(1 / value)} days`;
23
+ }
24
+ function entryHeading(entry) {
25
+ return ` ${entry.entryId} ${(0, space_notebook_1.oneLine)(entry.label, 80)}`;
26
+ }
27
+ function convertLines(entry) {
28
+ const lines = [entryHeading(entry)];
29
+ const target = entry.target;
30
+ if (target) {
31
+ lines.push(` becomes ${SHAPE_WORD[target.shape] || target.shape}: owned by user ${target.ownerUserId}, held by agent ${target.agentId}`);
32
+ }
33
+ if (entry.pointer) {
34
+ lines.push(` loop ${entry.pointer.commitmentId} (${entry.pointer.loopStatus || 'unknown'}); the entry keeps firing until it is active`);
35
+ }
36
+ const cadence = entry.cadence;
37
+ if (cadence) {
38
+ lines.push(` cadence ${cadence.fidelity}: ${(0, space_notebook_1.oneLine)(cadence.before.summary, 80)}, ${perDay(cadence.before.turnsPerDay)} -> ${(0, space_notebook_1.oneLine)(cadence.after.summary, 100)}, ${perDay(cadence.after.turnsPerDay)}`);
39
+ for (const note of cadence.notes)
40
+ lines.push(` ${(0, space_notebook_1.oneLine)(note.message, 200)}`);
41
+ }
42
+ for (const note of entry.notes)
43
+ lines.push(` differs ${(0, space_notebook_1.oneLine)(note.message, 200)}`);
44
+ if (entry.activation?.knownBlockers?.length) {
45
+ lines.push(` activate will stay a draft until fixed: ${entry.activation.knownBlockers.join(', ')} (the entry keeps firing meanwhile)`);
46
+ }
47
+ lines.push(entry.apply.allowed
48
+ ? ' apply you can apply this'
49
+ : ` apply not you: ${(0, space_notebook_1.oneLine)(entry.apply.message || entry.apply.reason, 200)}`);
50
+ return lines;
51
+ }
52
+ /** The plan, as a person reviews it before applying. */
53
+ function planLines(plan, { binName = 'skrr' } = {}) {
54
+ const lines = [
55
+ `Converting ${plan.sourceLabel} entries of space ${plan.spaceId} into Space loops`,
56
+ plan.executionPrincipal
57
+ ? `Execution principal: user ${plan.executionPrincipal.userId} (version ${plan.executionPrincipal.version}). Their entries become the Space's loops; everyone else's become their own Commitments.`
58
+ : "This Space has no active execution principal, so every entry becomes its owner's own Commitment.",
59
+ ];
60
+ if (plan.entryScope === 'owner') {
61
+ lines.push(`A ${plan.sourceLabel} is private to its member: this plan lists only yours, and each member converts their own.`);
62
+ }
63
+ const groups = [
64
+ ['Will convert', plan.entries.filter((entry) => entry.disposition === 'convert')],
65
+ [
66
+ 'Converted, loop not active yet',
67
+ plan.entries.filter((entry) => entry.disposition === 'resume'),
68
+ ],
69
+ ['Handed over', plan.entries.filter((entry) => entry.disposition === 'handed_over')],
70
+ ['Not converted', plan.entries.filter((entry) => entry.disposition === 'not_convertible')],
71
+ ];
72
+ for (const [title, entries] of groups) {
73
+ if (entries.length === 0)
74
+ continue;
75
+ lines.push('', `${title} (${entries.length}):`);
76
+ for (const entry of entries) {
77
+ if (entry.disposition === 'convert' || entry.disposition === 'resume') {
78
+ lines.push(...convertLines(entry));
79
+ }
80
+ else if (entry.disposition === 'handed_over') {
81
+ const status = entry.pointer?.loopStatus;
82
+ lines.push(`${entryHeading(entry)}: retired, replaced by loop ${entry.pointer?.commitmentId} (${status || 'unknown'})${status && status !== 'active' && status !== 'paused'
83
+ ? '. A retired entry stays retired; make a new loop or heartbeat to bring the turn back.'
84
+ : ''}`);
85
+ }
86
+ else {
87
+ // A short detail reads inline; a long one (which events and filters
88
+ // block a Space assistant, OSK-18010) gets its own line, never cut short.
89
+ const detail = entry.detail ? (0, space_notebook_1.oneLine)(entry.detail, 600) : '';
90
+ const inline = detail && detail.length <= 160;
91
+ lines.push(`${entryHeading(entry)}: ${(0, space_notebook_1.oneLine)(entry.message || entry.reason, 240)}${inline ? ` (${detail})` : ''}`);
92
+ if (detail && !inline)
93
+ lines.push(` why ${detail}`);
94
+ }
95
+ }
96
+ }
97
+ if (plan.entries.length === 0) {
98
+ lines.push('', plan.entryScope === 'owner'
99
+ ? `You have no ${plan.sourceLabel} in this space.`
100
+ : `No ${plan.sourceLabel} entries in this space.`);
101
+ }
102
+ lines.push('', `Plan digest: ${plan.planDigest}`);
103
+ if (plan.counts.applicableByYou > 0) {
104
+ lines.push(`Apply the ${plan.counts.applicableByYou} you can: ${binName} spaces loops migrate ${plan.spaceId} --from ${plan.source} --apply --plan-digest ${plan.planDigest}`);
105
+ }
106
+ else {
107
+ lines.push('Nothing here is yours to apply.');
108
+ }
109
+ return lines;
110
+ }
111
+ /** What applying did, one line per entry. */
112
+ function applyLines(response) {
113
+ const lines = response.results.map((result) => {
114
+ const word = OUTCOME_WORD[result.outcome] || result.outcome;
115
+ const loop = result.commitmentId ? ` -> loop ${result.commitmentId}` : '';
116
+ const code = result.code ? ` (${result.code})` : '';
117
+ const detail = result.detail ? `: ${(0, space_notebook_1.oneLine)(result.detail, 240)}` : '';
118
+ return `${result.entryId} ${word}${loop}${code}${detail}`;
119
+ });
120
+ const counts = Object.entries(response.counts)
121
+ .map(([outcome, count]) => `${count} ${OUTCOME_WORD[outcome] || outcome}`)
122
+ .join(', ');
123
+ lines.push('', counts || 'Nothing to apply.');
124
+ if (response.results.some((result) => result.outcome === 'awaiting_activation')) {
125
+ lines.push('A loop that is not active yet leaves its entry firing. Fix what the code names, then activate the loop; its entry retires the moment it is active.');
126
+ }
127
+ return lines;
128
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The Space Notebook on the CLI (OSK-17996): how `skrr spaces notebook` prints
3
+ * one page of a Space's timeline.
4
+ *
5
+ * The vocabulary, the link paths and the sentences that explain why a kind
6
+ * ends where it does are `@skrr-ai/data-provider`'s (`spaces/notebook.ts`);
7
+ * this file only lays them out, so the CLI cannot describe a window or a
8
+ * visibility rule differently from the web Notebook tab.
9
+ *
10
+ * A row's summary was written by a person, an Agent or the platform (its
11
+ * author says which) and is printed as data: on one line, control characters
12
+ * removed, so a summary cannot forge a row of its own.
13
+ */
14
+ import { type SpaceNotebookAuthor, type SpaceNotebookResponse } from '@skrr-ai/data-provider';
15
+ /** One printable line: no control or bidi characters, whitespace collapsed. */
16
+ export declare function oneLine(value: unknown, max?: number): string;
17
+ export declare function notebookAuthorLabel(author: SpaceNotebookAuthor | undefined): string;
18
+ /** The lines `spaces notebook` prints for one page. */
19
+ export declare function notebookLines(page: SpaceNotebookResponse, { webOrigin, binName }: {
20
+ webOrigin?: string;
21
+ binName: string;
22
+ }): string[];
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.oneLine = oneLine;
4
+ exports.notebookAuthorLabel = notebookAuthorLabel;
5
+ exports.notebookLines = notebookLines;
6
+ /**
7
+ * The Space Notebook on the CLI (OSK-17996): how `skrr spaces notebook` prints
8
+ * one page of a Space's timeline.
9
+ *
10
+ * The vocabulary, the link paths and the sentences that explain why a kind
11
+ * ends where it does are `@skrr-ai/data-provider`'s (`spaces/notebook.ts`);
12
+ * this file only lays them out, so the CLI cannot describe a window or a
13
+ * visibility rule differently from the web Notebook tab.
14
+ *
15
+ * A row's summary was written by a person, an Agent or the platform (its
16
+ * author says which) and is printed as data: on one line, control characters
17
+ * removed, so a summary cannot forge a row of its own.
18
+ */
19
+ const data_provider_1 = require("@skrr-ai/data-provider");
20
+ const KIND_TAG = {
21
+ task_result: 'result',
22
+ loop_cycle: 'cycle',
23
+ hypothesis: 'hypothesis',
24
+ journal_entry: 'journal',
25
+ report: 'report',
26
+ };
27
+ const VERDICT_WORD = {
28
+ supported: 'supported',
29
+ refuted: 'ruled out',
30
+ inconclusive: 'inconclusive',
31
+ superseded: 'superseded',
32
+ };
33
+ /** One printable line: no control or bidi characters, whitespace collapsed. */
34
+ function oneLine(value, max = 240) {
35
+ const text = String(value ?? '')
36
+ // eslint-disable-next-line no-control-regex
37
+ .replace(/[\u0000-\u001f\u007f-\u009f‎‏‪-‮⁦-⁩]/g, ' ')
38
+ .replace(/\s+/g, ' ')
39
+ .trim();
40
+ return text.length > max ? `${text.slice(0, max - 1).trimEnd()}…` : text;
41
+ }
42
+ function notebookAuthorLabel(author) {
43
+ if (!author)
44
+ return 'unknown';
45
+ if (author.kind === 'agent')
46
+ return author.agentId ? `agent ${author.agentId}` : 'agent';
47
+ if (author.kind === 'person')
48
+ return author.userId ? `person ${author.userId}` : 'person';
49
+ return author.label ? `system (${oneLine(author.label, 60)})` : 'system';
50
+ }
51
+ const LINK_WORD = {
52
+ home: 'loop of this Space',
53
+ watch: 'watching this Space',
54
+ };
55
+ const VISIBILITY_WORD = {
56
+ space_access: 'shared with the Space',
57
+ commitment_access: 'only for people who can open the Commitment',
58
+ };
59
+ /** Which Commitment a loop row came from, and who may see the row. */
60
+ function loopLine(row) {
61
+ const link = LINK_WORD[row.loop.link] || row.loop.link;
62
+ const seen = VISIBILITY_WORD[row.visibility] || row.visibility;
63
+ return `${link} · ${seen}`;
64
+ }
65
+ function detailLines(row) {
66
+ switch (row.kind) {
67
+ case 'task_result': {
68
+ const task = row.task.identifier || row.task.id;
69
+ const conclusion = row.result.conclusionType ? `, ${row.result.conclusionType}` : '';
70
+ const current = row.result.current ? '' : ', superseded';
71
+ return [`task ${task}, result v${row.result.version}${conclusion}${current}`];
72
+ }
73
+ case 'loop_cycle': {
74
+ const stop = row.cycle.stop;
75
+ const lines = [
76
+ stop
77
+ ? `stopped at ${stop.question}/${stop.gate}${stop.reason ? ` (${stop.reason})` : ''}`
78
+ : 'an agent turn was dispatched',
79
+ ];
80
+ if (stop?.fix)
81
+ lines.push(`fix: ${oneLine(stop.fix)}`);
82
+ lines.push(loopLine(row));
83
+ return lines;
84
+ }
85
+ case 'hypothesis': {
86
+ const word = VERDICT_WORD[row.verdict.status] || row.verdict.status;
87
+ const by = row.verdict.authority === 'observation_backed' ? 'settled by readings' : 'agent-reported';
88
+ const lines = [`verdict: ${word} (${by})`];
89
+ if (row.verdict.reason)
90
+ lines.push(`because: ${oneLine(row.verdict.reason)}`);
91
+ lines.push(loopLine(row));
92
+ return lines;
93
+ }
94
+ default:
95
+ return [];
96
+ }
97
+ }
98
+ /** The lines `spaces notebook` prints for one page. */
99
+ function notebookLines(page, { webOrigin, binName }) {
100
+ const lines = [];
101
+ if (!page.rows.length) {
102
+ lines.push(page.nextCursor
103
+ ? 'Nothing on this page.'
104
+ : `No available records in this listing (${page.kinds.map(data_provider_1.spaceNotebookKindLabel).join(', ')}).`);
105
+ }
106
+ for (const row of page.rows) {
107
+ const tag = (KIND_TAG[row.kind] || row.kind).padEnd(10);
108
+ lines.push(`${row.at} ${tag} ${oneLine(row.title, 80)} · ${notebookAuthorLabel(row.author)}`);
109
+ if (row.summary) {
110
+ lines.push(` ${oneLine(row.summary)}${row.summaryTruncated ? ' (cut; open it for the rest)' : ''}`);
111
+ }
112
+ for (const detail of detailLines(row))
113
+ lines.push(` ${detail}`);
114
+ lines.push(` ${webOrigin ? `${webOrigin}${row.link.path}` : row.link.path}`);
115
+ }
116
+ const notes = [];
117
+ for (const source of page.sources) {
118
+ if (source.state !== 'ended')
119
+ continue;
120
+ for (const window of source.windows || []) {
121
+ notes.push((0, data_provider_1.describeSpaceNotebookWindow)(source.kind, window));
122
+ }
123
+ }
124
+ // Who may see a loop row, once per rule the page shows.
125
+ for (const row of page.rows) {
126
+ if ('visibility' in row && row.visibility) {
127
+ notes.push((0, data_provider_1.describeSpaceNotebookVisibility)(row.visibility));
128
+ }
129
+ }
130
+ lines.push('', ...[...new Set(notes)], data_provider_1.SPACE_NOTEBOOK_COVERAGE_NOTE);
131
+ if (page.nextCursor) {
132
+ // A cursor is bound to the filter it was issued for; every kind is the
133
+ // default, so the flag is only repeated when the page was filtered.
134
+ const kinds = page.kinds.length && page.kinds.length < data_provider_1.SPACE_NOTEBOOK_KINDS.length
135
+ ? ` --kinds ${page.kinds.join(',')}`
136
+ : '';
137
+ lines.push('', `More: ${binName} spaces notebook ${page.spaceId}${kinds} --cursor ${page.nextCursor}`);
138
+ }
139
+ return lines;
140
+ }
@@ -0,0 +1,36 @@
1
+ import { BaseCommand } from '../base-command';
2
+ import { type SpaceProposalDecision } from './space-proposals';
3
+ /**
4
+ * The flags `keep` and `discard` share. Exported so each command spreads it
5
+ * into its own `flags`: the command-hygiene scan reads one file at a time and
6
+ * recognises a shared `...xFlags` spread, not a static inherited from a class.
7
+ */
8
+ export declare const spaceProposalDecisionFlags: {
9
+ expected: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ reason: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ 'reason-code': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
+ };
14
+ /**
15
+ * `skrr spaces proposals keep|discard <space> <KIND:ID>` (OSK-17993).
16
+ *
17
+ * Reads the item from the Space's inbox, then sends the decision to the
18
+ * endpoint the item names (`decisionRoute`): the owning object's own. The CLI
19
+ * decides nothing itself and adds no decision path. An Action Bundle is pinned
20
+ * to `--expected`, the revision the caller reviewed in `list`: deciding the
21
+ * bundle as it is NOW would approve writes the caller never saw.
22
+ */
23
+ export declare abstract class SpaceProposalDecisionCommand extends BaseCommand {
24
+ static decision: SpaceProposalDecision;
25
+ static args: {
26
+ space: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
27
+ item: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
28
+ };
29
+ static flags: {
30
+ expected: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
31
+ reason: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
32
+ 'reason-code': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
33
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
34
+ };
35
+ run(): Promise<void>;
36
+ }