@skrr-ai/cli 0.1.104 → 0.1.106
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.js +6 -2
- package/dist/commands/agenda/trigger/list.js +2 -0
- package/dist/commands/agents/chat.js +4 -1
- package/dist/commands/agents/operating-plan.js +5 -2
- package/dist/commands/agents/triggers/create.js +3 -1
- package/dist/commands/agents/triggers/fire.js +2 -0
- package/dist/commands/agents/triggers/replay.js +2 -0
- package/dist/commands/agents/triggers/update.js +12 -4
- package/dist/commands/commitments/action-history.js +7 -2
- package/dist/commands/commitments/cadence-decisions.js +6 -1
- package/dist/commands/commitments/cadence-requests/decide.d.ts +1 -1
- package/dist/commands/commitments/cadence-requests/decide.js +1 -1
- package/dist/commands/commitments/doctor.js +7 -1
- package/dist/commands/commitments/observations.js +7 -1
- package/dist/commands/commitments/operating-review.d.ts +15 -0
- package/dist/commands/commitments/operating-review.js +23 -2
- package/dist/commands/commitments/preflight.d.ts +12 -0
- package/dist/commands/commitments/preflight.js +23 -9
- package/dist/commands/commitments/reflection.js +6 -1
- package/dist/commands/commitments/show.js +3 -1
- package/dist/commands/commitments/trigger-status.js +2 -22
- package/dist/commands/commitments/wake-capabilities.d.ts +13 -0
- package/dist/commands/commitments/wake-capabilities.js +39 -3
- package/dist/commands/daemon/logs.d.ts +73 -3
- package/dist/commands/daemon/logs.js +304 -17
- package/dist/commands/followups/act.js +13 -1
- package/dist/commands/followups/checkin.js +11 -2
- package/dist/commands/followups/reschedule.js +13 -1
- package/dist/commands/proposals/discard.d.ts +1 -1
- package/dist/commands/proposals/keep.d.ts +1 -1
- package/dist/commands/proposals/list.d.ts +7 -0
- package/dist/commands/proposals/list.js +31 -5
- package/dist/commands/proposals/show.d.ts +2 -1
- package/dist/commands/proposals/show.js +31 -4
- package/dist/commands/proposals/snooze.d.ts +1 -1
- package/dist/commands/requests/create.js +8 -3
- package/dist/commands/spaces/workflows/create.js +3 -3
- package/dist/commands/tasks/complete.js +4 -0
- package/dist/commands/tasks/create.d.ts +2 -0
- package/dist/commands/tasks/create.js +17 -3
- package/dist/commands/tasks/deliverable/add.d.ts +2 -0
- package/dist/commands/tasks/deliverable/add.js +22 -7
- package/dist/commands/tasks/deliverable/list.d.ts +13 -0
- package/dist/commands/tasks/deliverable/list.js +34 -1
- package/dist/commands/tasks/economics-compare.js +7 -1
- package/dist/commands/tasks/expectations.d.ts +10 -0
- package/dist/commands/tasks/expectations.js +31 -3
- package/dist/commands/tasks/list.d.ts +9 -0
- package/dist/commands/tasks/list.js +40 -5
- package/dist/commands/tasks/report.js +1 -1
- package/dist/commands/tasks/result/show.d.ts +7 -0
- package/dist/commands/tasks/result/show.js +32 -1
- package/dist/commands/tasks/result/submit.js +1 -1
- package/dist/commands/tasks/retry-schedule.js +11 -1
- package/dist/commands/tasks/show.d.ts +6 -0
- package/dist/commands/tasks/show.js +23 -0
- package/dist/commands/tasks/update.d.ts +3 -0
- package/dist/commands/tasks/update.js +23 -3
- package/dist/commands/triggers/audit.js +6 -2
- package/dist/commands/triggers/create.js +3 -1
- package/dist/commands/triggers/fire.d.ts +1 -0
- package/dist/commands/triggers/fire.js +16 -1
- package/dist/commands/triggers/preflight.js +6 -5
- package/dist/commands/triggers/replay.js +2 -0
- package/dist/commands/triggers/update.js +12 -4
- package/dist/commands/workspaces/stewardship.js +5 -1
- package/dist/lib/agentic-stream.d.ts +9 -0
- package/dist/lib/agentic-stream.js +38 -18
- package/dist/lib/commitment-event-wakes.d.ts +8 -0
- package/dist/lib/commitment-event-wakes.js +39 -0
- package/dist/lib/commitment-ledgers.d.ts +9 -0
- package/dist/lib/commitment-ledgers.js +126 -0
- package/dist/lib/commitments.d.ts +102 -2
- package/dist/lib/commitments.js +208 -8
- package/dist/lib/delegated-cli.js +13 -2
- package/dist/lib/followups.d.ts +6 -0
- package/dist/lib/followups.js +12 -0
- package/dist/lib/message-content.d.ts +6 -0
- package/dist/lib/message-content.js +24 -0
- package/dist/lib/operating-plan-loops.d.ts +8 -0
- package/dist/lib/operating-plan-loops.js +32 -0
- package/dist/lib/preflight-copy.d.ts +27 -0
- package/dist/lib/preflight-copy.js +89 -0
- package/dist/lib/proposal-decision-command.d.ts +1 -1
- package/dist/lib/proposal-decision-command.js +27 -3
- package/dist/lib/proposals.d.ts +17 -0
- package/dist/lib/proposals.js +41 -0
- package/dist/lib/stewardship-output.js +57 -12
- package/dist/lib/task-economics-line.d.ts +30 -0
- package/dist/lib/task-economics-line.js +49 -0
- package/dist/lib/task-economics.d.ts +15 -0
- package/dist/lib/task-economics.js +73 -8
- package/dist/lib/task-recurrence-outcome.d.ts +19 -0
- package/dist/lib/task-recurrence-outcome.js +30 -0
- package/dist/lib/triggers.d.ts +42 -0
- package/dist/lib/triggers.js +136 -2
- package/dist/lib/widgetTerminalText.d.ts +8 -0
- package/dist/lib/widgetTerminalText.js +116 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/cliHandoffWire.d.ts +33 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/cliHandoffWire.js +27 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/telemetryRedaction.d.ts +28 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/telemetryRedaction.js +50 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/cliHandoffWire.d.ts +33 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/cliHandoffWire.js +26 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/telemetryRedaction.d.ts +28 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/telemetryRedaction.js +50 -5
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +7261 -7056
- package/docs/v1/operations.md +1 -1
- package/oclif.manifest.json +116 -72
- package/package.json +1 -1
package/dist/base-command.js
CHANGED
|
@@ -1298,7 +1298,6 @@ class BaseCommand extends core_1.Command {
|
|
|
1298
1298
|
// CI scripts key off 75 to distinguish "re-authenticate" from
|
|
1299
1299
|
// "bad command" (exit 2); without this carve-out they had to
|
|
1300
1300
|
// string-match the stderr message, which was fragile.
|
|
1301
|
-
const exitCode = this.bareMode ? 75 : 2;
|
|
1302
1301
|
// An `osk_ci_*` token is a DAEMON BOOTSTRAP credential — only
|
|
1303
1302
|
// `POST /api/daemons/token` accepts it. Telling its holder to run
|
|
1304
1303
|
// `login` sends a CI job to do the one thing it cannot, and hides the
|
|
@@ -1308,6 +1307,11 @@ class BaseCommand extends core_1.Command {
|
|
|
1308
1307
|
// and no daemon to ask: the server's own reason (expired, revoked) IS
|
|
1309
1308
|
// the answer, and the repair is a new token, not `login`.
|
|
1310
1309
|
const presentedPat = Boolean(this.resolvedCredential?.token?.startsWith('osk_pat_'));
|
|
1310
|
+
// A token nothing can renew is refused for good: a new token is the only repair, so a retry
|
|
1311
|
+
// loop is exactly the wrong response to it (OSK-15360). 77 (EX_NOPERM) rather than 75
|
|
1312
|
+
// (EX_TEMPFAIL), as the delegated-credential refusal that only a new sign-in repairs does.
|
|
1313
|
+
const unrenewable = presentedCiToken || presentedPat;
|
|
1314
|
+
const exitCode = this.bareMode ? (unrenewable ? 77 : 75) : 2;
|
|
1311
1315
|
// OSK-12116 — the 401 is usually the SECOND failure: the token expired
|
|
1312
1316
|
// (routine) and renewing it was refused (the fault). The server's code
|
|
1313
1317
|
// for the retry is `TOKEN_EXPIRED`, which names the routine half; the
|
|
@@ -1361,7 +1365,7 @@ class BaseCommand extends core_1.Command {
|
|
|
1361
1365
|
code: refreshRefusal?.code || bodyCode || 'AUTHENTICATION_FAILED',
|
|
1362
1366
|
status: e.status,
|
|
1363
1367
|
exit: exitCode,
|
|
1364
|
-
retryable:
|
|
1368
|
+
retryable: !unrenewable,
|
|
1365
1369
|
...(Object.keys(details).length > 0 ? { details } : {}),
|
|
1366
1370
|
});
|
|
1367
1371
|
}
|
|
@@ -5,6 +5,7 @@ const core_1 = require("@oclif/core");
|
|
|
5
5
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
6
6
|
const base_command_1 = require("../../../base-command");
|
|
7
7
|
const format_1 = require("../../../lib/format");
|
|
8
|
+
const triggers_1 = require("../../../lib/triggers");
|
|
8
9
|
/**
|
|
9
10
|
* A schedule persisted while handling a conversation turn, for which no explicit
|
|
10
11
|
* confirmation was recorded.
|
|
@@ -69,6 +70,7 @@ class AgendaTriggerList extends base_command_1.BaseCommand {
|
|
|
69
70
|
const rows = items.map((t) => {
|
|
70
71
|
const next = t.schedule?.nextRunAt ??
|
|
71
72
|
t.selfScheduled?.nextRunAt ??
|
|
73
|
+
(0, triggers_1.onceDueAt)(t) ??
|
|
72
74
|
'-';
|
|
73
75
|
const fires = t.audit?.fireCount ?? 0;
|
|
74
76
|
return {
|
|
@@ -366,7 +366,10 @@ class AgentsChat extends base_command_1.BaseCommand {
|
|
|
366
366
|
'Assistant text arrives as `text.delta` whose `text` is the CUMULATIVE answer so far, ' +
|
|
367
367
|
'not a delta — take the last one, or `run.result` at the end. The same text is ' +
|
|
368
368
|
'mirrored inside `session.output` envelopes for consumers that want the raw stream, ' +
|
|
369
|
-
'so folding both doubles the answer: pick ONE lane.
|
|
369
|
+
'so folding both doubles the answer: pick ONE lane. A widget the agent wrote ' +
|
|
370
|
+
'(a block of CSS, HTML and JavaScript the apps draw) is its text description in ' +
|
|
371
|
+
'`text.delta` and `run.result`; the `session.output` lane carries the block itself. ' +
|
|
372
|
+
'Inside a `session.output`, ' +
|
|
370
373
|
'`envelopes[].__seq` is the dedupe key and the ordering key — the same envelope is ' +
|
|
371
374
|
'delivered by more than one room, and a re-delivery repeats its `__seq`. A ' +
|
|
372
375
|
'`stream.gap` event means envelopes in that seq range never arrived and replay from ' +
|
|
@@ -4,6 +4,8 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
4
4
|
const core_1 = require("@oclif/core");
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
6
|
const roles_1 = require("../../lib/roles");
|
|
7
|
+
const operating_plan_loops_1 = require("../../lib/operating-plan-loops");
|
|
8
|
+
const preflight_copy_1 = require("../../lib/preflight-copy");
|
|
7
9
|
class AgentOperatingPlan extends base_command_1.BaseCommand {
|
|
8
10
|
static description = 'Read responsibilities, evidence, inquiries, work, delayed evaluation and existing planning loops without scheduling work';
|
|
9
11
|
static args = {
|
|
@@ -25,7 +27,7 @@ class AgentOperatingPlan extends base_command_1.BaseCommand {
|
|
|
25
27
|
for (const r of plan.responsibilities) {
|
|
26
28
|
this.log(`\n${r.title} · ${r.status} · ${r.kind} v${r.version}`);
|
|
27
29
|
this.log(` Responsibility: ${r.purpose}`);
|
|
28
|
-
this.log(` Evidence: ${r.evidence.status}${r.evidence.issues?.length ? ` (${r.evidence.issues.join('
|
|
30
|
+
this.log(` Evidence: ${r.evidence.status}${r.evidence.issues?.length ? ` (${r.evidence.issues.map(preflight_copy_1.sourceRefusalWords).join('; ')})` : ''}`);
|
|
29
31
|
this.log(" Execution authority: tools, sandbox and approvals use the Agent's runtime permissions.");
|
|
30
32
|
for (const observation of r.evidenceAuthority?.observations || []) {
|
|
31
33
|
const comparison = (0, data_provider_1.describeObservationChange)({
|
|
@@ -44,7 +46,8 @@ class AgentOperatingPlan extends base_command_1.BaseCommand {
|
|
|
44
46
|
if (r.blocker)
|
|
45
47
|
this.log(` Blocker: ${r.blocker.code} — ${r.blocker.remediation || ''}`);
|
|
46
48
|
}
|
|
47
|
-
|
|
49
|
+
for (const line of (0, operating_plan_loops_1.planningLoopLines)(plan.planning.loops, plan.planning.todos.length))
|
|
50
|
+
this.log(line);
|
|
48
51
|
if (plan.learning?.skillValidation)
|
|
49
52
|
this.log(`Skill validation: ${plan.learning.skillValidation.enabled ? 'enabled' : 'disabled'} (${plan.learning.skillValidation.scope}); external effects validated: ${plan.learning.skillValidation.externalEffectsValidated}.`);
|
|
50
53
|
if (!plan.coverage.complete) {
|
|
@@ -75,7 +75,9 @@ class AgentsTriggersCreate extends base_command_1.BaseCommand {
|
|
|
75
75
|
'end-at': core_1.Flags.string({
|
|
76
76
|
description: 'ISO-8601 datetime after which a schedule stops firing (--kind schedule)',
|
|
77
77
|
}),
|
|
78
|
-
'stale-catchup-ms': core_1.Flags.integer({
|
|
78
|
+
'stale-catchup-ms': core_1.Flags.integer({
|
|
79
|
+
description: 'How late a missed occurrence may still run, in ms (a positive number). After downtime, an occurrence more than this overdue is skipped rather than run late, and the schedule moves to its next future slot. Unset: 3600000 (1 hour).',
|
|
80
|
+
}),
|
|
79
81
|
// once
|
|
80
82
|
at: core_1.Flags.string({
|
|
81
83
|
description: 'ISO-8601 datetime to fire once (--kind once). Must be ≥5s in the future.',
|
|
@@ -51,6 +51,8 @@ class AgentsTriggersFire extends base_command_1.BaseCommand {
|
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
53
|
this.log(`Fire requested: outcome=${String(result.outcome ?? '-')} reason=${String(result.reason ?? '-')}`);
|
|
54
|
+
for (const line of (0, triggers_1.describeFireDetail)(result))
|
|
55
|
+
this.log(line);
|
|
54
56
|
}
|
|
55
57
|
}
|
|
56
58
|
exports.default = AgentsTriggersFire;
|
|
@@ -50,6 +50,8 @@ class AgentsTriggersReplay extends base_command_1.BaseCommand {
|
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
52
52
|
this.log(`Replay requested: ok=${String(result.ok ?? '-')} outcome=${String(result.outcome ?? '-')} reason=${String(result.reason ?? '-')}`);
|
|
53
|
+
for (const line of (0, triggers_1.describeFireDetail)(result))
|
|
54
|
+
this.log(line);
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
57
|
exports.default = AgentsTriggersReplay;
|
|
@@ -62,9 +62,13 @@ class AgentsTriggersUpdate extends base_command_1.BaseCommand {
|
|
|
62
62
|
'end-at': core_1.Flags.string({
|
|
63
63
|
description: 'ISO-8601 datetime after which a schedule stops firing',
|
|
64
64
|
}),
|
|
65
|
-
'stale-catchup-ms': core_1.Flags.integer({
|
|
65
|
+
'stale-catchup-ms': core_1.Flags.integer({
|
|
66
|
+
description: 'How late a missed occurrence may still run, in ms (a positive number). After downtime, an occurrence more than this overdue is skipped rather than run late, and the schedule moves to its next future slot. Unset: 3600000 (1 hour).',
|
|
67
|
+
}),
|
|
66
68
|
at: core_1.Flags.string({ description: 'ISO-8601 datetime for once triggers' }),
|
|
67
|
-
entity: core_1.Flags.string({
|
|
69
|
+
entity: core_1.Flags.string({
|
|
70
|
+
description: 'Event entity type for event triggers (create only; refused on update)',
|
|
71
|
+
}),
|
|
68
72
|
event: core_1.Flags.string({ description: 'Event type for event triggers' }),
|
|
69
73
|
'filter-mode': core_1.Flags.string({
|
|
70
74
|
description: 'Event filter mode',
|
|
@@ -79,8 +83,12 @@ class AgentsTriggersUpdate extends base_command_1.BaseCommand {
|
|
|
79
83
|
'max-per-hour': core_1.Flags.integer({ description: 'Event hourly cap' }),
|
|
80
84
|
probability: core_1.Flags.string({ description: 'Stochastic probability from 0 to 1' }),
|
|
81
85
|
'jitter-ms': core_1.Flags.integer({ description: 'Stochastic jitter in ms' }),
|
|
82
|
-
'eval-interval-minutes': core_1.Flags.integer({
|
|
83
|
-
|
|
86
|
+
'eval-interval-minutes': core_1.Flags.integer({
|
|
87
|
+
description: 'Stochastic eval interval in minutes (create only; refused on update)',
|
|
88
|
+
}),
|
|
89
|
+
'next-run-at': core_1.Flags.string({
|
|
90
|
+
description: 'ISO datetime: alias of --at for once triggers; for self_scheduled triggers it is set at create and refused on update',
|
|
91
|
+
}),
|
|
84
92
|
'form-title': core_1.Flags.string({ description: 'Form heading for form triggers' }),
|
|
85
93
|
'form-subtitle': core_1.Flags.string({ description: 'Form subtitle for form triggers' }),
|
|
86
94
|
'form-fields': core_1.Flags.string({ description: 'Form fields JSON array for form triggers' }),
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
4
|
const base_command_1 = require("../../base-command");
|
|
5
5
|
const commitments_1 = require("../../lib/commitments");
|
|
6
|
+
const commitment_ledgers_1 = require("../../lib/commitment-ledgers");
|
|
6
7
|
/**
|
|
7
8
|
* `skrr commitments action-history <id>` — what the commitment DID, as opposed to
|
|
8
9
|
* what it decided.
|
|
@@ -40,8 +41,12 @@ class CommitmentsActionHistory extends base_command_1.BaseCommand {
|
|
|
40
41
|
catch (err) {
|
|
41
42
|
this.handleApiError(err);
|
|
42
43
|
}
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
if (flags.json) {
|
|
45
|
+
this.log(JSON.stringify(response, null, 2));
|
|
46
|
+
(0, commitments_1.renderListPageHint)(response, (line) => this.log(line));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
(0, commitment_ledgers_1.renderActionHistory)(response, (line) => this.log(line));
|
|
45
50
|
}
|
|
46
51
|
}
|
|
47
52
|
exports.default = CommitmentsActionHistory;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
4
|
const base_command_1 = require("../../base-command");
|
|
5
5
|
const commitments_1 = require("../../lib/commitments");
|
|
6
|
+
const commitment_ledgers_1 = require("../../lib/commitment-ledgers");
|
|
6
7
|
/**
|
|
7
8
|
* `skrr commitments cadence-decisions <id>` — the adaptive controller's
|
|
8
9
|
* append-only decision ledger, including shadow recommendations.
|
|
@@ -30,7 +31,11 @@ class CommitmentsCadenceDecisions extends base_command_1.BaseCommand {
|
|
|
30
31
|
catch (error) {
|
|
31
32
|
this.handleApiError(error);
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
+
if (flags.json) {
|
|
35
|
+
this.log(JSON.stringify(response, null, 2));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
(0, commitment_ledgers_1.renderCadenceDecisions)(response, (line) => this.log(line));
|
|
34
39
|
}
|
|
35
40
|
}
|
|
36
41
|
exports.default = CommitmentsCadenceDecisions;
|
|
@@ -6,7 +6,7 @@ import { BaseCommand } from '../../../base-command';
|
|
|
6
6
|
* Approval changes only the check schedule; it grants no execution permissions.
|
|
7
7
|
* Rejection records the decision and leaves the schedule unchanged.
|
|
8
8
|
*
|
|
9
|
-
* List the pending ones with `skrr commitments show <id
|
|
9
|
+
* List the pending ones with `skrr commitments show <id>` (it prints each request id).
|
|
10
10
|
*/
|
|
11
11
|
export default class CommitmentsCadenceRequestsDecide extends BaseCommand {
|
|
12
12
|
static description: string;
|
|
@@ -10,7 +10,7 @@ const commitments_1 = require("../../../lib/commitments");
|
|
|
10
10
|
* Approval changes only the check schedule; it grants no execution permissions.
|
|
11
11
|
* Rejection records the decision and leaves the schedule unchanged.
|
|
12
12
|
*
|
|
13
|
-
* List the pending ones with `skrr commitments show <id
|
|
13
|
+
* List the pending ones with `skrr commitments show <id>` (it prints each request id).
|
|
14
14
|
*/
|
|
15
15
|
class CommitmentsCadenceRequestsDecide extends base_command_1.BaseCommand {
|
|
16
16
|
static description = 'Approve or reject an agent-proposed commitment cadence change';
|
|
@@ -11,7 +11,13 @@ function doctorVerdict(input) {
|
|
|
11
11
|
const operatingState = input.operatingState || {};
|
|
12
12
|
const blocker = operatingState.firstActionableBlocker;
|
|
13
13
|
if (blocker?.code) {
|
|
14
|
-
|
|
14
|
+
// A lifecycle stop is a state, not a fault: a Commitment its owner paused is `paused`, with the
|
|
15
|
+
// way back as its next step, not `blocked` (OSK-15423).
|
|
16
|
+
const lifecycle = /^status_([a-z_]+)$/.exec(String(blocker.code));
|
|
17
|
+
return {
|
|
18
|
+
verdict: lifecycle ? lifecycle[1] : blocker.code === 'deleted' ? 'deleted' : 'blocked',
|
|
19
|
+
next: String(blocker.remediation || 'Inspect the Commitment'),
|
|
20
|
+
};
|
|
15
21
|
}
|
|
16
22
|
if (operatingState.status === 'waiting_approval') {
|
|
17
23
|
return { verdict: 'waiting_approval', next: 'Open the pending prepared action for review' };
|
|
@@ -60,7 +60,13 @@ function renderObservationWindow(response, log) {
|
|
|
60
60
|
* actually move the loop.
|
|
61
61
|
*/
|
|
62
62
|
class CommitmentsObservations extends base_command_1.BaseCommand {
|
|
63
|
-
static description = "Show what the commitment's runs reported observing"
|
|
63
|
+
static description = "Show what the commitment's runs reported observing.\n\n" +
|
|
64
|
+
'Columns: VALUE is shortened to fit the table (--json has the stored value). DECLARED no / ' +
|
|
65
|
+
"REASON undeclared means the key is not declared on the Commitment's agent_run source: the " +
|
|
66
|
+
'reading is recorded but can never open a loop. CLAMPED yes means the observed time the run ' +
|
|
67
|
+
'claimed was moved into the accepted window (CLAIMED is what it said). CHANGED is the ' +
|
|
68
|
+
"server's verdict against the previous reading of the same key, never the run's. CONF is a " +
|
|
69
|
+
'cap on how much an Agent-reported reading is worth, not a measurement.';
|
|
64
70
|
static examples = [
|
|
65
71
|
'<%= config.bin %> commitments observations obj_abc123',
|
|
66
72
|
'<%= config.bin %> commitments observations obj_abc123 --declared-only --changed-only',
|
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
import { BaseCommand } from '../../base-command';
|
|
2
|
+
type SystemCommitmentRow = {
|
|
3
|
+
systemRole?: string;
|
|
4
|
+
status?: string;
|
|
5
|
+
lastCheckedAt?: string;
|
|
6
|
+
lastMaterialChangeAt?: string;
|
|
7
|
+
lastUserNudgedAt?: string;
|
|
8
|
+
maxUserNudgesPerDay?: number;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* What "no open questions" means, said only as far as it is true. "It has not told you anything is
|
|
12
|
+
* missing" read as reassurance under an Always-On-OFF header and loops that had never checked
|
|
13
|
+
* (OSK-15438): an Agent that cannot run cannot have asked.
|
|
14
|
+
*/
|
|
15
|
+
export declare function noQuestionsSentence(alwaysOn: boolean, roles: SystemCommitmentRow[]): string;
|
|
2
16
|
export default class CommitmentsOperatingReview extends BaseCommand {
|
|
3
17
|
static description: string;
|
|
4
18
|
static args: {
|
|
@@ -9,3 +23,4 @@ export default class CommitmentsOperatingReview extends BaseCommand {
|
|
|
9
23
|
};
|
|
10
24
|
run(): Promise<void>;
|
|
11
25
|
}
|
|
26
|
+
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.noQuestionsSentence = noQuestionsSentence;
|
|
3
4
|
const core_1 = require("@oclif/core");
|
|
4
5
|
const base_command_1 = require("../../base-command");
|
|
5
6
|
const commitments_1 = require("../../lib/commitments");
|
|
@@ -24,6 +25,20 @@ function ago(value) {
|
|
|
24
25
|
return `${Math.round(mins / 60)}h ago`;
|
|
25
26
|
return `${Math.round(mins / (60 * 24))}d ago`;
|
|
26
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* What "no open questions" means, said only as far as it is true. "It has not told you anything is
|
|
30
|
+
* missing" read as reassurance under an Always-On-OFF header and loops that had never checked
|
|
31
|
+
* (OSK-15438): an Agent that cannot run cannot have asked.
|
|
32
|
+
*/
|
|
33
|
+
function noQuestionsSentence(alwaysOn, roles) {
|
|
34
|
+
if (!alwaysOn) {
|
|
35
|
+
return 'None recorded. Its background loops are not running (Always-On is off), so it has had no chance to ask.';
|
|
36
|
+
}
|
|
37
|
+
const checked = roles.some((role) => role.status === 'active' && role.lastCheckedAt);
|
|
38
|
+
return checked
|
|
39
|
+
? 'None. It has not told you anything is missing.'
|
|
40
|
+
: 'None recorded yet. None of its loops has checked, so this says nothing about whether anything is missing.';
|
|
41
|
+
}
|
|
27
42
|
class CommitmentsOperatingReview extends base_command_1.BaseCommand {
|
|
28
43
|
static description = 'Read an agent’s system-managed commitment operating review';
|
|
29
44
|
static args = {
|
|
@@ -33,6 +48,11 @@ class CommitmentsOperatingReview extends base_command_1.BaseCommand {
|
|
|
33
48
|
async run() {
|
|
34
49
|
this.requireAuth();
|
|
35
50
|
const { args, flags } = await this.parse(CommitmentsOperatingReview);
|
|
51
|
+
// A Commitment id here answered "Agent not found" without saying an Agent id was wanted.
|
|
52
|
+
if (/^obj_/.test(args.agentId)) {
|
|
53
|
+
this.error(`${args.agentId} is a Commitment id; operating-review takes an Agent id. ` +
|
|
54
|
+
`Use \`skrr commitments status ${args.agentId}\` for one Commitment.`, { exit: 1 });
|
|
55
|
+
}
|
|
36
56
|
let result;
|
|
37
57
|
try {
|
|
38
58
|
result = await commitments_1.commitmentApi.operatingReview(args.agentId);
|
|
@@ -84,7 +104,7 @@ class CommitmentsOperatingReview extends base_command_1.BaseCommand {
|
|
|
84
104
|
this.log('');
|
|
85
105
|
this.log(`Open questions from this agent (${questions.length})`);
|
|
86
106
|
if (questions.length === 0) {
|
|
87
|
-
this.log(
|
|
107
|
+
this.log(` ${noQuestionsSentence(alwaysOn, roles)}`);
|
|
88
108
|
}
|
|
89
109
|
for (const q of questions) {
|
|
90
110
|
this.log(` • ${q.question}`);
|
|
@@ -93,7 +113,8 @@ class CommitmentsOperatingReview extends base_command_1.BaseCommand {
|
|
|
93
113
|
this.log(` asked ${ago(q.askedAt)}`);
|
|
94
114
|
}
|
|
95
115
|
this.log('');
|
|
96
|
-
|
|
116
|
+
const drafts = portfolio.draftCommitmentCount ?? 0;
|
|
117
|
+
this.log(`Business commitments: ${portfolio.activeCommitmentCount ?? 0} active, ${portfolio.pausedCommitmentCount ?? 0} paused${drafts > 0 ? `, ${drafts} draft` : ''}`);
|
|
97
118
|
}
|
|
98
119
|
}
|
|
99
120
|
exports.default = CommitmentsOperatingReview;
|
|
@@ -23,6 +23,18 @@ type PreflightGate = CommitmentPreflightReport['gates'][number];
|
|
|
23
23
|
* The note gets its own indented line. It is prose, and hanging it off the same
|
|
24
24
|
* dash as a short code puts two different kinds of thing in one slot.
|
|
25
25
|
*/
|
|
26
|
+
/**
|
|
27
|
+
* The upcoming runs, said honestly under the verdict above them (OSK-15440).
|
|
28
|
+
*
|
|
29
|
+
* The cadence projection does not know whether the Commitment can run, so a paused one, or one
|
|
30
|
+
* with Always-On off, still listed three timestamps beneath "Run is blocked" and answered "when
|
|
31
|
+
* next?" opposite to `show` ("no wake observed yet"). While the run is blocked they are what the
|
|
32
|
+
* cadence WOULD do, so they are labelled that way instead of reading as a promise.
|
|
33
|
+
*/
|
|
34
|
+
export declare function nextRunsLines(report: {
|
|
35
|
+
verdict?: string;
|
|
36
|
+
nextRuns?: string[];
|
|
37
|
+
}): string[];
|
|
26
38
|
export declare function preflightGateLines(gate: PreflightGate, verbose?: boolean): string[];
|
|
27
39
|
export default class CommitmentsPreflight extends BaseCommand {
|
|
28
40
|
static description: string;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.nextRunsLines = nextRunsLines;
|
|
3
4
|
exports.preflightGateLines = preflightGateLines;
|
|
4
5
|
const core_1 = require("@oclif/core");
|
|
5
6
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
6
7
|
const base_command_1 = require("../../base-command");
|
|
7
8
|
const commitments_1 = require("../../lib/commitments");
|
|
8
9
|
const prompt_1 = require("../../lib/prompt");
|
|
10
|
+
const preflight_copy_1 = require("../../lib/preflight-copy");
|
|
9
11
|
/**
|
|
10
12
|
* The lines one preflight gate contributes.
|
|
11
13
|
*
|
|
@@ -23,6 +25,22 @@ const prompt_1 = require("../../lib/prompt");
|
|
|
23
25
|
* The note gets its own indented line. It is prose, and hanging it off the same
|
|
24
26
|
* dash as a short code puts two different kinds of thing in one slot.
|
|
25
27
|
*/
|
|
28
|
+
/**
|
|
29
|
+
* The upcoming runs, said honestly under the verdict above them (OSK-15440).
|
|
30
|
+
*
|
|
31
|
+
* The cadence projection does not know whether the Commitment can run, so a paused one, or one
|
|
32
|
+
* with Always-On off, still listed three timestamps beneath "Run is blocked" and answered "when
|
|
33
|
+
* next?" opposite to `show` ("no wake observed yet"). While the run is blocked they are what the
|
|
34
|
+
* cadence WOULD do, so they are labelled that way instead of reading as a promise.
|
|
35
|
+
*/
|
|
36
|
+
function nextRunsLines(report) {
|
|
37
|
+
if (!report.nextRuns?.length)
|
|
38
|
+
return ['', 'Next runs: none scheduled'];
|
|
39
|
+
const header = report.verdict === 'blocked'
|
|
40
|
+
? 'Next runs (the cadence\u2019s times; none will fire while the run is blocked above):'
|
|
41
|
+
: 'Next runs:';
|
|
42
|
+
return ['', header, ...report.nextRuns.map((run) => ` ${run}`)];
|
|
43
|
+
}
|
|
26
44
|
function preflightGateLines(gate, verbose = false) {
|
|
27
45
|
// "Could it contact you now?" is not a Run gate. It answers whether a message
|
|
28
46
|
// would reach the owner, and a limit the owner set themselves (zero nudges a day,
|
|
@@ -90,6 +108,8 @@ function preflightGateLines(gate, verbose = false) {
|
|
|
90
108
|
if (typeof hint === 'string' && hint.trim()) {
|
|
91
109
|
lines.push(` ${hint.trim()}`);
|
|
92
110
|
}
|
|
111
|
+
for (const sentence of (0, preflight_copy_1.gateExplanationLines)(gate))
|
|
112
|
+
lines.push(` ${sentence}`);
|
|
93
113
|
return lines;
|
|
94
114
|
}
|
|
95
115
|
class CommitmentsPreflight extends base_command_1.BaseCommand {
|
|
@@ -171,21 +191,15 @@ class CommitmentsPreflight extends base_command_1.BaseCommand {
|
|
|
171
191
|
cloud_runtime: 'Runtime-scoped access',
|
|
172
192
|
};
|
|
173
193
|
for (const capability of report.capabilities) {
|
|
174
|
-
this.log(` ${sourceLabels[capability.source]} · ${capability.provider} · ${capability.capability}${capability.scope ? ` · ${capability.scope}` : ''}: ${capability
|
|
194
|
+
this.log(` ${sourceLabels[capability.source]} · ${capability.provider} · ${capability.capability}${capability.scope ? ` · ${capability.scope}` : ''}: ${(0, preflight_copy_1.capabilityStatusLabel)(capability)}`);
|
|
175
195
|
if (capability.testedAt)
|
|
176
196
|
this.log(` Tested: ${capability.testedAt}${capability.expiresAt ? ` · expires ${capability.expiresAt}` : ''}`);
|
|
177
197
|
if (capability.attestation === 'machine')
|
|
178
198
|
this.log(' Machine-attested; not platform-attested.');
|
|
179
199
|
}
|
|
180
200
|
}
|
|
181
|
-
|
|
182
|
-
this.log(
|
|
183
|
-
for (const run of report.nextRuns)
|
|
184
|
-
this.log(` ${run}`);
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
this.log('\nNext runs: none scheduled');
|
|
188
|
-
}
|
|
201
|
+
for (const line of nextRunsLines(report))
|
|
202
|
+
this.log(line);
|
|
189
203
|
this.log('\nEndpoints:');
|
|
190
204
|
for (const endpoint of report.endpoints || []) {
|
|
191
205
|
this.log(` ${endpoint.available ? 'ok ' : 'BLOCK'} ${endpoint.label || endpoint.destination}` +
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
4
|
const base_command_1 = require("../../base-command");
|
|
5
5
|
const commitments_1 = require("../../lib/commitments");
|
|
6
|
+
const commitment_ledgers_1 = require("../../lib/commitment-ledgers");
|
|
6
7
|
class CommitmentsReflection extends base_command_1.BaseCommand {
|
|
7
8
|
static description = 'Read pending and decided reflection proposals for a commitment';
|
|
8
9
|
static args = {
|
|
@@ -19,7 +20,11 @@ class CommitmentsReflection extends base_command_1.BaseCommand {
|
|
|
19
20
|
catch (error) {
|
|
20
21
|
this.handleApiError(error);
|
|
21
22
|
}
|
|
22
|
-
|
|
23
|
+
if (flags.json) {
|
|
24
|
+
this.log(JSON.stringify(result, null, 2));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
(0, commitment_ledgers_1.renderReflection)(result, (line) => this.log(line));
|
|
23
28
|
}
|
|
24
29
|
}
|
|
25
30
|
exports.default = CommitmentsReflection;
|
|
@@ -49,7 +49,9 @@ class CommitmentsShow extends base_command_1.BaseCommand {
|
|
|
49
49
|
this.log(`Commitment ${args.id} not found.`);
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
52
|
-
(0, commitments_1.renderCommitmentSummary)((0, commitments_1.withLiveAssessment)(response.commitment, response.operatingState), (line) => this.log(line), response.latestCheck);
|
|
52
|
+
(0, commitments_1.renderCommitmentSummary)((0, commitments_1.withLiveAssessment)(response.commitment, response.operatingState), (line) => this.log(line), response.latestCheck, response.scheduleIssues);
|
|
53
|
+
for (const line of (0, commitments_1.pendingCadenceRequestLines)(response.commitment))
|
|
54
|
+
this.log(line);
|
|
53
55
|
// Whose permissions a run uses (OSK-11975) — read from the operating state,
|
|
54
56
|
// which carries the same projection preflight reports (OSK-12065).
|
|
55
57
|
const autonomy = response.operatingState?.execution;
|
|
@@ -4,6 +4,7 @@ exports.formatTriggerStatus = formatTriggerStatus;
|
|
|
4
4
|
const core_1 = require("@oclif/core");
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
6
|
const commitments_1 = require("../../lib/commitments");
|
|
7
|
+
const commitment_event_wakes_1 = require("../../lib/commitment-event-wakes");
|
|
7
8
|
/**
|
|
8
9
|
* `skrr commitments trigger-status <id>` — what the SCHEDULER actually has.
|
|
9
10
|
*
|
|
@@ -103,29 +104,8 @@ function formatTriggerStatus(status) {
|
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
|
-
const caps = (status.eventCapabilities ?? {});
|
|
107
107
|
lines.push('');
|
|
108
|
-
lines.push(
|
|
109
|
-
lines.push(` requested: ${caps.requested ? 'yes' : 'no'}`);
|
|
110
|
-
lines.push(` configured sources: ${(caps.configuredSources ?? []).join(', ') || 'none'}`);
|
|
111
|
-
lines.push(` eligible sources: ${(caps.eligibleSources ?? []).join(', ') || 'none'}`);
|
|
112
|
-
lines.push(` materialized sources: ${(caps.materializedSources ?? []).join(', ') || 'none'}`);
|
|
113
|
-
if ((caps.dormantSources ?? []).length) {
|
|
114
|
-
lines.push(` dormant sources: ${caps.dormantSources.join(', ')} (configured but the cadence never requests them)`);
|
|
115
|
-
}
|
|
116
|
-
if ((caps.unroutableSources ?? []).length) {
|
|
117
|
-
lines.push(` unroutable sources: ${caps
|
|
118
|
-
.unroutableSources.map((item) => `${item.source} (${item.reason})`)
|
|
119
|
-
.join(', ')} — materialized but no upstream producer can deliver events`);
|
|
120
|
-
}
|
|
121
|
-
if ((caps.permissionGaps ?? []).length) {
|
|
122
|
-
lines.push(` permission gaps: ${caps
|
|
123
|
-
.permissionGaps.map((gap) => `${gap.source} ${gap.capability ?? gap.permission}` +
|
|
124
|
-
` (${gap.impact === 'evidence_read' ? 'needed by' : 'blocks'} ${(gap.events ?? []).join(', ')})`)
|
|
125
|
-
.join('; ')} — the routing GitHub installation does not hold the permission`);
|
|
126
|
-
}
|
|
127
|
-
if (caps.degradedReason)
|
|
128
|
-
lines.push(` degraded: ${caps.degradedReason}`);
|
|
108
|
+
lines.push(...(0, commitment_event_wakes_1.eventWakeLines)((status.eventCapabilities ?? {})));
|
|
129
109
|
const recent = (status.recent ?? {});
|
|
130
110
|
const fires = recent.fires ?? [];
|
|
131
111
|
lines.push('');
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import { BaseCommand } from '../../base-command';
|
|
2
|
+
import { type CommitmentWakeCapabilities } from '../../lib/commitments';
|
|
3
|
+
/**
|
|
4
|
+
* The headline used to stop at "configured sources may wake the Agent within lifecycle and execution
|
|
5
|
+
* budgets", over a column marked ACTIVE, which read as bound while `trigger-status` said no event
|
|
6
|
+
* wake would fire (OSK-15428, OSK-15419). It still says what a source does, conditionally.
|
|
7
|
+
*/
|
|
2
8
|
export declare function wakePolicyHeadline(_result?: unknown): string;
|
|
9
|
+
/**
|
|
10
|
+
* The lines above the table. The table is what the Agent may PICK; what is bound is the server's
|
|
11
|
+
* `trigger-status` event-wake block, printed by the same function in the same words, so the two
|
|
12
|
+
* commands cannot disagree. No sentence here concludes "armed" or "none will fire": that depends
|
|
13
|
+
* on Always-On, the upstream installation and leftover rows, which only the facts carry.
|
|
14
|
+
*/
|
|
15
|
+
export declare function wakePolicyLines(result?: CommitmentWakeCapabilities): string[];
|
|
3
16
|
/**
|
|
4
17
|
* `skrr commitments wake-capabilities <id>` — which wakes an Agent may pick.
|
|
5
18
|
*
|
|
@@ -1,12 +1,47 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.wakePolicyHeadline = wakePolicyHeadline;
|
|
4
|
+
exports.wakePolicyLines = wakePolicyLines;
|
|
4
5
|
const core_1 = require("@oclif/core");
|
|
5
6
|
const base_command_1 = require("../../base-command");
|
|
6
7
|
const commitments_1 = require("../../lib/commitments");
|
|
7
8
|
const format_1 = require("../../lib/format");
|
|
9
|
+
const commitment_event_wakes_1 = require("../../lib/commitment-event-wakes");
|
|
10
|
+
/**
|
|
11
|
+
* The headline used to stop at "configured sources may wake the Agent within lifecycle and execution
|
|
12
|
+
* budgets", over a column marked ACTIVE, which read as bound while `trigger-status` said no event
|
|
13
|
+
* wake would fire (OSK-15428, OSK-15419). It still says what a source does, conditionally.
|
|
14
|
+
*/
|
|
8
15
|
function wakePolicyHeadline(_result) {
|
|
9
|
-
return 'Wake behavior: configured sources may wake the Agent within lifecycle and execution budgets.';
|
|
16
|
+
return 'Wake behavior: configured sources may wake the Agent within lifecycle and execution budgets, once an event wake is bound to them.';
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The lines above the table. The table is what the Agent may PICK; what is bound is the server's
|
|
20
|
+
* `trigger-status` event-wake block, printed by the same function in the same words, so the two
|
|
21
|
+
* commands cannot disagree. No sentence here concludes "armed" or "none will fire": that depends
|
|
22
|
+
* on Always-On, the upstream installation and leftover rows, which only the facts carry.
|
|
23
|
+
*/
|
|
24
|
+
function wakePolicyLines(result) {
|
|
25
|
+
const wakes = result?.standingEventWakes;
|
|
26
|
+
const pickable = 'The table lists wakes the Agent may pick, not what is bound.';
|
|
27
|
+
if (!wakes) {
|
|
28
|
+
return [
|
|
29
|
+
wakePolicyHeadline(),
|
|
30
|
+
`${pickable} \`skrr commitments trigger-status <id>\` shows what is bound.`,
|
|
31
|
+
];
|
|
32
|
+
}
|
|
33
|
+
const lines = [wakePolicyHeadline(), pickable];
|
|
34
|
+
if (wakes.commitmentStatus !== 'active') {
|
|
35
|
+
lines.push(`The Commitment's status is ${wakes.commitmentStatus}, so none of this wakes it.`);
|
|
36
|
+
}
|
|
37
|
+
lines.push(`Cadence mode: ${wakes.cadenceMode ?? 'unknown'}`);
|
|
38
|
+
lines.push(...(0, commitment_event_wakes_1.eventWakeLines)(wakes.eventCapabilities));
|
|
39
|
+
lines.push('`materialized` means a trigger exists, not that it is enabled or can fire (Always-On, the upstream ' +
|
|
40
|
+
'installation): `skrr commitments trigger-status <id>` lists each binding with its state.');
|
|
41
|
+
if (wakes.commitmentStatus === 'active' && wakes.agentChosenEventWaits > 0) {
|
|
42
|
+
lines.push(`The Agent has ${wakes.agentChosenEventWaits} event wait(s) of its own set (enabled trigger rows); the cadence does not gate those.`);
|
|
43
|
+
}
|
|
44
|
+
return lines;
|
|
10
45
|
}
|
|
11
46
|
/**
|
|
12
47
|
* `skrr commitments wake-capabilities <id>` — which wakes an Agent may pick.
|
|
@@ -47,7 +82,8 @@ class CommitmentsWakeCapabilities extends base_command_1.BaseCommand {
|
|
|
47
82
|
this.log(JSON.stringify(result, null, 2));
|
|
48
83
|
return;
|
|
49
84
|
}
|
|
50
|
-
|
|
85
|
+
for (const line of wakePolicyLines(result))
|
|
86
|
+
this.log(line);
|
|
51
87
|
const visible = new Set(result.visibleCapabilities.map((item) => item.id));
|
|
52
88
|
(0, format_1.renderTable)(result.eligibleCapabilities.map((item) => ({
|
|
53
89
|
id: item.id,
|
|
@@ -58,7 +94,7 @@ class CommitmentsWakeCapabilities extends base_command_1.BaseCommand {
|
|
|
58
94
|
{ key: 'id', header: 'CAPABILITY' },
|
|
59
95
|
{ key: 'kind', header: 'KIND' },
|
|
60
96
|
{ key: 'source', header: 'SOURCE' },
|
|
61
|
-
{ key: 'offered', header: '
|
|
97
|
+
{ key: 'offered', header: 'OFFERED' },
|
|
62
98
|
], (line) => this.log(line));
|
|
63
99
|
}
|
|
64
100
|
}
|