@skrr-ai/cli 0.1.127 → 0.1.129

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 (165) hide show
  1. package/dist/base-command.d.ts +35 -0
  2. package/dist/base-command.js +107 -0
  3. package/dist/commands/agenda/trigger/list.d.ts +2 -1
  4. package/dist/commands/agenda/trigger/list.js +55 -6
  5. package/dist/commands/agents/chat.js +7 -0
  6. package/dist/commands/agents/create.js +3 -1
  7. package/dist/commands/browser/persistent-profile.d.ts +22 -0
  8. package/dist/commands/browser/persistent-profile.js +46 -0
  9. package/dist/commands/commitments/action-history.js +1 -1
  10. package/dist/commands/commitments/cases.js +3 -3
  11. package/dist/commands/commitments/check-now.d.ts +10 -2
  12. package/dist/commands/commitments/check-now.js +53 -3
  13. package/dist/commands/commitments/create.d.ts +6 -14
  14. package/dist/commands/commitments/create.js +64 -7
  15. package/dist/commands/commitments/doctor.js +3 -1
  16. package/dist/commands/commitments/effective-policy.d.ts +11 -1
  17. package/dist/commands/commitments/effective-policy.js +90 -4
  18. package/dist/commands/commitments/explain.js +10 -1
  19. package/dist/commands/commitments/hypotheses.js +12 -12
  20. package/dist/commands/commitments/next-tick.js +5 -0
  21. package/dist/commands/commitments/observations.js +18 -17
  22. package/dist/commands/commitments/pack/list.js +2 -1
  23. package/dist/commands/commitments/pack/plan.d.ts +6 -0
  24. package/dist/commands/commitments/pack/plan.js +19 -0
  25. package/dist/commands/commitments/plan.d.ts +14 -0
  26. package/dist/commands/commitments/plan.js +32 -0
  27. package/dist/commands/commitments/preflight.d.ts +20 -1
  28. package/dist/commands/commitments/preflight.js +118 -12
  29. package/dist/commands/commitments/show.d.ts +9 -0
  30. package/dist/commands/commitments/show.js +14 -1
  31. package/dist/commands/commitments/trigger-status.js +8 -0
  32. package/dist/commands/commitments/update.d.ts +1 -0
  33. package/dist/commands/commitments/update.js +45 -4
  34. package/dist/commands/commitments/wake-capabilities.js +13 -0
  35. package/dist/commands/compass/archive.js +4 -0
  36. package/dist/commands/compass/commitments.js +15 -1
  37. package/dist/commands/compass/create.js +11 -3
  38. package/dist/commands/compass/effective-policy.d.ts +1 -0
  39. package/dist/commands/compass/effective-policy.js +8 -7
  40. package/dist/commands/compass/revert.d.ts +8 -0
  41. package/dist/commands/compass/revert.js +25 -1
  42. package/dist/commands/compass/revisions.d.ts +6 -0
  43. package/dist/commands/compass/revisions.js +26 -2
  44. package/dist/commands/compass/tactic.d.ts +10 -3
  45. package/dist/commands/compass/tactic.js +22 -7
  46. package/dist/commands/compass/update.js +19 -3
  47. package/dist/commands/followups/act.js +1 -1
  48. package/dist/commands/followups/cancel.js +13 -0
  49. package/dist/commands/followups/observability.js +20 -1
  50. package/dist/commands/followups/plans/create.js +12 -1
  51. package/dist/commands/followups/show.js +13 -0
  52. package/dist/commands/followups/watch.js +1 -1
  53. package/dist/commands/goals/planner-config.d.ts +11 -0
  54. package/dist/commands/goals/planner-config.js +16 -0
  55. package/dist/commands/harnesses/list.js +1 -1
  56. package/dist/commands/machines/update.d.ts +5 -3
  57. package/dist/commands/machines/update.js +70 -9
  58. package/dist/commands/northstars/create.js +3 -1
  59. package/dist/commands/northstars/governance/configure.d.ts +4 -0
  60. package/dist/commands/northstars/governance/configure.js +76 -10
  61. package/dist/commands/northstars/intents/decide.d.ts +6 -0
  62. package/dist/commands/northstars/intents/decide.js +68 -15
  63. package/dist/commands/northstars/intents/list.d.ts +2 -1
  64. package/dist/commands/northstars/intents/list.js +15 -5
  65. package/dist/commands/northstars/intents.d.ts +26 -0
  66. package/dist/commands/northstars/intents.js +49 -0
  67. package/dist/commands/northstars/list.d.ts +1 -0
  68. package/dist/commands/northstars/list.js +24 -3
  69. package/dist/commands/northstars/recommendations/list.d.ts +1 -1
  70. package/dist/commands/northstars/recommendations/list.js +3 -3
  71. package/dist/commands/northstars/recommendations.d.ts +19 -0
  72. package/dist/commands/northstars/recommendations.js +42 -0
  73. package/dist/commands/northstars/review-now.d.ts +1 -0
  74. package/dist/commands/northstars/review-now.js +15 -4
  75. package/dist/commands/northstars/reviews.d.ts +1 -0
  76. package/dist/commands/northstars/reviews.js +34 -6
  77. package/dist/commands/northstars/update.js +8 -1
  78. package/dist/commands/proposals/list.js +11 -2
  79. package/dist/commands/proposals/show.js +9 -1
  80. package/dist/commands/spaces/auto-executor/preview.d.ts +14 -1
  81. package/dist/commands/spaces/auto-executor/preview.js +35 -1
  82. package/dist/commands/spaces/auto-executor/run.d.ts +17 -0
  83. package/dist/commands/spaces/auto-executor/run.js +60 -2
  84. package/dist/commands/spaces/auto-executor/runs.d.ts +9 -1
  85. package/dist/commands/spaces/auto-executor/runs.js +18 -1
  86. package/dist/commands/spaces/files/upload.js +1 -2
  87. package/dist/commands/spaces/heartbeats/create.js +7 -5
  88. package/dist/commands/spaces/heartbeats/update.js +5 -3
  89. package/dist/commands/spaces/index.js +23 -0
  90. package/dist/commands/store/artifacts/releases.d.ts +20 -0
  91. package/dist/commands/store/artifacts/releases.js +85 -0
  92. package/dist/commands/store/library.d.ts +14 -0
  93. package/dist/commands/store/library.js +71 -0
  94. package/dist/commands/tasks/list.d.ts +48 -0
  95. package/dist/commands/tasks/list.js +141 -9
  96. package/dist/commands/tasks/remind.js +23 -11
  97. package/dist/commands/tasks/retry-schedule.js +6 -3
  98. package/dist/commands/tasks/schedule.js +29 -7
  99. package/dist/commands/tasks/show.js +4 -0
  100. package/dist/generated/agent-guides.json +69 -69
  101. package/dist/lib/agent-trigger-listing.d.ts +26 -0
  102. package/dist/lib/agent-trigger-listing.js +63 -0
  103. package/dist/lib/agentic-stream.d.ts +9 -0
  104. package/dist/lib/agentic-stream.js +152 -41
  105. package/dist/lib/command-miss.js +11 -2
  106. package/dist/lib/commitment-attention-copy.d.ts +96 -0
  107. package/dist/lib/commitment-attention-copy.js +209 -0
  108. package/dist/lib/commitment-ledgers.js +3 -1
  109. package/dist/lib/commitment-loop-status.d.ts +6 -0
  110. package/dist/lib/commitment-loop-status.js +16 -6
  111. package/dist/lib/commitments.d.ts +112 -0
  112. package/dist/lib/commitments.js +250 -2
  113. package/dist/lib/compass-body-help.d.ts +20 -0
  114. package/dist/lib/compass-body-help.js +61 -0
  115. package/dist/lib/compass-refusals.d.ts +35 -0
  116. package/dist/lib/compass-refusals.js +50 -0
  117. package/dist/lib/compasses.d.ts +82 -4
  118. package/dist/lib/compasses.js +232 -12
  119. package/dist/lib/followups.d.ts +22 -1
  120. package/dist/lib/followups.js +21 -1
  121. package/dist/lib/format.d.ts +11 -0
  122. package/dist/lib/format.js +29 -0
  123. package/dist/lib/initiatives.d.ts +9 -2
  124. package/dist/lib/initiatives.js +13 -2
  125. package/dist/lib/iso-instant.d.ts +52 -0
  126. package/dist/lib/iso-instant.js +162 -0
  127. package/dist/lib/machines.d.ts +14 -1
  128. package/dist/lib/machines.js +24 -0
  129. package/dist/lib/northstars.d.ts +201 -24
  130. package/dist/lib/northstars.js +655 -27
  131. package/dist/lib/proposal-decision-command.js +21 -1
  132. package/dist/lib/proposals.d.ts +26 -1
  133. package/dist/lib/proposals.js +167 -0
  134. package/dist/lib/rate-limit-retry.d.ts +5 -0
  135. package/dist/lib/rate-limit-retry.js +19 -0
  136. package/dist/lib/roles.d.ts +1 -1
  137. package/dist/lib/space-charter.js +9 -0
  138. package/dist/lib/store-artifact-releases.d.ts +39 -0
  139. package/dist/lib/store-artifact-releases.js +12 -0
  140. package/dist/lib/store-library.d.ts +37 -0
  141. package/dist/lib/store-library.js +12 -0
  142. package/dist/lib/task-asset-upload.js +1 -2
  143. package/dist/lib/task-calendar.d.ts +19 -0
  144. package/dist/lib/task-calendar.js +72 -0
  145. package/dist/lib/task-recurrence-outcome.js +3 -1
  146. package/dist/lib/task-recurrence-summary.d.ts +15 -0
  147. package/dist/lib/task-recurrence-summary.js +228 -0
  148. package/dist/lib/task-reminder.d.ts +28 -0
  149. package/dist/lib/task-reminder.js +50 -0
  150. package/dist/lib/triggers.d.ts +13 -2
  151. package/dist/lib/triggers.js +31 -13
  152. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonWire.js +11 -1
  153. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/executorStopReceipt.d.ts +123 -0
  154. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/executorStopReceipt.js +160 -0
  155. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -0
  156. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +17 -0
  157. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonWire.js +11 -1
  158. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/executorStopReceipt.d.ts +123 -0
  159. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/executorStopReceipt.js +173 -0
  160. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -0
  161. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +2 -0
  162. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  163. package/dist/node_modules/@skrr-ai/data-provider/index.js +6922 -6828
  164. package/oclif.manifest.json +612 -62
  165. package/package.json +4 -4
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+ /**
3
+ * The attention settings of a Commitment, said in words.
4
+ *
5
+ * `show`, `effective-policy` and `preflight` all print these, from this one
6
+ * file, so the three cannot phrase a setting three ways. A value is described
7
+ * from the RAW stored setting and never through a coercion: `null` is "no
8
+ * limit" and `0` is "muted", and `Number(null)` is `0`, which is exactly how a
9
+ * cap that was never set would read as a mute (the server documents the same
10
+ * trap at `policySchema.maxUserNudgesPerDay` in api/server/routes/commitments.js).
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.EVENT_SOURCES_HELP = exports.QUIET_HOURS_HELP = exports.CLOCK_TIME_HINT = exports.MAX_NUDGES_FLAG_HELP = void 0;
14
+ exports.parseMaxNudgesFlag = parseMaxNudgesFlag;
15
+ exports.describeNudgeCap = describeNudgeCap;
16
+ exports.describeNudgeGap = describeNudgeGap;
17
+ exports.describeNoReplyRule = describeNoReplyRule;
18
+ exports.nudgeSettingsFromPolicy = nudgeSettingsFromPolicy;
19
+ exports.nudgeSettingLines = nudgeSettingLines;
20
+ exports.describeEventSources = describeEventSources;
21
+ exports.quietHoursInputProblem = quietHoursInputProblem;
22
+ exports.describeQuietHours = describeQuietHours;
23
+ exports.describeQuietHoursEnd = describeQuietHoursEnd;
24
+ /** What the owner can type for `--max-nudges`, as `--help` prints it. */
25
+ exports.MAX_NUDGES_FLAG_HELP = 'Daily limit on messages that interrupt you: a whole number from 0 up (0 mutes it: ' +
26
+ 'it never contacts you) or "unlimited" to remove the limit. Left unset it is unlimited';
27
+ /**
28
+ * Parse `--max-nudges`: a whole number, or the word `unlimited` (stored as `null`).
29
+ * The server accepts 0 up to MAX_SAFE_INTEGER, so there is no 0..20 ceiling here.
30
+ */
31
+ function parseMaxNudgesFlag(raw) {
32
+ if (raw === undefined)
33
+ return undefined;
34
+ const value = raw.trim().toLowerCase();
35
+ if (value === 'unlimited')
36
+ return null;
37
+ if (/^\d+$/.test(value)) {
38
+ const parsed = Number(value);
39
+ if (Number.isSafeInteger(parsed))
40
+ return parsed;
41
+ }
42
+ throw new Error(`--max-nudges must be a whole number (0 mutes it) or the word "unlimited"; got "${raw}".`);
43
+ }
44
+ /** `null` and an unset cap are "no daily limit"; `0` is a mute; N is "at most N a day". */
45
+ function describeNudgeCap(value) {
46
+ if (value === null || value === undefined)
47
+ return 'no daily limit';
48
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
49
+ return `unreadable (${String(value)})`;
50
+ }
51
+ if (value <= 0)
52
+ return 'muted: it never contacts you';
53
+ return `at most ${value} a day`;
54
+ }
55
+ function durationWords(ms) {
56
+ if (ms < 60_000)
57
+ return `${Math.max(1, Math.round(ms / 1000))} s`;
58
+ const totalMinutes = Math.round(ms / 60_000);
59
+ const days = Math.floor(totalMinutes / 1440);
60
+ const hours = Math.floor((totalMinutes % 1440) / 60);
61
+ const minutes = totalMinutes % 60;
62
+ return [days ? `${days} d` : '', hours ? `${hours} h` : '', minutes ? `${minutes} min` : '']
63
+ .filter(Boolean)
64
+ .join(' ');
65
+ }
66
+ /** The least time the platform leaves between two nudges to you. */
67
+ function describeNudgeGap(ms) {
68
+ if (ms === null || ms === undefined || ms === 0)
69
+ return 'no minimum gap between nudges';
70
+ if (typeof ms !== 'number' || !Number.isFinite(ms) || ms < 0) {
71
+ return `unreadable (${String(ms)})`;
72
+ }
73
+ return `at least ${durationWords(ms)} between nudges`;
74
+ }
75
+ /** The back-off for a person who is not answering. The server's default count is 2. */
76
+ function describeNoReplyRule(noReply) {
77
+ if (noReply?.enabled !== true)
78
+ return 'off: it keeps nudging whether or not you answer';
79
+ const after = Number.isInteger(noReply.afterNudges) ? noReply.afterNudges : 2;
80
+ return `after ${after} unanswered nudge${after === 1 ? '' : 's'} it waits until you reply`;
81
+ }
82
+ /** Read the three settings out of a stored `policy`. */
83
+ function nudgeSettingsFromPolicy(policy) {
84
+ return {
85
+ maxUserNudgesPerDay: policy.maxUserNudgesPerDay,
86
+ minUserNudgeIntervalMs: policy.minUserNudgeIntervalMs,
87
+ noReply: policy.attention?.noReply,
88
+ };
89
+ }
90
+ /**
91
+ * The lines that say how much a Commitment may interrupt its owner. A muted one
92
+ * prints the mute alone: a gap and a back-off on a Commitment that never speaks
93
+ * would only suggest it does. `withNoReply: false` leaves the back-off out when the
94
+ * stored rule could not be read, rather than claim it is off.
95
+ */
96
+ function nudgeSettingLines(settings, { withNoReply = true } = {}) {
97
+ const lines = [`Nudges: ${describeNudgeCap(settings.maxUserNudgesPerDay)}`];
98
+ const muted = typeof settings.maxUserNudgesPerDay === 'number' && settings.maxUserNudgesPerDay <= 0;
99
+ if (muted)
100
+ return lines;
101
+ lines.push(`Min gap: ${describeNudgeGap(settings.minUserNudgeIntervalMs)}`);
102
+ if (withNoReply)
103
+ lines.push(`No reply: ${describeNoReplyRule(settings.noReply)}`);
104
+ return lines;
105
+ }
106
+ const CLOCK = /^(\d{1,2}):(\d{2})$/;
107
+ /** What a time of day is, in the words a person can type. */
108
+ exports.CLOCK_TIME_HINT = 'use HH:MM, 00:00-23:59, for example 22:00';
109
+ /**
110
+ * How to set quiet hours, for the `--from-json` help of `create` and `update`. There is no flag for
111
+ * them, so without this sentence a user had to know the `policy.quietHours` key from outside the CLI
112
+ * (OSK-21123).
113
+ */
114
+ exports.QUIET_HOURS_HELP = 'Quiet hours (no messages to you) go in the JSON as policy.quietHours: ' +
115
+ '{"enabled":true,"start":"22:00","end":"07:00","timezone":"America/Los_Angeles"}. ' +
116
+ 'Times are 24-hour HH:MM (00:00-23:59); the window may cross midnight and its end is not ' +
117
+ 'inside it; timezone is an IANA name, and when omitted it is UTC, not your local zone.';
118
+ /**
119
+ * What `policy.executionBudget.allowedEventSources` means, for the same help. An empty list is the
120
+ * unrestricted case, which is the opposite of what `[]` suggests (OSK-21113).
121
+ */
122
+ exports.EVENT_SOURCES_HELP = 'policy.executionBudget.allowedEventSources limits which event sources may wake the Commitment: ' +
123
+ 'an empty or missing list allows every source (it is not "none"); name sources to restrict it.';
124
+ /**
125
+ * The allowlist in words. An empty or missing list means every source is allowed
126
+ * (`sourceAllowed` in api/server/services/EventBus/commitmentWakeCapabilities.js and the check in
127
+ * WakeIntentResolver.js both treat it so); the stored form of "never set" is the same `[]`.
128
+ */
129
+ function describeEventSources(allowed) {
130
+ return Array.isArray(allowed) && allowed.length
131
+ ? `limited to: ${allowed.map(String).join(', ')}`
132
+ : 'all allowed (the list is empty)';
133
+ }
134
+ function validClock(value) {
135
+ if (typeof value !== 'string')
136
+ return false;
137
+ const match = CLOCK.exec(value);
138
+ return Boolean(match) && Number(match[1]) <= 23 && Number(match[2]) <= 59;
139
+ }
140
+ /**
141
+ * The problem with the quiet-hours times in a `policy` about to be sent, or null. The server
142
+ * answered a bad time with its raw pattern (`must match pattern /^\d{1,2}:\d{2}$/`), which says
143
+ * nothing a person can type, and accepted `25:00` (a window that then never applies). Checked
144
+ * here, so the request never leaves with either.
145
+ */
146
+ function quietHoursInputProblem(policy) {
147
+ const quietHours = policy?.quietHours;
148
+ if (!quietHours || typeof quietHours !== 'object')
149
+ return null;
150
+ for (const key of ['start', 'end']) {
151
+ const value = quietHours[key];
152
+ if (value !== undefined && !validClock(value)) {
153
+ return `policy.quietHours.${key} ${JSON.stringify(value)} is not a time of day: ${exports.CLOCK_TIME_HINT}.`;
154
+ }
155
+ }
156
+ return null;
157
+ }
158
+ /** `9:00` and `09:00` are the same time to the server; show the zero-padded form. */
159
+ function clockText(value) {
160
+ const match = CLOCK.exec(String(value ?? '').trim());
161
+ return match ? `${match[1].padStart(2, '0')}:${match[2]}` : String(value ?? '');
162
+ }
163
+ /** An omitted timezone is UTC, and no text surface said so (OSK-21122). */
164
+ const NO_TIMEZONE_NOTE = 'UTC (no timezone set, UTC is used)';
165
+ /**
166
+ * The Commitment's own quiet-hours window in words. Without one of its own a Commitment uses its
167
+ * Agent's Compass window (`scheduleIssues.js` documents the same rule), so "none set" says where
168
+ * else a window may come from rather than claiming there is no quiet time at all.
169
+ */
170
+ function describeQuietHours(quietHours) {
171
+ if (!quietHours) {
172
+ return "none set on this Commitment (a window in its Agent's Compass applies, if it has one)";
173
+ }
174
+ const zone = quietHours.timezone ? quietHours.timezone : NO_TIMEZONE_NOTE;
175
+ const window = quietHours.start && quietHours.end
176
+ ? `${clockText(quietHours.start)}-${clockText(quietHours.end)} ${zone}`
177
+ : null;
178
+ if (quietHours.enabled !== true) {
179
+ return window ? `off (${window} is saved but switched off)` : 'off';
180
+ }
181
+ if (!window)
182
+ return 'on, but start and end are not both set, so no quiet window applies';
183
+ if (clockText(quietHours.start) === clockText(quietHours.end)) {
184
+ return `${window}: start and end are the same time, so the window is empty and nothing is held`;
185
+ }
186
+ return window;
187
+ }
188
+ /** `2026-11-01T15:00:00.000Z` as `2026-11-01 15:00 UTC`. */
189
+ function utcText(iso) {
190
+ const parsed = typeof iso === 'string' ? new Date(iso) : null;
191
+ if (!parsed || Number.isNaN(parsed.getTime()))
192
+ return null;
193
+ return `${parsed.toISOString().slice(0, 16).replace('T', ' ')} UTC`;
194
+ }
195
+ /**
196
+ * When a held message is released, for the preflight line "Held until your quiet hours end".
197
+ * The report's `quietHours` carries the end as typed, the zone, and the exact instant (`endsAt`,
198
+ * daylight saving included); null when it carries no instant, so the caller keeps its generic
199
+ * sentence rather than inventing a time.
200
+ */
201
+ function describeQuietHoursEnd(quietHours) {
202
+ const utc = utcText(quietHours?.endsAt);
203
+ if (!utc)
204
+ return null;
205
+ const zone = quietHours?.timezone || 'UTC';
206
+ if (zone === 'UTC' || !quietHours?.end)
207
+ return `Held until your quiet hours end: ${utc}.`;
208
+ return `Held until your quiet hours end: ${clockText(quietHours.end)} ${zone}, ${utc}.`;
209
+ }
@@ -45,7 +45,9 @@ function renderActionHistory(page, log) {
45
45
  status: text(row.status),
46
46
  check: text(row.checkId),
47
47
  // A failed or refused action's reason is the point of reading history.
48
- why: [text(row.errorCode, ''), brief(row.errorMessage ?? row.reason)]
48
+ // A skipped action says why in `skippedReason` (a zero budget, a fenced Check), which this column
49
+ // never read, so every skipped row printed an empty WHY (OSK-21610).
50
+ why: [text(row.errorCode, ''), brief(row.errorMessage ?? row.skippedReason ?? row.reason)]
49
51
  .filter(Boolean)
50
52
  .join(' · '),
51
53
  })), [
@@ -10,6 +10,12 @@
10
10
  */
11
11
  import { type CommitmentLoopStatus, type CommitmentRoster } from '@skrr-ai/data-provider';
12
12
  export declare function loopStateLabel(state: unknown): string;
13
+ /**
14
+ * What an empty "next wakes" list means. "Nothing is scheduled" is true only of an unarmed loop: a held
15
+ * wake IS scheduled and is being refused, and the line above it says "armed" (OSK-21261). Unknown stays
16
+ * "could not be read" because cannot-see is not none.
17
+ */
18
+ export declare function noNextWakeText(status: Pick<CommitmentLoopStatus, 'loopState' | 'loopReason'>): string;
13
19
  /** Roster table: one row per Commitment. */
14
20
  export declare function formatCommitmentRoster(roster: Partial<CommitmentRoster>): string[];
15
21
  /**
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.loopStateLabel = loopStateLabel;
4
+ exports.noNextWakeText = noNextWakeText;
4
5
  exports.formatCommitmentRoster = formatCommitmentRoster;
5
6
  exports.formatLoopSummary = formatLoopSummary;
6
7
  exports.formatCommitmentLoopStatus = formatCommitmentLoopStatus;
@@ -64,6 +65,19 @@ function spend(status) {
64
65
  // A partial ledger is a lower bound; never print it as the whole answer.
65
66
  return status.cost?.spendKnown ? amount : `≥ ${amount} (some runs unpriced)`;
66
67
  }
68
+ /**
69
+ * What an empty "next wakes" list means. "Nothing is scheduled" is true only of an unarmed loop: a held
70
+ * wake IS scheduled and is being refused, and the line above it says "armed" (OSK-21261). Unknown stays
71
+ * "could not be read" because cannot-see is not none.
72
+ */
73
+ function noNextWakeText(status) {
74
+ if (status.loopState === 'unknown')
75
+ return 'could not be read';
76
+ if (status.loopReason === 'wake_control_blocked' || status.loopReason === 'wake_admission_blocked') {
77
+ return 'none while its wakes are held (see the loop line)';
78
+ }
79
+ return 'none — nothing is scheduled to wake it';
80
+ }
67
81
  function nextWake(status) {
68
82
  const wake = status.nextWakes?.[0];
69
83
  return wake ? `${when(wake.at)} ${wake.kind}` : '-';
@@ -136,9 +150,7 @@ function formatLoopSummary(status) {
136
150
  const wake = status.nextWakes?.[0];
137
151
  lines.push(`next wake: ${wake
138
152
  ? `${when(wake.at)} ${wake.kind}`
139
- : status.loopState === 'unknown'
140
- ? 'could not be read'
141
- : 'none — nothing is scheduled to wake it'}`);
153
+ : noNextWakeText(status)}`);
142
154
  if (status.lastStop) {
143
155
  const stop = status.lastStop;
144
156
  lines.push(`last stop: ${stop.question}${stop.reason ? ` — ${stop.reason}` : ''}${stop.detail ? `: ${stop.detail}` : ''}`);
@@ -189,9 +201,7 @@ function formatCommitmentLoopStatus(status) {
189
201
  const wakes = Array.isArray(status.nextWakes) ? status.nextWakes : [];
190
202
  lines.push(' Next wakes:');
191
203
  if (!wakes.length) {
192
- lines.push(status.loopState === 'unknown'
193
- ? ' (could not be read)'
194
- : ' none — nothing is scheduled to wake it');
204
+ lines.push(status.loopState === 'unknown' ? ' (could not be read)' : ` ${noNextWakeText(status)}`);
195
205
  }
196
206
  for (const wake of wakes) {
197
207
  lines.push(` ${when(wake.at)} ${wake.kind}${wake.reason ? ` (${wake.reason})` : ''}`);
@@ -60,6 +60,12 @@ export type CommitmentPreflightReport = {
60
60
  id: string;
61
61
  label: string;
62
62
  verdict: 'pass' | 'indeterminate' | 'block';
63
+ /**
64
+ * Whether this gate can stop a Run (`blocking`) or only informs (`advisory`). An advisory gate
65
+ * can still say `block` (a Pack that watches its Goal through a link, not a watched source,
66
+ * has "no observation source"); it stops nothing and never feeds the verdict.
67
+ */
68
+ admission?: 'blocking' | 'advisory';
63
69
  /** Short machine code for why a gate did NOT pass. */
64
70
  reason?: string | null;
65
71
  /**
@@ -96,7 +102,41 @@ export type CommitmentPreflightReport = {
96
102
  retired?: string[];
97
103
  retiredReason?: string;
98
104
  } & Record<string, unknown>;
105
+ /**
106
+ * Whether Resume / `create --activate` would be accepted, answered by the server's one activation
107
+ * rule (`CommitmentActivation`). Absent from an older server. A gate can be advisory for a run and
108
+ * still refuse activation, so this is the answer, not the gate list.
109
+ */
110
+ activation?: {
111
+ canActivate?: boolean;
112
+ blockers?: Array<{
113
+ gate: string;
114
+ label?: string;
115
+ reason?: string;
116
+ hint?: string;
117
+ }>;
118
+ } | null;
99
119
  };
120
+ /**
121
+ * The lines preflight prints when the server says activation would be refused (OSK-21258). The gate
122
+ * list marks an advisory gate `info (advisory: does not stop a run)`, which is true of a run and false
123
+ * of activation: `resume` refused the same gate with a 409 while preflight read as if nothing stopped
124
+ * it. The server owns which gates refuse; this lays out its answer and never re-derives it. Nothing
125
+ * for an allowed activation or an older server that does not send the block.
126
+ */
127
+ export declare function activationRefusalLines(activation: CommitmentPreflightReport['activation']): string[];
128
+ /**
129
+ * Whether the server's activation answer names this gate as one that refuses activation (OSK-21258).
130
+ * A gate can be advisory for a run (`admission: 'advisory'`) and still be what `resume` refuses with a
131
+ * 409; the gate list printed it `info (advisory: does not stop a run)` right under an "Activation:
132
+ * would be refused" section naming the same gate. Matches on the gate id, and on the reason too when
133
+ * both sides carry one, so a gate advisory for one reason is not promoted by another. An older server
134
+ * that sends no answer promotes nothing.
135
+ */
136
+ export declare function gateRefusesActivation(activation: CommitmentPreflightReport['activation'], gate: {
137
+ id?: string;
138
+ reason?: string | null;
139
+ }): boolean;
100
140
  /**
101
141
  * The lines every Commitment read surface prints for "whose permissions does a
102
142
  * run use?" — `show`, `effective-policy` and `preflight` share it so the three
@@ -161,6 +201,8 @@ export type CommitmentPackPreflightResponse = {
161
201
  export type CommitmentPackDefinition = {
162
202
  id: string;
163
203
  version: string;
204
+ /** The Pack's name as the server sends it. `title` is not a field of the catalogue (OSK-21110). */
205
+ label?: string;
164
206
  title?: string;
165
207
  description?: string;
166
208
  [key: string]: unknown;
@@ -179,6 +221,17 @@ export type CommitmentPackPlanResponse = {
179
221
  agentId: string;
180
222
  holder?: 'space_lead' | 'explicit';
181
223
  };
224
+ /**
225
+ * What the plan cannot fix and `pack preflight` would report later: today only a holder whose
226
+ * runtime can never activate this loop. Beside the plan, outside its digest.
227
+ */
228
+ readiness?: Array<{
229
+ gate: string;
230
+ label: string;
231
+ verdict: 'block';
232
+ reason: string;
233
+ hint?: string;
234
+ }>;
182
235
  [key: string]: unknown;
183
236
  };
184
237
  export type CommitmentPackBindResponse = {
@@ -719,6 +772,21 @@ export declare function readCommitmentAgentDirective({ directive, file, }: {
719
772
  directive?: string;
720
773
  file?: string;
721
774
  }): Promise<string | undefined>;
775
+ /**
776
+ * The top-level keys of a `--from-json` body that `create`/`preflight` will not send. A key within two edits
777
+ * of a real one is a `typo`; the rest are `ignored`. A server-owned dump field is neither.
778
+ */
779
+ export declare function unrecognizedCreateKeys(src: Record<string, unknown>): {
780
+ typos: Array<{
781
+ key: string;
782
+ suggestion: string;
783
+ }>;
784
+ ignored: string[];
785
+ };
786
+ /** The keys of a `--from-json` body that are neither sent nor server-owned and not a typo: to be warned about. */
787
+ export declare function ignoredCreateKeys(input: Record<string, unknown>): string[];
788
+ /** The one sentence `create` and `preflight` print for them. */
789
+ export declare function ignoredCreateKeysWarning(keys: string[]): string | null;
722
790
  /**
723
791
  * Normalize a `--from-json` body into something the create endpoint accepts.
724
792
  *
@@ -951,6 +1019,34 @@ export declare function commitmentWriteWarnings(response: unknown, fallback: {
951
1019
  /** One `Warning:` line per authoring warning, after the write's own output. */
952
1020
  export declare function renderCommitmentWriteWarnings(warnings: CommitmentAuthoringWarning[], warn: (line: string) => void): void;
953
1021
  export declare function describeCommitmentRevision(revision: CommitmentRevisionReceipt | undefined): string;
1022
+ /**
1023
+ * A commitment's priority, as one line: `high · weight 70 · from northstar`.
1024
+ *
1025
+ * Linking a commitment to a northstar rewrites its priority (`source: northstar`) and a governor
1026
+ * reprioritization changes it again, so the place a person looks to confirm either is `show`, which
1027
+ * printed everything but this and sent them to `--json`. An unset priority says so rather than
1028
+ * printing nothing.
1029
+ */
1030
+ export declare function describeCommitmentPriority(priority: CommitmentView['priority']): string;
1031
+ /**
1032
+ * The `Compass:` line of a bound commitment. A commitment names its compass (`compassId`) but the
1033
+ * read does not carry that compass's STATUS, and an archived one governs nothing (the commitment
1034
+ * runs on defaults), so the id alone could be read as "governed by it". Only what is known is
1035
+ * stated: the id, and the command that says whether it is active (OSK-21242).
1036
+ */
1037
+ export declare function describeBoundCompass(commitment: Pick<CommitmentView, 'compassId' | 'agentId'>): string;
1038
+ /**
1039
+ * The bound Compass, as `explain` prints it (OSK-21332). `explain` is where a person asks "why does
1040
+ * this Commitment behave this way", and a bound Compass (or an archived one, which runs the
1041
+ * Commitment on defaults) is part of the answer. The explain payload names neither the Compass nor
1042
+ * its status, so the caller reads the Commitment itself, the same read `show` renders, and hands the
1043
+ * result here: the line is `describeBoundCompass`, the one `show` prints, not a second wording.
1044
+ *
1045
+ * `null` means that read did not come back. It is said, not skipped: a silent skip is
1046
+ * indistinguishable from "no Compass is bound". A Commitment bound to none prints nothing, as in
1047
+ * `show`.
1048
+ */
1049
+ export declare function explainCompassLines(commitmentId: string, commitment: Pick<CommitmentView, 'compassId' | 'agentId'> | null | undefined): string[];
954
1050
  export declare function renderCommitmentSummary(commitment: CommitmentView, log: (line: string) => void,
955
1051
  /**
956
1052
  * The most recent check, when the caller has one. Optional because pause /
@@ -1011,10 +1107,26 @@ export declare function hypothesisRefusalLines(run: {
1011
1107
  count: number;
1012
1108
  }>;
1013
1109
  }): string[];
1110
+ /**
1111
+ * A wake the Agent asked for and the platform did not arm, in the server's words.
1112
+ * The only record used to be `ledger --json`; the cycle read `advanced` (OSK-21132).
1113
+ */
1114
+ export declare function wakeOutcomeLines(run: {
1115
+ wake?: {
1116
+ status?: string;
1117
+ reason?: string;
1118
+ detail?: string;
1119
+ fix?: string;
1120
+ };
1121
+ }): string[];
1014
1122
  export declare function formatCommitmentExplanation(explanation: Partial<CommitmentExplanationResponse>): string[];
1015
1123
  /**
1016
1124
  * Print the continuation hint for a paged `object:'list'` response — the line
1017
1125
  * that makes history beyond the newest page reachable instead of invisible.
1126
+ *
1127
+ * Text mode ONLY. Under `--json` stdout must be one JSON document, and the same
1128
+ * facts are already in it as `has_more` / `next_cursor`: a caller that prints
1129
+ * this after the JSON makes `| json.load` fail (OSK-21118).
1018
1130
  */
1019
1131
  export declare function renderListPageHint(page: {
1020
1132
  has_more?: boolean;