@skrr-ai/cli 0.1.13 → 0.1.15
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 +12 -36
- package/dist/base-command.js +96 -11
- package/dist/commands/agents/create.d.ts +1 -0
- package/dist/commands/agents/create.js +6 -1
- package/dist/commands/agents/instructions/add.d.ts +21 -0
- package/dist/commands/agents/instructions/add.js +115 -0
- package/dist/commands/agents/instructions/disable.d.ts +13 -0
- package/dist/commands/agents/instructions/disable.js +50 -0
- package/dist/commands/agents/instructions/edit.d.ts +16 -0
- package/dist/commands/agents/instructions/edit.js +79 -0
- package/dist/commands/agents/instructions/enable.d.ts +13 -0
- package/dist/commands/agents/instructions/enable.js +50 -0
- package/dist/commands/agents/instructions/move.d.ts +15 -0
- package/dist/commands/agents/instructions/move.js +61 -0
- package/dist/commands/agents/instructions/preview.d.ts +13 -0
- package/dist/commands/agents/instructions/preview.js +59 -0
- package/dist/commands/agents/instructions/remove.d.ts +13 -0
- package/dist/commands/agents/instructions/remove.js +49 -0
- package/dist/commands/agents/instructions/set.d.ts +17 -0
- package/dist/commands/agents/instructions/set.js +79 -0
- package/dist/commands/agents/instructions/show.d.ts +15 -0
- package/dist/commands/agents/instructions/show.js +76 -0
- package/dist/commands/agents/instructions/upgrade.d.ts +16 -0
- package/dist/commands/agents/instructions/upgrade.js +77 -0
- package/dist/commands/agents/list.d.ts +10 -0
- package/dist/commands/agents/list.js +16 -1
- package/dist/commands/agents/show.js +5 -0
- package/dist/commands/agents/triggers/policy.js +8 -2
- package/dist/commands/agents/update.d.ts +1 -0
- package/dist/commands/agents/update.js +8 -2
- package/dist/commands/browser.js +5 -5
- package/dist/commands/commitments/create.d.ts +2 -0
- package/dist/commands/commitments/create.js +30 -13
- package/dist/commands/commitments/update.d.ts +2 -0
- package/dist/commands/commitments/update.js +24 -4
- package/dist/commands/daemon/byok.js +5 -5
- package/dist/commands/daemon/index.js +5 -3
- package/dist/commands/daemon/install.js +8 -5
- package/dist/commands/daemon/login.js +5 -5
- package/dist/commands/daemon/logs.js +5 -5
- package/dist/commands/daemon/recover-offline-queue.d.ts +9 -0
- package/dist/commands/daemon/recover-offline-queue.js +24 -0
- package/dist/commands/daemon/restart.js +5 -5
- package/dist/commands/daemon/start.js +34 -6
- package/dist/commands/daemon/status.js +5 -5
- package/dist/commands/daemon/stop.js +5 -5
- package/dist/commands/daemon/uninstall.js +5 -5
- package/dist/commands/daemon/unlock.js +5 -5
- package/dist/commands/daemon/usage.js +6 -6
- package/dist/commands/instruction-blocks/create.d.ts +19 -0
- package/dist/commands/instruction-blocks/create.js +94 -0
- package/dist/commands/instruction-blocks/delete.d.ts +13 -0
- package/dist/commands/instruction-blocks/delete.js +35 -0
- package/dist/commands/instruction-blocks/list.d.ts +13 -0
- package/dist/commands/instruction-blocks/list.js +71 -0
- package/dist/commands/instruction-blocks/show.d.ts +12 -0
- package/dist/commands/instruction-blocks/show.js +35 -0
- package/dist/commands/instruction-blocks/update.d.ts +23 -0
- package/dist/commands/instruction-blocks/update.js +94 -0
- package/dist/commands/login.js +7 -2
- package/dist/commands/spaces/auto-executor/preview.d.ts +1 -0
- package/dist/commands/spaces/auto-executor/preview.js +62 -3
- package/dist/commands/spaces/auto-executor/update.d.ts +4 -0
- package/dist/commands/spaces/auto-executor/update.js +78 -7
- package/dist/commands/spaces/capacity.js +14 -2
- package/dist/commands/spaces/list.d.ts +13 -0
- package/dist/commands/spaces/list.js +20 -1
- package/dist/commands/spaces/update.d.ts +4 -0
- package/dist/commands/spaces/update.js +49 -2
- package/dist/commands/tasks/complete.d.ts +12 -5
- package/dist/commands/tasks/complete.js +50 -28
- package/dist/commands/tasks/continue-ready.js +9 -1
- package/dist/commands/tasks/create.d.ts +1 -0
- package/dist/commands/tasks/create.js +25 -1
- package/dist/commands/tasks/deliverable/add.d.ts +23 -0
- package/dist/commands/tasks/deliverable/add.js +70 -0
- package/dist/commands/tasks/events/append.d.ts +1 -1
- package/dist/commands/tasks/events/append.js +4 -4
- package/dist/commands/tasks/expectations.d.ts +12 -0
- package/dist/commands/tasks/expectations.js +92 -0
- package/dist/commands/tasks/judge.d.ts +29 -0
- package/dist/commands/tasks/judge.js +68 -0
- package/dist/commands/tasks/list.d.ts +11 -0
- package/dist/commands/tasks/list.js +82 -11
- package/dist/commands/tasks/report.d.ts +1 -1
- package/dist/commands/tasks/report.js +3 -3
- package/dist/commands/tasks/update.d.ts +1 -0
- package/dist/commands/tasks/update.js +34 -4
- package/dist/commands/tasks/waive.d.ts +25 -0
- package/dist/commands/tasks/waive.js +58 -0
- package/dist/commands/wiki/cat.js +2 -1
- package/dist/commands/wiki/mv.js +5 -1
- package/dist/commands/wiki/write.js +5 -1
- package/dist/lib/agent-config.js +5 -0
- package/dist/lib/agent-instructions.d.ts +15 -0
- package/dist/lib/agent-instructions.js +55 -0
- package/dist/lib/api-fetch.d.ts +2 -1
- package/dist/lib/api-fetch.js +9 -2
- package/dist/lib/command-hygiene.d.ts +6 -1
- package/dist/lib/command-hygiene.js +49 -29
- package/dist/lib/commitments.d.ts +44 -0
- package/dist/lib/commitments.js +123 -0
- package/dist/lib/daemon-binding.d.ts +3 -4
- package/dist/lib/daemon-binding.js +11 -10
- package/dist/lib/daemon-handoff-opt-out.d.ts +8 -0
- package/dist/lib/daemon-handoff-opt-out.js +17 -0
- package/dist/lib/daemon-installer.d.ts +1 -1
- package/dist/lib/daemon-installer.js +2 -2
- package/dist/lib/daemon-setup.js +13 -7
- package/dist/lib/daemonHandoff.d.ts +1 -1
- package/dist/lib/daemonHandoff.js +20 -7
- package/dist/lib/delegated-cli.d.ts +0 -9
- package/dist/lib/delegated-cli.js +149 -6
- package/dist/lib/{exec-oversky.d.ts → exec-runtime-binary.d.ts} +28 -4
- package/dist/lib/{exec-oversky.js → exec-runtime-binary.js} +138 -37
- package/dist/lib/git-task.d.ts +37 -0
- package/dist/lib/git-task.js +151 -0
- package/dist/lib/instruction-blocks.d.ts +29 -0
- package/dist/lib/instruction-blocks.js +159 -0
- package/dist/lib/node-adapter.js +6 -0
- package/dist/lib/runtime-start-verification.d.ts +49 -0
- package/dist/lib/runtime-start-verification.js +108 -0
- package/dist/lib/sky-code.d.ts +1 -1
- package/dist/lib/sky-code.js +1 -1
- package/dist/lib/task-execution.d.ts +18 -2
- package/dist/lib/task-execution.js +19 -14
- package/dist/lib/task-transcript.js +1 -1
- package/dist/lib/tasks.d.ts +50 -0
- package/dist/lib/tasks.js +66 -1
- package/dist/lib/usage-discovery.js +1 -1
- package/dist/lib/web-url.d.ts +16 -0
- package/dist/lib/web-url.js +25 -0
- package/dist/node_modules/@skrr-ai/data-provider/index.js +4075 -3905
- package/dist/node_modules/@skrr-ai/inference-broker/package.json +1 -1
- package/oclif.manifest.json +12364 -10488
- package/package.json +4 -1
|
@@ -136,6 +136,12 @@ class TasksCreate extends base_command_1.BaseCommand {
|
|
|
136
136
|
'dri-user': core_1.Flags.string({
|
|
137
137
|
description: 'Explicit accountable human DRI (separate from assignees)',
|
|
138
138
|
}),
|
|
139
|
+
expect: core_1.Flags.string({
|
|
140
|
+
multiple: true,
|
|
141
|
+
description: tasks_1.EXPECT_FLAG_HELP +
|
|
142
|
+
" Injected into the agent's instructions and checked against what the run produced. " +
|
|
143
|
+
'Omit to inherit the space default.',
|
|
144
|
+
}),
|
|
139
145
|
'execution-mode': core_1.Flags.string({
|
|
140
146
|
description: 'Who executes the task: agent or human. Required when both Humans and Agents are ' +
|
|
141
147
|
'assigned. Passing "human" with no assignee flags files the task against you, ' +
|
|
@@ -184,7 +190,25 @@ class TasksCreate extends base_command_1.BaseCommand {
|
|
|
184
190
|
retryable: false,
|
|
185
191
|
});
|
|
186
192
|
}
|
|
187
|
-
|
|
193
|
+
// Resolve --expect BEFORE any write. A bad spec must fail here rather than
|
|
194
|
+
// reaching the server as a silently-dropped field: a declaration that did
|
|
195
|
+
// not stick is worse than none, because the board then shows a contract
|
|
196
|
+
// nobody is enforcing.
|
|
197
|
+
const parsedExpectations = (0, tasks_1.parseExpectations)(flags.expect);
|
|
198
|
+
if (!parsedExpectations.ok) {
|
|
199
|
+
this.failWithCliError({
|
|
200
|
+
message: parsedExpectations.error,
|
|
201
|
+
code: 'INVALID_TASK_EXPECTATION',
|
|
202
|
+
exit: 1,
|
|
203
|
+
retryable: false,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
const payload = (0, tasks_1.buildTaskCreatePayload)(body, {
|
|
207
|
+
...flags,
|
|
208
|
+
expectations: parsedExpectations.ok && parsedExpectations.value.length > 0
|
|
209
|
+
? parsedExpectations.value
|
|
210
|
+
: undefined,
|
|
211
|
+
});
|
|
188
212
|
const isTemplateInstantiation = typeof payload.templateId === 'string' && payload.templateId.length > 0;
|
|
189
213
|
// Template defaults (including its assigned agents) are part of the saved
|
|
190
214
|
// resource. Do not let the ordinary "who owns an empty task?" policy
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* `skrr tasks deliverable add <task> <kind>:<identity>[@<location>]`
|
|
4
|
+
*
|
|
5
|
+
* The command an agent runs to say what it produced. Deliberately small: one
|
|
6
|
+
* positional carrying a coordinate it already knows, because the measured
|
|
7
|
+
* behaviour is that agents emit a real commit sha 77% of the time when asked
|
|
8
|
+
* for it in a required field, and 0% of the time when asked for it in an
|
|
9
|
+
* optional structured one.
|
|
10
|
+
*/
|
|
11
|
+
export default class TasksDeliverableAdd extends BaseCommand {
|
|
12
|
+
static description: string;
|
|
13
|
+
static examples: string[];
|
|
14
|
+
static args: {
|
|
15
|
+
task: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
16
|
+
coordinate: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
17
|
+
};
|
|
18
|
+
static flags: {
|
|
19
|
+
lifecycle: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
20
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
21
|
+
};
|
|
22
|
+
run(): Promise<void>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
|
+
const base_command_1 = require("../../../base-command");
|
|
6
|
+
const tasks_1 = require("../../../lib/tasks");
|
|
7
|
+
/**
|
|
8
|
+
* `skrr tasks deliverable add <task> <kind>:<identity>[@<location>]`
|
|
9
|
+
*
|
|
10
|
+
* The command an agent runs to say what it produced. Deliberately small: one
|
|
11
|
+
* positional carrying a coordinate it already knows, because the measured
|
|
12
|
+
* behaviour is that agents emit a real commit sha 77% of the time when asked
|
|
13
|
+
* for it in a required field, and 0% of the time when asked for it in an
|
|
14
|
+
* optional structured one.
|
|
15
|
+
*/
|
|
16
|
+
class TasksDeliverableAdd extends base_command_1.BaseCommand {
|
|
17
|
+
static description = 'Record something this task produced (a commit, a page, a URL, a file, a message, a dataset)';
|
|
18
|
+
static examples = [
|
|
19
|
+
'<%= config.bin %> tasks deliverable add <task-id> code:a1b2c3d@origin/main',
|
|
20
|
+
'<%= config.bin %> tasks deliverable add <task-id> page:d_92@Engineering/deploy',
|
|
21
|
+
'<%= config.bin %> tasks deliverable add <task-id> file/pdf:f_71@Drive/Reports',
|
|
22
|
+
'<%= config.bin %> tasks deliverable add <task-id> code:a1b2c3d --lifecycle in_review',
|
|
23
|
+
];
|
|
24
|
+
static args = {
|
|
25
|
+
task: core_1.Args.string({ description: 'Task id or ref', required: true, ignoreStdin: true }),
|
|
26
|
+
coordinate: core_1.Args.string({
|
|
27
|
+
description: '<kind>[/<format>]:<identity>[@<location>] — e.g. code:a1b2c3d@origin/main, ' +
|
|
28
|
+
'file/pdf:report_92@Drive/Reports',
|
|
29
|
+
required: true,
|
|
30
|
+
ignoreStdin: true,
|
|
31
|
+
}),
|
|
32
|
+
};
|
|
33
|
+
static flags = {
|
|
34
|
+
lifecycle: core_1.Flags.string({
|
|
35
|
+
options: ['local', 'in_review', 'durable', 'blocked', 'superseded'],
|
|
36
|
+
description: 'How far along it is. Defaults to `local` — recording that a commit exists is not a ' +
|
|
37
|
+
'claim that it landed. Only an external receipt should assert `durable`.',
|
|
38
|
+
}),
|
|
39
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
40
|
+
};
|
|
41
|
+
async run() {
|
|
42
|
+
this.requireAuth();
|
|
43
|
+
const { args, flags } = await this.parse(TasksDeliverableAdd);
|
|
44
|
+
const parsed = (0, tasks_1.parseDeliverableCoordinate)(args.coordinate);
|
|
45
|
+
if (!parsed.ok) {
|
|
46
|
+
// For an agent this message IS the documentation — it hits the error and
|
|
47
|
+
// corrects, so the refusal carries the whole form and vocabulary.
|
|
48
|
+
this.error(parsed.error, { exit: 1 });
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
let result;
|
|
52
|
+
try {
|
|
53
|
+
result = await data_provider_1.dataService.addTaskDeliverable(args.task, {
|
|
54
|
+
...parsed.value,
|
|
55
|
+
...(flags.lifecycle ? { lifecycle: flags.lifecycle } : {}),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
this.handleApiError(err);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (flags.json) {
|
|
63
|
+
this.log(JSON.stringify(result, null, 2));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const where = parsed.value.location ? ` at ${parsed.value.location}` : '';
|
|
67
|
+
this.log(`Recorded ${parsed.value.kind}:${parsed.value.identity}${where} (${flags.lifecycle || 'local'}).`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.default = TasksDeliverableAdd;
|
|
@@ -15,7 +15,7 @@ export default class TasksEventsAppend extends BaseCommand {
|
|
|
15
15
|
changed: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
16
16
|
next: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
17
17
|
evidence: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
18
|
-
|
|
18
|
+
deliverable: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
19
|
};
|
|
20
20
|
run(): Promise<void>;
|
|
21
21
|
}
|
|
@@ -15,7 +15,7 @@ class TasksEventsAppend extends base_command_1.BaseCommand {
|
|
|
15
15
|
static examples = [
|
|
16
16
|
'<%= config.bin %> tasks events append <task-id> --kind checkpoint --idempotency-key "<task-id>:first-pass" --summary "Parser handles nested fences"',
|
|
17
17
|
'<%= config.bin %> tasks events append <task-id> --kind decision --idempotency-key "<task-id>:storage-choice" --summary "Chose the CRDT path" --evidence "A direct contentHtml write is reverted by the next render tick"',
|
|
18
|
-
'<%= config.bin %> tasks events append <task-id> --kind verification --idempotency-key "<task-id>:verified" --summary "Repro no longer reproduces" --
|
|
18
|
+
'<%= config.bin %> tasks events append <task-id> --kind verification --idempotency-key "<task-id>:verified" --summary "Repro no longer reproduces" --deliverable <commit-sha>',
|
|
19
19
|
];
|
|
20
20
|
static args = {
|
|
21
21
|
id: core_1.Args.string({
|
|
@@ -54,9 +54,9 @@ class TasksEventsAppend extends base_command_1.BaseCommand {
|
|
|
54
54
|
evidence: core_1.Flags.string({
|
|
55
55
|
description: 'Why it is true — an observation, command output, or a before → after',
|
|
56
56
|
}),
|
|
57
|
-
|
|
57
|
+
deliverable: core_1.Flags.string({
|
|
58
58
|
multiple: true,
|
|
59
|
-
description: 'Durable reference: a file path, commit sha, or URL. Repeatable. "in the conversation" is not
|
|
59
|
+
description: 'Durable reference: a file path, commit sha, or URL. Repeatable. "in the conversation" is not a deliverable',
|
|
60
60
|
}),
|
|
61
61
|
};
|
|
62
62
|
async run() {
|
|
@@ -70,7 +70,7 @@ class TasksEventsAppend extends base_command_1.BaseCommand {
|
|
|
70
70
|
changed: flags.changed,
|
|
71
71
|
next: flags.next,
|
|
72
72
|
evidence: flags.evidence,
|
|
73
|
-
artifacts: flags.
|
|
73
|
+
artifacts: flags.deliverable?.map((ref) => ({ label: 'deliverable', ref })),
|
|
74
74
|
};
|
|
75
75
|
const path = await (0, session_task_endpoints_1.sessionScopedTaskPath)('event');
|
|
76
76
|
let result;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
export default class TasksExpectations extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
task: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
|
+
const base_command_1 = require("../../base-command");
|
|
6
|
+
/**
|
|
7
|
+
* `skrr tasks expectations <task>` — what this task owes, and how far each got.
|
|
8
|
+
*
|
|
9
|
+
* Reads the SERVER's verdict rather than recomputing one. The judge and the
|
|
10
|
+
* completion gate are the same module, so a CLI that decided "met" for itself
|
|
11
|
+
* could disagree with the gate that refuses the task — and the reader would
|
|
12
|
+
* have no way to tell which was lying.
|
|
13
|
+
*/
|
|
14
|
+
const STATE_LABEL = {
|
|
15
|
+
met: 'done',
|
|
16
|
+
waived: 'dropped',
|
|
17
|
+
blocked: 'stuck',
|
|
18
|
+
underway: 'on its way',
|
|
19
|
+
owed: 'not yet',
|
|
20
|
+
unjudged: 'needs a person',
|
|
21
|
+
};
|
|
22
|
+
function line(expectation) {
|
|
23
|
+
const label = STATE_LABEL[expectation.state] || expectation.state;
|
|
24
|
+
// A judged expectation is stated as NOT a gate. A list that reads like a
|
|
25
|
+
// contract while enforcing nothing is worse than no list, because it is
|
|
26
|
+
// trusted.
|
|
27
|
+
const gate = expectation.gating ? '' : ' (does not block completion)';
|
|
28
|
+
const from = expectation.source === 'space' ? ' [space default]' : '';
|
|
29
|
+
return ` ${expectation.id.padEnd(18)} ${label.padEnd(14)} ${expectation.sentence}${gate}${from}`;
|
|
30
|
+
}
|
|
31
|
+
class TasksExpectations extends base_command_1.BaseCommand {
|
|
32
|
+
static description = 'Show what a task must produce and how far each expectation got ("Done when")';
|
|
33
|
+
static examples = [
|
|
34
|
+
'<%= config.bin %> tasks expectations <task-id>',
|
|
35
|
+
'<%= config.bin %> tasks expectations <task-id> --json',
|
|
36
|
+
];
|
|
37
|
+
static args = {
|
|
38
|
+
task: core_1.Args.string({ description: 'Task id or ref', required: true, ignoreStdin: true }),
|
|
39
|
+
};
|
|
40
|
+
static flags = {
|
|
41
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
42
|
+
};
|
|
43
|
+
async run() {
|
|
44
|
+
this.requireAuth();
|
|
45
|
+
const { args, flags } = await this.parse(TasksExpectations);
|
|
46
|
+
let acceptance;
|
|
47
|
+
try {
|
|
48
|
+
acceptance = await data_provider_1.dataService.getTaskAcceptance(args.task);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
this.handleApiError(err);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (flags.json) {
|
|
55
|
+
this.log(JSON.stringify(acceptance, null, 2));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (acceptance.expectations.length === 0) {
|
|
59
|
+
// An empty contract is a real answer, not an unfilled field. Say so
|
|
60
|
+
// plainly rather than prompting for something most tasks do not owe.
|
|
61
|
+
this.log('Nothing durable is expected of this task.');
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// The evidence read fails OPEN by design, so "produced nothing" and "we
|
|
65
|
+
// could not look" are indistinguishable downstream unless the server says
|
|
66
|
+
// which happened. Never print the first when it might be the second.
|
|
67
|
+
if (!acceptance.evidenceRead) {
|
|
68
|
+
this.warn('Could not read what this task produced — the states below may understate it. ' +
|
|
69
|
+
'This is not a claim that nothing was produced.');
|
|
70
|
+
}
|
|
71
|
+
this.log('Done when:');
|
|
72
|
+
for (const expectation of acceptance.expectations) {
|
|
73
|
+
this.log(line(expectation));
|
|
74
|
+
}
|
|
75
|
+
const gating = acceptance.expectations.filter((e) => e.gating);
|
|
76
|
+
const met = gating.filter((e) => e.met).length;
|
|
77
|
+
this.log('');
|
|
78
|
+
this.log(`${met} of ${gating.length} met · overall: ${acceptance.state}`);
|
|
79
|
+
// Only the ones actually stored on the task can be judged. A space default
|
|
80
|
+
// is synthesised per read, so pointing at `tasks judge` for one would send
|
|
81
|
+
// the reader at a command that can only refuse it.
|
|
82
|
+
const settleable = acceptance.expectations.filter((e) => e.state === 'unjudged' && e.source !== 'space').length;
|
|
83
|
+
if (settleable > 0) {
|
|
84
|
+
this.log(`${settleable} awaiting a person — settle with \`${this.config.bin} tasks judge\`.`);
|
|
85
|
+
}
|
|
86
|
+
const inherited = acceptance.unjudged - settleable;
|
|
87
|
+
if (inherited > 0) {
|
|
88
|
+
this.log(`${inherited} inherited from the space default — declare them on the task to settle them.`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
exports.default = TasksExpectations;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* `skrr tasks judge <task> <expectation-id> --verdict met --reason "<why>"`
|
|
4
|
+
*
|
|
5
|
+
* Settle a `judged` expectation — one whose text nothing here can evaluate.
|
|
6
|
+
*
|
|
7
|
+
* Only a judged one. A checkable expectation is settled by recording what was
|
|
8
|
+
* produced, and letting a person mark it met by hand would make the deliverables
|
|
9
|
+
* ledger optional, which is the same as not having one. The server refuses that
|
|
10
|
+
* case with an error naming the command to use instead.
|
|
11
|
+
*
|
|
12
|
+
* The reason is REQUIRED, for the same purpose a waiver's is: a verdict with no
|
|
13
|
+
* reason is indistinguishable from a click, and the entire value of a judged
|
|
14
|
+
* expectation is that somebody actually looked.
|
|
15
|
+
*/
|
|
16
|
+
export default class TasksJudge extends BaseCommand {
|
|
17
|
+
static description: string;
|
|
18
|
+
static examples: string[];
|
|
19
|
+
static args: {
|
|
20
|
+
task: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
21
|
+
expectation: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
22
|
+
};
|
|
23
|
+
static flags: {
|
|
24
|
+
verdict: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
25
|
+
reason: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
26
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
27
|
+
};
|
|
28
|
+
run(): Promise<void>;
|
|
29
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
|
+
const base_command_1 = require("../../base-command");
|
|
6
|
+
/**
|
|
7
|
+
* `skrr tasks judge <task> <expectation-id> --verdict met --reason "<why>"`
|
|
8
|
+
*
|
|
9
|
+
* Settle a `judged` expectation — one whose text nothing here can evaluate.
|
|
10
|
+
*
|
|
11
|
+
* Only a judged one. A checkable expectation is settled by recording what was
|
|
12
|
+
* produced, and letting a person mark it met by hand would make the deliverables
|
|
13
|
+
* ledger optional, which is the same as not having one. The server refuses that
|
|
14
|
+
* case with an error naming the command to use instead.
|
|
15
|
+
*
|
|
16
|
+
* The reason is REQUIRED, for the same purpose a waiver's is: a verdict with no
|
|
17
|
+
* reason is indistinguishable from a click, and the entire value of a judged
|
|
18
|
+
* expectation is that somebody actually looked.
|
|
19
|
+
*/
|
|
20
|
+
class TasksJudge extends base_command_1.BaseCommand {
|
|
21
|
+
static description = 'Settle a judged expectation with a verdict and a stated reason';
|
|
22
|
+
static examples = [
|
|
23
|
+
'<%= config.bin %> tasks judge <task-id> e2 --verdict met --reason "Read it end to end; a non-engineer follows it."',
|
|
24
|
+
'<%= config.bin %> tasks judge <task-id> e2 --verdict unmet --reason "Still assumes the reader knows the schema."',
|
|
25
|
+
];
|
|
26
|
+
static args = {
|
|
27
|
+
task: core_1.Args.string({ description: 'Task id or ref', required: true, ignoreStdin: true }),
|
|
28
|
+
expectation: core_1.Args.string({
|
|
29
|
+
description: 'Expectation id (see `tasks expectations`)',
|
|
30
|
+
required: true,
|
|
31
|
+
ignoreStdin: true,
|
|
32
|
+
}),
|
|
33
|
+
};
|
|
34
|
+
static flags = {
|
|
35
|
+
verdict: core_1.Flags.string({
|
|
36
|
+
options: ['met', 'unmet'],
|
|
37
|
+
required: true,
|
|
38
|
+
description: 'Whether the expectation was met.',
|
|
39
|
+
}),
|
|
40
|
+
reason: core_1.Flags.string({
|
|
41
|
+
required: true,
|
|
42
|
+
description: 'What you looked at. A verdict without one is not a judgement.',
|
|
43
|
+
}),
|
|
44
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
45
|
+
};
|
|
46
|
+
async run() {
|
|
47
|
+
this.requireAuth();
|
|
48
|
+
const { args, flags } = await this.parse(TasksJudge);
|
|
49
|
+
let result;
|
|
50
|
+
try {
|
|
51
|
+
result = await data_provider_1.dataService.judgeTaskExpectation(args.task, {
|
|
52
|
+
expectationId: args.expectation,
|
|
53
|
+
verdict: flags.verdict,
|
|
54
|
+
reason: flags.reason,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
this.handleApiError(err);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (flags.json) {
|
|
62
|
+
this.log(JSON.stringify(result, null, 2));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
this.log(`Recorded ${args.expectation} as ${flags.verdict}: ${flags.reason}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.default = TasksJudge;
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import type { TaskListParams } from '@skrr-ai/data-provider';
|
|
2
2
|
import { BaseCommand } from '../../base-command';
|
|
3
3
|
type ListFlags = Record<string, unknown>;
|
|
4
|
+
/**
|
|
5
|
+
* What the zero-row case is allowed to say. The bare `No tasks.` was step 3
|
|
6
|
+
* of `GETTING_STARTED.md` and named no next step; a new user reading it hit
|
|
7
|
+
* three of these in a row and concluded the product was empty. Follow the
|
|
8
|
+
* `commitments/list.ts` pattern: name the command that fixes THIS empty state,
|
|
9
|
+
* with the specific `--status in_progress` hint kept because a reaped run
|
|
10
|
+
* genuinely hides here (a real bug, not a first-run scenario).
|
|
11
|
+
*
|
|
12
|
+
* Exported and pure so the wording is testable without an oclif runtime.
|
|
13
|
+
*/
|
|
14
|
+
export declare function emptyTasksMessage(flags: ListFlags, bin?: string): string;
|
|
4
15
|
/**
|
|
5
16
|
* The task-list request bag is shared with import/export so every CLI list
|
|
6
17
|
* surface serializes the same server-side filters. Keep user-id resolution in
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.emptyTasksMessage = emptyTasksMessage;
|
|
3
4
|
exports.buildListParams = buildListParams;
|
|
4
5
|
const core_1 = require("@oclif/core");
|
|
5
6
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
@@ -7,6 +8,86 @@ const base_command_1 = require("../../base-command");
|
|
|
7
8
|
const web_url_1 = require("../../lib/web-url");
|
|
8
9
|
const format_1 = require("../../lib/format");
|
|
9
10
|
const tasks_1 = require("../../lib/tasks");
|
|
11
|
+
/**
|
|
12
|
+
* Names of `tasks list` flags that narrow the result set. Used to distinguish
|
|
13
|
+
* "no tasks anywhere" from "no tasks matching your filters" — the first case
|
|
14
|
+
* wants a create-command hint, the second wants a loosen-filters hint. Kept
|
|
15
|
+
* as a set so a new filter added to `buildListParams` shows up here at review
|
|
16
|
+
* time rather than silently changing the empty state.
|
|
17
|
+
*/
|
|
18
|
+
const FILTER_FLAGS = new Set([
|
|
19
|
+
'goal',
|
|
20
|
+
'project',
|
|
21
|
+
'cycle',
|
|
22
|
+
'parent',
|
|
23
|
+
'status',
|
|
24
|
+
'status-type',
|
|
25
|
+
'execution-state',
|
|
26
|
+
'actionable-by',
|
|
27
|
+
'actionable-for-agent',
|
|
28
|
+
'needs-me',
|
|
29
|
+
'actionability-state',
|
|
30
|
+
'actionability-reason',
|
|
31
|
+
'priority',
|
|
32
|
+
'estimate',
|
|
33
|
+
'min-estimate',
|
|
34
|
+
'assignee-agent',
|
|
35
|
+
'assignee-user',
|
|
36
|
+
'dri',
|
|
37
|
+
'dri-kind',
|
|
38
|
+
'mine',
|
|
39
|
+
'explicit-only',
|
|
40
|
+
'subscribed',
|
|
41
|
+
'include-snoozed',
|
|
42
|
+
'external-key',
|
|
43
|
+
'blocked-by',
|
|
44
|
+
'blocks',
|
|
45
|
+
'due-before',
|
|
46
|
+
'due-after',
|
|
47
|
+
'overdue',
|
|
48
|
+
'tag',
|
|
49
|
+
'label-id',
|
|
50
|
+
'q',
|
|
51
|
+
]);
|
|
52
|
+
/**
|
|
53
|
+
* What the zero-row case is allowed to say. The bare `No tasks.` was step 3
|
|
54
|
+
* of `GETTING_STARTED.md` and named no next step; a new user reading it hit
|
|
55
|
+
* three of these in a row and concluded the product was empty. Follow the
|
|
56
|
+
* `commitments/list.ts` pattern: name the command that fixes THIS empty state,
|
|
57
|
+
* with the specific `--status in_progress` hint kept because a reaped run
|
|
58
|
+
* genuinely hides here (a real bug, not a first-run scenario).
|
|
59
|
+
*
|
|
60
|
+
* Exported and pure so the wording is testable without an oclif runtime.
|
|
61
|
+
*/
|
|
62
|
+
function emptyTasksMessage(flags, bin = 'skrr') {
|
|
63
|
+
const activeFilters = Array.from(FILTER_FLAGS).filter((name) => {
|
|
64
|
+
const value = flags[name];
|
|
65
|
+
if (value === undefined || value === null || value === false)
|
|
66
|
+
return false;
|
|
67
|
+
if (typeof value === 'string' && value.length === 0)
|
|
68
|
+
return false;
|
|
69
|
+
if (Array.isArray(value) && value.length === 0)
|
|
70
|
+
return false;
|
|
71
|
+
return true;
|
|
72
|
+
});
|
|
73
|
+
const lines = ['No tasks.'];
|
|
74
|
+
if (activeFilters.length === 0) {
|
|
75
|
+
lines.push('');
|
|
76
|
+
lines.push(` → Create your first one: \`${bin} tasks create --title "..." --space <space-id>\``);
|
|
77
|
+
lines.push(` → List spaces to find one: \`${bin} spaces list\``);
|
|
78
|
+
}
|
|
79
|
+
else if (flags.status === 'in_progress' && !flags['execution-state']) {
|
|
80
|
+
// `--status in_progress` filters the board column only. A run that was
|
|
81
|
+
// reaped/reset (e.g. a stuck-task timeout) is moved OFF `in_progress` but
|
|
82
|
+
// keeps its execution markers, so it hides here. Point the operator at
|
|
83
|
+
// the execution-state views that still surface it.
|
|
84
|
+
lines.push('');
|
|
85
|
+
lines.push('Note: `--status in_progress` shows only the board column. A reaped or reset run');
|
|
86
|
+
lines.push(' no longer has that status. Try `--execution-state active` (running now) or');
|
|
87
|
+
lines.push(` \`--execution-state recovered\` (reaped, startable), or \`${bin} tasks active\`.`);
|
|
88
|
+
}
|
|
89
|
+
return lines.join('\n');
|
|
90
|
+
}
|
|
10
91
|
/**
|
|
11
92
|
* The task-list request bag is shared with import/export so every CLI list
|
|
12
93
|
* surface serializes the same server-side filters. Keep user-id resolution in
|
|
@@ -303,17 +384,7 @@ class TasksList extends base_command_1.BaseCommand {
|
|
|
303
384
|
const r = response;
|
|
304
385
|
const items = r?.data ?? [];
|
|
305
386
|
if (items.length === 0) {
|
|
306
|
-
this.log(
|
|
307
|
-
// `--status in_progress` filters the board column only. A run that was
|
|
308
|
-
// reaped/reset (e.g. a stuck-task timeout) is moved OFF `in_progress` but
|
|
309
|
-
// keeps its execution markers, so it hides here. Point the operator at the
|
|
310
|
-
// execution-state views that still surface it.
|
|
311
|
-
if (flags.status === 'in_progress' && !flags['execution-state']) {
|
|
312
|
-
this.log('');
|
|
313
|
-
this.log('Note: `--status in_progress` shows only the board column. A reaped or reset run');
|
|
314
|
-
this.log(' no longer has that status. Try `--execution-state active` (running now) or');
|
|
315
|
-
this.log(' `--execution-state recovered` (reaped, startable), or `skrr tasks active`.');
|
|
316
|
-
}
|
|
387
|
+
this.log(emptyTasksMessage(flags, this.config.bin));
|
|
317
388
|
return;
|
|
318
389
|
}
|
|
319
390
|
const rows = items.map((t) => {
|
|
@@ -18,7 +18,7 @@ export default class TasksReport extends BaseCommand {
|
|
|
18
18
|
finding: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
19
|
evidence: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
20
20
|
next: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
21
|
-
|
|
21
|
+
deliverable: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
22
22
|
};
|
|
23
23
|
run(): Promise<void>;
|
|
24
24
|
}
|
|
@@ -18,7 +18,7 @@ class TasksReport extends base_command_1.BaseCommand {
|
|
|
18
18
|
static description = 'Record a self-contained outcome, findings, evidence, and next actions';
|
|
19
19
|
static examples = [
|
|
20
20
|
'<%= config.bin %> tasks report <task-id> --outcome "Adopt the event ledger" --finding "The task page omits work-event details" --evidence "Task detail reads only legacy activity" --next "Add an Outcome section"',
|
|
21
|
-
'<%= config.bin %> tasks report <task-id> --kind handoff --outcome "Ready for review" --finding "All acceptance criteria are met" --
|
|
21
|
+
'<%= config.bin %> tasks report <task-id> --kind handoff --outcome "Ready for review" --finding "All acceptance criteria are met" --deliverable "src/task.ts" --json',
|
|
22
22
|
];
|
|
23
23
|
static args = {
|
|
24
24
|
id: core_1.Args.string({
|
|
@@ -48,7 +48,7 @@ class TasksReport extends base_command_1.BaseCommand {
|
|
|
48
48
|
multiple: true,
|
|
49
49
|
}),
|
|
50
50
|
next: core_1.Flags.string({ description: 'A follow-up or next action (repeatable)', multiple: true }),
|
|
51
|
-
|
|
51
|
+
deliverable: core_1.Flags.string({
|
|
52
52
|
description: 'Durable file, commit, PR, or URL (repeatable)',
|
|
53
53
|
multiple: true,
|
|
54
54
|
}),
|
|
@@ -92,7 +92,7 @@ class TasksReport extends base_command_1.BaseCommand {
|
|
|
92
92
|
idempotencyKey: (0, outbox_1.idempotencyKeyFor)('task-report', task.id, JSON.stringify({ report, kind: flags.kind })),
|
|
93
93
|
kind,
|
|
94
94
|
...(0, task_report_1.taskReportEventFields)(report),
|
|
95
|
-
artifacts: flags.
|
|
95
|
+
artifacts: flags.deliverable?.map((ref) => ({ label: 'deliverable', ref })),
|
|
96
96
|
};
|
|
97
97
|
const sessionPath = await (0, session_task_endpoints_1.sessionScopedTaskPath)('event');
|
|
98
98
|
let result;
|
|
@@ -10,6 +10,7 @@ export default class TasksUpdate extends BaseCommand {
|
|
|
10
10
|
task: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
11
|
'from-json': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
12
|
title: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
|
+
expect: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
14
|
description: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
14
15
|
'description-format': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
15
16
|
priority: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -5,8 +5,9 @@ const data_provider_1 = require("@skrr-ai/data-provider");
|
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
6
|
const web_url_1 = require("../../lib/web-url");
|
|
7
7
|
const prompt_1 = require("../../lib/prompt");
|
|
8
|
-
const task_resolver_1 = require("../../lib/task-resolver");
|
|
9
8
|
const tasks_1 = require("../../lib/tasks");
|
|
9
|
+
const task_resolver_1 = require("../../lib/task-resolver");
|
|
10
|
+
const tasks_2 = require("../../lib/tasks");
|
|
10
11
|
const create_1 = require("./create");
|
|
11
12
|
class TasksUpdate extends base_command_1.BaseCommand {
|
|
12
13
|
static description = 'Update an existing task (partial patch). Status and PROJECT changes go through ' +
|
|
@@ -41,6 +42,11 @@ class TasksUpdate extends base_command_1.BaseCommand {
|
|
|
41
42
|
description: 'Path to a JSON file (or "-" for stdin) to use as the patch body; may include taskId',
|
|
42
43
|
}),
|
|
43
44
|
title: core_1.Flags.string({ description: 'New title' }),
|
|
45
|
+
expect: core_1.Flags.string({
|
|
46
|
+
multiple: true,
|
|
47
|
+
description: tasks_1.EXPECT_FLAG_HELP +
|
|
48
|
+
' Replaces the whole list; pass "clear" to drop it and inherit the space default.',
|
|
49
|
+
}),
|
|
44
50
|
description: core_1.Flags.string({ description: 'New description' }),
|
|
45
51
|
'description-format': core_1.Flags.string({
|
|
46
52
|
description: 'Input format for --description or from-json description',
|
|
@@ -48,7 +54,7 @@ class TasksUpdate extends base_command_1.BaseCommand {
|
|
|
48
54
|
}),
|
|
49
55
|
priority: core_1.Flags.string({
|
|
50
56
|
description: 'New priority',
|
|
51
|
-
options: [...
|
|
57
|
+
options: [...tasks_2.TASK_PRIORITIES],
|
|
52
58
|
}),
|
|
53
59
|
'start-date': core_1.Flags.string({ description: 'New planned start date (ISO string)' }),
|
|
54
60
|
'due-date': core_1.Flags.string({ description: 'New due date (ISO string)' }),
|
|
@@ -198,8 +204,32 @@ class TasksUpdate extends base_command_1.BaseCommand {
|
|
|
198
204
|
details: { suggestion: failure.suggestion, context: failure.details },
|
|
199
205
|
});
|
|
200
206
|
}
|
|
207
|
+
// `--expect clear` is an explicit empty list, which the API turns into $unset —
|
|
208
|
+
// distinct from omitting the flag, which leaves the declaration untouched.
|
|
209
|
+
// Without the sentinel there is no way to say "stop requiring an output"
|
|
210
|
+
// short of hand-writing --from-json.
|
|
211
|
+
// `--expect clear` empties the list; otherwise the flags REPLACE it, because
|
|
212
|
+
// a partial patch of a list has no honest meaning — "add one" and "this is
|
|
213
|
+
// now the whole contract" are different requests and the flag can only be
|
|
214
|
+
// one of them.
|
|
215
|
+
let expectationsPatch;
|
|
216
|
+
if (flags.expect !== undefined && flags.expect.length > 0) {
|
|
217
|
+
if (flags.expect.length === 1 && flags.expect[0].trim() === 'clear') {
|
|
218
|
+
expectationsPatch = null;
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
const parsed = (0, tasks_1.parseExpectations)(flags.expect);
|
|
222
|
+
if (!parsed.ok) {
|
|
223
|
+
this.error(parsed.error, { exit: 1 });
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
expectationsPatch = parsed.value;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
201
230
|
const payload = (0, prompt_1.mergeDefined)((0, task_resolver_1.stripTaskIdentityFields)(body), {
|
|
202
231
|
title: flags.title,
|
|
232
|
+
expectations: expectationsPatch === null ? [] : (expectationsPatch ?? undefined),
|
|
203
233
|
description: flags.description,
|
|
204
234
|
descriptionFormat: flags['description-format'],
|
|
205
235
|
priority: flags.priority,
|
|
@@ -231,7 +261,7 @@ class TasksUpdate extends base_command_1.BaseCommand {
|
|
|
231
261
|
labelIds: flags['label-id'],
|
|
232
262
|
// Worktree isolation override. --worktree ⇒ 'ephemeral', --no-worktree ⇒
|
|
233
263
|
// 'shared', omitted ⇒ unchanged. (Clear-to-inherit via --from-json.)
|
|
234
|
-
executionIsolation: (0,
|
|
264
|
+
executionIsolation: (0, tasks_2.executionIsolationFromWorktreeFlag)(flags.worktree),
|
|
235
265
|
// A mutation option, not a field — `undefined` unless explicitly asked
|
|
236
266
|
// for, so it never counts toward the "nothing to update" check below.
|
|
237
267
|
repairReleasePins: flags['repair-release-pins'] ? true : undefined,
|
|
@@ -253,7 +283,7 @@ class TasksUpdate extends base_command_1.BaseCommand {
|
|
|
253
283
|
retryable: false,
|
|
254
284
|
});
|
|
255
285
|
}
|
|
256
|
-
const mutationGuardFailure = (0,
|
|
286
|
+
const mutationGuardFailure = (0, tasks_2.taskUpdateMutationGuard)(payload);
|
|
257
287
|
if (mutationGuardFailure) {
|
|
258
288
|
this.failWithCliError({
|
|
259
289
|
message: mutationGuardFailure.message,
|