@skrr-ai/cli 0.1.127 → 0.1.129
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base-command.d.ts +35 -0
- package/dist/base-command.js +107 -0
- package/dist/commands/agenda/trigger/list.d.ts +2 -1
- package/dist/commands/agenda/trigger/list.js +55 -6
- package/dist/commands/agents/chat.js +7 -0
- package/dist/commands/agents/create.js +3 -1
- package/dist/commands/browser/persistent-profile.d.ts +22 -0
- package/dist/commands/browser/persistent-profile.js +46 -0
- package/dist/commands/commitments/action-history.js +1 -1
- package/dist/commands/commitments/cases.js +3 -3
- package/dist/commands/commitments/check-now.d.ts +10 -2
- package/dist/commands/commitments/check-now.js +53 -3
- package/dist/commands/commitments/create.d.ts +6 -14
- package/dist/commands/commitments/create.js +64 -7
- package/dist/commands/commitments/doctor.js +3 -1
- package/dist/commands/commitments/effective-policy.d.ts +11 -1
- package/dist/commands/commitments/effective-policy.js +90 -4
- package/dist/commands/commitments/explain.js +10 -1
- package/dist/commands/commitments/hypotheses.js +12 -12
- package/dist/commands/commitments/next-tick.js +5 -0
- package/dist/commands/commitments/observations.js +18 -17
- package/dist/commands/commitments/pack/list.js +2 -1
- package/dist/commands/commitments/pack/plan.d.ts +6 -0
- package/dist/commands/commitments/pack/plan.js +19 -0
- package/dist/commands/commitments/plan.d.ts +14 -0
- package/dist/commands/commitments/plan.js +32 -0
- package/dist/commands/commitments/preflight.d.ts +20 -1
- package/dist/commands/commitments/preflight.js +118 -12
- package/dist/commands/commitments/show.d.ts +9 -0
- package/dist/commands/commitments/show.js +14 -1
- package/dist/commands/commitments/trigger-status.js +8 -0
- package/dist/commands/commitments/update.d.ts +1 -0
- package/dist/commands/commitments/update.js +45 -4
- package/dist/commands/commitments/wake-capabilities.js +13 -0
- package/dist/commands/compass/archive.js +4 -0
- package/dist/commands/compass/commitments.js +15 -1
- package/dist/commands/compass/create.js +11 -3
- package/dist/commands/compass/effective-policy.d.ts +1 -0
- package/dist/commands/compass/effective-policy.js +8 -7
- package/dist/commands/compass/revert.d.ts +8 -0
- package/dist/commands/compass/revert.js +25 -1
- package/dist/commands/compass/revisions.d.ts +6 -0
- package/dist/commands/compass/revisions.js +26 -2
- package/dist/commands/compass/tactic.d.ts +10 -3
- package/dist/commands/compass/tactic.js +22 -7
- package/dist/commands/compass/update.js +19 -3
- package/dist/commands/followups/act.js +1 -1
- package/dist/commands/followups/cancel.js +13 -0
- package/dist/commands/followups/observability.js +20 -1
- package/dist/commands/followups/plans/create.js +12 -1
- package/dist/commands/followups/show.js +13 -0
- package/dist/commands/followups/watch.js +1 -1
- package/dist/commands/goals/planner-config.d.ts +11 -0
- package/dist/commands/goals/planner-config.js +16 -0
- package/dist/commands/harnesses/list.js +1 -1
- package/dist/commands/machines/update.d.ts +5 -3
- package/dist/commands/machines/update.js +70 -9
- package/dist/commands/northstars/create.js +3 -1
- package/dist/commands/northstars/governance/configure.d.ts +4 -0
- package/dist/commands/northstars/governance/configure.js +76 -10
- package/dist/commands/northstars/intents/decide.d.ts +6 -0
- package/dist/commands/northstars/intents/decide.js +68 -15
- package/dist/commands/northstars/intents/list.d.ts +2 -1
- package/dist/commands/northstars/intents/list.js +15 -5
- package/dist/commands/northstars/intents.d.ts +26 -0
- package/dist/commands/northstars/intents.js +49 -0
- package/dist/commands/northstars/list.d.ts +1 -0
- package/dist/commands/northstars/list.js +24 -3
- package/dist/commands/northstars/recommendations/list.d.ts +1 -1
- package/dist/commands/northstars/recommendations/list.js +3 -3
- package/dist/commands/northstars/recommendations.d.ts +19 -0
- package/dist/commands/northstars/recommendations.js +42 -0
- package/dist/commands/northstars/review-now.d.ts +1 -0
- package/dist/commands/northstars/review-now.js +15 -4
- package/dist/commands/northstars/reviews.d.ts +1 -0
- package/dist/commands/northstars/reviews.js +34 -6
- package/dist/commands/northstars/update.js +8 -1
- package/dist/commands/proposals/list.js +11 -2
- package/dist/commands/proposals/show.js +9 -1
- package/dist/commands/spaces/auto-executor/preview.d.ts +14 -1
- package/dist/commands/spaces/auto-executor/preview.js +35 -1
- package/dist/commands/spaces/auto-executor/run.d.ts +17 -0
- package/dist/commands/spaces/auto-executor/run.js +60 -2
- package/dist/commands/spaces/auto-executor/runs.d.ts +9 -1
- package/dist/commands/spaces/auto-executor/runs.js +18 -1
- package/dist/commands/spaces/files/upload.js +1 -2
- package/dist/commands/spaces/heartbeats/create.js +7 -5
- package/dist/commands/spaces/heartbeats/update.js +5 -3
- package/dist/commands/spaces/index.js +23 -0
- package/dist/commands/store/artifacts/releases.d.ts +20 -0
- package/dist/commands/store/artifacts/releases.js +85 -0
- package/dist/commands/store/library.d.ts +14 -0
- package/dist/commands/store/library.js +71 -0
- package/dist/commands/tasks/list.d.ts +48 -0
- package/dist/commands/tasks/list.js +141 -9
- package/dist/commands/tasks/remind.js +23 -11
- package/dist/commands/tasks/retry-schedule.js +6 -3
- package/dist/commands/tasks/schedule.js +29 -7
- package/dist/commands/tasks/show.js +4 -0
- package/dist/generated/agent-guides.json +69 -69
- package/dist/lib/agent-trigger-listing.d.ts +26 -0
- package/dist/lib/agent-trigger-listing.js +63 -0
- package/dist/lib/agentic-stream.d.ts +9 -0
- package/dist/lib/agentic-stream.js +152 -41
- package/dist/lib/command-miss.js +11 -2
- package/dist/lib/commitment-attention-copy.d.ts +96 -0
- package/dist/lib/commitment-attention-copy.js +209 -0
- package/dist/lib/commitment-ledgers.js +3 -1
- package/dist/lib/commitment-loop-status.d.ts +6 -0
- package/dist/lib/commitment-loop-status.js +16 -6
- package/dist/lib/commitments.d.ts +112 -0
- package/dist/lib/commitments.js +250 -2
- package/dist/lib/compass-body-help.d.ts +20 -0
- package/dist/lib/compass-body-help.js +61 -0
- package/dist/lib/compass-refusals.d.ts +35 -0
- package/dist/lib/compass-refusals.js +50 -0
- package/dist/lib/compasses.d.ts +82 -4
- package/dist/lib/compasses.js +232 -12
- package/dist/lib/followups.d.ts +22 -1
- package/dist/lib/followups.js +21 -1
- package/dist/lib/format.d.ts +11 -0
- package/dist/lib/format.js +29 -0
- package/dist/lib/initiatives.d.ts +9 -2
- package/dist/lib/initiatives.js +13 -2
- package/dist/lib/iso-instant.d.ts +52 -0
- package/dist/lib/iso-instant.js +162 -0
- package/dist/lib/machines.d.ts +14 -1
- package/dist/lib/machines.js +24 -0
- package/dist/lib/northstars.d.ts +201 -24
- package/dist/lib/northstars.js +655 -27
- package/dist/lib/proposal-decision-command.js +21 -1
- package/dist/lib/proposals.d.ts +26 -1
- package/dist/lib/proposals.js +167 -0
- package/dist/lib/rate-limit-retry.d.ts +5 -0
- package/dist/lib/rate-limit-retry.js +19 -0
- package/dist/lib/roles.d.ts +1 -1
- package/dist/lib/space-charter.js +9 -0
- package/dist/lib/store-artifact-releases.d.ts +39 -0
- package/dist/lib/store-artifact-releases.js +12 -0
- package/dist/lib/store-library.d.ts +37 -0
- package/dist/lib/store-library.js +12 -0
- package/dist/lib/task-asset-upload.js +1 -2
- package/dist/lib/task-calendar.d.ts +19 -0
- package/dist/lib/task-calendar.js +72 -0
- package/dist/lib/task-recurrence-outcome.js +3 -1
- package/dist/lib/task-recurrence-summary.d.ts +15 -0
- package/dist/lib/task-recurrence-summary.js +228 -0
- package/dist/lib/task-reminder.d.ts +28 -0
- package/dist/lib/task-reminder.js +50 -0
- package/dist/lib/triggers.d.ts +13 -2
- package/dist/lib/triggers.js +31 -13
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonWire.js +11 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/executorStopReceipt.d.ts +123 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/executorStopReceipt.js +160 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +17 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonWire.js +11 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/executorStopReceipt.d.ts +123 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/executorStopReceipt.js +173 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +6922 -6828
- package/oclif.manifest.json +612 -62
- package/package.json +4 -4
|
@@ -10,6 +10,7 @@ const base_command_1 = require("../../base-command");
|
|
|
10
10
|
const guide_pointer_1 = require("../../lib/guide-pointer");
|
|
11
11
|
const web_url_1 = require("../../lib/web-url");
|
|
12
12
|
const prompt_1 = require("../../lib/prompt");
|
|
13
|
+
const commitment_attention_copy_1 = require("../../lib/commitment-attention-copy");
|
|
13
14
|
const triggers_1 = require("../../lib/triggers");
|
|
14
15
|
const commitment_product_1 = require("../../lib/commitment-product");
|
|
15
16
|
const commitments_1 = require("../../lib/commitments");
|
|
@@ -153,8 +154,27 @@ function createCadenceFromFlags({ eventDriven, cadence: cadenceInput, cadenceMod
|
|
|
153
154
|
* it. `{code, reason, fix}` mirrors the MCP surface's refusal; `guide` points
|
|
154
155
|
* at the section that explains the code when one does (resolved offline).
|
|
155
156
|
*/
|
|
157
|
+
/** Everything that blocks an activation, when the server listed more than the first gate. */
|
|
158
|
+
function activationBlockers(body) {
|
|
159
|
+
const diagnostic = body?.diagnostic;
|
|
160
|
+
if (!Array.isArray(diagnostic?.blockers))
|
|
161
|
+
return [];
|
|
162
|
+
const blockers = [];
|
|
163
|
+
for (const item of diagnostic.blockers) {
|
|
164
|
+
const gate = item?.gate;
|
|
165
|
+
const reason = item?.reason;
|
|
166
|
+
if (typeof gate === 'string' && gate && typeof reason === 'string' && reason) {
|
|
167
|
+
blockers.push({ gate, reason });
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return blockers;
|
|
171
|
+
}
|
|
156
172
|
function commitmentActivationRefusal(err, { id, bin }) {
|
|
157
173
|
const refusal = (0, base_command_1.apiRefusal)(err);
|
|
174
|
+
// `resume` answers with every blocking gate, but only the first is in the message. Fixing it
|
|
175
|
+
// revealed the next one on the following try (Always-On, then the runtime), so the refusal says
|
|
176
|
+
// all of them when there is more than one (dogfood df-261031-commitment-authoring, F12).
|
|
177
|
+
const blockers = activationBlockers(refusal.body);
|
|
158
178
|
const errorField = refusal.body?.error;
|
|
159
179
|
const code = refusal.code ||
|
|
160
180
|
(typeof errorField === 'string' && /^[A-Za-z][A-Za-z0-9_]*$/.test(errorField)
|
|
@@ -162,11 +182,17 @@ function commitmentActivationRefusal(err, { id, bin }) {
|
|
|
162
182
|
: undefined) ||
|
|
163
183
|
'COMMITMENT_ACTIVATION_REFUSED';
|
|
164
184
|
const guide = (0, guide_pointer_1.agentGuidePointerFor)(code);
|
|
185
|
+
// The blocking gate's own remedy beats the generic "fix the gate the reason names": the reason is
|
|
186
|
+
// a token, and the sentence that says what to run is the hint beside it (OSK-21126).
|
|
187
|
+
const hint = (0, base_command_1.commitmentActivationHint)(refusal.body);
|
|
165
188
|
return {
|
|
166
189
|
code,
|
|
167
190
|
reason: refusal.message || (err instanceof Error ? err.message : 'Activation was refused.'),
|
|
168
|
-
fix:
|
|
191
|
+
fix: hint
|
|
192
|
+
? `${hint} Then run \`${bin} commitments resume ${id}\`.`
|
|
193
|
+
: (0, data_provider_1.describeCommitmentActivationFix)(code === 'COMMITMENT_ACTIVATION_REFUSED' ? undefined : code, { turnOn: `run \`${bin} commitments resume ${id}\`` }),
|
|
169
194
|
...(guide ? { guide } : {}),
|
|
195
|
+
...(blockers.length > 1 ? { blockers } : {}),
|
|
170
196
|
};
|
|
171
197
|
}
|
|
172
198
|
/**
|
|
@@ -210,6 +236,7 @@ cat > commitment.json <<'JSON'
|
|
|
210
236
|
}],
|
|
211
237
|
"policy": {
|
|
212
238
|
"maxUserNudgesPerDay": 0,
|
|
239
|
+
"quietHours": { "enabled": true, "start": "22:00", "end": "07:00", "timezone": "Asia/Shanghai" },
|
|
213
240
|
"executionBudget": { "maxRunsPerDay": 0, "maxObservationRunsPerDay": 0, "maxCostUsdPerDay": 0 }
|
|
214
241
|
}
|
|
215
242
|
}
|
|
@@ -217,11 +244,27 @@ JSON
|
|
|
217
244
|
<%= config.bin %> commitments preflight --from-json commitment.json
|
|
218
245
|
<%= config.bin %> commitments create --from-json commitment.json --json`,
|
|
219
246
|
'<%= config.bin %> commitments create --agent <agent-id> --title "Keep CI healthy" --outcome "Failed checks are repaired" --watch github --github-event check_run_failed --event-driven --delivery draft-pr --repo owner/repo --base main --status draft',
|
|
247
|
+
`# Govern a Commitment with a Compass. There is no flag: "compassId" goes in the --from-json body.
|
|
248
|
+
# It must be an active Compass of the same Agent (a draft may name an archived one).
|
|
249
|
+
# The binding cannot be changed later: bind a successor Commitment to another Compass instead.
|
|
250
|
+
cat > commitment.json <<'JSON'
|
|
251
|
+
{
|
|
252
|
+
"agentId": "<agent-id>",
|
|
253
|
+
"compassId": "<compass-id>",
|
|
254
|
+
"title": "Keep p99 under 300 ms",
|
|
255
|
+
"status": "draft",
|
|
256
|
+
"target": { "outcome": "p99 API latency stays under 300 ms" }
|
|
257
|
+
}
|
|
258
|
+
JSON
|
|
259
|
+
<%= config.bin %> commitments create --from-json commitment.json --json
|
|
260
|
+
<%= config.bin %> compass commitments <compass-id> --agent <agent-id> # lists it once it is bound`,
|
|
220
261
|
];
|
|
221
262
|
static flags = {
|
|
222
|
-
json: core_1.Flags.boolean({
|
|
263
|
+
json: core_1.Flags.boolean({
|
|
264
|
+
description: 'Output the created commitment as JSON: the commitment itself, not wrapped (commitments show --json puts it under .commitment)',
|
|
265
|
+
}),
|
|
223
266
|
'from-json': core_1.Flags.string({
|
|
224
|
-
description:
|
|
267
|
+
description: `JSON file (or "-" for stdin) for fields not exposed as flags. See examples below for daily times, named agent_run keys, zero budgets and "compassId" (binds a Compass; fixed at creation). ${commitment_attention_copy_1.QUIET_HOURS_HELP} ${commitment_attention_copy_1.EVENT_SOURCES_HELP}`,
|
|
225
268
|
}),
|
|
226
269
|
agent: core_1.Flags.string({ description: 'Agent that owns and watches this commitment (required)' }),
|
|
227
270
|
kind: core_1.Flags.string({
|
|
@@ -321,7 +364,7 @@ JSON
|
|
|
321
364
|
options: [...commitments_1.COMMITMENT_EXECUTION_ISOLATION_MODES],
|
|
322
365
|
hidden: true,
|
|
323
366
|
}),
|
|
324
|
-
'max-nudges': core_1.Flags.
|
|
367
|
+
'max-nudges': core_1.Flags.string({ description: commitment_attention_copy_1.MAX_NUDGES_FLAG_HELP }),
|
|
325
368
|
'max-concurrent-runs': core_1.Flags.string({
|
|
326
369
|
description: 'Owner concurrency policy: "unlimited" (default) or 1..100. Finite values require --concurrency-reason and cannot be activated by an autonomous Agent session.',
|
|
327
370
|
}),
|
|
@@ -337,7 +380,11 @@ JSON
|
|
|
337
380
|
// `createBodySchema` is a z.strictObject, so unwrap a `plan --json`
|
|
338
381
|
// envelope and drop any key it does not declare (a contract dumped from
|
|
339
382
|
// `list --json` carries id/version/state/… and would otherwise 400).
|
|
340
|
-
|
|
383
|
+
const rawBody = await (0, prompt_1.readJsonBody)(flags['from-json']);
|
|
384
|
+
payload = (0, commitments_1.normalizeCreateBody)(rawBody);
|
|
385
|
+
const ignoredWarning = (0, commitments_1.ignoredCreateKeysWarning)((0, commitments_1.ignoredCreateKeys)(rawBody));
|
|
386
|
+
if (ignoredWarning)
|
|
387
|
+
this.warn(ignoredWarning);
|
|
341
388
|
if (flags.agent)
|
|
342
389
|
payload.agentId = flags.agent;
|
|
343
390
|
if (flags.kind)
|
|
@@ -430,8 +477,9 @@ JSON
|
|
|
430
477
|
(0, commitment_product_1.normalizeTaskReviewPolicy)(declaredDelivery.reviewPolicy);
|
|
431
478
|
if (flags.isolation)
|
|
432
479
|
policy.executionIsolation = flags.isolation;
|
|
433
|
-
|
|
434
|
-
|
|
480
|
+
const maxNudges = (0, commitment_attention_copy_1.parseMaxNudgesFlag)(flags['max-nudges']);
|
|
481
|
+
if (maxNudges !== undefined)
|
|
482
|
+
policy.maxUserNudgesPerDay = maxNudges;
|
|
435
483
|
const concurrencyPatch = (0, commitments_1.commitmentConcurrencyEnvelopePatch)({
|
|
436
484
|
rawValue: flags['max-concurrent-runs'],
|
|
437
485
|
reason: flags['concurrency-reason'],
|
|
@@ -446,6 +494,9 @@ JSON
|
|
|
446
494
|
}
|
|
447
495
|
if (Object.keys(policy).length)
|
|
448
496
|
payload.policy = policy;
|
|
497
|
+
const quietHoursProblem = (0, commitment_attention_copy_1.quietHoursInputProblem)(policy);
|
|
498
|
+
if (quietHoursProblem)
|
|
499
|
+
throw new Error(quietHoursProblem);
|
|
449
500
|
if (payload.createdVia === undefined) {
|
|
450
501
|
payload.createdVia = process.env.OVERSKY_AUTONOMOUS_SESSION === '1' ? 'agent_cli' : 'cli';
|
|
451
502
|
}
|
|
@@ -533,6 +584,12 @@ JSON
|
|
|
533
584
|
if (activation && !activation.activated) {
|
|
534
585
|
const { refusal } = activation;
|
|
535
586
|
this.warn(`Activation refused (${refusal.code}): ${refusal.reason}`);
|
|
587
|
+
if (refusal.blockers) {
|
|
588
|
+
this.warn(`All ${refusal.blockers.length} things blocking it (it stays a draft until each is fixed):`);
|
|
589
|
+
for (const blocker of refusal.blockers)
|
|
590
|
+
this.warn(` - ${blocker.gate}: ${blocker.reason}`);
|
|
591
|
+
this.warn(`Details: ${this.config.bin} commitments preflight ${String(commitment?.id)}`);
|
|
592
|
+
}
|
|
536
593
|
if (refusal.fix)
|
|
537
594
|
this.warn(`Fix: ${refusal.fix}`);
|
|
538
595
|
if (refusal.guide)
|
|
@@ -86,7 +86,9 @@ function spaceLoopLine(value) {
|
|
|
86
86
|
if (status === 'admitted') {
|
|
87
87
|
detail = loop.principalVersion ? ` (principal v${loop.principalVersion})` : '';
|
|
88
88
|
}
|
|
89
|
-
|
|
89
|
+
// Said in words first, with the code kept in parentheses for anyone who searches by it.
|
|
90
|
+
const said = status !== 'admitted' && loop.detail ? ` — ${loop.detail}` : '';
|
|
91
|
+
return `Space loop: ${status}${loop.spaceId ? ` · ${loop.spaceId}` : ''}${said}${detail}`;
|
|
90
92
|
}
|
|
91
93
|
class CommitmentsDoctor extends base_command_1.BaseCommand {
|
|
92
94
|
static description = 'Summarize commitment readiness and the next operator action';
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { BaseCommand } from '../../base-command';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* `2026-11-02 00:00` for an instant, in a time zone. Built from parts, never from a locale: `02/11/2026`
|
|
4
|
+
* is the 2nd of November to one reader and the 11th of February to the next, and the budget reset is
|
|
5
|
+
* exactly the date a person reads this line for.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isoWallClock(instant: unknown, timeZone?: string): string | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* `stored` is the Commitment's own policy, read beside the effective one: the no-reply back-off
|
|
10
|
+
* is not part of the effective-policy answer, so without it that line is left out, not guessed.
|
|
11
|
+
*/
|
|
12
|
+
export declare function effectivePolicyLines(policy: Record<string, any>, stored?: Record<string, any> | null): string[];
|
|
3
13
|
/** Show the policy actually governing a Commitment without changing it. */
|
|
4
14
|
export default class CommitmentsEffectivePolicy extends BaseCommand {
|
|
5
15
|
static description: string;
|
|
@@ -1,23 +1,62 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isoWallClock = isoWallClock;
|
|
3
4
|
exports.effectivePolicyLines = effectivePolicyLines;
|
|
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 commitment_product_1 = require("../../lib/commitment-product");
|
|
9
|
+
const commitment_attention_copy_1 = require("../../lib/commitment-attention-copy");
|
|
10
|
+
const northstars_1 = require("../../lib/northstars");
|
|
8
11
|
/** Which limit binds the daily action runs — the fix lives on that object. */
|
|
9
12
|
const RUN_LIMIT_BINDING_LABELS = {
|
|
10
13
|
northstar_allocation: 'Northstar allocation',
|
|
11
14
|
workspace_admin: 'workspace limit',
|
|
12
15
|
owner: 'owner limit',
|
|
13
16
|
};
|
|
17
|
+
/**
|
|
18
|
+
* `2026-11-02 00:00` for an instant, in a time zone. Built from parts, never from a locale: `02/11/2026`
|
|
19
|
+
* is the 2nd of November to one reader and the 11th of February to the next, and the budget reset is
|
|
20
|
+
* exactly the date a person reads this line for.
|
|
21
|
+
*/
|
|
22
|
+
function isoWallClock(instant, timeZone = 'UTC') {
|
|
23
|
+
const date = new Date(String(instant ?? ''));
|
|
24
|
+
if (Number.isNaN(date.getTime()))
|
|
25
|
+
return undefined;
|
|
26
|
+
try {
|
|
27
|
+
const parts = new Intl.DateTimeFormat('en-US', {
|
|
28
|
+
timeZone,
|
|
29
|
+
year: 'numeric',
|
|
30
|
+
month: '2-digit',
|
|
31
|
+
day: '2-digit',
|
|
32
|
+
hour: '2-digit',
|
|
33
|
+
minute: '2-digit',
|
|
34
|
+
hourCycle: 'h23',
|
|
35
|
+
}).formatToParts(date);
|
|
36
|
+
const part = (type) => parts.find((p) => p.type === type)?.value;
|
|
37
|
+
return `${part('year')}-${part('month')}-${part('day')} ${part('hour')}:${part('minute')}`;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
14
43
|
/** The admission day is UTC and said so; the shared Northstar pools are named apart. */
|
|
15
44
|
function budgetDayLines(policy) {
|
|
16
45
|
const day = policy.budgetDay;
|
|
17
46
|
const shared = policy.portfolio?.sharedBudget;
|
|
18
47
|
const lines = [];
|
|
19
48
|
if (day) {
|
|
20
|
-
|
|
49
|
+
// The server's `localResetAt` is day-first (`02/11/2026, 00:00`); the next reset is rebuilt from the
|
|
50
|
+
// ISO instant it also sends, so the date reads the same to everyone.
|
|
51
|
+
const next = isoWallClock(day.nextResetAt);
|
|
52
|
+
const local = day.localTimeZone && day.localTimeZone !== 'UTC'
|
|
53
|
+
? isoWallClock(day.nextResetAt, day.localTimeZone)
|
|
54
|
+
: undefined;
|
|
55
|
+
const when = [
|
|
56
|
+
next ? `next ${next} UTC` : undefined,
|
|
57
|
+
local ? `${local} ${day.localTimeZone}` : undefined,
|
|
58
|
+
].filter(Boolean);
|
|
59
|
+
lines.push(`Daily budgets reset at ${day.resetsAt ?? '00:00 UTC'}${when.length ? ` (${when.join('; ')})` : ''}`);
|
|
21
60
|
}
|
|
22
61
|
if (shared?.status === 'unavailable') {
|
|
23
62
|
lines.push('Northstar shared run pools: unavailable (could not be read)');
|
|
@@ -33,10 +72,23 @@ function budgetDayLines(policy) {
|
|
|
33
72
|
? 'no ceiling'
|
|
34
73
|
: `${value}/day`;
|
|
35
74
|
lines.push(`Northstar shared pools: action runs ${pool(shared.actionRunsPerDay, shared.actionRunsPerDayState)} · observation runs ${pool(shared.observationRunsPerDay, shared.observationRunsPerDayState)}`);
|
|
75
|
+
// A pool below the number of linked active commitments is still handed out at the floor of
|
|
76
|
+
// 1/day each: the same sentence `northstars governance show` and `review-now` print (OSK-21334).
|
|
77
|
+
const floorNote = (0, northstars_1.runBudgetFloorNote)(policy.portfolio?.runBudgetFloor);
|
|
78
|
+
if (floorNote)
|
|
79
|
+
lines.push(`! ${floorNote}`);
|
|
36
80
|
}
|
|
37
81
|
return lines;
|
|
38
82
|
}
|
|
39
|
-
|
|
83
|
+
/** An effective-policy `{ mode, value }` limit, back to the stored `null` = unlimited. */
|
|
84
|
+
function storedLimit(limit) {
|
|
85
|
+
return limit?.mode === 'limited' ? limit.value : null;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* `stored` is the Commitment's own policy, read beside the effective one: the no-reply back-off
|
|
89
|
+
* is not part of the effective-policy answer, so without it that line is left out, not guessed.
|
|
90
|
+
*/
|
|
91
|
+
function effectivePolicyLines(policy, stored) {
|
|
40
92
|
const governance = policy.governance || {};
|
|
41
93
|
const owner = policy.owner || {};
|
|
42
94
|
const lines = [];
|
|
@@ -61,7 +113,16 @@ function effectivePolicyLines(policy) {
|
|
|
61
113
|
lines.push(`Owner action-run limit: ${runLimit.mode === 'unbounded' ? 'Unlimited' : `${runLimit.value}/day`}`);
|
|
62
114
|
}
|
|
63
115
|
const effectiveRuns = policy.effective?.actionRunsPerDay;
|
|
64
|
-
|
|
116
|
+
// A portfolio pool of 0 refuses every action run, so "Unlimited" on the line above it is false and
|
|
117
|
+
// the pool line below it ("action runs 0/day") contradicts it: say what the pool means here.
|
|
118
|
+
const sharedPool = policy.portfolio?.sharedBudget;
|
|
119
|
+
const poolRefusesAll = sharedPool?.status === 'available' &&
|
|
120
|
+
sharedPool.actionRunsPerDay === 0 &&
|
|
121
|
+
sharedPool.actionRunsPerDayState !== 'malformed';
|
|
122
|
+
if (poolRefusesAll) {
|
|
123
|
+
lines.push('Action runs: none (portfolio pool is 0/day)');
|
|
124
|
+
}
|
|
125
|
+
else if (effectiveRuns) {
|
|
65
126
|
const bindingLabel = RUN_LIMIT_BINDING_LABELS[effectiveRuns.binding];
|
|
66
127
|
const binding = bindingLabel ? ` (binding: ${bindingLabel})` : '';
|
|
67
128
|
lines.push(`Effective action-run limit: ${effectiveRuns.mode === 'unbounded' ? 'Unlimited' : `${effectiveRuns.value}/day`}${binding}`);
|
|
@@ -72,6 +133,21 @@ function effectivePolicyLines(policy) {
|
|
|
72
133
|
}
|
|
73
134
|
if (policy.observation?.sensing)
|
|
74
135
|
lines.push("Sensing runs: the Agent's own permissions");
|
|
136
|
+
// How much it may interrupt the owner (OSK-21120). The JSON has carried the cap and the gap as
|
|
137
|
+
// `owner.userNudgesPerDay` / `minUserNudgeIntervalMs`; the text dropped both.
|
|
138
|
+
if (owner.userNudgesPerDay) {
|
|
139
|
+
lines.push(...(0, commitment_attention_copy_1.nudgeSettingLines)({
|
|
140
|
+
maxUserNudgesPerDay: storedLimit(owner.userNudgesPerDay),
|
|
141
|
+
minUserNudgeIntervalMs: storedLimit(owner.minUserNudgeIntervalMs),
|
|
142
|
+
noReply: stored?.attention?.noReply,
|
|
143
|
+
}, { withNoReply: Boolean(stored) }));
|
|
144
|
+
}
|
|
145
|
+
// Which event sources may wake it (OSK-21113). The effective-policy answer has never carried
|
|
146
|
+
// `allowedEventSources`, so it is read from the Commitment's own policy; unread, the line is
|
|
147
|
+
// left out, because "all allowed" would be a claim.
|
|
148
|
+
if (stored) {
|
|
149
|
+
lines.push(`Event sources: ${(0, commitment_attention_copy_1.describeEventSources)(stored.executionBudget?.allowedEventSources)}`);
|
|
150
|
+
}
|
|
75
151
|
lines.push(...budgetDayLines(policy));
|
|
76
152
|
return lines;
|
|
77
153
|
}
|
|
@@ -104,8 +180,18 @@ class CommitmentsEffectivePolicy extends base_command_1.BaseCommand {
|
|
|
104
180
|
this.log(JSON.stringify(policy, null, 2));
|
|
105
181
|
return;
|
|
106
182
|
}
|
|
183
|
+
// The Commitment's own policy, for the settings the effective answer does not carry. A failed
|
|
184
|
+
// read costs those lines, never the command.
|
|
185
|
+
let stored = null;
|
|
186
|
+
try {
|
|
187
|
+
stored =
|
|
188
|
+
(await commitments_1.commitmentApi.get(args.id))?.commitment?.policy ?? null;
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
stored = null;
|
|
192
|
+
}
|
|
107
193
|
this.log('Effective policy:');
|
|
108
|
-
for (const line of effectivePolicyLines(policy))
|
|
194
|
+
for (const line of effectivePolicyLines(policy, stored))
|
|
109
195
|
this.log(` ${line}`);
|
|
110
196
|
if (flags.verbose) {
|
|
111
197
|
this.log('\nRaw policy diagnostics:');
|
|
@@ -24,13 +24,22 @@ class CommitmentsExplain extends base_command_1.BaseCommand {
|
|
|
24
24
|
this.requireAuth();
|
|
25
25
|
const { args, flags } = await this.parse(CommitmentsExplain);
|
|
26
26
|
try {
|
|
27
|
-
|
|
27
|
+
// The explanation names neither the bound Compass nor its status, so the text view reads the
|
|
28
|
+
// Commitment beside it (the read `show` renders). `--json` stays the explanation as the
|
|
29
|
+
// server sent it, with no extra request. A failed read must not fail the explanation
|
|
30
|
+
// (OSK-21332): it becomes a "not shown" line instead.
|
|
31
|
+
const [explanation, read] = await Promise.all([
|
|
32
|
+
commitments_1.commitmentApi.explain(args.commitmentId),
|
|
33
|
+
flags.json ? null : commitments_1.commitmentApi.get(args.commitmentId).catch(() => null),
|
|
34
|
+
]);
|
|
28
35
|
if (flags.json) {
|
|
29
36
|
this.log(JSON.stringify(explanation, null, 2));
|
|
30
37
|
return;
|
|
31
38
|
}
|
|
32
39
|
for (const line of (0, commitments_1.formatCommitmentExplanation)(explanation))
|
|
33
40
|
this.log(line);
|
|
41
|
+
for (const line of (0, commitments_1.explainCompassLines)(args.commitmentId, read?.commitment))
|
|
42
|
+
this.log(line);
|
|
34
43
|
}
|
|
35
44
|
catch (err) {
|
|
36
45
|
this.handleApiError(err);
|
|
@@ -55,20 +55,20 @@ class CommitmentsHypotheses extends base_command_1.BaseCommand {
|
|
|
55
55
|
this.handleApiError(err);
|
|
56
56
|
}
|
|
57
57
|
if (flags.json) {
|
|
58
|
+
// One JSON document and nothing else: has_more / next_cursor are in it.
|
|
58
59
|
this.log(JSON.stringify(response, null, 2));
|
|
60
|
+
return;
|
|
59
61
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
(0, commitments_1.renderCommitmentHypotheses)(response, (line) => this.log(line), { emptyMessage });
|
|
71
|
-
}
|
|
62
|
+
// A filtered-out list is not an empty ledger — say which filter did it
|
|
63
|
+
// (OSK-10953).
|
|
64
|
+
const filters = [
|
|
65
|
+
flags.status ? `--status ${flags.status}` : null,
|
|
66
|
+
flags['investigation-key'] ? `--investigation-key ${flags['investigation-key']}` : null,
|
|
67
|
+
].filter(Boolean);
|
|
68
|
+
const emptyMessage = filters.length
|
|
69
|
+
? `No hypotheses match ${filters.join(' ')}.`
|
|
70
|
+
: 'No hypotheses recorded.';
|
|
71
|
+
(0, commitments_1.renderCommitmentHypotheses)(response, (line) => this.log(line), { emptyMessage });
|
|
72
72
|
(0, commitments_1.renderListPageHint)(response, (line) => this.log(line));
|
|
73
73
|
}
|
|
74
74
|
}
|
|
@@ -71,6 +71,11 @@ function formatNextTick(projection) {
|
|
|
71
71
|
// is entirely in that: a reader who thinks a check just ran will misread
|
|
72
72
|
// every number on the commitment afterwards.
|
|
73
73
|
'Projection only — no check was recorded, no budget spent, no action routed.',
|
|
74
|
+
// And what it does not MODEL (OSK-21104): it decides from the evidence alone. A real Check also
|
|
75
|
+
// applies the repeat-evidence window, earlier Runs and owed retries, today's Run budget, the
|
|
76
|
+
// dispatch breaker and the attention contract, so it can stop sooner than this, or run a
|
|
77
|
+
// retry this does not show. Without the sentence a projected `enqueue_agent_turn` reads as a promise.
|
|
78
|
+
"It decides from the evidence alone: a real check also applies the repeat-evidence window, earlier runs and owed retries, today's run budget, the dispatch breaker and the attention contract, so it can stop sooner (or run a retry) than shown here.",
|
|
74
79
|
'',
|
|
75
80
|
`Posture: ${decision.posture ?? '-'}`,
|
|
76
81
|
`Health: ${decision.health ?? '-'}`,
|
|
@@ -152,25 +152,26 @@ class CommitmentsObservations extends base_command_1.BaseCommand {
|
|
|
152
152
|
this.handleApiError(err);
|
|
153
153
|
}
|
|
154
154
|
if (flags.json) {
|
|
155
|
+
// One JSON document and nothing else: has_more / next_cursor are in it
|
|
156
|
+
// (OSK-21118).
|
|
155
157
|
this.printJsonResult(response);
|
|
158
|
+
return;
|
|
156
159
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
(0, commitments_1.renderCommitmentObservations)(response, (line) => this.log(line), { emptyMessage });
|
|
173
|
-
}
|
|
160
|
+
// "The commitment has none" and "your filter matched none" are different
|
|
161
|
+
// facts; a filter that empties the list must not claim the first
|
|
162
|
+
// (OSK-10953).
|
|
163
|
+
const filters = [
|
|
164
|
+
flags.latest ? '--latest' : null,
|
|
165
|
+
flags['declared-only'] ? '--declared-only' : null,
|
|
166
|
+
flags['changed-only'] ? '--changed-only' : null,
|
|
167
|
+
flags.since ? `--since ${flags.since}` : null,
|
|
168
|
+
].filter(Boolean);
|
|
169
|
+
const emptyMessage = filters.length
|
|
170
|
+
? `No observations match ${filters.join(' ')}.`
|
|
171
|
+
: 'No observations recorded.';
|
|
172
|
+
if (response?.truncated)
|
|
173
|
+
this.log(`TRUNCATED: ${response.omitted} current keys omitted; increase --limit (max 200).`);
|
|
174
|
+
(0, commitments_1.renderCommitmentObservations)(response, (line) => this.log(line), { emptyMessage });
|
|
174
175
|
(0, commitments_1.renderListPageHint)(response, (line) => this.log(line));
|
|
175
176
|
}
|
|
176
177
|
}
|
|
@@ -41,7 +41,8 @@ class CommitmentsPackList extends base_command_1.BaseCommand {
|
|
|
41
41
|
(0, format_1.renderTable)(rows.map((pack) => ({
|
|
42
42
|
id: String(pack.id),
|
|
43
43
|
version: String(pack.version),
|
|
44
|
-
|
|
44
|
+
// The catalogue names a Pack `label`; reading only `title` printed a blank column for all eight.
|
|
45
|
+
title: String(pack.label || pack.title || ''),
|
|
45
46
|
})), [
|
|
46
47
|
// No maxWidth: a clipped pack id cannot be pasted into `pack plan --pack` (OSK-6175).
|
|
47
48
|
{ key: 'id', header: 'PACK ID' },
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
import { type CommitmentPackPlanResponse } from '../../../lib/commitments';
|
|
3
|
+
/**
|
|
4
|
+
* Lines for what the plan says will stop the loop from ever being activated. `bind` would still
|
|
5
|
+
* write a draft, so a reader who sees only "Nothing was created" must also see this.
|
|
6
|
+
*/
|
|
7
|
+
export declare function formatReadiness(readiness: CommitmentPackPlanResponse['readiness']): string[];
|
|
2
8
|
/**
|
|
3
9
|
* Draft what a Pack WOULD create, without creating it.
|
|
4
10
|
*
|
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatReadiness = formatReadiness;
|
|
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");
|
|
7
|
+
/**
|
|
8
|
+
* Lines for what the plan says will stop the loop from ever being activated. `bind` would still
|
|
9
|
+
* write a draft, so a reader who sees only "Nothing was created" must also see this.
|
|
10
|
+
*/
|
|
11
|
+
function formatReadiness(readiness) {
|
|
12
|
+
if (!readiness?.length)
|
|
13
|
+
return [];
|
|
14
|
+
const lines = [];
|
|
15
|
+
for (const item of readiness) {
|
|
16
|
+
lines.push(`Not ready: ${item.label} — ${item.reason}`);
|
|
17
|
+
if (item.hint)
|
|
18
|
+
lines.push(` ${item.hint}`);
|
|
19
|
+
}
|
|
20
|
+
lines.push(' `bind` would still create the draft, but `pack activate` will be refused until this is fixed.');
|
|
21
|
+
return lines;
|
|
22
|
+
}
|
|
6
23
|
/**
|
|
7
24
|
* Draft what a Pack WOULD create, without creating it.
|
|
8
25
|
*
|
|
@@ -87,6 +104,8 @@ class CommitmentsPackPlan extends base_command_1.BaseCommand {
|
|
|
87
104
|
const holder = placement.holder === 'space_lead' ? ' (the Space lead)' : '';
|
|
88
105
|
this.log(`Space loop: ${placement.spaceId}, held by ${placement.agentId}${holder}`);
|
|
89
106
|
}
|
|
107
|
+
for (const line of formatReadiness(result.readiness))
|
|
108
|
+
this.log(line);
|
|
90
109
|
this.log('\nNothing was created. Pass this digest to `skrr commitments pack bind --plan-digest`.');
|
|
91
110
|
}
|
|
92
111
|
}
|
|
@@ -18,6 +18,20 @@ import { BaseCommand } from '../../base-command';
|
|
|
18
18
|
* the command body so it can be unit-tested without the oclif harness.
|
|
19
19
|
*/
|
|
20
20
|
export declare function formatDroppedFields(droppedFields: string[] | undefined): string[];
|
|
21
|
+
/**
|
|
22
|
+
* The zone a proposal's daily times will be read in, said before the person applies it (OSK-21336).
|
|
23
|
+
* The planner is not told a timezone unless `--timezone` is passed, and the proposal is printed as raw JSON,
|
|
24
|
+
* so "every day at 9am" came back as `times: ["09:00"]` with no zone; applied as it is, a daily cadence with
|
|
25
|
+
* no zone is read in UTC, while the web wizard writes the browser's zone for the same proposal and says so.
|
|
26
|
+
* Nothing for a proposal with no daily times.
|
|
27
|
+
*/
|
|
28
|
+
export declare function planTimezoneLines(proposal: {
|
|
29
|
+
cadence?: {
|
|
30
|
+
mode?: unknown;
|
|
31
|
+
times?: unknown;
|
|
32
|
+
timezone?: unknown;
|
|
33
|
+
};
|
|
34
|
+
} | null | undefined, requestedTimezone?: string): string[];
|
|
21
35
|
export default class CommitmentsPlan extends BaseCommand {
|
|
22
36
|
static description: string;
|
|
23
37
|
static examples: string[];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.formatDroppedFields = formatDroppedFields;
|
|
4
|
+
exports.planTimezoneLines = planTimezoneLines;
|
|
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");
|
|
@@ -36,6 +37,35 @@ function formatDroppedFields(droppedFields) {
|
|
|
36
37
|
lines.push(` - ${field}`);
|
|
37
38
|
return lines;
|
|
38
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* The zone a proposal's daily times will be read in, said before the person applies it (OSK-21336).
|
|
42
|
+
* The planner is not told a timezone unless `--timezone` is passed, and the proposal is printed as raw JSON,
|
|
43
|
+
* so "every day at 9am" came back as `times: ["09:00"]` with no zone; applied as it is, a daily cadence with
|
|
44
|
+
* no zone is read in UTC, while the web wizard writes the browser's zone for the same proposal and says so.
|
|
45
|
+
* Nothing for a proposal with no daily times.
|
|
46
|
+
*/
|
|
47
|
+
function planTimezoneLines(proposal, requestedTimezone) {
|
|
48
|
+
const cadence = proposal?.cadence;
|
|
49
|
+
if (!cadence || cadence.mode !== 'daily' || !Array.isArray(cadence.times) || !cadence.times.length) {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
const times = cadence.times.filter((time) => typeof time === 'string');
|
|
53
|
+
if (!times.length)
|
|
54
|
+
return [];
|
|
55
|
+
const label = `daily time${times.length === 1 ? '' : 's'} ${times.join(', ')}`;
|
|
56
|
+
if (typeof cadence.timezone === 'string' && cadence.timezone) {
|
|
57
|
+
return ['', `The ${label} ${times.length === 1 ? 'is' : 'are'} read in ${cadence.timezone}.`];
|
|
58
|
+
}
|
|
59
|
+
return [
|
|
60
|
+
'',
|
|
61
|
+
`Note: the ${label} ${times.length === 1 ? 'carries' : 'carry'} no timezone, so applying this as it is reads ` +
|
|
62
|
+
`${times.length === 1 ? 'it' : 'them'} in UTC (the web wizard would use your browser's zone). ` +
|
|
63
|
+
(requestedTimezone
|
|
64
|
+
? `You planned with --timezone ${requestedTimezone}, but the proposal did not keep it: add "timezone": ` +
|
|
65
|
+
`"${requestedTimezone}" to its cadence.`
|
|
66
|
+
: 'Add "timezone": "<IANA zone>" to its cadence, or plan again with --timezone <IANA zone>.'),
|
|
67
|
+
];
|
|
68
|
+
}
|
|
39
69
|
class CommitmentsPlan extends base_command_1.BaseCommand {
|
|
40
70
|
static description = 'Draft a commitment contract from a sentence (read-only proposal — nothing is created)';
|
|
41
71
|
static examples = [
|
|
@@ -115,6 +145,8 @@ class CommitmentsPlan extends base_command_1.BaseCommand {
|
|
|
115
145
|
this.log('No proposal produced.');
|
|
116
146
|
return;
|
|
117
147
|
}
|
|
148
|
+
for (const line of planTimezoneLines(response.proposal, flags.timezone))
|
|
149
|
+
this.log(line);
|
|
118
150
|
this.log('');
|
|
119
151
|
this.log('Proposed contract:');
|
|
120
152
|
this.log(JSON.stringify(response.proposal, null, 2));
|
|
@@ -35,7 +35,26 @@ export declare function nextRunsLines(report: {
|
|
|
35
35
|
verdict?: string;
|
|
36
36
|
nextRuns?: string[];
|
|
37
37
|
}): string[];
|
|
38
|
-
|
|
38
|
+
/**
|
|
39
|
+
* The first line of a preflight. `Ready to run` is a statement about activation (no blocking gate),
|
|
40
|
+
* and it sat directly above a spend-gate warning that the daily Run budget is 0, i.e. that no agent
|
|
41
|
+
* turn can ever start (OSK-21224). The verdict stays `ready` on purpose: a zero ACTION budget does
|
|
42
|
+
* not stop the sensing lane, so refusing activation would be wrong for a Commitment that only
|
|
43
|
+
* observes. The headline carries the caveat instead of contradicting the gate below it.
|
|
44
|
+
*/
|
|
45
|
+
export declare function preflightHeadline(report: Pick<CommitmentPreflightReport, 'verdict' | 'gates'>, persisted: boolean): string;
|
|
46
|
+
export declare function preflightGateLines(gate: PreflightGate, verbose?: boolean, refusesActivation?: boolean): string[];
|
|
47
|
+
/**
|
|
48
|
+
* The `Attention:` footer, and under it the settings behind the verdict (OSK-21120).
|
|
49
|
+
*
|
|
50
|
+
* "delivery allowed now" is the same words for a cap of 1, a mute lifted and no limit at all, so
|
|
51
|
+
* the cap, the gap and the no-reply rule are said beside it. `policy` is the stored policy the
|
|
52
|
+
* report was computed from, or the unsaved one under `--from-json`; without it nothing is said
|
|
53
|
+
* about the settings, rather than a guess. The raw reason code (`policy_nudge_muted`) is printed only
|
|
54
|
+
* with `--verbose`: beside the sentence it said the same thing twice, in a vocabulary nobody types
|
|
55
|
+
* (OSK-21124).
|
|
56
|
+
*/
|
|
57
|
+
export declare function attentionFooterLines(attention: CommitmentPreflightReport['attention'] | undefined, policy?: Record<string, any> | null, verbose?: boolean): string[];
|
|
39
58
|
export default class CommitmentsPreflight extends BaseCommand {
|
|
40
59
|
static description: string;
|
|
41
60
|
static examples: string[];
|