@usefragments/core 1.11.0 → 2.0.0

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.
Files changed (39) hide show
  1. package/dist/{chunk-RPSEABY3.js → chunk-BMPYIUZE.js} +23 -33
  2. package/dist/chunk-BMPYIUZE.js.map +1 -0
  3. package/dist/{chunk-3LLRNCPX.js → chunk-MZ2FS7U4.js} +1 -1
  4. package/dist/chunk-MZ2FS7U4.js.map +1 -0
  5. package/dist/codes/index.d.ts +1 -1
  6. package/dist/codes/index.js +1 -1
  7. package/dist/compiled-types/index.d.ts +1 -1
  8. package/dist/generate/index.d.ts +1 -1
  9. package/dist/{governance-BAsy1k2H.d.ts → governance-hOPXGbbs.d.ts} +3 -3
  10. package/dist/index.d.ts +133 -6026
  11. package/dist/index.js +179 -806
  12. package/dist/index.js.map +1 -1
  13. package/dist/preview-runtime.d.ts +1 -1
  14. package/dist/react-types.d.ts +1 -1
  15. package/dist/schemas/index.js +1 -1
  16. package/dist/storyAdapter.d.ts +1 -1
  17. package/dist/test-utils.d.ts +1 -1
  18. package/dist/topology/index.d.ts +1 -1
  19. package/dist/topology/index.js +1 -1
  20. package/package.json +1 -1
  21. package/src/approved-contract-tokens.test.ts +39 -0
  22. package/src/approved-contract-tokens.ts +18 -0
  23. package/src/codes/__tests__/codes.test.ts +4 -0
  24. package/src/codes/codes.ts +10 -0
  25. package/src/domain-ids.test.ts +9 -26
  26. package/src/domain-ids.ts +0 -45
  27. package/src/evaluation/evaluate.ts +17 -7
  28. package/src/evaluation/evaluation-v2-receipt-v1.test.ts +20 -8
  29. package/src/evaluation/index.ts +1 -1
  30. package/src/governance.ts +18 -0
  31. package/src/index.ts +10 -79
  32. package/src/topology/resolve-area.ts +1 -1
  33. package/src/types.ts +0 -3
  34. package/dist/chunk-3LLRNCPX.js.map +0 -1
  35. package/dist/chunk-RPSEABY3.js.map +0 -1
  36. package/src/feature-plan/digest.ts +0 -217
  37. package/src/feature-plan/feature-plan-v1.test.ts +0 -529
  38. package/src/feature-plan/index.ts +0 -65
  39. package/src/feature-plan/types.ts +0 -628
@@ -1,628 +0,0 @@
1
- import { z } from "zod";
2
- import {
3
- digestHexStringSchema,
4
- featurePlanIdStringSchema,
5
- featureRevisionIdStringSchema,
6
- type FeaturePlanId,
7
- type FeatureRevisionId,
8
- } from "../domain-ids.js";
9
-
10
- export const FEATURE_PLAN_MAX_EVIDENCE_REFS_V1 = 200;
11
- export const FEATURE_PLAN_MAX_USES_PER_KIND_V1 = 100;
12
- export const FEATURE_PLAN_MAX_GAPS_V1 = 50;
13
- export const FEATURE_PLAN_MAX_DECISIONS_V1 = 50;
14
- export const FEATURE_PLAN_MAX_SCENARIOS_V1 = 50;
15
- export const FEATURE_PLAN_MAX_ACCEPTANCE_ITEMS_V1 = 100;
16
- export const FEATURE_PLAN_MAX_TEXT_BYTES_V1 = 32 * 1024;
17
- export const AGENT_FEATURE_CONTEXT_MAX_BYTES_V1 = 64 * 1024;
18
-
19
- const utf8Length = (value: string): number => new TextEncoder().encode(value).byteLength;
20
- const boundedString = (maxBytes = FEATURE_PLAN_MAX_TEXT_BYTES_V1) =>
21
- z
22
- .string()
23
- .min(1)
24
- .refine((value) => utf8Length(value) <= maxBytes, `Value exceeds ${maxBytes} UTF-8 bytes`);
25
- const shortString = () => boundedString(4_096);
26
- const unique = (values: readonly string[]): boolean => new Set(values).size === values.length;
27
- const uniqueIdArray = (max = FEATURE_PLAN_MAX_EVIDENCE_REFS_V1) =>
28
- z.array(shortString()).max(max).refine(unique, "ID references must be unique");
29
-
30
- export const evidenceRefV1Schema = z
31
- .object({
32
- evidenceId: shortString(),
33
- kind: z.enum(["user_intent", "image", "source", "contract", "pattern", "model"]),
34
- authority: z.enum(["user_asserted", "source_observed", "contract_approved", "model_inferred"]),
35
- ref: boundedString(),
36
- digest: digestHexStringSchema,
37
- })
38
- .strict();
39
-
40
- export const placementDecisionV1Schema = z
41
- .object({
42
- targetKind: z.enum(["page", "section"]),
43
- targetRef: shortString(),
44
- routeRef: shortString().optional(),
45
- parentSlotRef: shortString(),
46
- evidenceRefIds: uniqueIdArray(),
47
- })
48
- .strict();
49
-
50
- const propValueSchema = z.union([boundedString(), z.number().finite(), z.boolean(), z.null()]);
51
- export const componentUseDecisionV1Schema = z
52
- .object({
53
- useId: shortString(),
54
- componentId: shortString(),
55
- importPath: shortString(),
56
- purpose: boundedString(),
57
- props: z
58
- .record(shortString(), propValueSchema)
59
- .refine((props) => Object.keys(props).length <= 100, "Component props exceed V1 limit"),
60
- evidenceRefIds: uniqueIdArray(),
61
- })
62
- .strict();
63
-
64
- export const tokenUseDecisionV1Schema = z
65
- .object({
66
- useId: shortString(),
67
- tokenId: shortString(),
68
- role: shortString(),
69
- evidenceRefIds: uniqueIdArray(),
70
- })
71
- .strict();
72
-
73
- export const patternStatusV1Schema = z.enum([
74
- "observed",
75
- "candidate",
76
- "approved_guidance",
77
- "contract_canonical",
78
- "deprecated",
79
- ]);
80
- export const patternUseDecisionV1Schema = z
81
- .object({
82
- useId: shortString(),
83
- patternId: shortString(),
84
- patternRevisionDigest: digestHexStringSchema,
85
- status: patternStatusV1Schema,
86
- disposition: z.enum(["reuse", "reference", "reject"]),
87
- evidenceRefIds: uniqueIdArray(),
88
- })
89
- .strict()
90
- .superRefine((pattern, context) => {
91
- if (
92
- pattern.disposition === "reuse" &&
93
- pattern.status !== "approved_guidance" &&
94
- pattern.status !== "contract_canonical"
95
- ) {
96
- context.addIssue({
97
- code: z.ZodIssueCode.custom,
98
- path: ["disposition"],
99
- message: "Only approved-guidance or contract-canonical patterns may be reused",
100
- });
101
- }
102
- });
103
-
104
- export const layoutConcernV1Schema = z.enum([
105
- "outer_inline_spacing",
106
- "outer_block_spacing",
107
- "inner_padding",
108
- "child_gap",
109
- "max_inline_size",
110
- "scroll_x",
111
- "scroll_y",
112
- "sticky_offset",
113
- "breakpoint_switching",
114
- ]);
115
- const layoutConcernOwnerV1Schema = z
116
- .object({
117
- concern: layoutConcernV1Schema,
118
- ownerLayer: z.enum([
119
- "application_shell",
120
- "route_shell",
121
- "page",
122
- "section",
123
- "pattern",
124
- "primitive",
125
- ]),
126
- ownerRef: shortString(),
127
- childAction: z.enum(["consume", "own", "override"]),
128
- tokenRef: shortString().optional(),
129
- breakpointRef: shortString().optional(),
130
- evidenceRefIds: uniqueIdArray(),
131
- overrideDecisionId: shortString().optional(),
132
- })
133
- .strict()
134
- .superRefine((row, context) => {
135
- if (row.childAction === "override" && !row.overrideDecisionId) {
136
- context.addIssue({
137
- code: z.ZodIssueCode.custom,
138
- path: ["overrideDecisionId"],
139
- message: "A layout override must reference an approved decision",
140
- });
141
- }
142
- if (row.childAction !== "override" && row.overrideDecisionId) {
143
- context.addIssue({
144
- code: z.ZodIssueCode.custom,
145
- path: ["overrideDecisionId"],
146
- message: "Only an override may reference an override decision",
147
- });
148
- }
149
- });
150
- export const layoutOwnershipV1Schema = z
151
- .object({
152
- concerns: z
153
- .array(layoutConcernOwnerV1Schema)
154
- .max(32)
155
- .refine(
156
- (rows) => new Set(rows.map((row) => row.concern)).size === rows.length,
157
- "Each layout concern must have exactly one owner"
158
- ),
159
- })
160
- .strict();
161
-
162
- export const responsiveDecisionV1Schema = z
163
- .object({
164
- decisionId: shortString(),
165
- source: z.enum(["contract", "observed", "desktop_only"]),
166
- breakpointRef: shortString().optional(),
167
- behavior: boundedString(),
168
- evidenceRefIds: uniqueIdArray(),
169
- })
170
- .strict()
171
- .superRefine((decision, context) => {
172
- if (decision.source !== "desktop_only" && !decision.breakpointRef) {
173
- context.addIssue({
174
- code: z.ZodIssueCode.custom,
175
- path: ["breakpointRef"],
176
- message: "Responsive contract/observed decisions must pin a breakpoint",
177
- });
178
- }
179
- });
180
-
181
- export const scenarioRequirementV1Schema = z
182
- .object({
183
- scenarioId: shortString(),
184
- viewportRef: shortString().optional(),
185
- themeRef: shortString().optional(),
186
- actorRole: shortString().optional(),
187
- dataState: z.enum(["default", "loading", "empty", "partial", "error"]),
188
- interactionState: z
189
- .enum(["pristine", "dirty", "validating", "saving", "saved", "disabled"])
190
- .optional(),
191
- acceptanceIds: uniqueIdArray(FEATURE_PLAN_MAX_ACCEPTANCE_ITEMS_V1),
192
- })
193
- .strict();
194
-
195
- export const gapDispositionV1Schema = z.enum([
196
- "canonical_reuse",
197
- "approved_pattern",
198
- "local_composition",
199
- "intentional_one_off",
200
- "proposed_contract_addition",
201
- "unresolved",
202
- ]);
203
- export const capabilityGapV1Schema = z
204
- .object({
205
- gapId: shortString(),
206
- capability: boundedString(),
207
- required: z.boolean(),
208
- disposition: gapDispositionV1Schema,
209
- reason: boundedString(),
210
- evidenceRefIds: uniqueIdArray(),
211
- proposedContractCandidateId: shortString().optional(),
212
- })
213
- .strict()
214
- .superRefine((gap, context) => {
215
- if (gap.disposition === "proposed_contract_addition" && !gap.proposedContractCandidateId) {
216
- context.addIssue({
217
- code: z.ZodIssueCode.custom,
218
- path: ["proposedContractCandidateId"],
219
- message: "A proposed contract addition must pin its candidate",
220
- });
221
- }
222
- if (gap.disposition !== "proposed_contract_addition" && gap.proposedContractCandidateId) {
223
- context.addIssue({
224
- code: z.ZodIssueCode.custom,
225
- path: ["proposedContractCandidateId"],
226
- message: "Only a proposed contract addition may carry a candidate ID",
227
- });
228
- }
229
- });
230
-
231
- export const featureAcceptanceItemV1Schema = z
232
- .object({
233
- acceptanceId: shortString(),
234
- statement: boundedString(),
235
- proof: z.enum(["unit", "integration", "browser", "governance", "manual"]),
236
- required: z.boolean(),
237
- evidenceRefIds: uniqueIdArray(),
238
- })
239
- .strict();
240
-
241
- const decisionOptionV1Schema = z
242
- .object({ optionId: shortString(), label: boundedString(), consequence: boundedString() })
243
- .strict();
244
- export const decisionRequestV1Schema = z
245
- .object({
246
- decisionId: shortString(),
247
- kind: z.enum(["placement", "reuse", "gap", "layout_override", "responsive", "scope"]),
248
- question: boundedString(),
249
- options: z
250
- .array(decisionOptionV1Schema)
251
- .min(2)
252
- .max(20)
253
- .refine(
254
- (options) => new Set(options.map((option) => option.optionId)).size === options.length,
255
- "Decision option IDs must be unique"
256
- ),
257
- recommendedOptionId: shortString().optional(),
258
- required: z.boolean(),
259
- evidenceRefIds: uniqueIdArray(),
260
- })
261
- .strict()
262
- .superRefine((decision, context) => {
263
- if (
264
- decision.recommendedOptionId &&
265
- !decision.options.some((option) => option.optionId === decision.recommendedOptionId)
266
- ) {
267
- context.addIssue({
268
- code: z.ZodIssueCode.custom,
269
- path: ["recommendedOptionId"],
270
- message: "Recommended option must resolve inside the decision",
271
- });
272
- }
273
- });
274
-
275
- export const decisionResolutionV1Schema = z
276
- .object({ decisionId: shortString(), selectedOptionId: shortString() })
277
- .strict();
278
-
279
- export const featurePinsV1Schema = z
280
- .object({
281
- bindingId: shortString(),
282
- grounding: z
283
- .object({
284
- sourceCommitId: shortString(),
285
- analysisPlanDigest: digestHexStringSchema,
286
- contextSliceDigest: digestHexStringSchema,
287
- })
288
- .strict(),
289
- authority: z
290
- .object({
291
- fcid: digestHexStringSchema,
292
- contractArtifactDigest: digestHexStringSchema,
293
- analysisObligationsDigest: digestHexStringSchema,
294
- })
295
- .strict(),
296
- evidenceDigest: digestHexStringSchema,
297
- })
298
- .strict();
299
-
300
- const commonRevisionShape = {
301
- pins: featurePinsV1Schema,
302
- placement: placementDecisionV1Schema,
303
- componentUses: z.array(componentUseDecisionV1Schema).max(FEATURE_PLAN_MAX_USES_PER_KIND_V1),
304
- tokenUses: z.array(tokenUseDecisionV1Schema).max(FEATURE_PLAN_MAX_USES_PER_KIND_V1),
305
- patternUses: z.array(patternUseDecisionV1Schema).max(FEATURE_PLAN_MAX_USES_PER_KIND_V1),
306
- layout: layoutOwnershipV1Schema,
307
- responsive: z.array(responsiveDecisionV1Schema).max(FEATURE_PLAN_MAX_DECISIONS_V1),
308
- scenarios: z.array(scenarioRequirementV1Schema).max(FEATURE_PLAN_MAX_SCENARIOS_V1),
309
- gaps: z.array(capabilityGapV1Schema).max(FEATURE_PLAN_MAX_GAPS_V1),
310
- acceptance: z.array(featureAcceptanceItemV1Schema).max(FEATURE_PLAN_MAX_ACCEPTANCE_ITEMS_V1),
311
- evidenceRefs: z.array(evidenceRefV1Schema).max(FEATURE_PLAN_MAX_EVIDENCE_REFS_V1),
312
- };
313
-
314
- function addUniqueIdIssue(
315
- rows: readonly Record<string, unknown>[],
316
- key: string,
317
- path: string,
318
- context: z.RefinementCtx
319
- ): void {
320
- const values = rows
321
- .map((row) => row[key])
322
- .filter((value): value is string => typeof value === "string");
323
- if (new Set(values).size !== values.length) {
324
- context.addIssue({
325
- code: z.ZodIssueCode.custom,
326
- path: [path],
327
- message: `${path} IDs must be unique`,
328
- });
329
- }
330
- }
331
-
332
- type CommonGraph = z.infer<z.ZodObject<typeof commonRevisionShape>>;
333
-
334
- function validateCommonGraph(
335
- graph: CommonGraph,
336
- context: z.RefinementCtx,
337
- decisionIds: ReadonlySet<string>
338
- ): void {
339
- addUniqueIdIssue(graph.evidenceRefs, "evidenceId", "evidenceRefs", context);
340
- addUniqueIdIssue(graph.componentUses, "useId", "componentUses", context);
341
- addUniqueIdIssue(graph.tokenUses, "useId", "tokenUses", context);
342
- addUniqueIdIssue(graph.patternUses, "useId", "patternUses", context);
343
- addUniqueIdIssue(graph.responsive, "decisionId", "responsive", context);
344
- addUniqueIdIssue(graph.scenarios, "scenarioId", "scenarios", context);
345
- addUniqueIdIssue(graph.gaps, "gapId", "gaps", context);
346
- addUniqueIdIssue(graph.acceptance, "acceptanceId", "acceptance", context);
347
-
348
- const evidenceIds = new Set(graph.evidenceRefs.map((evidence) => evidence.evidenceId));
349
- const acceptanceIds = new Set(graph.acceptance.map((acceptance) => acceptance.acceptanceId));
350
- const evidenceReferences: Array<readonly [readonly string[], string]> = [
351
- [graph.placement.evidenceRefIds, "placement.evidenceRefIds"],
352
- ...graph.componentUses.map(
353
- (row, index) => [row.evidenceRefIds, `componentUses.${index}.evidenceRefIds`] as const
354
- ),
355
- ...graph.tokenUses.map(
356
- (row, index) => [row.evidenceRefIds, `tokenUses.${index}.evidenceRefIds`] as const
357
- ),
358
- ...graph.patternUses.map(
359
- (row, index) => [row.evidenceRefIds, `patternUses.${index}.evidenceRefIds`] as const
360
- ),
361
- ...graph.layout.concerns.map(
362
- (row, index) => [row.evidenceRefIds, `layout.concerns.${index}.evidenceRefIds`] as const
363
- ),
364
- ...graph.responsive.map(
365
- (row, index) => [row.evidenceRefIds, `responsive.${index}.evidenceRefIds`] as const
366
- ),
367
- ...graph.gaps.map(
368
- (row, index) => [row.evidenceRefIds, `gaps.${index}.evidenceRefIds`] as const
369
- ),
370
- ...graph.acceptance.map(
371
- (row, index) => [row.evidenceRefIds, `acceptance.${index}.evidenceRefIds`] as const
372
- ),
373
- ];
374
- for (const [references, path] of evidenceReferences) {
375
- for (const reference of references) {
376
- if (!evidenceIds.has(reference)) {
377
- context.addIssue({
378
- code: z.ZodIssueCode.custom,
379
- path: path.split("."),
380
- message: `Unknown evidence reference: ${reference}`,
381
- });
382
- }
383
- }
384
- }
385
- for (const [index, scenario] of graph.scenarios.entries()) {
386
- for (const acceptanceId of scenario.acceptanceIds) {
387
- if (!acceptanceIds.has(acceptanceId)) {
388
- context.addIssue({
389
- code: z.ZodIssueCode.custom,
390
- path: ["scenarios", index, "acceptanceIds"],
391
- message: `Unknown acceptance reference: ${acceptanceId}`,
392
- });
393
- }
394
- }
395
- }
396
- for (const [index, row] of graph.layout.concerns.entries()) {
397
- if (row.overrideDecisionId && !decisionIds.has(row.overrideDecisionId)) {
398
- context.addIssue({
399
- code: z.ZodIssueCode.custom,
400
- path: ["layout", "concerns", index, "overrideDecisionId"],
401
- message: `Unknown decision reference: ${row.overrideDecisionId}`,
402
- });
403
- }
404
- }
405
- }
406
-
407
- const proposalInputShape = {
408
- schemaVersion: z.literal(1),
409
- kind: z.literal("proposal"),
410
- planId: featurePlanIdStringSchema,
411
- parentRevisionDigest: digestHexStringSchema.optional(),
412
- ...commonRevisionShape,
413
- questions: z.array(decisionRequestV1Schema).max(FEATURE_PLAN_MAX_DECISIONS_V1),
414
- };
415
-
416
- function validateProposal(
417
- proposal: z.infer<z.ZodObject<typeof proposalInputShape>>,
418
- context: z.RefinementCtx
419
- ): void {
420
- addUniqueIdIssue(proposal.questions, "decisionId", "questions", context);
421
- const decisionIds = new Set(proposal.questions.map((question) => question.decisionId));
422
- validateCommonGraph(proposal, context, decisionIds);
423
- const evidenceIds = new Set(proposal.evidenceRefs.map((evidence) => evidence.evidenceId));
424
- for (const [index, question] of proposal.questions.entries()) {
425
- for (const reference of question.evidenceRefIds) {
426
- if (!evidenceIds.has(reference)) {
427
- context.addIssue({
428
- code: z.ZodIssueCode.custom,
429
- path: ["questions", index, "evidenceRefIds"],
430
- message: `Unknown evidence reference: ${reference}`,
431
- });
432
- }
433
- }
434
- }
435
- }
436
-
437
- export const featureProposalInputV1Schema = z
438
- .object(proposalInputShape)
439
- .strict()
440
- .superRefine(validateProposal);
441
-
442
- export const featureProposalV1Schema = z
443
- .object({
444
- ...proposalInputShape,
445
- revisionId: featureRevisionIdStringSchema,
446
- revisionDigest: digestHexStringSchema,
447
- })
448
- .strict()
449
- .superRefine(validateProposal);
450
-
451
- const manifestInputShape = {
452
- schemaVersion: z.literal(1),
453
- kind: z.literal("approved_manifest"),
454
- planId: featurePlanIdStringSchema,
455
- parentRevisionDigest: digestHexStringSchema,
456
- proposalRevisionDigest: digestHexStringSchema,
457
- ...commonRevisionShape,
458
- validatedGrounding: z
459
- .object({
460
- sourceCommitId: shortString(),
461
- analysisPlanDigest: digestHexStringSchema,
462
- contextSliceDigest: digestHexStringSchema,
463
- })
464
- .strict(),
465
- decisions: z.array(decisionResolutionV1Schema).max(FEATURE_PLAN_MAX_DECISIONS_V1),
466
- approval: z
467
- .object({
468
- approverUserId: shortString(),
469
- decisionDigest: digestHexStringSchema,
470
- approvedAt: z.string().datetime({ offset: true }),
471
- expiresAt: z.string().datetime({ offset: true }).optional(),
472
- })
473
- .strict(),
474
- };
475
-
476
- const portableRepositoryPathSchema = shortString().refine(
477
- (value) => !value.startsWith("/") && !value.includes("\\") && !value.split("/").includes(".."),
478
- "Expected a portable repository-relative path"
479
- );
480
-
481
- function validateManifest(
482
- manifest: z.infer<z.ZodObject<typeof manifestInputShape>>,
483
- context: z.RefinementCtx
484
- ): void {
485
- addUniqueIdIssue(manifest.decisions, "decisionId", "decisions", context);
486
- validateCommonGraph(manifest, context, new Set(manifest.decisions.map((row) => row.decisionId)));
487
- if (
488
- manifest.validatedGrounding.contextSliceDigest !== manifest.pins.grounding.contextSliceDigest
489
- ) {
490
- context.addIssue({
491
- code: z.ZodIssueCode.custom,
492
- path: ["validatedGrounding", "contextSliceDigest"],
493
- message: "Validated material context must match the pinned proposal context",
494
- });
495
- }
496
- for (const [index, gap] of manifest.gaps.entries()) {
497
- if (
498
- gap.required &&
499
- (gap.disposition === "unresolved" || gap.disposition === "proposed_contract_addition")
500
- ) {
501
- context.addIssue({
502
- code: z.ZodIssueCode.custom,
503
- path: ["gaps", index, "disposition"],
504
- message:
505
- "A required unresolved or proposed-contract gap blocks approval until it is resolved",
506
- });
507
- }
508
- }
509
- }
510
-
511
- export const approvedFeatureManifestInputV1Schema = z
512
- .object(manifestInputShape)
513
- .strict()
514
- .superRefine(validateManifest);
515
-
516
- export const approvedFeatureManifestV1Schema = z
517
- .object({
518
- ...manifestInputShape,
519
- revisionId: featureRevisionIdStringSchema,
520
- revisionDigest: digestHexStringSchema,
521
- })
522
- .strict()
523
- .superRefine(validateManifest);
524
-
525
- export const agentFeatureContextV1Schema = z
526
- .object({
527
- schemaVersion: z.literal(1),
528
- planId: featurePlanIdStringSchema,
529
- manifestDigest: digestHexStringSchema,
530
- pins: featurePinsV1Schema,
531
- validatedGrounding: manifestInputShape.validatedGrounding,
532
- target: placementDecisionV1Schema,
533
- componentUses: commonRevisionShape.componentUses,
534
- tokenUses: commonRevisionShape.tokenUses,
535
- patternUses: commonRevisionShape.patternUses,
536
- layout: layoutOwnershipV1Schema,
537
- responsive: commonRevisionShape.responsive,
538
- scenarios: commonRevisionShape.scenarios,
539
- acceptedGaps: commonRevisionShape.gaps,
540
- acceptance: commonRevisionShape.acceptance,
541
- decisions: manifestInputShape.decisions,
542
- relevantFiles: z
543
- .array(portableRepositoryPathSchema)
544
- .max(500)
545
- .refine(unique, "relevantFiles must be unique"),
546
- commands: z.array(boundedString()).max(100),
547
- })
548
- .strict()
549
- .superRefine((contextValue, context) => {
550
- const graph = {
551
- pins: contextValue.pins,
552
- placement: contextValue.target,
553
- componentUses: contextValue.componentUses,
554
- tokenUses: contextValue.tokenUses,
555
- patternUses: contextValue.patternUses,
556
- layout: contextValue.layout,
557
- responsive: contextValue.responsive,
558
- scenarios: contextValue.scenarios,
559
- gaps: contextValue.acceptedGaps,
560
- acceptance: contextValue.acceptance,
561
- evidenceRefs: [],
562
- };
563
- // Evidence bodies are deliberately absent from the bounded agent projection,
564
- // so validate decision/acceptance/layout identity here and evidence links at
565
- // manifest construction time.
566
- addUniqueIdIssue(contextValue.decisions, "decisionId", "decisions", context);
567
- addUniqueIdIssue(graph.componentUses, "useId", "componentUses", context);
568
- addUniqueIdIssue(graph.tokenUses, "useId", "tokenUses", context);
569
- addUniqueIdIssue(graph.patternUses, "useId", "patternUses", context);
570
- addUniqueIdIssue(graph.scenarios, "scenarioId", "scenarios", context);
571
- addUniqueIdIssue(graph.acceptance, "acceptanceId", "acceptance", context);
572
- const decisions = new Set(contextValue.decisions.map((row) => row.decisionId));
573
- for (const [index, row] of contextValue.layout.concerns.entries()) {
574
- if (row.overrideDecisionId && !decisions.has(row.overrideDecisionId)) {
575
- context.addIssue({
576
- code: z.ZodIssueCode.custom,
577
- path: ["layout", "concerns", index, "overrideDecisionId"],
578
- message: `Unknown decision reference: ${row.overrideDecisionId}`,
579
- });
580
- }
581
- }
582
- for (const [index, gap] of contextValue.acceptedGaps.entries()) {
583
- if (
584
- gap.required &&
585
- (gap.disposition === "unresolved" || gap.disposition === "proposed_contract_addition")
586
- ) {
587
- context.addIssue({
588
- code: z.ZodIssueCode.custom,
589
- path: ["acceptedGaps", index],
590
- message: "Agent context cannot contain a required unresolved or proposed-contract gap",
591
- });
592
- }
593
- }
594
- });
595
-
596
- export type EvidenceRefV1 = z.infer<typeof evidenceRefV1Schema>;
597
- export type PlacementDecisionV1 = z.infer<typeof placementDecisionV1Schema>;
598
- export type ComponentUseDecisionV1 = z.infer<typeof componentUseDecisionV1Schema>;
599
- export type TokenUseDecisionV1 = z.infer<typeof tokenUseDecisionV1Schema>;
600
- export type PatternStatusV1 = z.infer<typeof patternStatusV1Schema>;
601
- export type PatternUseDecisionV1 = z.infer<typeof patternUseDecisionV1Schema>;
602
- export type LayoutConcernV1 = z.infer<typeof layoutConcernV1Schema>;
603
- export type LayoutOwnershipV1 = z.infer<typeof layoutOwnershipV1Schema>;
604
- export type ResponsiveDecisionV1 = z.infer<typeof responsiveDecisionV1Schema>;
605
- export type ScenarioRequirementV1 = z.infer<typeof scenarioRequirementV1Schema>;
606
- export type GapDispositionV1 = z.infer<typeof gapDispositionV1Schema>;
607
- export type CapabilityGapV1 = z.infer<typeof capabilityGapV1Schema>;
608
- export type FeatureAcceptanceItemV1 = z.infer<typeof featureAcceptanceItemV1Schema>;
609
- export type DecisionRequestV1 = z.infer<typeof decisionRequestV1Schema>;
610
- export type DecisionResolutionV1 = z.infer<typeof decisionResolutionV1Schema>;
611
- export type FeaturePinsV1 = z.infer<typeof featurePinsV1Schema>;
612
- export type FeatureProposalInputV1 = z.input<typeof featureProposalInputV1Schema> & {
613
- planId: FeaturePlanId;
614
- };
615
- export type FeatureProposalV1 = z.output<typeof featureProposalV1Schema> & {
616
- planId: FeaturePlanId;
617
- revisionId: FeatureRevisionId;
618
- };
619
- export type ApprovedFeatureManifestInputV1 = z.input<
620
- typeof approvedFeatureManifestInputV1Schema
621
- > & { planId: FeaturePlanId };
622
- export type ApprovedFeatureManifestV1 = z.output<typeof approvedFeatureManifestV1Schema> & {
623
- planId: FeaturePlanId;
624
- revisionId: FeatureRevisionId;
625
- };
626
- export type AgentFeatureContextV1 = z.output<typeof agentFeatureContextV1Schema> & {
627
- planId: FeaturePlanId;
628
- };