@humain/humain-code-contracts 0.4.9 → 0.4.10

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 CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.10] - 2026-10-13
4
+
5
+ ### Added
6
+
7
+ - Added optional `FlowProfileV1.modelSelection` for Flow-only tier and capability primaries, ordered backups and capability effort, with exported schemas, types and supported tier and capability constants. Backup lists allow at most eight models and reject duplicate references; omitted backups inherit while `[]` explicitly disables fallbacks.
8
+
9
+ ### Changed
10
+
11
+ - Profiles and admissions containing `modelSelection` include it in their digest input. Existing documents without it retain their original digests. Older strict readers reject the new field; update profile and admission consumers before exchanging new-format documents.
12
+
3
13
  ## [0.4.9] - 2026-10-13
4
14
 
5
15
  ### Added
@@ -172,6 +172,29 @@ export declare const FlowRunAdmissionV1Schema: Type.TObject<{
172
172
  readonly triage: Type.TOptional<Type.TInteger>;
173
173
  }>>;
174
174
  }>;
175
+ readonly modelSelection: Type.TOptional<Type.TObject<{
176
+ readonly tiers: Type.TOptional<Type.TObject<Record<"cheap" | "frontier" | "mid" | "premium", Type.TOptional<Type.TObject<{
177
+ readonly primary: Type.TOptional<Type.TObject<{
178
+ readonly provider: Type.TString;
179
+ readonly model: Type.TString;
180
+ }>>;
181
+ readonly backups: Type.TOptional<Type.TArray<Type.TObject<{
182
+ readonly provider: Type.TString;
183
+ readonly model: Type.TString;
184
+ }>>>;
185
+ }>>>>>;
186
+ readonly capabilities: Type.TOptional<Type.TObject<Record<"analysis_mid" | "analysis_strong" | "api_contract_review" | "architect" | "implementation_fast" | "implementation_strong" | "integration_review" | "lead" | "lead_large" | "lead_small" | "migration_review" | "performance_review" | "qa_agent" | "scope_scout" | "scout" | "security_review" | "technical_lead" | "technical_review" | "triage" | "worker", Type.TOptional<Type.TObject<{
187
+ readonly primary: Type.TOptional<Type.TObject<{
188
+ readonly provider: Type.TString;
189
+ readonly model: Type.TString;
190
+ }>>;
191
+ readonly backups: Type.TOptional<Type.TArray<Type.TObject<{
192
+ readonly provider: Type.TString;
193
+ readonly model: Type.TString;
194
+ }>>>;
195
+ readonly effort: Type.TOptional<Type.TUnion<[Type.TLiteral<"off">, Type.TLiteral<"minimal">, Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">, Type.TLiteral<"xhigh">, Type.TLiteral<"max">]>>;
196
+ }>>>>>;
197
+ }>>;
175
198
  readonly providers: Type.TOptional<Type.TObject<{
176
199
  readonly preference: Type.TArray<Type.TString>;
177
200
  }>>;
@@ -1 +1 @@
1
- {"version":3,"file":"flow-admission.d.ts","sourceRoot":"","sources":["../src/flow-admission.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAIN,KAAK,gBAAgB,EAUrB,MAAM,kBAAkB,CAAC;AAG1B,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuBnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAIzE,+GAA+G;AAC/G,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,kBAAkB,GAAG,MAAM,CAExE;AAYD;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,CAE/E;AAED,+HAA+H;AAC/H,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,GAAG,kBAAkB,CASpG"}
1
+ {"version":3,"file":"flow-admission.d.ts","sourceRoot":"","sources":["../src/flow-admission.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAIN,KAAK,gBAAgB,EAUrB,MAAM,kBAAkB,CAAC;AAG1B,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuBnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAIzE,+GAA+G;AAC/G,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,kBAAkB,GAAG,MAAM,CAExE;AAYD;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,CAE/E;AAED,+HAA+H;AAC/H,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,GAAG,kBAAkB,CASpG"}
@@ -1,20 +1,75 @@
1
- import { type Static, Type } from "typebox";
1
+ import { type Static, type TObject, type TOptional, Type } from "typebox";
2
2
  import { type FlowDigestHasher } from "./flow-common.ts";
3
3
  export { FlowProfileRefSchema, type FlowProfileRefV1 } from "./flow-common.ts";
4
4
  export declare const FlowEffortSchema: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
5
- export declare const FlowRoleBindingSchema: Type.TObject<{
6
- readonly primary: Type.TObject<{
5
+ export declare const FlowRoleBindingSchema: TObject<{
6
+ readonly primary: TObject<{
7
7
  readonly provider: Type.TString;
8
8
  readonly model: Type.TString;
9
9
  }>;
10
- readonly backups: Type.TArray<Type.TObject<{
10
+ readonly backups: Type.TArray<TObject<{
11
11
  readonly provider: Type.TString;
12
12
  readonly model: Type.TString;
13
13
  }>>;
14
14
  readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
15
15
  }>;
16
16
  export type FlowRoleBindingV1 = Static<typeof FlowRoleBindingSchema>;
17
- export declare const FlowProfileV1Schema: Type.TObject<{
17
+ /** Cost tiers a selection may declare (matches Flow's `Tier`). */
18
+ export declare const FLOW_MODEL_SELECTION_TIERS: readonly ["cheap", "mid", "premium", "frontier"];
19
+ export type FlowSelectionTier = (typeof FLOW_MODEL_SELECTION_TIERS)[number];
20
+ /** Flow's `ALL_CAPABILITIES` (method.json) plus the runtime `triage` capability; parity is pinned in the flow tests. */
21
+ export declare const FLOW_MODEL_SELECTION_CAPABILITIES: readonly ["scout", "scope_scout", "worker", "implementation_fast", "analysis_mid", "technical_lead", "lead_small", "lead", "lead_large", "implementation_strong", "technical_review", "integration_review", "migration_review", "performance_review", "api_contract_review", "qa_agent", "analysis_strong", "architect", "security_review", "triage"];
22
+ export type FlowSelectionCapability = (typeof FLOW_MODEL_SELECTION_CAPABILITIES)[number];
23
+ export declare const FlowSelectionEffortSchema: Type.TUnion<[Type.TLiteral<"off">, Type.TLiteral<"minimal">, Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">, Type.TLiteral<"xhigh">, Type.TLiteral<"max">]>;
24
+ /** Omitted `backups` inherits; an explicit `[]` means no fallbacks. Both must survive round-trips. */
25
+ export declare const FlowTierSelectionSchema: TObject<{
26
+ readonly primary: TOptional<TObject<{
27
+ readonly provider: Type.TString;
28
+ readonly model: Type.TString;
29
+ }>>;
30
+ readonly backups: TOptional<Type.TArray<TObject<{
31
+ readonly provider: Type.TString;
32
+ readonly model: Type.TString;
33
+ }>>>;
34
+ }>;
35
+ export type FlowTierSelectionV1 = Static<typeof FlowTierSelectionSchema>;
36
+ export declare const FlowCapabilitySelectionSchema: TObject<{
37
+ readonly primary: TOptional<TObject<{
38
+ readonly provider: Type.TString;
39
+ readonly model: Type.TString;
40
+ }>>;
41
+ readonly backups: TOptional<Type.TArray<TObject<{
42
+ readonly provider: Type.TString;
43
+ readonly model: Type.TString;
44
+ }>>>;
45
+ readonly effort: TOptional<Type.TUnion<[Type.TLiteral<"off">, Type.TLiteral<"minimal">, Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">, Type.TLiteral<"xhigh">, Type.TLiteral<"max">]>>;
46
+ }>;
47
+ export type FlowCapabilitySelectionV1 = Static<typeof FlowCapabilitySelectionSchema>;
48
+ export declare const FlowModelSelectionSchema: TObject<{
49
+ readonly tiers: TOptional<TObject<Record<"cheap" | "frontier" | "mid" | "premium", TOptional<TObject<{
50
+ readonly primary: TOptional<TObject<{
51
+ readonly provider: Type.TString;
52
+ readonly model: Type.TString;
53
+ }>>;
54
+ readonly backups: TOptional<Type.TArray<TObject<{
55
+ readonly provider: Type.TString;
56
+ readonly model: Type.TString;
57
+ }>>>;
58
+ }>>>>>;
59
+ readonly capabilities: TOptional<TObject<Record<"analysis_mid" | "analysis_strong" | "api_contract_review" | "architect" | "implementation_fast" | "implementation_strong" | "integration_review" | "lead" | "lead_large" | "lead_small" | "migration_review" | "performance_review" | "qa_agent" | "scope_scout" | "scout" | "security_review" | "technical_lead" | "technical_review" | "triage" | "worker", TOptional<TObject<{
60
+ readonly primary: TOptional<TObject<{
61
+ readonly provider: Type.TString;
62
+ readonly model: Type.TString;
63
+ }>>;
64
+ readonly backups: TOptional<Type.TArray<TObject<{
65
+ readonly provider: Type.TString;
66
+ readonly model: Type.TString;
67
+ }>>>;
68
+ readonly effort: TOptional<Type.TUnion<[Type.TLiteral<"off">, Type.TLiteral<"minimal">, Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">, Type.TLiteral<"xhigh">, Type.TLiteral<"max">]>>;
69
+ }>>>>>;
70
+ }>;
71
+ export type FlowModelSelectionV1 = Static<typeof FlowModelSelectionSchema>;
72
+ export declare const FlowProfileV1Schema: TObject<{
18
73
  readonly schema: Type.TLiteral<"humain-flow-profile">;
19
74
  readonly schemaVersion: Type.TLiteral<1>;
20
75
  readonly id: Type.TString;
@@ -22,139 +77,139 @@ export declare const FlowProfileV1Schema: Type.TObject<{
22
77
  readonly digest: Type.TString;
23
78
  readonly kind: Type.TUnion<[Type.TLiteral<"direct">, Type.TLiteral<"flow">]>;
24
79
  readonly label: Type.TString;
25
- readonly description: Type.TOptional<Type.TString>;
26
- readonly direct: Type.TOptional<Type.TObject<{
27
- readonly model: Type.TObject<{
80
+ readonly description: TOptional<Type.TString>;
81
+ readonly direct: TOptional<TObject<{
82
+ readonly model: TObject<{
28
83
  readonly provider: Type.TString;
29
84
  readonly model: Type.TString;
30
85
  }>;
31
- readonly fallbacks: Type.TArray<Type.TObject<{
86
+ readonly fallbacks: Type.TArray<TObject<{
32
87
  readonly provider: Type.TString;
33
88
  readonly model: Type.TString;
34
89
  }>>;
35
90
  }>>;
36
- readonly roles: Type.TOptional<Type.TObject<{
37
- readonly scout: Type.TOptional<Type.TObject<{
38
- readonly primary: Type.TObject<{
91
+ readonly roles: TOptional<TObject<{
92
+ readonly scout: TOptional<TObject<{
93
+ readonly primary: TObject<{
39
94
  readonly provider: Type.TString;
40
95
  readonly model: Type.TString;
41
96
  }>;
42
- readonly backups: Type.TArray<Type.TObject<{
97
+ readonly backups: Type.TArray<TObject<{
43
98
  readonly provider: Type.TString;
44
99
  readonly model: Type.TString;
45
100
  }>>;
46
101
  readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
47
102
  }>>;
48
- readonly worker: Type.TOptional<Type.TObject<{
49
- readonly primary: Type.TObject<{
103
+ readonly worker: TOptional<TObject<{
104
+ readonly primary: TObject<{
50
105
  readonly provider: Type.TString;
51
106
  readonly model: Type.TString;
52
107
  }>;
53
- readonly backups: Type.TArray<Type.TObject<{
108
+ readonly backups: Type.TArray<TObject<{
54
109
  readonly provider: Type.TString;
55
110
  readonly model: Type.TString;
56
111
  }>>;
57
112
  readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
58
113
  }>>;
59
- readonly implementer: Type.TOptional<Type.TObject<{
60
- readonly primary: Type.TObject<{
114
+ readonly implementer: TOptional<TObject<{
115
+ readonly primary: TObject<{
61
116
  readonly provider: Type.TString;
62
117
  readonly model: Type.TString;
63
118
  }>;
64
- readonly backups: Type.TArray<Type.TObject<{
119
+ readonly backups: Type.TArray<TObject<{
65
120
  readonly provider: Type.TString;
66
121
  readonly model: Type.TString;
67
122
  }>>;
68
123
  readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
69
124
  }>>;
70
- readonly lead: Type.TOptional<Type.TObject<{
71
- readonly primary: Type.TObject<{
125
+ readonly lead: TOptional<TObject<{
126
+ readonly primary: TObject<{
72
127
  readonly provider: Type.TString;
73
128
  readonly model: Type.TString;
74
129
  }>;
75
- readonly backups: Type.TArray<Type.TObject<{
130
+ readonly backups: Type.TArray<TObject<{
76
131
  readonly provider: Type.TString;
77
132
  readonly model: Type.TString;
78
133
  }>>;
79
134
  readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
80
135
  }>>;
81
- readonly lead_large: Type.TOptional<Type.TObject<{
82
- readonly primary: Type.TObject<{
136
+ readonly lead_large: TOptional<TObject<{
137
+ readonly primary: TObject<{
83
138
  readonly provider: Type.TString;
84
139
  readonly model: Type.TString;
85
140
  }>;
86
- readonly backups: Type.TArray<Type.TObject<{
141
+ readonly backups: Type.TArray<TObject<{
87
142
  readonly provider: Type.TString;
88
143
  readonly model: Type.TString;
89
144
  }>>;
90
145
  readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
91
146
  }>>;
92
- readonly architect: Type.TOptional<Type.TObject<{
93
- readonly primary: Type.TObject<{
147
+ readonly architect: TOptional<TObject<{
148
+ readonly primary: TObject<{
94
149
  readonly provider: Type.TString;
95
150
  readonly model: Type.TString;
96
151
  }>;
97
- readonly backups: Type.TArray<Type.TObject<{
152
+ readonly backups: Type.TArray<TObject<{
98
153
  readonly provider: Type.TString;
99
154
  readonly model: Type.TString;
100
155
  }>>;
101
156
  readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
102
157
  }>>;
103
- readonly reviewer: Type.TOptional<Type.TObject<{
104
- readonly primary: Type.TObject<{
158
+ readonly reviewer: TOptional<TObject<{
159
+ readonly primary: TObject<{
105
160
  readonly provider: Type.TString;
106
161
  readonly model: Type.TString;
107
162
  }>;
108
- readonly backups: Type.TArray<Type.TObject<{
163
+ readonly backups: Type.TArray<TObject<{
109
164
  readonly provider: Type.TString;
110
165
  readonly model: Type.TString;
111
166
  }>>;
112
167
  readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
113
168
  }>>;
114
- readonly security_reviewer: Type.TOptional<Type.TObject<{
115
- readonly primary: Type.TObject<{
169
+ readonly security_reviewer: TOptional<TObject<{
170
+ readonly primary: TObject<{
116
171
  readonly provider: Type.TString;
117
172
  readonly model: Type.TString;
118
173
  }>;
119
- readonly backups: Type.TArray<Type.TObject<{
174
+ readonly backups: Type.TArray<TObject<{
120
175
  readonly provider: Type.TString;
121
176
  readonly model: Type.TString;
122
177
  }>>;
123
178
  readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
124
179
  }>>;
125
- readonly qa: Type.TOptional<Type.TObject<{
126
- readonly primary: Type.TObject<{
180
+ readonly qa: TOptional<TObject<{
181
+ readonly primary: TObject<{
127
182
  readonly provider: Type.TString;
128
183
  readonly model: Type.TString;
129
184
  }>;
130
- readonly backups: Type.TArray<Type.TObject<{
185
+ readonly backups: Type.TArray<TObject<{
131
186
  readonly provider: Type.TString;
132
187
  readonly model: Type.TString;
133
188
  }>>;
134
189
  readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
135
190
  }>>;
136
- readonly triage: Type.TOptional<Type.TObject<{
137
- readonly primary: Type.TObject<{
191
+ readonly triage: TOptional<TObject<{
192
+ readonly primary: TObject<{
138
193
  readonly provider: Type.TString;
139
194
  readonly model: Type.TString;
140
195
  }>;
141
- readonly backups: Type.TArray<Type.TObject<{
196
+ readonly backups: Type.TArray<TObject<{
142
197
  readonly provider: Type.TString;
143
198
  readonly model: Type.TString;
144
199
  }>>;
145
200
  readonly effort: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">]>;
146
201
  }>>;
147
202
  }>>;
148
- readonly sizing: Type.TOptional<Type.TObject<{
203
+ readonly sizing: TOptional<TObject<{
149
204
  readonly classifierPolicyId: Type.TString;
150
- readonly thresholds: Type.TObject<{
205
+ readonly thresholds: TObject<{
151
206
  readonly mediumAt: Type.TNumber;
152
207
  readonly largeAt: Type.TNumber;
153
208
  }>;
154
209
  readonly triageRole: Type.TLiteral<"triage">;
155
210
  readonly maxEscalations: Type.TUnion<[Type.TLiteral<0>, Type.TLiteral<1>]>;
156
211
  }>>;
157
- readonly limits: Type.TObject<{
212
+ readonly limits: TObject<{
158
213
  readonly maxAgents: Type.TInteger;
159
214
  readonly maxConcurrent: Type.TInteger;
160
215
  readonly maxDepth: Type.TInteger;
@@ -162,30 +217,53 @@ export declare const FlowProfileV1Schema: Type.TObject<{
162
217
  readonly inactivityMs: Type.TInteger;
163
218
  readonly ciWaitMs: Type.TInteger;
164
219
  }>;
165
- readonly spend: Type.TObject<{
220
+ readonly spend: TObject<{
166
221
  readonly runCapMicrousd: Type.TInteger;
167
222
  readonly warnAtPct: Type.TInteger;
168
- readonly perRoleCapMicrousd: Type.TOptional<Type.TObject<{
169
- readonly scout: Type.TOptional<Type.TInteger>;
170
- readonly worker: Type.TOptional<Type.TInteger>;
171
- readonly implementer: Type.TOptional<Type.TInteger>;
172
- readonly lead: Type.TOptional<Type.TInteger>;
173
- readonly lead_large: Type.TOptional<Type.TInteger>;
174
- readonly architect: Type.TOptional<Type.TInteger>;
175
- readonly reviewer: Type.TOptional<Type.TInteger>;
176
- readonly security_reviewer: Type.TOptional<Type.TInteger>;
177
- readonly qa: Type.TOptional<Type.TInteger>;
178
- readonly triage: Type.TOptional<Type.TInteger>;
223
+ readonly perRoleCapMicrousd: TOptional<TObject<{
224
+ readonly scout: TOptional<Type.TInteger>;
225
+ readonly worker: TOptional<Type.TInteger>;
226
+ readonly implementer: TOptional<Type.TInteger>;
227
+ readonly lead: TOptional<Type.TInteger>;
228
+ readonly lead_large: TOptional<Type.TInteger>;
229
+ readonly architect: TOptional<Type.TInteger>;
230
+ readonly reviewer: TOptional<Type.TInteger>;
231
+ readonly security_reviewer: TOptional<Type.TInteger>;
232
+ readonly qa: TOptional<Type.TInteger>;
233
+ readonly triage: TOptional<Type.TInteger>;
179
234
  }>>;
180
235
  }>;
181
- readonly providers: Type.TOptional<Type.TObject<{
236
+ readonly modelSelection: TOptional<TObject<{
237
+ readonly tiers: TOptional<TObject<Record<"cheap" | "frontier" | "mid" | "premium", TOptional<TObject<{
238
+ readonly primary: TOptional<TObject<{
239
+ readonly provider: Type.TString;
240
+ readonly model: Type.TString;
241
+ }>>;
242
+ readonly backups: TOptional<Type.TArray<TObject<{
243
+ readonly provider: Type.TString;
244
+ readonly model: Type.TString;
245
+ }>>>;
246
+ }>>>>>;
247
+ readonly capabilities: TOptional<TObject<Record<"analysis_mid" | "analysis_strong" | "api_contract_review" | "architect" | "implementation_fast" | "implementation_strong" | "integration_review" | "lead" | "lead_large" | "lead_small" | "migration_review" | "performance_review" | "qa_agent" | "scope_scout" | "scout" | "security_review" | "technical_lead" | "technical_review" | "triage" | "worker", TOptional<TObject<{
248
+ readonly primary: TOptional<TObject<{
249
+ readonly provider: Type.TString;
250
+ readonly model: Type.TString;
251
+ }>>;
252
+ readonly backups: TOptional<Type.TArray<TObject<{
253
+ readonly provider: Type.TString;
254
+ readonly model: Type.TString;
255
+ }>>>;
256
+ readonly effort: TOptional<Type.TUnion<[Type.TLiteral<"off">, Type.TLiteral<"minimal">, Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">, Type.TLiteral<"xhigh">, Type.TLiteral<"max">]>>;
257
+ }>>>>>;
258
+ }>>;
259
+ readonly providers: TOptional<TObject<{
182
260
  readonly preference: Type.TArray<Type.TString>;
183
261
  }>>;
184
- readonly approval: Type.TOptional<Type.TObject<{
262
+ readonly approval: TOptional<TObject<{
185
263
  readonly approvedBy: Type.TString;
186
264
  readonly approvedAt: Type.TRefine<Type.TString>;
187
265
  }>>;
188
- readonly builtIn: Type.TOptional<Type.TLiteral<true>>;
266
+ readonly builtIn: TOptional<Type.TLiteral<true>>;
189
267
  }>;
190
268
  export type FlowProfileV1 = Static<typeof FlowProfileV1Schema>;
191
269
  /** Canonical text hashed (sha256 hex) to produce `digest`: the document without `digest`. */
@@ -1 +1 @@
1
- {"version":3,"file":"flow-profile.d.ts","sourceRoot":"","sources":["../src/flow-profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAIN,KAAK,gBAAgB,EAarB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,oBAAoB,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAE/E,eAAO,MAAM,gBAAgB,qFAAkF,CAAC;AAEhH,eAAO,MAAM,qBAAqB;;;;;;;;;;EAIhC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAErE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwC9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAK/D,6FAA6F;AAC7F,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAEjE;AAoBD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAErE;AAED,sHAAsH;AACtH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,GAAG,aAAa,CAM1F"}
1
+ {"version":3,"file":"flow-profile.d.ts","sourceRoot":"","sources":["../src/flow-profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAgB,IAAI,EAAE,MAAM,SAAS,CAAC;AACxF,OAAO,EAIN,KAAK,gBAAgB,EAcrB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,oBAAoB,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAE/E,eAAO,MAAM,gBAAgB,qFAAkF,CAAC;AAEhH,eAAO,MAAM,qBAAqB;;;;;;;;;;EAIhC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAErE,kEAAkE;AAClE,eAAO,MAAM,0BAA0B,YAAI,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,CAAU,CAAC;AAC3F,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5E,wHAAwH;AACxH,eAAO,MAAM,iCAAiC,YAC7C,OAAO,EACP,aAAa,EACb,QAAQ,EACR,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,MAAM,EACN,YAAY,EACZ,uBAAuB,EACvB,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,UAAU,EACV,iBAAiB,EACjB,WAAW,EACX,iBAAiB,EACjB,QAAQ,CACC,CAAC;AACX,MAAM,MAAM,uBAAuB,GAAG,CAAC,OAAO,iCAAiC,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzF,eAAO,MAAM,yBAAyB,mLAAiE,CAAC;AAExG,sGAAsG;AACtG,eAAO,MAAM,uBAAuB;;;;;;;;;EAGlC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAEzE,eAAO,MAAM,6BAA6B;;;;;;;;;;EAIxC,CAAC;AACH,MAAM,MAAM,yBAAyB,GAAG,MAAM,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAKrF,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;EAWnC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE3E,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyC9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAK/D,6FAA6F;AAC7F,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAEjE;AAiCD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAErE;AAED,sHAAsH;AACtH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,GAAG,aAAa,CAM1F"}
@@ -1,5 +1,5 @@
1
1
  import { Type } from "typebox";
2
- import { canonicalWithout, compileFlow, FlowContractError, FlowDigestSchema, FlowIdSchema, FlowMicrousdSchema, FlowModelRefSchema, FlowPositiveIntSchema, FlowTimestampSchema, hasDuplicateModels, parseFlowData, partialByRole, StrictObject, verifyFlowDigest, } from "./flow-common.js";
2
+ import { canonicalWithout, compileFlow, FlowContractError, FlowDigestSchema, FlowIdSchema, FlowMicrousdSchema, FlowModelRefSchema, FlowPositiveIntSchema, FlowTimestampSchema, hasDuplicateModels, lit, parseFlowData, partialByRole, StrictObject, verifyFlowDigest, } from "./flow-common.js";
3
3
  export { FlowProfileRefSchema } from "./flow-common.js";
4
4
  export const FlowEffortSchema = Type.Union([Type.Literal("low"), Type.Literal("medium"), Type.Literal("high")]);
5
5
  export const FlowRoleBindingSchema = StrictObject({
@@ -7,6 +7,47 @@ export const FlowRoleBindingSchema = StrictObject({
7
7
  backups: Type.Array(FlowModelRefSchema, { maxItems: 8 }),
8
8
  effort: FlowEffortSchema,
9
9
  });
10
+ /** Cost tiers a selection may declare (matches Flow's `Tier`). */
11
+ export const FLOW_MODEL_SELECTION_TIERS = ["cheap", "mid", "premium", "frontier"];
12
+ /** Flow's `ALL_CAPABILITIES` (method.json) plus the runtime `triage` capability; parity is pinned in the flow tests. */
13
+ export const FLOW_MODEL_SELECTION_CAPABILITIES = [
14
+ "scout",
15
+ "scope_scout",
16
+ "worker",
17
+ "implementation_fast",
18
+ "analysis_mid",
19
+ "technical_lead",
20
+ "lead_small",
21
+ "lead",
22
+ "lead_large",
23
+ "implementation_strong",
24
+ "technical_review",
25
+ "integration_review",
26
+ "migration_review",
27
+ "performance_review",
28
+ "api_contract_review",
29
+ "qa_agent",
30
+ "analysis_strong",
31
+ "architect",
32
+ "security_review",
33
+ "triage",
34
+ ];
35
+ export const FlowSelectionEffortSchema = lit("off", "minimal", "low", "medium", "high", "xhigh", "max");
36
+ /** Omitted `backups` inherits; an explicit `[]` means no fallbacks. Both must survive round-trips. */
37
+ export const FlowTierSelectionSchema = StrictObject({
38
+ primary: Type.Optional(FlowModelRefSchema),
39
+ backups: Type.Optional(Type.Array(FlowModelRefSchema, { maxItems: 8 })),
40
+ });
41
+ export const FlowCapabilitySelectionSchema = StrictObject({
42
+ primary: Type.Optional(FlowModelRefSchema),
43
+ backups: Type.Optional(Type.Array(FlowModelRefSchema, { maxItems: 8 })),
44
+ effort: Type.Optional(FlowSelectionEffortSchema),
45
+ });
46
+ const optionalEach = (keys, schema) => StrictObject(Object.fromEntries(keys.map((key) => [key, Type.Optional(schema)])));
47
+ export const FlowModelSelectionSchema = StrictObject({
48
+ tiers: Type.Optional(optionalEach(FLOW_MODEL_SELECTION_TIERS, FlowTierSelectionSchema)),
49
+ capabilities: Type.Optional(optionalEach(FLOW_MODEL_SELECTION_CAPABILITIES, FlowCapabilitySelectionSchema)),
50
+ });
10
51
  export const FlowProfileV1Schema = StrictObject({
11
52
  schema: Type.Literal("humain-flow-profile"),
12
53
  schemaVersion: Type.Literal(1),
@@ -40,6 +81,7 @@ export const FlowProfileV1Schema = StrictObject({
40
81
  warnAtPct: Type.Integer({ minimum: 1, maximum: 99 }),
41
82
  perRoleCapMicrousd: Type.Optional(partialByRole(FlowMicrousdSchema)),
42
83
  }),
84
+ modelSelection: Type.Optional(FlowModelSelectionSchema),
43
85
  providers: Type.Optional(StrictObject({ preference: Type.Array(FlowIdSchema, { maxItems: 16 }) })),
44
86
  approval: Type.Optional(StrictObject({ approvedBy: FlowIdSchema, approvedAt: FlowTimestampSchema })),
45
87
  builtIn: Type.Optional(Type.Literal(true)),
@@ -50,7 +92,18 @@ const REQUIRED_FLOW_ROLES = ["lead", "worker", "reviewer", "qa"];
50
92
  export function flowProfileDigestInput(doc) {
51
93
  return canonicalWithout(doc, "digest");
52
94
  }
95
+ function selectionLayerValid(layer) {
96
+ const refs = [...(layer.primary === undefined ? [] : [layer.primary]), ...(layer.backups ?? [])];
97
+ return !hasDuplicateModels(refs);
98
+ }
99
+ function modelSelectionValid(selection) {
100
+ const layers = [...Object.values(selection.tiers ?? {}), ...Object.values(selection.capabilities ?? {})];
101
+ return layers.every(selectionLayerValid);
102
+ }
53
103
  function crossFieldsValid(doc) {
104
+ if (doc.modelSelection !== undefined && (doc.kind === "direct" || !modelSelectionValid(doc.modelSelection))) {
105
+ return false;
106
+ }
54
107
  if (doc.kind === "direct") {
55
108
  if (doc.direct === undefined || doc.roles !== undefined || doc.sizing !== undefined)
56
109
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"flow-profile.js","sourceRoot":"","sources":["../src/flow-profile.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport {\n\tcanonicalWithout,\n\tcompileFlow,\n\tFlowContractError,\n\ttype FlowDigestHasher,\n\tFlowDigestSchema,\n\tFlowIdSchema,\n\tFlowMicrousdSchema,\n\ttype FlowModelRef,\n\tFlowModelRefSchema,\n\tFlowPositiveIntSchema,\n\tFlowTimestampSchema,\n\thasDuplicateModels,\n\tparseFlowData,\n\tpartialByRole,\n\tStrictObject,\n\tverifyFlowDigest,\n} from \"./flow-common.ts\";\n\nexport { FlowProfileRefSchema, type FlowProfileRefV1 } from \"./flow-common.ts\";\n\nexport const FlowEffortSchema = Type.Union([Type.Literal(\"low\"), Type.Literal(\"medium\"), Type.Literal(\"high\")]);\n\nexport const FlowRoleBindingSchema = StrictObject({\n\tprimary: FlowModelRefSchema,\n\tbackups: Type.Array(FlowModelRefSchema, { maxItems: 8 }),\n\teffort: FlowEffortSchema,\n});\nexport type FlowRoleBindingV1 = Static<typeof FlowRoleBindingSchema>;\n\nexport const FlowProfileV1Schema = StrictObject({\n\tschema: Type.Literal(\"humain-flow-profile\"),\n\tschemaVersion: Type.Literal(1),\n\tid: FlowIdSchema,\n\tversion: FlowPositiveIntSchema,\n\tdigest: FlowDigestSchema,\n\tkind: Type.Union([Type.Literal(\"direct\"), Type.Literal(\"flow\")]),\n\tlabel: Type.String({ minLength: 1, maxLength: 80 }),\n\tdescription: Type.Optional(Type.String({ maxLength: 500 })),\n\tdirect: Type.Optional(\n\t\tStrictObject({ model: FlowModelRefSchema, fallbacks: Type.Array(FlowModelRefSchema, { maxItems: 8 }) }),\n\t),\n\troles: Type.Optional(partialByRole(FlowRoleBindingSchema)),\n\tsizing: Type.Optional(\n\t\tStrictObject({\n\t\t\tclassifierPolicyId: FlowIdSchema,\n\t\t\tthresholds: StrictObject({\n\t\t\t\tmediumAt: Type.Number({ minimum: 0, maximum: 1_000_000 }),\n\t\t\t\tlargeAt: Type.Number({ minimum: 0, maximum: 1_000_000 }),\n\t\t\t}),\n\t\t\ttriageRole: Type.Literal(\"triage\"),\n\t\t\tmaxEscalations: Type.Union([Type.Literal(0), Type.Literal(1)]),\n\t\t}),\n\t),\n\tlimits: StrictObject({\n\t\tmaxAgents: Type.Integer({ minimum: 1, maximum: 256 }),\n\t\tmaxConcurrent: Type.Integer({ minimum: 1, maximum: 64 }),\n\t\tmaxDepth: Type.Integer({ minimum: 0, maximum: 3 }),\n\t\tmaxRetries: Type.Integer({ minimum: 0, maximum: 16 }),\n\t\tinactivityMs: Type.Integer({ minimum: 1, maximum: 86_400_000 }),\n\t\tciWaitMs: Type.Integer({ minimum: 0, maximum: 86_400_000 }),\n\t}),\n\tspend: StrictObject({\n\t\trunCapMicrousd: FlowMicrousdSchema,\n\t\twarnAtPct: Type.Integer({ minimum: 1, maximum: 99 }),\n\t\tperRoleCapMicrousd: Type.Optional(partialByRole(FlowMicrousdSchema)),\n\t}),\n\tproviders: Type.Optional(StrictObject({ preference: Type.Array(FlowIdSchema, { maxItems: 16 }) })),\n\tapproval: Type.Optional(StrictObject({ approvedBy: FlowIdSchema, approvedAt: FlowTimestampSchema })),\n\tbuiltIn: Type.Optional(Type.Literal(true)),\n});\nexport type FlowProfileV1 = Static<typeof FlowProfileV1Schema>;\n\nconst Validator = compileFlow(FlowProfileV1Schema);\nconst REQUIRED_FLOW_ROLES = [\"lead\", \"worker\", \"reviewer\", \"qa\"] as const;\n\n/** Canonical text hashed (sha256 hex) to produce `digest`: the document without `digest`. */\nexport function flowProfileDigestInput(doc: FlowProfileV1): string {\n\treturn canonicalWithout(doc, \"digest\");\n}\n\nfunction crossFieldsValid(doc: FlowProfileV1): boolean {\n\tif (doc.kind === \"direct\") {\n\t\tif (doc.direct === undefined || doc.roles !== undefined || doc.sizing !== undefined) return false;\n\t\treturn !hasDuplicateModels([doc.direct.model, ...doc.direct.fallbacks]);\n\t}\n\tif (doc.direct !== undefined || doc.roles === undefined) return false;\n\tfor (const role of REQUIRED_FLOW_ROLES) if (doc.roles[role] === undefined) return false;\n\tfor (const binding of Object.values(doc.roles)) {\n\t\tconst refs: FlowModelRef[] = [binding.primary, ...binding.backups];\n\t\tif (hasDuplicateModels(refs)) return false;\n\t}\n\treturn doc.sizing === undefined || doc.sizing.thresholds.mediumAt <= doc.sizing.thresholds.largeAt;\n}\n\nfunction isProfile(value: unknown): value is FlowProfileV1 {\n\treturn Validator.Check(value) && crossFieldsValid(value);\n}\n\n/**\n * SHAPE ONLY: validates structure and cross-field rules but does NOT verify `digest`. Use only for documents whose\n * integrity is established elsewhere (e.g. authored drafts); prefer {@link parseFlowProfileV1}.\n */\nexport function parseFlowProfileV1Shape(input: unknown): FlowProfileV1 {\n\treturn parseFlowData(\"profile_invalid\", input, isProfile);\n}\n\n/** Shape validation plus digest verification with the injected hasher (digests are integrity, not authentication). */\nexport function parseFlowProfileV1(input: unknown, hasher: FlowDigestHasher): FlowProfileV1 {\n\tconst profile = parseFlowProfileV1Shape(input);\n\tif (!verifyFlowDigest(hasher, flowProfileDigestInput(profile), profile.digest)) {\n\t\tthrow new FlowContractError(\"digest_mismatch\");\n\t}\n\treturn profile;\n}\n"]}
1
+ {"version":3,"file":"flow-profile.js","sourceRoot":"","sources":["../src/flow-profile.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Static, type TObject, type TOptional, type TSchema, Type } from \"typebox\";\nimport {\n\tcanonicalWithout,\n\tcompileFlow,\n\tFlowContractError,\n\ttype FlowDigestHasher,\n\tFlowDigestSchema,\n\tFlowIdSchema,\n\tFlowMicrousdSchema,\n\ttype FlowModelRef,\n\tFlowModelRefSchema,\n\tFlowPositiveIntSchema,\n\tFlowTimestampSchema,\n\thasDuplicateModels,\n\tlit,\n\tparseFlowData,\n\tpartialByRole,\n\tStrictObject,\n\tverifyFlowDigest,\n} from \"./flow-common.ts\";\n\nexport { FlowProfileRefSchema, type FlowProfileRefV1 } from \"./flow-common.ts\";\n\nexport const FlowEffortSchema = Type.Union([Type.Literal(\"low\"), Type.Literal(\"medium\"), Type.Literal(\"high\")]);\n\nexport const FlowRoleBindingSchema = StrictObject({\n\tprimary: FlowModelRefSchema,\n\tbackups: Type.Array(FlowModelRefSchema, { maxItems: 8 }),\n\teffort: FlowEffortSchema,\n});\nexport type FlowRoleBindingV1 = Static<typeof FlowRoleBindingSchema>;\n\n/** Cost tiers a selection may declare (matches Flow's `Tier`). */\nexport const FLOW_MODEL_SELECTION_TIERS = [\"cheap\", \"mid\", \"premium\", \"frontier\"] as const;\nexport type FlowSelectionTier = (typeof FLOW_MODEL_SELECTION_TIERS)[number];\n\n/** Flow's `ALL_CAPABILITIES` (method.json) plus the runtime `triage` capability; parity is pinned in the flow tests. */\nexport const FLOW_MODEL_SELECTION_CAPABILITIES = [\n\t\"scout\",\n\t\"scope_scout\",\n\t\"worker\",\n\t\"implementation_fast\",\n\t\"analysis_mid\",\n\t\"technical_lead\",\n\t\"lead_small\",\n\t\"lead\",\n\t\"lead_large\",\n\t\"implementation_strong\",\n\t\"technical_review\",\n\t\"integration_review\",\n\t\"migration_review\",\n\t\"performance_review\",\n\t\"api_contract_review\",\n\t\"qa_agent\",\n\t\"analysis_strong\",\n\t\"architect\",\n\t\"security_review\",\n\t\"triage\",\n] as const;\nexport type FlowSelectionCapability = (typeof FLOW_MODEL_SELECTION_CAPABILITIES)[number];\n\nexport const FlowSelectionEffortSchema = lit(\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\");\n\n/** Omitted `backups` inherits; an explicit `[]` means no fallbacks. Both must survive round-trips. */\nexport const FlowTierSelectionSchema = StrictObject({\n\tprimary: Type.Optional(FlowModelRefSchema),\n\tbackups: Type.Optional(Type.Array(FlowModelRefSchema, { maxItems: 8 })),\n});\nexport type FlowTierSelectionV1 = Static<typeof FlowTierSelectionSchema>;\n\nexport const FlowCapabilitySelectionSchema = StrictObject({\n\tprimary: Type.Optional(FlowModelRefSchema),\n\tbackups: Type.Optional(Type.Array(FlowModelRefSchema, { maxItems: 8 })),\n\teffort: Type.Optional(FlowSelectionEffortSchema),\n});\nexport type FlowCapabilitySelectionV1 = Static<typeof FlowCapabilitySelectionSchema>;\n\nconst optionalEach = <T extends TSchema>(keys: readonly string[], schema: T) =>\n\tStrictObject(Object.fromEntries(keys.map((key) => [key, Type.Optional(schema)])));\n\nexport const FlowModelSelectionSchema = StrictObject({\n\ttiers: Type.Optional(\n\t\toptionalEach(FLOW_MODEL_SELECTION_TIERS, FlowTierSelectionSchema) as TObject<\n\t\t\tRecord<FlowSelectionTier, TOptional<typeof FlowTierSelectionSchema>>\n\t\t>,\n\t),\n\tcapabilities: Type.Optional(\n\t\toptionalEach(FLOW_MODEL_SELECTION_CAPABILITIES, FlowCapabilitySelectionSchema) as TObject<\n\t\t\tRecord<FlowSelectionCapability, TOptional<typeof FlowCapabilitySelectionSchema>>\n\t\t>,\n\t),\n});\nexport type FlowModelSelectionV1 = Static<typeof FlowModelSelectionSchema>;\n\nexport const FlowProfileV1Schema = StrictObject({\n\tschema: Type.Literal(\"humain-flow-profile\"),\n\tschemaVersion: Type.Literal(1),\n\tid: FlowIdSchema,\n\tversion: FlowPositiveIntSchema,\n\tdigest: FlowDigestSchema,\n\tkind: Type.Union([Type.Literal(\"direct\"), Type.Literal(\"flow\")]),\n\tlabel: Type.String({ minLength: 1, maxLength: 80 }),\n\tdescription: Type.Optional(Type.String({ maxLength: 500 })),\n\tdirect: Type.Optional(\n\t\tStrictObject({ model: FlowModelRefSchema, fallbacks: Type.Array(FlowModelRefSchema, { maxItems: 8 }) }),\n\t),\n\troles: Type.Optional(partialByRole(FlowRoleBindingSchema)),\n\tsizing: Type.Optional(\n\t\tStrictObject({\n\t\t\tclassifierPolicyId: FlowIdSchema,\n\t\t\tthresholds: StrictObject({\n\t\t\t\tmediumAt: Type.Number({ minimum: 0, maximum: 1_000_000 }),\n\t\t\t\tlargeAt: Type.Number({ minimum: 0, maximum: 1_000_000 }),\n\t\t\t}),\n\t\t\ttriageRole: Type.Literal(\"triage\"),\n\t\t\tmaxEscalations: Type.Union([Type.Literal(0), Type.Literal(1)]),\n\t\t}),\n\t),\n\tlimits: StrictObject({\n\t\tmaxAgents: Type.Integer({ minimum: 1, maximum: 256 }),\n\t\tmaxConcurrent: Type.Integer({ minimum: 1, maximum: 64 }),\n\t\tmaxDepth: Type.Integer({ minimum: 0, maximum: 3 }),\n\t\tmaxRetries: Type.Integer({ minimum: 0, maximum: 16 }),\n\t\tinactivityMs: Type.Integer({ minimum: 1, maximum: 86_400_000 }),\n\t\tciWaitMs: Type.Integer({ minimum: 0, maximum: 86_400_000 }),\n\t}),\n\tspend: StrictObject({\n\t\trunCapMicrousd: FlowMicrousdSchema,\n\t\twarnAtPct: Type.Integer({ minimum: 1, maximum: 99 }),\n\t\tperRoleCapMicrousd: Type.Optional(partialByRole(FlowMicrousdSchema)),\n\t}),\n\tmodelSelection: Type.Optional(FlowModelSelectionSchema),\n\tproviders: Type.Optional(StrictObject({ preference: Type.Array(FlowIdSchema, { maxItems: 16 }) })),\n\tapproval: Type.Optional(StrictObject({ approvedBy: FlowIdSchema, approvedAt: FlowTimestampSchema })),\n\tbuiltIn: Type.Optional(Type.Literal(true)),\n});\nexport type FlowProfileV1 = Static<typeof FlowProfileV1Schema>;\n\nconst Validator = compileFlow(FlowProfileV1Schema);\nconst REQUIRED_FLOW_ROLES = [\"lead\", \"worker\", \"reviewer\", \"qa\"] as const;\n\n/** Canonical text hashed (sha256 hex) to produce `digest`: the document without `digest`. */\nexport function flowProfileDigestInput(doc: FlowProfileV1): string {\n\treturn canonicalWithout(doc, \"digest\");\n}\n\nfunction selectionLayerValid(layer: FlowTierSelectionV1 | FlowCapabilitySelectionV1): boolean {\n\tconst refs = [...(layer.primary === undefined ? [] : [layer.primary]), ...(layer.backups ?? [])];\n\treturn !hasDuplicateModels(refs);\n}\n\nfunction modelSelectionValid(selection: FlowModelSelectionV1): boolean {\n\tconst layers = [...Object.values(selection.tiers ?? {}), ...Object.values(selection.capabilities ?? {})];\n\treturn layers.every(selectionLayerValid);\n}\n\nfunction crossFieldsValid(doc: FlowProfileV1): boolean {\n\tif (doc.modelSelection !== undefined && (doc.kind === \"direct\" || !modelSelectionValid(doc.modelSelection))) {\n\t\treturn false;\n\t}\n\tif (doc.kind === \"direct\") {\n\t\tif (doc.direct === undefined || doc.roles !== undefined || doc.sizing !== undefined) return false;\n\t\treturn !hasDuplicateModels([doc.direct.model, ...doc.direct.fallbacks]);\n\t}\n\tif (doc.direct !== undefined || doc.roles === undefined) return false;\n\tfor (const role of REQUIRED_FLOW_ROLES) if (doc.roles[role] === undefined) return false;\n\tfor (const binding of Object.values(doc.roles)) {\n\t\tconst refs: FlowModelRef[] = [binding.primary, ...binding.backups];\n\t\tif (hasDuplicateModels(refs)) return false;\n\t}\n\treturn doc.sizing === undefined || doc.sizing.thresholds.mediumAt <= doc.sizing.thresholds.largeAt;\n}\n\nfunction isProfile(value: unknown): value is FlowProfileV1 {\n\treturn Validator.Check(value) && crossFieldsValid(value);\n}\n\n/**\n * SHAPE ONLY: validates structure and cross-field rules but does NOT verify `digest`. Use only for documents whose\n * integrity is established elsewhere (e.g. authored drafts); prefer {@link parseFlowProfileV1}.\n */\nexport function parseFlowProfileV1Shape(input: unknown): FlowProfileV1 {\n\treturn parseFlowData(\"profile_invalid\", input, isProfile);\n}\n\n/** Shape validation plus digest verification with the injected hasher (digests are integrity, not authentication). */\nexport function parseFlowProfileV1(input: unknown, hasher: FlowDigestHasher): FlowProfileV1 {\n\tconst profile = parseFlowProfileV1Shape(input);\n\tif (!verifyFlowDigest(hasher, flowProfileDigestInput(profile), profile.digest)) {\n\t\tthrow new FlowContractError(\"digest_mismatch\");\n\t}\n\treturn profile;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@humain/humain-code-contracts",
3
- "version": "0.4.9",
3
+ "version": "0.4.10",
4
4
  "private": false,
5
5
  "description": "Runtime-neutral HUMAIN Code CLI execution and RPC wire contracts",
6
6
  "type": "module",