@cleocode/contracts 2026.9.19 → 2026.9.21
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 +1 -1
- package/dist/__tests__/decide.test.d.ts +7 -0
- package/dist/__tests__/decide.test.d.ts.map +1 -0
- package/dist/__tests__/decide.test.js +91 -0
- package/dist/__tests__/decide.test.js.map +1 -0
- package/dist/__tests__/evidence-atom-schema.test.js +2 -1
- package/dist/__tests__/evidence-atom-schema.test.js.map +1 -1
- package/dist/__tests__/memory-wire-shapes.test.js.map +1 -1
- package/dist/acceptance-gate-schema.d.ts +5 -0
- package/dist/acceptance-gate-schema.d.ts.map +1 -1
- package/dist/acceptance-gate-schema.js +26 -0
- package/dist/acceptance-gate-schema.js.map +1 -1
- package/dist/acceptance-gate.d.ts +70 -3
- package/dist/acceptance-gate.d.ts.map +1 -1
- package/dist/backup-manifest.d.ts +13 -2
- package/dist/backup-manifest.d.ts.map +1 -1
- package/dist/boundary.js +1 -1
- package/dist/boundary.js.map +1 -1
- package/dist/branch-lock.d.ts +11 -0
- package/dist/branch-lock.d.ts.map +1 -1
- package/dist/branch-lock.js +31 -4
- package/dist/branch-lock.js.map +1 -1
- package/dist/cloud/api.d.ts +607 -0
- package/dist/cloud/api.d.ts.map +1 -0
- package/dist/cloud/api.js +417 -0
- package/dist/cloud/api.js.map +1 -0
- package/dist/cloud/envelope.d.ts +84 -0
- package/dist/cloud/envelope.d.ts.map +1 -0
- package/dist/cloud/envelope.js +54 -0
- package/dist/cloud/envelope.js.map +1 -0
- package/dist/cloud/ids.d.ts +30 -0
- package/dist/cloud/ids.d.ts.map +1 -0
- package/dist/cloud/ids.js +32 -0
- package/dist/cloud/ids.js.map +1 -0
- package/dist/cloud/index.d.ts +17 -0
- package/dist/cloud/index.d.ts.map +1 -0
- package/dist/cloud/index.js +17 -0
- package/dist/cloud/index.js.map +1 -0
- package/dist/data-accessor.d.ts +23 -3
- package/dist/data-accessor.d.ts.map +1 -1
- package/dist/data-accessor.js.map +1 -1
- package/dist/decide.d.ts +333 -0
- package/dist/decide.d.ts.map +1 -0
- package/dist/decide.js +184 -0
- package/dist/decide.js.map +1 -0
- package/dist/dispatch/operations-registry.d.ts.map +1 -1
- package/dist/dispatch/operations-registry.js +55 -0
- package/dist/dispatch/operations-registry.js.map +1 -1
- package/dist/done-plan.d.ts +311 -0
- package/dist/done-plan.d.ts.map +1 -0
- package/dist/done-plan.js +17 -0
- package/dist/done-plan.js.map +1 -0
- package/dist/evidence-atom-schema.d.ts +18 -1
- package/dist/evidence-atom-schema.d.ts.map +1 -1
- package/dist/evidence-atom-schema.js +27 -2
- package/dist/evidence-atom-schema.js.map +1 -1
- package/dist/exit-codes.d.ts +40 -0
- package/dist/exit-codes.d.ts.map +1 -1
- package/dist/exit-codes.js +41 -0
- package/dist/exit-codes.js.map +1 -1
- package/dist/graph.d.ts +40 -0
- package/dist/graph.d.ts.map +1 -1
- package/dist/index.d.ts +14 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/memory/observe.d.ts +16 -0
- package/dist/memory/observe.d.ts.map +1 -1
- package/dist/operations/__tests__/release-shared-surface.test.d.ts +10 -0
- package/dist/operations/__tests__/release-shared-surface.test.d.ts.map +1 -0
- package/dist/operations/__tests__/release-shared-surface.test.js +84 -0
- package/dist/operations/__tests__/release-shared-surface.test.js.map +1 -0
- package/dist/operations/dialectic.d.ts +16 -0
- package/dist/operations/dialectic.d.ts.map +1 -1
- package/dist/operations/memory.d.ts +48 -0
- package/dist/operations/memory.d.ts.map +1 -1
- package/dist/operations/nexus-scope-map.d.ts +8 -0
- package/dist/operations/nexus-scope-map.d.ts.map +1 -1
- package/dist/operations/nexus-scope-map.js +8 -0
- package/dist/operations/nexus-scope-map.js.map +1 -1
- package/dist/operations/nexus-user-profile.d.ts +27 -1
- package/dist/operations/nexus-user-profile.d.ts.map +1 -1
- package/dist/operations/nexus-user-profile.js +11 -1
- package/dist/operations/nexus-user-profile.js.map +1 -1
- package/dist/operations/nexus.d.ts +394 -3
- package/dist/operations/nexus.d.ts.map +1 -1
- package/dist/operations/release.d.ts +259 -0
- package/dist/operations/release.d.ts.map +1 -1
- package/dist/operations/release.js +130 -1
- package/dist/operations/release.js.map +1 -1
- package/dist/operations/session.d.ts +6 -4
- package/dist/operations/session.d.ts.map +1 -1
- package/dist/operations/tasks.d.ts +6 -0
- package/dist/operations/tasks.d.ts.map +1 -1
- package/dist/operations/tasks.js +1 -0
- package/dist/operations/tasks.js.map +1 -1
- package/dist/operations/validate.d.ts +5 -0
- package/dist/operations/validate.d.ts.map +1 -1
- package/dist/operations/worktree.d.ts +125 -1
- package/dist/operations/worktree.d.ts.map +1 -1
- package/dist/process-probe.d.ts +17 -0
- package/dist/process-probe.d.ts.map +1 -0
- package/dist/process-probe.js +21 -0
- package/dist/process-probe.js.map +1 -0
- package/dist/project-context.d.ts +44 -2
- package/dist/project-context.d.ts.map +1 -1
- package/dist/project-lifecycle.d.ts +143 -0
- package/dist/project-lifecycle.d.ts.map +1 -0
- package/dist/project-lifecycle.js +21 -0
- package/dist/project-lifecycle.js.map +1 -0
- package/dist/release/plan.d.ts +6 -2
- package/dist/release/plan.d.ts.map +1 -1
- package/dist/release/plan.js +8 -2
- package/dist/release/plan.js.map +1 -1
- package/dist/release/plan.test.js +6 -1
- package/dist/release/plan.test.js.map +1 -1
- package/dist/skills/install-gate.d.ts +109 -0
- package/dist/skills/install-gate.d.ts.map +1 -0
- package/dist/skills/install-gate.js +18 -0
- package/dist/skills/install-gate.js.map +1 -0
- package/dist/table-classification.d.ts +208 -0
- package/dist/table-classification.d.ts.map +1 -0
- package/dist/table-classification.js +23 -0
- package/dist/table-classification.js.map +1 -0
- package/dist/task.d.ts +79 -0
- package/dist/task.d.ts.map +1 -1
- package/package.json +6 -2
- package/schemas/gate-result.schema.json +43 -0
- package/src/__tests__/__snapshots__/operations-registry.test.ts.snap +1 -1
- package/src/__tests__/decide.test.ts +139 -0
- package/src/__tests__/evidence-atom-schema.test.ts +2 -1
- package/src/__tests__/memory-wire-shapes.test.ts +3 -0
- package/src/acceptance-gate-schema.ts +29 -0
- package/src/acceptance-gate.ts +68 -3
- package/src/backup-manifest.ts +13 -2
- package/src/boundary.ts +1 -1
- package/src/branch-lock.ts +36 -4
- package/src/cloud/api.ts +512 -0
- package/src/cloud/envelope.ts +63 -0
- package/src/cloud/ids.ts +51 -0
- package/src/cloud/index.ts +16 -0
- package/src/data-accessor.ts +24 -3
- package/src/decide.ts +355 -0
- package/src/dispatch/operations-registry.ts +58 -0
- package/src/done-plan.ts +350 -0
- package/src/evidence-atom-schema.ts +31 -2
- package/src/exit-codes.ts +42 -0
- package/src/graph.ts +44 -0
- package/src/index.ts +133 -0
- package/src/memory/observe.ts +16 -0
- package/src/operations/__tests__/release-shared-surface.test.ts +112 -0
- package/src/operations/dialectic.ts +17 -0
- package/src/operations/memory.ts +48 -0
- package/src/operations/nexus-scope-map.ts +9 -0
- package/src/operations/nexus-user-profile.ts +29 -1
- package/src/operations/nexus.ts +416 -3
- package/src/operations/release.ts +197 -0
- package/src/operations/session.ts +6 -4
- package/src/operations/tasks.ts +7 -0
- package/src/operations/validate.ts +5 -0
- package/src/operations/worktree.ts +133 -1
- package/src/process-probe.ts +21 -0
- package/src/project-context.ts +42 -2
- package/src/project-lifecycle.ts +149 -0
- package/src/release/plan.test.ts +6 -1
- package/src/release/plan.ts +8 -2
- package/src/skills/install-gate.ts +134 -0
- package/src/table-classification.ts +232 -0
- package/src/task.ts +84 -1
package/src/decide.ts
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed-decision contracts — provider-neutral domain types and zod schemas.
|
|
3
|
+
*
|
|
4
|
+
* A *typed decision* asks a decision model a set of named questions about a
|
|
5
|
+
* piece of state and receives, for every question, a calibrated probability
|
|
6
|
+
* distribution over the admissible answers plus a confidence score. Three
|
|
7
|
+
* question shapes exist:
|
|
8
|
+
*
|
|
9
|
+
* - `noul` — a yes/no question; the answer is a probability that it holds.
|
|
10
|
+
* - `choice` — pick one of several named options.
|
|
11
|
+
* - `score` — place the state on an ordered scale of 2–10 levels.
|
|
12
|
+
*
|
|
13
|
+
* These types describe the DOMAIN, not any one vendor's wire format. Provider
|
|
14
|
+
* adapters (in `packages/core/`) translate between these shapes and their
|
|
15
|
+
* transport; nothing here names a provider.
|
|
16
|
+
*
|
|
17
|
+
* This file is types + zod schemas + const data only (arch gate 10,
|
|
18
|
+
* `scripts/lint-no-runtime-in-contracts.mjs`). Validation entry points are the
|
|
19
|
+
* exported `*Schema` values; call `.parse()` / `.safeParse()` on them.
|
|
20
|
+
*
|
|
21
|
+
* @task T12489
|
|
22
|
+
* @epic T12486
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { z } from 'zod';
|
|
26
|
+
|
|
27
|
+
// ─── Const data ───────────────────────────────────────────────────────────────
|
|
28
|
+
|
|
29
|
+
/** Every supported decision-question shape, in canonical order. */
|
|
30
|
+
export const DECISION_QUESTION_TYPES = ['noul', 'choice', 'score'] as const;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Where a {@link DecisionOutcome} came from.
|
|
34
|
+
*
|
|
35
|
+
* - `provider` — answered live by a decision provider.
|
|
36
|
+
* - `cache` — replayed from a previously stored provider answer.
|
|
37
|
+
* - `fallback` — produced locally because no provider answer was available.
|
|
38
|
+
*/
|
|
39
|
+
export const DECISION_OUTCOME_SOURCES = ['provider', 'cache', 'fallback'] as const;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Hard limits a {@link DecisionRequest} must respect. Enforced by
|
|
43
|
+
* {@link decisionRequestSchema}.
|
|
44
|
+
*/
|
|
45
|
+
export const DECISION_REQUEST_LIMITS = {
|
|
46
|
+
/**
|
|
47
|
+
* Maximum size of `state`, in UTF-16 characters. A string state is measured
|
|
48
|
+
* directly; a structured (object/array) state is measured on its
|
|
49
|
+
* `JSON.stringify` serialization, which is what goes over the wire.
|
|
50
|
+
*/
|
|
51
|
+
maxStateChars: 32_000,
|
|
52
|
+
/** Minimum number of questions in one request. */
|
|
53
|
+
minQuestions: 1,
|
|
54
|
+
/** Maximum number of questions in one request. */
|
|
55
|
+
maxQuestions: 32,
|
|
56
|
+
/** Minimum number of options a `choice` question must offer. */
|
|
57
|
+
minChoiceOptions: 2,
|
|
58
|
+
/** Minimum number of levels on a `score` question's scale. */
|
|
59
|
+
minScoreLevels: 2,
|
|
60
|
+
/** Maximum number of levels on a `score` question's scale. */
|
|
61
|
+
maxScoreLevels: 10,
|
|
62
|
+
} as const;
|
|
63
|
+
|
|
64
|
+
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
/** A decision-question shape: `noul`, `choice` or `score`. */
|
|
67
|
+
export type DecisionQuestionType = (typeof DECISION_QUESTION_TYPES)[number];
|
|
68
|
+
|
|
69
|
+
/** Origin of a {@link DecisionOutcome}. See {@link DECISION_OUTCOME_SOURCES}. */
|
|
70
|
+
export type DecisionOutcomeSource = (typeof DECISION_OUTCOME_SOURCES)[number];
|
|
71
|
+
|
|
72
|
+
/** Any JSON value — the payload type for structured state and instructions. */
|
|
73
|
+
export type DecisionJsonValue =
|
|
74
|
+
| string
|
|
75
|
+
| number
|
|
76
|
+
| boolean
|
|
77
|
+
| null
|
|
78
|
+
| readonly DecisionJsonValue[]
|
|
79
|
+
| { readonly [key: string]: DecisionJsonValue };
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The state a decision is made about: free text, or a structured JSON
|
|
83
|
+
* object/array. Bounded by {@link DECISION_REQUEST_LIMITS.maxStateChars}.
|
|
84
|
+
*/
|
|
85
|
+
export type DecisionState =
|
|
86
|
+
| string
|
|
87
|
+
| readonly DecisionJsonValue[]
|
|
88
|
+
| { readonly [key: string]: DecisionJsonValue };
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Optional guidance for how a question should be judged: free text or a
|
|
92
|
+
* structured JSON object.
|
|
93
|
+
*/
|
|
94
|
+
export type DecisionInstructions = string | { readonly [key: string]: DecisionJsonValue };
|
|
95
|
+
|
|
96
|
+
/** A yes/no question. `criteria` describes what makes the answer "yes". */
|
|
97
|
+
export interface NoulDecisionQuestion {
|
|
98
|
+
/** Discriminant. */
|
|
99
|
+
readonly type: 'noul';
|
|
100
|
+
/** Optional extra guidance for the decision model. */
|
|
101
|
+
readonly instructions?: DecisionInstructions;
|
|
102
|
+
/** Description of the condition whose truth is being judged. */
|
|
103
|
+
readonly criteria: string;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* A pick-one question. `criteria` maps each option name to a description of
|
|
108
|
+
* when that option applies. At least two options are required.
|
|
109
|
+
*/
|
|
110
|
+
export interface ChoiceDecisionQuestion {
|
|
111
|
+
/** Discriminant. */
|
|
112
|
+
readonly type: 'choice';
|
|
113
|
+
/** Optional extra guidance for the decision model. */
|
|
114
|
+
readonly instructions?: DecisionInstructions;
|
|
115
|
+
/** Option name → description of when the option applies (≥ 2 entries). */
|
|
116
|
+
readonly criteria: Readonly<Record<string, string>>;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* An ordered-scale question. `criteria` lists the level descriptions from the
|
|
121
|
+
* lowest level (index 0) to the highest; 2–10 levels.
|
|
122
|
+
*/
|
|
123
|
+
export interface ScoreDecisionQuestion {
|
|
124
|
+
/** Discriminant. */
|
|
125
|
+
readonly type: 'score';
|
|
126
|
+
/** Optional extra guidance for the decision model. */
|
|
127
|
+
readonly instructions?: DecisionInstructions;
|
|
128
|
+
/** Level descriptions, lowest first (2–10 entries). */
|
|
129
|
+
readonly criteria: readonly string[];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** One question in a {@link DecisionRequest}, discriminated on `type`. */
|
|
133
|
+
export type DecisionQuestion =
|
|
134
|
+
| NoulDecisionQuestion
|
|
135
|
+
| ChoiceDecisionQuestion
|
|
136
|
+
| ScoreDecisionQuestion;
|
|
137
|
+
|
|
138
|
+
/** A typed-decision request: some state plus 1–32 named questions about it. */
|
|
139
|
+
export interface DecisionRequest {
|
|
140
|
+
/** Optional provider-specific model identifier; the provider default applies when absent. */
|
|
141
|
+
readonly model?: string;
|
|
142
|
+
/** The state being judged. */
|
|
143
|
+
readonly state: DecisionState;
|
|
144
|
+
/** Question name → question (1–32 entries). Names key the answers in {@link DecisionOutcome}. */
|
|
145
|
+
readonly questions: Readonly<Record<string, DecisionQuestion>>;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Answer to a {@link NoulDecisionQuestion}. */
|
|
149
|
+
export interface NoulDecisionAnswer {
|
|
150
|
+
/** Discriminant — matches the question's type. */
|
|
151
|
+
readonly type: 'noul';
|
|
152
|
+
/** The decided value: `true` when {@link NoulDecisionAnswer.probability} is at least 0.5. */
|
|
153
|
+
readonly value: boolean;
|
|
154
|
+
/** Probability in [0, 1] that the criteria hold. */
|
|
155
|
+
readonly probability: number;
|
|
156
|
+
/** Model confidence in [0, 1]. */
|
|
157
|
+
readonly confidence: number;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** Answer to a {@link ChoiceDecisionQuestion}. */
|
|
161
|
+
export interface ChoiceDecisionAnswer {
|
|
162
|
+
/** Discriminant — matches the question's type. */
|
|
163
|
+
readonly type: 'choice';
|
|
164
|
+
/** The decided option name (the most probable option). */
|
|
165
|
+
readonly value: string;
|
|
166
|
+
/** Option name → probability in [0, 1]. */
|
|
167
|
+
readonly probabilities: Readonly<Record<string, number>>;
|
|
168
|
+
/** Model confidence in [0, 1]. */
|
|
169
|
+
readonly confidence: number;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Answer to a {@link ScoreDecisionQuestion}. */
|
|
173
|
+
export interface ScoreDecisionAnswer {
|
|
174
|
+
/** Discriminant — matches the question's type. */
|
|
175
|
+
readonly type: 'score';
|
|
176
|
+
/** The decided level, as a 0-based index into the question's `criteria`. */
|
|
177
|
+
readonly value: number;
|
|
178
|
+
/** Per-level probabilities in [0, 1], index-aligned with the question's `criteria`. */
|
|
179
|
+
readonly probabilities: readonly number[];
|
|
180
|
+
/** Model confidence in [0, 1]. */
|
|
181
|
+
readonly confidence: number;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** Answer to one {@link DecisionQuestion}, discriminated on `type`. */
|
|
185
|
+
export type DecisionAnswer = NoulDecisionAnswer | ChoiceDecisionAnswer | ScoreDecisionAnswer;
|
|
186
|
+
|
|
187
|
+
/** The result of executing a {@link DecisionRequest}. */
|
|
188
|
+
export interface DecisionOutcome {
|
|
189
|
+
/** Question name → answer; keys match the request's `questions`. */
|
|
190
|
+
readonly answers: Readonly<Record<string, DecisionAnswer>>;
|
|
191
|
+
/** Where this outcome came from. */
|
|
192
|
+
readonly source: DecisionOutcomeSource;
|
|
193
|
+
/** Provider request identifier, when the provider returned one. */
|
|
194
|
+
readonly requestId?: string;
|
|
195
|
+
/** Wall-clock latency of producing this outcome, in milliseconds. */
|
|
196
|
+
readonly latencyMs: number;
|
|
197
|
+
/** Provider-reported cost in US dollars, when known. */
|
|
198
|
+
readonly costUsd?: number;
|
|
199
|
+
/** Provider-reported input-token count, when known. */
|
|
200
|
+
readonly inputTokens?: number;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** Connection settings for a decision provider. */
|
|
204
|
+
export interface DecisionProviderConfig {
|
|
205
|
+
/** Absolute base URL of the provider's API (no trailing path to the endpoint). */
|
|
206
|
+
readonly baseUrl: string;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// ─── Zod schemas ──────────────────────────────────────────────────────────────
|
|
210
|
+
|
|
211
|
+
/** Zod schema for {@link DecisionQuestionType}. */
|
|
212
|
+
export const decisionQuestionTypeSchema = z.enum(DECISION_QUESTION_TYPES);
|
|
213
|
+
|
|
214
|
+
/** Zod schema for {@link DecisionOutcomeSource}. */
|
|
215
|
+
export const decisionOutcomeSourceSchema = z.enum(DECISION_OUTCOME_SOURCES);
|
|
216
|
+
|
|
217
|
+
/** Zod schema for {@link DecisionInstructions}. */
|
|
218
|
+
export const decisionInstructionsSchema = z.union([z.string(), z.record(z.string(), z.json())]);
|
|
219
|
+
|
|
220
|
+
/** A probability or confidence: a finite number in [0, 1]. */
|
|
221
|
+
const unitIntervalSchema = z.number().min(0).max(1);
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Zod schema for {@link DecisionState}. Rejects a state whose size exceeds
|
|
225
|
+
* {@link DECISION_REQUEST_LIMITS.maxStateChars} (serialized size for
|
|
226
|
+
* structured state).
|
|
227
|
+
*/
|
|
228
|
+
export const decisionStateSchema = z
|
|
229
|
+
.union([z.string(), z.array(z.json()), z.record(z.string(), z.json())])
|
|
230
|
+
.superRefine((state, context) => {
|
|
231
|
+
const size = typeof state === 'string' ? state.length : JSON.stringify(state).length;
|
|
232
|
+
if (size > DECISION_REQUEST_LIMITS.maxStateChars) {
|
|
233
|
+
context.addIssue({
|
|
234
|
+
code: 'custom',
|
|
235
|
+
message: `state is ${size} characters; the limit is ${DECISION_REQUEST_LIMITS.maxStateChars}`,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
/** Zod schema for {@link NoulDecisionQuestion}. */
|
|
241
|
+
export const noulDecisionQuestionSchema = z.object({
|
|
242
|
+
type: z.literal('noul'),
|
|
243
|
+
instructions: decisionInstructionsSchema.optional(),
|
|
244
|
+
criteria: z.string().min(1),
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
/** Zod schema for {@link ChoiceDecisionQuestion}; requires at least two options. */
|
|
248
|
+
export const choiceDecisionQuestionSchema = z.object({
|
|
249
|
+
type: z.literal('choice'),
|
|
250
|
+
instructions: decisionInstructionsSchema.optional(),
|
|
251
|
+
criteria: z
|
|
252
|
+
.record(z.string().min(1), z.string())
|
|
253
|
+
.refine((options) => Object.keys(options).length >= DECISION_REQUEST_LIMITS.minChoiceOptions, {
|
|
254
|
+
message: `a choice question needs at least ${DECISION_REQUEST_LIMITS.minChoiceOptions} options`,
|
|
255
|
+
}),
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
/** Zod schema for {@link ScoreDecisionQuestion}; requires 2–10 levels. */
|
|
259
|
+
export const scoreDecisionQuestionSchema = z.object({
|
|
260
|
+
type: z.literal('score'),
|
|
261
|
+
instructions: decisionInstructionsSchema.optional(),
|
|
262
|
+
criteria: z
|
|
263
|
+
.array(z.string())
|
|
264
|
+
.min(DECISION_REQUEST_LIMITS.minScoreLevels)
|
|
265
|
+
.max(DECISION_REQUEST_LIMITS.maxScoreLevels),
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
/** Zod discriminated-union schema for {@link DecisionQuestion}. */
|
|
269
|
+
export const decisionQuestionSchema = z.discriminatedUnion('type', [
|
|
270
|
+
noulDecisionQuestionSchema,
|
|
271
|
+
choiceDecisionQuestionSchema,
|
|
272
|
+
scoreDecisionQuestionSchema,
|
|
273
|
+
]);
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Zod schema for {@link DecisionRequest}. Enforces every
|
|
277
|
+
* {@link DECISION_REQUEST_LIMITS} bound: state size, 1–32 questions, ≥ 2
|
|
278
|
+
* choice options and 2–10 score levels.
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* ```ts
|
|
282
|
+
* decisionRequestSchema.parse({
|
|
283
|
+
* state: 'The build failed on a flaky network test.',
|
|
284
|
+
* questions: {
|
|
285
|
+
* retry: { type: 'noul', criteria: 'Retrying is likely to succeed' },
|
|
286
|
+
* severity: { type: 'score', criteria: ['trivial', 'minor', 'major'] },
|
|
287
|
+
* },
|
|
288
|
+
* });
|
|
289
|
+
* ```
|
|
290
|
+
*/
|
|
291
|
+
export const decisionRequestSchema = z.object({
|
|
292
|
+
model: z.string().min(1).optional(),
|
|
293
|
+
state: decisionStateSchema,
|
|
294
|
+
questions: z.record(z.string().min(1), decisionQuestionSchema).refine(
|
|
295
|
+
(questions) => {
|
|
296
|
+
const count = Object.keys(questions).length;
|
|
297
|
+
return (
|
|
298
|
+
count >= DECISION_REQUEST_LIMITS.minQuestions &&
|
|
299
|
+
count <= DECISION_REQUEST_LIMITS.maxQuestions
|
|
300
|
+
);
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
message: `a request needs ${DECISION_REQUEST_LIMITS.minQuestions}–${DECISION_REQUEST_LIMITS.maxQuestions} questions`,
|
|
304
|
+
},
|
|
305
|
+
),
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
/** Zod schema for {@link NoulDecisionAnswer}. */
|
|
309
|
+
export const noulDecisionAnswerSchema = z.object({
|
|
310
|
+
type: z.literal('noul'),
|
|
311
|
+
value: z.boolean(),
|
|
312
|
+
probability: unitIntervalSchema,
|
|
313
|
+
confidence: unitIntervalSchema,
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
/** Zod schema for {@link ChoiceDecisionAnswer}. */
|
|
317
|
+
export const choiceDecisionAnswerSchema = z.object({
|
|
318
|
+
type: z.literal('choice'),
|
|
319
|
+
value: z.string().min(1),
|
|
320
|
+
probabilities: z.record(z.string().min(1), unitIntervalSchema),
|
|
321
|
+
confidence: unitIntervalSchema,
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
/** Zod schema for {@link ScoreDecisionAnswer}. */
|
|
325
|
+
export const scoreDecisionAnswerSchema = z.object({
|
|
326
|
+
type: z.literal('score'),
|
|
327
|
+
value: z.number().int().nonnegative(),
|
|
328
|
+
probabilities: z
|
|
329
|
+
.array(unitIntervalSchema)
|
|
330
|
+
.min(DECISION_REQUEST_LIMITS.minScoreLevels)
|
|
331
|
+
.max(DECISION_REQUEST_LIMITS.maxScoreLevels),
|
|
332
|
+
confidence: unitIntervalSchema,
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
/** Zod discriminated-union schema for {@link DecisionAnswer}. */
|
|
336
|
+
export const decisionAnswerSchema = z.discriminatedUnion('type', [
|
|
337
|
+
noulDecisionAnswerSchema,
|
|
338
|
+
choiceDecisionAnswerSchema,
|
|
339
|
+
scoreDecisionAnswerSchema,
|
|
340
|
+
]);
|
|
341
|
+
|
|
342
|
+
/** Zod schema for {@link DecisionOutcome} (e.g. when reading a cached outcome back). */
|
|
343
|
+
export const decisionOutcomeSchema = z.object({
|
|
344
|
+
answers: z.record(z.string().min(1), decisionAnswerSchema),
|
|
345
|
+
source: decisionOutcomeSourceSchema,
|
|
346
|
+
requestId: z.string().min(1).optional(),
|
|
347
|
+
latencyMs: z.number().nonnegative(),
|
|
348
|
+
costUsd: z.number().nonnegative().optional(),
|
|
349
|
+
inputTokens: z.number().int().nonnegative().optional(),
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
/** Zod schema for {@link DecisionProviderConfig}; `baseUrl` must be an absolute URL. */
|
|
353
|
+
export const decisionProviderConfigSchema = z.object({
|
|
354
|
+
baseUrl: z.url(),
|
|
355
|
+
});
|
|
@@ -3033,6 +3033,14 @@ export const OPERATIONS: OperationDef[] = [
|
|
|
3033
3033
|
description: 'Disable automatic parent completion',
|
|
3034
3034
|
cli: { flag: 'no-auto-complete' },
|
|
3035
3035
|
},
|
|
3036
|
+
{
|
|
3037
|
+
name: 'expectedUpdatedAt',
|
|
3038
|
+
type: 'string',
|
|
3039
|
+
required: false,
|
|
3040
|
+
description:
|
|
3041
|
+
'Optimistic-concurrency guard: fail with E_CONFLICT unless the task updatedAt still equals this value',
|
|
3042
|
+
cli: { flag: 'expected-updated-at' },
|
|
3043
|
+
},
|
|
3036
3044
|
] satisfies ParamDef[],
|
|
3037
3045
|
inputSchema: tasksUpdateInputContract,
|
|
3038
3046
|
outputSchema: OUTPUT_CONTRACTS['tasks.update'],
|
|
@@ -6942,6 +6950,44 @@ export const OPERATIONS: OperationDef[] = [
|
|
|
6942
6950
|
],
|
|
6943
6951
|
},
|
|
6944
6952
|
|
|
6953
|
+
{
|
|
6954
|
+
gateway: 'mutate' as const,
|
|
6955
|
+
domain: 'nexus',
|
|
6956
|
+
operation: 'projects.status',
|
|
6957
|
+
description:
|
|
6958
|
+
'nexus.projects.status (mutate) — probe and record git state of every project location on this device (bounded, parallel; no network unless fetch)',
|
|
6959
|
+
tier: 1,
|
|
6960
|
+
idempotent: true,
|
|
6961
|
+
sessionRequired: false,
|
|
6962
|
+
requiredParams: [],
|
|
6963
|
+
params: [
|
|
6964
|
+
{
|
|
6965
|
+
name: 'fetch',
|
|
6966
|
+
type: 'boolean',
|
|
6967
|
+
required: false,
|
|
6968
|
+
description: 'Run git fetch per location first (network; off by default)',
|
|
6969
|
+
},
|
|
6970
|
+
{
|
|
6971
|
+
name: 'concurrency',
|
|
6972
|
+
type: 'number',
|
|
6973
|
+
required: false,
|
|
6974
|
+
description: 'Locations probed at once (default 8, max 64)',
|
|
6975
|
+
},
|
|
6976
|
+
{
|
|
6977
|
+
name: 'timeoutMs',
|
|
6978
|
+
type: 'number',
|
|
6979
|
+
required: false,
|
|
6980
|
+
description: 'Per-location git budget in ms (default 10000; 30000 with fetch)',
|
|
6981
|
+
},
|
|
6982
|
+
{
|
|
6983
|
+
name: 'staleAfterMs',
|
|
6984
|
+
type: 'number',
|
|
6985
|
+
required: false,
|
|
6986
|
+
description: 'A fetch older than this marks remote state stale (default 24h)',
|
|
6987
|
+
},
|
|
6988
|
+
],
|
|
6989
|
+
},
|
|
6990
|
+
|
|
6945
6991
|
{
|
|
6946
6992
|
gateway: 'mutate' as const,
|
|
6947
6993
|
domain: 'nexus',
|
|
@@ -8151,6 +8197,12 @@ export const OPERATIONS: OperationDef[] = [
|
|
|
8151
8197
|
{ name: 'title', type: 'string' as const, required: false, description: 'Override PR title' },
|
|
8152
8198
|
{ name: 'body', type: 'string' as const, required: false, description: 'Override PR body' },
|
|
8153
8199
|
{ name: 'base', type: 'string' as const, required: false, description: 'PR base branch' },
|
|
8200
|
+
{
|
|
8201
|
+
name: 'taskId',
|
|
8202
|
+
type: 'string' as const,
|
|
8203
|
+
required: false,
|
|
8204
|
+
description: 'Owning task id (T####) for the PR commit subject',
|
|
8205
|
+
},
|
|
8154
8206
|
],
|
|
8155
8207
|
},
|
|
8156
8208
|
{
|
|
@@ -8184,6 +8236,12 @@ export const OPERATIONS: OperationDef[] = [
|
|
|
8184
8236
|
{ name: 'title', type: 'string' as const, required: false, description: 'Override PR title' },
|
|
8185
8237
|
{ name: 'body', type: 'string' as const, required: false, description: 'Override PR body' },
|
|
8186
8238
|
{ name: 'base', type: 'string' as const, required: false, description: 'PR base branch' },
|
|
8239
|
+
{
|
|
8240
|
+
name: 'taskId',
|
|
8241
|
+
type: 'string' as const,
|
|
8242
|
+
required: false,
|
|
8243
|
+
description: 'Owning task id (T####) for the PR commit subject',
|
|
8244
|
+
},
|
|
8187
8245
|
],
|
|
8188
8246
|
},
|
|
8189
8247
|
{
|