@skrr-ai/cli 0.1.37 → 0.1.39
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/bin/dev-fallback.js +175 -4
- package/dist/base-command.js +46 -2
- package/dist/commands/agents/actions/create.js +18 -7
- package/dist/commands/agents/actions/delete.d.ts +1 -0
- package/dist/commands/agents/actions/delete.js +7 -0
- package/dist/commands/agents/actions/update.js +5 -3
- package/dist/commands/agents/api-actions/add.js +5 -2
- package/dist/commands/agents/api-actions/index.d.ts +11 -0
- package/dist/commands/agents/api-actions/index.js +27 -1
- package/dist/commands/agents/avatar/default/index.d.ts +11 -0
- package/dist/commands/agents/avatar/default/index.js +17 -0
- package/dist/commands/agents/avatar/default/set.d.ts +2 -1
- package/dist/commands/agents/avatar/default/set.js +32 -7
- package/dist/commands/agents/avatar/upload.js +7 -1
- package/dist/commands/agents/categories/delete.js +8 -0
- package/dist/commands/agents/categories/index.d.ts +21 -5
- package/dist/commands/agents/categories/index.js +68 -15
- package/dist/commands/agents/chat.d.ts +21 -0
- package/dist/commands/agents/chat.js +94 -7
- package/dist/commands/agents/create.js +11 -4
- package/dist/commands/agents/list.d.ts +15 -0
- package/dist/commands/agents/list.js +31 -1
- package/dist/commands/agents/scene-background/upload.d.ts +30 -0
- package/dist/commands/agents/scene-background/upload.js +97 -0
- package/dist/commands/agents/show.js +13 -0
- package/dist/commands/agents/tools/calls.d.ts +23 -5
- package/dist/commands/agents/tools/calls.js +81 -18
- package/dist/commands/agents/update.js +15 -5
- package/dist/commands/code/{oversky-agent.d.ts → skrr-agent.d.ts} +3 -3
- package/dist/commands/code/{oversky-agent.js → skrr-agent.js} +11 -8
- package/dist/commands/convos/messages.d.ts +13 -0
- package/dist/commands/convos/messages.js +40 -16
- package/dist/commands/daemon/index.js +8 -1
- package/dist/commands/daemon/logs.d.ts +26 -0
- package/dist/commands/daemon/logs.js +56 -0
- package/dist/commands/daemon/uninstall.js +1 -1
- package/dist/commands/followups/act.js +3 -2
- package/dist/commands/followups/cancel.d.ts +6 -3
- package/dist/commands/followups/cancel.js +16 -6
- package/dist/commands/followups/observability.d.ts +23 -0
- package/dist/commands/followups/observability.js +114 -0
- package/dist/commands/followups/reschedule.js +1 -1
- package/dist/commands/followups/resolve.js +3 -3
- package/dist/commands/followups/show.js +2 -1
- package/dist/commands/followups/watch.js +9 -5
- package/dist/commands/harnesses/forget.js +28 -0
- package/dist/commands/harnesses/install.d.ts +41 -0
- package/dist/commands/harnesses/install.js +165 -0
- package/dist/commands/harnesses/installers.d.ts +45 -0
- package/dist/commands/harnesses/installers.js +155 -0
- package/dist/commands/harnesses/list.d.ts +82 -1
- package/dist/commands/harnesses/list.js +104 -12
- package/dist/commands/harnesses/models.js +10 -1
- package/dist/commands/harnesses/show.d.ts +15 -0
- package/dist/commands/harnesses/show.js +44 -3
- package/dist/commands/harnesses/update.js +1 -1
- package/dist/commands/harnesses/usage.d.ts +25 -0
- package/dist/commands/harnesses/usage.js +24 -2
- package/dist/commands/instructions/status.js +13 -1
- package/dist/commands/machines/dedicated/catalog.js +4 -15
- package/dist/commands/machines/dedicated/create.d.ts +8 -0
- package/dist/commands/machines/dedicated/create.js +63 -2
- package/dist/commands/machines/dedicated/destroy.js +19 -5
- package/dist/commands/machines/dedicated/exec.js +3 -1
- package/dist/commands/machines/dedicated/list.js +9 -6
- package/dist/commands/machines/dedicated/price-book.d.ts +17 -0
- package/dist/commands/machines/dedicated/price-book.js +35 -0
- package/dist/commands/machines/hosted/list.js +12 -0
- package/dist/commands/machines/list.js +11 -0
- package/dist/commands/machines/show.d.ts +1 -0
- package/dist/commands/machines/show.js +40 -11
- package/dist/commands/profiles/list.d.ts +23 -0
- package/dist/commands/profiles/list.js +96 -0
- package/dist/commands/search/skills.d.ts +11 -1
- package/dist/commands/search/skills.js +26 -8
- package/dist/commands/skills/details.d.ts +2 -0
- package/dist/commands/skills/details.js +24 -1
- package/dist/commands/skills/import-as-actions.d.ts +32 -0
- package/dist/commands/skills/import-as-actions.js +175 -0
- package/dist/commands/skills/install.d.ts +2 -0
- package/dist/commands/skills/install.js +24 -1
- package/dist/commands/skills/invocable.js +6 -2
- package/dist/commands/skills/local.d.ts +40 -0
- package/dist/commands/skills/local.js +160 -0
- package/dist/commands/skills/search.d.ts +11 -1
- package/dist/commands/skills/search.js +29 -8
- package/dist/commands/spaces/actions/add.js +23 -5
- package/dist/commands/spaces/actions/available.js +3 -0
- package/dist/commands/spaces/actions/list.d.ts +5 -0
- package/dist/commands/spaces/actions/list.js +49 -3
- package/dist/commands/spaces/actions/run.d.ts +28 -0
- package/dist/commands/spaces/actions/run.js +146 -0
- package/dist/commands/spaces/actions/update.js +27 -5
- package/dist/commands/spaces/label-summaries.d.ts +27 -0
- package/dist/commands/spaces/label-summaries.js +64 -0
- package/dist/commands/spaces/task-rollups.d.ts +5 -0
- package/dist/commands/spaces/task-rollups.js +15 -4
- package/dist/commands/spaces/workflows/lifecycle-diagnostics.js +63 -3
- package/dist/commands/tasks/actions/attach.js +32 -7
- package/dist/commands/tasks/complete.js +13 -0
- package/dist/commands/tasks/create.js +1 -1
- package/dist/commands/tasks/events/append.js +29 -6
- package/dist/commands/tasks/expectations/assess.d.ts +1 -0
- package/dist/commands/tasks/expectations/assess.js +43 -5
- package/dist/commands/tasks/expectations.js +77 -16
- package/dist/commands/tasks/follow-up.js +2 -2
- package/dist/commands/tasks/lifecycle/definitions.js +21 -2
- package/dist/commands/tasks/lifecycle/detach.d.ts +7 -0
- package/dist/commands/tasks/lifecycle/detach.js +43 -3
- package/dist/commands/tasks/lifecycle/migrate.d.ts +2 -0
- package/dist/commands/tasks/lifecycle/migrate.js +42 -3
- package/dist/commands/tasks/lifecycle/reopen.d.ts +2 -0
- package/dist/commands/tasks/lifecycle/reopen.js +40 -3
- package/dist/commands/tasks/lifecycle/transition.js +33 -2
- package/dist/commands/tasks/list.js +16 -9
- package/dist/commands/tasks/move.js +11 -13
- package/dist/commands/tasks/review-queue.d.ts +15 -0
- package/dist/commands/tasks/review-queue.js +180 -31
- package/dist/commands/tasks/show.d.ts +11 -0
- package/dist/commands/tasks/show.js +105 -12
- package/dist/commands/tasks/trust.js +7 -2
- package/dist/commands/tasks/update.js +46 -10
- package/dist/commands/tasks/updates/add.js +1 -1
- package/dist/commands/token/list.d.ts +22 -0
- package/dist/commands/token/list.js +68 -0
- package/dist/commands/token/revoke.d.ts +23 -0
- package/dist/commands/token/revoke.js +53 -0
- package/dist/lib/agent-actions.d.ts +57 -2
- package/dist/lib/agent-actions.js +113 -21
- package/dist/lib/agent-pin-mute.d.ts +10 -5
- package/dist/lib/agent-pin-mute.js +17 -4
- package/dist/lib/agent-visual-refs.d.ts +27 -0
- package/dist/lib/agent-visual-refs.js +127 -2
- package/dist/lib/agentic-stream.d.ts +6 -0
- package/dist/lib/agentic-stream.js +34 -3
- package/dist/lib/assignee-resolver.d.ts +1 -1
- package/dist/lib/assignee-resolver.js +8 -0
- package/dist/lib/bulk-task-targets.d.ts +12 -0
- package/dist/lib/bulk-task-targets.js +34 -1
- package/dist/lib/cli-installers.d.ts +130 -0
- package/dist/lib/cli-installers.js +145 -0
- package/dist/lib/command-miss.js +55 -7
- package/dist/lib/dedicated-lease-command.d.ts +16 -1
- package/dist/lib/dedicated-lease-command.js +26 -3
- package/dist/lib/dedicated-machines.d.ts +135 -1
- package/dist/lib/dedicated-machines.js +307 -3
- package/dist/lib/failed-lookup.d.ts +3 -0
- package/dist/lib/failed-lookup.js +40 -0
- package/dist/lib/first-party-harness-agent.js +9 -2
- package/dist/lib/first-party-harness-doctor.d.ts +15 -0
- package/dist/lib/first-party-harness-doctor.js +126 -27
- package/dist/lib/followups.d.ts +14 -6
- package/dist/lib/followups.js +31 -6
- package/dist/lib/harnesses.d.ts +8 -0
- package/dist/lib/instruction-input.d.ts +19 -1
- package/dist/lib/instruction-input.js +52 -1
- package/dist/lib/label-scope.d.ts +15 -0
- package/dist/lib/label-scope.js +25 -5
- package/dist/lib/local-skills.d.ts +98 -0
- package/dist/lib/local-skills.js +195 -0
- package/dist/lib/machines.d.ts +10 -10
- package/dist/lib/machines.js +23 -1
- package/dist/lib/search-query.d.ts +19 -0
- package/dist/lib/search-query.js +35 -0
- package/dist/lib/space-custom-actions.d.ts +72 -0
- package/dist/lib/space-custom-actions.js +117 -0
- package/dist/lib/space-resolver.d.ts +1 -21
- package/dist/lib/space-resolver.js +19 -10
- package/dist/lib/task-closure.d.ts +3 -2
- package/dist/lib/task-closure.js +18 -20
- package/dist/lib/task-lifecycle-output.js +117 -9
- package/dist/lib/task-ref-resolver.d.ts +1 -17
- package/dist/lib/task-ref-resolver.js +18 -8
- package/dist/lib/tasks.js +9 -3
- package/dist/node_modules/@skrr-ai/data-provider/index.js +5076 -4947
- package/oclif.manifest.json +15505 -14460
- package/package.json +9 -3
|
@@ -4,6 +4,7 @@ const core_1 = require("@oclif/core");
|
|
|
4
4
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
5
|
const data_provider_2 = require("@skrr-ai/data-provider");
|
|
6
6
|
const base_command_1 = require("../../base-command");
|
|
7
|
+
const data_provider_3 = require("@skrr-ai/data-provider");
|
|
7
8
|
const task_closure_1 = require("../../lib/task-closure");
|
|
8
9
|
/**
|
|
9
10
|
* `skrr tasks expectations <task>` — what this task owes, and how far each got.
|
|
@@ -13,18 +14,21 @@ const task_closure_1 = require("../../lib/task-closure");
|
|
|
13
14
|
* could disagree with the gate that refuses the task — and the reader would
|
|
14
15
|
* have no way to tell which was lying.
|
|
15
16
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
17
|
+
/*
|
|
18
|
+
* The labels come from `@skrr-ai/data-provider`, not from here.
|
|
19
|
+
*
|
|
20
|
+
* This file said `dropped` where the user had typed `waived` and `done` where
|
|
21
|
+
* they had typed `met`; the web said `Waived` and `Met`; and an unjudged row
|
|
22
|
+
* read as `not yet` in one column and `needs assessment` in the trailer. Three
|
|
23
|
+
* spellings of one vocabulary is how a user stops trusting that the word they
|
|
24
|
+
* wrote is the word that was stored.
|
|
25
|
+
*
|
|
26
|
+
* A state derived from a DECISION now reads back as that decision's own word.
|
|
27
|
+
* `owed` and `unassessed` stay distinct — "nobody produced it" and "nobody
|
|
28
|
+
* judged it" are different next actions — and the legend below says so, which
|
|
29
|
+
* the near-synonymous English never could on its own.
|
|
30
|
+
*/
|
|
31
|
+
const STATE_LABEL = data_provider_3.EXPECTATION_STATE_LABEL;
|
|
28
32
|
/**
|
|
29
33
|
* The evidence gap, on the rows where a reader can act on it.
|
|
30
34
|
*
|
|
@@ -75,7 +79,9 @@ function evidenceGap(expectation) {
|
|
|
75
79
|
function assessorSuffix(expectation) {
|
|
76
80
|
if (!expectation.assessedByKind)
|
|
77
81
|
return '';
|
|
78
|
-
|
|
82
|
+
// `unmet` joins them: a rejection is a judgement, and whose it was matters at
|
|
83
|
+
// least as much as whose `met` it was.
|
|
84
|
+
if (!['met', 'waived', 'unmet'].includes(expectation.state))
|
|
79
85
|
return '';
|
|
80
86
|
return ` (${(0, task_closure_1.describeAssessor)(expectation.assessedByKind)})`;
|
|
81
87
|
}
|
|
@@ -144,9 +150,13 @@ class TasksExpectations extends base_command_1.BaseCommand {
|
|
|
144
150
|
// "2 of 2 met" for a Task where one expectation was dropped, which is the
|
|
145
151
|
// one thing a reader checking this line needs to know.
|
|
146
152
|
const waived = gating.filter((e) => e.state === 'waived').length;
|
|
147
|
-
const met = gating.filter((e) => e.met).length
|
|
153
|
+
const met = gating.filter((e) => e.passed ?? e.state === 'met').length;
|
|
154
|
+
const rejected = gating.filter((e) => e.state === 'unmet').length;
|
|
148
155
|
this.log('');
|
|
149
|
-
this.log(`${met} of ${gating.length} met
|
|
156
|
+
this.log(`${met} of ${gating.length} met` +
|
|
157
|
+
(waived > 0 ? ` · ${waived} waived` : '') +
|
|
158
|
+
(rejected > 0 ? ` · ${rejected} unmet` : '') +
|
|
159
|
+
` · overall: ${acceptance.state}`);
|
|
150
160
|
// Space defaults are copied into the Task at creation. `source=space`
|
|
151
161
|
// remains useful provenance, but these are Task-owned Expectations now and
|
|
152
162
|
// are assessed exactly like explicitly declared ones.
|
|
@@ -173,6 +183,24 @@ class TasksExpectations extends base_command_1.BaseCommand {
|
|
|
173
183
|
if (settleable > 0) {
|
|
174
184
|
this.log(`${settleable} awaiting assessment — use \`${this.config.bin} tasks expectations assess\`.`);
|
|
175
185
|
}
|
|
186
|
+
/*
|
|
187
|
+
* A rejection is not an absence, and it used to read as one.
|
|
188
|
+
*
|
|
189
|
+
* `unmet` collapsed into `owed`/`unassessed`, so a reviewer's written "no"
|
|
190
|
+
* displayed as "needs assessment" — inviting someone to do the judging that
|
|
191
|
+
* had already been done, while the bulk settle skipped the row because it
|
|
192
|
+
* could see the assessment the display had hidden.
|
|
193
|
+
*/
|
|
194
|
+
const rejectedRows = acceptance.expectations.filter((e) => e.state === 'unmet');
|
|
195
|
+
if (rejectedRows.length > 0) {
|
|
196
|
+
this.log(`${rejectedRows.length} judged unmet — fix the work and re-assess, or waive ` +
|
|
197
|
+
`${rejectedRows.length === 1 ? 'it' : 'them'}:`);
|
|
198
|
+
for (const row of rejectedRows) {
|
|
199
|
+
const who = row.assessedByKind ? ` by ${(0, task_closure_1.describeAssessor)(row.assessedByKind)}` : '';
|
|
200
|
+
const when = row.assessedAt ? ` on ${String(row.assessedAt).slice(0, 10)}` : '';
|
|
201
|
+
this.log(` ${row.id}${who}${when}${row.reason ? `: ${row.reason}` : ''}`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
176
204
|
// Named separately from `unjudged`, and with a different command, because
|
|
177
205
|
// the two look alike on the board and are not: one needs a verdict on prose,
|
|
178
206
|
// the other needs somebody to look at a thing that already exists.
|
|
@@ -217,7 +245,40 @@ class TasksExpectations extends base_command_1.BaseCommand {
|
|
|
217
245
|
const settled = gating.filter((e) => e.met).length;
|
|
218
246
|
if (gating.length > settled) {
|
|
219
247
|
this.log('');
|
|
220
|
-
|
|
248
|
+
/*
|
|
249
|
+
* Say what is OWED, not what is forbidden.
|
|
250
|
+
*
|
|
251
|
+
* This read: "The current Result cannot be accepted while these
|
|
252
|
+
* Expectations remain unmet." That gate stopped existing in `56a6ded703`
|
|
253
|
+
* — unmet Expectations are advisory, and `assertTaskMayClose` throws on
|
|
254
|
+
* exactly one code, which is not this one. The Task closes; the unmet
|
|
255
|
+
* items are stamped onto `resolution.closure`.
|
|
256
|
+
*
|
|
257
|
+
* So the sentence asserted an outcome this command never evaluated, and
|
|
258
|
+
* asserted it wrongly: an operator who believed it would go hunting for a
|
|
259
|
+
* way to force a close that needs no forcing. It is the same failure as
|
|
260
|
+
* the hard-coded "it is ready for review" that this batch removed,
|
|
261
|
+
* pointing the other way.
|
|
262
|
+
*/
|
|
263
|
+
this.log(
|
|
264
|
+
// Tense-neutral on purpose: this command reads acceptance only, and
|
|
265
|
+
// fetching the Task as well — one extra round trip on every call — just
|
|
266
|
+
// to choose between "closing is allowed" and "was closed over these" is
|
|
267
|
+
// not worth it. This sentence is true before the close and after it.
|
|
268
|
+
`${gating.length - settled} Expectation(s) still owed. They do not block closing; ` +
|
|
269
|
+
'whatever is outstanding when a Task closes is recorded on `resolution.closure`.');
|
|
270
|
+
}
|
|
271
|
+
/*
|
|
272
|
+
* A legend, because two of these states are near-synonyms in English and
|
|
273
|
+
* genuinely different in what they ask of the reader.
|
|
274
|
+
*/
|
|
275
|
+
const shown = new Set(acceptance.expectations.map((e) => e.state));
|
|
276
|
+
const legend = ['owed', 'unassessed', 'unmet']
|
|
277
|
+
.filter((state) => shown.has(state))
|
|
278
|
+
.map((state) => `${data_provider_3.EXPECTATION_STATE_LABEL[state]} = ${data_provider_3.EXPECTATION_STATE_HINT[state]}`);
|
|
279
|
+
if (legend.length > 1) {
|
|
280
|
+
this.log('');
|
|
281
|
+
this.log(legend.join(' · '));
|
|
221
282
|
}
|
|
222
283
|
}
|
|
223
284
|
}
|
|
@@ -73,8 +73,8 @@ class TasksFollowUp extends base_command_1.BaseCommand {
|
|
|
73
73
|
description: 'Optional SLA fallback delay in seconds for event or poll_until follow-ups',
|
|
74
74
|
}),
|
|
75
75
|
visibility: core_1.Flags.string({
|
|
76
|
-
description: '
|
|
77
|
-
options: ['silent'
|
|
76
|
+
description: 'Always silent — the wake speaks only when the check finds something. Kept for compatibility; notify is not available',
|
|
77
|
+
options: ['silent'],
|
|
78
78
|
}),
|
|
79
79
|
priority: core_1.Flags.string({
|
|
80
80
|
description: 'Follow-up task priority',
|
|
@@ -5,7 +5,13 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
5
5
|
const base_command_1 = require("../../../base-command");
|
|
6
6
|
class TasksLifecycleDefinitions extends base_command_1.BaseCommand {
|
|
7
7
|
static description = 'List the lifecycle definitions and built-in packs a Task can attach';
|
|
8
|
-
static args = {
|
|
8
|
+
static args = {
|
|
9
|
+
id: core_1.Args.string({
|
|
10
|
+
required: true,
|
|
11
|
+
ignoreStdin: true,
|
|
12
|
+
description: 'Task ID or identifier — definitions are listed for its Space',
|
|
13
|
+
}),
|
|
14
|
+
};
|
|
9
15
|
static flags = { json: core_1.Flags.boolean({ description: 'Output JSON' }) };
|
|
10
16
|
async run() {
|
|
11
17
|
this.requireAuth();
|
|
@@ -24,12 +30,25 @@ class TasksLifecycleDefinitions extends base_command_1.BaseCommand {
|
|
|
24
30
|
this.log('Built-in packs:');
|
|
25
31
|
for (const pack of response.packs) {
|
|
26
32
|
this.log(` ${pack.id} v${pack.packVersion} — ${pack.title}${pack.description ? ` — ${pack.description}` : ''}`);
|
|
33
|
+
if (pack.stageKeys?.length) {
|
|
34
|
+
this.log(` stages: ${pack.stageKeys.join(' → ')}`);
|
|
35
|
+
}
|
|
27
36
|
}
|
|
28
37
|
}
|
|
29
38
|
if (response.definitions.length) {
|
|
30
39
|
this.log('Space definitions:');
|
|
31
40
|
for (const definition of response.definitions) {
|
|
32
|
-
this.log(` ${definition.id} v${definition.version} — ${definition.title}${definition.packId ? ` (pack ${definition.packId})` : ''}`);
|
|
41
|
+
this.log(` ${definition.id} v${definition.version} — ${definition.title}${definition.packId ? ` (pack ${definition.packId} v${definition.packVersion ?? '?'})` : ''}`);
|
|
42
|
+
// `attach --version` and `migrate --version` take a VERSION id, and
|
|
43
|
+
// this was the only place they could come from — and it printed the
|
|
44
|
+
// definition id and a version NUMBER, neither of which those flags
|
|
45
|
+
// accept. `migrate` was unusable without reading the API.
|
|
46
|
+
if (definition.publishedVersionId) {
|
|
47
|
+
this.log(` published version: ${definition.publishedVersionId} (pass to --version)`);
|
|
48
|
+
}
|
|
49
|
+
if (definition.stageKeys?.length) {
|
|
50
|
+
this.log(` stages: ${definition.stageKeys.join(' → ')}`);
|
|
51
|
+
}
|
|
33
52
|
}
|
|
34
53
|
}
|
|
35
54
|
if (!response.packs.length && !response.definitions.length) {
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { BaseCommand } from '../../../base-command';
|
|
2
2
|
export default class TasksLifecycleDetach extends BaseCommand {
|
|
3
3
|
static description: string;
|
|
4
|
+
/**
|
|
5
|
+
* oclif prints `description` in help and nothing else, so a one-liner that
|
|
6
|
+
* repeats the summary tells a reader nothing about an operation that is not
|
|
7
|
+
* obviously reversible. Say what it does to each thing it touches.
|
|
8
|
+
*/
|
|
9
|
+
static examples: string[];
|
|
4
10
|
static args: {
|
|
5
11
|
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
12
|
};
|
|
7
13
|
static flags: {
|
|
8
14
|
reason: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
15
|
+
'dry-run': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
9
16
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
17
|
};
|
|
11
18
|
run(): Promise<void>;
|
|
@@ -5,15 +5,49 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
5
5
|
const base_command_1 = require("../../../base-command");
|
|
6
6
|
class TasksLifecycleDetach extends base_command_1.BaseCommand {
|
|
7
7
|
static description = 'Detach the lifecycle from a Task — fences the generation, leaves the run as history';
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* oclif prints `description` in help and nothing else, so a one-liner that
|
|
10
|
+
* repeats the summary tells a reader nothing about an operation that is not
|
|
11
|
+
* obviously reversible. Say what it does to each thing it touches.
|
|
12
|
+
*/
|
|
13
|
+
static examples = [
|
|
14
|
+
'<%= config.bin %> tasks lifecycle detach OSK-1234 --dry-run',
|
|
15
|
+
'<%= config.bin %> tasks lifecycle detach OSK-1234 --reason "Wrong protocol for this work"',
|
|
16
|
+
];
|
|
17
|
+
static args = {
|
|
18
|
+
id: core_1.Args.string({ required: true, ignoreStdin: true, description: 'Task ID or identifier' }),
|
|
19
|
+
};
|
|
9
20
|
static flags = {
|
|
10
|
-
reason: core_1.Flags.string({ description: 'Why the lifecycle is detaching' }),
|
|
21
|
+
reason: core_1.Flags.string({ description: 'Why the lifecycle is detaching; recorded in history' }),
|
|
22
|
+
'dry-run': core_1.Flags.boolean({
|
|
23
|
+
description: 'Describe what detaching would do and exit without writing',
|
|
24
|
+
}),
|
|
11
25
|
json: core_1.Flags.boolean({ description: 'Output JSON' }),
|
|
12
26
|
};
|
|
13
27
|
async run() {
|
|
14
28
|
this.requireAuth();
|
|
15
29
|
const { args, flags } = await this.parse(TasksLifecycleDetach);
|
|
16
30
|
const taskId = await this.resolveTaskReference(args.id);
|
|
31
|
+
if (flags['dry-run']) {
|
|
32
|
+
let current;
|
|
33
|
+
try {
|
|
34
|
+
current = await data_provider_1.dataService.getTaskLifecycle(taskId);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
this.handleApiError(error);
|
|
38
|
+
}
|
|
39
|
+
if (flags.json)
|
|
40
|
+
return this.log(JSON.stringify({ dryRun: true, ...current }, null, 2));
|
|
41
|
+
const lifecycle = current.lifecycle;
|
|
42
|
+
if (!lifecycle)
|
|
43
|
+
return this.log('No lifecycle is attached to this Task — nothing to detach.');
|
|
44
|
+
this.log(`Would detach ${lifecycle.packId ? `pack ${lifecycle.packId}` : `definition ${lifecycle.definitionId}`}` +
|
|
45
|
+
` at generation ${lifecycle.generation}, stage ${lifecycle.currentStageKey ?? '—'}.`);
|
|
46
|
+
this.log(' The run is cancelled and kept as history; nothing already recorded is removed.');
|
|
47
|
+
this.log(' The generation is bumped, so no in-flight writer from the old run can land.');
|
|
48
|
+
this.log(' Re-attaching afterwards starts a NEW generation — it does not resume this one.');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
17
51
|
let response;
|
|
18
52
|
try {
|
|
19
53
|
response = await data_provider_1.dataService.detachTaskLifecycle({
|
|
@@ -26,7 +60,13 @@ class TasksLifecycleDetach extends base_command_1.BaseCommand {
|
|
|
26
60
|
}
|
|
27
61
|
if (flags.json)
|
|
28
62
|
return this.log(JSON.stringify(response, null, 2));
|
|
29
|
-
|
|
63
|
+
const lifecycle = response.lifecycle;
|
|
64
|
+
// Name what changed. "Detached lifecycle from the Task." left the reader to
|
|
65
|
+
// diff the state afterwards to learn what had happened.
|
|
66
|
+
this.log(`Detached${lifecycle?.packId ? ` pack ${lifecycle.packId}` : ''} — the run is cancelled and` +
|
|
67
|
+
` kept as history, and the binding is now generation ${lifecycle?.generation ?? '?'}` +
|
|
68
|
+
` (${lifecycle?.status ?? 'detached'}).`);
|
|
69
|
+
this.log('Re-attach with: skrr tasks lifecycle attach <task-id> --pack <pack>');
|
|
30
70
|
}
|
|
31
71
|
}
|
|
32
72
|
exports.default = TasksLifecycleDetach;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { BaseCommand } from '../../../base-command';
|
|
2
2
|
export default class TasksLifecycleMigrate extends BaseCommand {
|
|
3
3
|
static description: string;
|
|
4
|
+
static examples: string[];
|
|
4
5
|
static args: {
|
|
5
6
|
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
7
|
};
|
|
7
8
|
static flags: {
|
|
8
9
|
version: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
'dry-run': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
9
11
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
12
|
};
|
|
11
13
|
run(): Promise<void>;
|
|
@@ -5,15 +5,51 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
5
5
|
const base_command_1 = require("../../../base-command");
|
|
6
6
|
class TasksLifecycleMigrate extends base_command_1.BaseCommand {
|
|
7
7
|
static description = 'Migrate a bound lifecycle to a newer published version, fencing the old generation';
|
|
8
|
-
static
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> tasks lifecycle definitions OSK-1234 # where a --version comes from',
|
|
10
|
+
'<%= config.bin %> tasks lifecycle migrate OSK-1234 --version wfv_… --dry-run',
|
|
11
|
+
];
|
|
12
|
+
static args = {
|
|
13
|
+
id: core_1.Args.string({ required: true, ignoreStdin: true, description: 'Task ID or identifier' }),
|
|
14
|
+
};
|
|
9
15
|
static flags = {
|
|
10
|
-
version: core_1.Flags.string({
|
|
16
|
+
version: core_1.Flags.string({
|
|
17
|
+
required: true,
|
|
18
|
+
description: 'Target published version id — `tasks lifecycle definitions <task-id>` prints it',
|
|
19
|
+
}),
|
|
20
|
+
'dry-run': core_1.Flags.boolean({
|
|
21
|
+
description: 'Describe what migrating would do and exit without writing',
|
|
22
|
+
}),
|
|
11
23
|
json: core_1.Flags.boolean({ description: 'Output JSON' }),
|
|
12
24
|
};
|
|
13
25
|
async run() {
|
|
14
26
|
this.requireAuth();
|
|
15
27
|
const { args, flags } = await this.parse(TasksLifecycleMigrate);
|
|
16
28
|
const taskId = await this.resolveTaskReference(args.id);
|
|
29
|
+
// Moving a Task between published protocols is not obviously reversible,
|
|
30
|
+
// and the old output said only that a run had started. A flag rather than a
|
|
31
|
+
// prompt, so the command stays usable from a script.
|
|
32
|
+
if (flags['dry-run']) {
|
|
33
|
+
let current;
|
|
34
|
+
try {
|
|
35
|
+
current = await data_provider_1.dataService.getTaskLifecycle(taskId);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
this.handleApiError(error);
|
|
39
|
+
}
|
|
40
|
+
if (flags.json)
|
|
41
|
+
return this.log(JSON.stringify({ dryRun: true, ...current }, null, 2));
|
|
42
|
+
const lifecycle = current.lifecycle;
|
|
43
|
+
if (!lifecycle)
|
|
44
|
+
return this.log('No lifecycle is attached to this Task — nothing to migrate.');
|
|
45
|
+
this.log(`Would migrate from version ${lifecycle.versionId} to ${flags.version}, as generation ` +
|
|
46
|
+
`${Number(lifecycle.generation) + 1}.`);
|
|
47
|
+
this.log(` It re-enters at the CURRENT stage (${lifecycle.currentStageKey ?? '—'}) when that stage` +
|
|
48
|
+
" still exists on the target version; otherwise the protocol's entry stage decides.");
|
|
49
|
+
this.log(' The old generation is fenced — its run can no longer write.');
|
|
50
|
+
this.log(' Earlier generations stay readable in `tasks lifecycle history`.');
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
17
53
|
let result;
|
|
18
54
|
try {
|
|
19
55
|
result = await data_provider_1.dataService.migrateTaskLifecycle({ taskId, versionId: flags.version });
|
|
@@ -23,7 +59,10 @@ class TasksLifecycleMigrate extends base_command_1.BaseCommand {
|
|
|
23
59
|
}
|
|
24
60
|
if (flags.json)
|
|
25
61
|
return this.log(JSON.stringify(result, null, 2));
|
|
26
|
-
|
|
62
|
+
const lifecycle = result.lifecycle;
|
|
63
|
+
this.log(`Migrated to version ${lifecycle?.versionId ?? flags.version} — now generation ` +
|
|
64
|
+
`${lifecycle?.generation ?? '?'} at stage ${lifecycle?.currentStageKey ?? '—'}` +
|
|
65
|
+
` (run ${result.run.id}, ${result.run.status}).`);
|
|
27
66
|
}
|
|
28
67
|
}
|
|
29
68
|
exports.default = TasksLifecycleMigrate;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { BaseCommand } from '../../../base-command';
|
|
2
2
|
export default class TasksLifecycleReopen extends BaseCommand {
|
|
3
3
|
static description: string;
|
|
4
|
+
static examples: string[];
|
|
4
5
|
static args: {
|
|
5
6
|
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
7
|
};
|
|
7
8
|
static flags: {
|
|
8
9
|
stage: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
10
|
reason: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
'dry-run': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
12
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
13
|
};
|
|
12
14
|
run(): Promise<void>;
|
|
@@ -5,16 +5,50 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
5
5
|
const base_command_1 = require("../../../base-command");
|
|
6
6
|
class TasksLifecycleReopen extends base_command_1.BaseCommand {
|
|
7
7
|
static description = 'Fence the current lifecycle generation and reopen at an earlier stage';
|
|
8
|
-
static
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> tasks lifecycle reopen OSK-1234 --dry-run',
|
|
10
|
+
'<%= config.bin %> tasks lifecycle reopen OSK-1234 --stage fix --reason "The fix did not take"',
|
|
11
|
+
];
|
|
12
|
+
static args = {
|
|
13
|
+
id: core_1.Args.string({ required: true, ignoreStdin: true, description: 'Task ID or identifier' }),
|
|
14
|
+
};
|
|
9
15
|
static flags = {
|
|
10
16
|
stage: core_1.Flags.string({ description: 'Stage key to re-enter at; defaults to the entry stage' }),
|
|
11
|
-
reason: core_1.Flags.string({ description: 'Why the lifecycle is reopening' }),
|
|
17
|
+
reason: core_1.Flags.string({ description: 'Why the lifecycle is reopening; recorded in history' }),
|
|
18
|
+
'dry-run': core_1.Flags.boolean({
|
|
19
|
+
description: 'Describe what reopening would do and exit without writing',
|
|
20
|
+
}),
|
|
12
21
|
json: core_1.Flags.boolean({ description: 'Output JSON' }),
|
|
13
22
|
};
|
|
14
23
|
async run() {
|
|
15
24
|
this.requireAuth();
|
|
16
25
|
const { args, flags } = await this.parse(TasksLifecycleReopen);
|
|
17
26
|
const taskId = await this.resolveTaskReference(args.id);
|
|
27
|
+
// Reopen advances a generation and is not obviously reversible. A preview
|
|
28
|
+
// that names the target stage is cheaper than learning what it did by
|
|
29
|
+
// diffing state afterwards, and a flag keeps the command scriptable where
|
|
30
|
+
// an interactive prompt would not.
|
|
31
|
+
if (flags['dry-run']) {
|
|
32
|
+
let current;
|
|
33
|
+
try {
|
|
34
|
+
current = await data_provider_1.dataService.getTaskLifecycle(taskId);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
this.handleApiError(error);
|
|
38
|
+
}
|
|
39
|
+
if (flags.json)
|
|
40
|
+
return this.log(JSON.stringify({ dryRun: true, ...current }, null, 2));
|
|
41
|
+
const lifecycle = current.lifecycle;
|
|
42
|
+
if (!lifecycle)
|
|
43
|
+
return this.log('No lifecycle is attached to this Task — nothing to reopen.');
|
|
44
|
+
const entry = flags.stage || current.stages?.[0]?.key;
|
|
45
|
+
this.log(`Would reopen at stage ${entry ?? '(entry stage)'} as generation ${Number(lifecycle.generation) + 1}` +
|
|
46
|
+
` (currently generation ${lifecycle.generation}, stage ${lifecycle.currentStageKey ?? '—'}).`);
|
|
47
|
+
this.log(' The current run is cancelled; its transitions stay readable in history.');
|
|
48
|
+
this.log(" A terminal Task is brought back to the entry stage's declared status.");
|
|
49
|
+
this.log(' Stages the earlier generation finished keep reading as done in that generation.');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
18
52
|
let result;
|
|
19
53
|
try {
|
|
20
54
|
result = await data_provider_1.dataService.reopenTaskLifecycle({
|
|
@@ -28,7 +62,10 @@ class TasksLifecycleReopen extends base_command_1.BaseCommand {
|
|
|
28
62
|
}
|
|
29
63
|
if (flags.json)
|
|
30
64
|
return this.log(JSON.stringify(result, null, 2));
|
|
31
|
-
|
|
65
|
+
// Name where it landed, not just that it happened.
|
|
66
|
+
const lifecycle = result.lifecycle;
|
|
67
|
+
this.log(`Reopened at stage ${lifecycle?.currentStageKey ?? '—'} as generation ${lifecycle?.generation ?? '?'}` +
|
|
68
|
+
` — run ${result.run.id} (${result.run.status}). The previous generation stays in history.`);
|
|
32
69
|
}
|
|
33
70
|
}
|
|
34
71
|
exports.default = TasksLifecycleReopen;
|
|
@@ -42,6 +42,23 @@ class TasksLifecycleTransition extends base_command_1.BaseCommand {
|
|
|
42
42
|
this.error('--payload must be a JSON object.', { exit: 2 });
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
+
/*
|
|
46
|
+
* The fence only protects the interval it is given.
|
|
47
|
+
*
|
|
48
|
+
* `--expected-revision` is the caller's claim about the state they DECIDED
|
|
49
|
+
* against. When it is omitted this command re-reads the lifecycle and sends
|
|
50
|
+
* back what it just read — and a compare-and-set whose expected value was
|
|
51
|
+
* fetched microseconds before the write can only catch that microsecond,
|
|
52
|
+
* never the interval that matters, which is between the human's read and
|
|
53
|
+
* their write. So the default is a convenience, not protection, and it was
|
|
54
|
+
* silent about that: a `confirm` decided at revision 0 applied against
|
|
55
|
+
* revision 1 and closed a Task, with nothing in the output saying the world
|
|
56
|
+
* had moved in between.
|
|
57
|
+
*
|
|
58
|
+
* Kept as the default because requiring a number on every call would be
|
|
59
|
+
* paid by everyone to protect a minority of flows — but it now says what it
|
|
60
|
+
* fenced on and how to fence properly.
|
|
61
|
+
*/
|
|
45
62
|
let expectedRevision = flags['expected-revision'];
|
|
46
63
|
if (expectedRevision === undefined) {
|
|
47
64
|
let current;
|
|
@@ -55,6 +72,10 @@ class TasksLifecycleTransition extends base_command_1.BaseCommand {
|
|
|
55
72
|
this.error('No lifecycle is attached to this Task.', { exit: 2 });
|
|
56
73
|
}
|
|
57
74
|
expectedRevision = current.lifecycle.revision;
|
|
75
|
+
if (!flags.json) {
|
|
76
|
+
this.log(`Fencing on revision ${expectedRevision}, read just now — not the revision you saw. ` +
|
|
77
|
+
'Pass --expected-revision <n> to fence on the state you decided against.');
|
|
78
|
+
}
|
|
58
79
|
}
|
|
59
80
|
const idempotencyKey = flags['idempotency-key'] ?? `cli-lifecycle:${taskId}:${args.transition}:r${expectedRevision}`;
|
|
60
81
|
let response;
|
|
@@ -71,8 +92,18 @@ class TasksLifecycleTransition extends base_command_1.BaseCommand {
|
|
|
71
92
|
this.handleApiError(error);
|
|
72
93
|
}
|
|
73
94
|
if (flags.json)
|
|
74
|
-
|
|
75
|
-
|
|
95
|
+
this.log(JSON.stringify(response, null, 2));
|
|
96
|
+
else
|
|
97
|
+
(0, task_lifecycle_output_1.renderLifecycleTransitionResult)(response, (line) => this.log(line));
|
|
98
|
+
// Exit non-zero when the write did not land. `applied` is the only verdict
|
|
99
|
+
// that means the stage moved; `rejected`, `superseded` and `gated` all mean
|
|
100
|
+
// it did not. Exiting 0 on all four made
|
|
101
|
+
// `transition A && transition B` run B after A had been fenced off — which
|
|
102
|
+
// is precisely the lost update `expectedRevision` exists to prevent, waved
|
|
103
|
+
// through by the shell.
|
|
104
|
+
if (response.status !== 'applied') {
|
|
105
|
+
this.exit(1);
|
|
106
|
+
}
|
|
76
107
|
}
|
|
77
108
|
}
|
|
78
109
|
exports.default = TasksLifecycleTransition;
|
|
@@ -146,13 +146,13 @@ function buildListParams(flags, assigneeUserId) {
|
|
|
146
146
|
...(flag('actionability-reason')
|
|
147
147
|
? { actionabilityReason: flag('actionability-reason') }
|
|
148
148
|
: {}),
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
149
|
+
// This table always renders a NEXT column, so it always has to ask for the
|
|
150
|
+
// data behind it. Requesting it only alongside an actionability FILTER left
|
|
151
|
+
// the default board printing a header with nothing under it — and a plain
|
|
152
|
+
// `tasks list` is exactly where a person looks to find out what anything is
|
|
153
|
+
// waiting for. The server computes it in one batched read, so the cost is
|
|
154
|
+
// a column that works rather than a column that is there.
|
|
155
|
+
includeActionability: true,
|
|
156
156
|
...(flag('priority') ? { priority: flag('priority') } : {}),
|
|
157
157
|
...(flag('estimate') !== undefined ? { estimate: flag('estimate') } : {}),
|
|
158
158
|
...(flag('min-estimate') !== undefined
|
|
@@ -427,8 +427,13 @@ class TasksList extends base_command_1.BaseCommand {
|
|
|
427
427
|
priority: String(t.priority ?? '-'),
|
|
428
428
|
estimate: t.estimate === null || t.estimate === undefined ? '-' : String(t.estimate),
|
|
429
429
|
assignees,
|
|
430
|
+
// `reason` is the sentence the server wrote for a person; `reasonCode`
|
|
431
|
+
// is the enum it wrote for a machine. Printing the code rendered every
|
|
432
|
+
// stage of every lifecycle as `human:lifecycle_stage` — six different
|
|
433
|
+
// waits, one string — while the sentence naming the stage sat unread in
|
|
434
|
+
// the same payload.
|
|
430
435
|
next: actionability
|
|
431
|
-
? `${String(actionability.nextActor ?? '-')}
|
|
436
|
+
? `${String(actionability.nextActor ?? '-')}: ${String(actionability.reason || actionability.reasonCode || actionability.state || '-')}`
|
|
432
437
|
: String(t.executionMode ?? '-'),
|
|
433
438
|
match: String(t._matchField ?? '-'),
|
|
434
439
|
};
|
|
@@ -440,7 +445,9 @@ class TasksList extends base_command_1.BaseCommand {
|
|
|
440
445
|
{ key: 'priority', header: 'PRIORITY' },
|
|
441
446
|
{ key: 'estimate', header: 'ESTIMATE' },
|
|
442
447
|
{ key: 'assignees', header: 'ASSIGNEES' },
|
|
443
|
-
|
|
448
|
+
// Bounded: the reason is a sentence, and an unbounded column wraps the
|
|
449
|
+
// table into unreadability on a narrow terminal.
|
|
450
|
+
{ key: 'next', header: 'NEXT', maxWidth: 46 },
|
|
444
451
|
// Only meaningful on a search — the server computes it from the same
|
|
445
452
|
// relevance rank that orders the rows, and a plain listing has none.
|
|
446
453
|
...(flags.q ? [{ key: 'match', header: 'MATCH' }] : []),
|
|
@@ -5,6 +5,7 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
5
5
|
const api_fetch_1 = require("../../lib/api-fetch");
|
|
6
6
|
const session_task_endpoints_1 = require("../../lib/session-task-endpoints");
|
|
7
7
|
const base_command_1 = require("../../base-command");
|
|
8
|
+
const task_closure_1 = require("../../lib/task-closure");
|
|
8
9
|
const web_url_1 = require("../../lib/web-url");
|
|
9
10
|
const task_resolver_1 = require("../../lib/task-resolver");
|
|
10
11
|
const projects_1 = require("../../lib/projects");
|
|
@@ -155,19 +156,16 @@ class TasksMove extends base_command_1.BaseCommand {
|
|
|
155
156
|
// the loosely-typed receipt, so the narrowing cast stays; what matters is
|
|
156
157
|
// that the shape it names is the one data-provider owns.
|
|
157
158
|
const resolutionClosure = t.resolution?.closure;
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
if (parts.length) {
|
|
169
|
-
this.log(` Closed over ${parts.join('; ')} (resolution.closure).`);
|
|
170
|
-
}
|
|
159
|
+
/*
|
|
160
|
+
* Through the shared renderer. This hand-rolled the rendering and pushed
|
|
161
|
+
* blocker CODES at a human — `Closed over TASK_RESULT_REQUIRED`, which is a
|
|
162
|
+
* wire identifier and, read plainly, the opposite of what just happened. The
|
|
163
|
+
* worst instance was the one this batch cares most about: a Task closed over
|
|
164
|
+
* a reviewer's objection printed `TASK_RESULT_CHANGES_REQUESTED`, rendering
|
|
165
|
+
* "somebody looked and objected" as an identifier.
|
|
166
|
+
*/
|
|
167
|
+
for (const sentence of (0, task_closure_1.closureSnapshotLines)(resolutionClosure)) {
|
|
168
|
+
this.log(` ${sentence}`);
|
|
171
169
|
}
|
|
172
170
|
}
|
|
173
171
|
/**
|
|
@@ -23,7 +23,22 @@ export default class TasksReviewQueue extends BaseCommand {
|
|
|
23
23
|
space: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
24
24
|
actionable: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
25
25
|
limit: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
26
|
+
'include-closed': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
26
27
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
27
28
|
};
|
|
28
29
|
run(): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* An empty queue must not be how you learn a Space id is wrong.
|
|
32
|
+
*
|
|
33
|
+
* A UUID-shaped ref is accepted without a lookup (`base-command` short-circuits
|
|
34
|
+
* on the SHAPE, which is a cheap and correct optimisation nearly everywhere),
|
|
35
|
+
* and the list route deliberately never 404s — an unknown Space falls back to
|
|
36
|
+
* the ACL enumeration and returns an honest empty page. Those two reasonable
|
|
37
|
+
* decisions compose into "Nothing is awaiting a judgement", exit 0, for a
|
|
38
|
+
* Space that does not exist. A typo read as done.
|
|
39
|
+
*
|
|
40
|
+
* So the existence check is paid for ONLY on the path that is about to make
|
|
41
|
+
* the completeness claim — never on the path that found work.
|
|
42
|
+
*/
|
|
43
|
+
private assertSpaceExists;
|
|
29
44
|
}
|