@skrr-ai/cli 0.1.97 → 0.1.99
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.
- package/dist/base-command.d.ts +7 -0
- package/dist/base-command.js +10 -1
- package/dist/commands/agents/create.js +3 -3
- package/dist/commands/agents/update.js +22 -3
- package/dist/commands/commitments/create.js +29 -8
- package/dist/commands/commitments/observations.js +3 -1
- package/dist/commands/commitments/update.js +69 -14
- package/dist/commands/machines/dedicated/show.js +1 -0
- package/dist/commands/machines/show.js +13 -4
- package/dist/commands/signals/monitors/create.d.ts +2 -2
- package/dist/commands/signals/monitors/create.js +2 -2
- package/dist/commands/signals/monitors/list.d.ts +2 -2
- package/dist/commands/signals/monitors/list.js +2 -2
- package/dist/commands/signals/monitors/pause.d.ts +2 -2
- package/dist/commands/signals/monitors/pause.js +2 -2
- package/dist/commands/signals/monitors/resume.d.ts +2 -2
- package/dist/commands/signals/monitors/resume.js +2 -2
- package/dist/commands/signals/monitors/revise.d.ts +2 -2
- package/dist/commands/signals/monitors/revise.js +2 -2
- package/dist/commands/signals/monitors/show.d.ts +2 -2
- package/dist/commands/signals/monitors/show.js +2 -2
- package/dist/commands/signals/monitors/test.d.ts +2 -2
- package/dist/commands/signals/monitors/test.js +2 -2
- package/dist/commands/signals/monitors/transitions.d.ts +2 -2
- package/dist/commands/signals/monitors/transitions.js +2 -2
- package/dist/commands/signals/monitors/validate.d.ts +2 -2
- package/dist/commands/signals/monitors/validate.js +2 -2
- package/dist/commands/signals/schemas/list.d.ts +2 -2
- package/dist/commands/signals/schemas/list.js +2 -2
- package/dist/commands/signals/schemas/show.d.ts +2 -2
- package/dist/commands/signals/schemas/show.js +2 -2
- package/dist/commands/signals/sources/list.d.ts +2 -2
- package/dist/commands/signals/sources/list.js +2 -2
- package/dist/commands/signals/sources/receipts.d.ts +2 -2
- package/dist/commands/signals/sources/receipts.js +2 -2
- package/dist/commands/signals/sources/show.d.ts +2 -2
- package/dist/commands/signals/sources/show.js +2 -2
- package/dist/commands/tasks/assign.js +3 -4
- package/dist/commands/tasks/complete.d.ts +1 -0
- package/dist/commands/tasks/complete.js +1 -0
- package/dist/commands/tasks/create.js +4 -2
- package/dist/commands/tasks/deliverable/add.d.ts +1 -0
- package/dist/commands/tasks/deliverable/add.js +1 -0
- package/dist/commands/tasks/result/submit.d.ts +1 -0
- package/dist/commands/tasks/result/submit.js +1 -0
- package/dist/commands/tasks/resume/save.d.ts +1 -0
- package/dist/commands/tasks/resume/save.js +1 -0
- package/dist/commands/tasks/retry.js +38 -6
- package/dist/commands/tasks/show.js +3 -1
- package/dist/commands/tasks/update.js +31 -4
- package/dist/commands/tasks/updates/add.d.ts +1 -0
- package/dist/commands/tasks/updates/add.js +1 -0
- package/dist/lib/commitments.js +34 -2
- package/dist/lib/dedicated-machines.d.ts +5 -7
- package/dist/lib/dedicated-machines.js +19 -10
- package/dist/lib/signals.js +22 -13
- package/dist/lib/space-usage.js +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +35 -19
- package/dist/signal-command.d.ts +11 -0
- package/dist/signal-command.js +15 -0
- package/oclif.manifest.json +1273 -24
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class SourcesList extends
|
|
1
|
+
import { SignalCommand } from '../../../signal-command';
|
|
2
|
+
export default class SourcesList extends SignalCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static flags: {
|
|
5
5
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
|
-
const
|
|
4
|
+
const signal_command_1 = require("../../../signal-command");
|
|
5
5
|
const signals_1 = require("../../../lib/signals");
|
|
6
|
-
class SourcesList extends
|
|
6
|
+
class SourcesList extends signal_command_1.SignalCommand {
|
|
7
7
|
static description = 'List Signal sources (read-only; credentials are never shown)';
|
|
8
8
|
static flags = { json: core_1.Flags.boolean({ description: 'Output as JSON' }) };
|
|
9
9
|
async run() {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class SourcesReceipts extends
|
|
1
|
+
import { SignalCommand } from '../../../signal-command';
|
|
2
|
+
export default class SourcesReceipts extends SignalCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static flags: {
|
|
5
5
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
|
-
const
|
|
4
|
+
const signal_command_1 = require("../../../signal-command");
|
|
5
5
|
const signals_1 = require("../../../lib/signals");
|
|
6
|
-
class SourcesReceipts extends
|
|
6
|
+
class SourcesReceipts extends signal_command_1.SignalCommand {
|
|
7
7
|
static description = 'List recent redacted receipts of a Signal source';
|
|
8
8
|
static flags = { json: core_1.Flags.boolean({ description: 'Output as JSON' }) };
|
|
9
9
|
static args = { id: core_1.Args.string({ required: true, ignoreStdin: true }) };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class SourcesShow extends
|
|
1
|
+
import { SignalCommand } from '../../../signal-command';
|
|
2
|
+
export default class SourcesShow extends SignalCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static flags: {
|
|
5
5
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
|
-
const
|
|
4
|
+
const signal_command_1 = require("../../../signal-command");
|
|
5
5
|
const signals_1 = require("../../../lib/signals");
|
|
6
|
-
class SourcesShow extends
|
|
6
|
+
class SourcesShow extends signal_command_1.SignalCommand {
|
|
7
7
|
static description = 'Show one Signal source (read-only)';
|
|
8
8
|
static flags = { json: core_1.Flags.boolean({ description: 'Output as JSON' }) };
|
|
9
9
|
static args = { id: core_1.Args.string({ required: true, ignoreStdin: true }) };
|
|
@@ -196,11 +196,10 @@ class TasksAssign extends base_command_1.BaseCommand {
|
|
|
196
196
|
if (flags.json) {
|
|
197
197
|
this.log(JSON.stringify({
|
|
198
198
|
...(0, web_url_1.withTaskUrl)(this.cliConfig.baseURL, updated),
|
|
199
|
-
//
|
|
200
|
-
//
|
|
199
|
+
// Keep request details separate from the canonical assignee arrays
|
|
200
|
+
// returned by the server, especially when removing co-assignees.
|
|
201
|
+
assignmentAction: flags.remove ? 'remove' : flags.replace ? 'replace' : 'add',
|
|
201
202
|
resolved: [...people.resolved, ...agents.resolved],
|
|
202
|
-
assigneeUserIds: userIds,
|
|
203
|
-
assigneeAgentIds: agentIds,
|
|
204
203
|
}, null, 2));
|
|
205
204
|
return;
|
|
206
205
|
}
|
|
@@ -10,6 +10,7 @@ export declare function describePendingReview({ statusType, taskId, resultId, bi
|
|
|
10
10
|
}>;
|
|
11
11
|
}): string | null;
|
|
12
12
|
export default class TasksComplete extends BaseCommand {
|
|
13
|
+
static autonomousCredentialPolicy: "bound-session";
|
|
13
14
|
static description: string;
|
|
14
15
|
static examples: string[];
|
|
15
16
|
static args: {
|
|
@@ -99,6 +99,7 @@ function describePendingReview({ statusType, taskId, resultId, bin, advisories,
|
|
|
99
99
|
'may close without one — an override is recorded on the resolution.)');
|
|
100
100
|
}
|
|
101
101
|
class TasksComplete extends base_command_1.BaseCommand {
|
|
102
|
+
static autonomousCredentialPolicy = 'bound-session';
|
|
102
103
|
static description = 'Submit one versioned Result and advance the Task workflow';
|
|
103
104
|
static examples = [
|
|
104
105
|
'<%= config.bin %> tasks complete <task> --summary "Implemented and verified the fix" --deliverable <resource-link-id>',
|
|
@@ -159,9 +159,11 @@ class TasksCreate extends base_command_1.BaseCommand {
|
|
|
159
159
|
description: 'Task priority',
|
|
160
160
|
options: [...tasks_1.TASK_PRIORITIES],
|
|
161
161
|
}),
|
|
162
|
-
parent: core_1.Flags.string({
|
|
162
|
+
parent: core_1.Flags.string({
|
|
163
|
+
description: 'Structural parent task ID. Child statuses roll up; all terminal children can automatically close the parent, with unmet obligations recorded. Use --spawned-by for supporting work without status rollup.',
|
|
164
|
+
}),
|
|
163
165
|
'spawned-by': core_1.Flags.string({
|
|
164
|
-
description: 'Task whose execution produced this one (lineage).
|
|
166
|
+
description: 'Task whose execution produced this one (lineage only, without parent status rollup). Use --parent for structural containment and blockers for ordering.',
|
|
165
167
|
}),
|
|
166
168
|
'spawn-reason': core_1.Flags.string({
|
|
167
169
|
description: 'Why this work exists',
|
|
@@ -10,6 +10,7 @@ export declare function defaultDeliverableIdempotencyKey(task: string, payload:
|
|
|
10
10
|
* optional structured one.
|
|
11
11
|
*/
|
|
12
12
|
export default class TasksDeliverableAdd extends BaseCommand {
|
|
13
|
+
static autonomousCredentialPolicy: "bound-session";
|
|
13
14
|
static description: string;
|
|
14
15
|
static examples: string[];
|
|
15
16
|
static args: {
|
|
@@ -59,6 +59,7 @@ function defaultDeliverableIdempotencyKey(task, payload) {
|
|
|
59
59
|
* optional structured one.
|
|
60
60
|
*/
|
|
61
61
|
class TasksDeliverableAdd extends base_command_1.BaseCommand {
|
|
62
|
+
static autonomousCredentialPolicy = 'bound-session';
|
|
62
63
|
static description = 'Record something this task produced (a commit, a page, a URL, a file, a message, a dataset).\n' +
|
|
63
64
|
'\n' +
|
|
64
65
|
'IDENTITY is the part before @; LOCATION is the part after it. They are not the same ' +
|
|
@@ -53,6 +53,7 @@ function parseJson(value, label) {
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
class TasksResultSubmit extends base_command_1.BaseCommand {
|
|
56
|
+
static autonomousCredentialPolicy = 'bound-session';
|
|
56
57
|
static description = 'Submit the Task Result; this does not self-accept it or turn a domain conclusion into a Review';
|
|
57
58
|
static examples = [
|
|
58
59
|
'<%= config.bin %> tasks result submit <task> --summary "NO-SHIP until Gates A-D pass" --conclusion-type release_recommendation --conclusion-json \'{"posture":"no_ship"}\'',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BaseCommand } from '../../../base-command';
|
|
2
2
|
export default class TasksResumeSave extends BaseCommand {
|
|
3
|
+
static autonomousCredentialPolicy: "bound-session";
|
|
3
4
|
static description: string;
|
|
4
5
|
static args: {
|
|
5
6
|
task: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
@@ -9,6 +9,7 @@ const api_fetch_1 = require("../../../lib/api-fetch");
|
|
|
9
9
|
const session_task_write_1 = require("../../../lib/session-task-write");
|
|
10
10
|
const prompt_1 = require("../../../lib/prompt");
|
|
11
11
|
class TasksResumeSave extends base_command_1.BaseCommand {
|
|
12
|
+
static autonomousCredentialPolicy = 'bound-session';
|
|
12
13
|
static description = 'Save recovery state without publishing a visible Task Update';
|
|
13
14
|
static args = {
|
|
14
15
|
task: core_1.Args.string({ required: false, ignoreStdin: true, description: 'Task id or ref' }),
|
|
@@ -4,6 +4,7 @@ const core_1 = require("@oclif/core");
|
|
|
4
4
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
6
|
const task_resolver_1 = require("../../lib/task-resolver");
|
|
7
|
+
const start_1 = require("./start");
|
|
7
8
|
/**
|
|
8
9
|
* OSK-3815 — the CLI verb for the `retry_task` action.
|
|
9
10
|
*
|
|
@@ -72,8 +73,9 @@ class TasksRetry extends base_command_1.BaseCommand {
|
|
|
72
73
|
// Step 1 — clear the terminal state. `todo` rather than `backlog`: the task
|
|
73
74
|
// was already triaged into the working set once, and a retry is not a
|
|
74
75
|
// decision to deprioritise it.
|
|
76
|
+
let movedTask;
|
|
75
77
|
try {
|
|
76
|
-
await data_provider_1.dataService.moveTask({
|
|
78
|
+
movedTask = await data_provider_1.dataService.moveTask({
|
|
77
79
|
taskId: taskRef,
|
|
78
80
|
status: 'todo',
|
|
79
81
|
});
|
|
@@ -81,13 +83,23 @@ class TasksRetry extends base_command_1.BaseCommand {
|
|
|
81
83
|
catch (err) {
|
|
82
84
|
this.handleApiError(err, { subject: `Task ${taskRef}` });
|
|
83
85
|
}
|
|
86
|
+
// This receipt describes the first committed transition. Dispatch may
|
|
87
|
+
// change the Task again, so it is not an overall current-state snapshot.
|
|
88
|
+
const statusTransition = { requestedStatus: 'todo', task: movedTask };
|
|
84
89
|
if (flags['no-start']) {
|
|
85
90
|
if (flags.json) {
|
|
86
|
-
this.log(JSON.stringify({
|
|
91
|
+
this.log(JSON.stringify({
|
|
92
|
+
taskId: taskRef,
|
|
93
|
+
status: movedTask?.status,
|
|
94
|
+
started: false,
|
|
95
|
+
statusTransition,
|
|
96
|
+
}));
|
|
87
97
|
return;
|
|
88
98
|
}
|
|
89
|
-
this.log(`Cleared failed state on ${taskRef}
|
|
90
|
-
|
|
99
|
+
this.log(`Cleared failed state on ${taskRef}; execution was not requested.`);
|
|
100
|
+
if (typeof movedTask?.status === 'string')
|
|
101
|
+
this.log(`Status: ${movedTask.status}`);
|
|
102
|
+
this.log(`Start it with: ${this.config.bin} tasks start ${taskRef}`);
|
|
91
103
|
return;
|
|
92
104
|
}
|
|
93
105
|
let result;
|
|
@@ -95,12 +107,32 @@ class TasksRetry extends base_command_1.BaseCommand {
|
|
|
95
107
|
result = await data_provider_1.dataService.startTask(taskRef, flags.skill ? { skillId: flags.skill } : undefined);
|
|
96
108
|
}
|
|
97
109
|
catch (err) {
|
|
110
|
+
const waiting = (0, start_1.waitingForMachine)(err);
|
|
111
|
+
if (waiting) {
|
|
112
|
+
if (flags.json) {
|
|
113
|
+
this.log(JSON.stringify({
|
|
114
|
+
waiting: true,
|
|
115
|
+
code: 'TASK_WAITING_FOR_MACHINE',
|
|
116
|
+
taskId: taskRef,
|
|
117
|
+
started: false,
|
|
118
|
+
statusTransition,
|
|
119
|
+
...waiting,
|
|
120
|
+
}, null, 2));
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
this.log(`Task ${taskRef} is waiting for the machine to start; the task will run by itself once it is ready.`);
|
|
124
|
+
if (waiting.message)
|
|
125
|
+
this.log(waiting.message);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const observedStatus = typeof movedTask?.status === 'string' ? ` (returned status '${movedTask.status}')` : '';
|
|
98
129
|
this.handleApiError(err, {
|
|
99
|
-
subject: `Task ${taskRef} (
|
|
130
|
+
subject: `Task ${taskRef} (status transition committed${observedStatus}; start was not confirmed. ` +
|
|
131
|
+
`Check ${this.config.bin} tasks show ${taskRef}, then use ${this.config.bin} tasks start ${taskRef} if needed)`,
|
|
100
132
|
});
|
|
101
133
|
}
|
|
102
134
|
if (flags.json) {
|
|
103
|
-
this.log(JSON.stringify({ ...result, taskId: taskRef,
|
|
135
|
+
this.log(JSON.stringify({ ...result, taskId: taskRef, started: true, statusTransition }, null, 2));
|
|
104
136
|
return;
|
|
105
137
|
}
|
|
106
138
|
this.log(`Retried task ${taskRef}`);
|
|
@@ -518,7 +518,9 @@ class TasksShow extends base_command_1.BaseCommand {
|
|
|
518
518
|
: ''}`);
|
|
519
519
|
const actionability = t.actionability;
|
|
520
520
|
if (actionability) {
|
|
521
|
-
this.log(
|
|
521
|
+
this.log(actionability.state === 'terminal'
|
|
522
|
+
? 'Workflow: ended · no next executor'
|
|
523
|
+
: `Next action: ${actionability.nextActor ?? '-'} · ${actionability.state ?? '-'} · ${actionability.reasonCode ?? '-'}`);
|
|
522
524
|
this.log(`Why: ${actionability.reason ?? '-'}`);
|
|
523
525
|
await this.printBlockerDetail(t, actionability);
|
|
524
526
|
}
|
|
@@ -308,20 +308,47 @@ class TasksUpdate extends base_command_1.BaseCommand {
|
|
|
308
308
|
const field = expectationsPatch !== undefined || body.expectations !== undefined
|
|
309
309
|
? 'Changing Expectations'
|
|
310
310
|
: 'Changing the description';
|
|
311
|
-
|
|
312
|
-
|
|
311
|
+
const disclosure = [
|
|
312
|
+
`${field} advances the Task specification, so ${count} ${noun} ` +
|
|
313
|
+
'will stop counting and must be recorded again.',
|
|
314
|
+
];
|
|
313
315
|
/*
|
|
314
316
|
* NAME them. The count alone made the warning unactionable — and it is
|
|
315
317
|
* task-WIDE, so Expectations you are not touching lose their judgements
|
|
316
318
|
* too, which a bare number actively hides.
|
|
317
319
|
*/
|
|
318
320
|
for (const row of settled) {
|
|
319
|
-
|
|
321
|
+
disclosure.push(` ${row.id} ${row.sentence || row.text || ''}`);
|
|
320
322
|
}
|
|
321
323
|
if (settled.length > 0) {
|
|
322
|
-
|
|
324
|
+
disclosure.push('Revocation covers every Expectation on this Task, including ones this edit ' +
|
|
323
325
|
'does not touch.');
|
|
324
326
|
}
|
|
327
|
+
if (flags.json) {
|
|
328
|
+
// JSON callers acknowledge with --yes. Neither disclosure prose nor
|
|
329
|
+
// an interactive prompt may precede the single machine-readable result.
|
|
330
|
+
this.failWithCliError({
|
|
331
|
+
message: disclosure.join('\n') +
|
|
332
|
+
'\nNo change made — re-run with `--yes` to accept the revocation.',
|
|
333
|
+
code: 'TASK_SPEC_CHANGE_CONFIRMATION_REQUIRED',
|
|
334
|
+
exit: 2,
|
|
335
|
+
retryable: false,
|
|
336
|
+
details: {
|
|
337
|
+
taskId: taskRef,
|
|
338
|
+
assessmentCount: acceptanceUnreadable ? null : settled.length,
|
|
339
|
+
acceptanceReadable: !acceptanceUnreadable,
|
|
340
|
+
affectedExpectations: settled.map((row) => ({
|
|
341
|
+
id: row.id,
|
|
342
|
+
text: row.sentence || row.text || '',
|
|
343
|
+
})),
|
|
344
|
+
revocationScope: 'all_expectations',
|
|
345
|
+
confirmationFlag: '--yes',
|
|
346
|
+
disclosure,
|
|
347
|
+
},
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
for (const line of disclosure)
|
|
351
|
+
this.log(line);
|
|
325
352
|
const ok = await this.confirm('Continue? [y/N] ');
|
|
326
353
|
if (!ok) {
|
|
327
354
|
/*
|
|
@@ -60,6 +60,7 @@ function parseJsonObject(value, label) {
|
|
|
60
60
|
return parsed;
|
|
61
61
|
}
|
|
62
62
|
class TasksUpdatesAdd extends base_command_1.BaseCommand {
|
|
63
|
+
static autonomousCredentialPolicy = 'bound-session';
|
|
63
64
|
static description = 'Record a meaningful Task Update, optionally with recovery state';
|
|
64
65
|
static examples = [
|
|
65
66
|
'<%= config.bin %> tasks updates add <task> --type progress --summary "Migration review complete" --data \'{"completedSinceLast":["Checked migrations 001-014"],"nextActions":["Review authorization"]}\'',
|
package/dist/lib/commitments.js
CHANGED
|
@@ -1037,6 +1037,23 @@ columns, empty, log) {
|
|
|
1037
1037
|
}
|
|
1038
1038
|
(0, format_1.renderTable)(rows, columns, log);
|
|
1039
1039
|
}
|
|
1040
|
+
function describeRunCount(usage, key) {
|
|
1041
|
+
const value = usage?.[key];
|
|
1042
|
+
const status = usage?.[`${key}Status`];
|
|
1043
|
+
if (status === 'unknown' ||
|
|
1044
|
+
typeof value !== 'number' ||
|
|
1045
|
+
!Number.isSafeInteger(value) ||
|
|
1046
|
+
value < 0) {
|
|
1047
|
+
return 'unknown';
|
|
1048
|
+
}
|
|
1049
|
+
// A native session proves a floor, not the provider's complete internal
|
|
1050
|
+
// activity. Preserve that distinction in the human ledger, too.
|
|
1051
|
+
if (status === 'lower_bound')
|
|
1052
|
+
return `at least ${value}`;
|
|
1053
|
+
if (status !== undefined && status !== null)
|
|
1054
|
+
return 'unknown';
|
|
1055
|
+
return String(value);
|
|
1056
|
+
}
|
|
1040
1057
|
/** Human view for `commitments ledger`; JSON remains the automation surface. */
|
|
1041
1058
|
function renderCommitmentLedger(ledger, log) {
|
|
1042
1059
|
const checks = records(ledger.checks);
|
|
@@ -1073,12 +1090,16 @@ function renderCommitmentLedger(ledger, log) {
|
|
|
1073
1090
|
id: text(item.id),
|
|
1074
1091
|
status: text(item.status),
|
|
1075
1092
|
attempt: `${text(item.attempt, '0')}/${text(item.maxAttempts, '-')}`,
|
|
1093
|
+
turns: describeRunCount(record(item.usage), 'turns'),
|
|
1094
|
+
tools: describeRunCount(record(item.usage), 'toolCallCount'),
|
|
1076
1095
|
reason: text(firstValue(item, ['reason', 'error']), ''),
|
|
1077
1096
|
finished: text(firstValue(item, ['completedAt', 'updatedAt', 'startedAt'])),
|
|
1078
1097
|
})), [
|
|
1079
1098
|
{ key: 'id', header: 'RUN ID', verbatim: true },
|
|
1080
1099
|
{ key: 'status', header: 'STATUS', maxWidth: 12 },
|
|
1081
1100
|
{ key: 'attempt', header: 'ATTEMPT' },
|
|
1101
|
+
{ key: 'turns', header: 'TURNS' },
|
|
1102
|
+
{ key: 'tools', header: 'TOOLS' },
|
|
1082
1103
|
{ key: 'reason', header: 'REASON', maxWidth: 36 },
|
|
1083
1104
|
{ key: 'finished', header: 'LAST UPDATED', maxWidth: 24 },
|
|
1084
1105
|
], 'No runs recorded.', log);
|
|
@@ -1247,13 +1268,24 @@ function formatCommitmentCycles(page) {
|
|
|
1247
1268
|
*/
|
|
1248
1269
|
function formatCycleLatency(cycle) {
|
|
1249
1270
|
const latency = cycle.latency;
|
|
1271
|
+
const history = cycle.historyDetail;
|
|
1272
|
+
const disclosure = history?.state === 'compacted'
|
|
1273
|
+
? [
|
|
1274
|
+
` Detailed history was compacted${history.at ? ` at ${history.at}` : ''}; available reason and source timestamps were retained.`,
|
|
1275
|
+
]
|
|
1276
|
+
: history?.state === 'unavailable'
|
|
1277
|
+
? [' Detailed history is unavailable; why it is missing was not recorded.']
|
|
1278
|
+
: [];
|
|
1250
1279
|
const missingFor = (stage) => (latency?.pendingStages ? latency.pendingStages.includes(stage) : latency?.pending)
|
|
1251
1280
|
? 'pending'
|
|
1252
1281
|
: 'unmeasurable';
|
|
1253
1282
|
if (latency?.measured === false) {
|
|
1254
|
-
return [` latency: ${latency.pending ? 'pending' : 'unmeasurable'}`];
|
|
1283
|
+
return [...disclosure, ` latency: ${latency.pending ? 'pending' : 'unmeasurable'}`];
|
|
1255
1284
|
}
|
|
1256
|
-
return
|
|
1285
|
+
return [
|
|
1286
|
+
...disclosure,
|
|
1287
|
+
...Object.entries(latency?.stages || {}).map(([stage, ms]) => ` ${stage === 'event_to_turn' ? 'event_to_turn (server handoff)' : stage}: ${typeof ms === 'number' ? `${ms}ms` : missingFor(stage)}`),
|
|
1288
|
+
];
|
|
1257
1289
|
}
|
|
1258
1290
|
const ANSWER_GLYPH = { yes: '✓', no: '✗', 'n/a': '–' };
|
|
1259
1291
|
/** The six questions for the latest Cycle, the first ✗ carrying its fix. */
|
|
@@ -633,15 +633,13 @@ export declare function dedicatedLeaseDisplayName(lease: DedicatedLease | Harnes
|
|
|
633
633
|
/** `$12.34` — cents are what the API speaks; dollars are what a person reads. */
|
|
634
634
|
export declare function formatUsdCents(cents: number | null | undefined): string;
|
|
635
635
|
/**
|
|
636
|
-
*
|
|
637
|
-
* or why that sentence cannot be written.
|
|
636
|
+
* Name the monthly total that the machine's configured cap is checked against.
|
|
638
637
|
*
|
|
639
|
-
* The
|
|
640
|
-
* is a shared pot the server computes for (owner, team, machineProduct), so every
|
|
638
|
+
* The spend is a shared pot the server computes for (owner, team, machineProduct), so every
|
|
641
639
|
* lease of the same product reports the same number — a machine created minutes
|
|
642
|
-
* ago with no active seconds still reports the month's total. The cap is
|
|
643
|
-
* lease
|
|
644
|
-
*
|
|
640
|
+
* ago with no active seconds still reports the month's total. The cap is set on
|
|
641
|
+
* this lease, but admission compares it against that shared projected total.
|
|
642
|
+
* An old response without spendScope cannot establish who owns the total.
|
|
645
643
|
*/
|
|
646
644
|
export declare function dedicatedSpendSummary(lease: DedicatedLease): string;
|
|
647
645
|
/**
|
|
@@ -673,15 +673,13 @@ function formatUsdCents(cents) {
|
|
|
673
673
|
return `${sign}$${(Math.abs(cents) / 100).toFixed(2)}`;
|
|
674
674
|
}
|
|
675
675
|
/**
|
|
676
|
-
*
|
|
677
|
-
* or why that sentence cannot be written.
|
|
676
|
+
* Name the monthly total that the machine's configured cap is checked against.
|
|
678
677
|
*
|
|
679
|
-
* The
|
|
680
|
-
* is a shared pot the server computes for (owner, team, machineProduct), so every
|
|
678
|
+
* The spend is a shared pot the server computes for (owner, team, machineProduct), so every
|
|
681
679
|
* lease of the same product reports the same number — a machine created minutes
|
|
682
|
-
* ago with no active seconds still reports the month's total. The cap is
|
|
683
|
-
* lease
|
|
684
|
-
*
|
|
680
|
+
* ago with no active seconds still reports the month's total. The cap is set on
|
|
681
|
+
* this lease, but admission compares it against that shared projected total.
|
|
682
|
+
* An old response without spendScope cannot establish who owns the total.
|
|
685
683
|
*/
|
|
686
684
|
function dedicatedSpendSummary(lease) {
|
|
687
685
|
const billing = lease.billing;
|
|
@@ -690,14 +688,22 @@ function dedicatedSpendSummary(lease) {
|
|
|
690
688
|
const cap = billing.monthlySpendLimitCents !== undefined
|
|
691
689
|
? billing.monthlySpendLimitCents
|
|
692
690
|
: billing.spendingLimitCents;
|
|
691
|
+
const scope = billing.spendScope?.kind === 'owner_product'
|
|
692
|
+
? 'your machines of this type'
|
|
693
|
+
: billing.spendScope?.kind === 'workspace_product'
|
|
694
|
+
? "this workspace's machines of this type"
|
|
695
|
+
: 'reported machines (scope unavailable)';
|
|
696
|
+
const capSummary = cap === null
|
|
697
|
+
? 'no monthly cap'
|
|
698
|
+
: `${formatUsdCents(cap)} cap for this machine, checked against the projected monthly total`;
|
|
693
699
|
if (billing.spendStatusUnavailable) {
|
|
694
|
-
return `spend unavailable right now
|
|
700
|
+
return `spend unavailable right now for ${scope} · ${capSummary}`;
|
|
695
701
|
}
|
|
696
702
|
const spent = billing.currentMonthSpendCents;
|
|
697
703
|
const projected = billing.projectedCurrentMonthSpendCents;
|
|
698
704
|
const parts = [
|
|
699
|
-
`${formatUsdCents(spent)} this month for
|
|
700
|
-
|
|
705
|
+
`${formatUsdCents(spent)} this month for ${scope}`,
|
|
706
|
+
capSummary,
|
|
701
707
|
];
|
|
702
708
|
if (typeof projected === 'number' && projected !== spent) {
|
|
703
709
|
parts.push(`projected ${formatUsdCents(projected)}`);
|
|
@@ -815,6 +821,9 @@ function describeDedicatedLease(lease, harnesses = [], opts = {}) {
|
|
|
815
821
|
? ''
|
|
816
822
|
: (0, harnesses_1.describeHealthReasonSentences)(health.reasons, dedicatedLeaseState(lease));
|
|
817
823
|
row('health', health.assignable ? 'can take work' : `not assignable${why ? `: ${why}` : ''}`);
|
|
824
|
+
if (health.assignable) {
|
|
825
|
+
row('provider auth', `separate from runtime health; inspect saved sign-in: skrr machines dedicated sign-in-status ${dedicatedLeaseId(lease)} (credentials supplied for a run may differ)`);
|
|
826
|
+
}
|
|
818
827
|
}
|
|
819
828
|
row('spend', lease.billing ? dedicatedSpendSummary(lease) : undefined);
|
|
820
829
|
const deletionPlan = dedicatedDeletionLines(lease);
|
package/dist/lib/signals.js
CHANGED
|
@@ -2,23 +2,32 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.signalsApi = void 0;
|
|
4
4
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
|
+
const workspace_header_1 = require("./workspace-header");
|
|
6
|
+
function inSignalWorkspace(operation) {
|
|
7
|
+
if (!(0, workspace_header_1.withWorkspaceHeader)({})['X-Workspace-Id']) {
|
|
8
|
+
throw new Error(process.env.OVERSKY_AUTONOMOUS_SESSION === '1'
|
|
9
|
+
? 'Signal commands require a workspace-bound session. This session has no canonical workspace; --workspace and local selections cannot change its scope. No Signal request was sent.'
|
|
10
|
+
: 'Signal commands require a selected workspace. Pass --workspace <workspace-id>, or run `skrr workspaces list --json` then `skrr workspaces use <workspace-id>`. No Signal request was sent.');
|
|
11
|
+
}
|
|
12
|
+
return operation();
|
|
13
|
+
}
|
|
5
14
|
/**
|
|
6
15
|
* Secret-free Signal lifecycle (`/api/signal-monitors`, read-only sources and schemas).
|
|
7
16
|
* Source creation, credentials and schema review hand out one-display secrets and stay
|
|
8
17
|
* in the reviewed UI until a headless secret-display contract is approved.
|
|
9
18
|
*/
|
|
10
19
|
exports.signalsApi = {
|
|
11
|
-
listMonitors: () => data_provider_1.request.get('/api/signal-monitors'),
|
|
12
|
-
showMonitor: (id) => data_provider_1.request.get(`/api/signal-monitors/${encodeURIComponent(id)}`),
|
|
13
|
-
validateMonitor: (body) => data_provider_1.request.post('/api/signal-monitors/validate', body),
|
|
14
|
-
createMonitor: (body) => data_provider_1.request.post('/api/signal-monitors', body),
|
|
15
|
-
testMonitor: (id, body) => data_provider_1.request.post(`/api/signal-monitors/${encodeURIComponent(id)}/test`, body),
|
|
16
|
-
reviseMonitor: (id, body) => data_provider_1.request.post(`/api/signal-monitors/${encodeURIComponent(id)}/revisions`, body),
|
|
17
|
-
setMonitorStatus: (id, status) => data_provider_1.request.patch(`/api/signal-monitors/${encodeURIComponent(id)}`, { status }),
|
|
18
|
-
monitorTransitions: (id) => data_provider_1.request.get(`/api/signal-monitors/${encodeURIComponent(id)}/transitions`),
|
|
19
|
-
listSources: () => data_provider_1.request.get('/api/signal-sources'),
|
|
20
|
-
showSource: (id) => data_provider_1.request.get(`/api/signal-sources/${encodeURIComponent(id)}`),
|
|
21
|
-
sourceReceipts: (id) => data_provider_1.request.get(`/api/signal-sources/${encodeURIComponent(id)}/receipts`),
|
|
22
|
-
listSchemas: () => data_provider_1.request.get('/api/signal-schemas'),
|
|
23
|
-
showSchema: (id) => data_provider_1.request.get(`/api/signal-schemas/${encodeURIComponent(id)}`),
|
|
20
|
+
listMonitors: () => inSignalWorkspace(() => data_provider_1.request.get('/api/signal-monitors')),
|
|
21
|
+
showMonitor: (id) => inSignalWorkspace(() => data_provider_1.request.get(`/api/signal-monitors/${encodeURIComponent(id)}`)),
|
|
22
|
+
validateMonitor: (body) => inSignalWorkspace(() => data_provider_1.request.post('/api/signal-monitors/validate', body)),
|
|
23
|
+
createMonitor: (body) => inSignalWorkspace(() => data_provider_1.request.post('/api/signal-monitors', body)),
|
|
24
|
+
testMonitor: (id, body) => inSignalWorkspace(() => data_provider_1.request.post(`/api/signal-monitors/${encodeURIComponent(id)}/test`, body)),
|
|
25
|
+
reviseMonitor: (id, body) => inSignalWorkspace(() => data_provider_1.request.post(`/api/signal-monitors/${encodeURIComponent(id)}/revisions`, body)),
|
|
26
|
+
setMonitorStatus: (id, status) => inSignalWorkspace(() => data_provider_1.request.patch(`/api/signal-monitors/${encodeURIComponent(id)}`, { status })),
|
|
27
|
+
monitorTransitions: (id) => inSignalWorkspace(() => data_provider_1.request.get(`/api/signal-monitors/${encodeURIComponent(id)}/transitions`)),
|
|
28
|
+
listSources: () => inSignalWorkspace(() => data_provider_1.request.get('/api/signal-sources')),
|
|
29
|
+
showSource: (id) => inSignalWorkspace(() => data_provider_1.request.get(`/api/signal-sources/${encodeURIComponent(id)}`)),
|
|
30
|
+
sourceReceipts: (id) => inSignalWorkspace(() => data_provider_1.request.get(`/api/signal-sources/${encodeURIComponent(id)}/receipts`)),
|
|
31
|
+
listSchemas: () => inSignalWorkspace(() => data_provider_1.request.get('/api/signal-schemas')),
|
|
32
|
+
showSchema: (id) => inSignalWorkspace(() => data_provider_1.request.get(`/api/signal-schemas/${encodeURIComponent(id)}`)),
|
|
24
33
|
};
|
package/dist/lib/space-usage.js
CHANGED
|
@@ -10,7 +10,7 @@ const usd = (amount) => amount > 0 && amount < 0.01 ? '<$0.01' : `$${amount.toFi
|
|
|
10
10
|
function formatSpaceSpend(summary) {
|
|
11
11
|
const attribution = `Attribution since: ${summary.coverage.attributionSince || 'not certified'}; not attributed: ${summary.coverage.notAttributed.join(', ')}`;
|
|
12
12
|
if (summary.runCount === 0)
|
|
13
|
-
return `No runs in window\n${attribution}`;
|
|
13
|
+
return `No attributed runs in window\n${attribution}`;
|
|
14
14
|
const cost = summary.costUsd === null ? 'Not fully attributed' : usd(summary.costUsd);
|
|
15
15
|
const known = summary.knownCostUsd === null ? 'unavailable' : usd(summary.knownCostUsd);
|
|
16
16
|
return `${cost}; known subtotal ${known}; ${summary.runCount} cost records; ${summary.byCostStatus.unavailable} unavailable, ${summary.byCostStatus.partial} partial\n${attribution}`;
|