@wildo-ai/platform-core-shared 1.1.4 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/core/resources/resources-operations.custom.shared.definitions.d.ts.map +1 -1
- package/dist/esm/core/resources/resources-relationships.custom.shared.definitions.d.ts.map +1 -1
- package/dist/esm/index.d.ts +4 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +4 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/runtime/application-backend-env.contracts.d.ts +49 -4
- package/dist/esm/runtime/application-backend-env.contracts.d.ts.map +1 -1
- package/dist/esm/runtime/application-backend-env.contracts.js +48 -1
- package/dist/esm/runtime/application-backend-env.contracts.js.map +1 -1
- package/dist/esm/runtime/http-server-env.contracts.d.ts +46 -0
- package/dist/esm/runtime/http-server-env.contracts.d.ts.map +1 -0
- package/dist/esm/runtime/http-server-env.contracts.js +55 -0
- package/dist/esm/runtime/http-server-env.contracts.js.map +1 -0
- package/dist/esm/runtime/runtime-topology.contracts.d.ts +0 -4
- package/dist/esm/runtime/runtime-topology.contracts.d.ts.map +1 -1
- package/dist/esm/runtime/runtime-topology.contracts.js +0 -12
- package/dist/esm/runtime/runtime-topology.contracts.js.map +1 -1
- package/dist/esm/security/authorizations/roles.custom.shared.definitions.d.ts.map +1 -1
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.resources-config.schemas.d.ts +166 -70
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.schemas.d.ts +166 -70
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.schemas.js +2 -2
- package/dist/esm/wildo-application-executions/wildo-application-executions.custom.shared.schemas.js.map +1 -1
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.resources-config.schemas.d.ts +21 -10
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.schemas.d.ts +21 -10
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.schemas.js +26 -28
- package/dist/esm/wildo-application-tasks/wildo-application-tasks.custom.shared.schemas.js.map +1 -1
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.schemas.d.ts +29 -0
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.schemas.js +58 -0
- package/dist/esm/wildo-applications/wildo-applications.custom.shared.schemas.js.map +1 -1
- package/dist/esm/wildo-applications-versions/wildo-applications-versions.custom.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/wildo-applications-versions/wildo-applications-versions.custom.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/wildo-applications-versions/wildo-applications-versions.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-aspect-resources.custom.shared.schemas.d.ts +13 -0
- package/dist/esm/workbench/workbench-aspect-resources.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-aspect-resources.custom.shared.schemas.js +441 -1
- package/dist/esm/workbench/workbench-aspect-resources.custom.shared.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-creation-console.custom.shared.schemas.d.ts +279 -0
- package/dist/esm/workbench/workbench-creation-console.custom.shared.schemas.d.ts.map +1 -0
- package/dist/esm/workbench/workbench-creation-console.custom.shared.schemas.js +303 -0
- package/dist/esm/workbench/workbench-creation-console.custom.shared.schemas.js.map +1 -0
- package/dist/esm/workbench/workbench-creation-conversation.custom.shared.schemas.d.ts +199 -0
- package/dist/esm/workbench/workbench-creation-conversation.custom.shared.schemas.d.ts.map +1 -0
- package/dist/esm/workbench/workbench-creation-conversation.custom.shared.schemas.js +185 -0
- package/dist/esm/workbench/workbench-creation-conversation.custom.shared.schemas.js.map +1 -0
- package/dist/esm/workbench/workbench-creation-dossier.custom.shared.schemas.d.ts +49 -0
- package/dist/esm/workbench/workbench-creation-dossier.custom.shared.schemas.d.ts.map +1 -0
- package/dist/esm/workbench/workbench-creation-dossier.custom.shared.schemas.js +42 -0
- package/dist/esm/workbench/workbench-creation-dossier.custom.shared.schemas.js.map +1 -0
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.resources-config.schemas.d.ts +461 -11
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.resources-config.schemas.js +509 -6
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.schemas.d.ts +1102 -12
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.schemas.js +1520 -19
- package/dist/esm/workbench/workbench-creation-plane.custom.shared.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-resources-types.custom.shared.schemas.d.ts +123 -1
- package/dist/esm/workbench/workbench-resources-types.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-resources-types.custom.shared.schemas.js +168 -0
- package/dist/esm/workbench/workbench-resources-types.custom.shared.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-resources.custom.shared.resources-config.schemas.d.ts +229 -9
- package/dist/esm/workbench/workbench-resources.custom.shared.resources-config.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-resources.custom.shared.resources-config.schemas.js +2 -2
- package/dist/esm/workbench/workbench-resources.custom.shared.resources-config.schemas.js.map +1 -1
- package/dist/esm/workbench/workbench-resources.custom.shared.schemas.d.ts +18 -3
- package/dist/esm/workbench/workbench-resources.custom.shared.schemas.d.ts.map +1 -1
- package/dist/esm/workbench/workbench-resources.custom.shared.schemas.js +35 -7
- package/dist/esm/workbench/workbench-resources.custom.shared.schemas.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +4 -13
- package/dist/esm/workbench/workbench-creation-board.custom.shared.schemas.d.ts +0 -98
- package/dist/esm/workbench/workbench-creation-board.custom.shared.schemas.d.ts.map +0 -1
- package/dist/esm/workbench/workbench-creation-board.custom.shared.schemas.js +0 -86
- package/dist/esm/workbench/workbench-creation-board.custom.shared.schemas.js.map +0 -1
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { MetaWorkflow_ClarificationAction, MetaWorkflow_EvaluationVerdict } from '@wildo-ai/saas-models/meta-workflows';
|
|
2
|
+
import { EngineCapability, } from '@wildo-ai/saas-models';
|
|
1
3
|
import { z } from 'zod';
|
|
2
|
-
import { initZodDecorators } from '@wildo-ai/zod-decorators';
|
|
4
|
+
import { initZodDecorators, StringEditMode } from '@wildo-ai/zod-decorators';
|
|
5
|
+
import { WorkbenchSpecificationArtifactConcern } from './workbench-resources.custom.shared.schemas.js';
|
|
3
6
|
initZodDecorators(z);
|
|
4
7
|
/**
|
|
5
8
|
* The CREATION PLANE's shared vocabulary — schemas for the four companion-runtime resource
|
|
@@ -44,6 +47,26 @@ export var WorkbenchCreationPlaneBehavior;
|
|
|
44
47
|
WorkbenchCreationPlaneBehavior["RUN_WRITE_RECORDS"] = "creation-plane.run-write-records";
|
|
45
48
|
/** The execution-trace session index. */
|
|
46
49
|
WorkbenchCreationPlaneBehavior["TRACE_SESSIONS"] = "creation-plane.trace-sessions";
|
|
50
|
+
/** The governance questionnaires' unanswered prompts, flattened one row per question. */
|
|
51
|
+
WorkbenchCreationPlaneBehavior["GOVERNANCE_DOCUMENTS"] = "creation-plane.governance-documents";
|
|
52
|
+
WorkbenchCreationPlaneBehavior["GOVERNANCE_QUESTIONS"] = "creation-plane.governance-questions";
|
|
53
|
+
/** The build lane's dispatch history, one row per attempt. */
|
|
54
|
+
WorkbenchCreationPlaneBehavior["BUILD_DISPATCH_PLAN"] = "creation-plane.build-dispatch-plan";
|
|
55
|
+
WorkbenchCreationPlaneBehavior["BUILD_DISPATCHES"] = "creation-plane.build-dispatches";
|
|
56
|
+
/** The playbook runs suspended waiting on a person. */
|
|
57
|
+
WorkbenchCreationPlaneBehavior["PLAYBOOK_RUNS"] = "creation-plane.playbook-runs";
|
|
58
|
+
WorkbenchCreationPlaneBehavior["WAITING_PLAYBOOK_RUNS"] = "creation-plane.waiting-playbook-runs";
|
|
59
|
+
/** The coding runs parked on a question. */
|
|
60
|
+
WorkbenchCreationPlaneBehavior["CODING_LANE_STATUS"] = "creation-plane.coding-lane-status";
|
|
61
|
+
WorkbenchCreationPlaneBehavior["PARKED_CODING_QUESTIONS"] = "creation-plane.parked-coding-questions";
|
|
62
|
+
/** The dossier: every declared interview question × the creator's answer from `creator-inputs`. */
|
|
63
|
+
WorkbenchCreationPlaneBehavior["DOSSIER_ENTRIES"] = "creation-plane.dossier-entries";
|
|
64
|
+
/** HOME's lines (#1454): what happened, what is asked of the creator, what they could do next — one derivation. */
|
|
65
|
+
WorkbenchCreationPlaneBehavior["HOME_LINES"] = "creation-plane.home-lines";
|
|
66
|
+
/** The four creation OUTCOMES with their standing, derived from the landed families and the build plan. */
|
|
67
|
+
WorkbenchCreationPlaneBehavior["CREATION_OUTCOMES"] = "creation-plane.creation-outcomes";
|
|
68
|
+
/** The application's provider secrets per environment — what it needs and what is set, never a value (#1637). */
|
|
69
|
+
WorkbenchCreationPlaneBehavior["APPLICATION_SECRETS"] = "creation-plane.application-secrets";
|
|
47
70
|
})(WorkbenchCreationPlaneBehavior || (WorkbenchCreationPlaneBehavior = {}));
|
|
48
71
|
/** Membership test the companion's source routes by. */
|
|
49
72
|
export const WORKBENCH_CREATION_PLANE_BEHAVIOR_IDS = Object.freeze(Object.values(WorkbenchCreationPlaneBehavior));
|
|
@@ -62,6 +85,64 @@ export const WORKBENCH_CREATION_PLANE_BEHAVIOR_IDS = Object.freeze(Object.values
|
|
|
62
85
|
export function sanitizeWorkbenchCreationPlaneIdentity(value) {
|
|
63
86
|
return value.replaceAll('.', '__').replace(/[^a-zA-Z0-9_-]/g, '-');
|
|
64
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* A dossier row's id — `sanitize(playbookRef)--sanitize(questionRef)` for the step itself, and
|
|
90
|
+
* `sanitize(playbookRef)--<instanceKey>--sanitize(questionRef)` for one of its INSTANCES (#1609).
|
|
91
|
+
*
|
|
92
|
+
* Shared for the same reason the sanitizer is: the companion's projection EMITS the id and the
|
|
93
|
+
* conversation's answer tool ADDRESSES a row by it, and two copies would let the two drift apart the
|
|
94
|
+
* first time the shape changed — which is exactly what adding an instance did. An instance key is a
|
|
95
|
+
* kebab slug, so it needs no sanitizing and cannot contain the `--` separator's ambiguity in a way the
|
|
96
|
+
* question ref does not already (both are refused as duplicates by the projection, never guessed at).
|
|
97
|
+
*/
|
|
98
|
+
export function workbenchDossierEntryIdentity(input) {
|
|
99
|
+
const step = sanitizeWorkbenchCreationPlaneIdentity(input.playbookRef);
|
|
100
|
+
const question = sanitizeWorkbenchCreationPlaneIdentity(input.questionRef);
|
|
101
|
+
return input.instanceKey ? `${step}--${input.instanceKey}--${question}` : `${step}--${question}`;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* The creation plane's CORRELATION VOCABULARY on the engine's actor task — the one named source for
|
|
105
|
+
* the `context.correlation` envelope's domain and ref keys (#1348, #1330).
|
|
106
|
+
*
|
|
107
|
+
* The engine owns the envelope and validates only that keys and values are non-empty strings; this
|
|
108
|
+
* domain owns the keys. Both ends read them: the companion's coding-agent dispatch WRITES the
|
|
109
|
+
* envelope when it admits a run for a build-plan task, and the workbench READS it to draw the run's
|
|
110
|
+
* build-plan task as a resolved link. Two spellings of one key would be a join that silently stops
|
|
111
|
+
* matching, so neither end spells it.
|
|
112
|
+
*
|
|
113
|
+
* The value under {@link WorkbenchTaskCorrelationRef.BUILD_PLAN_TASK} is the build-plan ROW's
|
|
114
|
+
* identity — `sanitizeWorkbenchCreationPlaneIdentity(taskRef)` — so a reader holding the envelope
|
|
115
|
+
* addresses the row with no lookup.
|
|
116
|
+
*/
|
|
117
|
+
export const WORKBENCH_TASK_CORRELATION_DOMAIN = 'application-creation';
|
|
118
|
+
export var WorkbenchTaskCorrelationRef;
|
|
119
|
+
(function (WorkbenchTaskCorrelationRef) {
|
|
120
|
+
/** The `workbenchBuildPlanTaskId` of the build-plan task this coding run was dispatched for. */
|
|
121
|
+
WorkbenchTaskCorrelationRef["BUILD_PLAN_TASK"] = "buildPlanTaskRef";
|
|
122
|
+
/**
|
|
123
|
+
* The creation CONVERSATION (the engine conversational execution's `executionId`) a run was
|
|
124
|
+
* started from, when it was (#1454). The conversation page joins a thread to its runs on this
|
|
125
|
+
* key; a run started from the board or the CLI carries none.
|
|
126
|
+
*/
|
|
127
|
+
WorkbenchTaskCorrelationRef["CONVERSATION"] = "conversationId";
|
|
128
|
+
})(WorkbenchTaskCorrelationRef || (WorkbenchTaskCorrelationRef = {}));
|
|
129
|
+
/**
|
|
130
|
+
* The build-plan row a task's correlation envelope names, or `undefined` when the task was not
|
|
131
|
+
* dispatched for one — a task with no build-plan task is the normal case for anything the creation
|
|
132
|
+
* plane did not admit, and it must read as ABSENT rather than as loading.
|
|
133
|
+
*/
|
|
134
|
+
export function readBuildPlanTaskCorrelation(context) {
|
|
135
|
+
if (typeof context !== 'object' || context === null)
|
|
136
|
+
return undefined;
|
|
137
|
+
const correlation = context.correlation;
|
|
138
|
+
if (typeof correlation !== 'object' || correlation === null)
|
|
139
|
+
return undefined;
|
|
140
|
+
const { domain, refs } = correlation;
|
|
141
|
+
if (domain !== WORKBENCH_TASK_CORRELATION_DOMAIN || typeof refs !== 'object' || refs === null)
|
|
142
|
+
return undefined;
|
|
143
|
+
const value = refs[WorkbenchTaskCorrelationRef.BUILD_PLAN_TASK];
|
|
144
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
145
|
+
}
|
|
65
146
|
/**
|
|
66
147
|
* The dispatch status of one build-plan task — computed, never stored.
|
|
67
148
|
*
|
|
@@ -75,6 +156,86 @@ export var WorkbenchBuildPlanTaskStatus;
|
|
|
75
156
|
WorkbenchBuildPlanTaskStatus["LANDED"] = "landed";
|
|
76
157
|
WorkbenchBuildPlanTaskStatus["BLOCKED"] = "blocked";
|
|
77
158
|
})(WorkbenchBuildPlanTaskStatus || (WorkbenchBuildPlanTaskStatus = {}));
|
|
159
|
+
/**
|
|
160
|
+
* Why a READY build-plan task cannot make progress, so dispatch passes over it.
|
|
161
|
+
*
|
|
162
|
+
* Each member carries a DIFFERENT remedy, and the remedy is the only thing the operator gets. The
|
|
163
|
+
* companion's dispatch service is the only producer; the workbench board renders it. Declared here
|
|
164
|
+
* rather than beside the producer for the reason `Workbench_BuildDispatchPhase` gives: a browser
|
|
165
|
+
* bundle cannot import the companion, and re-spelling the members board-side would be a second
|
|
166
|
+
* source (#1451).
|
|
167
|
+
*
|
|
168
|
+
* None of them refuses the queue. A stuck task is skipped so every unrelated branch proceeds, and a
|
|
169
|
+
* dispatch refuses only when NOTHING ready can move. The READ door never refuses: it answers with the
|
|
170
|
+
* stuck tasks, because "nothing can run, and here is why" is an answer.
|
|
171
|
+
*/
|
|
172
|
+
export var Workbench_BuildTaskStuckReason;
|
|
173
|
+
(function (Workbench_BuildTaskStuckReason) {
|
|
174
|
+
/** It already ran, and its declared product is absent even from the working tree: fix the declaration or the work. */
|
|
175
|
+
Workbench_BuildTaskStuckReason["COMPLETED_UNLANDED"] = "completed_unlanded";
|
|
176
|
+
/**
|
|
177
|
+
* It already ran, and its declared product IS in the working tree but not committed. Landing means
|
|
178
|
+
* committed because acceptance is a commit.
|
|
179
|
+
*
|
|
180
|
+
* Under GUIDED that is the whole story, and the remedy is to review and commit what the run wrote.
|
|
181
|
+
* Under the autonomy posture the loop has ALREADY tried to commit it (#1534), so reaching this state
|
|
182
|
+
* means its accept REFUSED a path — carried changes from before the run, edited since, or not this
|
|
183
|
+
* run's — and the companion's warning names which. The remedy is that refusal's, not a blind commit.
|
|
184
|
+
*/
|
|
185
|
+
Workbench_BuildTaskStuckReason["COMPLETED_AWAITING_COMMIT"] = "completed_awaiting_commit";
|
|
186
|
+
/** Its run suspended on a question nobody has answered; re-dispatching would abandon that session. */
|
|
187
|
+
Workbench_BuildTaskStuckReason["PARKED_AWAITING_ANSWER"] = "parked_awaiting_answer";
|
|
188
|
+
/** It produces a governed document the engine catalog does not define, so no run can author it. */
|
|
189
|
+
Workbench_BuildTaskStuckReason["NO_DOCUMENT_BLUEPRINT"] = "no_document_blueprint";
|
|
190
|
+
/**
|
|
191
|
+
* Its coding runs FAILED as many times as the attempt budget allows (#1536), so another identical
|
|
192
|
+
* dispatch is not offered. Only failures the task caused count: a run failing on a check that was
|
|
193
|
+
* already red completes instead (`carriedVerificationFailures`), so this cannot be reached on the
|
|
194
|
+
* tree's account. Read the last failure, fix its cause, and re-arm the task.
|
|
195
|
+
*/
|
|
196
|
+
Workbench_BuildTaskStuckReason["ATTEMPTS_EXHAUSTED"] = "attempts_exhausted";
|
|
197
|
+
/**
|
|
198
|
+
* A run of it is LIVE right now — selected, admitted or running (#1528). Under a parallel build
|
|
199
|
+
* wave several tasks run at once, and the next selection must pass over one already being built,
|
|
200
|
+
* or two agents would build the same task. Nobody's move: it clears when that run settles.
|
|
201
|
+
*/
|
|
202
|
+
Workbench_BuildTaskStuckReason["IN_FLIGHT"] = "in_flight";
|
|
203
|
+
})(Workbench_BuildTaskStuckReason || (Workbench_BuildTaskStuckReason = {}));
|
|
204
|
+
/**
|
|
205
|
+
* How far one BUILD DISPATCH got — the whole of what `GET /build/dispatches` can honestly say.
|
|
206
|
+
*
|
|
207
|
+
* ## Why it lives in the SHARED package rather than beside the service that sets it
|
|
208
|
+
*
|
|
209
|
+
* Both ends of this vocabulary are real consumers. The companion's dispatch service is the only
|
|
210
|
+
* PRODUCER — since #1359 by PROJECTION: every dispatch is an actor-system execution from the moment
|
|
211
|
+
* its task is selected, and the phase is a pure function of that execution's row
|
|
212
|
+
* (`projectBuildDispatchPhase`), not a record the companion keeps. Until then it was an in-memory
|
|
213
|
+
* list of five that a companion restart emptied. The workbench's build lane reads it to decide
|
|
214
|
+
* whether a dispatch reads as working, done or broken, and a browser bundle cannot import the
|
|
215
|
+
* companion. Declared companion-side, the board
|
|
216
|
+
* would have had to re-spell the four members — the second-source defect the creation board's own
|
|
217
|
+
* client docstring refuses by name. So it is declared ONCE here, where the workbench vocabulary
|
|
218
|
+
* already lives and which the companion already imports.
|
|
219
|
+
*
|
|
220
|
+
* ## The two executors resolve at DIFFERENT moments, and that is the whole reason for four members
|
|
221
|
+
*
|
|
222
|
+
* A companion generation step's dispatch resolves when the step has FINISHED. A coding task's
|
|
223
|
+
* resolves when the run is ADMITTED, with the agent still working — its outcome is the durable
|
|
224
|
+
* actor-task row the record names. Measured 2026-09-13 on Wonder CRM: the record said `ok: true`
|
|
225
|
+
* for `build-task-company-schema` at the instant its run started, and the route told the caller to
|
|
226
|
+
* poll that record "for the outcome", so a script following it read an admitted run as a success.
|
|
227
|
+
*/
|
|
228
|
+
export var Workbench_BuildDispatchPhase;
|
|
229
|
+
(function (Workbench_BuildDispatchPhase) {
|
|
230
|
+
/** Selected and handed to its executor; nothing has resolved yet. */
|
|
231
|
+
Workbench_BuildDispatchPhase["SUBMITTED"] = "submitted";
|
|
232
|
+
/** A coding run was admitted and is running. Its outcome is the durable actor-task row `codingTaskId`. */
|
|
233
|
+
Workbench_BuildDispatchPhase["ADMITTED"] = "admitted";
|
|
234
|
+
/** A companion generation step ran to completion. */
|
|
235
|
+
Workbench_BuildDispatchPhase["FINISHED"] = "finished";
|
|
236
|
+
/** The dispatch threw — before a coding run was admitted, or while a generation step ran. */
|
|
237
|
+
Workbench_BuildDispatchPhase["FAILED"] = "failed";
|
|
238
|
+
})(Workbench_BuildDispatchPhase || (Workbench_BuildDispatchPhase = {}));
|
|
78
239
|
/**
|
|
79
240
|
* One playbook's row on the eligibility board.
|
|
80
241
|
*
|
|
@@ -102,9 +263,13 @@ export const Workbench_Playbook_Schema = z.object({
|
|
|
102
263
|
* what it carried: one application-level value stamped onto every row, while the workbench rendered
|
|
103
264
|
* it beside each playbook as if it described that playbook. The derived application phase is gone
|
|
104
265
|
* (`MetaWorkflow_Phase`); this is the label that was always true of the row.
|
|
266
|
+
*
|
|
267
|
+
* A STRING, not the enum: the vocabulary is `MetaWorkflow_Phase` in `saas-specifications`, which this
|
|
268
|
+
* package deliberately does not import. The map's lane headers (#1326) word each value through the
|
|
269
|
+
* board's own copy block, keyed by the value, so a member added to the enum renders its key — visibly
|
|
270
|
+
* unworded — rather than a guess.
|
|
105
271
|
*/
|
|
106
|
-
phase: z.string().min(1).isSummaryField(),
|
|
107
|
-
/** One sentence: what running this playbook produces. */
|
|
272
|
+
phase: z.string().min(1).isSummaryField(), /** One sentence: what running this playbook produces. */
|
|
108
273
|
intent: z.string().isSummaryField(),
|
|
109
274
|
/** The deterministic gate's verdict: may this playbook run right now. */
|
|
110
275
|
eligible: z.boolean().isSummaryField(),
|
|
@@ -112,19 +277,46 @@ export const Workbench_Playbook_Schema = z.object({
|
|
|
112
277
|
unmet: z.array(z.string()).isSummaryField(),
|
|
113
278
|
/** Every READINESS precondition holds and only SEQUENCING ones do not: information, not a refusal. */
|
|
114
279
|
blockedOnlyBySequencing: z.boolean().isSummaryField(),
|
|
115
|
-
/** This playbook
|
|
280
|
+
/** This playbook DECLARES an interview. Whether it is answered is `unansweredQuestionRefs`. */
|
|
116
281
|
requiresElicitation: z.boolean().isSummaryField(),
|
|
282
|
+
/**
|
|
283
|
+
* The declared questions the dossier does not answer yet (#1454). Empty means a run can proceed
|
|
284
|
+
* without asking — the run reads its interview from the dossier — so this, not
|
|
285
|
+
* `requiresElicitation`, is what "will stop and ask" means now.
|
|
286
|
+
*/
|
|
287
|
+
unansweredQuestionRefs: z.array(z.string().min(1)).isSummaryField(),
|
|
117
288
|
/** Families this playbook writes that ALREADY have content — a run implies an overwrite. */
|
|
118
289
|
wouldReplace: z.array(z.string()).isSummaryField(),
|
|
119
|
-
/**
|
|
290
|
+
/** Declaring playbooks for direct and composed output families. Derived board data, never persisted authority. */
|
|
291
|
+
outputOwners: z.array(z.object({ family: z.string(), playbookRefs: z.array(z.string()) })).isSummaryField(),
|
|
292
|
+
/** Child references missing from the catalog; distinct from a missing output renderer. */
|
|
293
|
+
unresolvedPlaybookRefs: z.array(z.string()).isSummaryField(),
|
|
294
|
+
/** Direct or composed families without a renderer; child impact is descriptive, not a parent readiness gate. */
|
|
120
295
|
unlandableFamilies: z.array(z.string()).isSummaryField(),
|
|
121
296
|
/** Landed outputs whose declared inputs have moved since. An ANNOTATION, never a gate. */
|
|
122
297
|
staleOutputs: z.array(z.object({
|
|
123
298
|
family: z.string().min(1),
|
|
124
299
|
changedInputs: z.array(z.string()),
|
|
125
300
|
})).isSummaryField(),
|
|
301
|
+
/**
|
|
302
|
+
* Whether the application's LINE runs this playbook at all (#1607): true when it is in the line's active
|
|
303
|
+
* set. Distinct from `eligible`, which asks whether an active playbook may run RIGHT NOW. Absent when the
|
|
304
|
+
* board was computed without a line.
|
|
305
|
+
*/
|
|
306
|
+
activeInLine: z.boolean().optional().isSummaryField(),
|
|
307
|
+
/**
|
|
308
|
+
* Why it is, or is not, in the active set — one sentence, already rendered by the runtime, like `unmet`:
|
|
309
|
+
* in the line, outside it, producing only what does not apply, or waiting for the line to be declared.
|
|
310
|
+
* A sentence rather than the status value because this package does not import the vocabulary.
|
|
311
|
+
*/
|
|
312
|
+
activationDetail: z.string().optional().isSummaryField(),
|
|
313
|
+
/**
|
|
314
|
+
* The instances of this playbook the creator opened and has not closed (#1609): each one's key and what it
|
|
315
|
+
* is for. The default instance is not listed; it is the playbook itself. Absent without a line.
|
|
316
|
+
*/
|
|
317
|
+
openInstances: z.array(z.object({ instanceKey: z.string().min(1), purpose: z.string().min(1) })).optional().isSummaryField(),
|
|
126
318
|
/** When the served board was computed — the cache's honesty field, rendered as "as of". */
|
|
127
|
-
computedAt: z.
|
|
319
|
+
computedAt: z.date().isSummaryField(),
|
|
128
320
|
});
|
|
129
321
|
/**
|
|
130
322
|
* One build-plan task in the DISPATCH view.
|
|
@@ -144,7 +336,7 @@ export const Workbench_BuildPlanTask_Schema = z.object({
|
|
|
144
336
|
targetKind: z.string().min(1).isSummaryField(),
|
|
145
337
|
/** Which phase of building the application this task belongs to (context, never ordering). */
|
|
146
338
|
functionalTopic: z.string().min(1).isSummaryField(),
|
|
147
|
-
status: z.enum(WorkbenchBuildPlanTaskStatus).isSummaryField(),
|
|
339
|
+
status: z.enum(WorkbenchBuildPlanTaskStatus).systemEnum('WorkbenchBuildPlanTaskStatus').isSummaryField(),
|
|
148
340
|
/** Task refs that must land first — the only thing that decides what may run next. */
|
|
149
341
|
prerequisiteTaskRefs: z.array(z.string()).isSummaryField(),
|
|
150
342
|
});
|
|
@@ -171,13 +363,15 @@ export const Workbench_RunWriteRecord_Schema = z.object({
|
|
|
171
363
|
/** The playbook this run executed — every record has one. */
|
|
172
364
|
workbenchPlaybookId: z.string().min(1).isForeignKey().isSummaryField(),
|
|
173
365
|
/**
|
|
174
|
-
* The execution-trace session the run recorded under,
|
|
175
|
-
*
|
|
176
|
-
*
|
|
366
|
+
* The execution-trace session the run recorded under, as the register RECORDED it (#1358 — the
|
|
367
|
+
* run id is the actor execution's id and carries no session, so the join is a recorded field, not
|
|
368
|
+
* a prefix match). NULL when the record carries none, or when no listed session matches — a
|
|
369
|
+
* register can legitimately outlive its trace directory, and a dangling id would render as a
|
|
370
|
+
* broken link.
|
|
177
371
|
*/
|
|
178
372
|
workbenchTraceSessionId: z.string().min(1).isForeignKey().isSummaryField().nullable(),
|
|
179
|
-
/** When the run recorded its writes
|
|
180
|
-
at: z.
|
|
373
|
+
/** When the run recorded its writes. */
|
|
374
|
+
at: z.date().isSummaryField(),
|
|
181
375
|
files: z.array(z.object({
|
|
182
376
|
/** App-root-relative path of the written file. */
|
|
183
377
|
path: z.string().min(1),
|
|
@@ -186,18 +380,147 @@ export const Workbench_RunWriteRecord_Schema = z.object({
|
|
|
186
380
|
})).isSummaryField(),
|
|
187
381
|
/** Projected count, so a list can say "wrote 7 files" without rendering the array. */
|
|
188
382
|
fileCount: z.number().int().isSummaryField(),
|
|
383
|
+
/** The commit the workbench's `accept` made of these writes (#1454, Step 7); NULL until one has. */
|
|
384
|
+
acceptedCommitSha: z.string().min(1).isSummaryField().nullable(),
|
|
189
385
|
});
|
|
190
386
|
/** One execution-trace session — the queryable index the board links from. */
|
|
191
387
|
export const Workbench_TraceSession_Schema = z.object({
|
|
192
388
|
/** Emitted by the behavior — session ids admit `.` (`dev-<ISO-ish>` directory names), so sanitized (see the playbook id note). */
|
|
193
389
|
workbenchTraceSessionId: z.string().min(1).isPrimaryKey().isSummaryField(),
|
|
194
390
|
sessionId: z.string().min(1).isSummaryField(),
|
|
195
|
-
/** When the session started (
|
|
196
|
-
startedAt: z.
|
|
391
|
+
/** When the session started (the session manifest's own `startedAt`). */
|
|
392
|
+
startedAt: z.date().isSummaryField(),
|
|
197
393
|
label: z.string().min(1).isSummaryField().nullable(),
|
|
198
394
|
eventCount: z.number().int().isSummaryField(),
|
|
199
395
|
stepCount: z.number().int().isSummaryField(),
|
|
200
396
|
});
|
|
397
|
+
/**
|
|
398
|
+
* One governance QUESTION a creator still owes an answer to.
|
|
399
|
+
*
|
|
400
|
+
* ## Why one row per question rather than per questionnaire
|
|
401
|
+
*
|
|
402
|
+
* The companion answers questionnaires — a document definition and the prompts it asks. The thing a
|
|
403
|
+
* creator ACTS on is one question, and the thing a board queues is one question, so the row is the
|
|
404
|
+
* question and the document it belongs to travels on it. That is the same flattening
|
|
405
|
+
* `Workbench_RunWriteRecord` does to a run's files, and for the same reason: a resource's row is
|
|
406
|
+
* whatever a reader selects.
|
|
407
|
+
*
|
|
408
|
+
* ## What it deliberately does NOT carry
|
|
409
|
+
*
|
|
410
|
+
* The ANSWER. Landing answers is a dispatch against the `document-facts-authored` family and goes
|
|
411
|
+
* through the companion's own service; a row here is the question as asked. Giving the row an answer
|
|
412
|
+
* field would make this the second place an answer lives, which is the ledger
|
|
413
|
+
* `one-source-of-truth.md` rule 5 refuses.
|
|
414
|
+
*/
|
|
415
|
+
/**
|
|
416
|
+
* One GOVERNED DOCUMENT whose questionnaire a person must answer — the document half of governance.
|
|
417
|
+
*
|
|
418
|
+
* ## Why this is its own resource rather than fields on the question row
|
|
419
|
+
*
|
|
420
|
+
* `derivedFactRefs` and the ask count are facts about the DOCUMENT, not about any one question, and
|
|
421
|
+
* a document-level fact repeated on every question row is a value with no owner: nothing says which
|
|
422
|
+
* copy is authoritative, and eight rows of one document can disagree.
|
|
423
|
+
*
|
|
424
|
+
* It is also what the board's document selector is a list OF. Before this it grouped question rows
|
|
425
|
+
* by `definitionRef` and had nowhere to read the derived facts from — so a panel showing only the
|
|
426
|
+
* human half presented four questions for a document declaring eight, and a reader had no way to
|
|
427
|
+
* tell a short questionnaire from a broken one.
|
|
428
|
+
*/
|
|
429
|
+
/**
|
|
430
|
+
* Where a dossier entry STANDS — the two states a question a playbook asks can be in from the
|
|
431
|
+
* creator's side (#1454). "Read from the product" (a typed config key) is a third source the
|
|
432
|
+
* dossier gains with the governed-document join (Step 6); it is not a standing of an interview
|
|
433
|
+
* question, so it is not here.
|
|
434
|
+
*/
|
|
435
|
+
export var WorkbenchDossierEntryStanding;
|
|
436
|
+
(function (WorkbenchDossierEntryStanding) {
|
|
437
|
+
/** The creator answered; the value is in the committed dossier. */
|
|
438
|
+
WorkbenchDossierEntryStanding["FROM_YOU"] = "from-you";
|
|
439
|
+
/** The playbook asks it and nobody has answered. */
|
|
440
|
+
WorkbenchDossierEntryStanding["STILL_NEEDED"] = "still-needed";
|
|
441
|
+
/**
|
|
442
|
+
* An opened INSTANCE of the step asks it and has no answer of its own, so it runs on the step's own
|
|
443
|
+
* answer (#1609). Answered, not needed: nothing is blocked, and an answer given here replaces the
|
|
444
|
+
* step's for this instance only.
|
|
445
|
+
*/
|
|
446
|
+
WorkbenchDossierEntryStanding["FROM_THE_STEP"] = "from-the-step";
|
|
447
|
+
/**
|
|
448
|
+
* The PRODUCT answers it: a governed-document fact the application's own declarations establish,
|
|
449
|
+
* read rather than asked (#1454, gap 4; `compliance-is-derived-from-the-product.md`). Never
|
|
450
|
+
* "needed" and never editable here — its answer changes when what the product declares changes.
|
|
451
|
+
*/
|
|
452
|
+
WorkbenchDossierEntryStanding["READ_FROM_PRODUCT"] = "read-from-product";
|
|
453
|
+
})(WorkbenchDossierEntryStanding || (WorkbenchDossierEntryStanding = {}));
|
|
454
|
+
export const Workbench_GovernanceDocument_Schema = z.object({
|
|
455
|
+
/** The document's ref, sanitized — a definition ref carries `:` and `.`. */
|
|
456
|
+
workbenchGovernanceDocumentId: z.string().min(1).isPrimaryKey().isSummaryField(),
|
|
457
|
+
/** The governed document this questionnaire belongs to. */
|
|
458
|
+
definitionRef: z.string().min(1).isSummaryField(),
|
|
459
|
+
/** How many facts a PERSON must establish for it. */
|
|
460
|
+
askCount: z.number().int().isSummaryField(),
|
|
461
|
+
/**
|
|
462
|
+
* The facts the GENERATOR derives, named rather than omitted.
|
|
463
|
+
*
|
|
464
|
+
* Naming them is what lets a reader tell a short questionnaire from a broken one: a document
|
|
465
|
+
* declaring eight facts of which four are derived shows four questions, and without this the
|
|
466
|
+
* other four look missing rather than answered.
|
|
467
|
+
*/
|
|
468
|
+
derivedFactRefs: z.array(z.string().min(1)).isSummaryField(),
|
|
469
|
+
/**
|
|
470
|
+
* How many of the asked facts NO authored declaration establishes yet (#1454, Step 6) — the
|
|
471
|
+
* dossier's "still needed" for this document. `askCount` is total; this is what is left.
|
|
472
|
+
*/
|
|
473
|
+
openCount: z.number().int().isSummaryField(),
|
|
474
|
+
/**
|
|
475
|
+
* The creator ASKED FOR this document: a draft of it has landed. An open fact of a drafted document
|
|
476
|
+
* is waiting on the person NOW (the draft carries the gap); an open fact of a document nobody
|
|
477
|
+
* drafted is merely not told yet, and does not count as asked of you.
|
|
478
|
+
*/
|
|
479
|
+
drafted: z.boolean().isSummaryField(),
|
|
480
|
+
});
|
|
481
|
+
export const Workbench_GovernanceQuestion_Schema = z.object({
|
|
482
|
+
/**
|
|
483
|
+
* Emitted by the behavior as `<definitionRef>--<questionRef>`, sanitized — both halves admit `.`
|
|
484
|
+
* and neither alone is unique, for the same reason the playbook id is sanitized (see its note).
|
|
485
|
+
*/
|
|
486
|
+
workbenchGovernanceQuestionId: z.string().min(1).isPrimaryKey().isSummaryField(),
|
|
487
|
+
/** The governed document whose questionnaire asks this. */
|
|
488
|
+
definitionRef: z.string().min(1).isSummaryField(),
|
|
489
|
+
/** The question's own ref within that questionnaire. */
|
|
490
|
+
questionRef: z.string().min(1).isSummaryField(),
|
|
491
|
+
/** The fact the answer establishes. */
|
|
492
|
+
factRef: z.string().min(1).isSummaryField(),
|
|
493
|
+
/** The question as a person reads it — the row's own words. */
|
|
494
|
+
creatorPrompt: z.string().min(1).isSummaryField(),
|
|
495
|
+
/** Why the answer is needed, in the document's terms. */
|
|
496
|
+
decisionPurpose: z.string().min(1).isSummaryField(),
|
|
497
|
+
/** What shape of answer the question takes. */
|
|
498
|
+
answerKind: z.string().min(1).isSummaryField(),
|
|
499
|
+
/** Whose authority the answer carries — a creator decision, a qualified review, a specification. */
|
|
500
|
+
factAuthorityKind: z.string().min(1).isSummaryField(),
|
|
501
|
+
/** Whether "not applicable" is an admissible answer. */
|
|
502
|
+
allowsNotApplicable: z.boolean().isSummaryField(),
|
|
503
|
+
/** How sensitive the answer is, by the document's own classification. */
|
|
504
|
+
sensitivityRef: z.string().min(1).isSummaryField(),
|
|
505
|
+
/** The closed set of answers, when the question has one. Empty for a free-text question. */
|
|
506
|
+
semanticOptions: z.array(z.object({
|
|
507
|
+
optionRef: z.string().min(1),
|
|
508
|
+
/** What choosing this option MEANS, in the creator's language rather than the schema's. */
|
|
509
|
+
creatorMeaning: z.string().min(1),
|
|
510
|
+
})).isSummaryField(),
|
|
511
|
+
/** Answered in the authored facts (from you) or not (still needed) — the same standing vocabulary the interview dossier uses. */
|
|
512
|
+
standing: z.enum(WorkbenchDossierEntryStanding).systemEnum('WorkbenchDossierEntryStanding').isSummaryField(),
|
|
513
|
+
/** The answer as a person reads it — the text, the chosen options, or the "does not apply" reason. `null` when still needed. */
|
|
514
|
+
answerSummary: z.string().nullable().isSummaryField(),
|
|
515
|
+
/** When the answer was decided (the declaration's own instant). `null` when still needed. */
|
|
516
|
+
answeredAt: z.date().nullable().isSummaryField(),
|
|
517
|
+
/**
|
|
518
|
+
* ASKED OF YOU NOW: still needed AND the document is DRAFTED — a draft is waiting on this fact. An
|
|
519
|
+
* open fact of an undrafted document is merely not told yet. Derived by the projection, declared
|
|
520
|
+
* as a LIST filter, for the same reason the dossier entry's is.
|
|
521
|
+
*/
|
|
522
|
+
askedNow: z.boolean().isSummaryField(),
|
|
523
|
+
});
|
|
201
524
|
/*
|
|
202
525
|
* ────────────────────────── Phase 3: dispatch OPERATIONS ──────────────────────────
|
|
203
526
|
*
|
|
@@ -216,6 +539,15 @@ export var WorkbenchPlaybooks_Operations;
|
|
|
216
539
|
WorkbenchPlaybooks_Operations["RUN"] = "run";
|
|
217
540
|
/** Answer a run that stopped at a clarification — accept with answers, decline, or cancel. */
|
|
218
541
|
WorkbenchPlaybooks_Operations["RESUME"] = "resume_run";
|
|
542
|
+
/**
|
|
543
|
+
* The questions this playbook still needs answered, as a decision payload — the declared interview
|
|
544
|
+
* minus what the dossier already answers (shared decisions included), and `null` when nothing is left
|
|
545
|
+
* to ask: the step declares none, or the dossier answers them all (#1454 review). Read
|
|
546
|
+
* ON DEMAND, at the moment somebody chooses to run it, and deliberately not a field of the row: one
|
|
547
|
+
* playbook alone declares fifteen questions, so carrying them on every row would pay for all of
|
|
548
|
+
* them on every poll in order to show none of them.
|
|
549
|
+
*/
|
|
550
|
+
WorkbenchPlaybooks_Operations["READ_INTERVIEW"] = "read_interview";
|
|
219
551
|
})(WorkbenchPlaybooks_Operations || (WorkbenchPlaybooks_Operations = {}));
|
|
220
552
|
/** The build-plan resource's dispatch verb. */
|
|
221
553
|
export var WorkbenchBuildPlanTasks_Operations;
|
|
@@ -226,12 +558,46 @@ export var WorkbenchBuildPlanTasks_Operations;
|
|
|
226
558
|
* with the first (the dispatch service's own doctrine).
|
|
227
559
|
*/
|
|
228
560
|
WorkbenchBuildPlanTasks_Operations["DISPATCH_NEXT"] = "dispatch_next";
|
|
561
|
+
/**
|
|
562
|
+
* Append ONE task the creator asked for, beside the plan that exists (#1454, Step 7). Collection-
|
|
563
|
+
* level: the row does not exist until the append answers. Deterministic — no model runs; the
|
|
564
|
+
* companion validates the task against the plan's own graph rules and re-renders the plan file.
|
|
565
|
+
*/
|
|
566
|
+
WorkbenchBuildPlanTasks_Operations["ADD_TASK"] = "add_task";
|
|
567
|
+
/**
|
|
568
|
+
* Run THIS task, by row. Admitted only when the task is READY — the graph still decides what may
|
|
569
|
+
* run, and this verb only lets the creator pick among the ready ones instead of taking the next.
|
|
570
|
+
* A non-ready task answers 409 naming what it waits on. Costs a coding run.
|
|
571
|
+
*/
|
|
572
|
+
WorkbenchBuildPlanTasks_Operations["DISPATCH_TASK"] = "dispatch_task";
|
|
573
|
+
/**
|
|
574
|
+
* ACCEPT what this task's latest completed coding run wrote: commit exactly those paths, from the
|
|
575
|
+
* coding-run write register, in one commit whose message names the task. Paths carrying another
|
|
576
|
+
* lane's hunks (dirty at the run's baseline) and paths edited since the run are refused by name
|
|
577
|
+
* unless `force`. Acceptance is a commit (`one-source-of-truth.md`), and under the YOLO posture the
|
|
578
|
+
* system may make it on the creator's word — this verb IS that word.
|
|
579
|
+
*/
|
|
580
|
+
WorkbenchBuildPlanTasks_Operations["ACCEPT"] = "accept";
|
|
229
581
|
})(WorkbenchBuildPlanTasks_Operations || (WorkbenchBuildPlanTasks_Operations = {}));
|
|
230
|
-
/** The write-record resource's dispatch
|
|
582
|
+
/** The write-record resource's dispatch verbs. */
|
|
231
583
|
export var WorkbenchRunWriteRecords_Operations;
|
|
232
584
|
(function (WorkbenchRunWriteRecords_Operations) {
|
|
233
585
|
/** Revert this run's writes. Files edited since are refused by name unless `force`. */
|
|
234
586
|
WorkbenchRunWriteRecords_Operations["REVERT"] = "revert_writes";
|
|
587
|
+
/**
|
|
588
|
+
* ACCEPT this run's writes: commit exactly the register's paths. A file that no longer holds the
|
|
589
|
+
* bytes the run wrote is refused by name unless `force` — the same divergence test `revert` applies,
|
|
590
|
+
* because in both directions a human edit is never silently swept into the run's account.
|
|
591
|
+
*/
|
|
592
|
+
WorkbenchRunWriteRecords_Operations["ACCEPT"] = "accept";
|
|
593
|
+
/**
|
|
594
|
+
* WHAT this run changed, per file — read on demand, one run at a time (#1274). Deliberately not a
|
|
595
|
+
* field of the LIST row: pre-image bytes "belong to the revert mechanism, and a list row carrying
|
|
596
|
+
* every pre-image would ship the working tree's history through every LIST". Computed from the
|
|
597
|
+
* register's own pre/post content, never from `git diff`, so it is the RUN's change and not
|
|
598
|
+
* everything uncommitted at those paths.
|
|
599
|
+
*/
|
|
600
|
+
WorkbenchRunWriteRecords_Operations["READ_DIFF"] = "read_diff";
|
|
235
601
|
})(WorkbenchRunWriteRecords_Operations || (WorkbenchRunWriteRecords_Operations = {}));
|
|
236
602
|
export const Workbench_PlaybookRunRequest_Schema = z.object({
|
|
237
603
|
/** Optional product brief forwarded to the derivation. */
|
|
@@ -247,12 +613,22 @@ export const Workbench_PlaybookRunRequest_Schema = z.object({
|
|
|
247
613
|
})).optional(),
|
|
248
614
|
/** Full pipe — generation, validation, rendering, judge — with NO filesystem writes. */
|
|
249
615
|
dryRun: z.boolean().optional(),
|
|
616
|
+
/**
|
|
617
|
+
* The opened INSTANCE to run (#1609); omitted runs the step itself. An instance nobody opened is refused,
|
|
618
|
+
* and its pre-answers are filed as that instance's answers, never the step's.
|
|
619
|
+
*/
|
|
620
|
+
instanceKey: z.string().min(1).optional(),
|
|
250
621
|
});
|
|
251
622
|
export const Workbench_PlaybookResumeRequest_Schema = z.object({
|
|
252
623
|
/** The suspended run being answered — the handle `run` returned when it stopped to ask. */
|
|
253
624
|
runId: z.string().min(1),
|
|
254
|
-
/**
|
|
255
|
-
|
|
625
|
+
/**
|
|
626
|
+
* WHICH round of its questions this answers, declines or cancels — the waiting row's `round` (#1584). A
|
|
627
|
+
* run asks again after an answer under the same `runId`; a round it has moved past is refused 409.
|
|
628
|
+
*/
|
|
629
|
+
round: z.number().int().min(1),
|
|
630
|
+
/** ACCEPT (every question answered), DECLINE (the rest delegated) or CANCEL — see `MetaWorkflow_ClarificationAction` (#1785). */
|
|
631
|
+
action: z.enum(MetaWorkflow_ClarificationAction),
|
|
256
632
|
answers: z.array(z.object({
|
|
257
633
|
ref: z.string().min(1),
|
|
258
634
|
answer: z.string().min(1),
|
|
@@ -267,10 +643,49 @@ export const Workbench_PlaybookResumeRequest_Schema = z.object({
|
|
|
267
643
|
* still takes a (currently empty) request body.
|
|
268
644
|
*/
|
|
269
645
|
export const Workbench_BuildPlanDispatchNextRequest_Schema = z.object({});
|
|
646
|
+
/**
|
|
647
|
+
* One task to append (#1454, Step 7). The `target` and `produces` shapes are owned by
|
|
648
|
+
* `@wildo-ai/saas-specifications` (`BuildPlanTaskSchema`), which this package deliberately does not
|
|
649
|
+
* depend on, so they cross here as records and the companion parses them against the real schema
|
|
650
|
+
* before anything is written. `taskRef` is derived from the objective when absent.
|
|
651
|
+
*/
|
|
652
|
+
export const Workbench_BuildPlanAddTaskRequest_Schema = z.object({
|
|
653
|
+
taskRef: z.string().min(1).optional(),
|
|
654
|
+
objective: z.string().min(1),
|
|
655
|
+
target: z.record(z.string(), z.unknown()),
|
|
656
|
+
produces: z.array(z.record(z.string(), z.unknown())),
|
|
657
|
+
functionalTopic: z.string().min(1),
|
|
658
|
+
skillRefs: z.array(z.string().min(1)).min(1),
|
|
659
|
+
prerequisiteTaskRefs: z.array(z.string().min(1)).optional(),
|
|
660
|
+
servesRefs: z.array(z.string().min(1)).optional(),
|
|
661
|
+
});
|
|
662
|
+
export const Workbench_BuildPlanDispatchTaskRequest_Schema = z.object({
|
|
663
|
+
/** The conversation this dispatch belongs to, so the thread shows the run as a card. */
|
|
664
|
+
conversationId: z.string().min(1).optional(),
|
|
665
|
+
});
|
|
666
|
+
export const Workbench_AcceptChangesRequest_Schema = z.object({
|
|
667
|
+
/** Commit paths that diverged since the run. NOT defaulted on — a human edit is never silently swept in. */
|
|
668
|
+
force: z.boolean().optional(),
|
|
669
|
+
});
|
|
270
670
|
export const Workbench_RunWriteRevertRequest_Schema = z.object({
|
|
271
671
|
/** Overwrite files edited since the run. NOT defaulted on — a human edit is never silently destroyed. */
|
|
272
672
|
force: z.boolean().optional(),
|
|
273
673
|
});
|
|
674
|
+
/**
|
|
675
|
+
* What a playbook run's answer says about the run, when it says anything (#1781). Absent on a run that
|
|
676
|
+
* concluded, or on a detached submission that is still going.
|
|
677
|
+
*
|
|
678
|
+
* One named home for a vocabulary the companion writes and several readers compare — the run record,
|
|
679
|
+
* the clarification lifecycle, the resume route, and the workbench's summary of a RESUME, which used
|
|
680
|
+
* to read every answer carrying a `runId` as "Started", a cancelled clarification included.
|
|
681
|
+
*/
|
|
682
|
+
export var Workbench_PlaybookRunOutcomeStatus;
|
|
683
|
+
(function (Workbench_PlaybookRunOutcomeStatus) {
|
|
684
|
+
/** Healthy, and waiting at a clarification: the run asked the creator something and holds until answered. */
|
|
685
|
+
Workbench_PlaybookRunOutcomeStatus["AWAITING_CREATOR_INPUT"] = "awaiting_creator_input";
|
|
686
|
+
/** The creator cancelled a clarification: the run was abandoned and does not continue. */
|
|
687
|
+
Workbench_PlaybookRunOutcomeStatus["CANCELLED"] = "cancelled";
|
|
688
|
+
})(Workbench_PlaybookRunOutcomeStatus || (Workbench_PlaybookRunOutcomeStatus = {}));
|
|
274
689
|
/**
|
|
275
690
|
* Dispatch RESPONSES are LOOSE objects, deliberately: each names the fields the board branches on
|
|
276
691
|
* and forwards the rest verbatim. The companion routes already spread the whole service result, and
|
|
@@ -279,19 +694,1105 @@ export const Workbench_RunWriteRevertRequest_Schema = z.object({
|
|
|
279
694
|
*/
|
|
280
695
|
export const Workbench_PlaybookRunOutcome_Schema = z.looseObject({
|
|
281
696
|
runId: z.string().optional(),
|
|
282
|
-
|
|
283
|
-
status: z.string().optional(),
|
|
697
|
+
status: z.enum(Workbench_PlaybookRunOutcomeStatus).optional(),
|
|
284
698
|
note: z.string().optional(),
|
|
285
699
|
});
|
|
286
700
|
export const Workbench_BuildPlanDispatchOutcome_Schema = z.looseObject({
|
|
287
701
|
taskRef: z.string().optional(),
|
|
288
702
|
note: z.string().optional(),
|
|
289
703
|
});
|
|
704
|
+
export const Workbench_BuildPlanAddTaskOutcome_Schema = z.looseObject({
|
|
705
|
+
taskRef: z.string().optional(),
|
|
706
|
+
/** TRUE when no plan existed and this task is its first. */
|
|
707
|
+
createdPlan: z.boolean().optional(),
|
|
708
|
+
/** Validator findings below the hard floor — worth telling the creator, never a refusal. */
|
|
709
|
+
advisoryFindings: z.array(z.object({ code: z.string(), taskRef: z.string(), message: z.string() })).optional(),
|
|
710
|
+
note: z.string().optional(),
|
|
711
|
+
});
|
|
712
|
+
/** How ACCEPT answers, for a task's coding run or a playbook run alike: what was committed, what was refused and why. */
|
|
713
|
+
export const Workbench_AcceptChangesOutcome_Schema = z.looseObject({
|
|
714
|
+
commitSha: z.string().optional(),
|
|
715
|
+
committedPaths: z.array(z.string()).optional(),
|
|
716
|
+
refusedPaths: z.array(z.object({ path: z.string(), reason: z.string() })).optional(),
|
|
717
|
+
message: z.string().optional(),
|
|
718
|
+
note: z.string().optional(),
|
|
719
|
+
});
|
|
290
720
|
export const Workbench_RunWriteRevertOutcome_Schema = z.looseObject({
|
|
291
721
|
runId: z.string().optional(),
|
|
292
722
|
reverted: z.array(z.string()).optional(),
|
|
293
723
|
/** Files whose current bytes differ from what the run wrote — refused by name, revertable with force. */
|
|
294
724
|
refusedDiverged: z.array(z.string()).optional(),
|
|
725
|
+
/**
|
|
726
|
+
* Files a LATER recorded run landed on (#1614): refused even under force, because the earlier bytes
|
|
727
|
+
* would destroy that run's work. Each names the run to revert first (#1666).
|
|
728
|
+
*/
|
|
729
|
+
refusedLaterRun: z.array(z.object({ path: z.string(), runId: z.string() })).optional(),
|
|
295
730
|
note: z.string().optional(),
|
|
296
731
|
});
|
|
732
|
+
/**
|
|
733
|
+
* One BUILD DISPATCH — an attempt to run one build-plan task.
|
|
734
|
+
*
|
|
735
|
+
* The lane's own history: what was selected, when, and how it ended. A task may be dispatched more
|
|
736
|
+
* than once (a failure is re-dispatchable), so the row is the ATTEMPT and `taskRef` is what groups
|
|
737
|
+
* them — the same relationship a run write record has to its playbook.
|
|
738
|
+
*/
|
|
739
|
+
/**
|
|
740
|
+
* The NEXT build task — what a dispatch would do, with nothing started. At most one row.
|
|
741
|
+
*
|
|
742
|
+
* ## Why a proposal is a row
|
|
743
|
+
*
|
|
744
|
+
* It looks like a computed answer rather than a record, and that is why it stayed a bespoke read
|
|
745
|
+
* longest. But everything a person asks of it is what they ask of a row: what is it, what may it
|
|
746
|
+
* touch, what must it pass, and how far through the plan are we. It has an identity (`taskRef`), it
|
|
747
|
+
* is polled, it is rendered as a card, and a dispatch acts on it.
|
|
748
|
+
*
|
|
749
|
+
* ## Distinct from the build-plan TASK, deliberately
|
|
750
|
+
*
|
|
751
|
+
* `workbenchBuildPlanTasks` is every task and its status. This is the SELECTION — which one is next,
|
|
752
|
+
* plus the guard rails a dispatch of it would carry (allowed paths, prohibited paths, required
|
|
753
|
+
* checks, installed skills), which belong to the dispatch rather than to the task. Two resources
|
|
754
|
+
* because they answer different questions; the task list never changes because a selection did.
|
|
755
|
+
*
|
|
756
|
+
* ## Zero rows means the build is FINISHED, not that the read failed
|
|
757
|
+
*
|
|
758
|
+
* The companion answers `plan: null` with an `exhausted` count for a completed build, and it is a
|
|
759
|
+
* 200. That used to be a non-2xx, so the end of the journey rendered as "could not look" — the board
|
|
760
|
+
* telling an operator something went wrong at the moment everything had gone right. The counts live
|
|
761
|
+
* on this row so the finished state can say how far it got.
|
|
762
|
+
*/
|
|
763
|
+
export const Workbench_BuildDispatchPlan_Schema = z.object({
|
|
764
|
+
/** The task's ref, sanitized — a task ref carries dots. */
|
|
765
|
+
workbenchBuildDispatchPlanId: z.string().min(1).isPrimaryKey().isSummaryField(),
|
|
766
|
+
/** The task a dispatch would run. NULL exactly when the build is exhausted. */
|
|
767
|
+
taskRef: z.string().min(1).isSummaryField().nullable(),
|
|
768
|
+
/** What it is for, in the plan's own words. */
|
|
769
|
+
objective: z.string().min(1).isSummaryField().nullable(),
|
|
770
|
+
/** What kind of thing it produces. */
|
|
771
|
+
targetKind: z.string().min(1).isSummaryField().nullable(),
|
|
772
|
+
/** Present exactly when the next task is a companion GENERATION step rather than a coding task. */
|
|
773
|
+
generationStepRef: z.string().min(1).isSummaryField().nullable(),
|
|
774
|
+
/** Where a dispatch of it MAY write. */
|
|
775
|
+
allowedPathPrefixes: z.array(z.string().min(1)).isSummaryField(),
|
|
776
|
+
/** Where it may NOT, whatever the agent decides. */
|
|
777
|
+
prohibitedPathPrefixes: z.array(z.string().min(1)).isSummaryField(),
|
|
778
|
+
/** What its work must pass before it counts as done. */
|
|
779
|
+
requiredChecks: z.array(z.string().min(1)).isSummaryField(),
|
|
780
|
+
/** The framework knowledge the agent is given for it. */
|
|
781
|
+
installedSkillRefs: z.array(z.string().min(1)).isSummaryField(),
|
|
782
|
+
/** Every task that could run right now — this one is the head of that queue. */
|
|
783
|
+
readyTaskRefs: z.array(z.string().min(1)).isSummaryField(),
|
|
784
|
+
/** Every task already landed. */
|
|
785
|
+
landedTaskRefs: z.array(z.string().min(1)).isSummaryField(),
|
|
786
|
+
/**
|
|
787
|
+
* The subset of `landedTaskRefs` that landed WITHOUT PROOF — a task declaring no product, which
|
|
788
|
+
* ran and therefore cannot be held against the queue, but whose work nothing verified.
|
|
789
|
+
*
|
|
790
|
+
* Empty and "not reported" are the same array here, which is the one thing this loses against the
|
|
791
|
+
* optional wire field it replaced. That is acceptable because the board never rendered a count: it
|
|
792
|
+
* names the refs, and naming none is what an empty list looks like either way.
|
|
793
|
+
*/
|
|
794
|
+
unverifiableLandedTaskRefs: z.array(z.string().min(1)).isSummaryField(),
|
|
795
|
+
/** TRUE when there is no next task because every one has landed. */
|
|
796
|
+
exhausted: z.boolean().isSummaryField(),
|
|
797
|
+
/**
|
|
798
|
+
* Every READY task dispatch passed over because it cannot make progress, and why (#1451).
|
|
799
|
+
*
|
|
800
|
+
* Present on BOTH kinds of row. Beside a next task it names what that selection skipped; with no
|
|
801
|
+
* next task and `exhausted` false it IS the answer: nothing ready can run. That state used to fail
|
|
802
|
+
* the read, so the board said "could not look" at the one moment it had a precise answer.
|
|
803
|
+
*
|
|
804
|
+
* Typed facts rather than a sentence: the remedy's WORDS belong to the reason
|
|
805
|
+
* (`system_enums.Workbench_BuildTaskStuckReason`), and each reason carries only the facts its
|
|
806
|
+
* remedy needs.
|
|
807
|
+
*/
|
|
808
|
+
stuckTasks: z.array(z.object({
|
|
809
|
+
taskRef: z.string().min(1),
|
|
810
|
+
reason: z.enum(Workbench_BuildTaskStuckReason).systemEnum('Workbench_BuildTaskStuckReason'),
|
|
811
|
+
/** The run that proves it is stuck; NULL for a task that is unbuildable before any run. */
|
|
812
|
+
priorTaskId: z.string().min(1).nullable(),
|
|
813
|
+
/** `completed_awaiting_commit` only: the probed paths present in the working tree and not committed. */
|
|
814
|
+
uncommittedPaths: z.array(z.string().min(1)),
|
|
815
|
+
/** `parked_awaiting_answer` (and a parked `no_document_blueprint`): the question the run is waiting on. */
|
|
816
|
+
question: z.string().min(1).nullable(),
|
|
817
|
+
/** `no_document_blueprint` only: the governed document the catalog does not define. */
|
|
818
|
+
documentRef: z.string().min(1).nullable(),
|
|
819
|
+
})).isSummaryField(),
|
|
820
|
+
/** How many tasks the plan holds. Meaningful on the exhausted row, where it is the total reached. */
|
|
821
|
+
taskCount: z.number().int().isSummaryField(),
|
|
822
|
+
/** How many have landed. */
|
|
823
|
+
landedCount: z.number().int().isSummaryField(),
|
|
824
|
+
});
|
|
825
|
+
export const Workbench_BuildDispatch_Schema = z.object({
|
|
826
|
+
/** Emitted by the behavior as `<taskRef>--<startedAt>`, sanitized — a task can be dispatched twice. */
|
|
827
|
+
workbenchBuildDispatchId: z.string().min(1).isPrimaryKey().isSummaryField(),
|
|
828
|
+
/** The build-plan task this attempt ran. */
|
|
829
|
+
taskRef: z.string().min(1).isSummaryField(),
|
|
830
|
+
/**
|
|
831
|
+
* What the task delivers, in its own sentence — joined from the plan by `taskRef` so a card, a pane
|
|
832
|
+
* title and a Home line name the run by what it does rather than by its key (#1454, gap 1). NULL when
|
|
833
|
+
* the plan no longer holds the task (a plan re-decomposed since): the ref is then the only name.
|
|
834
|
+
*/
|
|
835
|
+
objective: z.string().min(1).isSummaryField().nullable(),
|
|
836
|
+
/**
|
|
837
|
+
* How the attempt ended, or that it has not.
|
|
838
|
+
*
|
|
839
|
+
* `.systemEnum(...)` so the four words are authored ONCE for the enum rather than per field path:
|
|
840
|
+
* the frontend's label cascade reads only the vocabulary a field DECLARES, and without it every
|
|
841
|
+
* surface renders the raw constant.
|
|
842
|
+
*/
|
|
843
|
+
phase: z.enum(Workbench_BuildDispatchPhase).systemEnum('Workbench_BuildDispatchPhase').isSummaryField(),
|
|
844
|
+
/** When the dispatch was handed to its executor. */
|
|
845
|
+
startedAt: z.date().isSummaryField(),
|
|
846
|
+
/** When the phase left SUBMITTED. NULL while it has not — a dispatch still running has no end. */
|
|
847
|
+
settledAt: z.date().isSummaryField().nullable(),
|
|
848
|
+
/**
|
|
849
|
+
* The durable actor-task row a coding run produced, when one was admitted.
|
|
850
|
+
*
|
|
851
|
+
* NULL for a generation step (there is no coding task) and for a dispatch that failed before
|
|
852
|
+
* admission. It is the edge from this lane into the control plane, which is why it is a foreign
|
|
853
|
+
* key rather than a printed id.
|
|
854
|
+
*/
|
|
855
|
+
codingTaskId: z.string().min(1).isForeignKey().isSummaryField().nullable(),
|
|
856
|
+
/** Why it failed, verbatim. NULL on every dispatch that did not. */
|
|
857
|
+
error: z.string().min(1).isSummaryField().nullable(),
|
|
858
|
+
/**
|
|
859
|
+
* The conversation the dispatch was started from (#1454, Step 7), so the thread shows it as a
|
|
860
|
+
* card. NULL for a dispatch started from the plan's next-task door or before conversations existed.
|
|
861
|
+
*/
|
|
862
|
+
conversationId: z.string().min(1).isSummaryField().nullable(),
|
|
863
|
+
/**
|
|
864
|
+
* Whether the coding run's writes have been ACCEPTED — committed through the `accept` verb, or
|
|
865
|
+
* found already committed. NULL when there is nothing to accept: a generation step, a failed run,
|
|
866
|
+
* a run that wrote nothing, or a run older than the coding-run write register.
|
|
867
|
+
*/
|
|
868
|
+
accepted: z.boolean().isSummaryField().nullable(),
|
|
869
|
+
});
|
|
870
|
+
/**
|
|
871
|
+
* One playbook run SUSPENDED waiting on a person.
|
|
872
|
+
*
|
|
873
|
+
* The run stopped mid-way and asked something. The row carries where it stopped and what it asked,
|
|
874
|
+
* because both are what a creator needs to answer it — a question with no run context is a question
|
|
875
|
+
* nobody can answer.
|
|
876
|
+
*/
|
|
877
|
+
/**
|
|
878
|
+
* WHERE a playbook run is in its life — the one field that decides how its row reads.
|
|
879
|
+
*
|
|
880
|
+
* ## Why one vocabulary and not four collections
|
|
881
|
+
*
|
|
882
|
+
* The companion answers `{ running, runningDetached, interrupted, lastCompleted }`, and a board
|
|
883
|
+
* reading that shape has to know which array means what before it can render anything. They are not
|
|
884
|
+
* four kinds of thing: they are one thing — a run of a playbook — in four states, and the fields that
|
|
885
|
+
* differ between them (a finish time, a verdict, a checkpoint) are exactly the fields a state decides
|
|
886
|
+
* the presence of. Naming the state makes that explicit and makes the row renderable by one layout.
|
|
887
|
+
*
|
|
888
|
+
* The distinction that matters most is RUNNING vs RUNNING_DETACHED, and it is not cosmetic: the
|
|
889
|
+
* first is a composite holding its instance's single-flight subject and never an ordinary run, so a board
|
|
890
|
+
* that read it alone reported "nothing is running" while a fifteen-minute run was in flight.
|
|
891
|
+
*/
|
|
892
|
+
export var Workbench_PlaybookRunState;
|
|
893
|
+
(function (Workbench_PlaybookRunState) {
|
|
894
|
+
/** A composite holding its instance's single-flight subject (#1610): one per running instance, several at once, never an ordinary run. */
|
|
895
|
+
Workbench_PlaybookRunState["RUNNING"] = "running";
|
|
896
|
+
/** An ordinary run this companion process is executing right now. */
|
|
897
|
+
Workbench_PlaybookRunState["RUNNING_DETACHED"] = "running_detached";
|
|
898
|
+
/** A run that stopped without finishing and left a checkpoint that can be re-run. */
|
|
899
|
+
Workbench_PlaybookRunState["INTERRUPTED"] = "interrupted";
|
|
900
|
+
/** The most recent outcome for a playbook ref — settled, with a verdict. */
|
|
901
|
+
Workbench_PlaybookRunState["COMPLETED"] = "completed";
|
|
902
|
+
/**
|
|
903
|
+
* A run that STOPPED TO ASK and is waiting on a person — not running, not finished, no verdict.
|
|
904
|
+
*
|
|
905
|
+
* It borrowed COMPLETED until 2026-09-24, flagged by `awaitingFamily`, so every reader had to remember that one
|
|
906
|
+
* "completed" row was not complete. The outcome reader remembered; Home did not, and told the creator a dry run
|
|
907
|
+
* waiting on their answer had "ran and landed its result" (#1271). A state that has to be un-said by another field
|
|
908
|
+
* is a missing member of its vocabulary.
|
|
909
|
+
*/
|
|
910
|
+
Workbench_PlaybookRunState["AWAITING_ANSWER"] = "awaiting_answer";
|
|
911
|
+
})(Workbench_PlaybookRunState || (Workbench_PlaybookRunState = {}));
|
|
912
|
+
/**
|
|
913
|
+
* One playbook run, in whatever state it is in.
|
|
914
|
+
*
|
|
915
|
+
* Kept ONE-PER-REF for the completed state by the companion, so a COMPLETED row is the last run of
|
|
916
|
+
* that playbook and never a history of it.
|
|
917
|
+
*/
|
|
918
|
+
export const Workbench_PlaybookRun_Schema = z.object({
|
|
919
|
+
/** The row's own id, sanitized — run ids carry dots (see the playbook id note). */
|
|
920
|
+
workbenchPlaybookRunId: z.string().min(1).isPrimaryKey().isSummaryField(),
|
|
921
|
+
/**
|
|
922
|
+
* The run id as the companion records it. NULL only for an INTERRUPTED entry, which the companion
|
|
923
|
+
* knows by the checkpoint it left (its playbook and instance), not by a run.
|
|
924
|
+
*/
|
|
925
|
+
runId: z.string().min(1).isSummaryField().nullable(),
|
|
926
|
+
/** The playbook this run is of. Every state has one; it is how a run is known. */
|
|
927
|
+
playbookRef: z.string().min(1).isSummaryField(),
|
|
928
|
+
/**
|
|
929
|
+
* The playbook INSTANCE this run is of (#1609), or null for a run of the step itself. Two instances of
|
|
930
|
+
* one playbook run and settle side by side, so a reader telling runs apart by playbook alone would show
|
|
931
|
+
* one instance's outcome as the other's.
|
|
932
|
+
*/
|
|
933
|
+
instanceKey: z.string().min(1).isSummaryField().nullable(),
|
|
934
|
+
/**
|
|
935
|
+
* The execution-trace session the run recorded under, as the companion RECORDED it at run time.
|
|
936
|
+
* NULL when the request carried no session, and for the RUNNING and INTERRUPTED states.
|
|
937
|
+
*
|
|
938
|
+
* Recorded rather than derived (#1358): a run id used to be `<sessionId>-<playbookRef>-<ts>` and the
|
|
939
|
+
* board recovered the session by longest-prefix match. The run id is the actor execution's own id
|
|
940
|
+
* now, which says nothing about a session, so the join has to be a field.
|
|
941
|
+
*/
|
|
942
|
+
traceSessionId: z.string().min(1).isSummaryField().nullable(),
|
|
943
|
+
/**
|
|
944
|
+
* The creation CONVERSATION the run was started from, when it was — the engine conversational
|
|
945
|
+
* execution's `executionId`, read from the run's correlation envelope (#1454). The conversation
|
|
946
|
+
* page joins a thread to its run cards on this key; `null` for a run started from the board, the
|
|
947
|
+
* CLI, or a choreography.
|
|
948
|
+
*/
|
|
949
|
+
conversationId: z.string().min(1).isSummaryField().nullable(),
|
|
950
|
+
state: z.enum(Workbench_PlaybookRunState).systemEnum('Workbench_PlaybookRunState').isSummaryField(),
|
|
951
|
+
/** When it started. NULL for an INTERRUPTED entry, which records only when it checkpointed. */
|
|
952
|
+
startedAt: z.date().isSummaryField().nullable(),
|
|
953
|
+
/** When it settled. Present only for COMPLETED — a run AWAITING_ANSWER has not settled. */
|
|
954
|
+
finishedAt: z.date().isSummaryField().nullable(),
|
|
955
|
+
/**
|
|
956
|
+
* The run's own verdict, for COMPLETED only.
|
|
957
|
+
*
|
|
958
|
+
* TRUE for a run that SUSPENDED to ask, which is why `awaitingCreatorInput` below has to be read
|
|
959
|
+
* beside it: `ok` records whether the run threw, and a suspension does not throw. A board reading
|
|
960
|
+
* `ok` alone rendered a green "completed" badge for a run waiting on a person — the worst available
|
|
961
|
+
* lie, because their correct next action is to answer it and "completed" reads as no action at all.
|
|
962
|
+
*/
|
|
963
|
+
ok: z.boolean().isSummaryField().nullable(),
|
|
964
|
+
/**
|
|
965
|
+
* Why it failed, verbatim.
|
|
966
|
+
*
|
|
967
|
+
* A validation refusal an async submission could not throw — an unanswered elicitation, an
|
|
968
|
+
* ineligible playbook — surfaces HERE rather than as an HTTP error, which is the whole reason the
|
|
969
|
+
* board must render it.
|
|
970
|
+
*/
|
|
971
|
+
error: z.string().min(1).isSummaryField().nullable(),
|
|
972
|
+
/** How many iterations a checkpointed run completed. INTERRUPTED only. */
|
|
973
|
+
completedIterations: z.number().int().isSummaryField().nullable(),
|
|
974
|
+
/** When it checkpointed. INTERRUPTED only. */
|
|
975
|
+
checkpointedAt: z.date().isSummaryField().nullable(),
|
|
976
|
+
/** The family a suspended run was producing when it stopped to ask. Present only when it did. */
|
|
977
|
+
awaitingFamily: z.string().min(1).isSummaryField().nullable(),
|
|
978
|
+
/** Which round of asking a suspended run reached. Present only when it stopped to ask. */
|
|
979
|
+
awaitingRound: z.number().int().isSummaryField().nullable(),
|
|
980
|
+
/**
|
|
981
|
+
* The ADVISORY judge's verdict over the run's landed artifacts — the worst criterion, in
|
|
982
|
+
* PASS < CONCERN < INDETERMINATE < GAP order. COMPLETED only, and NULL when the judge did not run
|
|
983
|
+
* (`judgeSkipped` says why) or the playbook declares no evaluation (#1329).
|
|
984
|
+
*
|
|
985
|
+
* Lifted onto the row from the run's own result envelope, where it always was, because the
|
|
986
|
+
* timeline row and the detail's verdict tab both need it and `events.ndjson` — the only other
|
|
987
|
+
* place it lives — is a second call per run.
|
|
988
|
+
*/
|
|
989
|
+
judgeOverall: z.enum(MetaWorkflow_EvaluationVerdict).systemEnum('MetaWorkflow_EvaluationVerdict').isSummaryField().nullable(),
|
|
990
|
+
/** The per-criterion verdicts behind `judgeOverall`, with the judge's rationale for each. */
|
|
991
|
+
judgeCriteria: z.array(z.object({
|
|
992
|
+
criterionRef: z.string().min(1),
|
|
993
|
+
verdict: z.enum(MetaWorkflow_EvaluationVerdict).systemEnum('MetaWorkflow_EvaluationVerdict'),
|
|
994
|
+
rationale: z.string(),
|
|
995
|
+
})).nullable(),
|
|
996
|
+
/** Why the judge stayed silent, in its own words — a failed call, or an evaluation that never ran. */
|
|
997
|
+
judgeSkipped: z.string().min(1).nullable(),
|
|
998
|
+
});
|
|
999
|
+
export const Workbench_WaitingPlaybookRun_Schema = z.object({
|
|
1000
|
+
/** The run's own id, sanitized — run ids carry dots (see the playbook id note). */
|
|
1001
|
+
workbenchWaitingPlaybookRunId: z.string().min(1).isPrimaryKey().isSummaryField(),
|
|
1002
|
+
/** The run id as the companion records it. */
|
|
1003
|
+
runId: z.string().min(1).isSummaryField(),
|
|
1004
|
+
/**
|
|
1005
|
+
* Whether the checkpoint on disk could be READ.
|
|
1006
|
+
*
|
|
1007
|
+
* FALSE is a real row, not an omission. A checkpoint file that exists and fails to parse is a
|
|
1008
|
+
* suspended run an operator must deal with — the run is stopped, nothing will resume it, and the
|
|
1009
|
+
* remedy is to inspect or remove that file. Dropping it would make a stuck lane look like an idle
|
|
1010
|
+
* one, and the only thing knowable about such a run is its id, which is why every descriptive
|
|
1011
|
+
* field below is nullable.
|
|
1012
|
+
*
|
|
1013
|
+
* This is what keeps the resource TOTAL over what the companion knows. The bespoke read it
|
|
1014
|
+
* replaced carried the same fact in a separate `unreadable: string[]` beside the rows, which no
|
|
1015
|
+
* resource lane could express and which therefore had no way to reach a row template.
|
|
1016
|
+
*/
|
|
1017
|
+
readable: z.boolean().isSummaryField(),
|
|
1018
|
+
/** The playbook that was running. NULL when the checkpoint could not be read. */
|
|
1019
|
+
playbookRef: z.string().min(1).isSummaryField().nullable(),
|
|
1020
|
+
/** The family it was producing when it stopped. NULL when the checkpoint could not be read. */
|
|
1021
|
+
family: z.string().min(1).isSummaryField().nullable(),
|
|
1022
|
+
/** When it suspended. NULL when the checkpoint could not be read. */
|
|
1023
|
+
suspendedAt: z.date().isSummaryField().nullable(),
|
|
1024
|
+
/** Which round of asking this is — a run may stop more than once. NULL when unreadable. */
|
|
1025
|
+
round: z.number().int().isSummaryField().nullable(),
|
|
1026
|
+
/** Whether the suspended run was a dry run, which changes what answering it will write. */
|
|
1027
|
+
dryRun: z.boolean().isSummaryField().nullable(),
|
|
1028
|
+
/** What it is waiting to be told. */
|
|
1029
|
+
requests: z.array(z.object({
|
|
1030
|
+
ref: z.string().min(1),
|
|
1031
|
+
/** The question as a person reads it. */
|
|
1032
|
+
question: z.string().min(1),
|
|
1033
|
+
/** Why the run needs it — what it cannot decide without an answer. */
|
|
1034
|
+
why: z.string().min(1),
|
|
1035
|
+
/**
|
|
1036
|
+
* The question's shape. A plain string by this tier's contract: the vocabulary is
|
|
1037
|
+
* `HumanDecision_FieldKind` in `saas-specifications`, which this package
|
|
1038
|
+
* deliberately does not import.
|
|
1039
|
+
*/
|
|
1040
|
+
kind: z.string().min(1),
|
|
1041
|
+
/** The closed answer set, when the question has one. */
|
|
1042
|
+
options: z.array(z.string().min(1)),
|
|
1043
|
+
})).isSummaryField(),
|
|
1044
|
+
/**
|
|
1045
|
+
* The signed-in person the question is ROUTED to (#1751): whoever started the run from the workbench or
|
|
1046
|
+
* the conversation. Only they may answer it; anybody else is refused as if nothing waited. NULL when the
|
|
1047
|
+
* question is unrouted (a run started from the console) or the checkpoint could not be read.
|
|
1048
|
+
*/
|
|
1049
|
+
routedToUserId: z.string().min(1).isSummaryField().nullable(),
|
|
1050
|
+
});
|
|
1051
|
+
/**
|
|
1052
|
+
* One coding run PARKED on a question.
|
|
1053
|
+
*
|
|
1054
|
+
* It arrives inside the coding-agent status payload, which is a singleton and stays a companion
|
|
1055
|
+
* read. These do not: a parked question is identified by the task that parked on it, it persists
|
|
1056
|
+
* until somebody answers, and a queue of work waiting on a person is the last thing that should be
|
|
1057
|
+
* reachable only by reading a status blob.
|
|
1058
|
+
*/
|
|
1059
|
+
/**
|
|
1060
|
+
* The coding lane's own posture — ONE row, always present.
|
|
1061
|
+
*
|
|
1062
|
+
* ## Why a singleton resource rather than the read it replaced
|
|
1063
|
+
*
|
|
1064
|
+
* It was a companion read answering a status object, and that read ALSO carried the parked
|
|
1065
|
+
* questions — a queue keyed by task id — inside it. Two different things in one payload: a queue of
|
|
1066
|
+
* work waiting on a person, and a statement about the lane. The queue is
|
|
1067
|
+
* `workbenchParkedCodingQuestions`; this is what remains, and it is genuinely one row.
|
|
1068
|
+
*
|
|
1069
|
+
* ## What each field is careful about
|
|
1070
|
+
*
|
|
1071
|
+
* `codingAgentRegistered` reports exactly what the dispatch service can ESTABLISH — that every
|
|
1072
|
+
* declared agent resolves in the registry — and deliberately does not claim the transport is usable,
|
|
1073
|
+
* because that depends on the provider configuration and on a process it has not started. Anything
|
|
1074
|
+
* reading this must not upgrade it to "ready".
|
|
1075
|
+
*
|
|
1076
|
+
* `activeRunTaskId` being NULL does not mean idle. A run that parks on a question clears it while
|
|
1077
|
+
* staying very much alive, so a badge derived from this field alone read "idle" with a question
|
|
1078
|
+
* outstanding — which is why the parked queue has to be read beside it.
|
|
1079
|
+
*/
|
|
1080
|
+
export const Workbench_CodingLaneStatus_Schema = z.object({
|
|
1081
|
+
/** One row, one id. The projection stamps a constant: there is exactly one coding lane. */
|
|
1082
|
+
workbenchCodingLaneStatusId: z.string().min(1).isPrimaryKey().isSummaryField(),
|
|
1083
|
+
/** Every declared coding agent resolves in the registry. NOT a claim that the transport works. */
|
|
1084
|
+
codingAgentRegistered: z.boolean().isSummaryField(),
|
|
1085
|
+
/**
|
|
1086
|
+
* The coding agent this host dispatches to (a provider ref: `anthropic`, `openai`, `opencode`).
|
|
1087
|
+
* NULL when the selection cannot be resolved (#1637).
|
|
1088
|
+
*/
|
|
1089
|
+
codingAgentProviderRef: z.string().min(1).isSummaryField().nullable(),
|
|
1090
|
+
/**
|
|
1091
|
+
* Whether that agent's operator is signed in on this host, read from the agent's own status command
|
|
1092
|
+
* without a model call — what `codingAgentRegistered` cannot say: a registered agent with no login
|
|
1093
|
+
* fails every run on its first prompt. `false` means a definite "not signed in" — the one state a
|
|
1094
|
+
* dispatch refuses on. NULL when the state could not be read, and when the agent's status command is not
|
|
1095
|
+
* installed: the Claude and Codex agents run through adapters that do not need it, so its absence says
|
|
1096
|
+
* nothing about the login; {@link codingAgentLoginRemedy} then names the install (#1637).
|
|
1097
|
+
*/
|
|
1098
|
+
codingAgentSignedIn: z.boolean().isSummaryField().nullable(),
|
|
1099
|
+
/** What the status command reported, in one line. NULL when nothing was read. */
|
|
1100
|
+
codingAgentLoginDetail: z.string().nullable(),
|
|
1101
|
+
/** What to do when the agent is not signed in — the login or install command. NULL when nothing is owed. */
|
|
1102
|
+
codingAgentLoginRemedy: z.string().nullable(),
|
|
1103
|
+
/**
|
|
1104
|
+
* The durable actor-task row of the run in flight — the edge from this lane into the control
|
|
1105
|
+
* plane, which is why it is a foreign key rather than a printed id. NULL when none is running,
|
|
1106
|
+
* INCLUDING while a run is parked on a question.
|
|
1107
|
+
*/
|
|
1108
|
+
activeRunTaskId: z.string().min(1).isForeignKey().isSummaryField().nullable(),
|
|
1109
|
+
/** When the run in flight started. NULL when none is running. */
|
|
1110
|
+
activeRunStartedAt: z.date().isSummaryField().nullable(),
|
|
1111
|
+
/** The workspace mutation lock — one coding run at a time, and this is the file that says so. */
|
|
1112
|
+
lockFilePath: z.string().min(1).isSummaryField().nullable(),
|
|
1113
|
+
/** What a dispatch gets when it asks for no timeout of its own (ms). */
|
|
1114
|
+
defaultTimeoutMs: z.number().int(),
|
|
1115
|
+
/** The ceiling a dispatch cannot ask past (ms) — the answer to "why did my long run stop". */
|
|
1116
|
+
hardMaxTimeoutMs: z.number().int(),
|
|
1117
|
+
/** How much of an agent's output is captured by default (bytes). */
|
|
1118
|
+
defaultMaxCapturedBytes: z.number().int(),
|
|
1119
|
+
/** The capture ceiling (bytes). */
|
|
1120
|
+
hardMaxCapturedBytes: z.number().int(),
|
|
1121
|
+
});
|
|
1122
|
+
/**
|
|
1123
|
+
* The option refs a parked coding run offers. Closed, because the caller BRANCHES on which came back.
|
|
1124
|
+
*
|
|
1125
|
+
* Both are real decisions here, unlike a playbook interview — which offers only "run with these
|
|
1126
|
+
* answers", because declining an interview settles nothing that is waiting. A parked run IS waiting:
|
|
1127
|
+
* answering resumes the same session, and cancelling ends the run.
|
|
1128
|
+
*
|
|
1129
|
+
* ## Why it lives HERE rather than in the companion that mints it
|
|
1130
|
+
*
|
|
1131
|
+
* Both ends need it and neither can import the other: the companion projects a parked run as a
|
|
1132
|
+
* decision, and the workbench reconstructs that decision from the ROW to render the answer form. It
|
|
1133
|
+
* was declared in the companion alone until 2026-09-19, which meant a browser wanting to branch on
|
|
1134
|
+
* an option had to re-spell the two values — a second copy of a closed vocabulary, compiling
|
|
1135
|
+
* perfectly and free to drift.
|
|
1136
|
+
*/
|
|
1137
|
+
export var Workbench_ParkedCodingQuestionOptionRef;
|
|
1138
|
+
(function (Workbench_ParkedCodingQuestionOptionRef) {
|
|
1139
|
+
Workbench_ParkedCodingQuestionOptionRef["ANSWER"] = "answer";
|
|
1140
|
+
Workbench_ParkedCodingQuestionOptionRef["CANCEL"] = "cancel";
|
|
1141
|
+
})(Workbench_ParkedCodingQuestionOptionRef || (Workbench_ParkedCodingQuestionOptionRef = {}));
|
|
1142
|
+
/** The single field a parked run asks: the agent's own question, verbatim. */
|
|
1143
|
+
export const WORKBENCH_PARKED_CODING_QUESTION_FIELD_REF = 'answer';
|
|
1144
|
+
export const Workbench_ParkedCodingQuestion_Schema = z.object({
|
|
1145
|
+
/** The parked task's id, sanitized. */
|
|
1146
|
+
workbenchParkedCodingQuestionId: z.string().min(1).isPrimaryKey().isSummaryField(),
|
|
1147
|
+
/** The durable actor-task row that parked — the edge into the control plane. */
|
|
1148
|
+
taskId: z.string().min(1).isForeignKey().isSummaryField(),
|
|
1149
|
+
/** The build-plan task it was running. */
|
|
1150
|
+
taskRef: z.string().min(1).isSummaryField(),
|
|
1151
|
+
/** What the run is asking. */
|
|
1152
|
+
question: z.string().min(1).isSummaryField(),
|
|
1153
|
+
/** When it parked. */
|
|
1154
|
+
parkedAt: z.date().isSummaryField(),
|
|
1155
|
+
/**
|
|
1156
|
+
* Whether the SAME session can be re-entered.
|
|
1157
|
+
*
|
|
1158
|
+
* False is not a refusal: answering still works, but it starts a new session that must restate the
|
|
1159
|
+
* task context. Carried because it changes what answering COSTS, which is a thing a creator weighs
|
|
1160
|
+
* before answering rather than after.
|
|
1161
|
+
*/
|
|
1162
|
+
resumable: z.boolean().isSummaryField(),
|
|
1163
|
+
/**
|
|
1164
|
+
* WHICH of the run's questions this row shows — opaque, echoed back by an answer (#1581, eighth review).
|
|
1165
|
+
* A run may ask again after an answer, under the same task id, so the task id alone cannot say which
|
|
1166
|
+
* question a person was looking at when they typed; an answer carrying this continues only that one.
|
|
1167
|
+
*/
|
|
1168
|
+
suspensionRef: z.string().min(1),
|
|
1169
|
+
});
|
|
1170
|
+
/**
|
|
1171
|
+
* One dossier entry: a question a playbook declares, and what the creator said to it, if anything.
|
|
1172
|
+
*
|
|
1173
|
+
* The identity is the pair (`playbookRef`, `questionRef`), sanitized — the key the `creator-inputs`
|
|
1174
|
+
* family stores answers under, so the page addresses an answer the way the file does. The
|
|
1175
|
+
* question's own text, kind and options are carried on the row (from the compiled catalog) so a
|
|
1176
|
+
* surface can ASK it without a second read.
|
|
1177
|
+
*/
|
|
1178
|
+
export const Workbench_DossierEntry_Schema = z.object({
|
|
1179
|
+
/** EMITTED BY THE BEHAVIOR through `workbenchDossierEntryIdentity`. */
|
|
1180
|
+
workbenchDossierEntryId: z.string().min(1).isPrimaryKey().isSummaryField(),
|
|
1181
|
+
playbookRef: z.string().min(1).isSummaryField(),
|
|
1182
|
+
questionRef: z.string().min(1).isSummaryField(),
|
|
1183
|
+
/**
|
|
1184
|
+
* The INSTANCE of the step this question is asked for (#1609), or null for the step itself. An opened
|
|
1185
|
+
* instance asks its own questions, so the same question appears once per instance; an instance that
|
|
1186
|
+
* has not answered one falls back to the step's own answer when it runs.
|
|
1187
|
+
*/
|
|
1188
|
+
instanceKey: z.string().nullable().isSummaryField(),
|
|
1189
|
+
/** What the instance was opened FOR, in the creator's words; null for the step itself. */
|
|
1190
|
+
instancePurpose: z.string().nullable().isSummaryField(),
|
|
1191
|
+
/** The authored question, verbatim from the playbook. */
|
|
1192
|
+
question: z.string().min(1).isSummaryField(),
|
|
1193
|
+
/**
|
|
1194
|
+
* `free_text` | `choice` | `confirm` — `HumanDecision_FieldKind`, carried as a STRING for the same
|
|
1195
|
+
* reason `phase` is above: the vocabulary is the engine's, this package restates none of it.
|
|
1196
|
+
*/
|
|
1197
|
+
kind: z.string().min(1).isSummaryField(),
|
|
1198
|
+
/** The closed set for a `choice` question; empty otherwise. */
|
|
1199
|
+
options: z.array(z.string()).isSummaryField(),
|
|
1200
|
+
/** Where the question sits in its playbook's interview, 0-based — the order a scripted interview asks in. */
|
|
1201
|
+
position: z.number().int().min(0).isSummaryField(),
|
|
1202
|
+
standing: z.enum(WorkbenchDossierEntryStanding).systemEnum('WorkbenchDossierEntryStanding').isSummaryField(),
|
|
1203
|
+
/** The answer as stored, when there is one. */
|
|
1204
|
+
value: z.string().nullable().isSummaryField(),
|
|
1205
|
+
answeredAt: z.date().nullable().isSummaryField(),
|
|
1206
|
+
answeredByRef: z.string().nullable().isSummaryField(),
|
|
1207
|
+
/** Whether the asking playbook can run right now — a needed answer for an eligible playbook is what blocks something. */
|
|
1208
|
+
playbookEligible: z.boolean().isSummaryField(),
|
|
1209
|
+
/**
|
|
1210
|
+
* ASKED OF YOU NOW: still needed AND the asking playbook can run — the one state that blocks
|
|
1211
|
+
* something. Derived by the projection from the two facts above, and a declared LIST filter, so
|
|
1212
|
+
* "what waits on me" is one server-side question rather than a page's own arithmetic.
|
|
1213
|
+
*/
|
|
1214
|
+
askedNow: z.boolean().isSummaryField(),
|
|
1215
|
+
/**
|
|
1216
|
+
* CHANGING THIS AFFECTS: every family the answer feeds — what the asking playbook produces and
|
|
1217
|
+
* everything downstream of it (#1454, Step 8). Derived by the companion from the catalog's declared
|
|
1218
|
+
* inputs and outputs, so a person sees the reach of an answer before saving it, and a family
|
|
1219
|
+
* derived before the answer changed reads as stale on its playbook.
|
|
1220
|
+
*/
|
|
1221
|
+
affectsFamilies: z.array(z.string()).isSummaryField(),
|
|
1222
|
+
/**
|
|
1223
|
+
* WHAT THE QUESTION IS ABOUT, on the axis the artifact list groups families by (#1454, gap 4): the
|
|
1224
|
+
* concern of the family the asking step produces — or, for a step that produces none, of the first
|
|
1225
|
+
* family its answer reaches. The dossier groups by it, so a creator reads "why it exists", "how it
|
|
1226
|
+
* gets built" and "what it must promise" rather than three lists organised by machinery.
|
|
1227
|
+
*/
|
|
1228
|
+
subject: z.enum(WorkbenchSpecificationArtifactConcern).systemEnum('WorkbenchSpecificationArtifactConcern').isSummaryField(),
|
|
1229
|
+
/**
|
|
1230
|
+
* OUT OF DATE: answered, and a step READING this answer made its result before one of the answers it
|
|
1231
|
+
* reads changed (its stale outputs list `creator-inputs`; #1454, gap 4 and its review). Derived from `outOfDateStepRefs` (non-empty), and
|
|
1232
|
+
* kept as its own boolean because it is what the row's badge and a list filter ask.
|
|
1233
|
+
*/
|
|
1234
|
+
outOfDate: z.boolean().isSummaryField(),
|
|
1235
|
+
/**
|
|
1236
|
+
* WHICH steps are out of date for this answer: the asking step and every step sharing the decision
|
|
1237
|
+
* (`sharedWithPlaybookRefs`) with a stale output whose changed inputs include `creator-inputs`. A shared decision is ONE row,
|
|
1238
|
+
* so "Regenerate" has to name the step it reruns; before this carried the refs, a change to a shared
|
|
1239
|
+
* answer marked and reran only the owner (#1454 review, LOW).
|
|
1240
|
+
*/
|
|
1241
|
+
outOfDateStepRefs: z.array(z.string()).isSummaryField(),
|
|
1242
|
+
/**
|
|
1243
|
+
* The other steps that READ this decision (a `sameDecisionAs` fallback with no answer of its own,
|
|
1244
|
+
* #1454 review). One decision is one row, at its owner; those steps' interviews show and answer it,
|
|
1245
|
+
* so it is asked once.
|
|
1246
|
+
*/
|
|
1247
|
+
sharedWithPlaybookRefs: z.array(z.string()).isSummaryField(),
|
|
1248
|
+
});
|
|
1249
|
+
/** The dossier resource's one write verb. */
|
|
1250
|
+
export var WorkbenchDossierEntries_Operations;
|
|
1251
|
+
(function (WorkbenchDossierEntries_Operations) {
|
|
1252
|
+
/** Record (or change) the creator's answer to this question. Lands `creator-inputs`; a commit accepts it. */
|
|
1253
|
+
WorkbenchDossierEntries_Operations["ANSWER"] = "answer";
|
|
1254
|
+
})(WorkbenchDossierEntries_Operations || (WorkbenchDossierEntries_Operations = {}));
|
|
1255
|
+
export const Workbench_DossierAnswerRequest_Schema = z.object({
|
|
1256
|
+
/** The answer, in the creator's words — validated against the question's kind before it is stored. */
|
|
1257
|
+
value: z.string().min(1),
|
|
1258
|
+
});
|
|
1259
|
+
export const Workbench_DossierAnswerOutcome_Schema = z.looseObject({
|
|
1260
|
+
/** The answer as STORED (canonical for a `confirm`). */
|
|
1261
|
+
value: z.string(),
|
|
1262
|
+
answeredAt: z.string(),
|
|
1263
|
+
/** The dossier file this landed in, package-relative. */
|
|
1264
|
+
packageRelativePath: z.string(),
|
|
1265
|
+
/** The asking playbook's questions still unanswered after this one — empty means it can run. */
|
|
1266
|
+
unansweredQuestionRefs: z.array(z.string()),
|
|
1267
|
+
});
|
|
1268
|
+
/**
|
|
1269
|
+
* The SECTIONS of Home, the conversation page's opening surface (#1454, Step 3) — and the LIST filter
|
|
1270
|
+
* a reader of `workbenchCreationHomeLines` narrows by.
|
|
1271
|
+
*
|
|
1272
|
+
* Three questions, three sections: what happened since I was here, what is asked of me now, what
|
|
1273
|
+
* could I do next. Where the application stands is a resource of its own
|
|
1274
|
+
* (`workbenchCreationOutcomes`), because an outcome is a measured STATE, not a line that opens
|
|
1275
|
+
* something.
|
|
1276
|
+
*/
|
|
1277
|
+
export var WorkbenchCreationHomeSection;
|
|
1278
|
+
(function (WorkbenchCreationHomeSection) {
|
|
1279
|
+
/** A run completed or cut short, a build dispatch settled — newest first. */
|
|
1280
|
+
WorkbenchCreationHomeSection["SINCE"] = "since";
|
|
1281
|
+
/** What blocks something NOW and waits on the creator: a run stopped on a question, a coding run parked on one, a drafted document missing a fact. */
|
|
1282
|
+
WorkbenchCreationHomeSection["ASKED"] = "asked";
|
|
1283
|
+
/** What the creator could do next, outcome-first: the plan's next task, a step producing a missing family, a step refreshing a stale one. */
|
|
1284
|
+
WorkbenchCreationHomeSection["SUGGESTION"] = "suggestion";
|
|
1285
|
+
})(WorkbenchCreationHomeSection || (WorkbenchCreationHomeSection = {}));
|
|
1286
|
+
/**
|
|
1287
|
+
* The KIND of a Home line — one closed vocabulary across the three sections, because a line's words
|
|
1288
|
+
* and its tone are decided by its kind wherever it is rendered, and a section is only where it sits.
|
|
1289
|
+
*
|
|
1290
|
+
* ## Why the companion decides these and the page does not
|
|
1291
|
+
*
|
|
1292
|
+
* Until 2026-09-22 the page read SEVEN resources on their own cadences and derived every line itself
|
|
1293
|
+
* — 900 lines of client arithmetic over rows a projection had already computed, re-run on every
|
|
1294
|
+
* poll, invisible to the assistant's tools and to every other reader. A line is a FACT about the
|
|
1295
|
+
* application ("this run was refused", "this task's writes wait to be committed"); facts are
|
|
1296
|
+
* derived where the rows are, once, and served as rows themselves (`derive-before-you-ask.md`).
|
|
1297
|
+
*/
|
|
1298
|
+
export var WorkbenchCreationHomeLineKind;
|
|
1299
|
+
(function (WorkbenchCreationHomeLineKind) {
|
|
1300
|
+
/** A playbook run completed — landed or refused; `failed` says which. */
|
|
1301
|
+
WorkbenchCreationHomeLineKind["RUN_COMPLETED"] = "run-completed";
|
|
1302
|
+
/** A playbook run the companion's restart cut short; re-running resumes it. Shown whatever its date. */
|
|
1303
|
+
WorkbenchCreationHomeLineKind["RUN_INTERRUPTED"] = "run-interrupted";
|
|
1304
|
+
/** A build dispatch finished or failed; `acceptable` says whether its writes wait to be committed. */
|
|
1305
|
+
WorkbenchCreationHomeLineKind["DISPATCH_SETTLED"] = "dispatch-settled";
|
|
1306
|
+
/** A playbook run suspended on questions only the creator can answer. */
|
|
1307
|
+
WorkbenchCreationHomeLineKind["CLARIFICATION"] = "clarification";
|
|
1308
|
+
/** A coding run parked on a question the agent could not answer alone. */
|
|
1309
|
+
WorkbenchCreationHomeLineKind["PARKED_QUESTION"] = "parked-question";
|
|
1310
|
+
/** A governed document the creator asked for (a draft exists) still needing a fact only they can give. */
|
|
1311
|
+
WorkbenchCreationHomeLineKind["GOVERNANCE_DOCUMENT"] = "governance-document";
|
|
1312
|
+
/** The next READY build task of the dispatch plan. */
|
|
1313
|
+
WorkbenchCreationHomeLineKind["CONTINUE_THE_PLAN"] = "continue-the-plan";
|
|
1314
|
+
/**
|
|
1315
|
+
* The plan can run NOTHING: every ready task is stuck, and `stuckReason` says what unblocks it.
|
|
1316
|
+
*
|
|
1317
|
+
* ASKED rather than SUGGESTION, because every reason is the creator's move — committing what a
|
|
1318
|
+
* finished run wrote under GUIDED, or, under the autonomy posture where the loop commits (#1534),
|
|
1319
|
+
* resolving the path its accept refused or correcting a declaration no run can satisfy.
|
|
1320
|
+
* Without it the plan simply falls silent: `CONTINUE_THE_PLAN` is derived from the next ready task,
|
|
1321
|
+
* and a stuck queue has none (#1451, #1463).
|
|
1322
|
+
*/
|
|
1323
|
+
WorkbenchCreationHomeLineKind["UNBLOCK_THE_PLAN"] = "unblock-the-plan";
|
|
1324
|
+
/** An eligible playbook whose output family is missing. */
|
|
1325
|
+
WorkbenchCreationHomeLineKind["PRODUCE_MISSING"] = "produce-missing";
|
|
1326
|
+
/** An eligible playbook whose output is stale — derived before one of its inputs last changed. */
|
|
1327
|
+
WorkbenchCreationHomeLineKind["REFRESH_STALE"] = "refresh-stale";
|
|
1328
|
+
})(WorkbenchCreationHomeLineKind || (WorkbenchCreationHomeLineKind = {}));
|
|
1329
|
+
/**
|
|
1330
|
+
* One line of Home. Every line OPENS an element beside the page — `targetResourceType` +
|
|
1331
|
+
* `targetResourceId` are the address the engine's hosted pane resolves — and carries the one or two
|
|
1332
|
+
* facts the words need: the subject, in the creator's terms, and the flags that change the sentence.
|
|
1333
|
+
*
|
|
1334
|
+
* `targetResourceType` is a STRING, not `z.enum(WorkbenchShared_ResourceType)`: it is an address, not
|
|
1335
|
+
* a vocabulary anyone words, and binding it here would make a line pointing at a resource a newer
|
|
1336
|
+
* companion serves unparseable by an older workbench.
|
|
1337
|
+
*/
|
|
1338
|
+
export const Workbench_CreationHomeLine_Schema = z.object({
|
|
1339
|
+
/** EMITTED BY THE BEHAVIOR: `<section>--<kind>--<sanitized target id>`. */
|
|
1340
|
+
workbenchCreationHomeLineId: z.string().min(1).isPrimaryKey().isSummaryField(),
|
|
1341
|
+
section: z.enum(WorkbenchCreationHomeSection).systemEnum('WorkbenchCreationHomeSection').isSummaryField(),
|
|
1342
|
+
kind: z.enum(WorkbenchCreationHomeLineKind).systemEnum('WorkbenchCreationHomeLineKind').isSummaryField(),
|
|
1343
|
+
/** The instant the line is ordered on, newest first; null when the row records none (a suggestion, a document). */
|
|
1344
|
+
at: z.date().nullable().isSummaryField(),
|
|
1345
|
+
/** The playbook the line is about, when it is about one — its words come from the label tree. */
|
|
1346
|
+
playbookRef: z.string().nullable().isSummaryField(),
|
|
1347
|
+
/** The build task the line is about, when it is about one. */
|
|
1348
|
+
taskRef: z.string().nullable().isSummaryField(),
|
|
1349
|
+
/** The next task's objective, for CONTINUE_THE_PLAN; the document's definition ref, for GOVERNANCE_DOCUMENT. */
|
|
1350
|
+
subject: z.string().nullable().isSummaryField(),
|
|
1351
|
+
/** A refused run, a failed dispatch. */
|
|
1352
|
+
failed: z.boolean().isSummaryField(),
|
|
1353
|
+
/** A finished coding run whose writes are recorded and not yet committed — the one line Home offers ACCEPT on (#1454, Step 7). */
|
|
1354
|
+
acceptable: z.boolean().isSummaryField(),
|
|
1355
|
+
/** The suggested playbook still has questions the dossier does not answer, so the way in is its interview (#1454, Step 5). */
|
|
1356
|
+
needsAnswers: z.boolean().isSummaryField(),
|
|
1357
|
+
/**
|
|
1358
|
+
* Why the plan is stuck, for `UNBLOCK_THE_PLAN` — the remedy is what the line is FOR, and each
|
|
1359
|
+
* reason's is different. Its words are authored once for the vocabulary
|
|
1360
|
+
* (`system_enums.Workbench_BuildTaskStuckReason`), so this line states no remedy of its own.
|
|
1361
|
+
*/
|
|
1362
|
+
stuckReason: z.enum(Workbench_BuildTaskStuckReason).systemEnum('Workbench_BuildTaskStuckReason').nullable().isSummaryField(),
|
|
1363
|
+
/** The element the line opens: a `WorkbenchShared_ResourceType` value and that row's addressable id. */
|
|
1364
|
+
targetResourceType: z.string().min(1).isSummaryField(),
|
|
1365
|
+
targetResourceId: z.string().min(1).isSummaryField(),
|
|
1366
|
+
});
|
|
1367
|
+
/**
|
|
1368
|
+
* The four OUTCOMES an application's creation is measured by — the journey in the creator's words
|
|
1369
|
+
* (Paul, 2026-09-21: "we do not have a real journey; top-down and bottom-up are internal
|
|
1370
|
+
* considerations"). The playbook phases stay machinery underneath; this is what a person sees.
|
|
1371
|
+
*
|
|
1372
|
+
* Which specification family counts toward which outcome is the companion projection's business
|
|
1373
|
+
* (`creation-home-projection.companion.ts`, total over `ApplicationSpecificationFamily`); this
|
|
1374
|
+
* package deliberately does not import that vocabulary.
|
|
1375
|
+
*/
|
|
1376
|
+
export var WorkbenchCreationOutcome;
|
|
1377
|
+
(function (WorkbenchCreationOutcome) {
|
|
1378
|
+
/** Vision, market, requirements, features, business model, roadmap, brand. */
|
|
1379
|
+
WorkbenchCreationOutcome["KNOW_WHAT_WE_BUILD"] = "know-what-we-build";
|
|
1380
|
+
/** The compliance programme, the processor register, the facts and policies behind every governed document, the risks. */
|
|
1381
|
+
WorkbenchCreationOutcome["KNOW_THE_RULES"] = "know-the-rules";
|
|
1382
|
+
/** The domain plan, the placement plan, the build plan — and the build tasks landed. */
|
|
1383
|
+
WorkbenchCreationOutcome["APPLICATION_WORKS"] = "application-works";
|
|
1384
|
+
/** Governed documents released and published — and every other outcome done. */
|
|
1385
|
+
WorkbenchCreationOutcome["READY_FOR_A_REAL_USER"] = "ready-for-a-real-user";
|
|
1386
|
+
})(WorkbenchCreationOutcome || (WorkbenchCreationOutcome = {}));
|
|
1387
|
+
/** The order a person reads the outcomes in: what, rules, works, ready. Also the rows' `position`. */
|
|
1388
|
+
export const WORKBENCH_CREATION_OUTCOMES_IN_ORDER = [
|
|
1389
|
+
WorkbenchCreationOutcome.KNOW_WHAT_WE_BUILD,
|
|
1390
|
+
WorkbenchCreationOutcome.KNOW_THE_RULES,
|
|
1391
|
+
WorkbenchCreationOutcome.APPLICATION_WORKS,
|
|
1392
|
+
WorkbenchCreationOutcome.READY_FOR_A_REAL_USER,
|
|
1393
|
+
];
|
|
1394
|
+
export var WorkbenchCreationOutcomeStatus;
|
|
1395
|
+
(function (WorkbenchCreationOutcomeStatus) {
|
|
1396
|
+
WorkbenchCreationOutcomeStatus["NOT_STARTED"] = "not-started";
|
|
1397
|
+
WorkbenchCreationOutcomeStatus["IN_PROGRESS"] = "in-progress";
|
|
1398
|
+
WorkbenchCreationOutcomeStatus["DONE"] = "done";
|
|
1399
|
+
})(WorkbenchCreationOutcomeStatus || (WorkbenchCreationOutcomeStatus = {}));
|
|
1400
|
+
/**
|
|
1401
|
+
* Where the application stands on one outcome — ALWAYS four rows, one per outcome, in reading
|
|
1402
|
+
* order. "Done" is strict: every family of the outcome landed, valid and not stale; for the
|
|
1403
|
+
* application working, every build task landed too; for readiness, every other outcome done as
|
|
1404
|
+
* well.
|
|
1405
|
+
*/
|
|
1406
|
+
export const Workbench_CreationOutcome_Schema = z.object({
|
|
1407
|
+
/** EMITTED BY THE BEHAVIOR: the outcome value. */
|
|
1408
|
+
workbenchCreationOutcomeId: z.string().min(1).isPrimaryKey().isSummaryField(),
|
|
1409
|
+
outcome: z.enum(WorkbenchCreationOutcome).systemEnum('WorkbenchCreationOutcome').isSummaryField(),
|
|
1410
|
+
status: z.enum(WorkbenchCreationOutcomeStatus).systemEnum('WorkbenchCreationOutcomeStatus').isSummaryField(),
|
|
1411
|
+
/** 0-based reading order. */
|
|
1412
|
+
position: z.number().int().min(0).isSummaryField(),
|
|
1413
|
+
/** Families this outcome is measured by — those the projection reports, placed under this outcome. */
|
|
1414
|
+
familiesTotal: z.number().int().min(0).isSummaryField(),
|
|
1415
|
+
/** Landed, valid, and not stale. */
|
|
1416
|
+
familiesLanded: z.number().int().min(0).isSummaryField(),
|
|
1417
|
+
/** Landed but refused by the family's own validator. */
|
|
1418
|
+
familiesInvalid: z.number().int().min(0).isSummaryField(),
|
|
1419
|
+
/** Not landed at all. */
|
|
1420
|
+
familiesMissing: z.number().int().min(0).isSummaryField(),
|
|
1421
|
+
/** Landed, but derived before one of its inputs last changed. */
|
|
1422
|
+
familiesStale: z.number().int().min(0).isSummaryField(),
|
|
1423
|
+
/** Build tasks, for APPLICATION_WORKS only; null on the other three. */
|
|
1424
|
+
tasksTotal: z.number().int().min(0).nullable().isSummaryField(),
|
|
1425
|
+
tasksLanded: z.number().int().min(0).nullable().isSummaryField(),
|
|
1426
|
+
/**
|
|
1427
|
+
* APPLICATION_WORKS only: the application's runtimes whose dev-loop supervisor has PAUSED them — it
|
|
1428
|
+
* will not start them until something changes (#1537). While any is listed the outcome is not DONE,
|
|
1429
|
+
* whatever has landed: an application that cannot start does not work. Null on the other three,
|
|
1430
|
+
* and null when no supervisor could answer, which is "cannot tell" rather than "all up".
|
|
1431
|
+
*/
|
|
1432
|
+
unavailableRuntimes: z.array(z.string().min(1)).nullable().isSummaryField(),
|
|
1433
|
+
});
|
|
1434
|
+
/*
|
|
1435
|
+
* ────────────────────────────────────────────────────────────────────────────────────────────────
|
|
1436
|
+
* The verbs that were the workbench's BESPOKE companion client until 2026-09-22 (#1454), now
|
|
1437
|
+
* declared operations on the resources they always addressed. Same door for every act: the engine's
|
|
1438
|
+
* auth chain and role gate, request-DTO validation, the registered path, the operation identity the
|
|
1439
|
+
* invalidation chain keys on — and the companion's local token floor no longer needs a browser
|
|
1440
|
+
* exemption for any of them.
|
|
1441
|
+
* ────────────────────────────────────────────────────────────────────────────────────────────────
|
|
1442
|
+
*/
|
|
1443
|
+
/** An operation that takes nothing. */
|
|
1444
|
+
export const Workbench_EmptyRequest_Schema = z.object({});
|
|
1445
|
+
/** `read_interview` on a playbook: the `HumanDecision_Request` it declares, or null. Carried opaquely — the engine owns that vocabulary. */
|
|
1446
|
+
export const Workbench_PlaybookInterview_Schema = z.object({
|
|
1447
|
+
decision: z.unknown().nullable(),
|
|
1448
|
+
});
|
|
1449
|
+
/** One file's change within a run — see `read_diff`. */
|
|
1450
|
+
export const Workbench_RunWriteFileDiff_Schema = z.object({
|
|
1451
|
+
path: z.string().min(1),
|
|
1452
|
+
existedBefore: z.boolean(),
|
|
1453
|
+
/** The file on disk no longer holds what the run wrote; the diff still describes what the RUN did. */
|
|
1454
|
+
diverged: z.boolean(),
|
|
1455
|
+
/** Unified diff. Empty when the run rewrote a file with identical bytes. */
|
|
1456
|
+
diff: z.string(),
|
|
1457
|
+
});
|
|
1458
|
+
export const Workbench_RunWriteDiff_Schema = z.object({
|
|
1459
|
+
runId: z.string().min(1),
|
|
1460
|
+
playbookRef: z.string().min(1),
|
|
1461
|
+
at: z.string().min(1),
|
|
1462
|
+
files: z.array(Workbench_RunWriteFileDiff_Schema),
|
|
1463
|
+
});
|
|
1464
|
+
/** The trace-session resource's READ-shaped verbs — what a session RECORDED, beyond the summary its row carries. */
|
|
1465
|
+
export var WorkbenchTraceSessions_Operations;
|
|
1466
|
+
(function (WorkbenchTraceSessions_Operations) {
|
|
1467
|
+
/** ONE session: every event in order, and its step artifacts by name (#1328) — what the Conversation tab reads. */
|
|
1468
|
+
WorkbenchTraceSessions_Operations["READ_RECORD"] = "read_record";
|
|
1469
|
+
/** What one session SPENT, in tokens — summed from the agent-call usage already in its events (#1274). Never a currency. */
|
|
1470
|
+
WorkbenchTraceSessions_Operations["READ_USAGE"] = "read_usage";
|
|
1471
|
+
/** One step ARTIFACT, as text — the brief the model saw, the answer it gave, a coding task's input (#1329). */
|
|
1472
|
+
WorkbenchTraceSessions_Operations["READ_ARTIFACT"] = "read_artifact";
|
|
1473
|
+
/**
|
|
1474
|
+
* The trace sessions one ACTOR TASK ran in, latest first — the alias the coding lane writes for
|
|
1475
|
+
* every run (#1328). Collection-level: the task is the input, not a session. Empty for a task the
|
|
1476
|
+
* lane never ran, which is the ordinary case and not an error.
|
|
1477
|
+
*/
|
|
1478
|
+
WorkbenchTraceSessions_Operations["LIST_FOR_TASK"] = "list_for_task";
|
|
1479
|
+
})(WorkbenchTraceSessions_Operations || (WorkbenchTraceSessions_Operations = {}));
|
|
1480
|
+
/** One traced event, as the companion records it — the conversation's unit (#1328). */
|
|
1481
|
+
export const Workbench_TraceSessionEvent_Schema = z.object({
|
|
1482
|
+
timestamp: z.string().min(1),
|
|
1483
|
+
/** A `PlaybookExecutionTraceEvent` value, or a coding-lane event type; a closed vocabulary the companion owns. */
|
|
1484
|
+
type: z.string().min(1),
|
|
1485
|
+
summary: z.string(),
|
|
1486
|
+
stepId: z.string().optional(),
|
|
1487
|
+
payload: z.unknown().optional(),
|
|
1488
|
+
});
|
|
1489
|
+
/** One step directory of a session: the artifacts it holds, by file name. Bodies are read one at a time. */
|
|
1490
|
+
export const Workbench_TraceSessionStep_Schema = z.object({
|
|
1491
|
+
stepDirName: z.string().min(1),
|
|
1492
|
+
artifacts: z.array(z.string()),
|
|
1493
|
+
});
|
|
1494
|
+
export const Workbench_TraceSessionRecord_Schema = z.object({
|
|
1495
|
+
sessionId: z.string().min(1),
|
|
1496
|
+
startedAt: z.string().min(1),
|
|
1497
|
+
label: z.string().nullable(),
|
|
1498
|
+
eventCount: z.number().int(),
|
|
1499
|
+
stepCount: z.number().int(),
|
|
1500
|
+
events: z.array(Workbench_TraceSessionEvent_Schema),
|
|
1501
|
+
steps: z.array(Workbench_TraceSessionStep_Schema),
|
|
1502
|
+
});
|
|
1503
|
+
/** What one trace session spent, in TOKENS. `callsWithoutUsage` non-zero means the totals are a FLOOR, not the figure. */
|
|
1504
|
+
export const Workbench_TraceSessionUsage_Schema = z.object({
|
|
1505
|
+
sessionId: z.string().min(1),
|
|
1506
|
+
agentCalls: z.number().int(),
|
|
1507
|
+
callsWithoutUsage: z.number().int(),
|
|
1508
|
+
promptTokens: z.number().int(),
|
|
1509
|
+
completionTokens: z.number().int(),
|
|
1510
|
+
totalTokens: z.number().int(),
|
|
1511
|
+
});
|
|
1512
|
+
export const Workbench_TraceArtifactRequest_Schema = z.object({
|
|
1513
|
+
stepDirName: z.string().min(1),
|
|
1514
|
+
fileName: z.string().min(1),
|
|
1515
|
+
});
|
|
1516
|
+
/** The artifact body, verbatim. A big brief renders by its OUTLINE, computed by the reader — the text is what it is owed. */
|
|
1517
|
+
export const Workbench_TraceArtifact_Schema = z.object({
|
|
1518
|
+
body: z.string(),
|
|
1519
|
+
});
|
|
1520
|
+
export const Workbench_TraceSessionsForTaskRequest_Schema = z.object({
|
|
1521
|
+
/** The durable actor-task row a coding run was dispatched as. */
|
|
1522
|
+
taskId: z.string().min(1),
|
|
1523
|
+
});
|
|
1524
|
+
export const Workbench_TraceSessionsForTask_Schema = z.object({
|
|
1525
|
+
sessionIds: z.array(z.string()),
|
|
1526
|
+
});
|
|
1527
|
+
/**
|
|
1528
|
+
* The parked coding question's two verbs — the decision the row IS (see
|
|
1529
|
+
* {@link Workbench_ParkedCodingQuestionOptionRef}): answer it and resume the same session, or end
|
|
1530
|
+
* the run. Both were bespoke companion routes with a browser exemption on the token floor until
|
|
1531
|
+
* 2026-09-22; the row's own operations are where a reader meets them.
|
|
1532
|
+
*/
|
|
1533
|
+
export var WorkbenchParkedCodingQuestions_Operations;
|
|
1534
|
+
(function (WorkbenchParkedCodingQuestions_Operations) {
|
|
1535
|
+
/** Answer THIS parked run and resume the same agent session. A WRITE: it re-enters a workspace-mutating run behind the worktree lock. */
|
|
1536
|
+
WorkbenchParkedCodingQuestions_Operations["ANSWER"] = "answer";
|
|
1537
|
+
/**
|
|
1538
|
+
* End THIS parked run. Per row since #1581 (seventh review): with waves (#1528) several runs may be
|
|
1539
|
+
* live, and a collection-level cancel ended whatever this process drove — doing nothing for a park
|
|
1540
|
+
* no chain held, and stopping other runs while this one stayed parked.
|
|
1541
|
+
*/
|
|
1542
|
+
WorkbenchParkedCodingQuestions_Operations["CANCEL"] = "cancel";
|
|
1543
|
+
})(WorkbenchParkedCodingQuestions_Operations || (WorkbenchParkedCodingQuestions_Operations = {}));
|
|
1544
|
+
export const Workbench_ParkedQuestionAnswerRequest_Schema = z.object({
|
|
1545
|
+
/** The answer, in the operator's words. Empty is refused by the lane with its own sentence. */
|
|
1546
|
+
answer: z.string(),
|
|
1547
|
+
/** The row's `suspensionRef`: the question this answers. Refused (409) once the run has asked another. */
|
|
1548
|
+
suspensionRef: z.string().min(1),
|
|
1549
|
+
});
|
|
1550
|
+
/** The lane's admission of the resumed run — its own shape, carried loosely. */
|
|
1551
|
+
export const Workbench_ParkedQuestionAnswerOutcome_Schema = z.looseObject({});
|
|
1552
|
+
/**
|
|
1553
|
+
* The row's `cancel` answers ONLY a run it ended or signalled: a run that moved on meanwhile is a 409 the
|
|
1554
|
+
* gate shows, never a `cancelled: false` read as success (#1581, eleventh and twelfth reviews).
|
|
1555
|
+
*/
|
|
1556
|
+
export const Workbench_CodingRunCancelOutcome_Schema = z.looseObject({
|
|
1557
|
+
cancelled: z.literal(true),
|
|
1558
|
+
});
|
|
1559
|
+
/**
|
|
1560
|
+
* The governed document's one verb: LAND the facts a person established for it as the
|
|
1561
|
+
* `document-facts-authored` family. The row is the document; the body carries the governance scope,
|
|
1562
|
+
* the answers and, for a reviewed fact, the review — a per-question verb with a bare value could
|
|
1563
|
+
* carry none of that, which is why the question resource has no write verb of its own.
|
|
1564
|
+
*/
|
|
1565
|
+
export var WorkbenchGovernanceDocuments_Operations;
|
|
1566
|
+
(function (WorkbenchGovernanceDocuments_Operations) {
|
|
1567
|
+
WorkbenchGovernanceDocuments_Operations["LAND_FACTS"] = "land_facts";
|
|
1568
|
+
})(WorkbenchGovernanceDocuments_Operations || (WorkbenchGovernanceDocuments_Operations = {}));
|
|
1569
|
+
/**
|
|
1570
|
+
* The landing request's ENVELOPE. The answer SEMANTICS stay with the companion service that owns the
|
|
1571
|
+
* question catalog (it refuses an unknown question, a review with no reviewer, "does not apply" on a
|
|
1572
|
+
* question that does not offer it — each with its own sentence); this refuses a body that is not a
|
|
1573
|
+
* landing request at all.
|
|
1574
|
+
*/
|
|
1575
|
+
export const Workbench_GovernanceFactsLandingRequest_Schema = z.object({
|
|
1576
|
+
definitionRef: z.string().min(1),
|
|
1577
|
+
decidedByRef: z.string().min(1),
|
|
1578
|
+
decidedAt: z.string().min(1),
|
|
1579
|
+
governanceScope: z.object({
|
|
1580
|
+
subjectKind: z.string().min(1),
|
|
1581
|
+
subjectRef: z.string().min(1),
|
|
1582
|
+
scopeRef: z.string().min(1),
|
|
1583
|
+
scopeVersion: z.number().int().positive(),
|
|
1584
|
+
participantRefs: z.array(z.string()),
|
|
1585
|
+
precedenceRuleRefs: z.array(z.string()),
|
|
1586
|
+
}),
|
|
1587
|
+
answers: z.array(z.unknown()),
|
|
1588
|
+
/** Run the whole pipe and write nothing — what lets a person see the exact file their answers produce BEFORE anything touches the tree. */
|
|
1589
|
+
dryRun: z.boolean().optional(),
|
|
1590
|
+
});
|
|
1591
|
+
export const Workbench_GovernanceFactsLandingOutcome_Schema = z.object({
|
|
1592
|
+
family: z.string().min(1),
|
|
1593
|
+
packageRelativePath: z.string().min(1),
|
|
1594
|
+
exportedConstantName: z.string().min(1),
|
|
1595
|
+
renderedSource: z.string(),
|
|
1596
|
+
existedBefore: z.boolean(),
|
|
1597
|
+
wiringAlreadyInPlace: z.array(z.string()),
|
|
1598
|
+
});
|
|
1599
|
+
/**
|
|
1600
|
+
* Where one secret stands for an application in one environment (#1637).
|
|
1601
|
+
*
|
|
1602
|
+
* The ONE vocabulary for `wildo secrets list`, the creation essentials of `wildo init`/`setup` and
|
|
1603
|
+
* the workbench's secrets section, so the three cannot disagree about what "needed" means. Derived
|
|
1604
|
+
* from what the application declares (the providers it scopes, the capabilities it enables, its systems
|
|
1605
|
+
* of record and inbound endpoints), never from the provider catalogue.
|
|
1606
|
+
*/
|
|
1607
|
+
export var ApplicationSecretStanding;
|
|
1608
|
+
(function (ApplicationSecretStanding) {
|
|
1609
|
+
/**
|
|
1610
|
+
* Required by something the application uses, unset, and nothing else covers what it is for: a
|
|
1611
|
+
* capability, a provider the application scoped on purpose, a system of record or an inbound endpoint
|
|
1612
|
+
* cannot work until it is provided.
|
|
1613
|
+
*/
|
|
1614
|
+
ApplicationSecretStanding["NEEDED"] = "needed";
|
|
1615
|
+
/** It has a value in this environment, and something reads it. */
|
|
1616
|
+
ApplicationSecretStanding["SET"] = "set";
|
|
1617
|
+
/** Unset, and nothing waits for it: an optional key, or a capability another provider already serves. */
|
|
1618
|
+
ApplicationSecretStanding["AVAILABLE"] = "available";
|
|
1619
|
+
/**
|
|
1620
|
+
* It has a value, and nothing CONSUMES it: a provider key no provider declares, a system-of-record key
|
|
1621
|
+
* naming no declared instance or no slot its credential has, an inbound key naming no endpoint. It is
|
|
1622
|
+
* listed to be REMOVED — the one verb it offers. Usually the remains of something renamed or retired
|
|
1623
|
+
* (Odoo was a provider before it was a system of record).
|
|
1624
|
+
*
|
|
1625
|
+
* Unconsumed is not undelivered: the dev companion's `.env` carries EVERY provider key, and the backend
|
|
1626
|
+
* receives a well-formed inbound name or a slot of a declared instance. So a row says which runtimes still
|
|
1627
|
+
* receive it, and removing it regenerates their `.env` files like any other change — otherwise the value
|
|
1628
|
+
* would stay on disk and in the running process after the person was told it was gone.
|
|
1629
|
+
*/
|
|
1630
|
+
ApplicationSecretStanding["UNUSED"] = "unused";
|
|
1631
|
+
})(ApplicationSecretStanding || (ApplicationSecretStanding = {}));
|
|
1632
|
+
/**
|
|
1633
|
+
* What a secret belongs to, and so which section of `secrets.json` holds it and how its name is formed.
|
|
1634
|
+
* Three kinds because they are three different things, not three spellings of a provider key: a system of
|
|
1635
|
+
* record is deliberately NOT a provider (#1049 D10) and an inbound endpoint secret proves a delivery rather
|
|
1636
|
+
* than authenticating a call.
|
|
1637
|
+
*/
|
|
1638
|
+
export var ApplicationSecretKind;
|
|
1639
|
+
(function (ApplicationSecretKind) {
|
|
1640
|
+
/** A provider's secret, declared by its secrets contract; `secrets.json` → `providerEnv`. */
|
|
1641
|
+
ApplicationSecretKind["PROVIDER"] = "provider";
|
|
1642
|
+
/**
|
|
1643
|
+
* A credential slot of a declared system of record (#1055), named `WILDO_SOR_<NAME>__<SLOT>`;
|
|
1644
|
+
* `secrets.json` → `systemsOfRecordEnv`. Read by the application backend only.
|
|
1645
|
+
*/
|
|
1646
|
+
ApplicationSecretKind["SYSTEM_OF_RECORD"] = "system_of_record";
|
|
1647
|
+
/**
|
|
1648
|
+
* The verification secret of an application inbound endpoint (#1596), named
|
|
1649
|
+
* `WILDO_INBOUND_<ENDPOINT_KEY>__SECRET`; `secrets.json` → `inboundEndpointEnv`. Read by the backend only.
|
|
1650
|
+
*/
|
|
1651
|
+
ApplicationSecretKind["INBOUND_ENDPOINT"] = "inbound_endpoint";
|
|
1652
|
+
})(ApplicationSecretKind || (ApplicationSecretKind = {}));
|
|
1653
|
+
/**
|
|
1654
|
+
* Which GitHub level holds a REMOTE environment's provider secret. Remote secrets are GitHub Actions
|
|
1655
|
+
* secrets; the generated deploy job declares `environment: <env>`, so an environment secret applies to
|
|
1656
|
+
* that environment alone and overrides a repository secret of the same name, which is the fallback.
|
|
1657
|
+
* spec-cite: https://docs.github.com/en/actions/reference/security/secrets — "If an organization, repository, and environment all have a secret with the same name, the environment-level secret takes precedence."
|
|
1658
|
+
*/
|
|
1659
|
+
export var ApplicationSecretRemoteLevel;
|
|
1660
|
+
(function (ApplicationSecretRemoteLevel) {
|
|
1661
|
+
ApplicationSecretRemoteLevel["ENVIRONMENT"] = "environment";
|
|
1662
|
+
ApplicationSecretRemoteLevel["REPOSITORY"] = "repository";
|
|
1663
|
+
})(ApplicationSecretRemoteLevel || (ApplicationSecretRemoteLevel = {}));
|
|
1664
|
+
/**
|
|
1665
|
+
* Joins the parts of a secret row's id. The separator must be something an environment id and a kind cannot
|
|
1666
|
+
* contain, so the id splits back on its first two occurrences. Environment ids are `^[a-z0-9]+(?:-[a-z0-9]+)*$`
|
|
1667
|
+
* (`WildoEnvironmentIdSchema`), and no {@link ApplicationSecretKind} value contains `--`.
|
|
1668
|
+
*/
|
|
1669
|
+
const APPLICATION_SECRET_ROW_ID_SEPARATOR = '--';
|
|
1670
|
+
const APPLICATION_SECRET_KIND_VALUES = new Set(Object.values(ApplicationSecretKind));
|
|
1671
|
+
/**
|
|
1672
|
+
* The `id` of one secret row: environment, kind and name (`local--provider--OPENAI_API_KEY`). The same name is
|
|
1673
|
+
* a different secret per environment, and per KIND too — each kind is its own `secrets.json` section, so a
|
|
1674
|
+
* key left in the wrong section during a migration (an Odoo credential still in `providerEnv`) is a second
|
|
1675
|
+
* secret beside the one that belongs, and must be addressable on its own rather than colliding with it.
|
|
1676
|
+
*
|
|
1677
|
+
* The id travels in the URL of the row's page and of its `set` / `unset` operations, and the engine checks
|
|
1678
|
+
* it before any handler runs (`ExecutionContextCreator.validateParameterFormat`). It was
|
|
1679
|
+
* `<environment>::<NAME>` until 2026-09-26: the list rendered, but the row's page and both operations
|
|
1680
|
+
* answered `400 api_call_initiator_parameter_unsupported`, because that check then held every id to
|
|
1681
|
+
* `^[a-zA-Z0-9_-]+$`. Since #2048 it holds an introspected row's id to the introspection format, which admits
|
|
1682
|
+
* more; this id stays inside the narrower alphabet anyway, so it is valid under both, and
|
|
1683
|
+
* `workbench-application-secret-row-id.test.ts` pins that.
|
|
1684
|
+
*/
|
|
1685
|
+
export function applicationSecretRowId(envName, kind, envVarName) {
|
|
1686
|
+
return [envName, kind, envVarName].join(APPLICATION_SECRET_ROW_ID_SEPARATOR);
|
|
1687
|
+
}
|
|
1688
|
+
/**
|
|
1689
|
+
* Splits a secret row's id back into environment, kind and name, or `null` when it cannot be a row id. It
|
|
1690
|
+
* splits on the first two separators — neither the environment nor the kind can contain one — and the name
|
|
1691
|
+
* keeps any it has. A well-formed id naming nothing real is refused later by `wildo secrets`, which states
|
|
1692
|
+
* the reason itself.
|
|
1693
|
+
*/
|
|
1694
|
+
export function splitApplicationSecretRowId(rowId) {
|
|
1695
|
+
const first = rowId.indexOf(APPLICATION_SECRET_ROW_ID_SEPARATOR);
|
|
1696
|
+
if (first <= 0)
|
|
1697
|
+
return null;
|
|
1698
|
+
const kindStart = first + APPLICATION_SECRET_ROW_ID_SEPARATOR.length;
|
|
1699
|
+
const second = rowId.indexOf(APPLICATION_SECRET_ROW_ID_SEPARATOR, kindStart);
|
|
1700
|
+
if (second <= kindStart)
|
|
1701
|
+
return null;
|
|
1702
|
+
const kind = rowId.slice(kindStart, second);
|
|
1703
|
+
const envVarName = rowId.slice(second + APPLICATION_SECRET_ROW_ID_SEPARATOR.length);
|
|
1704
|
+
if (!APPLICATION_SECRET_KIND_VALUES.has(kind) || envVarName.length === 0)
|
|
1705
|
+
return null;
|
|
1706
|
+
return { envName: rowId.slice(0, first), kind: kind, envVarName };
|
|
1707
|
+
}
|
|
1708
|
+
/**
|
|
1709
|
+
* One secret an application declares a use for (or still holds), in one environment — the workbench's
|
|
1710
|
+
* secrets section. Names and standings only: a value never enters this row, in either direction of the wire.
|
|
1711
|
+
*/
|
|
1712
|
+
export const Workbench_ApplicationSecret_Schema = z.object({
|
|
1713
|
+
/**
|
|
1714
|
+
* `<environment>--<kind>--<NAME>` — see {@link applicationSecretRowId}. A SUMMARY field like every other
|
|
1715
|
+
* workbench row's key: the list is read in summary mode, and a card whose row carries no id cannot open its
|
|
1716
|
+
* row — which is where `set` and `unset` live (#1637).
|
|
1717
|
+
*/
|
|
1718
|
+
workbenchApplicationSecretId: z.string().min(1).isPrimaryKey().isSummaryField(),
|
|
1719
|
+
/** The environment this row describes (`local`, or a remote environment's name). */
|
|
1720
|
+
environmentName: z.string().min(1).isSummaryField(),
|
|
1721
|
+
/** The environment variable the runtime reads — the key in the `secrets.json` section its {@link kind} names. */
|
|
1722
|
+
envVarName: z.string().min(1).isSummaryField(),
|
|
1723
|
+
/** Where it stands: needed, set, available, or unused. */
|
|
1724
|
+
standing: z.enum(ApplicationSecretStanding).systemEnum('ApplicationSecretStanding').isSummaryField(),
|
|
1725
|
+
/** What it belongs to: a provider, a system of record, or an inbound endpoint. */
|
|
1726
|
+
kind: z.enum(ApplicationSecretKind).systemEnum('ApplicationSecretKind').isSummaryField(),
|
|
1727
|
+
/**
|
|
1728
|
+
* WHICH one, in the vocabulary of its {@link kind}: the provider ref, the system-of-record instance name,
|
|
1729
|
+
* or the inbound endpoint key. NULL only for an {@link ApplicationSecretStanding.UNUSED} key that names
|
|
1730
|
+
* no owner: a provider key no provider declares, or a system-of-record or inbound name that does not parse.
|
|
1731
|
+
*/
|
|
1732
|
+
ownerRef: z.string().min(1).nullable().isSummaryField(),
|
|
1733
|
+
/** Its owner's own description of it, when it has one. */
|
|
1734
|
+
description: z.string().nullable(),
|
|
1735
|
+
/** The enabled capabilities a provider serves for this application — why the secret is needed. Empty for the other kinds. */
|
|
1736
|
+
capabilities: z.array(z.enum(EngineCapability).systemEnum('EngineCapability')),
|
|
1737
|
+
/**
|
|
1738
|
+
* The runtimes that RECEIVE it in their environment — the ones a change regenerates and restarts: `backend`,
|
|
1739
|
+
* `companion`, `minions.<key>`, `workers.<key>`, `frontendServices.<key>`. For an UNUSED key this is where it
|
|
1740
|
+
* is still carried, never where it is used.
|
|
1741
|
+
*/
|
|
1742
|
+
runtimes: z.array(z.string()),
|
|
1743
|
+
/** The companion's LLM key — the one secret `wildo init`/`setup` ask for, because the creation chat runs on it. */
|
|
1744
|
+
creationEssential: z.boolean(),
|
|
1745
|
+
/** Remote only: which GitHub level holds it. NULL locally, and NULL for a remote secret that is not set. */
|
|
1746
|
+
remoteLevel: z.enum(ApplicationSecretRemoteLevel).systemEnum('ApplicationSecretRemoteLevel').nullable(),
|
|
1747
|
+
});
|
|
1748
|
+
/** The secret row's two verbs. Both run `wildo secrets set/unset`, which is the only writer of a secret. */
|
|
1749
|
+
export var WorkbenchApplicationSecrets_Operations;
|
|
1750
|
+
(function (WorkbenchApplicationSecrets_Operations) {
|
|
1751
|
+
/**
|
|
1752
|
+
* Provide THIS secret's value. Locally the runtimes that read it restart to pick it up; remotely it
|
|
1753
|
+
* becomes the GitHub Environment secret the deploy reads.
|
|
1754
|
+
*/
|
|
1755
|
+
WorkbenchApplicationSecrets_Operations["SET"] = "set";
|
|
1756
|
+
/** Remove THIS secret from its environment. */
|
|
1757
|
+
WorkbenchApplicationSecrets_Operations["UNSET"] = "unset";
|
|
1758
|
+
})(WorkbenchApplicationSecrets_Operations || (WorkbenchApplicationSecrets_Operations = {}));
|
|
1759
|
+
export const Workbench_ApplicationSecretSetRequest_Schema = z.object({
|
|
1760
|
+
/**
|
|
1761
|
+
* The value. Never returned, never logged, never stored by the companion: `.isWriteOnlySecret()` masks
|
|
1762
|
+
* it in every RESPONSE, so once saved nothing shows it again.
|
|
1763
|
+
*
|
|
1764
|
+
* Entered in a multi-line box, visible while typed, as GitHub's own secret form does. Decided by
|
|
1765
|
+
* practice rather than taste, and measured against the two alternatives:
|
|
1766
|
+
* - A masked (`type=password`) input was tried first. It is single-line, so a pasted key file lost its
|
|
1767
|
+
* line breaks, and a browser treats it as a login: Chrome ignores `autocomplete="off"` on password
|
|
1768
|
+
* fields and still autofills or offers to save into `new-password` ones, so a provider key could be
|
|
1769
|
+
* saved as a localhost password or a saved one filled in unseen. The vocabulary has no `off` token.
|
|
1770
|
+
* - A single-line text input strips newlines from a paste too (HTML value sanitization).
|
|
1771
|
+
* The box preserves what was pasted, and a person can check a paste before saving it.
|
|
1772
|
+
*/
|
|
1773
|
+
value: z.string().min(1).stringUI({ edit: { editMode: StringEditMode.TEXTAREA } }).isWriteOnlySecret(),
|
|
1774
|
+
});
|
|
1775
|
+
/**
|
|
1776
|
+
* What a change did — the shape `wildo secrets set/unset --json` prints (#1637). The local fields are
|
|
1777
|
+
* inert for a remote environment, whose change is the GitHub secret itself.
|
|
1778
|
+
*/
|
|
1779
|
+
export const Workbench_ApplicationSecretChangeOutcome_Schema = z.object({
|
|
1780
|
+
envVarName: z.string(),
|
|
1781
|
+
/** Which section the change was made in — with the name and the environment, the secret's identity. */
|
|
1782
|
+
kind: z.enum(ApplicationSecretKind).systemEnum('ApplicationSecretKind'),
|
|
1783
|
+
envName: z.string(),
|
|
1784
|
+
/** Local: the runtimes a LIVE `wildo local dev` supervisor was asked to restart to read the change. */
|
|
1785
|
+
restartSignalledRuntimes: z.array(z.string()),
|
|
1786
|
+
/** Local: whether the runtimes' `.env` files were regenerated. */
|
|
1787
|
+
envFilesRegenerated: z.boolean(),
|
|
1788
|
+
/** Local: why the `.env` files were not regenerated, with the command to run; null when they were. */
|
|
1789
|
+
envFilesRegenerationFailure: z.string().nullable(),
|
|
1790
|
+
/** Local: the companion reads this key and applies the change itself instead of restarting. */
|
|
1791
|
+
companionAppliesChange: z.boolean(),
|
|
1792
|
+
/**
|
|
1793
|
+
* Set by the COMPANION (never by the CLI) when it could not apply the change in-process: the value is
|
|
1794
|
+
* saved and reaches the companion at its next start. Absent when nothing failed.
|
|
1795
|
+
*/
|
|
1796
|
+
companionApplyFailure: z.string().optional(),
|
|
1797
|
+
});
|
|
297
1798
|
//# sourceMappingURL=workbench-creation-plane.custom.shared.schemas.js.map
|