@skrr-ai/cli 0.1.104 → 0.1.105
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base-command.js +6 -2
- package/dist/commands/agenda/trigger/list.js +2 -0
- package/dist/commands/agents/chat.js +4 -1
- package/dist/commands/agents/operating-plan.js +5 -2
- package/dist/commands/agents/triggers/create.js +3 -1
- package/dist/commands/agents/triggers/fire.js +2 -0
- package/dist/commands/agents/triggers/replay.js +2 -0
- package/dist/commands/agents/triggers/update.js +12 -4
- package/dist/commands/commitments/action-history.js +7 -2
- package/dist/commands/commitments/cadence-decisions.js +6 -1
- package/dist/commands/commitments/cadence-requests/decide.d.ts +1 -1
- package/dist/commands/commitments/cadence-requests/decide.js +1 -1
- package/dist/commands/commitments/doctor.js +7 -1
- package/dist/commands/commitments/observations.js +7 -1
- package/dist/commands/commitments/operating-review.d.ts +15 -0
- package/dist/commands/commitments/operating-review.js +23 -2
- package/dist/commands/commitments/preflight.d.ts +12 -0
- package/dist/commands/commitments/preflight.js +23 -9
- package/dist/commands/commitments/reflection.js +6 -1
- package/dist/commands/commitments/show.js +3 -1
- package/dist/commands/commitments/trigger-status.js +2 -22
- package/dist/commands/commitments/wake-capabilities.d.ts +13 -0
- package/dist/commands/commitments/wake-capabilities.js +39 -3
- package/dist/commands/daemon/logs.d.ts +41 -3
- package/dist/commands/daemon/logs.js +202 -17
- package/dist/commands/followups/act.js +13 -1
- package/dist/commands/followups/checkin.js +11 -2
- package/dist/commands/followups/reschedule.js +13 -1
- package/dist/commands/proposals/discard.d.ts +1 -1
- package/dist/commands/proposals/keep.d.ts +1 -1
- package/dist/commands/proposals/list.d.ts +7 -0
- package/dist/commands/proposals/list.js +31 -5
- package/dist/commands/proposals/show.d.ts +2 -1
- package/dist/commands/proposals/show.js +31 -4
- package/dist/commands/proposals/snooze.d.ts +1 -1
- package/dist/commands/requests/create.js +8 -3
- package/dist/commands/spaces/workflows/create.js +3 -3
- package/dist/commands/tasks/complete.js +4 -0
- package/dist/commands/tasks/create.d.ts +2 -0
- package/dist/commands/tasks/create.js +17 -3
- package/dist/commands/tasks/deliverable/add.d.ts +2 -0
- package/dist/commands/tasks/deliverable/add.js +22 -7
- package/dist/commands/tasks/deliverable/list.d.ts +13 -0
- package/dist/commands/tasks/deliverable/list.js +34 -1
- package/dist/commands/tasks/economics-compare.js +7 -1
- package/dist/commands/tasks/expectations.d.ts +10 -0
- package/dist/commands/tasks/expectations.js +31 -3
- package/dist/commands/tasks/list.d.ts +9 -0
- package/dist/commands/tasks/list.js +40 -5
- package/dist/commands/tasks/report.js +1 -1
- package/dist/commands/tasks/result/show.d.ts +7 -0
- package/dist/commands/tasks/result/show.js +32 -1
- package/dist/commands/tasks/result/submit.js +1 -1
- package/dist/commands/tasks/show.d.ts +6 -0
- package/dist/commands/tasks/show.js +23 -0
- package/dist/commands/tasks/update.d.ts +3 -0
- package/dist/commands/tasks/update.js +23 -3
- package/dist/commands/triggers/audit.js +6 -2
- package/dist/commands/triggers/create.js +3 -1
- package/dist/commands/triggers/fire.d.ts +1 -0
- package/dist/commands/triggers/fire.js +16 -1
- package/dist/commands/triggers/preflight.js +6 -5
- package/dist/commands/triggers/replay.js +2 -0
- package/dist/commands/triggers/update.js +12 -4
- package/dist/commands/workspaces/stewardship.js +5 -1
- package/dist/lib/agentic-stream.d.ts +9 -0
- package/dist/lib/agentic-stream.js +38 -18
- package/dist/lib/commitment-event-wakes.d.ts +8 -0
- package/dist/lib/commitment-event-wakes.js +39 -0
- package/dist/lib/commitment-ledgers.d.ts +9 -0
- package/dist/lib/commitment-ledgers.js +126 -0
- package/dist/lib/commitments.d.ts +102 -2
- package/dist/lib/commitments.js +208 -8
- package/dist/lib/delegated-cli.js +13 -2
- package/dist/lib/followups.d.ts +6 -0
- package/dist/lib/followups.js +12 -0
- package/dist/lib/message-content.d.ts +6 -0
- package/dist/lib/message-content.js +24 -0
- package/dist/lib/operating-plan-loops.d.ts +8 -0
- package/dist/lib/operating-plan-loops.js +32 -0
- package/dist/lib/preflight-copy.d.ts +27 -0
- package/dist/lib/preflight-copy.js +89 -0
- package/dist/lib/proposal-decision-command.d.ts +1 -1
- package/dist/lib/proposal-decision-command.js +27 -3
- package/dist/lib/proposals.d.ts +17 -0
- package/dist/lib/proposals.js +41 -0
- package/dist/lib/stewardship-output.js +57 -12
- package/dist/lib/task-economics-line.d.ts +30 -0
- package/dist/lib/task-economics-line.js +49 -0
- package/dist/lib/task-economics.d.ts +15 -0
- package/dist/lib/task-economics.js +73 -8
- package/dist/lib/task-recurrence-outcome.d.ts +19 -0
- package/dist/lib/task-recurrence-outcome.js +30 -0
- package/dist/lib/triggers.d.ts +42 -0
- package/dist/lib/triggers.js +136 -2
- package/dist/lib/widgetTerminalText.d.ts +8 -0
- package/dist/lib/widgetTerminalText.js +116 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/cliHandoffWire.d.ts +33 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/cliHandoffWire.js +27 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/telemetryRedaction.d.ts +28 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/telemetryRedaction.js +50 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/cliHandoffWire.d.ts +33 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/cliHandoffWire.js +26 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/telemetryRedaction.d.ts +28 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/telemetryRedaction.js +50 -5
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +7261 -7056
- package/docs/v1/operations.md +1 -1
- package/oclif.manifest.json +116 -72
- package/package.json +1 -1
|
@@ -1,24 +1,51 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
|
-
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
4
|
const base_command_1 = require("../../base-command");
|
|
6
5
|
const proposals_1 = require("../../lib/proposals");
|
|
7
6
|
class ProposalsShow extends base_command_1.BaseCommand {
|
|
8
7
|
static description = 'Show one viewer-scoped proposal and its frozen revision';
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> proposals show request <proposal-id>',
|
|
10
|
+
'<%= config.bin %> proposals show request:<proposal-id>',
|
|
11
|
+
];
|
|
12
|
+
// The kind is validated in `resolveProposalRef`, not by oclif, so the KIND:ID that `proposals list`
|
|
13
|
+
// prints can be pasted whole (OSK-15371).
|
|
9
14
|
static args = {
|
|
10
|
-
kind: core_1.Args.string({
|
|
11
|
-
|
|
15
|
+
kind: core_1.Args.string({
|
|
16
|
+
required: true,
|
|
17
|
+
description: 'Proposal kind, or the KIND:ID that `proposals list` prints',
|
|
18
|
+
ignoreStdin: true,
|
|
19
|
+
}),
|
|
20
|
+
id: core_1.Args.string({ required: false, description: 'Proposal id', ignoreStdin: true }),
|
|
12
21
|
};
|
|
13
22
|
static flags = { json: core_1.Flags.boolean() };
|
|
14
23
|
async run() {
|
|
15
24
|
this.requireAuth();
|
|
16
25
|
const { args } = await this.parse(ProposalsShow);
|
|
26
|
+
const ref = (0, proposals_1.resolveProposalRef)(args.kind, args.id, this.config?.bin);
|
|
27
|
+
if ('error' in ref) {
|
|
28
|
+
this.failWithCliError({
|
|
29
|
+
message: ref.error,
|
|
30
|
+
code: 'PROPOSAL_REF_INVALID',
|
|
31
|
+
exit: 2,
|
|
32
|
+
retryable: false,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
17
35
|
let result;
|
|
18
36
|
try {
|
|
19
|
-
result = await proposals_1.proposalApi.show(
|
|
37
|
+
result = await proposals_1.proposalApi.show(ref.kind, ref.id);
|
|
20
38
|
}
|
|
21
39
|
catch (error) {
|
|
40
|
+
if (error?.status === 404) {
|
|
41
|
+
this.failWithCliError({
|
|
42
|
+
message: (0, proposals_1.describeProposalNotFound)(ref.kind, ref.id, this.config?.bin),
|
|
43
|
+
code: 'PROPOSAL_NOT_FOUND',
|
|
44
|
+
status: 404,
|
|
45
|
+
exit: 4,
|
|
46
|
+
retryable: false,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
22
49
|
this.handleApiError(error);
|
|
23
50
|
}
|
|
24
51
|
this.log(JSON.stringify(result, null, 2));
|
|
@@ -3,7 +3,7 @@ export default class ProposalsSnooze extends ProposalDecisionCommand {
|
|
|
3
3
|
static description: string;
|
|
4
4
|
static args: {
|
|
5
5
|
kind: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
-
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
id: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
7
|
};
|
|
8
8
|
static decision: "snooze";
|
|
9
9
|
}
|
|
@@ -10,10 +10,15 @@ function hasRequestTarget(payload) {
|
|
|
10
10
|
}
|
|
11
11
|
class RequestsCreate extends base_command_1.BaseCommand {
|
|
12
12
|
static description = 'Create a new request';
|
|
13
|
+
// Every example names a recipient: a request without one is refused, so an example that omits it
|
|
14
|
+
// is a command that cannot run (OSK-15375).
|
|
13
15
|
static examples = [
|
|
14
|
-
'<%= config.bin %> requests create --title "Approve budget" --type approval',
|
|
15
|
-
'<%= config.bin %> requests create --title "Q1 review" --type task --description "Review Q1 goals"',
|
|
16
|
-
|
|
16
|
+
'<%= config.bin %> requests create --title "Approve budget" --type approval --target-user <user-id>',
|
|
17
|
+
'<%= config.bin %> requests create --title "Q1 review" --type task --description "Review Q1 goals" --target-agent <agent-id>',
|
|
18
|
+
`cat > request.json <<'JSON'
|
|
19
|
+
{ "title": "Approve budget", "type": "approval", "targetUserId": "<user-id>" }
|
|
20
|
+
JSON
|
|
21
|
+
<%= config.bin %> requests create --from-json request.json`,
|
|
17
22
|
];
|
|
18
23
|
static flags = {
|
|
19
24
|
json: core_1.Flags.boolean({ description: 'Output the created request as JSON' }),
|
|
@@ -29,15 +29,15 @@ class SpacesWorkflowsCreate extends base_command_1.BaseCommand {
|
|
|
29
29
|
title: core_1.Flags.string({ required: true, description: 'Workflow title' }),
|
|
30
30
|
description: core_1.Flags.string({ description: 'Optional description' }),
|
|
31
31
|
graph: core_1.Flags.string({
|
|
32
|
-
description: '
|
|
32
|
+
description: 'One of --graph, --draft or --starter (exactly one): path to graph JSON ({ nodes, edges }); inspect config with spaces workflows node-types',
|
|
33
33
|
exactlyOne: ['graph', 'draft', 'starter'],
|
|
34
34
|
}),
|
|
35
35
|
draft: core_1.Flags.string({
|
|
36
|
-
description: '
|
|
36
|
+
description: 'One of --graph, --draft or --starter (exactly one): path to complete Canvas draft JSON ({ semantic, presentation })',
|
|
37
37
|
exactlyOne: ['graph', 'draft', 'starter'],
|
|
38
38
|
}),
|
|
39
39
|
starter: core_1.Flags.boolean({
|
|
40
|
-
description: '
|
|
40
|
+
description: 'One of --graph, --draft or --starter (exactly one): create a valid one-node starter graph',
|
|
41
41
|
exactlyOne: ['graph', 'draft', 'starter'],
|
|
42
42
|
}),
|
|
43
43
|
json: core_1.Flags.boolean({ description: 'Output JSON' }),
|
|
@@ -38,6 +38,7 @@ const core_1 = require("@oclif/core");
|
|
|
38
38
|
const base_command_1 = require("../../base-command");
|
|
39
39
|
const task_closure_1 = require("../../lib/task-closure");
|
|
40
40
|
const api_fetch_1 = require("../../lib/api-fetch");
|
|
41
|
+
const task_recurrence_outcome_1 = require("../../lib/task-recurrence-outcome");
|
|
41
42
|
const outbox_1 = require("../../lib/outbox");
|
|
42
43
|
const prompt_1 = require("../../lib/prompt");
|
|
43
44
|
const session_task_write_1 = require("../../lib/session-task-write");
|
|
@@ -356,6 +357,9 @@ class TasksComplete extends base_command_1.BaseCommand {
|
|
|
356
357
|
for (const sentence of (0, task_closure_1.closureSnapshotLines)(result.task?.resolution?.closure)) {
|
|
357
358
|
this.log(sentence);
|
|
358
359
|
}
|
|
360
|
+
const recurrenceLine = (0, task_recurrence_outcome_1.recurrenceOutcomeLine)(result.recurrence);
|
|
361
|
+
if (recurrenceLine)
|
|
362
|
+
this.log(recurrenceLine);
|
|
359
363
|
for (const advisory of result.advisories || [])
|
|
360
364
|
this.warn(advisory.message);
|
|
361
365
|
if (url)
|
|
@@ -71,6 +71,8 @@ export default class TasksCreate extends BaseCommand {
|
|
|
71
71
|
per: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
72
72
|
effort: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
73
73
|
risk: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
74
|
+
confidence: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
75
|
+
rationale: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
74
76
|
estimate: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
75
77
|
tag: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
76
78
|
'label-id': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -226,13 +226,27 @@ class TasksCreate extends base_command_1.BaseCommand {
|
|
|
226
226
|
}),
|
|
227
227
|
'start-date': core_1.Flags.string({ description: 'Planned start date (ISO string)' }),
|
|
228
228
|
'due-date': core_1.Flags.string({ description: 'Due date (ISO string)' }),
|
|
229
|
-
savings: core_1.Flags.string({
|
|
229
|
+
savings: core_1.Flags.string({
|
|
230
|
+
description: 'Expected USD savings (requires --per). An estimate you write as a person is recorded as Human confirmed under your name, and an Agent edit is then refused with a 409; an Agent writes an Agent estimate. Re-sending the same values changes nothing.',
|
|
231
|
+
}),
|
|
230
232
|
per: core_1.Flags.string({
|
|
231
233
|
options: ['month', 'year', 'once'],
|
|
232
234
|
description: 'Savings period (requires --savings)',
|
|
233
235
|
}),
|
|
234
|
-
effort: core_1.Flags.string({
|
|
235
|
-
|
|
236
|
+
effort: core_1.Flags.string({
|
|
237
|
+
description: 'Expected effort in hours, nonnegative (part of the estimate; see --savings)',
|
|
238
|
+
}),
|
|
239
|
+
risk: core_1.Flags.string({
|
|
240
|
+
options: ['low', 'medium', 'high'],
|
|
241
|
+
description: 'Expected risk (part of the estimate; see --savings)',
|
|
242
|
+
}),
|
|
243
|
+
confidence: core_1.Flags.string({
|
|
244
|
+
options: ['low', 'medium', 'high'],
|
|
245
|
+
description: 'How sure the estimate is (part of the estimate; see --savings). An earlier confidence stays on the claim until you replace it.',
|
|
246
|
+
}),
|
|
247
|
+
rationale: core_1.Flags.string({
|
|
248
|
+
description: 'Why the estimate is what it is, up to 500 characters (part of the estimate). An earlier rationale stays on the claim, under its new basis, until you replace it.',
|
|
249
|
+
}),
|
|
236
250
|
estimate: core_1.Flags.integer({
|
|
237
251
|
// Names the prerequisite AND how to satisfy it. The first version of this
|
|
238
252
|
// help said the scale was reachable only from the web UI, which was true
|
|
@@ -46,3 +46,5 @@ export default class TasksDeliverableAdd extends BaseCommand {
|
|
|
46
46
|
*/
|
|
47
47
|
private archive;
|
|
48
48
|
}
|
|
49
|
+
/** The sentence for a `--status` an archived copy overrides, or null when nothing was overridden. */
|
|
50
|
+
export declare function statusNotApplied(requestedStatus: string | undefined): string | null;
|
|
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.defaultDeliverableIdempotencyKey = defaultDeliverableIdempotencyKey;
|
|
37
|
+
exports.statusNotApplied = statusNotApplied;
|
|
37
38
|
const fs = __importStar(require("node:fs"));
|
|
38
39
|
const path = __importStar(require("node:path"));
|
|
39
40
|
const core_1 = require("@oclif/core");
|
|
@@ -277,7 +278,15 @@ class TasksDeliverableAdd extends base_command_1.BaseCommand {
|
|
|
277
278
|
`Run skrr tasks deliverable list ${opts.taskId} --json to find the exact version before submitting a Result.`);
|
|
278
279
|
}
|
|
279
280
|
if (opts.json) {
|
|
280
|
-
|
|
281
|
+
// `--status` is overridden for an archived copy, and --json used to say nothing of it: the
|
|
282
|
+
// receipt's observation read `available` and the requested status appeared nowhere (OSK-15437).
|
|
283
|
+
const notes = statusNotApplied(opts.requestedStatus);
|
|
284
|
+
this.log(JSON.stringify({
|
|
285
|
+
...resourceReceipt,
|
|
286
|
+
archived,
|
|
287
|
+
identity: opts.identity,
|
|
288
|
+
...(notes ? { requestedStatus: opts.requestedStatus, notes: [notes] } : {}),
|
|
289
|
+
}, null, 2));
|
|
281
290
|
return true;
|
|
282
291
|
}
|
|
283
292
|
const recorded = resourceReceipt?.link.id
|
|
@@ -286,16 +295,22 @@ class TasksDeliverableAdd extends base_command_1.BaseCommand {
|
|
|
286
295
|
const version = resourceReceipt?.version.id ? `version ${resourceReceipt.version.id}; ` : '';
|
|
287
296
|
this.log(`${recorded} — archived copy ${asset.id} ` +
|
|
288
297
|
`(${version}sha256 pinned; observed available; self reported).`);
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
298
|
+
const notApplied = statusNotApplied(opts.requestedStatus);
|
|
299
|
+
// Not silent: the platform WATCHED these bytes land, which is a stronger
|
|
300
|
+
// and verified statement than the one that was asked for. Who vouched
|
|
301
|
+
// is unchanged — still `self_reported`, still nobody else's word.
|
|
302
|
+
if (notApplied)
|
|
303
|
+
this.log(notApplied);
|
|
295
304
|
return true;
|
|
296
305
|
}
|
|
297
306
|
}
|
|
298
307
|
exports.default = TasksDeliverableAdd;
|
|
308
|
+
/** The sentence for a `--status` an archived copy overrides, or null when nothing was overridden. */
|
|
309
|
+
function statusNotApplied(requestedStatus) {
|
|
310
|
+
return requestedStatus && requestedStatus !== 'available'
|
|
311
|
+
? `--status ${requestedStatus} did not apply: an archived copy is observed available.`
|
|
312
|
+
: null;
|
|
313
|
+
}
|
|
299
314
|
/**
|
|
300
315
|
* The local file a coordinate already names, if it names one. `location` is
|
|
301
316
|
* checked first because it is where the thing IS; `identity` is the fallback
|
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* Which listed Deliverables are an EARLIER version of one that is also listed.
|
|
4
|
+
*
|
|
5
|
+
* v1 and v2 of the same coordinate share a Resource and both read `available`, so nothing said which
|
|
6
|
+
* was current (OSK-15437). The newest observation of a Resource is its current version; a tie, or a
|
|
7
|
+
* row with no observation time, is left unmarked rather than guessed. Returns link id -> the link id
|
|
8
|
+
* of the newer version.
|
|
9
|
+
*/
|
|
10
|
+
export declare function earlierVersions(items: Array<{
|
|
11
|
+
linkId?: string;
|
|
12
|
+
resourceId?: string;
|
|
13
|
+
observedAt?: string;
|
|
14
|
+
}>): Map<string, string>;
|
|
2
15
|
export default class TasksDeliverableList extends BaseCommand {
|
|
3
16
|
static description: string;
|
|
4
17
|
static args: {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.earlierVersions = earlierVersions;
|
|
3
4
|
const core_1 = require("@oclif/core");
|
|
4
5
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
6
|
const base_command_1 = require("../../../base-command");
|
|
@@ -37,6 +38,35 @@ function versionLabel(item) {
|
|
|
37
38
|
const id = (item.resourceVersionId || '').replace(/^wrv_/, '');
|
|
38
39
|
return id ? `version ${id.slice(0, 12)}` : 'version unpinned';
|
|
39
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Which listed Deliverables are an EARLIER version of one that is also listed.
|
|
43
|
+
*
|
|
44
|
+
* v1 and v2 of the same coordinate share a Resource and both read `available`, so nothing said which
|
|
45
|
+
* was current (OSK-15437). The newest observation of a Resource is its current version; a tie, or a
|
|
46
|
+
* row with no observation time, is left unmarked rather than guessed. Returns link id -> the link id
|
|
47
|
+
* of the newer version.
|
|
48
|
+
*/
|
|
49
|
+
function earlierVersions(items) {
|
|
50
|
+
const newest = new Map();
|
|
51
|
+
const times = (item) => Date.parse(item.observedAt ?? '');
|
|
52
|
+
for (const item of items) {
|
|
53
|
+
const at = times(item);
|
|
54
|
+
if (!item.linkId || !item.resourceId || Number.isNaN(at))
|
|
55
|
+
continue;
|
|
56
|
+
const current = newest.get(item.resourceId);
|
|
57
|
+
if (!current || at > current.at)
|
|
58
|
+
newest.set(item.resourceId, { linkId: item.linkId, at });
|
|
59
|
+
}
|
|
60
|
+
const marks = new Map();
|
|
61
|
+
for (const item of items) {
|
|
62
|
+
const at = times(item);
|
|
63
|
+
const latest = item.resourceId ? newest.get(item.resourceId) : undefined;
|
|
64
|
+
if (item.linkId && latest && !Number.isNaN(at) && at < latest.at) {
|
|
65
|
+
marks.set(item.linkId, latest.linkId);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return marks;
|
|
69
|
+
}
|
|
40
70
|
class TasksDeliverableList extends base_command_1.BaseCommand {
|
|
41
71
|
static description = 'List Deliverables with exact version, location, and evidence state';
|
|
42
72
|
static args = {
|
|
@@ -61,11 +91,14 @@ class TasksDeliverableList extends base_command_1.BaseCommand {
|
|
|
61
91
|
return this.log(JSON.stringify(result, null, 2));
|
|
62
92
|
if (!result.data.length)
|
|
63
93
|
return this.log('No Deliverables recorded.');
|
|
94
|
+
const earlier = earlierVersions(result.data);
|
|
64
95
|
for (const item of result.data) {
|
|
96
|
+
const newer = item.linkId ? earlier.get(item.linkId) : undefined;
|
|
65
97
|
this.log(`${item.linkId} · ${item.kind}${item.format ? `/${item.format}` : ''} · ` +
|
|
66
98
|
`${item.title || item.identity || '(untitled)'}\n` +
|
|
67
99
|
` ${item.location || 'no locator'} · ${fidelityLabel(item.versionFidelity)} · ` +
|
|
68
|
-
`${versionLabel(item)} · ${item.status} · ${item.evidenceLevel}`
|
|
100
|
+
`${versionLabel(item)} · ${item.status} · ${item.evidenceLevel}` +
|
|
101
|
+
(newer ? `\n an earlier version of this Deliverable; the newer one is ${newer}` : ''));
|
|
69
102
|
}
|
|
70
103
|
}
|
|
71
104
|
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
4
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
5
|
const base_command_1 = require("../../base-command");
|
|
6
|
+
const task_economics_1 = require("../../lib/task-economics");
|
|
6
7
|
class TasksEconomicsCompare extends base_command_1.BaseCommand {
|
|
7
8
|
static description = 'Show a Task economics estimate beside retained platform readings (no measurement binding is created)';
|
|
8
9
|
static examples = [
|
|
@@ -28,6 +29,11 @@ class TasksEconomicsCompare extends base_command_1.BaseCommand {
|
|
|
28
29
|
async run() {
|
|
29
30
|
this.requireAuth();
|
|
30
31
|
const { args, flags } = await this.parse(TasksEconomicsCompare);
|
|
32
|
+
// Named by flag here; the server names the same faults by parameter (OSK-15368).
|
|
33
|
+
if (flags.fire.length > 2)
|
|
34
|
+
this.error('Give --fire once or twice: at most two readings can be compared.', { exit: 2 });
|
|
35
|
+
if (new Set(flags.fire).size !== flags.fire.length)
|
|
36
|
+
this.error('The two --fire ids must differ.', { exit: 2 });
|
|
31
37
|
const taskRef = await this.resolveEntityRef('task', args.id);
|
|
32
38
|
let response;
|
|
33
39
|
try {
|
|
@@ -45,7 +51,7 @@ class TasksEconomicsCompare extends base_command_1.BaseCommand {
|
|
|
45
51
|
return;
|
|
46
52
|
}
|
|
47
53
|
const readings = response.platformReadings;
|
|
48
|
-
this.log(`Estimate (revision ${response.economicsRevision}): ${
|
|
54
|
+
this.log(`Estimate (revision ${response.economicsRevision}): ${(0, task_economics_1.describeEstimate)(response.economics)}`);
|
|
49
55
|
if (readings.status === 'unavailable') {
|
|
50
56
|
this.log(`Platform readings unavailable: ${readings.reason}`);
|
|
51
57
|
}
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
+
import type { JudgedExpectation } from '@skrr-ai/data-provider';
|
|
1
2
|
import { BaseCommand } from '../../base-command';
|
|
3
|
+
export declare function evidenceGap(expectation: JudgedExpectation): string;
|
|
4
|
+
/**
|
|
5
|
+
* A judgement made about a Result that is no longer the current one (OSK-15431).
|
|
6
|
+
*
|
|
7
|
+
* An assessment stands for the specification, not for one Result, so submitting a superseding Result
|
|
8
|
+
* does not retire it, and the count after the v2 submit included judgements of v1 with nothing to say
|
|
9
|
+
* so. Only true when the assessment named a Result and the Task has a different current one.
|
|
10
|
+
*/
|
|
11
|
+
export declare function judgedOnEarlierResult(expectation: JudgedExpectation, currentResultId: string | null | undefined): boolean;
|
|
2
12
|
export default class TasksExpectations extends BaseCommand {
|
|
3
13
|
static description: string;
|
|
4
14
|
static examples: string[];
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.evidenceGap = evidenceGap;
|
|
4
|
+
exports.judgedOnEarlierResult = judgedOnEarlierResult;
|
|
3
5
|
const core_1 = require("@oclif/core");
|
|
4
6
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
7
|
const data_provider_2 = require("@skrr-ai/data-provider");
|
|
@@ -59,6 +61,11 @@ function evidenceGap(expectation) {
|
|
|
59
61
|
const { provided, required } = expectation.evidenceShortfall;
|
|
60
62
|
return ` (vouched at ${provided}, asked for ${required})`;
|
|
61
63
|
}
|
|
64
|
+
// `owed` reads "not produced yet"; when a deliverable of the right kind is recorded but does not
|
|
65
|
+
// qualify, say why instead of implying nothing was produced (OSK-15457).
|
|
66
|
+
if (expectation.state === 'owed' && expectation.nearMiss) {
|
|
67
|
+
return ` (one was recorded, but ${expectation.nearMiss})`;
|
|
68
|
+
}
|
|
62
69
|
if (!PINNED_STATES.has(expectation.state))
|
|
63
70
|
return '';
|
|
64
71
|
if (!expectation.evidenceLevel || !expectation.requiredEvidence)
|
|
@@ -85,7 +92,19 @@ function assessorSuffix(expectation) {
|
|
|
85
92
|
return '';
|
|
86
93
|
return ` (${(0, task_closure_1.describeAssessor)(expectation.assessedByKind)})`;
|
|
87
94
|
}
|
|
88
|
-
|
|
95
|
+
/**
|
|
96
|
+
* A judgement made about a Result that is no longer the current one (OSK-15431).
|
|
97
|
+
*
|
|
98
|
+
* An assessment stands for the specification, not for one Result, so submitting a superseding Result
|
|
99
|
+
* does not retire it, and the count after the v2 submit included judgements of v1 with nothing to say
|
|
100
|
+
* so. Only true when the assessment named a Result and the Task has a different current one.
|
|
101
|
+
*/
|
|
102
|
+
function judgedOnEarlierResult(expectation, currentResultId) {
|
|
103
|
+
return Boolean(expectation.assessedResultId &&
|
|
104
|
+
currentResultId &&
|
|
105
|
+
expectation.assessedResultId !== currentResultId);
|
|
106
|
+
}
|
|
107
|
+
function line(expectation, currentResultId) {
|
|
89
108
|
const label = (STATE_LABEL[expectation.state] || expectation.state) + assessorSuffix(expectation);
|
|
90
109
|
const from = expectation.source === 'space' ? ' [space default]' : '';
|
|
91
110
|
/*
|
|
@@ -98,7 +117,10 @@ function line(expectation) {
|
|
|
98
117
|
* thing is owed. The fallback is for a row that predates the resolved field.
|
|
99
118
|
*/
|
|
100
119
|
const sentence = expectation.sentence || expectation.text;
|
|
101
|
-
|
|
120
|
+
const earlier = judgedOnEarlierResult(expectation, currentResultId)
|
|
121
|
+
? ' (judged on an earlier Result)'
|
|
122
|
+
: '';
|
|
123
|
+
return ` ${expectation.id.padEnd(18)} ${label.padEnd(22)} ${sentence}${evidenceGap(expectation)}${earlier}${from}`;
|
|
102
124
|
}
|
|
103
125
|
class TasksExpectations extends base_command_1.BaseCommand {
|
|
104
126
|
static description = 'Show what must be true before the Task can close and the evidence-backed assessment state';
|
|
@@ -142,7 +164,13 @@ class TasksExpectations extends base_command_1.BaseCommand {
|
|
|
142
164
|
}
|
|
143
165
|
this.log('Expectations:');
|
|
144
166
|
for (const expectation of acceptance.expectations) {
|
|
145
|
-
this.log(line(expectation));
|
|
167
|
+
this.log(line(expectation, acceptance.currentResultId));
|
|
168
|
+
}
|
|
169
|
+
const carried = acceptance.expectations.filter((e) => judgedOnEarlierResult(e, acceptance.currentResultId)).length;
|
|
170
|
+
if (carried > 0) {
|
|
171
|
+
this.log(`${carried} judgement${carried === 1 ? ' was' : 's were'} made on an earlier Result. ` +
|
|
172
|
+
`${carried === 1 ? 'It still counts' : 'They still count'}: an assessment stands for the ` +
|
|
173
|
+
'Task specification, not for one Result. Re-assess if the current Result changes the answer.');
|
|
146
174
|
}
|
|
147
175
|
const gating = acceptance.expectations.filter((e) => e.gating);
|
|
148
176
|
// `met: true` is the GATE's answer — a waiver unblocks closure exactly as a
|
|
@@ -35,6 +35,15 @@ export declare function emptyTasksMessage(flags: ListFlags, bin?: string): strin
|
|
|
35
35
|
* naming the stage sat unread in the same payload.
|
|
36
36
|
*/
|
|
37
37
|
export declare function nextActionText(t: Record<string, unknown>): string;
|
|
38
|
+
/**
|
|
39
|
+
* The NEXT column's width. Bounded, because a sentence in an unbounded column wraps the table into
|
|
40
|
+
* unreadability on a narrow terminal, but widened when a row says what a Task was closed over: the
|
|
41
|
+
* two things it names come last in the sentence, and a column cut before them hid exactly the
|
|
42
|
+
* disclosure the row exists to make (OSK-15429).
|
|
43
|
+
*/
|
|
44
|
+
export declare function nextColumnWidth(rows: Array<{
|
|
45
|
+
next: string;
|
|
46
|
+
}>): number;
|
|
38
47
|
/**
|
|
39
48
|
* The REF column's value, aliased to `ref` under `--json` because `identifier`
|
|
40
49
|
* is the one name an agent scanning 43 keys does not guess (OSK-10692).
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.agentSessionOpenDefault = agentSessionOpenDefault;
|
|
4
4
|
exports.emptyTasksMessage = emptyTasksMessage;
|
|
5
5
|
exports.nextActionText = nextActionText;
|
|
6
|
+
exports.nextColumnWidth = nextColumnWidth;
|
|
6
7
|
exports.taskRef = taskRef;
|
|
7
8
|
exports.buildListParams = buildListParams;
|
|
8
9
|
exports.statusFilterWarnings = statusFilterWarnings;
|
|
@@ -13,6 +14,7 @@ const web_url_1 = require("../../lib/web-url");
|
|
|
13
14
|
const format_1 = require("../../lib/format");
|
|
14
15
|
const list_output_1 = require("../../lib/list-output");
|
|
15
16
|
const tasks_1 = require("../../lib/tasks");
|
|
17
|
+
const task_economics_1 = require("../../lib/task-economics");
|
|
16
18
|
/**
|
|
17
19
|
* Names of `tasks list` flags that narrow the result set. Used to distinguish
|
|
18
20
|
* "no tasks anywhere" from "no tasks matching your filters" — the first case
|
|
@@ -174,9 +176,38 @@ function statusTypeList(flags) {
|
|
|
174
176
|
*/
|
|
175
177
|
function nextActionText(t) {
|
|
176
178
|
const actionability = t.actionability;
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
179
|
+
if (!actionability)
|
|
180
|
+
return String(t.executionMode ?? '-');
|
|
181
|
+
// A finished Task has no next action, which is all this column said about one closed over unmet
|
|
182
|
+
// Expectations, a missing required Review, or past a Review by explicit force ("none: Task workflow
|
|
183
|
+
// type is completed"). The list row already carries the persisted closure snapshot, so say what it
|
|
184
|
+
// was closed over with the shared renderer (OSK-15429). Only when something is owed or overridden:
|
|
185
|
+
// a clean close reads as before.
|
|
186
|
+
if (actionability.state === 'terminal') {
|
|
187
|
+
const closed = closedOverText(t);
|
|
188
|
+
if (closed)
|
|
189
|
+
return `${String(actionability.nextActor ?? '-')}: closed. ${closed}`;
|
|
190
|
+
}
|
|
191
|
+
return `${String(actionability.nextActor ?? '-')}: ${String(actionability.reason || actionability.reasonCode || actionability.state || '-')}`;
|
|
192
|
+
}
|
|
193
|
+
/** What a finished Task's persisted closure snapshot says was overridden or is still owed, or null. */
|
|
194
|
+
function closedOverText(t) {
|
|
195
|
+
const closure = t.resolution?.closure;
|
|
196
|
+
const outstanding = (0, data_provider_1.describeClosureOutstanding)(closure);
|
|
197
|
+
const parts = [
|
|
198
|
+
...(0, data_provider_1.describeClosureOverrides)(closure),
|
|
199
|
+
...(outstanding ? [`Outstanding at close: ${outstanding}.`] : []),
|
|
200
|
+
];
|
|
201
|
+
return parts.length > 0 ? parts.join(' ') : null;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* The NEXT column's width. Bounded, because a sentence in an unbounded column wraps the table into
|
|
205
|
+
* unreadability on a narrow terminal, but widened when a row says what a Task was closed over: the
|
|
206
|
+
* two things it names come last in the sentence, and a column cut before them hid exactly the
|
|
207
|
+
* disclosure the row exists to make (OSK-15429).
|
|
208
|
+
*/
|
|
209
|
+
function nextColumnWidth(rows) {
|
|
210
|
+
return rows.some((row) => row.next.includes(': closed. ')) ? 140 : 46;
|
|
180
211
|
}
|
|
181
212
|
/**
|
|
182
213
|
* The REF column's value, aliased to `ref` under `--json` because `identifier`
|
|
@@ -647,6 +678,7 @@ class TasksList extends base_command_1.BaseCommand {
|
|
|
647
678
|
: 'Unknown',
|
|
648
679
|
effort: economics?.effortHours !== undefined ? `${economics.effortHours}h` : 'Unknown',
|
|
649
680
|
risk: economics?.risk ?? 'Unknown',
|
|
681
|
+
score: (0, task_economics_1.economicsScoreText)(economics),
|
|
650
682
|
basis: economics?.basis && Object.prototype.hasOwnProperty.call(basis, economics.basis)
|
|
651
683
|
? basis[economics.basis]
|
|
652
684
|
: 'Unknown',
|
|
@@ -662,6 +694,7 @@ class TasksList extends base_command_1.BaseCommand {
|
|
|
662
694
|
{ key: 'savings', header: 'SAVINGS' },
|
|
663
695
|
{ key: 'effort', header: 'EFFORT' },
|
|
664
696
|
{ key: 'risk', header: 'RISK' },
|
|
697
|
+
{ key: 'score', header: 'SCORE' },
|
|
665
698
|
{ key: 'basis', header: 'BASIS' },
|
|
666
699
|
]
|
|
667
700
|
: []),
|
|
@@ -669,14 +702,16 @@ class TasksList extends base_command_1.BaseCommand {
|
|
|
669
702
|
{ key: 'assignees', header: 'ASSIGNEES' },
|
|
670
703
|
// Bounded: the reason is a sentence, and an unbounded column wraps the
|
|
671
704
|
// table into unreadability on a narrow terminal.
|
|
672
|
-
{ key: 'next', header: 'NEXT', maxWidth:
|
|
705
|
+
{ key: 'next', header: 'NEXT', maxWidth: nextColumnWidth(rows) },
|
|
673
706
|
// Only meaningful on a search — the server computes it from the same
|
|
674
707
|
// relevance rank that orders the rows, and a plain listing has none.
|
|
675
708
|
...(flags.q ? [{ key: 'match', header: 'MATCH' }] : []),
|
|
676
709
|
{ key: 'id', header: 'ID' },
|
|
677
710
|
], (line) => this.log(line));
|
|
678
711
|
if (flags.rank)
|
|
679
|
-
this.log('\nRanked only within this fetched page; estimates are claims, not measured savings
|
|
712
|
+
this.log('\nRanked only within this fetched page; estimates are claims, not measured savings.\n' +
|
|
713
|
+
'SCORE = annualized USD savings / max(effort hours, 0.5) x risk factor (low 1, medium 0.6, high 0.25); ' +
|
|
714
|
+
'— means savings, effort or risk is missing, so the row is not scored and sorts last.');
|
|
680
715
|
if (r?.next_cursor) {
|
|
681
716
|
this.log('');
|
|
682
717
|
this.log(`Next page: --cursor ${r.next_cursor}`);
|
|
@@ -171,7 +171,7 @@ class TasksReport extends base_command_1.BaseCommand {
|
|
|
171
171
|
this.log(JSON.stringify({ ...result, url }, null, 2));
|
|
172
172
|
return;
|
|
173
173
|
}
|
|
174
|
-
this.log(`Submitted Result v${result.result.version} on task ${task.id}.${url ? ` ${url}` : ''}`);
|
|
174
|
+
this.log(`Submitted Result v${result.result.version} (${result.result.id}) on task ${task.id}.${url ? ` ${url}` : ''}`);
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
177
|
exports.default = TasksReport;
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
+
import type { TaskResultRecord } from '@skrr-ai/data-provider';
|
|
1
2
|
import { BaseCommand } from '../../../base-command';
|
|
3
|
+
/**
|
|
4
|
+
* What a reviewer needs to accept ONE exact Result (OSK-15430). `result show` printed the summary and
|
|
5
|
+
* the conclusion, and kept the Result id (the value `tasks review --result-id` requires), the linked
|
|
6
|
+
* deliverables, the evidence, the remaining work and the Result it supersedes for `--json`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function describeResultDetail(current: TaskResultRecord, all?: TaskResultRecord[]): string[];
|
|
2
9
|
export default class TasksResultShow extends BaseCommand {
|
|
3
10
|
static description: string;
|
|
4
11
|
static args: {
|
|
@@ -1,10 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.describeResultDetail = describeResultDetail;
|
|
3
4
|
const core_1 = require("@oclif/core");
|
|
4
5
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
5
6
|
const base_command_1 = require("../../../base-command");
|
|
6
7
|
const task_resolver_1 = require("../../../lib/task-resolver");
|
|
7
8
|
const task_legacy_1 = require("../../../lib/task-legacy");
|
|
9
|
+
/**
|
|
10
|
+
* What a reviewer needs to accept ONE exact Result (OSK-15430). `result show` printed the summary and
|
|
11
|
+
* the conclusion, and kept the Result id (the value `tasks review --result-id` requires), the linked
|
|
12
|
+
* deliverables, the evidence, the remaining work and the Result it supersedes for `--json`.
|
|
13
|
+
*/
|
|
14
|
+
function describeResultDetail(current, all = []) {
|
|
15
|
+
const lines = [];
|
|
16
|
+
if (current.supersedesResultId) {
|
|
17
|
+
const previous = all.find((row) => row.id === current.supersedesResultId);
|
|
18
|
+
lines.push(`Supersedes: ${current.supersedesResultId}${previous ? ` (v${previous.version})` : ''}`);
|
|
19
|
+
}
|
|
20
|
+
const links = current.resourceLinkIds ?? [];
|
|
21
|
+
lines.push(`Deliverables: ${links.length > 0 ? links.join(', ') : 'none linked'}`);
|
|
22
|
+
const evidence = current.evidenceRefs ?? [];
|
|
23
|
+
lines.push(`Evidence: ${evidence.length > 0
|
|
24
|
+
? evidence.map((ref) => `${ref.kind}:${ref.id}`).join(', ')
|
|
25
|
+
: 'none attached'}`);
|
|
26
|
+
const remaining = current.remainingWork ?? [];
|
|
27
|
+
if (remaining.length > 0) {
|
|
28
|
+
lines.push('Remaining work:');
|
|
29
|
+
for (const item of remaining)
|
|
30
|
+
lines.push(` - ${item.summary}`);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
lines.push('Remaining work: none declared');
|
|
34
|
+
}
|
|
35
|
+
return lines;
|
|
36
|
+
}
|
|
8
37
|
class TasksResultShow extends base_command_1.BaseCommand {
|
|
9
38
|
static description = 'Show the current Task Result and its exact Review';
|
|
10
39
|
static args = {
|
|
@@ -32,9 +61,11 @@ class TasksResultShow extends base_command_1.BaseCommand {
|
|
|
32
61
|
if (!current)
|
|
33
62
|
return this.log(await (0, task_legacy_1.emptyCanonicalView)(task.id, 'Result'));
|
|
34
63
|
const review = result.reviews.find((row) => row.resultId === current.id);
|
|
35
|
-
this.log(`Result v${current.version}\n${current.summary}`);
|
|
64
|
+
this.log(`Result v${current.version} ${current.id}\n${current.summary}`);
|
|
36
65
|
if (current.conclusion)
|
|
37
66
|
this.log(`Conclusion (${current.conclusion.type}): ${JSON.stringify(current.conclusion.value)}`);
|
|
67
|
+
for (const line of describeResultDetail(current, result.results))
|
|
68
|
+
this.log(line);
|
|
38
69
|
// Only "awaiting" while a review can still be recorded. A closed Task
|
|
39
70
|
// refuses one outright (`TASK_REOPEN_REQUIRED`), so the old wording named a
|
|
40
71
|
// state nothing could ever leave — and a reader could not tell it from a
|
|
@@ -211,7 +211,7 @@ class TasksResultSubmit extends base_command_1.BaseCommand {
|
|
|
211
211
|
// managed instructions told the agent to read the status the call returns,
|
|
212
212
|
// which the call did not carry. Submitting a Result is not closing a Task;
|
|
213
213
|
// the response now reports where it stands and this prints exactly that.
|
|
214
|
-
this.log(`Submitted Result v${result.result.version} for ${task.id}.`);
|
|
214
|
+
this.log(`Submitted Result v${result.result.version} (${result.result.id}) for ${task.id}.`);
|
|
215
215
|
for (const line of (0, task_closure_1.closureReport)(result.closure, { closing: false }))
|
|
216
216
|
this.log(line);
|
|
217
217
|
if (url)
|
|
@@ -50,6 +50,12 @@ export declare function completionLines(projection: {
|
|
|
50
50
|
} | null | undefined, { read }?: {
|
|
51
51
|
read?: boolean;
|
|
52
52
|
}): string[];
|
|
53
|
+
/**
|
|
54
|
+
* The review-policy line, or null for the default. Only a non-default policy is printed: `none` is
|
|
55
|
+
* every Task that never asked, and printing it would add a line to all of them. Without this the
|
|
56
|
+
* policy was readable in --json alone (OSK-15434).
|
|
57
|
+
*/
|
|
58
|
+
export declare function reviewPolicyLine(policy: unknown): string | null;
|
|
53
59
|
export declare function labelsLine(labelIds?: string[], nameById?: Map<string, string>): string;
|
|
54
60
|
/**
|
|
55
61
|
* The `Executor:` value — who does this task, and whether anyone said so.
|