toolroll 0.9.52 → 0.9.54
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/CHANGELOG.md +16 -0
- package/README.md +55 -80
- package/dist/agentconfig.d.ts +11 -36
- package/dist/agentconfig.js +3 -62
- package/dist/approval-policy.d.ts +1 -1
- package/dist/approval-policy.js +1 -1
- package/dist/board.d.ts +3 -19
- package/dist/board.js +4 -42
- package/dist/browser/workspace.js +18 -18
- package/dist/browser-workspace.d.ts +2 -1
- package/dist/builder.d.ts +9 -40
- package/dist/builder.js +50 -257
- package/dist/chat-actions.js +3 -14
- package/dist/chat-ask.js +8 -8
- package/dist/chat-controls.d.ts +0 -4
- package/dist/chat-controls.js +0 -1
- package/dist/chat-core.d.ts +171 -0
- package/dist/chat-core.js +288 -0
- package/dist/chat-decide.d.ts +10 -8
- package/dist/chat-decide.js +27 -24
- package/dist/chat-delivery-state.d.ts +51 -75
- package/dist/chat-delivery-state.js +140 -170
- package/dist/chat-delivery.d.ts +21 -4
- package/dist/chat-delivery.js +313 -195
- package/dist/chat-flow.d.ts +29 -1
- package/dist/chat-flow.js +24 -50
- package/dist/chat-messages.d.ts +319 -0
- package/dist/chat-messages.js +841 -0
- package/dist/chat-migration.d.ts +30 -0
- package/dist/chat-migration.js +802 -0
- package/dist/chat-quiet.d.ts +3 -0
- package/dist/chat-quiet.js +7 -2
- package/dist/chat-task-actions.d.ts +1 -1
- package/dist/chat-task-actions.js +0 -2
- package/dist/claim.d.ts +79 -244
- package/dist/claim.js +688 -1023
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +10 -2
- package/dist/contracts/chat-content.d.ts +71 -2
- package/dist/contracts/chat-content.js +22 -3
- package/dist/contracts/chat-tables.d.ts +11 -4
- package/dist/contracts/chat-tables.js +165 -87
- package/dist/contracts/cli.d.ts +0 -13
- package/dist/contracts/cli.js +0 -2
- package/dist/contracts/console-api.d.ts +5 -10
- package/dist/contracts/console-api.js +4 -10
- package/dist/contracts/discord-callback.js +2 -1
- package/dist/contracts/flow.d.ts +50 -0
- package/dist/contracts/flow.js +26 -1
- package/dist/contracts/lead-tools.d.ts +0 -13
- package/dist/contracts/lead-tools.js +3 -3
- package/dist/contracts/slack-callback.js +3 -2
- package/dist/contracts/store-json.d.ts +1 -29
- package/dist/contracts/store-json.js +4 -17
- package/dist/contracts/teams-callback.js +2 -1
- package/dist/converse.d.ts +1 -11
- package/dist/converse.js +6 -38
- package/dist/coordinator.d.ts +0 -1
- package/dist/coordinator.js +3 -5
- package/dist/demo.js +16 -26
- package/dist/desktop-update-gate.js +0 -1
- package/dist/desktop-update.js +1 -3
- package/dist/discord-chat.js +19 -38
- package/dist/discord-settings.js +4 -13
- package/dist/discord.js +4 -14
- package/dist/dispatch.d.ts +1 -1
- package/dist/dispatch.js +1 -1
- package/dist/dispose.d.ts +2 -3
- package/dist/dispose.js +17 -92
- package/dist/envelope.js +0 -3
- package/dist/exec.d.ts +0 -64
- package/dist/exec.js +3 -356
- package/dist/exhaustion.d.ts +22 -76
- package/dist/exhaustion.js +14 -140
- package/dist/export.js +8 -8
- package/dist/flow-engine.js +1 -1
- package/dist/flow-schedule.d.ts +154 -0
- package/dist/flow-schedule.js +321 -0
- package/dist/flow-share.js +1 -1
- package/dist/flow-triggers.d.ts +6 -1
- package/dist/flow-triggers.js +65 -10
- package/dist/flows-cli.js +8 -4
- package/dist/flows-ui.js +2 -0
- package/dist/flows.js +1 -1
- package/dist/guides.js +9 -29
- package/dist/invoke.d.ts +1 -24
- package/dist/invoke.js +17 -259
- package/dist/lead-status.js +2 -4
- package/dist/lead-voice.js +1 -1
- package/dist/mate-doors.d.ts +1 -2
- package/dist/mate-doors.js +12 -25
- package/dist/mate-tools.d.ts +2 -2
- package/dist/mate-tools.js +13 -24
- package/dist/modes.d.ts +19 -8
- package/dist/modes.js +24 -14
- package/dist/notification-rows.d.ts +30 -0
- package/dist/notification-rows.js +102 -0
- package/dist/operate-remote-arguments.js +2 -6
- package/dist/operate-remote.js +6 -7
- package/dist/operate.d.ts +0 -6
- package/dist/operate.js +226 -2248
- package/dist/phase-routing.d.ts +13 -23
- package/dist/phase-routing.js +13 -35
- package/dist/plan-auto.js +2 -2
- package/dist/plane-review.js +5 -11
- package/dist/planner-source.js +2 -1
- package/dist/policy.d.ts +1 -4
- package/dist/policy.js +0 -8
- package/dist/process-recovery-eligibility.js +2 -3
- package/dist/project-delete.js +24 -41
- package/dist/proposal.d.ts +4 -24
- package/dist/proposal.js +3 -88
- package/dist/provider-auth.d.ts +3 -3
- package/dist/provider-auth.js +4 -6
- package/dist/provider.d.ts +11 -25
- package/dist/provider.js +4 -36
- package/dist/push.js +1 -1
- package/dist/recipe-ui.js +6 -6
- package/dist/recipes.d.ts +3 -3
- package/dist/recipes.js +27 -23
- package/dist/result-shots.js +2 -2
- package/dist/retention.js +1 -1
- package/dist/run-closeout.d.ts +1 -1
- package/dist/run-closeout.js +1 -4
- package/dist/scope.d.ts +11 -65
- package/dist/scope.js +17 -82
- package/dist/serve.js +15 -24
- package/dist/server/chat.js +7 -30
- package/dist/server/flows.js +11 -10
- package/dist/server/guards.js +0 -1
- package/dist/server/pages-assets.js +1 -1
- package/dist/server/pages.js +0 -2
- package/dist/server/people-tokens.js +0 -4
- package/dist/server/route-table.d.ts +1 -1
- package/dist/server/route-table.js +2 -17
- package/dist/server/settings.js +6 -12
- package/dist/server/shared.d.ts +28 -212
- package/dist/server/shared.js +71 -780
- package/dist/server/task-views.js +9 -76
- package/dist/server/tasks.d.ts +1 -50
- package/dist/server/tasks.js +36 -946
- package/dist/setup-guide.d.ts +2 -2
- package/dist/slack-api.d.ts +5 -1
- package/dist/slack-api.js +2 -2
- package/dist/slack-chat.d.ts +9 -6
- package/dist/slack-chat.js +29 -53
- package/dist/slack-settings.js +6 -15
- package/dist/slack.js +6 -16
- package/dist/store.d.ts +200 -1702
- package/dist/store.js +811 -5439
- package/dist/surface.js +10 -24
- package/dist/task-composer.d.ts +1 -1
- package/dist/task-composer.js +1 -1
- package/dist/task-control.d.ts +3 -10
- package/dist/task-control.js +2 -7
- package/dist/teammate-desk.js +1 -1
- package/dist/teammate-question.js +12 -12
- package/dist/teammates-ui.js +1 -1
- package/dist/teams-chat.js +12 -9
- package/dist/teams-settings.js +2 -2
- package/dist/teams.js +4 -5
- package/dist/telegram-flow.js +5 -5
- package/dist/telegram-mate.d.ts +0 -3
- package/dist/telegram-mate.js +0 -1
- package/dist/telegram.js +4 -4
- package/dist/templates.d.ts +11 -7
- package/dist/templates.js +12 -9
- package/dist/toolroll-update.d.ts +20 -0
- package/dist/toolroll-update.js +104 -5
- package/dist/work-index.js +2 -6
- package/dist/workspace-revision.js +3 -1
- package/dist/workspace-ui.js +1 -1
- package/package.json +1 -1
- package/scripts/recovery-canary.mjs +3 -3
- package/dist/contest.d.ts +0 -318
- package/dist/contest.js +0 -753
- package/dist/held.d.ts +0 -150
- package/dist/held.js +0 -799
- package/dist/liveness.d.ts +0 -30
- package/dist/liveness.js +0 -42
- package/dist/pricing.d.ts +0 -45
- package/dist/pricing.js +0 -77
- package/dist/routine.d.ts +0 -228
- package/dist/routine.js +0 -764
- package/dist/slack-state.d.ts +0 -13
- package/dist/slack-state.js +0 -10
- package/dist/supervisor.mjs +0 -297
|
@@ -123,15 +123,13 @@ export declare const CONSOLE_FORMS: {
|
|
|
123
123
|
readonly tasksAdd: FormContract<"acceptance" | "after" | "goal" | "id" | "not" | "permission-mode" | "plan-first" | "planning-policy" | "projectRevision" | "quality-mode" | "repo" | "scout" | "title" | "touches">;
|
|
124
124
|
readonly queue: FormContract<"before" | "column" | "from" | "note" | "projectRevision" | "queueRevision" | "respond" | "runner" | "task">;
|
|
125
125
|
readonly runnerRegister: FormContract<"capacity" | "name" | "token">;
|
|
126
|
-
readonly mode: FormContract<"
|
|
126
|
+
readonly mode: FormContract<"auto-approve" | "chat-approve" | "days" | "digest" | "expiry" | "name" | "nonce" | "plan-auto" | "publication" | "repair-auto" | "review-auto" | "review-retry-auto" | "token">;
|
|
127
127
|
readonly peopleProjects: FormContract<"access" | "name" | "projects" | "token">;
|
|
128
128
|
readonly peopleInvite: FormContract<"access" | "projects" | "role" | "token">;
|
|
129
129
|
readonly peopleInviteRevoke: FormContract<"id" | "token">;
|
|
130
130
|
readonly peopleRevoke: FormContract<"name" | "token">;
|
|
131
131
|
readonly runnerRetire: FormContract<"name" | "token">;
|
|
132
132
|
readonly decisionAnswer: FormContract<"choice" | "confirm" | "note" | "return">;
|
|
133
|
-
readonly contest: FormContract<"act" | "choice" | "nonce" | "token">;
|
|
134
|
-
readonly attend: FormContract<"budget" | "digest" | "expiry" | "followup" | "minutes" | "model" | "nonce" | "parent" | "posture" | "token" | "turns">;
|
|
135
133
|
readonly confirmStopped: FormContract<"checked" | "return" | "run" | "token">;
|
|
136
134
|
readonly merge: FormContract<"anyway" | "run" | "token">;
|
|
137
135
|
readonly onboard: FormContract<"big-ok" | "nonce" | "repo" | "root" | "token">;
|
|
@@ -152,12 +150,9 @@ export declare const CONSOLE_FORMS: {
|
|
|
152
150
|
readonly chatFile: FormContract<"token">;
|
|
153
151
|
readonly chatAck: FormContract<"nonce" | "token">;
|
|
154
152
|
readonly recipes: FormContract<"document" | "next" | "preview" | "projectRevision" | "purpose" | "recipe" | "recipeRevision" | "repo" | "source" | "sourceRevision">;
|
|
155
|
-
readonly routinesAdd: FormContract<"acceptance" | "ceiling" | "goal" | "interval" | "interval-unit" | "name" | "not" | "projectRevision" | "repeat" | "schedule" | "time" | "timezone" | "touches" | "weekday">;
|
|
156
|
-
readonly routine: FormContract<"digest" | "nonce" | "token">;
|
|
157
153
|
readonly runNote: FormContract<"note">;
|
|
158
154
|
readonly diffComment: FormContract<"batch" | "intent" | "line" | "note" | "path" | "request" | "return" | "source" | "tab">;
|
|
159
155
|
readonly editorLinks: FormContract<"on" | "return">;
|
|
160
|
-
readonly turn: FormContract<"text">;
|
|
161
156
|
readonly revise: FormContract<"batch" | "return" | "source">;
|
|
162
157
|
readonly followUp: FormContract<"level" | "return">;
|
|
163
158
|
readonly resolveIncident: FormContract<"return">;
|
|
@@ -172,8 +167,8 @@ export declare const CONSOLE_FORMS: {
|
|
|
172
167
|
readonly taskPlanEdit: FormContract<"plan-document" | "saw-plan">;
|
|
173
168
|
readonly taskRevision: FormContract<"revision-id" | "token">;
|
|
174
169
|
readonly taskCancel: FormContract<"reason">;
|
|
175
|
-
readonly taskRoute: FormContract<"agent" | "clear-phase" | "model" | "phase" | "provider" | "return" | "
|
|
176
|
-
readonly taskScope: FormContract<"acceptance" | "budget-microusd" | "budget-usd" | "goal" | "goal-brief" | "not" | "permission-mode" | "quality-mode" | "
|
|
170
|
+
readonly taskRoute: FormContract<"agent" | "clear-phase" | "model" | "phase" | "provider" | "return" | "risky" | "sawDigest" | "size">;
|
|
171
|
+
readonly taskScope: FormContract<"acceptance" | "budget-microusd" | "budget-usd" | "goal" | "goal-brief" | "not" | "permission-mode" | "quality-mode" | "requirement" | "requirement-new" | "sawDigest" | "touches">;
|
|
177
172
|
readonly taskApprove: FormContract<"digest" | "nonce" | "return" | "token">;
|
|
178
173
|
readonly taskAcceptProof: FormContract<"note" | "return" | "run">;
|
|
179
174
|
readonly taskComplete: FormContract<"accept" | "note" | "publish" | "receipt" | "return" | "run">;
|
|
@@ -181,8 +176,8 @@ export declare const CONSOLE_FORMS: {
|
|
|
181
176
|
readonly taskResume: FormContract<"nonce" | "return" | "run" | "token">;
|
|
182
177
|
};
|
|
183
178
|
export type ConsoleFormName = keyof typeof CONSOLE_FORMS;
|
|
184
|
-
/** The console POSTs whose handlers read no field (sign-out
|
|
185
|
-
export declare const BODILESS_POSTS: readonly ["POST /settings/lead/on", "POST /r/<run>/draft-repair", "POST /ledger/checkpoint", "POST /settings/backups/now", "POST /mode/revoke", "POST /settings/telegram/retry", "POST /providers/<provider>/resume", "POST /
|
|
179
|
+
/** The console POSTs whose handlers read no field (sign-out not even the shared guard): their contract is the empty form. */
|
|
180
|
+
export declare const BODILESS_POSTS: readonly ["POST /settings/lead/on", "POST /r/<run>/draft-repair", "POST /ledger/checkpoint", "POST /settings/backups/now", "POST /mode/revoke", "POST /settings/telegram/retry", "POST /providers/<provider>/resume", "POST /logout", "POST /t/<task>/unhold", "POST /t/<task>/plan", "POST /t/<task>/retry-review"];
|
|
186
181
|
/** The field names a console form's handler may read. */
|
|
187
182
|
export type FormFieldOf<N extends ConsoleFormName> = (typeof CONSOLE_FORMS)[N] extends FormContract<infer K> ? K : never;
|
|
188
183
|
/** `GET /ledger?format=json`: the chain's state, a page of entries (newest first) and the cursor for the next. */
|
|
@@ -132,15 +132,13 @@ export const CONSOLE_FORMS = {
|
|
|
132
132
|
tasksAdd: formContract("POST /tasks/add", ["projectRevision", "id", "title", "repo", "goal", "not", "touches", "scout", "permission-mode", "quality-mode", "after", "acceptance", "planning-policy", "plan-first"]),
|
|
133
133
|
queue: formContract("POST /queue/move, /queue/note", ["runner", "note", "from", "projectRevision", "respond", "task", "column", "before", "queueRevision"]),
|
|
134
134
|
runnerRegister: formContract("POST /fleet/runner/register", ["token", "name", "capacity"]),
|
|
135
|
-
mode: formContract("POST /mode/confirm, /mode/sign", ["name", "days", "auto-approve", "plan-auto", "
|
|
135
|
+
mode: formContract("POST /mode/confirm, /mode/sign", ["name", "days", "auto-approve", "plan-auto", "chat-approve", "publication", "expiry", "nonce", "digest", "token", "review-auto", "review-retry-auto", "repair-auto"]),
|
|
136
136
|
peopleProjects: formContract("POST /people/projects", ["token", "name", "access", "projects"]),
|
|
137
137
|
peopleInvite: formContract("POST /people/invite", ["token", "role", "access", "projects"]),
|
|
138
138
|
peopleInviteRevoke: formContract("POST /people/invite-revoke", ["token", "id"]),
|
|
139
139
|
peopleRevoke: formContract("POST /people/revoke", ["token", "name"]),
|
|
140
140
|
runnerRetire: formContract("POST /fleet/runner/retire", ["token", "name"]),
|
|
141
141
|
decisionAnswer: formContract("POST /d/<id>/answer", ["return", "choice", "confirm", "note"]),
|
|
142
|
-
contest: formContract("POST /contest/<id>/arm|pick|abandon", ["act", "choice", "token", "nonce"]),
|
|
143
|
-
attend: formContract("POST /t/<task>/attend|attend-preview|attend-revoke", ["parent", "followup", "minutes", "turns", "budget", "expiry", "model", "posture", "nonce", "digest", "token"]),
|
|
144
142
|
confirmStopped: formContract("POST /t/<task>/confirm-stopped", ["run", "token", "checked", "return"]),
|
|
145
143
|
merge: formContract("POST /t/<task>/merge", ["run", "token", "anyway"]),
|
|
146
144
|
onboard: formContract("POST /projects/onboard-preview, /projects/onboard-confirm", ["repo", "root", "token", "nonce", "big-ok"]),
|
|
@@ -162,12 +160,9 @@ export const CONSOLE_FORMS = {
|
|
|
162
160
|
chatAck: formContract("POST /chat/ack/<id>", ["token", "nonce"]),
|
|
163
161
|
// A recipe's own answers and editor fields are read by recipes.ts from the whole form (`sent`; item 17).
|
|
164
162
|
recipes: formContract("POST /recipes/prepare, /recipes/preview, /recipes/import, /recipes/launch, /recipes/save", ["repo", "projectRevision", "recipe", "recipeRevision", "document", "purpose", "source", "sourceRevision", "preview", "next"]),
|
|
165
|
-
routinesAdd: formContract("POST /routines/add", ["projectRevision", "name", "ceiling", "repeat", "interval", "interval-unit", "time", "timezone", "weekday", "schedule", "goal", "not", "touches", "acceptance"]),
|
|
166
|
-
routine: formContract("POST /routines/<id>/approve|refresh|pause|resume|run-now", ["digest", "nonce", "token"]),
|
|
167
163
|
runNote: formContract("POST /r/<run>/note", ["note"]),
|
|
168
164
|
diffComment: formContract("POST /r/<run>/comment", ["return", "tab", "intent", "batch", "source", "note", "path", "line", "request"]),
|
|
169
165
|
editorLinks: formContract("POST /session/editor-links", ["on", "return"]),
|
|
170
|
-
turn: formContract("POST /r/<run>/turn", ["text"]),
|
|
171
166
|
revise: formContract("POST /r/<run>/revise", ["return", "batch", "source"]),
|
|
172
167
|
followUp: formContract("POST /r/<run>/checks|add-tests", ["return", "level"]),
|
|
173
168
|
resolveIncident: formContract("POST /i/<id>/resolve", ["return"]),
|
|
@@ -183,15 +178,15 @@ export const CONSOLE_FORMS = {
|
|
|
183
178
|
taskPlanEdit: formContract("POST /t/<task>/plan-edit", ["saw-plan", "plan-document"]),
|
|
184
179
|
taskRevision: formContract("POST /t/<task>/accept-revision|reject-revision", ["revision-id", "token"]),
|
|
185
180
|
taskCancel: formContract("POST /t/<task>/cancel", ["reason"]),
|
|
186
|
-
taskRoute: formContract("POST /t/<task>/route", ["
|
|
187
|
-
taskScope: formContract("POST /t/<task>/scope", ["sawDigest", "permission-mode", "quality-mode", "budget-usd", "budget-microusd", "requirement", "requirement-new", "
|
|
181
|
+
taskRoute: formContract("POST /t/<task>/route", ["size", "risky", "phase", "clear-phase", "agent", "provider", "model", "sawDigest", "return"]),
|
|
182
|
+
taskScope: formContract("POST /t/<task>/scope", ["sawDigest", "permission-mode", "quality-mode", "budget-usd", "budget-microusd", "requirement", "requirement-new", "goal-brief", "goal", "not", "touches", "acceptance"]),
|
|
188
183
|
taskApprove: formContract("POST /t/<task>/approve", ["return", "digest", "token", "nonce"]),
|
|
189
184
|
taskAcceptProof: formContract("POST /t/<task>/accept-proof", ["run", "note", "return"]),
|
|
190
185
|
taskComplete: formContract("POST /t/<task>/complete", ["receipt", "run", "accept", "note", "publish", "return"]),
|
|
191
186
|
taskStop: formContract("POST /t/<task>/stop", ["run", "return"]),
|
|
192
187
|
taskResume: formContract("POST /t/<task>/resume|resume-arm", ["run", "token", "nonce", "return"]),
|
|
193
188
|
};
|
|
194
|
-
/** The console POSTs whose handlers read no field (sign-out
|
|
189
|
+
/** The console POSTs whose handlers read no field (sign-out not even the shared guard): their contract is the empty form. */
|
|
195
190
|
export const BODILESS_POSTS = [
|
|
196
191
|
"POST /settings/lead/on",
|
|
197
192
|
"POST /r/<run>/draft-repair",
|
|
@@ -200,7 +195,6 @@ export const BODILESS_POSTS = [
|
|
|
200
195
|
"POST /mode/revoke",
|
|
201
196
|
"POST /settings/telegram/retry",
|
|
202
197
|
"POST /providers/<provider>/resume",
|
|
203
|
-
"POST /session/attended-beats",
|
|
204
198
|
"POST /logout",
|
|
205
199
|
"POST /t/<task>/unhold",
|
|
206
200
|
"POST /t/<task>/plan",
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* message whose button can't be read is answered with why (`data.custom_id: not a Toolroll button`), and nothing is done.
|
|
6
6
|
*/
|
|
7
7
|
import { z } from "zod";
|
|
8
|
+
import { CHAT_BUTTON_TOKEN } from "./chat-content.js";
|
|
8
9
|
import { parseContract } from "./contract.js";
|
|
9
10
|
const user = z.object({ id: z.string() });
|
|
10
11
|
/** The interaction around a tap (type 3: a message component): the app, the person, the channel, the message. */
|
|
@@ -22,7 +23,7 @@ export const discordComponentInteractionSchema = z.object({
|
|
|
22
23
|
});
|
|
23
24
|
/** Toolroll's button data: `so_` and a one-time token. */
|
|
24
25
|
export const discordButtonSchema = z.object({
|
|
25
|
-
custom_id: z.string().regex(
|
|
26
|
+
custom_id: z.string().regex(new RegExp(`^so_${CHAT_BUTTON_TOKEN.source.slice(1)}`), { error: "not a Toolroll button" }),
|
|
26
27
|
});
|
|
27
28
|
export function readDiscordComponentInteraction(body) {
|
|
28
29
|
return parseContract(discordComponentInteractionSchema, body);
|
package/dist/contracts/flow.d.ts
CHANGED
|
@@ -10964,6 +10964,36 @@ export declare const leadTriggerSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
10964
10964
|
at: z.ZodOptional<z.ZodString>;
|
|
10965
10965
|
timeZone: z.ZodOptional<z.ZodString>;
|
|
10966
10966
|
}, z.core.$strict>], "kind">;
|
|
10967
|
+
/**
|
|
10968
|
+
* v115: the exact task a schedule files each time — what a routine was before routines became scheduled flows. Its
|
|
10969
|
+
* terms are copied into each firing's scope unchanged; `costCeilingUsd` caps what its tasks spend in a rolling 7 days
|
|
10970
|
+
* and a firing waits while the last task is unfinished. `approval` is a routine's approval carried over whole (the
|
|
10971
|
+
* digest the approver signed over these terms, this schedule and project, and the agents it froze): while it still
|
|
10972
|
+
* verifies, each firing is approved as the routine's were; otherwise each firing is an ordinary proposal under the
|
|
10973
|
+
* project's approval rules. Only the v115 migration carries an approval; a template or a recipe makes one with none
|
|
10974
|
+
* (createScheduledFlow), and no trigger settings a person or a flow file gives can carry one.
|
|
10975
|
+
*/
|
|
10976
|
+
export declare const standingOrderSchema: z.ZodObject<{
|
|
10977
|
+
stem: z.ZodString;
|
|
10978
|
+
goal: z.ZodString;
|
|
10979
|
+
outOfScope: z.ZodNullable<z.ZodString>;
|
|
10980
|
+
touches: z.ZodArray<z.ZodString>;
|
|
10981
|
+
requirements: z.ZodArray<z.ZodString>;
|
|
10982
|
+
acceptance: z.ZodArray<z.ZodUnknown>;
|
|
10983
|
+
budgetPerRunMicrousd: z.ZodNullable<z.ZodInt>;
|
|
10984
|
+
costCeilingUsd: z.ZodNullable<z.ZodNumber>;
|
|
10985
|
+
singleFlight: z.ZodLiteral<true>;
|
|
10986
|
+
filedBy: z.ZodNullable<z.ZodString>;
|
|
10987
|
+
routine: z.ZodNullable<z.ZodInt>;
|
|
10988
|
+
approval: z.ZodNullable<z.ZodObject<{
|
|
10989
|
+
digest: z.ZodString;
|
|
10990
|
+
by: z.ZodNullable<z.ZodString>;
|
|
10991
|
+
at: z.ZodString;
|
|
10992
|
+
profileJson: z.ZodString;
|
|
10993
|
+
routeJson: z.ZodString;
|
|
10994
|
+
}, z.core.$strict>>;
|
|
10995
|
+
}, z.core.$strict>;
|
|
10996
|
+
export type StandingOrder = z.infer<typeof standingOrderSchema>;
|
|
10967
10997
|
/** A trigger as it is saved (`configJson`), one schema per kind. */
|
|
10968
10998
|
export declare const triggerConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
10969
10999
|
zone: z.ZodNullable<z.ZodString>;
|
|
@@ -10978,6 +11008,26 @@ export declare const triggerConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
10978
11008
|
description: z.ZodNullable<z.ZodString>;
|
|
10979
11009
|
script: z.ZodOptional<z.ZodString>;
|
|
10980
11010
|
secrets: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
11011
|
+
order: z.ZodOptional<z.ZodObject<{
|
|
11012
|
+
stem: z.ZodString;
|
|
11013
|
+
goal: z.ZodString;
|
|
11014
|
+
outOfScope: z.ZodNullable<z.ZodString>;
|
|
11015
|
+
touches: z.ZodArray<z.ZodString>;
|
|
11016
|
+
requirements: z.ZodArray<z.ZodString>;
|
|
11017
|
+
acceptance: z.ZodArray<z.ZodUnknown>;
|
|
11018
|
+
budgetPerRunMicrousd: z.ZodNullable<z.ZodInt>;
|
|
11019
|
+
costCeilingUsd: z.ZodNullable<z.ZodNumber>;
|
|
11020
|
+
singleFlight: z.ZodLiteral<true>;
|
|
11021
|
+
filedBy: z.ZodNullable<z.ZodString>;
|
|
11022
|
+
routine: z.ZodNullable<z.ZodInt>;
|
|
11023
|
+
approval: z.ZodNullable<z.ZodObject<{
|
|
11024
|
+
digest: z.ZodString;
|
|
11025
|
+
by: z.ZodNullable<z.ZodString>;
|
|
11026
|
+
at: z.ZodString;
|
|
11027
|
+
profileJson: z.ZodString;
|
|
11028
|
+
routeJson: z.ZodString;
|
|
11029
|
+
}, z.core.$strict>>;
|
|
11030
|
+
}, z.core.$strict>>;
|
|
10981
11031
|
}, z.core.$strict>, z.ZodObject<{
|
|
10982
11032
|
zone: z.ZodNullable<z.ZodString>;
|
|
10983
11033
|
kind: z.ZodLiteral<"github">;
|
package/dist/contracts/flow.js
CHANGED
|
@@ -309,11 +309,36 @@ export const leadTriggerSchema = z.discriminatedUnion("kind", [
|
|
|
309
309
|
TRIGGER_INPUTS.flow.omit({ flow: true }).extend({ follow: z.int().min(1).describe("The other flow's id (get_flows).") }), TRIGGER_INPUTS.email, TRIGGER_INPUTS["plane-review"],
|
|
310
310
|
]);
|
|
311
311
|
const ZONE_OR_NULL = { zone: zoneId.nullable() };
|
|
312
|
+
/**
|
|
313
|
+
* v115: the exact task a schedule files each time — what a routine was before routines became scheduled flows. Its
|
|
314
|
+
* terms are copied into each firing's scope unchanged; `costCeilingUsd` caps what its tasks spend in a rolling 7 days
|
|
315
|
+
* and a firing waits while the last task is unfinished. `approval` is a routine's approval carried over whole (the
|
|
316
|
+
* digest the approver signed over these terms, this schedule and project, and the agents it froze): while it still
|
|
317
|
+
* verifies, each firing is approved as the routine's were; otherwise each firing is an ordinary proposal under the
|
|
318
|
+
* project's approval rules. Only the v115 migration carries an approval; a template or a recipe makes one with none
|
|
319
|
+
* (createScheduledFlow), and no trigger settings a person or a flow file gives can carry one.
|
|
320
|
+
*/
|
|
321
|
+
export const standingOrderSchema = z.strictObject({
|
|
322
|
+
stem: z.string().regex(/^[a-z0-9][a-z0-9-]{0,40}$/),
|
|
323
|
+
// The terms exactly as they were approved: each firing's filing checks them again, as every filing is checked.
|
|
324
|
+
goal: z.string().max(8_000),
|
|
325
|
+
outOfScope: z.string().max(8_000).nullable(),
|
|
326
|
+
touches: z.array(z.string().max(800)).max(200),
|
|
327
|
+
requirements: z.array(z.string().max(400)).max(100),
|
|
328
|
+
acceptance: z.array(z.unknown()),
|
|
329
|
+
budgetPerRunMicrousd: z.int().nullable(),
|
|
330
|
+
costCeilingUsd: z.number().nullable(),
|
|
331
|
+
singleFlight: z.literal(true),
|
|
332
|
+
filedBy: z.string().min(1).nullable(),
|
|
333
|
+
/** The routine it came from: that routine's earlier tasks still count toward one-at-a-time and the ceiling. */
|
|
334
|
+
routine: z.int().nullable(),
|
|
335
|
+
approval: z.strictObject({ digest: z.string().min(1), by: z.string().nullable(), at: z.string().min(1), profileJson: z.string().min(1), routeJson: z.string().min(1) }).nullable(),
|
|
336
|
+
});
|
|
312
337
|
/** A trigger as it is saved (`configJson`), one schema per kind. */
|
|
313
338
|
export const triggerConfigSchema = z.discriminatedUnion("kind", [
|
|
314
339
|
z.strictObject({ kind: z.literal("button"), label: z.string().min(1).max(TEXT_LIMITS.triggerButton), questions: z.array(z.string().min(1).max(TEXT_LIMITS.triggerQuestion)).min(1).max(6), ...ZONE_OR_NULL }),
|
|
315
340
|
/** `script`: run this project script on the schedule and make a card of each item it prints, instead of one card titled `title`. */
|
|
316
|
-
z.strictObject({ kind: z.literal("schedule"), schedule: z.string().min(1), title: z.string().min(1).max(TEXT_LIMITS.triggerTitle), description: z.string().max(TEXT_LIMITS.triggerDescription).nullable(), ...ZONE_OR_NULL, script: scriptName.optional(), secrets: z.array(secretName).min(1).max(SECRETS_MAX).optional() }),
|
|
341
|
+
z.strictObject({ kind: z.literal("schedule"), schedule: z.string().min(1), title: z.string().min(1).max(TEXT_LIMITS.triggerTitle), description: z.string().max(TEXT_LIMITS.triggerDescription).nullable(), ...ZONE_OR_NULL, script: scriptName.optional(), secrets: z.array(secretName).min(1).max(SECRETS_MAX).optional(), order: standingOrderSchema.optional() }),
|
|
317
342
|
z.strictObject({ kind: z.literal("github"), repo: z.string().min(1).max(TEXT_LIMITS.triggerGithubRepo), watch: z.enum(["issues", "pulls", "checks"]), label: z.string().max(TEXT_LIMITS.triggerLabel).nullable(), branch: z.string().max(TEXT_LIMITS.triggerBranch).nullable(), from: z.enum(["team", "anyone"]), delivery, ...ZONE_OR_NULL }),
|
|
318
343
|
z.strictObject({ kind: z.literal("linear"), team: z.string().max(TEXT_LIMITS.triggerTeam).nullable(), state: z.string().max(TEXT_LIMITS.triggerState).nullable(), label: z.string().max(TEXT_LIMITS.triggerLabel).nullable(), delivery, ...ZONE_OR_NULL }),
|
|
319
344
|
z.strictObject({ kind: z.literal("flow"), flow: z.int().min(1), when: zoneId, ...ZONE_OR_NULL }),
|
|
@@ -686,11 +686,6 @@ export declare const LEAD_TOOL_INPUTS: {
|
|
|
686
686
|
}, z.core.$strict>;
|
|
687
687
|
readonly propose_agents: z.ZodObject<{
|
|
688
688
|
task: z.ZodString;
|
|
689
|
-
risk: z.ZodOptional<z.ZodEnum<{
|
|
690
|
-
elevated: "elevated";
|
|
691
|
-
high: "high";
|
|
692
|
-
routine: "routine";
|
|
693
|
-
}>>;
|
|
694
689
|
size: z.ZodOptional<z.ZodEnum<{
|
|
695
690
|
large: "large";
|
|
696
691
|
medium: "medium";
|
|
@@ -1388,11 +1383,6 @@ export declare const LEAD_TOOL_READ_INPUTS: {
|
|
|
1388
1383
|
}, z.core.$strict>;
|
|
1389
1384
|
readonly propose_agents: z.ZodObject<{
|
|
1390
1385
|
task: z.ZodString;
|
|
1391
|
-
risk: z.ZodOptional<z.ZodEnum<{
|
|
1392
|
-
elevated: "elevated";
|
|
1393
|
-
high: "high";
|
|
1394
|
-
routine: "routine";
|
|
1395
|
-
}>>;
|
|
1396
1386
|
size: z.ZodOptional<z.ZodEnum<{
|
|
1397
1387
|
large: "large";
|
|
1398
1388
|
medium: "medium";
|
|
@@ -1811,9 +1801,6 @@ export declare const LEAD_TOOL_OUTPUTS: {
|
|
|
1811
1801
|
readonly get_agents: z.ZodObject<{
|
|
1812
1802
|
repo: z.ZodString;
|
|
1813
1803
|
task: z.ZodString;
|
|
1814
|
-
risk: z.ZodObject<{
|
|
1815
|
-
level: z.ZodString;
|
|
1816
|
-
}, z.core.$loose>;
|
|
1817
1804
|
standing: z.ZodString;
|
|
1818
1805
|
agents: z.ZodArray<z.ZodUnknown>;
|
|
1819
1806
|
choices: z.ZodObject<{}, z.core.$loose>;
|
|
@@ -16,7 +16,7 @@ import { CHAT_TASK_ACTIONS } from "../chat-task-actions.js";
|
|
|
16
16
|
import { LIMITS } from "../decision.js";
|
|
17
17
|
import { CHECK_RESULTS, RUN_OUTCOMES, TASK_STATES } from "../lead-commitments.js";
|
|
18
18
|
import { PERSON_ID } from "../lead-people.js";
|
|
19
|
-
import {
|
|
19
|
+
import { TASK_SIZES } from "../phase-routing.js";
|
|
20
20
|
import { ACCEPTANCE_LIMITS } from "../scope.js";
|
|
21
21
|
import { TEAMMATE_TEMPLATES } from "../teammates.js";
|
|
22
22
|
import { TEXT_LIMITS } from "../text-limits.js";
|
|
@@ -134,7 +134,7 @@ export const LEAD_TOOL_INPUTS = {
|
|
|
134
134
|
propose_dependency_repair: z.strictObject({ task: taskRef, blocker: taskRef, operation: z.enum(["retry", "unlink", "replace"]), replacement: taskRef.optional() }),
|
|
135
135
|
propose_scope: z.strictObject({ task: taskRef, goal: scopeText, not: scopeText.nullable().optional(), touches: touches.optional(), acceptance }),
|
|
136
136
|
propose_agents: z.strictObject({
|
|
137
|
-
task: taskRef,
|
|
137
|
+
task: taskRef,
|
|
138
138
|
size: z.enum(TASK_SIZES).optional(), risky: z.boolean().optional(),
|
|
139
139
|
role: z.enum(["planner", "builder", "repair"]).optional(),
|
|
140
140
|
agent: z.strictObject({ provider: text("agentProvider"), model: text("agentModel") }).optional(),
|
|
@@ -238,7 +238,7 @@ export const LEAD_TOOL_OUTPUTS = {
|
|
|
238
238
|
repo: str, task: str, root: str, currentExecution: str, title: str, state: str, deliverable: str, scope: str,
|
|
239
239
|
queue: nullable(z.looseObject({ position: int, of: int, column: str })), holds: list, attempts: int, decisionsOpen: int, dependencies: list,
|
|
240
240
|
}),
|
|
241
|
-
get_agents: z.looseObject({ repo: str, task: str,
|
|
241
|
+
get_agents: z.looseObject({ repo: str, task: str, standing: str, agents: list, choices: z.looseObject({}), approval: str, organisationPolicy: z.looseObject({}) }),
|
|
242
242
|
list_decisions: decisionsOutput,
|
|
243
243
|
get_decision: decisionOutput,
|
|
244
244
|
queue: z.looseObject({ repo: str, queueRevision: int, ...queueColumnsOutput }),
|
|
@@ -6,11 +6,12 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
import { parseContract } from "./contract.js";
|
|
9
|
+
import { CHAT_BUTTON_TOKEN } from "./chat-content.js";
|
|
9
10
|
/** Toolroll's buttons: toolroll_* since the rename; standing_orders_* buttons on older messages still work. */
|
|
10
|
-
export const SLACK_BUTTON_ACTION = /^(?:toolroll|standing_orders)_(?:confirm|dismiss|yes|cancel|flow_approve|flow_edit|flow_send_back|flow_choose_[0-3]|flow_note_(?:yes|no)|question_choice|question_words)$/;
|
|
11
|
+
export const SLACK_BUTTON_ACTION = /^(?:toolroll|standing_orders)_(?:confirm|dismiss|yes|cancel|flow_approve|flow_edit|flow_send_back|flow_choose_[0-3]|flow_note_(?:yes|no)|question_choice|question_words|decide_[0-9]{1,2})$/;
|
|
11
12
|
/** A link button opens its page in Slack's own client; Slack still reports the tap, and there is nothing to do. */
|
|
12
13
|
export const SLACK_LINK_ACTION = /^(?:toolroll|standing_orders)_link(?:_[0-9]+)?$/;
|
|
13
|
-
const token = z.string().regex(
|
|
14
|
+
const token = z.string().regex(CHAT_BUTTON_TOKEN, { error: "must be a Toolroll button token" });
|
|
14
15
|
/** The interaction around a tap: who, and the message the button is on. */
|
|
15
16
|
export const slackBlockActionsSchema = z.object({
|
|
16
17
|
type: z.literal("block_actions"),
|
|
@@ -115,11 +115,7 @@ declare const STORE_COLUMN_VALUES: {
|
|
|
115
115
|
quickMint: z.ZodOptional<z.ZodBoolean>;
|
|
116
116
|
publication: z.ZodOptional<z.ZodString>;
|
|
117
117
|
}, z.core.$loose>;
|
|
118
|
-
readonly "attended_authorization.terms_json": z.ZodObject<{
|
|
119
|
-
profileJson: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
120
|
-
}, z.core.$loose>;
|
|
121
118
|
readonly "approval_policy.protected_paths": z.ZodArray<z.ZodUnknown>;
|
|
122
|
-
readonly "fallback_config.entries_json": z.ZodArray<z.ZodUnknown>;
|
|
123
119
|
readonly "runner.repos": z.ZodArray<z.ZodUnknown>;
|
|
124
120
|
readonly "runner.agents": z.ZodArray<z.ZodUnknown>;
|
|
125
121
|
readonly "decision.options": z.ZodArray<z.ZodObject<{
|
|
@@ -159,36 +155,12 @@ declare const STORE_COLUMN_VALUES: {
|
|
|
159
155
|
note: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
160
156
|
}, z.core.$loose>>;
|
|
161
157
|
}, z.core.$loose>;
|
|
162
|
-
readonly "telegram_conversation_part.keyboard_json": z.ZodArray<z.ZodArray<z.ZodObject<{
|
|
163
|
-
text: z.ZodString;
|
|
164
|
-
callback_data: z.ZodString;
|
|
165
|
-
}, z.core.$loose>>>;
|
|
166
158
|
readonly "publication_grant.capabilities": z.ZodArray<z.ZodEnum<{
|
|
167
159
|
"open-pr": "open-pr";
|
|
168
160
|
"push-branch": "push-branch";
|
|
169
161
|
}>>;
|
|
170
162
|
readonly "task_ref.zones": z.ZodArray<z.ZodUnknown>;
|
|
171
163
|
readonly "task_ref.capability_requirements": z.ZodArray<z.ZodUnknown>;
|
|
172
|
-
readonly "routine.touches": z.ZodArray<z.ZodUnknown>;
|
|
173
|
-
readonly "routine.requirements": z.ZodArray<z.ZodUnknown>;
|
|
174
|
-
/** Read by `parseAcceptanceCriteria`, as `task_scope.acceptance_json`. */
|
|
175
|
-
readonly "routine.acceptance_json": z.ZodLazy<z.ZodArray<z.ZodObject<{
|
|
176
|
-
id: z.ZodString;
|
|
177
|
-
statement: z.ZodString;
|
|
178
|
-
how: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
179
|
-
evidence: z.ZodArray<z.ZodEnum<{
|
|
180
|
-
"changed-path": "changed-path";
|
|
181
|
-
check: "check";
|
|
182
|
-
"manual-review": "manual-review";
|
|
183
|
-
screenshot: "screenshot";
|
|
184
|
-
}>>;
|
|
185
|
-
}, z.core.$strict>>>;
|
|
186
|
-
readonly "tournament_terms.agents": z.ZodArray<z.ZodObject<{
|
|
187
|
-
provider: z.ZodString;
|
|
188
|
-
model: z.ZodString;
|
|
189
|
-
repairModel: z.ZodString;
|
|
190
|
-
permissionMode: z.ZodOptional<z.ZodString>;
|
|
191
|
-
}, z.core.$loose>>;
|
|
192
164
|
readonly "coordinator_proposal.payload_json": z.ZodObject<{}, z.core.$loose>;
|
|
193
165
|
readonly "coordinator_proposal.outcome_json": z.ZodObject<{}, z.core.$loose>;
|
|
194
166
|
readonly "mate_proposal.payload_json": z.ZodUnion<readonly [z.ZodObject<{
|
|
@@ -278,7 +250,7 @@ declare const STORE_COLUMN_VALUES: {
|
|
|
278
250
|
export type StoreColumn = keyof typeof STORE_COLUMN_VALUES;
|
|
279
251
|
export type StoreColumnValue<C extends StoreColumn> = z.infer<(typeof STORE_COLUMN_VALUES)[C]>;
|
|
280
252
|
/** Every JSON column the store reads itself, by `table.column`. */
|
|
281
|
-
export declare const STORE_COLUMNS: ("approval_policy.protected_paths" | "
|
|
253
|
+
export declare const STORE_COLUMNS: ("approval_policy.protected_paths" | "backend_grant.mutations" | "backend_grant.paths" | "coordinator_proposal.outcome_json" | "coordinator_proposal.payload_json" | "criterion_review.screenshots_json" | "decision.options" | "flow_card.source_json" | "flow_comment.mentions_json" | "lead_config.about_json" | "mate_ask.options_json" | "mate_proposal.outcome_json" | "mate_proposal.payload_json" | "mutation.result" | "operating_mode.terms_json" | "plan_revision.changed_fields" | "proof_verdict.matrix_json" | "proof_verdict.reasons_json" | "publication_grant.capabilities" | "repair_chain.unresolved_json" | "run_check.suites_json" | "run_checkpoint.snapshot_json" | "run_tool.tools_json" | "runner.agents" | "runner.repos" | "task_ref.capability_requirements" | "task_ref.zones" | "task_scope.acceptance_json" | "task_scope.touches" | "teammate_call.input_json" | "teammate_event.detail_json" | "teammate_question.options_json" | "teammate_suggestion.evidence_json" | "teammate_suggestion.rule_json" | "teammate_suggestion.was_json" | "teammate_tool.actions_json" | "teammate_tool.rules_json" | "tool_seal.tools_json")[];
|
|
282
254
|
/** A SQL projection, not a physical column; replay it separately after its owning column. */
|
|
283
255
|
export declare const STORE_PROJECTIONS: readonly ["run_tool.tools_json.fence"];
|
|
284
256
|
/** These readers historically only parsed JSON. Shape errors must not change their values or catch boundaries. */
|
|
@@ -16,7 +16,6 @@ import { decisionOptionSchema } from "./decision.js";
|
|
|
16
16
|
import { scopeTermsSchema, storedRubricSchema } from "./scope.js";
|
|
17
17
|
import { criterionEvidenceSchema, proofCriterionSchema } from "./proof.js";
|
|
18
18
|
import { sharedActionSchema } from "./chat-actions.js";
|
|
19
|
-
import { telegramCallbackButtonSchema } from "./telegram-callback.js";
|
|
20
19
|
import { readVersioned, versioned } from "./contract.js";
|
|
21
20
|
/** Dynamic tool arguments, event details and operation results have no common field contract. */
|
|
22
21
|
const savedObject = z.looseObject({});
|
|
@@ -53,10 +52,6 @@ const savedProgressSchema = z.looseObject({
|
|
|
53
52
|
id: z.string(), state: z.enum(["pending", "current", "completed", "blocked"]), note: z.string().nullable().optional(),
|
|
54
53
|
})),
|
|
55
54
|
});
|
|
56
|
-
const savedAgentSchema = z.looseObject({
|
|
57
|
-
provider: z.string(), model: z.string(), repairModel: z.string(), permissionMode: z.string().optional(),
|
|
58
|
-
});
|
|
59
|
-
const savedKeyboardSchema = z.array(z.array(telegramCallbackButtonSchema.extend({ callback_data: z.string() }).loose()));
|
|
60
55
|
const savedMatrixRowSchema = proofCriterionSchema.pick({ id: true, statement: true }).extend({
|
|
61
56
|
id: z.string(), statement: z.string(), requiredEvidence: savedList, state: z.string(), detail: savedList,
|
|
62
57
|
answered: z.array(criterionEvidenceSchema.extend({ ref: z.string() }).loose()).optional(),
|
|
@@ -78,9 +73,7 @@ const STORE_COLUMN_VALUES = {
|
|
|
78
73
|
/** Read by the scope contract's `parseAcceptanceCriteria` (`scope.ts`), which owns the criterion's shape. */
|
|
79
74
|
"task_scope.acceptance_json": storedRubricSchema,
|
|
80
75
|
"operating_mode.terms_json": savedModeTermsSchema,
|
|
81
|
-
"attended_authorization.terms_json": z.looseObject({ profileJson: z.string().nullable().optional() }),
|
|
82
76
|
"approval_policy.protected_paths": savedList,
|
|
83
|
-
"fallback_config.entries_json": savedList,
|
|
84
77
|
"runner.repos": savedList,
|
|
85
78
|
"runner.agents": savedList,
|
|
86
79
|
"decision.options": z.array(savedDecisionOptionSchema),
|
|
@@ -93,15 +86,9 @@ const STORE_COLUMN_VALUES = {
|
|
|
93
86
|
"mutation.result": z.unknown(),
|
|
94
87
|
"plan_revision.changed_fields": z.array(z.string()),
|
|
95
88
|
"run_checkpoint.snapshot_json": savedProgressSchema,
|
|
96
|
-
"telegram_conversation_part.keyboard_json": savedKeyboardSchema,
|
|
97
89
|
"publication_grant.capabilities": z.array(z.enum(["push-branch", "open-pr"])),
|
|
98
90
|
"task_ref.zones": savedList,
|
|
99
91
|
"task_ref.capability_requirements": savedList,
|
|
100
|
-
"routine.touches": savedList,
|
|
101
|
-
"routine.requirements": savedList,
|
|
102
|
-
/** Read by `parseAcceptanceCriteria`, as `task_scope.acceptance_json`. */
|
|
103
|
-
"routine.acceptance_json": storedRubricSchema,
|
|
104
|
-
"tournament_terms.agents": z.array(savedAgentSchema),
|
|
105
92
|
"coordinator_proposal.payload_json": savedObject,
|
|
106
93
|
"coordinator_proposal.outcome_json": savedObject,
|
|
107
94
|
// Other proposal kinds have operation-specific fields; the action variant already has a canonical contract.
|
|
@@ -122,11 +109,11 @@ export const STORE_PROJECTIONS = ["run_tool.tools_json.fence"];
|
|
|
122
109
|
export const LEGACY_JSON_COLUMNS = [
|
|
123
110
|
"teammate_suggestion.rule_json", "teammate_suggestion.was_json", "teammate_suggestion.evidence_json",
|
|
124
111
|
"teammate_call.input_json", "teammate_tool.actions_json", "teammate_tool.rules_json", "teammate_question.options_json",
|
|
125
|
-
"teammate_event.detail_json", "task_scope.touches", "task_scope.acceptance_json",
|
|
126
|
-
"operating_mode.terms_json", "
|
|
112
|
+
"teammate_event.detail_json", "task_scope.touches", "task_scope.acceptance_json",
|
|
113
|
+
"operating_mode.terms_json", "decision.options", "run_tool.tools_json",
|
|
127
114
|
"run_tool.tools_json.fence", "mate_ask.options_json", "mutation.result", "plan_revision.changed_fields",
|
|
128
|
-
"run_checkpoint.snapshot_json", "
|
|
129
|
-
"
|
|
115
|
+
"run_checkpoint.snapshot_json", "publication_grant.capabilities",
|
|
116
|
+
"coordinator_proposal.payload_json", "coordinator_proposal.outcome_json",
|
|
130
117
|
"mate_proposal.payload_json", "mate_proposal.outcome_json",
|
|
131
118
|
];
|
|
132
119
|
/** One column's versioned envelope: `{ version: 1, value }`, built in memory around the saved bare value. */
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
* is answered with why (`value.so: must be a Toolroll button token`), and nothing is done.
|
|
6
6
|
*/
|
|
7
7
|
import { z } from "zod";
|
|
8
|
+
import { CHAT_BUTTON_TOKEN } from "./chat-content.js";
|
|
8
9
|
import { parseContract } from "./contract.js";
|
|
9
|
-
export const teamsSubmitSchema = z.object({ so: z.string().regex(
|
|
10
|
+
export const teamsSubmitSchema = z.object({ so: z.string().regex(CHAT_BUTTON_TOKEN, { error: "must be a Toolroll button token" }) });
|
|
10
11
|
/** A submit's one-time token. */
|
|
11
12
|
export function readTeamsSubmit(value) {
|
|
12
13
|
const read = parseContract(z.object({ value: teamsSubmitSchema }), { value });
|
package/dist/converse.d.ts
CHANGED
|
@@ -110,17 +110,7 @@ export type ChatTaskDraft = {
|
|
|
110
110
|
* password before it becomes a real, unapproved scope. */
|
|
111
111
|
acceptance: AcceptanceCriterion[];
|
|
112
112
|
};
|
|
113
|
-
export type
|
|
114
|
-
kind: "routine";
|
|
115
|
-
repoId: string;
|
|
116
|
-
name: string;
|
|
117
|
-
goal: string;
|
|
118
|
-
outOfScope: string | null;
|
|
119
|
-
touches: string[];
|
|
120
|
-
acceptance: AcceptanceCriterion[];
|
|
121
|
-
schedule: string;
|
|
122
|
-
};
|
|
123
|
-
export type ChatDraft = ChatTaskDraft | ChatRoutineDraft;
|
|
113
|
+
export type ChatDraft = ChatTaskDraft;
|
|
124
114
|
export type ParsedEnvelope = {
|
|
125
115
|
reply: string;
|
|
126
116
|
proposals: ChatDraft[];
|
package/dist/converse.js
CHANGED
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
import { TASK_TEXT_LIMITS } from "./task-text.js";
|
|
23
23
|
import { createHash } from "node:crypto";
|
|
24
24
|
import { hasForbiddenControls, hasDisguisedText } from "./decision.js";
|
|
25
|
-
import { ROUTINE_NAME, parseSchedule } from "./routine.js";
|
|
26
25
|
import { parseAcceptanceCriteria } from "./scope.js";
|
|
27
26
|
// ---------------------------------------------------------------- limits
|
|
28
27
|
export const WRAPPER_CAP_BYTES = 262_144; // the provider response body
|
|
@@ -285,17 +284,8 @@ function readDraft(raw) {
|
|
|
285
284
|
return null;
|
|
286
285
|
const body = raw;
|
|
287
286
|
const kind = body["kind"];
|
|
288
|
-
if (kind
|
|
289
|
-
if (!exactKeys(body, ["kind", "repoId", "title", "goal", "outOfScope", "touches", "acceptance"]))
|
|
290
|
-
return null;
|
|
291
|
-
}
|
|
292
|
-
else if (kind === "routine") {
|
|
293
|
-
if (!exactKeys(body, ["kind", "repoId", "name", "goal", "outOfScope", "touches", "schedule", "acceptance"]))
|
|
294
|
-
return null;
|
|
295
|
-
}
|
|
296
|
-
else {
|
|
287
|
+
if (kind !== "task" || !exactKeys(body, ["kind", "repoId", "title", "goal", "outOfScope", "touches", "acceptance"]))
|
|
297
288
|
return null;
|
|
298
|
-
}
|
|
299
289
|
const repoId = body["repoId"];
|
|
300
290
|
const goal = body["goal"];
|
|
301
291
|
const outOfScope = body["outOfScope"];
|
|
@@ -318,28 +308,10 @@ function readDraft(raw) {
|
|
|
318
308
|
if (acceptanceParse.problems.length > 0 || acceptanceParse.criteria.length === 0)
|
|
319
309
|
return null;
|
|
320
310
|
const acceptance = acceptanceParse.criteria;
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
if (typeof title !== "string" || title.trim() === "" || !honest(title, 200, 800))
|
|
324
|
-
return null;
|
|
325
|
-
return { kind, repoId, title, goal, outOfScope: outOfScope, touches: touches, acceptance };
|
|
326
|
-
}
|
|
327
|
-
const name = body["name"];
|
|
328
|
-
const schedule = body["schedule"];
|
|
329
|
-
if (typeof name !== "string" || !ROUTINE_NAME.test(name))
|
|
330
|
-
return null;
|
|
331
|
-
if (typeof schedule !== "string" || parseSchedule(schedule) === null)
|
|
311
|
+
const title = body["title"];
|
|
312
|
+
if (typeof title !== "string" || title.trim() === "" || !honest(title, 200, 800))
|
|
332
313
|
return null;
|
|
333
|
-
return {
|
|
334
|
-
kind,
|
|
335
|
-
repoId,
|
|
336
|
-
name,
|
|
337
|
-
goal,
|
|
338
|
-
outOfScope: outOfScope,
|
|
339
|
-
touches: touches,
|
|
340
|
-
acceptance,
|
|
341
|
-
schedule,
|
|
342
|
-
};
|
|
314
|
+
return { kind, repoId, title, goal, outOfScope: outOfScope, touches: touches, acceptance };
|
|
343
315
|
}
|
|
344
316
|
/**
|
|
345
317
|
* The assistant envelope: exactly {chatEnvelope: 1, reply, proposals}.
|
|
@@ -716,14 +688,12 @@ export function buildDataDocument(snapshot, budgetBytes = DATA_DOCUMENT_BUDGET_B
|
|
|
716
688
|
})),
|
|
717
689
|
decisions: snapshot.decisions.map(one => ({ repo: id(one.repoIndex), id: one.id, question: one.question, optionLabels: one.optionLabels })),
|
|
718
690
|
incidents: snapshot.incidents.map(one => ({ repo: id(one.repoIndex), kind: one.kind, ageHours: one.ageHours })),
|
|
719
|
-
routines: snapshot.routines.map(one => ({ repo: id(one.repoIndex), name: one.name, schedule: one.schedule, status: one.status, lastFire: one.lastFire })),
|
|
720
691
|
publications: snapshot.publications.map(one => ({ repo: id(one.repoIndex), pr: one.pr, checkState: one.checkState })),
|
|
721
692
|
};
|
|
722
693
|
const notShown = {
|
|
723
694
|
tasks: snapshot.tasksSaturated ? "more exist" : "",
|
|
724
695
|
decisions: snapshot.decisionsSaturated ? "more exist" : "",
|
|
725
696
|
incidents: snapshot.incidentsSaturated ? "more exist" : "",
|
|
726
|
-
routines: snapshot.routinesSaturated ? "more exist" : "",
|
|
727
697
|
publications: snapshot.publicationsSaturated ? "more exist" : "",
|
|
728
698
|
};
|
|
729
699
|
let shed = 0;
|
|
@@ -756,10 +726,8 @@ const SYSTEM_RULES = [
|
|
|
756
726
|
"Never recommend which option a pending decision should take.",
|
|
757
727
|
"Answer with EXACTLY one JSON document and nothing else:",
|
|
758
728
|
'{"chatEnvelope": 1, "reply": "<markdown-free plain text>", "proposals": []}',
|
|
759
|
-
"A proposal is
|
|
760
|
-
'{"kind":"task","repoId":"r1","title":"…","goal":"…","outOfScope":null,"touches":[],"acceptance":[…]}',
|
|
761
|
-
"or",
|
|
762
|
-
'{"kind":"routine","repoId":"r1","name":"lowercase-dashes","goal":"…","outOfScope":null,"touches":[],"schedule":"daily:03:30[@Zone], weekly:<0-6>:<HH:MM>[@Zone], or every:<minutes>","acceptance":[…]}.',
|
|
729
|
+
"A proposal is",
|
|
730
|
+
'{"kind":"task","repoId":"r1","title":"…","goal":"…","outOfScope":null,"touches":[],"acceptance":[…]}.',
|
|
763
731
|
'acceptance is REQUIRED and non-empty: [{"id":"c1","statement":"<one testable outcome>","evidence":["check"|"screenshot"|"changed-path"|"manual-review",…],"how":"<optional guidance, or null>"}]. A proposal with no acceptance criterion is dropped, whole.',
|
|
764
732
|
"At most 3 proposals. repoId must be one of the ids in the data document.",
|
|
765
733
|
].join("\n");
|
package/dist/coordinator.d.ts
CHANGED
package/dist/coordinator.js
CHANGED
|
@@ -300,8 +300,6 @@ export function statusFor(store, who, now) {
|
|
|
300
300
|
const incidents = one(`SELECT COUNT(*) AS n FROM incident JOIN run ON run.id = incident.run
|
|
301
301
|
JOIN task_ref ON task_ref.id = run.task_ref AND task_ref.backend = 'built-in'
|
|
302
302
|
WHERE task_ref.repo IN (${sql}) AND incident.resolved_at IS NULL`);
|
|
303
|
-
const picks = one(`SELECT COUNT(*) AS n FROM contest JOIN task_ref ON task_ref.id = contest.task_ref AND task_ref.backend = 'built-in'
|
|
304
|
-
WHERE task_ref.repo IN (${sql}) AND contest.state = 'pick-wait'`);
|
|
305
303
|
const builtToday = one(`SELECT COUNT(*) AS n FROM run JOIN task_ref ON task_ref.id = run.task_ref AND task_ref.backend = 'built-in'
|
|
306
304
|
WHERE task_ref.repo IN (${sql}) AND run.outcome = 'built' AND run.finished_at > ?`, [dayAgo]);
|
|
307
305
|
const failedToday = one(`SELECT COUNT(*) AS n FROM run JOIN task_ref ON task_ref.id = run.task_ref AND task_ref.backend = 'built-in'
|
|
@@ -315,8 +313,8 @@ export function statusFor(store, who, now) {
|
|
|
315
313
|
.all(...args)
|
|
316
314
|
.map(row => ({ repo: String(row["repo"]), queued: Number(row["queued"]), running: Number(row["running"]) }));
|
|
317
315
|
return {
|
|
318
|
-
waitsOnYou: unsealed + questions + incidents
|
|
319
|
-
waits: { approvals: unsealed, questions, incidents
|
|
316
|
+
waitsOnYou: unsealed + questions + incidents,
|
|
317
|
+
waits: { approvals: unsealed, questions, incidents },
|
|
320
318
|
running,
|
|
321
319
|
builtToday,
|
|
322
320
|
failedToday,
|
|
@@ -432,7 +430,7 @@ export function taskDetailFor(store, who, taskId, evidenceRoot, now = new Date()
|
|
|
432
430
|
scope: {
|
|
433
431
|
sealed: store.scopeSealed(taskId),
|
|
434
432
|
goal: scope?.goal ?? null,
|
|
435
|
-
// The scope in the console's own words
|
|
433
|
+
// The scope in the console's own words.
|
|
436
434
|
words: scope === null ? [] : describeScope(scope),
|
|
437
435
|
},
|
|
438
436
|
waits,
|