@skrr-ai/cli 0.1.108 → 0.1.110
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/README.md +10 -0
- package/dist/base-command.d.ts +74 -0
- package/dist/base-command.js +182 -24
- package/dist/commands/agents/triggers/create.js +1 -1
- package/dist/commands/agents/triggers/update.js +1 -1
- package/dist/commands/agents/update.d.ts +25 -0
- package/dist/commands/agents/update.js +98 -3
- package/dist/commands/commitments/accounting.js +7 -2
- package/dist/commands/commitments/cost.d.ts +11 -0
- package/dist/commands/commitments/cost.js +26 -3
- package/dist/commands/commitments/create.js +2 -1
- package/dist/commands/commitments/operating-review.d.ts +15 -0
- package/dist/commands/commitments/operating-review.js +103 -50
- package/dist/commands/commitments/update.js +12 -5
- package/dist/commands/daemon/install.js +17 -1
- package/dist/commands/daemon/login.js +14 -0
- package/dist/commands/doctor.js +9 -0
- package/dist/commands/goals/list.js +6 -1
- package/dist/commands/grants/rotate.js +4 -0
- package/dist/commands/harnesses/prune.d.ts +26 -0
- package/dist/commands/harnesses/prune.js +172 -0
- package/dist/commands/login.js +53 -14
- package/dist/commands/machines/list.js +28 -6
- package/dist/commands/projects/show.js +1 -1
- package/dist/commands/revoke-daemon.js +2 -1
- package/dist/commands/spaces/workflows/archive.d.ts +1 -0
- package/dist/commands/spaces/workflows/archive.js +1 -0
- package/dist/commands/spaces/workflows/artifact.d.ts +1 -0
- package/dist/commands/spaces/workflows/artifact.js +1 -0
- package/dist/commands/spaces/workflows/cancel-node.d.ts +1 -0
- package/dist/commands/spaces/workflows/cancel-node.js +1 -0
- package/dist/commands/spaces/workflows/cancel.d.ts +1 -0
- package/dist/commands/spaces/workflows/cancel.js +6 -2
- package/dist/commands/spaces/workflows/create.d.ts +1 -0
- package/dist/commands/spaces/workflows/create.js +7 -1
- package/dist/commands/spaces/workflows/events.d.ts +1 -0
- package/dist/commands/spaces/workflows/events.js +1 -0
- package/dist/commands/spaces/workflows/fixtures/create.d.ts +1 -0
- package/dist/commands/spaces/workflows/fixtures/create.js +1 -0
- package/dist/commands/spaces/workflows/fixtures/list.d.ts +1 -0
- package/dist/commands/spaces/workflows/fixtures/list.js +1 -0
- package/dist/commands/spaces/workflows/lifecycle-diagnostics.d.ts +1 -0
- package/dist/commands/spaces/workflows/lifecycle-diagnostics.js +1 -0
- package/dist/commands/spaces/workflows/list.d.ts +1 -0
- package/dist/commands/spaces/workflows/list.js +1 -0
- package/dist/commands/spaces/workflows/node-types.d.ts +2 -0
- package/dist/commands/spaces/workflows/node-types.js +24 -6
- package/dist/commands/spaces/workflows/pause.d.ts +1 -0
- package/dist/commands/spaces/workflows/pause.js +1 -0
- package/dist/commands/spaces/workflows/plan/show.d.ts +1 -0
- package/dist/commands/spaces/workflows/plan/show.js +1 -0
- package/dist/commands/spaces/workflows/plan/update.d.ts +1 -0
- package/dist/commands/spaces/workflows/plan/update.js +1 -0
- package/dist/commands/spaces/workflows/proposals/apply.d.ts +1 -0
- package/dist/commands/spaces/workflows/proposals/apply.js +1 -0
- package/dist/commands/spaces/workflows/proposals/confirm.d.ts +1 -0
- package/dist/commands/spaces/workflows/proposals/confirm.js +1 -0
- package/dist/commands/spaces/workflows/proposals/create.d.ts +1 -0
- package/dist/commands/spaces/workflows/proposals/create.js +1 -0
- package/dist/commands/spaces/workflows/proposals/dismiss.d.ts +1 -0
- package/dist/commands/spaces/workflows/proposals/dismiss.js +1 -0
- package/dist/commands/spaces/workflows/proposals/list.d.ts +1 -0
- package/dist/commands/spaces/workflows/proposals/list.js +1 -0
- package/dist/commands/spaces/workflows/publish.d.ts +1 -0
- package/dist/commands/spaces/workflows/publish.js +9 -0
- package/dist/commands/spaces/workflows/reconcile.d.ts +1 -0
- package/dist/commands/spaces/workflows/reconcile.js +1 -0
- package/dist/commands/spaces/workflows/resume.d.ts +1 -0
- package/dist/commands/spaces/workflows/resume.js +1 -0
- package/dist/commands/spaces/workflows/retry.d.ts +1 -0
- package/dist/commands/spaces/workflows/retry.js +1 -0
- package/dist/commands/spaces/workflows/run.d.ts +1 -0
- package/dist/commands/spaces/workflows/run.js +14 -7
- package/dist/commands/spaces/workflows/runs.d.ts +1 -0
- package/dist/commands/spaces/workflows/runs.js +1 -0
- package/dist/commands/spaces/workflows/show.d.ts +25 -0
- package/dist/commands/spaces/workflows/show.js +42 -4
- package/dist/commands/spaces/workflows/signal.d.ts +12 -0
- package/dist/commands/spaces/workflows/signal.js +40 -2
- package/dist/commands/spaces/workflows/start.d.ts +1 -0
- package/dist/commands/spaces/workflows/start.js +4 -1
- package/dist/commands/spaces/workflows/task-execution/create.d.ts +1 -0
- package/dist/commands/spaces/workflows/task-execution/create.js +1 -0
- package/dist/commands/spaces/workflows/test.d.ts +1 -0
- package/dist/commands/spaces/workflows/test.js +1 -0
- package/dist/commands/spaces/workflows/triggers/create.d.ts +1 -0
- package/dist/commands/spaces/workflows/triggers/create.js +1 -0
- package/dist/commands/spaces/workflows/triggers/fire.d.ts +1 -0
- package/dist/commands/spaces/workflows/triggers/fire.js +1 -0
- package/dist/commands/spaces/workflows/triggers/list.d.ts +1 -0
- package/dist/commands/spaces/workflows/triggers/list.js +1 -0
- package/dist/commands/spaces/workflows/triggers/update.d.ts +1 -0
- package/dist/commands/spaces/workflows/triggers/update.js +1 -0
- package/dist/commands/spaces/workflows/update.d.ts +1 -0
- package/dist/commands/spaces/workflows/update.js +4 -0
- package/dist/commands/spaces/workflows/validate.d.ts +1 -0
- package/dist/commands/spaces/workflows/validate.js +27 -2
- package/dist/commands/tasks/activity.js +17 -3
- package/dist/commands/tasks/bulk-update.d.ts +1 -0
- package/dist/commands/tasks/bulk-update.js +7 -0
- package/dist/commands/tasks/complete.js +2 -1
- package/dist/commands/tasks/create-tree.d.ts +69 -0
- package/dist/commands/tasks/create-tree.js +413 -47
- package/dist/commands/tasks/list.d.ts +2 -0
- package/dist/commands/tasks/list.js +25 -3
- package/dist/commands/tasks/rearm-recurrence.d.ts +22 -0
- package/dist/commands/tasks/rearm-recurrence.js +87 -0
- package/dist/commands/tasks/show.d.ts +9 -0
- package/dist/commands/tasks/show.js +79 -33
- package/dist/commands/tasks/timeline.js +4 -0
- package/dist/commands/tasks/unschedule.js +5 -1
- package/dist/commands/tasks/update.d.ts +1 -0
- package/dist/commands/tasks/update.js +17 -2
- package/dist/commands/triggers/audit.js +12 -3
- package/dist/commands/triggers/create.js +9 -3
- package/dist/commands/triggers/fire-detail.d.ts +7 -0
- package/dist/commands/triggers/fire-detail.js +30 -12
- package/dist/commands/triggers/fire.js +13 -3
- package/dist/commands/triggers/parse-intent.d.ts +7 -0
- package/dist/commands/triggers/parse-intent.js +31 -9
- package/dist/commands/triggers/update.js +1 -1
- package/dist/commands/workspaces/grants.js +20 -3
- package/dist/commands/workspaces/members.d.ts +20 -0
- package/dist/commands/workspaces/members.js +64 -0
- package/dist/commands/workspaces/stewardship.js +14 -2
- package/dist/help.js +12 -0
- package/dist/hooks/command-not-found.js +27 -1
- package/dist/lib/command-miss.d.ts +52 -2
- package/dist/lib/command-miss.js +187 -18
- package/dist/lib/commitment-loop-status.d.ts +8 -0
- package/dist/lib/commitment-loop-status.js +45 -0
- package/dist/lib/commitment-product.js +5 -2
- package/dist/lib/commitments.d.ts +18 -3
- package/dist/lib/commitments.js +85 -45
- package/dist/lib/daemon-command-hint.d.ts +15 -0
- package/dist/lib/daemon-command-hint.js +21 -0
- package/dist/lib/daemon-machine-identity-copy.d.ts +14 -0
- package/dist/lib/daemon-machine-identity-copy.js +27 -0
- package/dist/lib/daemon-machine-identity.d.ts +27 -0
- package/dist/lib/daemon-machine-identity.js +61 -0
- package/dist/lib/daemon-setup.js +10 -1
- package/dist/lib/daemonBrokerRefusal.js +3 -2
- package/dist/lib/daemonHandoff.d.ts +19 -1
- package/dist/lib/daemonHandoff.js +61 -1
- package/dist/lib/deployed-build.d.ts +43 -0
- package/dist/lib/deployed-build.js +66 -0
- package/dist/lib/grants.d.ts +27 -1
- package/dist/lib/grants.js +39 -21
- package/dist/lib/harnesses.d.ts +71 -0
- package/dist/lib/harnesses.js +70 -0
- package/dist/lib/json-mode.d.ts +11 -0
- package/dist/lib/json-mode.js +19 -0
- package/dist/lib/json-output.d.ts +25 -0
- package/dist/lib/json-output.js +30 -0
- package/dist/lib/list-output.d.ts +10 -1
- package/dist/lib/list-output.js +22 -1
- package/dist/lib/local-daemon-readiness.d.ts +90 -0
- package/dist/lib/local-daemon-readiness.js +143 -0
- package/dist/lib/machines.d.ts +117 -0
- package/dist/lib/machines.js +139 -0
- package/dist/lib/managed-instruction-local.d.ts +2 -0
- package/dist/lib/managed-instruction-local.js +2 -0
- package/dist/lib/profile-machine-identity-guard.d.ts +18 -0
- package/dist/lib/profile-machine-identity-guard.js +39 -0
- package/dist/lib/request-field-flags.d.ts +20 -0
- package/dist/lib/request-field-flags.js +34 -0
- package/dist/lib/stewardship-output.d.ts +1 -1
- package/dist/lib/stewardship-output.js +26 -30
- package/dist/lib/task-batch.d.ts +61 -4
- package/dist/lib/task-batch.js +316 -80
- package/dist/lib/task-economics.d.ts +15 -0
- package/dist/lib/task-economics.js +39 -2
- package/dist/lib/task-recurrence-outcome.d.ts +6 -6
- package/dist/lib/task-recurrence-outcome.js +27 -3
- package/dist/lib/tasks.d.ts +39 -0
- package/dist/lib/tasks.js +132 -0
- package/dist/lib/triggers.d.ts +42 -1
- package/dist/lib/triggers.js +98 -2
- package/dist/lib/workflow-issues.d.ts +14 -0
- package/dist/lib/workflow-issues.js +32 -0
- package/dist/lib/workflow-run-view.d.ts +59 -0
- package/dist/lib/workflow-run-view.js +110 -0
- package/dist/lib/workspaces.d.ts +48 -4
- package/dist/lib/workspaces.js +55 -0
- package/dist/lib/write-target.d.ts +29 -0
- package/dist/lib/write-target.js +72 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +5 -3
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.d.ts +60 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.js +130 -6
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/workspaceIsolationProbeWire.d.ts +51 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/workspaceIsolationProbeWire.js +50 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.d.ts +60 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.js +128 -6
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/workspaceIsolationProbeWire.d.ts +51 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/workspaceIsolationProbeWire.js +46 -0
- package/dist/node_modules/@skrr-ai/auth-core/package.json +11 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +7523 -7140
- package/oclif.manifest.json +473 -59
- package/package.json +28 -1
|
@@ -105,6 +105,8 @@ export default class TasksList extends BaseCommand {
|
|
|
105
105
|
subscribed: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
106
106
|
'include-snoozed': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
107
107
|
'external-key': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
108
|
+
'external-key-prefix': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
109
|
+
'description-format': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
108
110
|
tag: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
109
111
|
'label-id': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
110
112
|
q: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -48,6 +48,7 @@ const FILTER_FLAGS = new Set([
|
|
|
48
48
|
'subscribed',
|
|
49
49
|
'include-snoozed',
|
|
50
50
|
'external-key',
|
|
51
|
+
'external-key-prefix',
|
|
51
52
|
'blocked-by',
|
|
52
53
|
'blocks',
|
|
53
54
|
'due-before',
|
|
@@ -286,6 +287,13 @@ function buildListParams(flags, assigneeUserId) {
|
|
|
286
287
|
...(flag('external-key')
|
|
287
288
|
? { externalKey: flag('external-key') }
|
|
288
289
|
: {}),
|
|
290
|
+
...(flag('external-key-prefix')
|
|
291
|
+
? { externalKeyPrefix: flag('external-key-prefix') }
|
|
292
|
+
: {}),
|
|
293
|
+
// A presentation of each row, not a filter: it is deliberately not in FILTER_FLAGS.
|
|
294
|
+
...(flag('description-format') === 'markdown'
|
|
295
|
+
? { descriptionFormat: 'markdown' }
|
|
296
|
+
: {}),
|
|
289
297
|
...(flag('blocked-by') ? { blockedBy: flag('blocked-by') } : {}),
|
|
290
298
|
...(flag('blocks') ? { blocks: flag('blocks') } : {}),
|
|
291
299
|
...(flag('due-before') ? { dueBefore: flag('due-before') } : {}),
|
|
@@ -469,6 +477,13 @@ class TasksList extends base_command_1.BaseCommand {
|
|
|
469
477
|
description: 'Include tasks you have personally snoozed (hidden by default)',
|
|
470
478
|
}),
|
|
471
479
|
'external-key': core_1.Flags.string({ description: 'Filter by external key' }),
|
|
480
|
+
'external-key-prefix': core_1.Flags.string({
|
|
481
|
+
description: 'Filter to tasks whose external key starts with this literal prefix, e.g. every task of one tree written under --external-key-prefix. Combine with --space; see also `tasks create-tree --verify`.',
|
|
482
|
+
}),
|
|
483
|
+
'description-format': core_1.Flags.string({
|
|
484
|
+
description: 'JSON/text: how to read each description. html (default) is what is stored; markdown returns it as it was written, so a description you wrote compares equal to the one you read back.',
|
|
485
|
+
options: ['html', 'markdown'],
|
|
486
|
+
}),
|
|
472
487
|
tag: core_1.Flags.string({
|
|
473
488
|
description: 'Filter to tasks carrying EVERY listed tag (repeatable, AND-intersection, ' +
|
|
474
489
|
'case-insensitive)',
|
|
@@ -573,7 +588,9 @@ class TasksList extends base_command_1.BaseCommand {
|
|
|
573
588
|
Array.isArray(response.data)) {
|
|
574
589
|
response = {
|
|
575
590
|
...response,
|
|
576
|
-
|
|
591
|
+
// Each row carries the `economicsRank` it was sorted by, so `--json` shows the same SCORE
|
|
592
|
+
// as the table, computed once in the shared ranking (OSK-16476).
|
|
593
|
+
data: (0, data_provider_1.annotateEconomicRank)(response.data),
|
|
577
594
|
rank_applied: { key: 'economics', scope: 'fetched_page' },
|
|
578
595
|
};
|
|
579
596
|
}
|
|
@@ -678,7 +695,9 @@ class TasksList extends base_command_1.BaseCommand {
|
|
|
678
695
|
: 'Unknown',
|
|
679
696
|
effort: economics?.effortHours !== undefined ? `${economics.effortHours}h` : 'Unknown',
|
|
680
697
|
risk: economics?.risk ?? 'Unknown',
|
|
681
|
-
score:
|
|
698
|
+
score: t.economicsRank
|
|
699
|
+
? (0, task_economics_1.scoreText)(t.economicsRank.score)
|
|
700
|
+
: (0, task_economics_1.economicsScoreText)(economics),
|
|
682
701
|
basis: economics?.basis && Object.prototype.hasOwnProperty.call(basis, economics.basis)
|
|
683
702
|
? basis[economics.basis]
|
|
684
703
|
: 'Unknown',
|
|
@@ -711,7 +730,8 @@ class TasksList extends base_command_1.BaseCommand {
|
|
|
711
730
|
if (flags.rank)
|
|
712
731
|
this.log('\nRanked only within this fetched page; estimates are claims, not measured savings.\n' +
|
|
713
732
|
'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
|
|
733
|
+
'— means savings, effort or risk is missing (or outside the plausible range), so the row is not scored ' +
|
|
734
|
+
'and sorts after every scored row: larger stated savings first, then rows with no estimate.');
|
|
715
735
|
if (r?.next_cursor) {
|
|
716
736
|
this.log('');
|
|
717
737
|
this.log(`Next page: --cursor ${r.next_cursor}`);
|
|
@@ -719,6 +739,8 @@ class TasksList extends base_command_1.BaseCommand {
|
|
|
719
739
|
const note = (0, list_output_1.limitNote)(flags.limit, items.length, Boolean(r?.has_more));
|
|
720
740
|
for (const line of (0, list_output_1.warningLines)(note.warning ? [note.warning] : []))
|
|
721
741
|
this.log(line);
|
|
742
|
+
for (const line of (0, list_output_1.textModeProjectionNotes)(flags))
|
|
743
|
+
this.log(line);
|
|
722
744
|
}
|
|
723
745
|
}
|
|
724
746
|
exports.default = TasksList;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* Continue a recurring series whose next occurrence was never armed (OSK-15338).
|
|
4
|
+
*
|
|
5
|
+
* The failure (`recurrence.armFailure`) is recorded on the FINISHED occurrence, and `tasks schedule`
|
|
6
|
+
* refuses a finished Task, so this is the command every surface names for the way back. It arms the
|
|
7
|
+
* occurrence the series is owed and clears the failure; `--cron` / `--timezone` correct the series
|
|
8
|
+
* first, which is the only cure for an `invalid_pattern` failure.
|
|
9
|
+
*/
|
|
10
|
+
export default class TasksRearmRecurrence extends BaseCommand {
|
|
11
|
+
static description: string;
|
|
12
|
+
static examples: string[];
|
|
13
|
+
static args: {
|
|
14
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
15
|
+
};
|
|
16
|
+
static flags: {
|
|
17
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
18
|
+
cron: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
|
+
timezone: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
20
|
+
};
|
|
21
|
+
run(): Promise<void>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
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 web_url_1 = require("../../lib/web-url");
|
|
7
|
+
/**
|
|
8
|
+
* Continue a recurring series whose next occurrence was never armed (OSK-15338).
|
|
9
|
+
*
|
|
10
|
+
* The failure (`recurrence.armFailure`) is recorded on the FINISHED occurrence, and `tasks schedule`
|
|
11
|
+
* refuses a finished Task, so this is the command every surface names for the way back. It arms the
|
|
12
|
+
* occurrence the series is owed and clears the failure; `--cron` / `--timezone` correct the series
|
|
13
|
+
* first, which is the only cure for an `invalid_pattern` failure.
|
|
14
|
+
*/
|
|
15
|
+
class TasksRearmRecurrence extends base_command_1.BaseCommand {
|
|
16
|
+
static description = 'Re-arm a recurring series from the finished occurrence whose next occurrence was never scheduled';
|
|
17
|
+
static examples = [
|
|
18
|
+
'<%= config.bin %> tasks rearm-recurrence OSK-42',
|
|
19
|
+
'<%= config.bin %> tasks rearm-recurrence OSK-42 --cron "0 9 * * 1-5" --timezone America/New_York',
|
|
20
|
+
];
|
|
21
|
+
static args = {
|
|
22
|
+
id: core_1.Args.string({
|
|
23
|
+
description: 'The finished occurrence (Task ID or identifier) that carries the arm failure',
|
|
24
|
+
required: true,
|
|
25
|
+
ignoreStdin: true,
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
28
|
+
static flags = {
|
|
29
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
30
|
+
cron: core_1.Flags.string({
|
|
31
|
+
description: 'Correct the series pattern first: five cron fields "minute hour day-of-month month day-of-week", e.g. "0 9 * * 1-5"',
|
|
32
|
+
}),
|
|
33
|
+
timezone: core_1.Flags.string({
|
|
34
|
+
description: 'Correct the series timezone first (IANA zone, e.g. America/New_York)',
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
37
|
+
async run() {
|
|
38
|
+
this.requireAuth();
|
|
39
|
+
const { args, flags } = await this.parse(TasksRearmRecurrence);
|
|
40
|
+
const taskRef = await this.resolveEntityRef('task', args.id);
|
|
41
|
+
let result;
|
|
42
|
+
try {
|
|
43
|
+
result = await data_provider_1.dataService.rearmTaskRecurrence({
|
|
44
|
+
taskId: taskRef,
|
|
45
|
+
pattern: flags.cron,
|
|
46
|
+
timezone: flags.timezone,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
this.handleApiError(err);
|
|
51
|
+
}
|
|
52
|
+
if (flags.json) {
|
|
53
|
+
this.log(JSON.stringify({
|
|
54
|
+
...result,
|
|
55
|
+
task: (0, web_url_1.withTaskUrl)(this.cliConfig.baseURL, result.task),
|
|
56
|
+
}, null, 2));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const finished = result.task;
|
|
60
|
+
const from = finished.identifier || finished.id || taskRef;
|
|
61
|
+
const next = result.successor.identifier || result.successor.id;
|
|
62
|
+
const when = result.successor.scheduledFor ? ` for ${result.successor.scheduledFor}` : '';
|
|
63
|
+
// The server's sentence IS the answer: it is derived with the JSON fields, so the two can
|
|
64
|
+
// never disagree (round 3 of OSK-15321 found them disagreeing). The fallback below is only
|
|
65
|
+
// for an older server that sends no `message`.
|
|
66
|
+
if (typeof result.message === 'string' && result.message) {
|
|
67
|
+
this.log(result.message);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
// Never call a successor with no schedule "armed": it will not fire (#4262 verification).
|
|
71
|
+
let line;
|
|
72
|
+
if (!result.successor.scheduledFor) {
|
|
73
|
+
line = `The next occurrence ${next} of the series from ${from} exists but has no schedule, so nothing will fire it on its own; start it by hand or give it a time with \`${this.config.bin} tasks schedule ${next} --at <ISO time>\`.`;
|
|
74
|
+
}
|
|
75
|
+
else if (result.rescheduled) {
|
|
76
|
+
line = `The next occurrence ${next} existed but had no schedule; it is now scheduled${when}. The failure marker is cleared.`;
|
|
77
|
+
}
|
|
78
|
+
else if (result.alreadyArmed) {
|
|
79
|
+
line = `The series from ${from} was already armed: next occurrence ${next}${when}. The failure marker is cleared.`;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
line = `Re-armed the series from ${from}: next occurrence ${next} is scheduled${when}.`;
|
|
83
|
+
}
|
|
84
|
+
this.log(line);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.default = TasksRearmRecurrence;
|
|
@@ -69,6 +69,14 @@ export declare function labelsLine(labelIds?: string[], nameById?: Map<string, s
|
|
|
69
69
|
* reassigning the task changes only the implied kind.
|
|
70
70
|
*/
|
|
71
71
|
export declare function taskExecutorLabel(t: Record<string, unknown>, bin?: string): string;
|
|
72
|
+
/**
|
|
73
|
+
* The `Resolution:` lines for any resolved Task: how it ended, the reason the
|
|
74
|
+
* closer recorded, who closed it, and what the close stood on. The reason used to
|
|
75
|
+
* be JSON-only, so text showed "Task workflow type is cancelled" for every
|
|
76
|
+
* cancel, and a Task its Workflow step cancelled could not be told from one a
|
|
77
|
+
* person cancelled by hand (OSK-16475). Silent for an open Task.
|
|
78
|
+
*/
|
|
79
|
+
export declare function resolutionLines(t: Record<string, unknown>, names?: Map<string, string>): string[];
|
|
72
80
|
/**
|
|
73
81
|
* The `Recurrence:` line for a series whose next occurrence was never armed.
|
|
74
82
|
* Silent otherwise: a healthy series has nothing to say here.
|
|
@@ -112,6 +120,7 @@ export default class TasksShow extends BaseCommand {
|
|
|
112
120
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
113
121
|
task: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
114
122
|
'no-enrich': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
123
|
+
'description-format': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
115
124
|
};
|
|
116
125
|
run(): Promise<void>;
|
|
117
126
|
/**
|
|
@@ -6,6 +6,7 @@ exports.completionLines = completionLines;
|
|
|
6
6
|
exports.reviewPolicyLine = reviewPolicyLine;
|
|
7
7
|
exports.labelsLine = labelsLine;
|
|
8
8
|
exports.taskExecutorLabel = taskExecutorLabel;
|
|
9
|
+
exports.resolutionLines = resolutionLines;
|
|
9
10
|
exports.recurrenceArmFailureLines = recurrenceArmFailureLines;
|
|
10
11
|
exports.taskFailureLines = taskFailureLines;
|
|
11
12
|
const core_1 = require("@oclif/core");
|
|
@@ -21,6 +22,7 @@ const label_ref_1 = require("../../lib/label-ref");
|
|
|
21
22
|
const principal_display_1 = require("../../lib/principal-display");
|
|
22
23
|
const task_economics_line_1 = require("../../lib/task-economics-line");
|
|
23
24
|
const format_1 = require("../../lib/format");
|
|
25
|
+
const task_recurrence_outcome_1 = require("../../lib/task-recurrence-outcome");
|
|
24
26
|
/**
|
|
25
27
|
* Where to look next — as COMMANDS, not as facts about the task.
|
|
26
28
|
*
|
|
@@ -150,6 +152,43 @@ function taskExecutorLabel(t, bin = 'skrr') {
|
|
|
150
152
|
return '-';
|
|
151
153
|
}
|
|
152
154
|
}
|
|
155
|
+
function resolverLabel(by, names) {
|
|
156
|
+
if (!by || typeof by !== 'object' || !by.kind)
|
|
157
|
+
return null;
|
|
158
|
+
const kind = String(by.kind);
|
|
159
|
+
if (kind === 'human')
|
|
160
|
+
return `person ${(0, principal_display_1.displayPrincipal)(by.userId, names)}`;
|
|
161
|
+
if (kind === 'agent')
|
|
162
|
+
return `agent ${(0, principal_display_1.displayPrincipal)(by.agentId, names)}`;
|
|
163
|
+
if (kind === 'system')
|
|
164
|
+
return `system${by.service ? ` (${String(by.service)})` : ''}`;
|
|
165
|
+
if (kind === 'integration')
|
|
166
|
+
return `integration${by.provider ? ` (${String(by.provider)})` : ''}`;
|
|
167
|
+
return kind;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* The `Resolution:` lines for any resolved Task: how it ended, the reason the
|
|
171
|
+
* closer recorded, who closed it, and what the close stood on. The reason used to
|
|
172
|
+
* be JSON-only, so text showed "Task workflow type is cancelled" for every
|
|
173
|
+
* cancel, and a Task its Workflow step cancelled could not be told from one a
|
|
174
|
+
* person cancelled by hand (OSK-16475). Silent for an open Task.
|
|
175
|
+
*/
|
|
176
|
+
function resolutionLines(t, names) {
|
|
177
|
+
const resolution = t.resolution;
|
|
178
|
+
if (!resolution || typeof resolution !== 'object' || !resolution.kind)
|
|
179
|
+
return [];
|
|
180
|
+
const reason = typeof resolution.reason === 'string' ? resolution.reason.trim() : '';
|
|
181
|
+
const closure = resolution.closure
|
|
182
|
+
? (0, task_closure_1.closureSnapshotLines)(resolution.closure)
|
|
183
|
+
: [];
|
|
184
|
+
const lines = [`Resolution: ${String(resolution.kind)}${reason ? ` — ${reason}` : ''}`];
|
|
185
|
+
if (closure.length > 0)
|
|
186
|
+
lines.push(` ${closure.join(' ')}`);
|
|
187
|
+
const by = resolverLabel(resolution.resolvedBy, names);
|
|
188
|
+
if (by)
|
|
189
|
+
lines.push(`Resolved by: ${by}`);
|
|
190
|
+
return lines;
|
|
191
|
+
}
|
|
153
192
|
/**
|
|
154
193
|
* The `Recurrence:` line for a series whose next occurrence was never armed.
|
|
155
194
|
* Silent otherwise: a healthy series has nothing to say here.
|
|
@@ -159,9 +198,17 @@ function recurrenceArmFailureLines(t, bin = 'skrr') {
|
|
|
159
198
|
const code = recurrence?.armFailure?.code;
|
|
160
199
|
if (typeof code !== 'string' || !code)
|
|
161
200
|
return [];
|
|
201
|
+
const ref = (typeof t.identifier === 'string' && t.identifier) ||
|
|
202
|
+
(typeof t.id === 'string' && t.id) ||
|
|
203
|
+
'<task-id>';
|
|
204
|
+
// A finished occurrence is re-armed (`tasks schedule` refuses it, OSK-15338); a LIVE series the
|
|
205
|
+
// scheduler stopped on an unrunnable pattern is rescheduled with a valid one, which clears it.
|
|
206
|
+
const finished = ['completed', 'cancelled'].includes(String(t.statusType ?? ''));
|
|
162
207
|
return [
|
|
163
208
|
`Recurrence: ${(0, data_provider_1.describeRecurrenceArmFailure)(code)} (${code})`,
|
|
164
|
-
|
|
209
|
+
finished || t.statusType === undefined
|
|
210
|
+
? ` ${(0, task_recurrence_outcome_1.recurrenceRearmHint)(code, ref, bin)}`
|
|
211
|
+
: ` Reschedule it with \`${bin} tasks schedule ${ref} --at <ISO time> --cron "<minute hour day month weekday>"\`.`,
|
|
165
212
|
];
|
|
166
213
|
}
|
|
167
214
|
/**
|
|
@@ -246,6 +293,10 @@ class TasksShow extends base_command_1.BaseCommand {
|
|
|
246
293
|
'no-enrich': core_1.Flags.boolean({
|
|
247
294
|
description: 'Skip server-side enrichment (assignee names, parent titles)',
|
|
248
295
|
}),
|
|
296
|
+
'description-format': core_1.Flags.string({
|
|
297
|
+
description: 'How to read the description. html (default) is what is stored; markdown returns it as it was written.',
|
|
298
|
+
options: ['html', 'markdown'],
|
|
299
|
+
}),
|
|
249
300
|
};
|
|
250
301
|
async run() {
|
|
251
302
|
this.requireAuth();
|
|
@@ -304,7 +355,12 @@ class TasksShow extends base_command_1.BaseCommand {
|
|
|
304
355
|
task = bound;
|
|
305
356
|
}
|
|
306
357
|
else {
|
|
307
|
-
task = await data_provider_1.dataService.getTask(taskId, {
|
|
358
|
+
task = await data_provider_1.dataService.getTask(taskId, {
|
|
359
|
+
enrich: !flags['no-enrich'],
|
|
360
|
+
...(flags['description-format'] === 'markdown'
|
|
361
|
+
? { descriptionFormat: 'markdown' }
|
|
362
|
+
: {}),
|
|
363
|
+
});
|
|
308
364
|
}
|
|
309
365
|
}
|
|
310
366
|
catch (err) {
|
|
@@ -331,13 +387,28 @@ class TasksShow extends base_command_1.BaseCommand {
|
|
|
331
387
|
completionRead = false;
|
|
332
388
|
}
|
|
333
389
|
if (flags.json) {
|
|
334
|
-
this.
|
|
390
|
+
this.printJsonResult({ ...t, url, completion });
|
|
335
391
|
return;
|
|
336
392
|
}
|
|
337
393
|
for (const line of completionLines(completion, { read: completionRead }))
|
|
338
394
|
this.log(line);
|
|
339
395
|
const agents = Array.isArray(t.assigneeAgentIds) ? t.assigneeAgentIds : [];
|
|
340
396
|
const users = Array.isArray(t.assigneeUserIds) ? t.assigneeUserIds : [];
|
|
397
|
+
// Principals print as names, not ObjectIds — same rule as labels: a
|
|
398
|
+
// roster that cannot be read prints ids rather than failing the command.
|
|
399
|
+
const resolvedBy = t.resolution?.resolvedBy;
|
|
400
|
+
const principalIds = [
|
|
401
|
+
t.author,
|
|
402
|
+
t.dri?.resolved?.id,
|
|
403
|
+
...(Array.isArray(t.assigneeAgentIds) ? t.assigneeAgentIds : []),
|
|
404
|
+
...(Array.isArray(t.assigneeUserIds) ? t.assigneeUserIds : []),
|
|
405
|
+
t.economics?.confirmedBy,
|
|
406
|
+
resolvedBy?.userId,
|
|
407
|
+
resolvedBy?.agentId,
|
|
408
|
+
];
|
|
409
|
+
const principalNames = await (0, principal_display_1.resolvePrincipalNames)(principalIds, {
|
|
410
|
+
spaceId: t.spaceId ?? null,
|
|
411
|
+
});
|
|
341
412
|
this.log(`ID: ${t.id ?? t._id ?? '-'}`);
|
|
342
413
|
this.log(`Ref: ${t.identifier ?? (t.taskNumber ? `#${t.taskNumber}` : '-')}`);
|
|
343
414
|
this.log(`Title: ${t.title ?? '-'}`);
|
|
@@ -354,25 +425,12 @@ class TasksShow extends base_command_1.BaseCommand {
|
|
|
354
425
|
* Closing is the actor's call — a Task may be `done` with work still
|
|
355
426
|
* outstanding, and `resolution.closure` is where the server recorded what
|
|
356
427
|
* it stood on at close. Show it so a bare "done" never reads as "clean."
|
|
428
|
+
* The closure sentences share the `tasks move` receipt's renderer, so the
|
|
429
|
+
* two cannot disagree; the reason and the closer are printed for every
|
|
430
|
+
* resolved Task (OSK-16475).
|
|
357
431
|
*/
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
* Same renderer as the `tasks move` receipt, so the two cannot disagree
|
|
361
|
-
* about a Task they are both describing.
|
|
362
|
-
*
|
|
363
|
-
* This copy showed an owner's ordinary close as an override:
|
|
364
|
-
* `TASK_RESULT_REVIEW_REQUIRED` lands in `blockers` whenever the policy is
|
|
365
|
-
* unsatisfied — including when the owner, who is not bound by the Review
|
|
366
|
-
* they declared, closes it themselves — and this rendered it identically to
|
|
367
|
-
* a genuine forced close. So the only read surface for "was this gate
|
|
368
|
-
* overridden?" could not answer the question.
|
|
369
|
-
*/
|
|
370
|
-
if (resolution?.closure) {
|
|
371
|
-
const sentences = (0, task_closure_1.closureSnapshotLines)(resolution.closure);
|
|
372
|
-
if (sentences.length > 0) {
|
|
373
|
-
this.log(`Resolution: ${resolution.kind ?? '-'} — ${sentences.join(' ')}`);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
432
|
+
for (const line of resolutionLines(t, principalNames))
|
|
433
|
+
this.log(line);
|
|
376
434
|
/*
|
|
377
435
|
* A Result orphaned by a spec edit is not the same as no Result.
|
|
378
436
|
*
|
|
@@ -505,18 +563,6 @@ class TasksShow extends base_command_1.BaseCommand {
|
|
|
505
563
|
}
|
|
506
564
|
}
|
|
507
565
|
this.log(`Labels: ${labelsLine(labelIds, labelNames)}`);
|
|
508
|
-
// Principals print as names, not ObjectIds — same rule as labels above: a
|
|
509
|
-
// roster that cannot be read prints ids rather than failing the command.
|
|
510
|
-
const principalIds = [
|
|
511
|
-
t.author,
|
|
512
|
-
t.dri?.resolved?.id,
|
|
513
|
-
...(Array.isArray(t.assigneeAgentIds) ? t.assigneeAgentIds : []),
|
|
514
|
-
...(Array.isArray(t.assigneeUserIds) ? t.assigneeUserIds : []),
|
|
515
|
-
t.economics?.confirmedBy,
|
|
516
|
-
];
|
|
517
|
-
const principalNames = await (0, principal_display_1.resolvePrincipalNames)(principalIds, {
|
|
518
|
-
spaceId: t.spaceId ?? null,
|
|
519
|
-
});
|
|
520
566
|
this.log(`Author: ${t.authorDisplayName || (0, principal_display_1.displayPrincipal)(t.author, principalNames)}`);
|
|
521
567
|
const dri = t.dri;
|
|
522
568
|
if (dri?.resolved) {
|
|
@@ -5,6 +5,7 @@ const core_1 = require("@oclif/core");
|
|
|
5
5
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
6
6
|
const base_command_1 = require("../../base-command");
|
|
7
7
|
const format_1 = require("../../lib/format");
|
|
8
|
+
const task_economics_1 = require("../../lib/task-economics");
|
|
8
9
|
const task_legacy_1 = require("../../lib/task-legacy");
|
|
9
10
|
/**
|
|
10
11
|
* `<action> (<k=v ...>)`, or just the preview when there is nothing to add.
|
|
@@ -13,6 +14,9 @@ const task_legacy_1 = require("../../lib/task-legacy");
|
|
|
13
14
|
* renders `details` with, so the two surfaces describe one entry the same way.
|
|
14
15
|
*/
|
|
15
16
|
function withDetails(item) {
|
|
17
|
+
// An estimate change reads as from-what-to-what, the same line `tasks activity` prints.
|
|
18
|
+
if (typeof item.type === 'string' && item.type.startsWith(data_provider_1.TASK_ECONOMICS_ACTIVITY_TYPE_PREFIX))
|
|
19
|
+
return (0, task_economics_1.describeEconomicsChange)(item.data);
|
|
16
20
|
const preview = String(item.preview ?? '-');
|
|
17
21
|
const details = (0, format_1.formatCell)(item.data ?? item.details, '');
|
|
18
22
|
return details ? `${preview} (${details})` : preview;
|
|
@@ -5,7 +5,11 @@ 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
|
class TasksUnschedule extends base_command_1.BaseCommand {
|
|
8
|
-
|
|
8
|
+
// Decision (OSK-15321, round 3): unschedule ENDS the series at this occurrence; it clears the
|
|
9
|
+
// time and the recurrence. Stopping without ending is `pause-schedule` (keeps the series,
|
|
10
|
+
// `resume-schedule` continues it). A series ended here by mistake is restored, settings and
|
|
11
|
+
// all, with `rearm-recurrence <the previous occurrence>`.
|
|
12
|
+
static description = 'Clear the schedule on a task and end its series here (no future fires). To stop without ending the series use pause-schedule; to restore an ended series run rearm-recurrence on the previous occurrence';
|
|
9
13
|
static examples = [
|
|
10
14
|
'<%= config.bin %> tasks unschedule <task-id>',
|
|
11
15
|
'<%= config.bin %> tasks unschedule <task-id> --json',
|
|
@@ -23,6 +23,7 @@ export default class TasksUpdate extends BaseCommand {
|
|
|
23
23
|
risk: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
24
24
|
confidence: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
25
25
|
rationale: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
26
|
+
'retract-estimate': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
26
27
|
estimate: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
27
28
|
/**
|
|
28
29
|
* Declared, hidden, and refused — on purpose. (S4 dogfood finding)
|
|
@@ -84,6 +84,10 @@ class TasksUpdate extends base_command_1.BaseCommand {
|
|
|
84
84
|
rationale: core_1.Flags.string({
|
|
85
85
|
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.',
|
|
86
86
|
}),
|
|
87
|
+
'retract-estimate': core_1.Flags.boolean({
|
|
88
|
+
description: "Remove the Task's economic estimate (savings, effort, risk, confidence and rationale). Recorded in `tasks activity` as task.economics.retracted under your name; an Agent cannot retract an estimate a person confirmed (409).",
|
|
89
|
+
exclusive: ['savings', 'per', 'effort', 'risk', 'confidence', 'rationale'],
|
|
90
|
+
}),
|
|
87
91
|
estimate: core_1.Flags.integer({
|
|
88
92
|
description: 'New estimate value from the Space estimate scale. Requires a scale on the Space (or an ' +
|
|
89
93
|
'ancestor it inherits from); with none set, the server drops the value. Set the scale ' +
|
|
@@ -410,7 +414,8 @@ class TasksUpdate extends base_command_1.BaseCommand {
|
|
|
410
414
|
startDate: flags['start-date'],
|
|
411
415
|
dueDate: flags['due-date'],
|
|
412
416
|
estimate: flags.estimate,
|
|
413
|
-
|
|
417
|
+
// `null` is the retraction the server records as its own Activity event (OSK-15370).
|
|
418
|
+
economics: flags['retract-estimate'] ? null : (0, task_economics_1.economicsFromFlags)(flags, body.economics),
|
|
414
419
|
// Never sent: `taskUpdateMutationGuard` refuses any payload carrying
|
|
415
420
|
// `status` before the request is built. It is merged in only so the guard
|
|
416
421
|
// sees it and answers with the sentence that names `tasks move`.
|
|
@@ -538,7 +543,17 @@ class TasksUpdate extends base_command_1.BaseCommand {
|
|
|
538
543
|
}
|
|
539
544
|
const t = updated;
|
|
540
545
|
const ref = t.identifier ?? (t.taskNumber ? `#${t.taskNumber}` : '');
|
|
541
|
-
|
|
546
|
+
const label = `${t.id ?? t._id ?? taskRef}${ref ? ` (${ref})` : ''}`;
|
|
547
|
+
// The server's own answer about the estimate (OSK-16476): a no-op says so, never "Updated".
|
|
548
|
+
const unchanged = (0, task_economics_1.estimateUnchangedLine)(payload.economics, t);
|
|
549
|
+
const onlyEstimate = payloadKeys.every((key) => key === 'economics' || payload[key] === undefined);
|
|
550
|
+
if (unchanged && onlyEstimate) {
|
|
551
|
+
this.log(`Task ${label}: ${unchanged}`);
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
this.log(`Updated task ${label} — ${t.title ?? '(no title)'}`);
|
|
555
|
+
if (unchanged)
|
|
556
|
+
this.log(unchanged);
|
|
542
557
|
// `--yes` asserts the revocation; it does not erase that it happened.
|
|
543
558
|
// Report the cost after the write too, or the evidence is silently gone.
|
|
544
559
|
if (changesSpec && flags.yes && (settledSpecAssessments > 0 || acceptanceUnreadable)) {
|
|
@@ -25,17 +25,25 @@ class TriggersAudit extends base_command_1.BaseCommand {
|
|
|
25
25
|
agent: core_1.Flags.string({ description: 'Agent ID filter for owner-wide audit history' }),
|
|
26
26
|
scope: core_1.Flags.string({ description: 'Scope kind filter for owner-wide audit history' }),
|
|
27
27
|
outcome: core_1.Flags.string({
|
|
28
|
-
description: 'Outcome filter
|
|
28
|
+
description: 'Outcome filter (succeeded, failed, skipped, incomplete, capped, ...); an unknown value is refused with the full list',
|
|
29
29
|
}),
|
|
30
30
|
source: core_1.Flags.string({
|
|
31
|
-
description: 'Source filter
|
|
31
|
+
description: 'Source filter (schedule, once, event, manual, webhook, replay, ...); an unknown value is refused with the full list',
|
|
32
32
|
}),
|
|
33
33
|
};
|
|
34
34
|
async run() {
|
|
35
35
|
this.requireAuth();
|
|
36
36
|
const { args, flags } = await this.parse(TriggersAudit);
|
|
37
37
|
const triggerId = args.id ?? flags.trigger;
|
|
38
|
-
|
|
38
|
+
// The per-trigger route takes no filters. A filter passed with a trigger id used to be
|
|
39
|
+
// dropped without a word, so `--outcome failed` listed succeeded rows and exited 0 (OSK-16474).
|
|
40
|
+
// A filter now always reaches the filtered history, narrowed to that trigger; that history
|
|
41
|
+
// covers triggers you own, which is said out loud rather than discovered.
|
|
42
|
+
const filtered = [flags.outcome, flags.source, flags.scope, flags.agent].some((value) => value !== undefined);
|
|
43
|
+
if (triggerId && filtered && !flags.json) {
|
|
44
|
+
this.warn('Filters read the fire history of triggers you own: a trigger shared with you but owned by someone else lists no rows here (omit the filters to read its own audit).');
|
|
45
|
+
}
|
|
46
|
+
const path = triggerId && !filtered
|
|
39
47
|
? (0, triggers_1.withQuery)(`/api/triggers/${encodeURIComponent(triggerId)}/audit`, {
|
|
40
48
|
limit: flags.limit,
|
|
41
49
|
before: flags.before,
|
|
@@ -47,6 +55,7 @@ class TriggersAudit extends base_command_1.BaseCommand {
|
|
|
47
55
|
agentId: flags.agent,
|
|
48
56
|
outcome: flags.outcome,
|
|
49
57
|
source: flags.source,
|
|
58
|
+
...(triggerId ? { triggerId } : {}),
|
|
50
59
|
});
|
|
51
60
|
let response;
|
|
52
61
|
try {
|
|
@@ -7,7 +7,7 @@ const builtinActions_1 = require("../../lib/builtinActions");
|
|
|
7
7
|
const triggers_1 = require("../../lib/triggers");
|
|
8
8
|
const web_url_1 = require("../../lib/web-url");
|
|
9
9
|
class TriggersCreate extends base_command_1.BaseCommand {
|
|
10
|
-
static description = 'Create a universal trigger';
|
|
10
|
+
static description = 'Create a universal trigger. A schedule trigger skips an occurrence that is overdue by more than its catch-up window (--stale-catchup-ms)';
|
|
11
11
|
static examples = [
|
|
12
12
|
'<%= config.bin %> triggers create --scope agent --ref agentId=<agent-id> --kind schedule --mode send_message --cron "0 9 * * *" --prompt "Prepare the daily brief"',
|
|
13
13
|
'<%= config.bin %> triggers create --scope agent --ref agentId=<agent-id> --kind once --mode send_message --at 2026-06-01T15:30:00Z --prompt "Send the launch recap"',
|
|
@@ -65,7 +65,7 @@ class TriggersCreate extends base_command_1.BaseCommand {
|
|
|
65
65
|
}),
|
|
66
66
|
'effect-options': core_1.Flags.string({ description: 'Effect policy options JSON object' }),
|
|
67
67
|
'workflow-event-key': core_1.Flags.string({
|
|
68
|
-
description: 'Exact event key the parked workflow step waits on (required for mode=workflow_signal). Resolves steps in the scope Space; the trigger owner must hold Space edit access at every fire',
|
|
68
|
+
description: 'Exact event key the parked workflow step waits on (required for mode=workflow_signal). Resolves steps in the scope Space; the trigger owner must hold Space edit access at every fire. A person resolves one wait by hand with `skrr workflows signal`',
|
|
69
69
|
}),
|
|
70
70
|
'workflow-outcome': core_1.Flags.string({
|
|
71
71
|
description: 'How the resolved step settles (default success)',
|
|
@@ -99,7 +99,7 @@ class TriggersCreate extends base_command_1.BaseCommand {
|
|
|
99
99
|
description: 'ISO-8601 datetime after which a schedule stops firing',
|
|
100
100
|
}),
|
|
101
101
|
'stale-catchup-ms': core_1.Flags.integer({
|
|
102
|
-
description: 'How late a missed occurrence may still run, in ms (
|
|
102
|
+
description: 'How late a missed occurrence may still run, in ms, from 1000 (1 second) to 31622400000 (366 days). After downtime, an occurrence more than this overdue is skipped rather than run late, and the schedule moves to its next future slot. Unset: 3600000 (1 hour).',
|
|
103
103
|
}),
|
|
104
104
|
at: core_1.Flags.string({
|
|
105
105
|
description: 'ISO-8601 datetime for once triggers. --next-run-at is also accepted with --kind once for backwards compatibility.',
|
|
@@ -290,6 +290,8 @@ class TriggersCreate extends base_command_1.BaseCommand {
|
|
|
290
290
|
dryRun: flags['dry-run'],
|
|
291
291
|
});
|
|
292
292
|
(0, triggers_1.mergeObjectField)(payload, 'execution', execution);
|
|
293
|
+
const mergedExecution = payload.execution;
|
|
294
|
+
(0, triggers_1.assertModeRequiredFlags)(mergedExecution?.mode, flags, mergedExecution);
|
|
293
295
|
(0, triggers_1.mergeTriggerKindConfig)(payload, flags.kind ?? payload.kind, {
|
|
294
296
|
schedule,
|
|
295
297
|
once,
|
|
@@ -304,6 +306,10 @@ class TriggersCreate extends base_command_1.BaseCommand {
|
|
|
304
306
|
this.error(err.message, { exit: 1 });
|
|
305
307
|
}
|
|
306
308
|
this.validatePayload(payload);
|
|
309
|
+
// A body assembled from flags: the server's field paths are read back as those flags. A
|
|
310
|
+
// body the person wrote (--from-json) keeps the paths, which are then what they typed.
|
|
311
|
+
if (!flags['from-json'])
|
|
312
|
+
this.requestFieldFlags = triggers_1.TRIGGER_CREATE_FIELD_FLAGS;
|
|
307
313
|
let trigger;
|
|
308
314
|
try {
|
|
309
315
|
trigger = await triggers_1.triggerApi.create(payload);
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { BaseCommand } from '../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* The text rendering of one fire. `reason` is the typed code and `errorMessage` the sentence a
|
|
4
|
+
* person reads; the view printed whichever came first, so a fire that resolved nothing showed
|
|
5
|
+
* only `Reason: no_waiting_step` and its sentence ("No step in this Space was waiting on that
|
|
6
|
+
* event key.") was JSON-only (OSK-16474). Both are shown now when both exist.
|
|
7
|
+
*/
|
|
8
|
+
export declare function describeFireAuditDetail(detail: Record<string, unknown>, fireId: string, triggerId: string): string[];
|
|
2
9
|
export default class TriggersFireDetail extends BaseCommand {
|
|
3
10
|
static description: string;
|
|
4
11
|
static examples: string[];
|
|
@@ -1,8 +1,36 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.describeFireAuditDetail = describeFireAuditDetail;
|
|
3
4
|
const core_1 = require("@oclif/core");
|
|
4
5
|
const base_command_1 = require("../../base-command");
|
|
5
6
|
const triggers_1 = require("../../lib/triggers");
|
|
7
|
+
/**
|
|
8
|
+
* The text rendering of one fire. `reason` is the typed code and `errorMessage` the sentence a
|
|
9
|
+
* person reads; the view printed whichever came first, so a fire that resolved nothing showed
|
|
10
|
+
* only `Reason: no_waiting_step` and its sentence ("No step in this Space was waiting on that
|
|
11
|
+
* event key.") was JSON-only (OSK-16474). Both are shown now when both exist.
|
|
12
|
+
*/
|
|
13
|
+
function describeFireAuditDetail(detail, fireId, triggerId) {
|
|
14
|
+
const text = (value) => (typeof value === 'string' && value.trim() ? value.trim() : '');
|
|
15
|
+
const lines = [
|
|
16
|
+
`Fire: ${String(detail._id ?? fireId)}`,
|
|
17
|
+
`Trigger: ${String(detail.triggerId ?? triggerId)}`,
|
|
18
|
+
`Fired at: ${String(detail.firedAt ?? '-')}`,
|
|
19
|
+
`Outcome: ${String(detail.outcome ?? '-')}`,
|
|
20
|
+
`Source: ${String(detail.source ?? '-')}`,
|
|
21
|
+
];
|
|
22
|
+
const reason = text(detail.reason);
|
|
23
|
+
const message = text(detail.errorMessage);
|
|
24
|
+
if (reason)
|
|
25
|
+
lines.push(`Reason: ${reason}`);
|
|
26
|
+
if (message && message !== reason)
|
|
27
|
+
lines.push(`${reason ? 'Detail:' : 'Reason:'} ${message}`);
|
|
28
|
+
if (detail.durationMs !== undefined)
|
|
29
|
+
lines.push(`Duration: ${String(detail.durationMs)}ms`);
|
|
30
|
+
if (detail.conversationId)
|
|
31
|
+
lines.push(`Conversation: ${String(detail.conversationId)}`);
|
|
32
|
+
return lines;
|
|
33
|
+
}
|
|
6
34
|
class TriggersFireDetail extends base_command_1.BaseCommand {
|
|
7
35
|
static description = 'Show full detail for one trigger fire record';
|
|
8
36
|
static examples = [
|
|
@@ -34,18 +62,8 @@ class TriggersFireDetail extends base_command_1.BaseCommand {
|
|
|
34
62
|
this.log(JSON.stringify(detail, null, 2));
|
|
35
63
|
return;
|
|
36
64
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
this.log(`Fired at: ${detail.firedAt ?? '-'}`);
|
|
40
|
-
this.log(`Outcome: ${detail.outcome ?? '-'}`);
|
|
41
|
-
this.log(`Source: ${detail.source ?? '-'}`);
|
|
42
|
-
if (detail.reason || detail.errorMessage) {
|
|
43
|
-
this.log(`Reason: ${detail.reason ?? detail.errorMessage}`);
|
|
44
|
-
}
|
|
45
|
-
if (detail.durationMs !== undefined)
|
|
46
|
-
this.log(`Duration: ${detail.durationMs}ms`);
|
|
47
|
-
if (detail.conversationId)
|
|
48
|
-
this.log(`Conversation: ${detail.conversationId}`);
|
|
65
|
+
for (const line of describeFireAuditDetail(detail, args.fireId, args.id))
|
|
66
|
+
this.log(line);
|
|
49
67
|
}
|
|
50
68
|
}
|
|
51
69
|
exports.default = TriggersFireDetail;
|