toolroll 0.9.91 → 0.9.92
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 +22 -0
- package/dist/approval-authority.d.ts +9 -1
- package/dist/approval-authority.js +15 -2
- package/dist/build-review.js +2 -0
- package/dist/chat-actions.d.ts +11 -3
- package/dist/chat-actions.js +47 -2
- package/dist/chat-decide.js +2 -0
- package/dist/chat-review.d.ts +2 -1
- package/dist/chat-review.js +2 -2
- package/dist/contracts/chat-actions.d.ts +10 -0
- package/dist/contracts/chat-actions.js +4 -0
- package/dist/contracts/console-api.d.ts +1 -0
- package/dist/contracts/console-api.js +3 -0
- package/dist/contracts/route-results.d.ts +121 -0
- package/dist/contracts/route-results.js +71 -0
- package/dist/contracts/route.d.ts +343 -5
- package/dist/contracts/route.js +36 -7
- package/dist/contracts/store-json.d.ts +2 -0
- package/dist/dispose.js +6 -0
- package/dist/flow-engine.js +1 -1
- package/dist/flow-pull-request.js +1 -1
- package/dist/lead-doors.js +4 -2
- package/dist/lead-tools.js +10 -2
- package/dist/local-owner.d.ts +1 -1
- package/dist/local-owner.js +11 -0
- package/dist/memory-cli.d.ts +3 -0
- package/dist/memory-cli.js +3 -3
- package/dist/memory-pass.js +5 -1
- package/dist/model-choices.d.ts +7 -3
- package/dist/model-choices.js +26 -11
- package/dist/models-cli.d.ts +205 -0
- package/dist/models-cli.js +143 -4
- package/dist/models-ui.d.ts +57 -0
- package/dist/models-ui.js +44 -1
- package/dist/operate-remote-arguments.js +4 -4
- package/dist/operate-remote.js +1 -1
- package/dist/operate.js +53 -5
- package/dist/phase-routing.d.ts +82 -2
- package/dist/phase-routing.js +132 -18
- package/dist/project-delete.d.ts +4 -0
- package/dist/project-delete.js +12 -4
- package/dist/project-knowledge.d.ts +6 -6
- package/dist/project-memory.d.ts +8 -0
- package/dist/project-memory.js +20 -1
- package/dist/pull-request-flow.js +1 -1
- package/dist/release-auto.js +12 -3
- package/dist/result-actions.d.ts +4 -0
- package/dist/result-actions.js +3 -0
- package/dist/route-hooks.d.ts +54 -0
- package/dist/route-hooks.js +179 -0
- package/dist/route-results.d.ts +70 -0
- package/dist/route-results.js +340 -0
- package/dist/route-rules.d.ts +324 -0
- package/dist/route-rules.js +781 -0
- package/dist/route-savings.d.ts +136 -0
- package/dist/route-savings.js +193 -0
- package/dist/route-store.d.ts +300 -0
- package/dist/route-store.js +598 -0
- package/dist/scope.d.ts +3 -1
- package/dist/scope.js +4 -1
- package/dist/server/render-chat.js +2 -2
- package/dist/server/render-tasks.d.ts +7 -0
- package/dist/server/render-tasks.js +13 -0
- package/dist/server/route-table.js +12 -0
- package/dist/server/settings.d.ts +2 -1
- package/dist/server/settings.js +87 -1
- package/dist/server/task-views.js +6 -0
- package/dist/server/tasks.js +3 -0
- package/dist/settings-proofs.js +2 -0
- package/dist/setup-guide.d.ts +2 -2
- package/dist/spend-ui.d.ts +11 -0
- package/dist/spend-ui.js +49 -2
- package/dist/store.d.ts +38 -2
- package/dist/store.js +320 -35
- package/dist/surface.js +16 -4
- package/dist/task-outcome-cli.js +5 -2
- package/dist/toolroll-update.js +3 -2
- package/package.json +1 -1
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { z } from "zod";
|
|
14
14
|
import { type ContractResult } from "./contract.js";
|
|
15
|
+
import { type Selection } from "./route-results.js";
|
|
15
16
|
/** The phases a route has a leg for, in the order its legs run. */
|
|
16
17
|
export declare const ROUTE_PHASES: readonly ["plan", "build", "repair", "review"];
|
|
17
18
|
/** provider.ts's provider ids, restated (provider.ts sits above phase-routing.ts in the module graph) and pinned to
|
|
@@ -22,8 +23,15 @@ export declare const ROUTE_PROVIDERS: readonly ["claude", "codex", "openrouter",
|
|
|
22
23
|
export declare const MODEL_ID_SHAPE: RegExp;
|
|
23
24
|
export declare const RISKS: readonly ["routine", "elevated", "high"];
|
|
24
25
|
export declare const TASK_SIZE_WORDS: readonly ["small", "medium", "large"];
|
|
25
|
-
/** The route version this code seals
|
|
26
|
-
|
|
26
|
+
/** The newest route version this code seals (docs/plans/results-routing.md, slice 2): version 3 adds the build leg's
|
|
27
|
+
* sealed `selection`, and is sealed only for a build leg that carries one (an earned rule's). Every other route still
|
|
28
|
+
* seals as version 2 (PLAIN_ROUTE_VERSION), so its bytes and digest are what they always were; version 1 (before
|
|
29
|
+
* sizing) still reads. */
|
|
30
|
+
export declare const ROUTE_VERSION = 3;
|
|
31
|
+
/** The version a route with no selection seals as. */
|
|
32
|
+
export declare const PLAIN_ROUTE_VERSION = 2;
|
|
33
|
+
/** The newest route version this code reads. */
|
|
34
|
+
export declare const READ_ROUTE_VERSION = 3;
|
|
27
35
|
/** How big a change the task is, as it was sized (by the classifier, the description, or a person). */
|
|
28
36
|
export declare const taskSizingSchema: z.ZodObject<{
|
|
29
37
|
size: z.ZodEnum<{
|
|
@@ -114,6 +122,73 @@ export declare const routeLegSchema: z.ZodObject<{
|
|
|
114
122
|
reasons: z.ZodArray<z.ZodString>;
|
|
115
123
|
problem: z.ZodNullable<z.ZodString>;
|
|
116
124
|
}, z.core.$strict>;
|
|
125
|
+
/** One leg of a version 3 route: a version 2 leg, and the build leg may say how it was selected. */
|
|
126
|
+
export declare const routeLegV3Schema: z.ZodObject<{
|
|
127
|
+
phase: z.ZodEnum<{
|
|
128
|
+
build: "build";
|
|
129
|
+
plan: "plan";
|
|
130
|
+
repair: "repair";
|
|
131
|
+
review: "review";
|
|
132
|
+
}>;
|
|
133
|
+
provider: z.ZodEnum<{
|
|
134
|
+
claude: "claude";
|
|
135
|
+
cline: "cline";
|
|
136
|
+
codex: "codex";
|
|
137
|
+
cursor: "cursor";
|
|
138
|
+
gemini: "gemini";
|
|
139
|
+
goose: "goose";
|
|
140
|
+
opencode: "opencode";
|
|
141
|
+
openrouter: "openrouter";
|
|
142
|
+
qwen: "qwen";
|
|
143
|
+
}>;
|
|
144
|
+
model: z.ZodString;
|
|
145
|
+
tier: z.ZodEnum<{
|
|
146
|
+
light: "light";
|
|
147
|
+
routine: "routine";
|
|
148
|
+
strong: "strong";
|
|
149
|
+
}>;
|
|
150
|
+
chosen: z.ZodEnum<{
|
|
151
|
+
override: "override";
|
|
152
|
+
pinned: "pinned";
|
|
153
|
+
recommended: "recommended";
|
|
154
|
+
}>;
|
|
155
|
+
recommended: z.ZodObject<{
|
|
156
|
+
provider: z.ZodEnum<{
|
|
157
|
+
claude: "claude";
|
|
158
|
+
cline: "cline";
|
|
159
|
+
codex: "codex";
|
|
160
|
+
cursor: "cursor";
|
|
161
|
+
gemini: "gemini";
|
|
162
|
+
goose: "goose";
|
|
163
|
+
opencode: "opencode";
|
|
164
|
+
openrouter: "openrouter";
|
|
165
|
+
qwen: "qwen";
|
|
166
|
+
}>;
|
|
167
|
+
model: z.ZodString;
|
|
168
|
+
tier: z.ZodEnum<{
|
|
169
|
+
light: "light";
|
|
170
|
+
routine: "routine";
|
|
171
|
+
strong: "strong";
|
|
172
|
+
}>;
|
|
173
|
+
}, z.core.$strict>;
|
|
174
|
+
reasons: z.ZodArray<z.ZodString>;
|
|
175
|
+
problem: z.ZodNullable<z.ZodString>;
|
|
176
|
+
selection: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
177
|
+
kind: z.ZodLiteral<"rule">;
|
|
178
|
+
rule: z.ZodNumber;
|
|
179
|
+
ruleGeneration: z.ZodNumber;
|
|
180
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
181
|
+
kind: z.ZodLiteral<"trial">;
|
|
182
|
+
rule: z.ZodNumber;
|
|
183
|
+
reservation: z.ZodNumber;
|
|
184
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
185
|
+
kind: z.ZodEnum<{
|
|
186
|
+
configured: "configured";
|
|
187
|
+
override: "override";
|
|
188
|
+
pin: "pin";
|
|
189
|
+
}>;
|
|
190
|
+
}, z.core.$strict>], "kind">>;
|
|
191
|
+
}, z.core.$strict>;
|
|
117
192
|
export declare const sealedRouteV1Schema: z.ZodObject<{
|
|
118
193
|
version: z.ZodLiteral<1>;
|
|
119
194
|
risk: z.ZodEnum<{
|
|
@@ -328,7 +403,137 @@ export declare const sealedRouteV2Schema: z.ZodObject<{
|
|
|
328
403
|
reason: z.ZodString;
|
|
329
404
|
}, z.core.$strict>>;
|
|
330
405
|
}, z.core.$strict>;
|
|
331
|
-
|
|
406
|
+
export declare const sealedRouteV3Schema: z.ZodObject<{
|
|
407
|
+
version: z.ZodLiteral<3>;
|
|
408
|
+
risk: z.ZodEnum<{
|
|
409
|
+
elevated: "elevated";
|
|
410
|
+
high: "high";
|
|
411
|
+
routine: "routine";
|
|
412
|
+
}>;
|
|
413
|
+
qualityMode: z.ZodEnum<{
|
|
414
|
+
default: "default";
|
|
415
|
+
strict: "strict";
|
|
416
|
+
}>;
|
|
417
|
+
publication: z.ZodEnum<{
|
|
418
|
+
automerge: "automerge";
|
|
419
|
+
none: "none";
|
|
420
|
+
notify: "notify";
|
|
421
|
+
}>;
|
|
422
|
+
evidence: z.ZodArray<z.ZodEnum<{
|
|
423
|
+
"changed-path": "changed-path";
|
|
424
|
+
check: "check";
|
|
425
|
+
"manual-review": "manual-review";
|
|
426
|
+
screenshot: "screenshot";
|
|
427
|
+
}>>;
|
|
428
|
+
posture: z.ZodEnum<{
|
|
429
|
+
economy: "economy";
|
|
430
|
+
strong: "strong";
|
|
431
|
+
}>;
|
|
432
|
+
demands: z.ZodArray<z.ZodString>;
|
|
433
|
+
legs: z.ZodArray<z.ZodObject<{
|
|
434
|
+
phase: z.ZodEnum<{
|
|
435
|
+
build: "build";
|
|
436
|
+
plan: "plan";
|
|
437
|
+
repair: "repair";
|
|
438
|
+
review: "review";
|
|
439
|
+
}>;
|
|
440
|
+
provider: z.ZodEnum<{
|
|
441
|
+
claude: "claude";
|
|
442
|
+
cline: "cline";
|
|
443
|
+
codex: "codex";
|
|
444
|
+
cursor: "cursor";
|
|
445
|
+
gemini: "gemini";
|
|
446
|
+
goose: "goose";
|
|
447
|
+
opencode: "opencode";
|
|
448
|
+
openrouter: "openrouter";
|
|
449
|
+
qwen: "qwen";
|
|
450
|
+
}>;
|
|
451
|
+
model: z.ZodString;
|
|
452
|
+
tier: z.ZodEnum<{
|
|
453
|
+
light: "light";
|
|
454
|
+
routine: "routine";
|
|
455
|
+
strong: "strong";
|
|
456
|
+
}>;
|
|
457
|
+
chosen: z.ZodEnum<{
|
|
458
|
+
override: "override";
|
|
459
|
+
pinned: "pinned";
|
|
460
|
+
recommended: "recommended";
|
|
461
|
+
}>;
|
|
462
|
+
recommended: z.ZodObject<{
|
|
463
|
+
provider: z.ZodEnum<{
|
|
464
|
+
claude: "claude";
|
|
465
|
+
cline: "cline";
|
|
466
|
+
codex: "codex";
|
|
467
|
+
cursor: "cursor";
|
|
468
|
+
gemini: "gemini";
|
|
469
|
+
goose: "goose";
|
|
470
|
+
opencode: "opencode";
|
|
471
|
+
openrouter: "openrouter";
|
|
472
|
+
qwen: "qwen";
|
|
473
|
+
}>;
|
|
474
|
+
model: z.ZodString;
|
|
475
|
+
tier: z.ZodEnum<{
|
|
476
|
+
light: "light";
|
|
477
|
+
routine: "routine";
|
|
478
|
+
strong: "strong";
|
|
479
|
+
}>;
|
|
480
|
+
}, z.core.$strict>;
|
|
481
|
+
reasons: z.ZodArray<z.ZodString>;
|
|
482
|
+
problem: z.ZodNullable<z.ZodString>;
|
|
483
|
+
selection: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
484
|
+
kind: z.ZodLiteral<"rule">;
|
|
485
|
+
rule: z.ZodNumber;
|
|
486
|
+
ruleGeneration: z.ZodNumber;
|
|
487
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
488
|
+
kind: z.ZodLiteral<"trial">;
|
|
489
|
+
rule: z.ZodNumber;
|
|
490
|
+
reservation: z.ZodNumber;
|
|
491
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
492
|
+
kind: z.ZodEnum<{
|
|
493
|
+
configured: "configured";
|
|
494
|
+
override: "override";
|
|
495
|
+
pin: "pin";
|
|
496
|
+
}>;
|
|
497
|
+
}, z.core.$strict>], "kind">>;
|
|
498
|
+
}, z.core.$strict>>;
|
|
499
|
+
overrides: z.ZodArray<z.ZodObject<{
|
|
500
|
+
phase: z.ZodEnum<{
|
|
501
|
+
build: "build";
|
|
502
|
+
plan: "plan";
|
|
503
|
+
repair: "repair";
|
|
504
|
+
review: "review";
|
|
505
|
+
}>;
|
|
506
|
+
provider: z.ZodEnum<{
|
|
507
|
+
claude: "claude";
|
|
508
|
+
cline: "cline";
|
|
509
|
+
codex: "codex";
|
|
510
|
+
cursor: "cursor";
|
|
511
|
+
gemini: "gemini";
|
|
512
|
+
goose: "goose";
|
|
513
|
+
opencode: "opencode";
|
|
514
|
+
openrouter: "openrouter";
|
|
515
|
+
qwen: "qwen";
|
|
516
|
+
}>;
|
|
517
|
+
model: z.ZodString;
|
|
518
|
+
by: z.ZodString;
|
|
519
|
+
at: z.ZodString;
|
|
520
|
+
}, z.core.$strict>>;
|
|
521
|
+
size: z.ZodNullable<z.ZodObject<{
|
|
522
|
+
size: z.ZodEnum<{
|
|
523
|
+
large: "large";
|
|
524
|
+
medium: "medium";
|
|
525
|
+
small: "small";
|
|
526
|
+
}>;
|
|
527
|
+
risky: z.ZodBoolean;
|
|
528
|
+
source: z.ZodEnum<{
|
|
529
|
+
classifier: "classifier";
|
|
530
|
+
heuristic: "heuristic";
|
|
531
|
+
person: "person";
|
|
532
|
+
}>;
|
|
533
|
+
reason: z.ZodString;
|
|
534
|
+
}, z.core.$strict>>;
|
|
535
|
+
}, z.core.$strict>;
|
|
536
|
+
/** A sealed route as saved, in any version. */
|
|
332
537
|
export declare const sealedRouteSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
333
538
|
version: z.ZodLiteral<1>;
|
|
334
539
|
risk: z.ZodEnum<{
|
|
@@ -541,15 +746,148 @@ export declare const sealedRouteSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
541
746
|
}>;
|
|
542
747
|
reason: z.ZodString;
|
|
543
748
|
}, z.core.$strict>>;
|
|
749
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
750
|
+
version: z.ZodLiteral<3>;
|
|
751
|
+
risk: z.ZodEnum<{
|
|
752
|
+
elevated: "elevated";
|
|
753
|
+
high: "high";
|
|
754
|
+
routine: "routine";
|
|
755
|
+
}>;
|
|
756
|
+
qualityMode: z.ZodEnum<{
|
|
757
|
+
default: "default";
|
|
758
|
+
strict: "strict";
|
|
759
|
+
}>;
|
|
760
|
+
publication: z.ZodEnum<{
|
|
761
|
+
automerge: "automerge";
|
|
762
|
+
none: "none";
|
|
763
|
+
notify: "notify";
|
|
764
|
+
}>;
|
|
765
|
+
evidence: z.ZodArray<z.ZodEnum<{
|
|
766
|
+
"changed-path": "changed-path";
|
|
767
|
+
check: "check";
|
|
768
|
+
"manual-review": "manual-review";
|
|
769
|
+
screenshot: "screenshot";
|
|
770
|
+
}>>;
|
|
771
|
+
posture: z.ZodEnum<{
|
|
772
|
+
economy: "economy";
|
|
773
|
+
strong: "strong";
|
|
774
|
+
}>;
|
|
775
|
+
demands: z.ZodArray<z.ZodString>;
|
|
776
|
+
legs: z.ZodArray<z.ZodObject<{
|
|
777
|
+
phase: z.ZodEnum<{
|
|
778
|
+
build: "build";
|
|
779
|
+
plan: "plan";
|
|
780
|
+
repair: "repair";
|
|
781
|
+
review: "review";
|
|
782
|
+
}>;
|
|
783
|
+
provider: z.ZodEnum<{
|
|
784
|
+
claude: "claude";
|
|
785
|
+
cline: "cline";
|
|
786
|
+
codex: "codex";
|
|
787
|
+
cursor: "cursor";
|
|
788
|
+
gemini: "gemini";
|
|
789
|
+
goose: "goose";
|
|
790
|
+
opencode: "opencode";
|
|
791
|
+
openrouter: "openrouter";
|
|
792
|
+
qwen: "qwen";
|
|
793
|
+
}>;
|
|
794
|
+
model: z.ZodString;
|
|
795
|
+
tier: z.ZodEnum<{
|
|
796
|
+
light: "light";
|
|
797
|
+
routine: "routine";
|
|
798
|
+
strong: "strong";
|
|
799
|
+
}>;
|
|
800
|
+
chosen: z.ZodEnum<{
|
|
801
|
+
override: "override";
|
|
802
|
+
pinned: "pinned";
|
|
803
|
+
recommended: "recommended";
|
|
804
|
+
}>;
|
|
805
|
+
recommended: z.ZodObject<{
|
|
806
|
+
provider: z.ZodEnum<{
|
|
807
|
+
claude: "claude";
|
|
808
|
+
cline: "cline";
|
|
809
|
+
codex: "codex";
|
|
810
|
+
cursor: "cursor";
|
|
811
|
+
gemini: "gemini";
|
|
812
|
+
goose: "goose";
|
|
813
|
+
opencode: "opencode";
|
|
814
|
+
openrouter: "openrouter";
|
|
815
|
+
qwen: "qwen";
|
|
816
|
+
}>;
|
|
817
|
+
model: z.ZodString;
|
|
818
|
+
tier: z.ZodEnum<{
|
|
819
|
+
light: "light";
|
|
820
|
+
routine: "routine";
|
|
821
|
+
strong: "strong";
|
|
822
|
+
}>;
|
|
823
|
+
}, z.core.$strict>;
|
|
824
|
+
reasons: z.ZodArray<z.ZodString>;
|
|
825
|
+
problem: z.ZodNullable<z.ZodString>;
|
|
826
|
+
selection: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
827
|
+
kind: z.ZodLiteral<"rule">;
|
|
828
|
+
rule: z.ZodNumber;
|
|
829
|
+
ruleGeneration: z.ZodNumber;
|
|
830
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
831
|
+
kind: z.ZodLiteral<"trial">;
|
|
832
|
+
rule: z.ZodNumber;
|
|
833
|
+
reservation: z.ZodNumber;
|
|
834
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
835
|
+
kind: z.ZodEnum<{
|
|
836
|
+
configured: "configured";
|
|
837
|
+
override: "override";
|
|
838
|
+
pin: "pin";
|
|
839
|
+
}>;
|
|
840
|
+
}, z.core.$strict>], "kind">>;
|
|
841
|
+
}, z.core.$strict>>;
|
|
842
|
+
overrides: z.ZodArray<z.ZodObject<{
|
|
843
|
+
phase: z.ZodEnum<{
|
|
844
|
+
build: "build";
|
|
845
|
+
plan: "plan";
|
|
846
|
+
repair: "repair";
|
|
847
|
+
review: "review";
|
|
848
|
+
}>;
|
|
849
|
+
provider: z.ZodEnum<{
|
|
850
|
+
claude: "claude";
|
|
851
|
+
cline: "cline";
|
|
852
|
+
codex: "codex";
|
|
853
|
+
cursor: "cursor";
|
|
854
|
+
gemini: "gemini";
|
|
855
|
+
goose: "goose";
|
|
856
|
+
opencode: "opencode";
|
|
857
|
+
openrouter: "openrouter";
|
|
858
|
+
qwen: "qwen";
|
|
859
|
+
}>;
|
|
860
|
+
model: z.ZodString;
|
|
861
|
+
by: z.ZodString;
|
|
862
|
+
at: z.ZodString;
|
|
863
|
+
}, z.core.$strict>>;
|
|
864
|
+
size: z.ZodNullable<z.ZodObject<{
|
|
865
|
+
size: z.ZodEnum<{
|
|
866
|
+
large: "large";
|
|
867
|
+
medium: "medium";
|
|
868
|
+
small: "small";
|
|
869
|
+
}>;
|
|
870
|
+
risky: z.ZodBoolean;
|
|
871
|
+
source: z.ZodEnum<{
|
|
872
|
+
classifier: "classifier";
|
|
873
|
+
heuristic: "heuristic";
|
|
874
|
+
person: "person";
|
|
875
|
+
}>;
|
|
876
|
+
reason: z.ZodString;
|
|
877
|
+
}, z.core.$strict>>;
|
|
544
878
|
}, z.core.$strict>], "version">;
|
|
545
879
|
export type SealedRoute = z.infer<typeof sealedRouteSchema>;
|
|
546
880
|
export type RouteVersion = SealedRoute["version"];
|
|
547
|
-
|
|
881
|
+
/** A leg as every reader returns it: only a version 3 build leg can carry a selection. */
|
|
882
|
+
export type RouteLeg = z.infer<typeof routeLegSchema> & {
|
|
883
|
+
selection?: Selection | undefined;
|
|
884
|
+
};
|
|
548
885
|
export type RouteOverride = z.infer<typeof routeOverrideSchema>;
|
|
549
886
|
export type TaskSizing = z.infer<typeof taskSizingSchema>;
|
|
550
887
|
/** A route as every reader returns it: a version 1 route reads with no size. */
|
|
551
|
-
export type PhaseRoute = Omit<z.infer<typeof sealedRouteV2Schema>, "version"> & {
|
|
888
|
+
export type PhaseRoute = Omit<z.infer<typeof sealedRouteV2Schema>, "version" | "legs"> & {
|
|
552
889
|
version: RouteVersion;
|
|
890
|
+
legs: RouteLeg[];
|
|
553
891
|
};
|
|
554
892
|
/** The posture legs actually run under: strong only when a leg runs a configured strong agent as recommended. */
|
|
555
893
|
export declare function postureOf(legs: readonly Pick<RouteLeg, "chosen" | "tier">[]): "economy" | "strong";
|
package/dist/contracts/route.js
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { z } from "zod";
|
|
14
14
|
import { EVIDENCE_KINDS } from "./acceptance-terms.js";
|
|
15
15
|
import { limited, parseContract, versioned } from "./contract.js";
|
|
16
|
+
import { selectionSchema } from "./route-results.js";
|
|
16
17
|
/** The phases a route has a leg for, in the order its legs run. */
|
|
17
18
|
export const ROUTE_PHASES = ["plan", "build", "repair", "review"];
|
|
18
19
|
/** provider.ts's provider ids, restated (provider.ts sits above phase-routing.ts in the module graph) and pinned to
|
|
@@ -23,8 +24,15 @@ export const ROUTE_PROVIDERS = ["claude", "codex", "openrouter", "gemini", "open
|
|
|
23
24
|
export const MODEL_ID_SHAPE = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/;
|
|
24
25
|
export const RISKS = ["routine", "elevated", "high"];
|
|
25
26
|
export const TASK_SIZE_WORDS = ["small", "medium", "large"];
|
|
26
|
-
/** The route version this code seals
|
|
27
|
-
|
|
27
|
+
/** The newest route version this code seals (docs/plans/results-routing.md, slice 2): version 3 adds the build leg's
|
|
28
|
+
* sealed `selection`, and is sealed only for a build leg that carries one (an earned rule's). Every other route still
|
|
29
|
+
* seals as version 2 (PLAIN_ROUTE_VERSION), so its bytes and digest are what they always were; version 1 (before
|
|
30
|
+
* sizing) still reads. */
|
|
31
|
+
export const ROUTE_VERSION = 3;
|
|
32
|
+
/** The version a route with no selection seals as. */
|
|
33
|
+
export const PLAIN_ROUTE_VERSION = 2;
|
|
34
|
+
/** The newest route version this code reads. */
|
|
35
|
+
export const READ_ROUTE_VERSION = ROUTE_VERSION;
|
|
28
36
|
const phase = z.enum(ROUTE_PHASES);
|
|
29
37
|
const provider = z.enum(ROUTE_PROVIDERS);
|
|
30
38
|
const model = z.string().regex(MODEL_ID_SHAPE, { error: "must be an exact model id: letters, digits and . _ : / -, not starting with a dash" });
|
|
@@ -53,6 +61,8 @@ function legSchema(tiers) {
|
|
|
53
61
|
}
|
|
54
62
|
/** One leg of a version 2 route: the light tier exists. */
|
|
55
63
|
export const routeLegSchema = legSchema(["light", "routine", "strong"]);
|
|
64
|
+
/** One leg of a version 3 route: a version 2 leg, and the build leg may say how it was selected. */
|
|
65
|
+
export const routeLegV3Schema = routeLegSchema.extend({ selection: selectionSchema.optional() });
|
|
56
66
|
const terms = {
|
|
57
67
|
risk: z.enum(RISKS),
|
|
58
68
|
qualityMode: z.enum(["default", "strict"]),
|
|
@@ -66,14 +76,20 @@ export const sealedRouteV1Schema = versioned(1, {
|
|
|
66
76
|
legs: z.array(legSchema(["routine", "strong"])).length(ROUTE_PHASES.length),
|
|
67
77
|
overrides: z.array(routeOverrideSchema),
|
|
68
78
|
});
|
|
69
|
-
export const sealedRouteV2Schema = versioned(
|
|
79
|
+
export const sealedRouteV2Schema = versioned(PLAIN_ROUTE_VERSION, {
|
|
70
80
|
...terms,
|
|
71
81
|
legs: z.array(routeLegSchema).length(ROUTE_PHASES.length),
|
|
72
82
|
overrides: z.array(routeOverrideSchema),
|
|
73
83
|
size: taskSizingSchema.nullable(),
|
|
74
84
|
});
|
|
75
|
-
|
|
76
|
-
|
|
85
|
+
export const sealedRouteV3Schema = versioned(READ_ROUTE_VERSION, {
|
|
86
|
+
...terms,
|
|
87
|
+
legs: z.array(routeLegV3Schema).length(ROUTE_PHASES.length),
|
|
88
|
+
overrides: z.array(routeOverrideSchema),
|
|
89
|
+
size: taskSizingSchema.nullable(),
|
|
90
|
+
});
|
|
91
|
+
/** A sealed route as saved, in any version. */
|
|
92
|
+
export const sealedRouteSchema = z.discriminatedUnion("version", [sealedRouteV1Schema, sealedRouteV2Schema, sealedRouteV3Schema]);
|
|
77
93
|
/** The posture legs actually run under: strong only when a leg runs a configured strong agent as recommended. */
|
|
78
94
|
export function postureOf(legs) {
|
|
79
95
|
return legs.some(leg => leg.chosen === "recommended" && leg.tier === "strong") ? "strong" : "economy";
|
|
@@ -94,14 +110,27 @@ export function readRouteOverrides(input) {
|
|
|
94
110
|
/** Read a sealed route: either version as itself, every leg, override and the size proved, nothing unknown. */
|
|
95
111
|
export function readSealedRoute(input) {
|
|
96
112
|
const version = typeof input === "object" && input !== null ? input["version"] : undefined;
|
|
97
|
-
if (typeof version === "number" && Number.isInteger(version) && version >
|
|
98
|
-
return { ok: false, issues: [{ path: "version", kind: "newer-version", line: `version: made by a newer Toolroll (version ${version}; this one reads up to ${
|
|
113
|
+
if (typeof version === "number" && Number.isInteger(version) && version > READ_ROUTE_VERSION) {
|
|
114
|
+
return { ok: false, issues: [{ path: "version", kind: "newer-version", line: `version: made by a newer Toolroll (version ${version}; this one reads up to ${READ_ROUTE_VERSION})` }] };
|
|
99
115
|
}
|
|
100
116
|
const parsed = parseContract(sealedRouteSchema, input);
|
|
101
117
|
if (!parsed.ok)
|
|
102
118
|
return parsed;
|
|
103
119
|
const route = parsed.value;
|
|
104
120
|
const issues = route.legs.flatMap((leg, index) => (leg.phase === ROUTE_PHASES[index] ? [] : [issue(`legs[${index}].phase`, `must be ${JSON.stringify(ROUTE_PHASES[index])} (legs run plan, build, repair, review)`)]));
|
|
121
|
+
// Version 3: only the build leg says how it was selected, and what it says agrees with how it was chosen.
|
|
122
|
+
route.legs.forEach((leg, index) => {
|
|
123
|
+
const selection = leg.selection;
|
|
124
|
+
if (selection === undefined)
|
|
125
|
+
return;
|
|
126
|
+
if (leg.phase !== "build") {
|
|
127
|
+
issues.push(issue(`legs[${index}].selection`, "only the build leg carries a selection"));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const chosen = selection.kind === "override" ? "override" : selection.kind === "pin" ? "pinned" : "recommended";
|
|
131
|
+
if (leg.chosen !== chosen)
|
|
132
|
+
issues.push(issue(`legs[${index}].selection`, `a ${selection.kind} selection is chosen ${JSON.stringify(chosen)}, not ${JSON.stringify(leg.chosen)}`));
|
|
133
|
+
});
|
|
105
134
|
const posture = postureOf(route.legs);
|
|
106
135
|
if (posture !== route.posture)
|
|
107
136
|
issues.push(issue("posture", `must be ${JSON.stringify(posture)}: that is what its legs run`));
|
|
@@ -210,12 +210,14 @@ declare const STORE_COLUMN_VALUES: {
|
|
|
210
210
|
subagent_state: "subagent_state";
|
|
211
211
|
subagent_tools: "subagent_tools";
|
|
212
212
|
subagent_undo: "subagent_undo";
|
|
213
|
+
suggestion_not_now: "suggestion_not_now";
|
|
213
214
|
sweep_cancel_rest: "sweep_cancel_rest";
|
|
214
215
|
sweep_file: "sweep_file";
|
|
215
216
|
task_cancel: "task_cancel";
|
|
216
217
|
task_resume: "task_resume";
|
|
217
218
|
tool_add: "tool_add";
|
|
218
219
|
tool_remove: "tool_remove";
|
|
220
|
+
trial_stop: "trial_stop";
|
|
219
221
|
}>;
|
|
220
222
|
request: z.ZodObject<{}, z.core.$catchall<z.ZodUnknown>>;
|
|
221
223
|
repo: z.ZodString;
|
package/dist/dispose.js
CHANGED
|
@@ -25,6 +25,7 @@ import { verificationEvidence, failedVerificationEvidence } from "./verification
|
|
|
25
25
|
import { classifyGateFailure, describeGateFailure, gateFailureSummary } from "./gate-failure.js";
|
|
26
26
|
import { propose, approve, liveReleaseOf, releaseCheckScope } from "./scope.js";
|
|
27
27
|
import { headWithin } from "./names.js";
|
|
28
|
+
import { recordExecClass } from "./route-store.js";
|
|
28
29
|
/** The reasons tick classifies as the attempt itself breaking. */
|
|
29
30
|
const TICK_FAILURE_REASONS = new Set([
|
|
30
31
|
"agent",
|
|
@@ -247,6 +248,8 @@ function disposeBuildOutcomeLocked(context, result) {
|
|
|
247
248
|
return { kind: "malformed", sealed: sealed.ok };
|
|
248
249
|
}
|
|
249
250
|
const outcome = STANDALONE_BROKE_REASONS.has(result.reason) ? "failed" : "refused";
|
|
251
|
+
if (outcome === "failed")
|
|
252
|
+
recordExecClass(store, runId, result.reason);
|
|
250
253
|
store.finishRun(runId, { outcome, reason: result.reason, now: clock() });
|
|
251
254
|
return { kind: "recorded", outcome };
|
|
252
255
|
}
|
|
@@ -281,6 +284,9 @@ function disposeBuildOutcomeLocked(context, result) {
|
|
|
281
284
|
return { kind: "handed-back", requeued: handed.requeued };
|
|
282
285
|
}
|
|
283
286
|
if (TICK_FAILURE_REASONS.has(result.reason)) {
|
|
287
|
+
// Results routing (v148): the raw reason's execution class, kept on the run before the mapping below folds
|
|
288
|
+
// timeouts and setup failures together (route-store.ts recordExecClass; first write wins).
|
|
289
|
+
recordExecClass(store, runId, result.reason);
|
|
284
290
|
// One fenced transaction decides what the failure means. The
|
|
285
291
|
// classification trusts only what the machine itself observed.
|
|
286
292
|
const failureClass = result.reason === "agent-reported"
|
package/dist/flow-engine.js
CHANGED
|
@@ -507,7 +507,7 @@ export function revisionWithNote(store, card, target, note, actor, repos, eviden
|
|
|
507
507
|
return null;
|
|
508
508
|
const revised = requestResultChanges(store, evidenceRoot, {
|
|
509
509
|
run: runId, source: revisionSourceOf(store.getScope(runTask)?.digest ?? null), actor, repos,
|
|
510
|
-
batch: "", note, path: "", line: "", request: `flow-${card.id}-${card.entry}`, allowMode: true,
|
|
510
|
+
batch: "", note, path: "", line: "", request: `flow-${card.id}-${card.entry}`, allowMode: true, origin: "flow",
|
|
511
511
|
}, now);
|
|
512
512
|
return revised.ok ? revised.id : null;
|
|
513
513
|
}
|
|
@@ -140,7 +140,7 @@ export async function pullRequestStep(store, flow, definition, stage, card, now,
|
|
|
140
140
|
const runTask = store.externalIdFor(store.getRun(runId)?.taskRef ?? -1);
|
|
141
141
|
const revised = runTask === null ? null : requestResultChanges(store, io.evidenceRoot, {
|
|
142
142
|
run: runId, source: revisionSourceOf(store.getScope(runTask)?.digest ?? null), actor: "toolroll", repos: [flow.repo], batch: "",
|
|
143
|
-
note: found?.note ?? said, path: "", line: "", allowMode: true,
|
|
143
|
+
note: found?.note ?? said, path: "", line: "", allowMode: true, origin: "flow",
|
|
144
144
|
request: createHash("sha256").update(`flow-ci ${card.id} ${card.entry} ${publication.id}`).digest("hex").slice(0, 32),
|
|
145
145
|
}, now);
|
|
146
146
|
if (revised?.ok === true)
|
package/dist/lead-doors.js
CHANGED
|
@@ -25,7 +25,7 @@ import { teamChatAuthorization, subscriptionTeamChatProvider } from './team-chat
|
|
|
25
25
|
import { readProjectAccess } from "./project-access.js";
|
|
26
26
|
import { TeamLeads } from './team-leads.js';
|
|
27
27
|
import { fileTaskProposal } from "./proposal.js";
|
|
28
|
-
import { proposeGuarded } from "./scope.js";
|
|
28
|
+
import { machineActing, proposeGuarded } from "./scope.js";
|
|
29
29
|
import { isTaskSize, PHASES, specWords } from "./phase-routing.js";
|
|
30
30
|
import { isProviderId } from "./provider.js";
|
|
31
31
|
import { applyChatReview } from "./chat-review.js";
|
|
@@ -377,7 +377,9 @@ function executeProposal(store, actor, kind, payload, now, options) {
|
|
|
377
377
|
const request = payload;
|
|
378
378
|
if (request.snapshot == null || request.snapshot.task !== taskId || (request.operation !== "note" && request.operation !== "revise"))
|
|
379
379
|
return refuse("refused", "This feedback card is incomplete. Ask again.");
|
|
380
|
-
|
|
380
|
+
// A review card is the lead's (or a coordinator's) proposal; a person confirming it here decided the result needs
|
|
381
|
+
// these changes, so the revision is theirs. Under the lead's own chain or a remote run nobody confirmed it: lead.
|
|
382
|
+
const result = applyChatReview(store, actor, options.evidenceRoot, request, now, options.via !== "cli", machineActing() ? "lead" : "person");
|
|
381
383
|
return result.ok ? { ok: true, kind, taskId: result.taskId, said: result.said } : refuse("stale", result.message);
|
|
382
384
|
}
|
|
383
385
|
// The place the proposer saw must be the place the task holds now
|
package/dist/lead-tools.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { rulesOf, ruleWords as earnedRuleWords, suggestionsFor, suggestionWords, trialOffersFor, trialOfferWords, trialsOf, trialWords } from "./route-rules.js";
|
|
1
2
|
import { sameFeedbackImage } from "./result-review.js";
|
|
2
3
|
import { sweepLine, sweepTable } from "./lead-sweep.js";
|
|
3
4
|
import { connectionsOf, oneClickOf } from "./mcp-connect.js";
|
|
@@ -1602,7 +1603,7 @@ const LEAD_TOOL_HANDLERS = {
|
|
|
1602
1603
|
},
|
|
1603
1604
|
},
|
|
1604
1605
|
get_models: {
|
|
1605
|
-
description: "Default agent per role with the exact model each name runs now, installed CLI versions and updates,
|
|
1606
|
+
description: "Default agent per role with the exact model each name runs now, installed CLI versions and updates, models released in the last two weeks, and cheaper models your projects' own results suggest (with their earned rules), cheaper models to try and the trials in use. Read-only; accepting and starting a trial happen in Settings → Models; Not now is propose_action suggestion_not_now; stopping a trial is propose_action trial_stop.",
|
|
1606
1607
|
handle: (ctx) => {
|
|
1607
1608
|
const roles = ["plan", "build", "review", "repair"].map(phase => {
|
|
1608
1609
|
const row = ctx.store.phaseConfig(INSTALLATION_SCOPE, phase);
|
|
@@ -1610,7 +1611,14 @@ const LEAD_TOOL_HANDLERS = {
|
|
|
1610
1611
|
});
|
|
1611
1612
|
const tools = runtimeStates(ctx.store).map(one => ({ name: one.name, installed: one.installed, latest: one.latest, updateAvailable: one.behind }));
|
|
1612
1613
|
const newModels = ["claude", "codex", "gemini"].flatMap(source => seenModels(ctx.store, source)).filter(model => isNewModel(model, ctx.now)).map(model => ({ name: model.name, id: model.id, price: priceWords(model), released: model.releasedAt }));
|
|
1613
|
-
|
|
1614
|
+
// Results routing: the same suggestions and rules Settings → Models and `toolroll models suggestions` show.
|
|
1615
|
+
const suggestions = ctx.who.repos.flatMap(repo => suggestionsFor(ctx.store, repo, ctx.now)).map(one => ({ id: one.id, repo: one.repo, words: suggestionWords(one),
|
|
1616
|
+
review: `/settings/models?scope=${encodeURIComponent(one.repo)}&suggestion=${encodeURIComponent(one.id)}#models-suggested` }));
|
|
1617
|
+
const rules = ctx.who.repos.flatMap(repo => rulesOf(ctx.store, repo, ctx.now)).map(one => ({ id: one.id, repo: one.repo, state: one.state, words: earnedRuleWords(ctx.store, one) }));
|
|
1618
|
+
const trialOffers = ctx.who.repos.flatMap(repo => trialOffersFor(ctx.store, repo, ctx.now)).map(one => ({ id: one.id, repo: one.repo, words: trialOfferWords(one),
|
|
1619
|
+
start: `/settings/models?scope=${encodeURIComponent(one.repo)}#models-suggested` }));
|
|
1620
|
+
const trials = ctx.who.repos.flatMap(repo => trialsOf(ctx.store, repo, ctx.now)).map(one => ({ id: one.id, repo: one.repo, state: one.state, words: trialWords(ctx.store, one) }));
|
|
1621
|
+
return { ok: true, body: { roles, tools, newModels, suggestions, rules, trialOffers, trials, change: "/settings/models" } };
|
|
1614
1622
|
},
|
|
1615
1623
|
},
|
|
1616
1624
|
list_tasks: {
|
package/dist/local-owner.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export declare function authorityOf(value: unknown): Authority | null;
|
|
|
10
10
|
* The acts a local owner may do (plan C1). Ids only: each surface (a route row, a chat action, a CLI command) names
|
|
11
11
|
* the act it is, and an act not in this list is refused to a local owner.
|
|
12
12
|
*/
|
|
13
|
-
export declare const LOCAL_OWNER_ACTS: readonly ["file-task", "lead-send", "approve-plan", "answer-question", "stop-run", "pause-run", "resume-run", "complete-task", "request-revision", "archive-task", "add-project", "choose-default-agent", "mark-seen", "watch-agent", "read"];
|
|
13
|
+
export declare const LOCAL_OWNER_ACTS: readonly ["file-task", "lead-send", "approve-plan", "answer-question", "stop-run", "pause-run", "resume-run", "complete-task", "request-revision", "archive-task", "add-project", "choose-default-agent", "mark-seen", "watch-agent", "read", "routing-turn-off", "dismiss-suggestion", "trial-stop"];
|
|
14
14
|
export type LocalOwnerAct = (typeof LOCAL_OWNER_ACTS)[number];
|
|
15
15
|
/** Whether a runtime string names an act a local owner may do. */
|
|
16
16
|
export declare function localOwnerAct(value: unknown): value is LocalOwnerAct;
|
package/dist/local-owner.js
CHANGED
|
@@ -32,6 +32,13 @@ export const LOCAL_OWNER_ACTS = Object.freeze([
|
|
|
32
32
|
"mark-seen",
|
|
33
33
|
"watch-agent",
|
|
34
34
|
"read",
|
|
35
|
+
// Results routing (docs/plans/results-routing.md, Authority): lowering only — turning an earned rule off (or
|
|
36
|
+
// dropping a paused one), and saying Not now to a suggestion (or switching suggestions off). The writer
|
|
37
|
+
// (route-store.ts proveRuleDoor) checks the in-flight act is exactly the one it needs.
|
|
38
|
+
"routing-turn-off",
|
|
39
|
+
"dismiss-suggestion",
|
|
40
|
+
// Slice 3: stopping a trial of a cheaper model only lowers (proveRuleDoor checks this exact act).
|
|
41
|
+
"trial-stop",
|
|
35
42
|
]);
|
|
36
43
|
const ACT_SET = new Set(LOCAL_OWNER_ACTS);
|
|
37
44
|
/** Whether a runtime string names an act a local owner may do. */
|
|
@@ -150,6 +157,10 @@ export const CHAT_ACTION_LOCAL_ACTS = Object.freeze({
|
|
|
150
157
|
subagent_create: null, subagent_soul: null, subagent_state: null, subagent_note: null, subagent_ask: null,
|
|
151
158
|
subagent_answer: null, subagent_tools: null, subagent_memory: null, subagent_routine: null, subagent_undo: null,
|
|
152
159
|
kit_setup: null, decision_record: null, decision_retire: null, lead_about_you: null,
|
|
160
|
+
// Results routing: Not now only lowers (the rule door checks this exact act).
|
|
161
|
+
suggestion_not_now: "dismiss-suggestion",
|
|
162
|
+
// Stopping a trial only lowers (the rule door checks this exact act).
|
|
163
|
+
trial_stop: "trial-stop",
|
|
153
164
|
scope_approve: "approve-plan",
|
|
154
165
|
result_accept: "complete-task",
|
|
155
166
|
task_cancel: "stop-run",
|
package/dist/memory-cli.d.ts
CHANGED
|
@@ -200,6 +200,7 @@ export declare const MEMORY_DESCRIPTORS: readonly [{
|
|
|
200
200
|
readonly takesValue: false;
|
|
201
201
|
readonly meaning: 'read only the plane\'s own transcripts, not local Claude Code or Codex session files';
|
|
202
202
|
}];
|
|
203
|
+
readonly audience: 'operator';
|
|
203
204
|
}, {
|
|
204
205
|
readonly action: 'retire';
|
|
205
206
|
readonly synopsis: 'retire a decision that no longer holds: memory retire <id> --reason "<why>"';
|
|
@@ -250,6 +251,7 @@ export declare const MEMORY_DESCRIPTORS: readonly [{
|
|
|
250
251
|
readonly takesValue: false;
|
|
251
252
|
readonly meaning: 'read only the plane\'s own transcripts, not local Claude Code or Codex session files';
|
|
252
253
|
}];
|
|
254
|
+
readonly audience: 'operator';
|
|
253
255
|
}, {
|
|
254
256
|
readonly action: 'propose';
|
|
255
257
|
readonly synopsis: 'the backward pass: read recent sessions, keep a ledger of evidenced gaps, propose a few edits (writes nothing to memory)';
|
|
@@ -400,6 +402,7 @@ export declare const MEMORY_DESCRIPTORS: readonly [{
|
|
|
400
402
|
readonly takesValue: false;
|
|
401
403
|
readonly meaning: 'read only the plane\'s own transcripts, not local Claude Code or Codex session files';
|
|
402
404
|
}];
|
|
405
|
+
readonly audience: 'operator';
|
|
403
406
|
}, {
|
|
404
407
|
readonly action: 'status';
|
|
405
408
|
readonly synopsis: 'surface version, instruction budget, sessions analysed, open gaps and pending proposals';
|