@skrr-ai/cli 0.1.36 → 0.1.37
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 +17 -4
- package/dist/commands/agents/actions/create.d.ts +5 -0
- package/dist/commands/agents/actions/create.js +26 -0
- package/dist/commands/agents/actions/update.d.ts +5 -0
- package/dist/commands/agents/actions/update.js +24 -0
- package/dist/commands/agents/api-actions/add.d.ts +41 -0
- package/dist/commands/agents/api-actions/add.js +202 -0
- package/dist/commands/agents/api-actions/index.d.ts +28 -0
- package/dist/commands/agents/api-actions/index.js +77 -0
- package/dist/commands/agents/api-actions/remove.d.ts +14 -0
- package/dist/commands/agents/api-actions/remove.js +36 -0
- package/dist/commands/agents/avatar/default/apply.d.ts +25 -0
- package/dist/commands/agents/avatar/default/apply.js +56 -0
- package/dist/commands/agents/avatar/default/index.d.ts +18 -0
- package/dist/commands/agents/avatar/default/index.js +44 -0
- package/dist/commands/agents/avatar/default/set.d.ts +23 -0
- package/dist/commands/agents/avatar/default/set.js +95 -0
- package/dist/commands/agents/avatar/library/delete.d.ts +20 -0
- package/dist/commands/agents/avatar/library/delete.js +47 -0
- package/dist/commands/agents/avatar/library/index.d.ts +16 -0
- package/dist/commands/agents/avatar/library/index.js +56 -0
- package/dist/commands/agents/avatar/presets.d.ts +19 -0
- package/dist/commands/agents/avatar/presets.js +56 -0
- package/dist/commands/agents/categories/create.d.ts +14 -0
- package/dist/commands/agents/categories/create.js +46 -0
- package/dist/commands/agents/categories/delete.d.ts +13 -0
- package/dist/commands/agents/categories/delete.js +33 -0
- package/dist/commands/agents/categories/index.d.ts +20 -0
- package/dist/commands/agents/categories/index.js +82 -0
- package/dist/commands/agents/categories/update.d.ts +22 -0
- package/dist/commands/agents/categories/update.js +59 -0
- package/dist/commands/agents/create.d.ts +10 -0
- package/dist/commands/agents/create.js +57 -3
- package/dist/commands/agents/ensure-default.d.ts +27 -0
- package/dist/commands/agents/ensure-default.js +65 -0
- package/dist/commands/agents/mute.d.ts +16 -0
- package/dist/commands/agents/mute.js +38 -0
- package/dist/commands/agents/pin.d.ts +16 -0
- package/dist/commands/agents/pin.js +38 -0
- package/dist/commands/agents/tools/auth.d.ts +19 -0
- package/dist/commands/agents/tools/auth.js +41 -0
- package/dist/commands/agents/tools/calls.d.ts +18 -0
- package/dist/commands/agents/tools/calls.js +54 -0
- package/dist/commands/agents/tools/index.d.ts +20 -0
- package/dist/commands/agents/tools/index.js +77 -0
- package/dist/commands/agents/unmute.d.ts +16 -0
- package/dist/commands/agents/unmute.js +38 -0
- package/dist/commands/agents/unpin.d.ts +16 -0
- package/dist/commands/agents/unpin.js +38 -0
- package/dist/commands/agents/update.d.ts +12 -0
- package/dist/commands/agents/update.js +64 -3
- package/dist/commands/followups/act.d.ts +22 -0
- package/dist/commands/followups/act.js +102 -0
- package/dist/commands/followups/cancel.d.ts +17 -0
- package/dist/commands/followups/cancel.js +40 -0
- package/dist/commands/followups/checkin.d.ts +27 -0
- package/dist/commands/followups/checkin.js +107 -0
- package/dist/commands/followups/list.d.ts +24 -0
- package/dist/commands/followups/list.js +90 -0
- package/dist/commands/followups/remind.d.ts +26 -0
- package/dist/commands/followups/remind.js +106 -0
- package/dist/commands/followups/reschedule.d.ts +15 -0
- package/dist/commands/followups/reschedule.js +48 -0
- package/dist/commands/followups/resolve.d.ts +23 -0
- package/dist/commands/followups/resolve.js +54 -0
- package/dist/commands/followups/show.d.ts +12 -0
- package/dist/commands/followups/show.js +45 -0
- package/dist/commands/followups/watch.d.ts +51 -0
- package/dist/commands/followups/watch.js +207 -0
- package/dist/commands/goals/labels/add.js +19 -2
- package/dist/commands/goals/labels/remove.js +22 -2
- package/dist/commands/labels/list.d.ts +24 -1
- package/dist/commands/labels/list.js +62 -19
- package/dist/commands/memory/governance/index.d.ts +21 -0
- package/dist/commands/memory/governance/index.js +64 -0
- package/dist/commands/memory/governance/set.d.ts +24 -0
- package/dist/commands/memory/governance/set.js +95 -0
- package/dist/commands/memory/provenance.d.ts +18 -0
- package/dist/commands/memory/provenance.js +66 -0
- package/dist/commands/spaces/create.d.ts +3 -0
- package/dist/commands/spaces/create.js +32 -2
- package/dist/commands/spaces/labels/add.js +19 -2
- package/dist/commands/spaces/labels/remove.js +22 -2
- package/dist/commands/spaces/show.js +2 -0
- package/dist/commands/spaces/update.d.ts +5 -0
- package/dist/commands/spaces/update.js +41 -4
- package/dist/commands/spaces/workflows/lifecycle-diagnostics.d.ts +11 -0
- package/dist/commands/spaces/workflows/lifecycle-diagnostics.js +45 -0
- package/dist/commands/tasks/complete.d.ts +1 -0
- package/dist/commands/tasks/complete.js +8 -1
- package/dist/commands/tasks/create.d.ts +3 -0
- package/dist/commands/tasks/create.js +34 -2
- package/dist/commands/tasks/expectations/assess.d.ts +11 -0
- package/dist/commands/tasks/expectations/assess.js +85 -14
- package/dist/commands/tasks/expectations.js +19 -2
- package/dist/commands/tasks/labels/attach.js +20 -3
- package/dist/commands/tasks/labels/detach.js +21 -3
- package/dist/commands/tasks/lifecycle/attach.d.ts +14 -0
- package/dist/commands/tasks/lifecycle/attach.js +47 -0
- package/dist/commands/tasks/lifecycle/definitions.d.ts +11 -0
- package/dist/commands/tasks/lifecycle/definitions.js +40 -0
- package/dist/commands/tasks/lifecycle/detach.d.ts +12 -0
- package/dist/commands/tasks/lifecycle/detach.js +32 -0
- package/dist/commands/tasks/lifecycle/history.d.ts +13 -0
- package/dist/commands/tasks/lifecycle/history.js +38 -0
- package/dist/commands/tasks/lifecycle/migrate.d.ts +12 -0
- package/dist/commands/tasks/lifecycle/migrate.js +29 -0
- package/dist/commands/tasks/lifecycle/reconcile.d.ts +11 -0
- package/dist/commands/tasks/lifecycle/reconcile.js +27 -0
- package/dist/commands/tasks/lifecycle/reopen.d.ts +13 -0
- package/dist/commands/tasks/lifecycle/reopen.js +34 -0
- package/dist/commands/tasks/lifecycle/show.d.ts +11 -0
- package/dist/commands/tasks/lifecycle/show.js +27 -0
- package/dist/commands/tasks/lifecycle/start.d.ts +12 -0
- package/dist/commands/tasks/lifecycle/start.js +30 -0
- package/dist/commands/tasks/lifecycle/transition.d.ts +15 -0
- package/dist/commands/tasks/lifecycle/transition.js +78 -0
- package/dist/commands/tasks/move.d.ts +1 -0
- package/dist/commands/tasks/move.js +31 -0
- package/dist/commands/tasks/result/submit.js +11 -1
- package/dist/commands/tasks/review-queue.d.ts +29 -0
- package/dist/commands/tasks/review-queue.js +165 -0
- package/dist/commands/tasks/show.js +42 -0
- package/dist/commands/tasks/update.d.ts +1 -0
- package/dist/commands/tasks/update.js +47 -0
- package/dist/lib/agent-actions.d.ts +36 -10
- package/dist/lib/agent-actions.js +63 -9
- package/dist/lib/agent-config.d.ts +11 -0
- package/dist/lib/agent-config.js +85 -3
- package/dist/lib/agent-pin-mute.d.ts +24 -0
- package/dist/lib/agent-pin-mute.js +17 -0
- package/dist/lib/agent-visual-refs.d.ts +6 -0
- package/dist/lib/agent-visual-refs.js +142 -0
- package/dist/lib/first-party-harness-agent.js +7 -0
- package/dist/lib/followups.d.ts +107 -0
- package/dist/lib/followups.js +102 -0
- package/dist/lib/label-ref.d.ts +95 -0
- package/dist/lib/label-ref.js +163 -0
- package/dist/lib/label-scope.d.ts +2 -2
- package/dist/lib/label-scope.js +3 -3
- package/dist/lib/task-closure.d.ts +32 -0
- package/dist/lib/task-closure.js +106 -0
- package/dist/lib/task-lifecycle-output.d.ts +14 -0
- package/dist/lib/task-lifecycle-output.js +101 -0
- package/dist/lib/tasks.d.ts +3 -0
- package/dist/lib/tasks.js +31 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessTrust.js +4 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessTrust.js +4 -0
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +5079 -4546
- package/oclif.manifest.json +20216 -16002
- package/package.json +16 -4
package/dist/lib/label-scope.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Shared plumbing for the unified label commands (`skrr labels …`).
|
|
4
4
|
*
|
|
5
|
-
* Labels are anchored to exactly one scope — a user
|
|
5
|
+
* Labels are anchored to exactly one scope — a user or a workspace —
|
|
6
6
|
* via the `(scope, scopeId)` pair. That pair is simultaneously the uniqueness
|
|
7
7
|
* key and the permission boundary server-side (see
|
|
8
8
|
* `api/server/services/Labels/LabelService.js`), so every label command has to
|
|
@@ -16,7 +16,7 @@ exports.normalizeLabelColor = normalizeLabelColor;
|
|
|
16
16
|
exports.resolveLabelScope = resolveLabelScope;
|
|
17
17
|
exports.resolveApplicableTo = resolveApplicableTo;
|
|
18
18
|
const core_1 = require("@oclif/core");
|
|
19
|
-
exports.LABEL_SCOPES = ['user', '
|
|
19
|
+
exports.LABEL_SCOPES = ['user', 'workspace'];
|
|
20
20
|
exports.LABEL_APPLICABLE = ['task', 'space', 'goal', 'routine'];
|
|
21
21
|
/**
|
|
22
22
|
* The server stores colors as bare 6-hex (`api/server/routes/labels.js` Zod is
|
|
@@ -44,7 +44,7 @@ exports.labelScopeFlags = {
|
|
|
44
44
|
function resolveLabelScope(flags) {
|
|
45
45
|
const scope = (flags.scope ?? 'user');
|
|
46
46
|
const scopeId = flags['scope-id'];
|
|
47
|
-
if (
|
|
47
|
+
if (scope === 'workspace' && !scopeId) {
|
|
48
48
|
throw new Error(`--scope-id is required for --scope ${scope}.`);
|
|
49
49
|
}
|
|
50
50
|
if (scope === 'user' && scopeId) {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { TaskClosureEvaluation } from '@skrr-ai/data-provider';
|
|
2
|
+
/**
|
|
3
|
+
* Render "where does this Task actually stand" for every surface that should
|
|
4
|
+
* say it.
|
|
5
|
+
*
|
|
6
|
+
* ONE renderer, because the failure this exists to fix was several surfaces each
|
|
7
|
+
* asserting a closure state none of them had checked: `tasks result submit`
|
|
8
|
+
* printed a hard-coded "it is ready for review", the server wrote a
|
|
9
|
+
* `ready_for_review` Update to match, and the managed instructions told the
|
|
10
|
+
* agent to read a status the response did not carry. Three confident voices,
|
|
11
|
+
* one unchecked claim.
|
|
12
|
+
*
|
|
13
|
+
* So the rule here is narrow and absolute: this function says only what the
|
|
14
|
+
* evaluation says. If the evaluation is absent or could not run, it says THAT —
|
|
15
|
+
* it never falls back to an optimistic sentence, because the optimistic sentence
|
|
16
|
+
* is the bug.
|
|
17
|
+
*/
|
|
18
|
+
export type ClosureLike = TaskClosureEvaluation | {
|
|
19
|
+
unavailable: true;
|
|
20
|
+
reason?: string;
|
|
21
|
+
} | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* The full account, for the moment a caller has just written something and is
|
|
24
|
+
* deciding what to do next.
|
|
25
|
+
*
|
|
26
|
+
* Every unmet Expectation is NAMED. The ids alone (`e1`, `e2`) are what the
|
|
27
|
+
* gate's own details carried for a while, and they are unusable on their own —
|
|
28
|
+
* the whole point is to be able to act without a second lookup.
|
|
29
|
+
*/
|
|
30
|
+
export declare function closureReport(closure: ClosureLike): string[];
|
|
31
|
+
/** `met (agent)` vs `met (you)` — whose judgement settled it, never hidden. */
|
|
32
|
+
export declare function describeAssessor(kind: string | null | undefined): string;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.closureReport = closureReport;
|
|
4
|
+
exports.describeAssessor = describeAssessor;
|
|
5
|
+
function isUnavailable(closure) {
|
|
6
|
+
return Boolean(closure && closure.unavailable);
|
|
7
|
+
}
|
|
8
|
+
const SHORT_BLOCKER = {
|
|
9
|
+
TASK_RESULT_REQUIRED: 'no Result submitted',
|
|
10
|
+
TASK_CURRENT_RESULT_MISSING: 'the current Result does not resolve',
|
|
11
|
+
TASK_RESULT_SPEC_VERSION_MISMATCH: 'the Result answers an older specification',
|
|
12
|
+
TASK_RESULT_CHANGES_REQUESTED: 'a reviewer requested changes',
|
|
13
|
+
TASK_RESULT_REVIEW_REQUIRED: 'an independent accepted Review is required',
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* The full account, for the moment a caller has just written something and is
|
|
17
|
+
* deciding what to do next.
|
|
18
|
+
*
|
|
19
|
+
* Every unmet Expectation is NAMED. The ids alone (`e1`, `e2`) are what the
|
|
20
|
+
* gate's own details carried for a while, and they are unusable on their own —
|
|
21
|
+
* the whole point is to be able to act without a second lookup.
|
|
22
|
+
*/
|
|
23
|
+
function closureReport(closure) {
|
|
24
|
+
if (!closure)
|
|
25
|
+
return ['Closure state: not reported by this call.'];
|
|
26
|
+
if (isUnavailable(closure)) {
|
|
27
|
+
return [
|
|
28
|
+
'Closure state could not be evaluated. That is a statement about this read,',
|
|
29
|
+
'not about the work — run `skrr tasks expectations <task-id>` to ask directly.',
|
|
30
|
+
];
|
|
31
|
+
}
|
|
32
|
+
const lines = [];
|
|
33
|
+
const exp = closure.expectations;
|
|
34
|
+
/*
|
|
35
|
+
* The degraded note comes FIRST, and before the closable shortcut.
|
|
36
|
+
*
|
|
37
|
+
* An unreadable assessment ledger makes the gate fail OPEN — deliberately, so
|
|
38
|
+
* a Mongo blip cannot create a Task nothing can close — which means `closable`
|
|
39
|
+
* can be true precisely because a check did not run. Reporting only "nothing
|
|
40
|
+
* is outstanding" there would launder an infrastructure failure into a clean
|
|
41
|
+
* bill of health, which is the same class of silence this whole file exists to
|
|
42
|
+
* remove.
|
|
43
|
+
*/
|
|
44
|
+
if (exp?.degraded === 'assessments_unreadable' || closure.degraded === 'assessments_unreadable') {
|
|
45
|
+
lines.push('Expectation assessments could not be read; that check was skipped, not passed.');
|
|
46
|
+
}
|
|
47
|
+
if (closure.closable) {
|
|
48
|
+
lines.push('Nothing is outstanding — this Task can close.');
|
|
49
|
+
return lines;
|
|
50
|
+
}
|
|
51
|
+
if (exp && exp.total > 0) {
|
|
52
|
+
/*
|
|
53
|
+
* "Settled," not "met" — a waived Expectation was judged no longer owed,
|
|
54
|
+
* which is a different fact from done. The count names waivers when any
|
|
55
|
+
* exist so a scope change never reads as completed work.
|
|
56
|
+
*/
|
|
57
|
+
const settled = exp.settledCount ?? exp.settled?.length ?? exp.met;
|
|
58
|
+
const waivedNote = exp.waived ? ` (${exp.waived} waived)` : '';
|
|
59
|
+
lines.push(`Expectations: ${settled} of ${exp.total} settled${waivedNote}.`);
|
|
60
|
+
for (const row of exp.unmet) {
|
|
61
|
+
lines.push(` ${row.id} ${truncate(row.sentence || row.text || '(no text)', 76)}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
for (const blocker of closure.blockers) {
|
|
65
|
+
if (blocker.code === 'TASK_EXPECTATIONS_NOT_MET')
|
|
66
|
+
continue;
|
|
67
|
+
lines.push(SHORT_BLOCKER[blocker.code] ? capitalize(SHORT_BLOCKER[blocker.code]) + '.' : blocker.message);
|
|
68
|
+
}
|
|
69
|
+
if (exp && exp.unmet.length > 0) {
|
|
70
|
+
lines.push('');
|
|
71
|
+
lines.push('Settle each with `skrr tasks expectations assess <task-id> <expectation-id>');
|
|
72
|
+
lines.push(' --decision met|waived --reason "..."`, or review the whole space with');
|
|
73
|
+
lines.push(' `skrr tasks review-queue --space <space-id>`.');
|
|
74
|
+
}
|
|
75
|
+
/*
|
|
76
|
+
* Everything else is advisory — stamped onto `resolution.closure` if the
|
|
77
|
+
* Task closes over it. The one refusal left is an owner-declared required
|
|
78
|
+
* Review, and only for someone who is not the owner; when that blocker is
|
|
79
|
+
* present, say the narrower truth.
|
|
80
|
+
*/
|
|
81
|
+
const reviewRequired = closure.blockers.some((b) => b.code === 'TASK_RESULT_REVIEW_REQUIRED');
|
|
82
|
+
lines.push('');
|
|
83
|
+
lines.push(reviewRequired
|
|
84
|
+
? 'Only an accepted independent Review — or the Task owner closing directly — settles this. The rest is recorded on resolution.closure.'
|
|
85
|
+
: 'Closing anyway is allowed — all of this is recorded on resolution.closure.');
|
|
86
|
+
return lines;
|
|
87
|
+
}
|
|
88
|
+
/** `met (agent)` vs `met (you)` — whose judgement settled it, never hidden. */
|
|
89
|
+
function describeAssessor(kind) {
|
|
90
|
+
if (kind === 'agent')
|
|
91
|
+
return 'agent';
|
|
92
|
+
if (kind === 'human')
|
|
93
|
+
return 'person';
|
|
94
|
+
if (kind === 'system')
|
|
95
|
+
return 'system';
|
|
96
|
+
if (kind === 'integration')
|
|
97
|
+
return 'integration';
|
|
98
|
+
return 'unattributed';
|
|
99
|
+
}
|
|
100
|
+
function truncate(value, max) {
|
|
101
|
+
const flat = value.replace(/\s+/g, ' ').trim();
|
|
102
|
+
return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;
|
|
103
|
+
}
|
|
104
|
+
function capitalize(value) {
|
|
105
|
+
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
106
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TaskLifecycleHistoryResponse, TaskLifecycleResponse, TaskLifecycleTransitionResponse } from '@skrr-ai/data-provider';
|
|
2
|
+
/**
|
|
3
|
+
* Render the Task Lifecycle response — the projection, its stages in protocol
|
|
4
|
+
* order, and the transitions the waiting stage currently declares.
|
|
5
|
+
*/
|
|
6
|
+
export declare function renderTaskLifecycleSummary(response: TaskLifecycleResponse, log: (line: string) => void): void;
|
|
7
|
+
/** Render the outcome of a lifecycle transition call. */
|
|
8
|
+
export declare function renderLifecycleTransitionResult(response: TaskLifecycleTransitionResponse, log: (line: string) => void): void;
|
|
9
|
+
/**
|
|
10
|
+
* Render the durable lifecycle event stream — every generation's transitions,
|
|
11
|
+
* gates and run events, newest first. `lifecycle show` answers where the Task
|
|
12
|
+
* IS; this answers how it got there.
|
|
13
|
+
*/
|
|
14
|
+
export declare function renderLifecycleHistory(response: TaskLifecycleHistoryResponse, log: (line: string) => void): void;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renderTaskLifecycleSummary = renderTaskLifecycleSummary;
|
|
4
|
+
exports.renderLifecycleTransitionResult = renderLifecycleTransitionResult;
|
|
5
|
+
exports.renderLifecycleHistory = renderLifecycleHistory;
|
|
6
|
+
/**
|
|
7
|
+
* Render the Task Lifecycle response — the projection, its stages in protocol
|
|
8
|
+
* order, and the transitions the waiting stage currently declares.
|
|
9
|
+
*/
|
|
10
|
+
function renderTaskLifecycleSummary(response, log) {
|
|
11
|
+
const lifecycle = response.lifecycle;
|
|
12
|
+
if (!lifecycle) {
|
|
13
|
+
log('No lifecycle is attached to this Task.');
|
|
14
|
+
log('Attach one: skrr tasks lifecycle attach <task-id> --pack finding');
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
log(`Lifecycle: ${lifecycle.status} (v${lifecycle.version}, generation ${lifecycle.generation}, revision ${lifecycle.revision})` +
|
|
18
|
+
(lifecycle.packId ? ` — pack ${lifecycle.packId}` : ''));
|
|
19
|
+
if (response.run)
|
|
20
|
+
log(`Run: ${response.run.id} — ${response.run.status}`);
|
|
21
|
+
for (const stage of response.stages || []) {
|
|
22
|
+
const marker = stage.key === lifecycle.currentStageKey ? '>' : ' ';
|
|
23
|
+
const state = stage.status
|
|
24
|
+
? ` — ${stage.status}${stage.outcome ? `/${stage.outcome}` : ''}`
|
|
25
|
+
: '';
|
|
26
|
+
log(`${marker} ${stage.label || stage.key}${state}`);
|
|
27
|
+
}
|
|
28
|
+
if (response.gate) {
|
|
29
|
+
log('');
|
|
30
|
+
log(`Closure gate: ${response.gate.message}`);
|
|
31
|
+
}
|
|
32
|
+
const transitions = response.allowedTransitions || [];
|
|
33
|
+
const waiting = response.stage?.waitingFor;
|
|
34
|
+
if (response.stage && transitions.length) {
|
|
35
|
+
log('');
|
|
36
|
+
log(`Stage "${response.stage.nodeKey}" is waiting${waiting?.nextActor ? ` on ${waiting.nextActor}` : ''}. Legal transitions:`);
|
|
37
|
+
for (const transition of transitions) {
|
|
38
|
+
const needs = [
|
|
39
|
+
...(transition.requires?.fields || []).map((f) => `payload.${f}`),
|
|
40
|
+
transition.requires?.updateType ? `${transition.requires.updateType} update` : undefined,
|
|
41
|
+
transition.requires?.evidence
|
|
42
|
+
? `${transition.requires.evidence} evidence ref(s)`
|
|
43
|
+
: undefined,
|
|
44
|
+
transition.requires?.deliverableRef ? 'deliverable ref' : undefined,
|
|
45
|
+
].filter(Boolean);
|
|
46
|
+
log(` ${transition.id} -> ${transition.outcome}${transition.label ? ` (${transition.label})` : ''}${needs.length ? ` — needs ${needs.join(', ')}` : ''}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (response.pendingEffects?.length) {
|
|
50
|
+
log('');
|
|
51
|
+
log(`${response.pendingEffects.length} effect(s) pending repair:`);
|
|
52
|
+
for (const effect of response.pendingEffects) {
|
|
53
|
+
log(` ${effect.kind}${effect.lastError ? ` — ${effect.lastError}` : ''}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (lifecycle.statusDrift) {
|
|
57
|
+
log(`Status drift: stage expects ${lifecycle.statusDrift.expected}, Task shows ${lifecycle.statusDrift.actual}.`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** Render the outcome of a lifecycle transition call. */
|
|
61
|
+
function renderLifecycleTransitionResult(response, log) {
|
|
62
|
+
log(`Transition ${response.status}${response.code ? ` (${response.code})` : ''}.`);
|
|
63
|
+
if (response.message)
|
|
64
|
+
log(response.message);
|
|
65
|
+
for (const effect of response.effects || []) {
|
|
66
|
+
log(` effect ${effect.kind}: ${effect.status}${effect.ref ? ` -> ${effect.ref}` : ''}${effect.error ? ` — ${effect.error}` : ''}`);
|
|
67
|
+
}
|
|
68
|
+
if (response.gate)
|
|
69
|
+
log(`Gate: ${response.gate.message}`);
|
|
70
|
+
if (response.lifecycle) {
|
|
71
|
+
log(`Lifecycle: ${response.lifecycle.status}, stage ${response.lifecycle.currentStageKey ?? '—'}, revision ${response.lifecycle.revision}.`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Render the durable lifecycle event stream — every generation's transitions,
|
|
76
|
+
* gates and run events, newest first. `lifecycle show` answers where the Task
|
|
77
|
+
* IS; this answers how it got there.
|
|
78
|
+
*/
|
|
79
|
+
function renderLifecycleHistory(response, log) {
|
|
80
|
+
if (!response.events.length) {
|
|
81
|
+
log('No lifecycle events recorded for this Task.');
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
for (const event of response.events) {
|
|
85
|
+
const parts = [
|
|
86
|
+
event.at,
|
|
87
|
+
event.type,
|
|
88
|
+
event.generation !== undefined ? `gen ${event.generation}` : undefined,
|
|
89
|
+
event.transitionId,
|
|
90
|
+
event.status,
|
|
91
|
+
event.outcome,
|
|
92
|
+
event.code,
|
|
93
|
+
].filter(Boolean);
|
|
94
|
+
log(parts.join(' '));
|
|
95
|
+
if (event.message)
|
|
96
|
+
log(` ${event.message}`);
|
|
97
|
+
}
|
|
98
|
+
if (response.truncated) {
|
|
99
|
+
log(`— truncated at the event limit; re-query with a higher --limit or --before.`);
|
|
100
|
+
}
|
|
101
|
+
}
|
package/dist/lib/tasks.d.ts
CHANGED
|
@@ -66,6 +66,9 @@ export type TaskCreateFlagValues = {
|
|
|
66
66
|
tag?: string[];
|
|
67
67
|
'label-id'?: string[];
|
|
68
68
|
worktree?: boolean;
|
|
69
|
+
'lifecycle-definition'?: string;
|
|
70
|
+
'lifecycle-version'?: string;
|
|
71
|
+
'lifecycle-pack'?: string;
|
|
69
72
|
};
|
|
70
73
|
/**
|
|
71
74
|
* Map the tri-state `--worktree` flag to the `executionIsolation` value.
|
package/dist/lib/tasks.js
CHANGED
|
@@ -241,6 +241,22 @@ function normalizeTaskCreateJsonAliases(body) {
|
|
|
241
241
|
}
|
|
242
242
|
return normalized;
|
|
243
243
|
}
|
|
244
|
+
/**
|
|
245
|
+
* Assemble the create-time lifecycle binding from its three flags. Returns
|
|
246
|
+
* undefined when none are set so `mergeDefined` never writes an empty object.
|
|
247
|
+
*/
|
|
248
|
+
function lifecycleBindingFromFlags(flags) {
|
|
249
|
+
const definitionId = flags['lifecycle-definition'];
|
|
250
|
+
const versionId = flags['lifecycle-version'];
|
|
251
|
+
const packId = flags['lifecycle-pack'];
|
|
252
|
+
if (!definitionId && !versionId && !packId)
|
|
253
|
+
return undefined;
|
|
254
|
+
return {
|
|
255
|
+
...(definitionId ? { definitionId } : {}),
|
|
256
|
+
...(versionId ? { versionId } : {}),
|
|
257
|
+
...(packId ? { packId } : {}),
|
|
258
|
+
};
|
|
259
|
+
}
|
|
244
260
|
function buildTaskCreatePayload(body, flags = {}) {
|
|
245
261
|
const payload = (0, prompt_1.mergeDefined)(normalizeTaskCreateJsonAliases(body), {
|
|
246
262
|
templateId: flags.template,
|
|
@@ -275,6 +291,7 @@ function buildTaskCreatePayload(body, flags = {}) {
|
|
|
275
291
|
// Worktree isolation opt-in. --worktree ⇒ 'ephemeral', --no-worktree ⇒
|
|
276
292
|
// 'shared', omitted ⇒ undefined (inherit space policy / global default).
|
|
277
293
|
executionIsolation: executionIsolationFromWorktreeFlag(flags.worktree),
|
|
294
|
+
lifecycle: lifecycleBindingFromFlags(flags),
|
|
278
295
|
});
|
|
279
296
|
applyDaemonSessionDefaults(payload);
|
|
280
297
|
normalizeStringField(payload, 'externalKey', 300);
|
|
@@ -349,6 +366,20 @@ function validateTaskCreatePayload(payload) {
|
|
|
349
366
|
if (payload.templateId !== undefined && !isBoundedString(payload.templateId, 1, 100)) {
|
|
350
367
|
errors.push('templateId must be a non-empty string at most 100 characters');
|
|
351
368
|
}
|
|
369
|
+
if (payload.lifecycle !== undefined) {
|
|
370
|
+
const binding = payload.lifecycle;
|
|
371
|
+
if (!binding || typeof binding !== 'object' || Array.isArray(binding)) {
|
|
372
|
+
errors.push('lifecycle must be an object with definitionId, versionId, or packId');
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
if (!isNonEmptyString(binding.definitionId) && !isNonEmptyString(binding.packId)) {
|
|
376
|
+
errors.push('lifecycle requires a definitionId or a packId');
|
|
377
|
+
}
|
|
378
|
+
if (binding.versionId !== undefined && !isNonEmptyString(binding.definitionId)) {
|
|
379
|
+
errors.push('lifecycle.versionId requires lifecycle.definitionId');
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
352
383
|
for (const field of [
|
|
353
384
|
'parentId',
|
|
354
385
|
'goalId',
|
|
@@ -68,6 +68,10 @@ exports.HARNESS_TIERS = Object.freeze({
|
|
|
68
68
|
'opencode-acp': 1,
|
|
69
69
|
gemini: 1,
|
|
70
70
|
'gemini-acp': 1,
|
|
71
|
+
// Cognition's own CLI (`devin acp`). Vendor first-party like claude/codex —
|
|
72
|
+
// its credential is Cognition's API key, delivered over the ACP
|
|
73
|
+
// `authenticate` RPC rather than env (see daemon backends/devin.ts).
|
|
74
|
+
devin: 1,
|
|
71
75
|
...Object.fromEntries((0, firstPartyHarness_js_1.firstPartyHarnessSpellings)().map((spelling) => [spelling, 1])),
|
|
72
76
|
// --- Tier 2: reviewed open-source community harnesses ---
|
|
73
77
|
goose: 2,
|
|
@@ -62,6 +62,10 @@ export const HARNESS_TIERS = Object.freeze({
|
|
|
62
62
|
'opencode-acp': 1,
|
|
63
63
|
gemini: 1,
|
|
64
64
|
'gemini-acp': 1,
|
|
65
|
+
// Cognition's own CLI (`devin acp`). Vendor first-party like claude/codex —
|
|
66
|
+
// its credential is Cognition's API key, delivered over the ACP
|
|
67
|
+
// `authenticate` RPC rather than env (see daemon backends/devin.ts).
|
|
68
|
+
devin: 1,
|
|
65
69
|
...Object.fromEntries(firstPartyHarnessSpellings().map((spelling) => [spelling, 1])),
|
|
66
70
|
// --- Tier 2: reviewed open-source community harnesses ---
|
|
67
71
|
goose: 2,
|