@skrr-ai/cli 0.1.102 → 0.1.103

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 (47) hide show
  1. package/dist/base-command.js +24 -0
  2. package/dist/commands/agent/message/send.js +6 -2
  3. package/dist/commands/agents/triggers/create.js +7 -17
  4. package/dist/commands/agents/triggers/update.js +41 -28
  5. package/dist/commands/commitments/preflight.js +18 -1
  6. package/dist/commands/commitments/roster.d.ts +15 -0
  7. package/dist/commands/commitments/roster.js +39 -0
  8. package/dist/commands/commitments/show.js +1 -1
  9. package/dist/commands/commitments/status.d.ts +17 -0
  10. package/dist/commands/commitments/status.js +41 -0
  11. package/dist/commands/commitments/update.js +12 -0
  12. package/dist/commands/daemon/logs.d.ts +39 -1
  13. package/dist/commands/daemon/logs.js +140 -13
  14. package/dist/commands/followups/checkin.js +46 -3
  15. package/dist/commands/tasks/approvals/resolve.d.ts +12 -0
  16. package/dist/commands/tasks/approvals/resolve.js +21 -5
  17. package/dist/commands/triggers/create.js +8 -17
  18. package/dist/commands/triggers/fire.js +3 -0
  19. package/dist/commands/triggers/update.js +41 -27
  20. package/dist/commands/widgets/check.d.ts +39 -0
  21. package/dist/commands/widgets/check.js +179 -0
  22. package/dist/lib/agent-mailbox.d.ts +0 -1
  23. package/dist/lib/agent-mailbox.js +0 -1
  24. package/dist/lib/commitment-loop-status.d.ts +16 -0
  25. package/dist/lib/commitment-loop-status.js +164 -0
  26. package/dist/lib/commitments.d.ts +28 -1
  27. package/dist/lib/commitments.js +184 -5
  28. package/dist/lib/delegated-cli.d.ts +23 -1
  29. package/dist/lib/delegated-cli.js +61 -4
  30. package/dist/lib/first-party-harness.d.ts +1 -1
  31. package/dist/lib/first-party-harness.js +1 -1
  32. package/dist/lib/session-task-write.d.ts +13 -0
  33. package/dist/lib/session-task-write.js +63 -3
  34. package/dist/lib/triggers.d.ts +26 -0
  35. package/dist/lib/triggers.js +134 -1
  36. package/dist/lib/widgetCheck.d.ts +123 -0
  37. package/dist/lib/widgetCheck.js +998 -0
  38. package/dist/lib/widgetStaticScan.d.ts +111 -0
  39. package/dist/lib/widgetStaticScan.js +833 -0
  40. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.d.ts +9 -1
  41. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.js +12 -0
  42. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.d.ts +9 -1
  43. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.js +12 -0
  44. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  45. package/dist/node_modules/@skrr-ai/data-provider/index.js +11902 -8696
  46. package/oclif.manifest.json +218 -5
  47. package/package.json +2 -2
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.WIDGETS_CHECK_EXIT = void 0;
37
+ const core_1 = require("@oclif/core");
38
+ const fs = __importStar(require("node:fs"));
39
+ const prompt_1 = require("../../lib/prompt");
40
+ const widgetCheck_1 = require("../../lib/widgetCheck");
41
+ /**
42
+ * `skrr widgets check` — the offline self-check a harness runs in Bash BEFORE it
43
+ * replies, because a rejected widget is only discovered after the message is sent.
44
+ *
45
+ * It extends `Command`, not `BaseCommand`, on purpose: it reads a file or stdin and
46
+ * prints, so it must work with no sign-in, no network and no daemon credential
47
+ * (a sandboxed harness has none, and `BaseCommand.init()` resolves one before any
48
+ * command body runs). The same reason `instructions guide` does it.
49
+ *
50
+ * It reaches NO API. There is no route behind it, so there is nothing for the
51
+ * CLI/API parity spec (`domain-api-parity.spec.ts`) to hold it to: it adds nothing
52
+ * to `api-endpoints.ts` or `dataService`, and it is safe to run anywhere.
53
+ *
54
+ * Exit codes: 0 every widget would be accepted and has no error finding; 1 at
55
+ * least one would be refused or has an error finding (or none was found); 2 the
56
+ * input could not be read.
57
+ */
58
+ exports.WIDGETS_CHECK_EXIT = { ok: 0, notOk: 1, unreadable: 2 };
59
+ class WidgetsCheck extends core_1.Command {
60
+ static description = 'Check a generative-UI widget offline before sending it: grammar, size limits, JavaScript syntax and likely sandbox failures. Runs entirely offline: it reaches no API, so it needs no sign-in and has no route to keep in parity.';
61
+ static examples = [
62
+ '<%= config.bin %> widgets check reply.md',
63
+ '<%= config.bin %> widgets check - < reply.md',
64
+ '<%= config.bin %> widgets check widget.json --json',
65
+ '<%= config.bin %> widgets check widget.json --render-fence > block.txt',
66
+ ];
67
+ static args = {
68
+ file: core_1.Args.string({
69
+ description: 'File to check, or - for stdin. Text containing a widget block, or a JSON widget (a payload, a ui_widget part, or the ui_widget_render arguments, one or an array).',
70
+ required: true,
71
+ ignoreStdin: true,
72
+ }),
73
+ };
74
+ static flags = {
75
+ json: core_1.Flags.boolean({
76
+ description: 'Output the report as JSON: { ok, widgets: [{ id, title, bytes, limits, complete, accepted, ok, issues }], errors, warnings, summary }',
77
+ }),
78
+ format: core_1.Flags.string({
79
+ description: 'How to read the input: auto (JSON if it parses as JSON, otherwise text that contains a widget block), fence, or json',
80
+ options: ['auto', 'fence', 'json'],
81
+ default: 'auto',
82
+ }),
83
+ strict: core_1.Flags.boolean({
84
+ description: 'Also fail (exit 1) on warnings',
85
+ default: false,
86
+ }),
87
+ 'render-fence': core_1.Flags.boolean({
88
+ description: 'For a JSON widget: print the correctly delimited block to stdout (the report goes to stderr), verified by parsing it back',
89
+ default: false,
90
+ }),
91
+ };
92
+ async run() {
93
+ const { args, flags } = await this.parse(WidgetsCheck);
94
+ const read = await this.readInput(args.file);
95
+ if (!read.ok) {
96
+ this.emitInputError(flags.json, read.error);
97
+ this.exit(exports.WIDGETS_CHECK_EXIT.unreadable);
98
+ }
99
+ const result = (0, widgetCheck_1.checkWidgetInput)(read.text, {
100
+ format: flags.format,
101
+ strict: flags.strict,
102
+ });
103
+ if (flags['render-fence']) {
104
+ const rendered = (0, widgetCheck_1.renderWidgetFences)(result);
105
+ const report = {
106
+ ...result.report,
107
+ errors: [...result.report.errors, ...rendered.errors],
108
+ };
109
+ report.ok = report.ok && rendered.errors.length === 0;
110
+ report.summary = {
111
+ ...report.summary,
112
+ errors: report.summary.errors + rendered.errors.length,
113
+ };
114
+ if (flags.json) {
115
+ this.log(JSON.stringify({ ...report, fences: rendered.fences }, null, 2));
116
+ }
117
+ else {
118
+ for (const fence of rendered.fences) {
119
+ this.log(fence);
120
+ }
121
+ process.stderr.write(`${(0, widgetCheck_1.formatWidgetCheckReport)(report).join('\n')}\n`);
122
+ }
123
+ this.exit(report.ok ? exports.WIDGETS_CHECK_EXIT.ok : exports.WIDGETS_CHECK_EXIT.notOk);
124
+ }
125
+ if (flags.json) {
126
+ this.log(JSON.stringify(result.report, null, 2));
127
+ }
128
+ else {
129
+ this.log((0, widgetCheck_1.formatWidgetCheckReport)(result.report).join('\n'));
130
+ }
131
+ this.exit(result.report.ok ? exports.WIDGETS_CHECK_EXIT.ok : exports.WIDGETS_CHECK_EXIT.notOk);
132
+ }
133
+ async readInput(source) {
134
+ try {
135
+ if (source === '-') {
136
+ if (process.stdin.isTTY) {
137
+ return {
138
+ ok: false,
139
+ error: {
140
+ code: 'input/no-stdin',
141
+ message: 'No input on stdin: it is a terminal, so there is nothing to read.',
142
+ fix: `Pipe the widget in (${this.config.bin} widgets check - < reply.md) or pass a file path.`,
143
+ },
144
+ };
145
+ }
146
+ return { ok: true, text: await (0, prompt_1.readStdin)() };
147
+ }
148
+ const size = fs.statSync(source).size;
149
+ if (size > widgetCheck_1.WIDGET_CHECK_MAX_INPUT_CHARS * 4) {
150
+ return {
151
+ ok: false,
152
+ error: {
153
+ code: 'input/too-large',
154
+ message: `${source} is ${size} bytes, far more than a message can carry.`,
155
+ },
156
+ };
157
+ }
158
+ return { ok: true, text: fs.readFileSync(source, 'utf8') };
159
+ }
160
+ catch (err) {
161
+ return {
162
+ ok: false,
163
+ error: {
164
+ code: 'input/unreadable',
165
+ message: `Could not read ${source}: ${err?.message ?? String(err)}`,
166
+ fix: 'Pass the path of a readable file, or - to read stdin.',
167
+ },
168
+ };
169
+ }
170
+ }
171
+ emitInputError(json, error) {
172
+ if (json) {
173
+ this.log(JSON.stringify((0, widgetCheck_1.inputErrorReport)(error), null, 2));
174
+ return;
175
+ }
176
+ process.stderr.write(`error: ${error.message}\n${error.fix ? ` fix: ${error.fix}\n` : ''}`);
177
+ }
178
+ }
179
+ exports.default = WidgetsCheck;
@@ -3,7 +3,6 @@ export interface AgentMailboxMetadata {
3
3
  id: string;
4
4
  agentId: string;
5
5
  workspaceId: string;
6
- handle: string;
7
6
  address: string;
8
7
  status: string;
9
8
  sending: string;
@@ -20,7 +20,6 @@ async function getAgentMailboxMetadata(agentId) {
20
20
  id: mailbox.id,
21
21
  agentId: mailbox.agentId,
22
22
  workspaceId: mailbox.workspaceId,
23
- handle: mailbox.handle,
24
23
  address: mailbox.address,
25
24
  status: mailbox.status,
26
25
  sending: mailbox.sending,
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Text rendering for `skrr commitments roster` / `skrr commitments status`.
3
+ *
4
+ * The loop state is DERIVED server-side (`CommitmentLoopStatus`); this file
5
+ * only words it. Two rules it must keep:
6
+ * - paused, unarmed and degraded read differently — "you paused it", "nothing
7
+ * will wake it" and "it cannot see" have different fixes;
8
+ * - `unknown` never borrows the healthy wording or an OK mark. "Cannot see"
9
+ * is not "fine".
10
+ */
11
+ import { type CommitmentLoopStatus, type CommitmentRoster } from '@skrr-ai/data-provider';
12
+ export declare function loopStateLabel(state: unknown): string;
13
+ /** Roster table: one row per Commitment. */
14
+ export declare function formatCommitmentRoster(roster: Partial<CommitmentRoster>): string[];
15
+ /** One Commitment's loop, in full. */
16
+ export declare function formatCommitmentLoopStatus(status: CommitmentLoopStatus): string[];
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loopStateLabel = loopStateLabel;
4
+ exports.formatCommitmentRoster = formatCommitmentRoster;
5
+ exports.formatCommitmentLoopStatus = formatCommitmentLoopStatus;
6
+ /**
7
+ * Text rendering for `skrr commitments roster` / `skrr commitments status`.
8
+ *
9
+ * The loop state is DERIVED server-side (`CommitmentLoopStatus`); this file
10
+ * only words it. Two rules it must keep:
11
+ * - paused, unarmed and degraded read differently — "you paused it", "nothing
12
+ * will wake it" and "it cannot see" have different fixes;
13
+ * - `unknown` never borrows the healthy wording or an OK mark. "Cannot see"
14
+ * is not "fine".
15
+ */
16
+ const data_provider_1 = require("@skrr-ai/data-provider");
17
+ const format_1 = require("./format");
18
+ /** One word per state, with a mark only `healthy` may use. */
19
+ const STATE_LABEL = {
20
+ healthy: '✓ healthy',
21
+ blocked: '! blocked',
22
+ paused: '‖ paused',
23
+ unarmed: '! unarmed',
24
+ degraded: '! degraded',
25
+ inactive: '- inactive',
26
+ unknown: '? unknown',
27
+ };
28
+ function loopStateLabel(state) {
29
+ return typeof state === 'string' && state in STATE_LABEL
30
+ ? STATE_LABEL[state]
31
+ : STATE_LABEL.unknown;
32
+ }
33
+ function when(value) {
34
+ if (typeof value !== 'string')
35
+ return '-';
36
+ const date = new Date(value);
37
+ if (Number.isNaN(date.getTime()))
38
+ return '-';
39
+ const pad = (n) => String(n).padStart(2, '0');
40
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;
41
+ }
42
+ function count(value) {
43
+ return typeof value === 'number' && Number.isFinite(value) ? String(value) : '?';
44
+ }
45
+ function runs(status) {
46
+ const used = count(status.cost?.runsToday);
47
+ const max = status.cost?.maxRunsPerDay;
48
+ return typeof max === 'number' ? `${used}/${max}` : used;
49
+ }
50
+ function spend(status) {
51
+ const value = status.cost?.spendTodayUsd;
52
+ if (typeof value !== 'number')
53
+ return 'not metered';
54
+ const amount = `$${value.toFixed(2)}`;
55
+ // A partial ledger is a lower bound; never print it as the whole answer.
56
+ return status.cost?.spendKnown ? amount : `≥ ${amount} (some runs unpriced)`;
57
+ }
58
+ function nextWake(status) {
59
+ const wake = status.nextWakes?.[0];
60
+ return wake ? `${when(wake.at)} ${wake.kind}` : '-';
61
+ }
62
+ function watchSummary(status) {
63
+ const rows = Array.isArray(status.watching) ? status.watching : [];
64
+ if (!rows.length)
65
+ return '-';
66
+ return rows
67
+ .map((row) => {
68
+ const mark = row.access === 'blocked'
69
+ ? '✗'
70
+ : row.access === 'unknown'
71
+ ? '?'
72
+ : row.completeness === 'partial'
73
+ ? '~'
74
+ : '✓';
75
+ return `${row.source}${mark}`;
76
+ })
77
+ .join(' ');
78
+ }
79
+ /** Roster table: one row per Commitment. */
80
+ function formatCommitmentRoster(roster) {
81
+ const lines = [];
82
+ const commitments = Array.isArray(roster.commitments) ? roster.commitments : [];
83
+ lines.push(`Agent ${roster.agentId ?? '-'} — ${commitments.length} commitment${commitments.length === 1 ? '' : 's'}`);
84
+ if (!commitments.length) {
85
+ lines.push('No commitments.');
86
+ return lines;
87
+ }
88
+ (0, format_1.renderTable)(commitments.map((status) => ({
89
+ state: loopStateLabel(status.loopState),
90
+ id: status.commitmentId,
91
+ title: status.systemRole ? `${status.title} [${status.systemRole}]` : status.title,
92
+ next: nextWake(status),
93
+ runs: runs(status),
94
+ watching: watchSummary(status),
95
+ reason: status.loopReason ?? '',
96
+ })), [
97
+ { key: 'state', header: 'STATE' },
98
+ { key: 'id', header: 'ID', verbatim: true },
99
+ { key: 'title', header: 'TITLE', maxWidth: 36 },
100
+ { key: 'next', header: 'NEXT WAKE' },
101
+ { key: 'runs', header: 'RUNS TODAY' },
102
+ { key: 'watching', header: 'WATCHING', maxWidth: 40 },
103
+ { key: 'reason', header: 'REASON', maxWidth: 40 },
104
+ ], (line) => lines.push(line));
105
+ const attention = commitments.filter((status) => !['healthy', 'paused', 'inactive'].includes(String(status.loopState))).length;
106
+ if (attention) {
107
+ lines.push(`${attention} need${attention === 1 ? 's' : ''} attention — run \`skrr commitments status <id>\` for why.`);
108
+ }
109
+ if (roster.truncated) {
110
+ lines.push('More commitments exist than this roster shows.');
111
+ }
112
+ return lines;
113
+ }
114
+ /** One Commitment's loop, in full. */
115
+ function formatCommitmentLoopStatus(status) {
116
+ const lines = [];
117
+ lines.push(`${status.title} (${status.commitmentId})${status.systemRole ? ` [${status.systemRole}]` : ''}`);
118
+ lines.push(` Loop: ${loopStateLabel(status.loopState)}${status.loopReason ? ` (${status.loopReason})` : ''}`);
119
+ lines.push(` ${status.loopDetail || (0, data_provider_1.describeCommitmentLoopState)(status.loopState)}`);
120
+ lines.push(` Lifecycle: ${status.lifecycleStatus}`);
121
+ lines.push(` Last check: ${when(status.lastCheckAt)}`);
122
+ lines.push(` Last seen: ${when(status.lastSuccessfulObservationAt)}`);
123
+ if (status.lastStop) {
124
+ // `fix` is an optional contract field; read it defensively across package builds.
125
+ const stop = status.lastStop;
126
+ lines.push(` Last stop: ${stop.question}${stop.reason ? ` — ${stop.reason}` : ''}`);
127
+ if (stop.detail)
128
+ lines.push(` ${stop.detail}`);
129
+ if (stop.fix)
130
+ lines.push(` Fix: ${stop.fix}`);
131
+ }
132
+ const wakes = Array.isArray(status.nextWakes) ? status.nextWakes : [];
133
+ lines.push(' Next wakes:');
134
+ if (!wakes.length) {
135
+ lines.push(status.loopState === 'unknown'
136
+ ? ' (could not be read)'
137
+ : ' none — nothing is scheduled to wake it');
138
+ }
139
+ for (const wake of wakes) {
140
+ lines.push(` ${when(wake.at)} ${wake.kind}${wake.reason ? ` (${wake.reason})` : ''}`);
141
+ }
142
+ const watching = Array.isArray(status.watching) ? status.watching : [];
143
+ lines.push(' Watching:');
144
+ if (!watching.length)
145
+ lines.push(' nothing declared');
146
+ for (const row of watching) {
147
+ const access = row.access === 'readable'
148
+ ? row.completeness === 'partial'
149
+ ? 'readable, PARTIAL read'
150
+ : 'readable'
151
+ : row.access === 'blocked'
152
+ ? 'CANNOT READ'
153
+ : 'not known';
154
+ lines.push(` ${row.source}${row.scope ? ` (${row.scope})` : ''}: ${access}${row.reason ? ` — ${row.reason}` : ''}`);
155
+ // Optional contract field; read defensively across package builds.
156
+ const limitations = row.limitations;
157
+ if (Array.isArray(limitations) && limitations.length) {
158
+ lines.push(` not watched: ${limitations.join(', ')}`);
159
+ }
160
+ }
161
+ lines.push(` Open loops: ${count(status.pendingWork?.openLoops)} Pending runs: ${count(status.pendingWork?.pendingRuns)}`);
162
+ lines.push(` Runs today: ${runs(status)} Spend today: ${spend(status)}`);
163
+ return lines;
164
+ }
@@ -18,7 +18,7 @@ import { type CommitmentObservationsQuery, type CommitmentObservationsResponse }
18
18
  * "hold this state", derived from a Compass invariant — not authored here).
19
19
  */
20
20
  import { COMMITMENT_WATCHED_SOURCES, COMMITMENT_TEMPLATE_IDS, COMMITMENT_CADENCE_MODES, COMMITMENT_CADENCE_TIME_PATTERN, COMMITMENT_CADENCE_MAX_TIMES, COMMITMENT_EXECUTION_ISOLATION_MODES, COMMITMENT_STATUSES, COMMITMENT_KIND_VALUES } from '@skrr-ai/data-provider';
21
- import type { CommitmentCheck, CommitmentChecksResponse, Commitment, CommitmentActionProposal, CommitmentListResponse, CommitmentPlanResponse, CommitmentStatusResponse, CommitmentWorkLink, CommitmentExecutionReceiptListResponse, CommitmentExecutionReceiptQuarterlyMetricsResponse, CommitmentCapabilitySource, CommitmentDeliveryPatchResponse, CommitmentDeliveryBundleResponse, CommitmentCyclesResponse, CommitmentExplanationResponse, CommitmentRunPermissions } from '@skrr-ai/data-provider';
21
+ import type { CommitmentCheck, CommitmentChecksResponse, Commitment, CommitmentActionProposal, CommitmentListResponse, CommitmentPlanResponse, CommitmentStatusResponse, CommitmentWorkLink, CommitmentExecutionReceiptListResponse, CommitmentExecutionReceiptQuarterlyMetricsResponse, CommitmentCapabilitySource, CommitmentDeliveryPatchResponse, CommitmentDeliveryBundleResponse, CommitmentCyclesResponse, CommitmentExplanationResponse, CommitmentRunPermissions, CommitmentLoopStatus, CommitmentRoster } from '@skrr-ai/data-provider';
22
22
  import { withQuery } from './triggers';
23
23
  export { COMMITMENT_WATCHED_SOURCES, COMMITMENT_TEMPLATE_IDS, COMMITMENT_CADENCE_MODES, COMMITMENT_CADENCE_TIME_PATTERN, COMMITMENT_CADENCE_MAX_TIMES, COMMITMENT_STATUSES, COMMITMENT_KIND_VALUES, };
24
24
  export type { CommitmentCheck, CommitmentChecksResponse, Commitment, CommitmentActionProposal, CommitmentListResponse, CommitmentPlanResponse, CommitmentStatusResponse, CommitmentWorkLink, };
@@ -223,6 +223,10 @@ export declare const commitmentApi: {
223
223
  * swept, how stale that is, and the tally it last persisted. Aggregate only.
224
224
  */
225
225
  livenessSweep: () => Promise<Record<string, unknown>>;
226
+ /** One agent's Commitments, system roles included, each with its loop status. */
227
+ roster: (agentId: string) => Promise<CommitmentRoster>;
228
+ /** Is this Commitment's loop installed and working. */
229
+ loopStatus: (id: string) => Promise<CommitmentLoopStatus>;
226
230
  manifest: (id: string) => Promise<Record<string, unknown>>;
227
231
  import: (body: Record<string, unknown>) => Promise<{
228
232
  commitment: {
@@ -737,6 +741,17 @@ export declare function extractStandstillFromCheck(check?: {
737
741
  * null rather than printing a guess.
738
742
  */
739
743
  export declare function describeExecutorBlocked(commitment: CommitmentView): string | null;
744
+ /**
745
+ * The commitment `show` should render: its stored contract, with the
746
+ * assessment replaced by the one the operating state recomputed for this read
747
+ * when the server sent one (OSK-15989). The stored `commitment.assessment` is
748
+ * what the LAST check wrote; while a run is in flight it can still say
749
+ * `blocked`, and printing it above "Agent is working" made the header
750
+ * contradict the rest of the page. `doctor` already reads the live one first.
751
+ */
752
+ export declare function withLiveAssessment(commitment: CommitmentView, operatingState?: {
753
+ assessment?: unknown;
754
+ } | null): CommitmentView;
740
755
  export declare function renderCommitmentSummary(commitment: CommitmentView, log: (line: string) => void,
741
756
  /**
742
757
  * The most recent check, when the caller has one. Optional because pause /
@@ -776,6 +791,7 @@ type ReadModelRecord = Record<string, unknown>;
776
791
  /** Human view for `commitments ledger`; JSON remains the automation surface. */
777
792
  export declare function renderCommitmentLedger(ledger: ReadModelRecord, log: (line: string) => void): void;
778
793
  export declare function renderCommitmentTrace(trace: ReadModelRecord, log: (line: string) => void): void;
794
+ export declare function renderProactivenessScorecard(scorecard: ReadModelRecord, log: (line: string) => void): void;
779
795
  /**
780
796
  * One line per Cycle:
781
797
  * `09-22 12:04 ● stopped act commitment_execution_budget_exhausted — Raise maxRunsPerDay…`
@@ -793,6 +809,17 @@ export declare function renderListPageHint(page: {
793
809
  has_more?: boolean;
794
810
  next_cursor?: string | null;
795
811
  } | undefined, log: (line: string) => void): void;
812
+ /**
813
+ * Whether a row's retained evidence can still be reopened (OSK-16125).
814
+ *
815
+ * The count alone read as evidence even when every path pointed into a
816
+ * worktree the daemon had already deleted. `retained` artifacts are git
817
+ * locators on the run's delivery commit; `ephemeral` ones cannot be counted
818
+ * on; `unconfirmed` are locators for a path the run did not change. Refs the
819
+ * server classified as none of these (URLs, hashes, legacy rows) count as
820
+ * `other`. `--json` carries each artifact's `ref`, `locator` and `originalRef`.
821
+ */
822
+ export declare function describeObservationArtifacts(artifacts: unknown): string;
796
823
  export declare function renderCommitmentObservations(response: ReadModelRecord, log: (line: string) => void, options?: {
797
824
  emptyMessage?: string;
798
825
  }): void;