@cleocode/contracts 2026.5.122 → 2026.5.124

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 (108) hide show
  1. package/dist/__tests__/completion-operation-contracts.test.d.ts +8 -0
  2. package/dist/__tests__/completion-operation-contracts.test.d.ts.map +1 -0
  3. package/dist/__tests__/completion-operation-contracts.test.js +114 -0
  4. package/dist/__tests__/completion-operation-contracts.test.js.map +1 -0
  5. package/dist/__tests__/operation-envelope-validation.test.d.ts +8 -0
  6. package/dist/__tests__/operation-envelope-validation.test.d.ts.map +1 -0
  7. package/dist/__tests__/operation-envelope-validation.test.js +105 -0
  8. package/dist/__tests__/operation-envelope-validation.test.js.map +1 -0
  9. package/dist/__tests__/satisfies-atom.test.js +21 -3
  10. package/dist/__tests__/satisfies-atom.test.js.map +1 -1
  11. package/dist/__tests__/workgraph-context-scaffold-contracts.test.d.ts +8 -0
  12. package/dist/__tests__/workgraph-context-scaffold-contracts.test.d.ts.map +1 -0
  13. package/dist/__tests__/workgraph-context-scaffold-contracts.test.js +188 -0
  14. package/dist/__tests__/workgraph-context-scaffold-contracts.test.js.map +1 -0
  15. package/dist/__tests__/workgraph-operation-contracts.test.d.ts +8 -0
  16. package/dist/__tests__/workgraph-operation-contracts.test.d.ts.map +1 -0
  17. package/dist/__tests__/workgraph-operation-contracts.test.js +115 -0
  18. package/dist/__tests__/workgraph-operation-contracts.test.js.map +1 -0
  19. package/dist/data-accessor.d.ts +77 -0
  20. package/dist/data-accessor.d.ts.map +1 -1
  21. package/dist/data-accessor.js.map +1 -1
  22. package/dist/dispatch/__tests__/docs-update-registry.test.d.ts +2 -0
  23. package/dist/dispatch/__tests__/docs-update-registry.test.d.ts.map +1 -0
  24. package/dist/dispatch/__tests__/docs-update-registry.test.js +27 -0
  25. package/dist/dispatch/__tests__/docs-update-registry.test.js.map +1 -0
  26. package/dist/dispatch/__tests__/operation-envelope-snapshots.test.d.ts +2 -0
  27. package/dist/dispatch/__tests__/operation-envelope-snapshots.test.d.ts.map +1 -0
  28. package/dist/dispatch/__tests__/operation-envelope-snapshots.test.js +271 -0
  29. package/dist/dispatch/__tests__/operation-envelope-snapshots.test.js.map +1 -0
  30. package/dist/dispatch/operations-registry.d.ts.map +1 -1
  31. package/dist/dispatch/operations-registry.js +487 -7
  32. package/dist/dispatch/operations-registry.js.map +1 -1
  33. package/dist/evidence-atom-schema.d.ts +4 -4
  34. package/dist/evidence-atom-schema.d.ts.map +1 -1
  35. package/dist/evidence-atom-schema.js +9 -9
  36. package/dist/evidence-atom-schema.js.map +1 -1
  37. package/dist/index.d.ts +12 -6
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +8 -0
  40. package/dist/index.js.map +1 -1
  41. package/dist/operation-envelope-validation.d.ts +79 -0
  42. package/dist/operation-envelope-validation.d.ts.map +1 -0
  43. package/dist/operation-envelope-validation.js +219 -0
  44. package/dist/operation-envelope-validation.js.map +1 -0
  45. package/dist/operations/__tests__/agent-operation-contract.test.d.ts +2 -0
  46. package/dist/operations/__tests__/agent-operation-contract.test.d.ts.map +1 -0
  47. package/dist/operations/__tests__/agent-operation-contract.test.js +128 -0
  48. package/dist/operations/__tests__/agent-operation-contract.test.js.map +1 -0
  49. package/dist/operations/__tests__/tasks-input-contracts.test.js +15 -0
  50. package/dist/operations/__tests__/tasks-input-contracts.test.js.map +1 -1
  51. package/dist/operations/agent-operation-contract.d.ts +227 -0
  52. package/dist/operations/agent-operation-contract.d.ts.map +1 -0
  53. package/dist/operations/agent-operation-contract.js +38 -0
  54. package/dist/operations/agent-operation-contract.js.map +1 -0
  55. package/dist/operations/docs.d.ts +19 -1
  56. package/dist/operations/docs.d.ts.map +1 -1
  57. package/dist/operations/docs.js +20 -0
  58. package/dist/operations/docs.js.map +1 -1
  59. package/dist/operations/focus.d.ts +1 -1
  60. package/dist/operations/index.d.ts +1 -0
  61. package/dist/operations/index.d.ts.map +1 -1
  62. package/dist/operations/index.js +1 -0
  63. package/dist/operations/index.js.map +1 -1
  64. package/dist/operations/orchestrate.d.ts +66 -0
  65. package/dist/operations/orchestrate.d.ts.map +1 -1
  66. package/dist/operations/tasks.d.ts +568 -11
  67. package/dist/operations/tasks.d.ts.map +1 -1
  68. package/dist/operations/tasks.js +22 -3
  69. package/dist/operations/tasks.js.map +1 -1
  70. package/dist/task-record.d.ts +15 -0
  71. package/dist/task-record.d.ts.map +1 -1
  72. package/dist/task.d.ts +15 -6
  73. package/dist/task.d.ts.map +1 -1
  74. package/dist/task.js.map +1 -1
  75. package/dist/tasks.d.ts +944 -0
  76. package/dist/tasks.d.ts.map +1 -1
  77. package/dist/tasks.js +198 -1
  78. package/dist/tasks.js.map +1 -1
  79. package/dist/workgraph.d.ts +1950 -0
  80. package/dist/workgraph.d.ts.map +1 -0
  81. package/dist/workgraph.js +449 -0
  82. package/dist/workgraph.js.map +1 -0
  83. package/package.json +10 -2
  84. package/src/__tests__/__snapshots__/operations-registry.test.ts.snap +1 -1
  85. package/src/__tests__/completion-operation-contracts.test.ts +154 -0
  86. package/src/__tests__/operation-envelope-validation.test.ts +140 -0
  87. package/src/__tests__/satisfies-atom.test.ts +23 -3
  88. package/src/__tests__/workgraph-context-scaffold-contracts.test.ts +232 -0
  89. package/src/__tests__/workgraph-operation-contracts.test.ts +151 -0
  90. package/src/data-accessor.ts +94 -1
  91. package/src/dispatch/__tests__/docs-update-registry.test.ts +35 -0
  92. package/src/dispatch/__tests__/operation-envelope-snapshots.test.ts +289 -0
  93. package/src/dispatch/operations-registry.ts +502 -7
  94. package/src/evidence-atom-schema.ts +10 -10
  95. package/src/index.ts +193 -2
  96. package/src/operation-envelope-validation.ts +319 -0
  97. package/src/operations/__tests__/agent-operation-contract.test.ts +161 -0
  98. package/src/operations/__tests__/tasks-input-contracts.test.ts +30 -0
  99. package/src/operations/agent-operation-contract.ts +253 -0
  100. package/src/operations/docs.ts +27 -7
  101. package/src/operations/focus.ts +1 -1
  102. package/src/operations/index.ts +1 -0
  103. package/src/operations/orchestrate.ts +71 -0
  104. package/src/operations/tasks.ts +612 -15
  105. package/src/task-record.ts +16 -0
  106. package/src/task.ts +16 -6
  107. package/src/tasks.ts +558 -0
  108. package/src/workgraph.ts +1153 -0
@@ -9,6 +9,7 @@
9
9
  * @since SG-ARCH-SOLID Saga T9831 · E-CLI-BOUNDARY T9833 · T10061
10
10
  */
11
11
 
12
+ import { DOCS_LIFECYCLE_STATUSES } from '../operations/docs.js';
12
13
  import type { CanonicalDomain, Gateway, OperationDef, ParamDef, Tier } from './operation-def.js';
13
14
 
14
15
  export type { CanonicalDomain, Gateway, OperationDef, ParamDef, Tier };
@@ -76,6 +77,168 @@ export const OPERATIONS: OperationDef[] = [
76
77
  required: false,
77
78
  description: 'Include IVTR phase chain history in the response',
78
79
  },
80
+ {
81
+ name: 'relations',
82
+ type: 'boolean',
83
+ required: false,
84
+ description: 'Expand relation/doc lists while preserving compact MVI counts',
85
+ },
86
+ ] satisfies ParamDef[],
87
+ },
88
+ {
89
+ gateway: 'query',
90
+ domain: 'tasks',
91
+ operation: 'traverse',
92
+ description: 'tasks.traverse (query) — WorkGraph traversal from a task root',
93
+ tier: 1,
94
+ idempotent: true,
95
+ sessionRequired: false,
96
+ requiredParams: ['rootId', 'direction'],
97
+ params: [
98
+ {
99
+ name: 'rootId',
100
+ type: 'string',
101
+ required: true,
102
+ description: 'Root task ID for the traversal',
103
+ cli: { positional: true },
104
+ },
105
+ {
106
+ name: 'direction',
107
+ type: 'string',
108
+ required: true,
109
+ description: 'Traversal direction to project from the root task',
110
+ enum: ['ancestors', 'descendants', 'upstream', 'downstream'],
111
+ },
112
+ {
113
+ name: 'maxDepth',
114
+ type: 'number',
115
+ required: false,
116
+ description: 'Maximum traversal depth to include',
117
+ },
118
+ {
119
+ name: 'includeRelations',
120
+ type: 'boolean',
121
+ required: false,
122
+ description: 'Include non-containment relation edges',
123
+ },
124
+ { name: 'cursor', type: 'string', required: false, description: 'Opaque pagination cursor' },
125
+ { name: 'limit', type: 'number', required: false, description: 'Maximum nodes to return' },
126
+ ] satisfies ParamDef[],
127
+ },
128
+ {
129
+ gateway: 'query',
130
+ domain: 'tasks',
131
+ operation: 'tree',
132
+ description: 'tasks.tree (query) — WorkGraph containment tree projection',
133
+ tier: 1,
134
+ idempotent: true,
135
+ sessionRequired: false,
136
+ requiredParams: ['rootId'],
137
+ params: [
138
+ {
139
+ name: 'rootId',
140
+ type: 'string',
141
+ required: true,
142
+ description: 'Root task ID for the tree projection',
143
+ cli: { positional: true },
144
+ },
145
+ {
146
+ name: 'maxDepth',
147
+ type: 'number',
148
+ required: false,
149
+ description: 'Maximum containment depth to include',
150
+ },
151
+ { name: 'cursor', type: 'string', required: false, description: 'Opaque pagination cursor' },
152
+ { name: 'limit', type: 'number', required: false, description: 'Maximum nodes to return' },
153
+ ] satisfies ParamDef[],
154
+ },
155
+ {
156
+ gateway: 'query',
157
+ domain: 'tasks',
158
+ operation: 'rollup',
159
+ description: 'tasks.rollup (query) — WorkGraph direct and subtree status/type summary',
160
+ tier: 1,
161
+ idempotent: true,
162
+ sessionRequired: false,
163
+ requiredParams: ['rootId'],
164
+ params: [
165
+ {
166
+ name: 'rootId',
167
+ type: 'string',
168
+ required: true,
169
+ description: 'Root task ID for the rollup',
170
+ cli: { positional: true },
171
+ },
172
+ {
173
+ name: 'expectedDirectRollup',
174
+ type: 'string',
175
+ required: false,
176
+ description: 'Optional serialized expected direct rollup for stale-projection diagnostics',
177
+ },
178
+ ] satisfies ParamDef[],
179
+ },
180
+ {
181
+ gateway: 'query',
182
+ domain: 'tasks',
183
+ operation: 'frontier',
184
+ description: 'tasks.frontier (query) — WorkGraph ready and blocked frontier under a root',
185
+ tier: 1,
186
+ idempotent: true,
187
+ sessionRequired: false,
188
+ requiredParams: ['rootId'],
189
+ params: [
190
+ {
191
+ name: 'rootId',
192
+ type: 'string',
193
+ required: true,
194
+ description: 'Root task ID for the frontier',
195
+ cli: { positional: true },
196
+ },
197
+ {
198
+ name: 'role',
199
+ type: 'string',
200
+ required: false,
201
+ description: 'Optional assignee/role lane filter',
202
+ },
203
+ ] satisfies ParamDef[],
204
+ },
205
+ {
206
+ gateway: 'query',
207
+ domain: 'tasks',
208
+ operation: 'workgraph.audit',
209
+ description:
210
+ 'tasks.workgraph.audit (query) — aggregate WorkGraph hierarchy/traversal/frontier/rollup diagnostics',
211
+ tier: 1,
212
+ idempotent: true,
213
+ sessionRequired: false,
214
+ requiredParams: ['rootId'],
215
+ params: [
216
+ {
217
+ name: 'rootId',
218
+ type: 'string',
219
+ required: true,
220
+ description: 'Root task ID for the WorkGraph audit',
221
+ cli: { positional: true },
222
+ },
223
+ {
224
+ name: 'maxDepth',
225
+ type: 'number',
226
+ required: false,
227
+ description: 'Maximum descendant depth to include in audit projections',
228
+ },
229
+ {
230
+ name: 'includeRelations',
231
+ type: 'boolean',
232
+ required: false,
233
+ description: 'Include relation-edge diagnostics in the audit result',
234
+ },
235
+ { name: 'cursor', type: 'string', required: false, description: 'Opaque pagination cursor' },
236
+ {
237
+ name: 'limit',
238
+ type: 'number',
239
+ required: false,
240
+ description: 'Maximum nodes to return in paginated audit projections',
241
+ },
79
242
  ] satisfies ParamDef[],
80
243
  },
81
244
  {
@@ -274,6 +437,152 @@ export const OPERATIONS: OperationDef[] = [
274
437
  requiredParams: [],
275
438
  params: [],
276
439
  },
440
+ {
441
+ gateway: 'query',
442
+ domain: 'tasks',
443
+ operation: 'completion.list',
444
+ description: 'tasks.completion.list (query) — list typed completion criteria results',
445
+ tier: 1,
446
+ idempotent: true,
447
+ sessionRequired: false,
448
+ requiredParams: ['taskId'],
449
+ params: [
450
+ {
451
+ name: 'taskId',
452
+ type: 'string',
453
+ required: true,
454
+ description: 'Task ID to list completion criteria for',
455
+ cli: { positional: true },
456
+ },
457
+ {
458
+ name: 'status',
459
+ type: 'string',
460
+ required: false,
461
+ description: 'Optional criterion status filter',
462
+ enum: ['satisfied', 'unsatisfied', 'waived', 'replaced'],
463
+ },
464
+ {
465
+ name: 'kind',
466
+ type: 'string',
467
+ required: false,
468
+ description: 'Optional criterion kind filter',
469
+ enum: ['text', 'evidence_bound', 'child_task'],
470
+ },
471
+ ] satisfies ParamDef[],
472
+ },
473
+ {
474
+ gateway: 'query',
475
+ domain: 'tasks',
476
+ operation: 'completion.evaluate',
477
+ description:
478
+ 'tasks.completion.evaluate (query) — evaluate completion readiness with typed AC results',
479
+ tier: 1,
480
+ idempotent: true,
481
+ sessionRequired: false,
482
+ requiredParams: ['taskId'],
483
+ params: [
484
+ {
485
+ name: 'taskId',
486
+ type: 'string',
487
+ required: true,
488
+ description: 'Task ID to evaluate completion readiness for',
489
+ cli: { positional: true },
490
+ },
491
+ {
492
+ name: 'includeContext',
493
+ type: 'boolean',
494
+ required: false,
495
+ description: 'Include bounded audit context pack',
496
+ },
497
+ {
498
+ name: 'limit',
499
+ type: 'number',
500
+ required: false,
501
+ description: 'Maximum audit context events when context is included',
502
+ },
503
+ {
504
+ name: 'since',
505
+ type: 'string',
506
+ required: false,
507
+ description: 'Lower ISO timestamp bound for audit context',
508
+ },
509
+ {
510
+ name: 'relationDepth',
511
+ type: 'number',
512
+ required: false,
513
+ description: 'Related-task audit context depth',
514
+ },
515
+ ] satisfies ParamDef[],
516
+ },
517
+ {
518
+ gateway: 'query',
519
+ domain: 'tasks',
520
+ operation: 'completion.explain',
521
+ description: 'tasks.completion.explain (query) — explain completion blockers and stale state',
522
+ tier: 1,
523
+ idempotent: true,
524
+ sessionRequired: false,
525
+ requiredParams: ['taskId'],
526
+ params: [
527
+ {
528
+ name: 'taskId',
529
+ type: 'string',
530
+ required: true,
531
+ description: 'Task ID to explain completion readiness for',
532
+ cli: { positional: true },
533
+ },
534
+ {
535
+ name: 'includeContext',
536
+ type: 'boolean',
537
+ required: false,
538
+ description: 'Include bounded audit context pack',
539
+ },
540
+ {
541
+ name: 'limit',
542
+ type: 'number',
543
+ required: false,
544
+ description: 'Maximum audit context events when context is included',
545
+ },
546
+ {
547
+ name: 'since',
548
+ type: 'string',
549
+ required: false,
550
+ description: 'Lower ISO timestamp bound for audit context',
551
+ },
552
+ {
553
+ name: 'relationDepth',
554
+ type: 'number',
555
+ required: false,
556
+ description: 'Related-task audit context depth',
557
+ },
558
+ ] satisfies ParamDef[],
559
+ },
560
+ {
561
+ gateway: 'mutate',
562
+ domain: 'tasks',
563
+ operation: 'projection.repair',
564
+ description:
565
+ 'tasks.projection.repair (mutate) — repair stale completion projection state with typed errors',
566
+ tier: 1,
567
+ idempotent: true,
568
+ sessionRequired: false,
569
+ requiredParams: ['taskId'],
570
+ params: [
571
+ {
572
+ name: 'taskId',
573
+ type: 'string',
574
+ required: true,
575
+ description: 'Task ID whose completion projection should be repaired',
576
+ cli: { positional: true },
577
+ },
578
+ {
579
+ name: 'dryRun',
580
+ type: 'boolean',
581
+ required: false,
582
+ description: 'Preview repair actions without writing projection state',
583
+ },
584
+ ] satisfies ParamDef[],
585
+ },
277
586
  {
278
587
  gateway: 'query',
279
588
  domain: 'tasks',
@@ -667,6 +976,38 @@ export const OPERATIONS: OperationDef[] = [
667
976
  requiredParams: [],
668
977
  params: [],
669
978
  },
979
+ {
980
+ gateway: 'query',
981
+ domain: 'orchestrate',
982
+ operation: 'report',
983
+ description:
984
+ 'orchestrate.report (query) — grouped readiness report: ready, blocked, blockedBy, gate-blocked, invalid (T10631)',
985
+ tier: 1,
986
+ idempotent: true,
987
+ sessionRequired: false,
988
+ requiredParams: ['epicId'],
989
+ params: [
990
+ {
991
+ name: 'epicId',
992
+ type: 'string',
993
+ required: true,
994
+ description: 'Epic ID to generate the report for',
995
+ cli: { positional: true },
996
+ },
997
+ {
998
+ name: 'page',
999
+ type: 'number',
1000
+ required: false,
1001
+ description: 'Page number for paginated output (1-indexed, default 1)',
1002
+ },
1003
+ {
1004
+ name: 'pageSize',
1005
+ type: 'number',
1006
+ required: false,
1007
+ description: 'Page size for paginated output (default 50, max 200)',
1008
+ },
1009
+ ],
1010
+ },
670
1011
  {
671
1012
  gateway: 'query',
672
1013
  domain: 'orchestrate',
@@ -2375,7 +2716,8 @@ export const OPERATIONS: OperationDef[] = [
2375
2716
  gateway: 'mutate',
2376
2717
  domain: 'tasks',
2377
2718
  operation: 'saga.create',
2378
- description: 'tasks.saga.create (mutate) — create a labeled top-level Epic as a Saga',
2719
+ description:
2720
+ 'tasks.saga.create (mutate) — create a Saga as a first-class TaskType (type=saga) per ADR-083',
2379
2721
  tier: 0,
2380
2722
  idempotent: false,
2381
2723
  sessionRequired: false,
@@ -2402,6 +2744,13 @@ export const OPERATIONS: OperationDef[] = [
2402
2744
  description: 'Pipe-separated acceptance criteria',
2403
2745
  cli: { flag: 'acceptance' },
2404
2746
  },
2747
+ {
2748
+ name: 'dryRun',
2749
+ type: 'boolean',
2750
+ required: false,
2751
+ description: 'Validate and preview without writing task, relation, or doc rows',
2752
+ cli: { flag: 'dry-run' },
2753
+ },
2405
2754
  ] satisfies ParamDef[],
2406
2755
  },
2407
2756
  {
@@ -2418,7 +2767,7 @@ export const OPERATIONS: OperationDef[] = [
2418
2767
  name: 'sagaId',
2419
2768
  type: 'string',
2420
2769
  required: true,
2421
- description: 'Saga task ID (must have label=saga)',
2770
+ description: 'Saga task ID (must have type=saga)',
2422
2771
  cli: { positional: true },
2423
2772
  },
2424
2773
  {
@@ -2530,7 +2879,7 @@ export const OPERATIONS: OperationDef[] = [
2530
2879
  name: 'sagaId',
2531
2880
  type: 'string',
2532
2881
  required: true,
2533
- description: 'Saga task ID (must have label=saga)',
2882
+ description: 'Saga task ID (must have type=saga)',
2534
2883
  cli: { positional: true },
2535
2884
  },
2536
2885
  ] satisfies ParamDef[],
@@ -2565,6 +2914,35 @@ export const OPERATIONS: OperationDef[] = [
2565
2914
  },
2566
2915
  ] satisfies ParamDef[],
2567
2916
  },
2917
+ {
2918
+ // T10637 — migrate parent_id-based Saga membership to groups relations.
2919
+ // Converts Epics whose parent_id points to a type='saga' task into proper
2920
+ // groups relations. Non-Epic tasks are documented as conflicts.
2921
+ gateway: 'mutate',
2922
+ domain: 'tasks',
2923
+ operation: 'saga.migrate-containment',
2924
+ description:
2925
+ 'tasks.saga.migrate-containment (mutate) — convert parent_id-based Saga membership to groups relations; idempotent; audits to saga-contain-migration.jsonl',
2926
+ tier: 0,
2927
+ idempotent: true,
2928
+ sessionRequired: false,
2929
+ requiredParams: [],
2930
+ params: [
2931
+ {
2932
+ name: 'sagaId',
2933
+ type: 'string',
2934
+ required: false,
2935
+ description: 'Optional saga task ID. Omit to migrate all sagas.',
2936
+ cli: { positional: true },
2937
+ },
2938
+ {
2939
+ name: 'dryRun',
2940
+ type: 'boolean',
2941
+ required: false,
2942
+ description: 'Report what would happen without mutating rows or writing audit log',
2943
+ },
2944
+ ] satisfies ParamDef[],
2945
+ },
2568
2946
  {
2569
2947
  gateway: 'mutate',
2570
2948
  domain: 'tasks',
@@ -6886,6 +7264,7 @@ export const OPERATIONS: OperationDef[] = [
6886
7264
  type: 'string' as const,
6887
7265
  required: true,
6888
7266
  description: 'Slug of the existing attachment to update',
7267
+ cli: { positional: true },
6889
7268
  },
6890
7269
  {
6891
7270
  name: 'file',
@@ -6893,6 +7272,14 @@ export const OPERATIONS: OperationDef[] = [
6893
7272
  required: false,
6894
7273
  description: 'Path to a local file containing the new content',
6895
7274
  },
7275
+ {
7276
+ name: 'allowExternal',
7277
+ type: 'boolean' as const,
7278
+ required: false,
7279
+ description:
7280
+ 'Permit --file to resolve outside the canonical project root; required for explicit external/worktree update ingestion.',
7281
+ cli: { flag: 'allow-external' },
7282
+ },
6896
7283
  {
6897
7284
  name: 'content',
6898
7285
  type: 'string' as const,
@@ -6909,15 +7296,32 @@ export const OPERATIONS: OperationDef[] = [
6909
7296
  name: 'status',
6910
7297
  type: 'string' as const,
6911
7298
  required: false,
7299
+ enum: DOCS_LIFECYCLE_STATUSES,
6912
7300
  description:
6913
7301
  'Override the new lifecycle status. Defaults to "draft" on every update. ' +
6914
- 'Valid: draft|proposed|accepted|superseded|archived|deprecated.',
7302
+ `Valid: ${DOCS_LIFECYCLE_STATUSES.join('|')}.`,
7303
+ },
7304
+ {
7305
+ name: 'dryRun',
7306
+ type: 'boolean' as const,
7307
+ required: false,
7308
+ description:
7309
+ 'Preview validation and resulting envelope without mutating attachment rows, blob storage, or audit logs.',
7310
+ cli: { flag: 'dry-run' },
7311
+ },
7312
+ {
7313
+ name: 'strict',
7314
+ type: 'boolean' as const,
7315
+ required: false,
7316
+ description:
7317
+ 'Fail body-schema diagnostics instead of surfacing advisory warnings before the write.',
6915
7318
  },
6916
7319
  {
6917
7320
  name: 'attachedBy',
6918
7321
  type: 'string' as const,
6919
7322
  required: false,
6920
7323
  description: 'Agent identity that performed the update (defaults to "human")',
7324
+ cli: { flag: 'attached-by' },
6921
7325
  },
6922
7326
  ],
6923
7327
  },
@@ -7516,7 +7920,7 @@ export const OPERATIONS: OperationDef[] = [
7516
7920
  tier: 1,
7517
7921
  idempotent: true,
7518
7922
  sessionRequired: false,
7519
- requiredParams: ['version', 'epicId'],
7923
+ requiredParams: ['version'],
7520
7924
  params: [
7521
7925
  {
7522
7926
  name: 'version',
@@ -7527,8 +7931,23 @@ export const OPERATIONS: OperationDef[] = [
7527
7931
  {
7528
7932
  name: 'epicId',
7529
7933
  type: 'string',
7530
- required: true,
7531
- description: 'Epic task ID whose children scope the release (R-303)',
7934
+ required: false,
7935
+ description:
7936
+ 'Epic task ID whose children scope the release (R-303); mutually exclusive with sagaId/taskIds',
7937
+ },
7938
+ {
7939
+ name: 'sagaId',
7940
+ type: 'string',
7941
+ required: false,
7942
+ description:
7943
+ 'Saga task ID whose grouped member Epics scope the release; mutually exclusive with epicId/taskIds',
7944
+ },
7945
+ {
7946
+ name: 'taskIds',
7947
+ type: 'array',
7948
+ required: false,
7949
+ description:
7950
+ 'Explicit task-list release scope; mutually exclusive with epicId/sagaId (T10088)',
7532
7951
  },
7533
7952
  {
7534
7953
  name: 'scheme',
@@ -8224,4 +8643,80 @@ export const OPERATIONS: OperationDef[] = [
8224
8643
  },
8225
8644
  ] satisfies ParamDef[],
8226
8645
  },
8646
+
8647
+ // ---------------------------------------------------------------------------
8648
+ // T10629 — tasks.context: bounded task-scoped context pack with token budget
8649
+ // ---------------------------------------------------------------------------
8650
+ {
8651
+ gateway: 'query' as const,
8652
+ domain: 'tasks',
8653
+ operation: 'context',
8654
+ description:
8655
+ 'tasks.context (query) — bounded context pack for a single task. ' +
8656
+ 'Combines identity + acceptance criteria + blockers + attached docs + ' +
8657
+ 'graph edges (from tasks.slice) + recent activity within a configurable ' +
8658
+ 'token budget, with explicit omission tracking and expansion hints.',
8659
+ tier: 1,
8660
+ idempotent: true,
8661
+ sessionRequired: false,
8662
+ requiredParams: ['taskId'],
8663
+ params: [
8664
+ {
8665
+ name: 'taskId',
8666
+ type: 'string' as const,
8667
+ required: true,
8668
+ description: 'Task ID to build context for (e.g. T10629)',
8669
+ cli: { positional: true },
8670
+ },
8671
+ {
8672
+ name: 'budgetTokens',
8673
+ type: 'number' as const,
8674
+ required: false,
8675
+ description: 'Maximum token budget for the returned pack. Default: 1500',
8676
+ },
8677
+ {
8678
+ name: 'includeAcceptance',
8679
+ type: 'boolean' as const,
8680
+ required: false,
8681
+ description: 'Include acceptance criteria in the pack. Default: true',
8682
+ },
8683
+ {
8684
+ name: 'includeBlockers',
8685
+ type: 'boolean' as const,
8686
+ required: false,
8687
+ description: 'Include blocker summary in the pack. Default: true',
8688
+ },
8689
+ {
8690
+ name: 'includeDocs',
8691
+ type: 'boolean' as const,
8692
+ required: false,
8693
+ description: 'Include attached docs in the pack. Default: true',
8694
+ },
8695
+ {
8696
+ name: 'includeEdges',
8697
+ type: 'boolean' as const,
8698
+ required: false,
8699
+ description:
8700
+ 'Include graph edges (upstream/downstream/siblings/related) in the pack. Default: true',
8701
+ },
8702
+ {
8703
+ name: 'includeActivity',
8704
+ type: 'boolean' as const,
8705
+ required: false,
8706
+ description: 'Include recent activity (audit log) in the pack. Default: true',
8707
+ },
8708
+ {
8709
+ name: 'activityLimit',
8710
+ type: 'number' as const,
8711
+ required: false,
8712
+ description: 'Maximum number of recent activity events. Default: 10',
8713
+ },
8714
+ {
8715
+ name: 'edgeDepth',
8716
+ type: 'number' as const,
8717
+ required: false,
8718
+ description: 'Maximum depth for graph edges when includeEdges is true. Default: 1',
8719
+ },
8720
+ ] satisfies ParamDef[],
8721
+ },
8227
8722
  ];
@@ -200,10 +200,10 @@ export const callsiteCoverageAtomSchema = z.object({
200
200
  // ---------------------------------------------------------------------------
201
201
 
202
202
  /**
203
- * Strict UUIDv4 regex (lowercase, hyphenated 8-4-4-4-12 with the `4` major
204
- * version nibble and `[89ab]` variant nibble) per ADR-079-r2 §2.1 ABNF
205
- * (`ac-uuid` production) and RFC 9562 §5.4. Used by the `satisfies:` atom
206
- * to validate the target-AC UUID form.
203
+ * Strict AC UUID regex (lowercase, hyphenated 8-4-4-4-12 with v4/v5 major
204
+ * version nibble and `[89ab]` variant nibble). T10586 keeps legacy random
205
+ * UUIDv4 AC ids valid while allowing deterministic UUIDv5-shaped ids derived
206
+ * from task id + source key.
207
207
  *
208
208
  * Validators MUST reject mixed-case to prevent silent dedupe failures — the
209
209
  * canonical column casing is lowercase per ADR-079-r1 §2.1.
@@ -212,7 +212,7 @@ export const callsiteCoverageAtomSchema = z.object({
212
212
  * @adr ADR-079-r2 §2.1
213
213
  */
214
214
  export const AC_UUID_REGEX =
215
- /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
215
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[45][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
216
216
 
217
217
  /**
218
218
  * Positional-alias regex for `satisfies:` atom target-AC identifiers per
@@ -286,10 +286,10 @@ export const satisfiesAtomSchema = z.object({
286
286
  targetTaskId: z
287
287
  .string()
288
288
  .regex(SATISFIES_TASK_ID_REGEX, 'satisfies atom targetTaskId must match /^T[0-9]{1,7}$/'),
289
- /** Lowercase UUIDv4 — populated for the canonical form; undefined for alias form. */
289
+ /** Lowercase UUIDv4/v5 — populated for the canonical form; undefined for alias form. */
290
290
  targetAcId: z
291
291
  .string()
292
- .regex(AC_UUID_REGEX, 'satisfies atom targetAcId must be a lowercase UUIDv4')
292
+ .regex(AC_UUID_REGEX, 'satisfies atom targetAcId must be a lowercase UUIDv4/v5')
293
293
  .optional(),
294
294
  /** Positional alias `AC<1-4 digits>` — populated for alias form; undefined for UUID form. */
295
295
  targetAcAlias: z
@@ -882,7 +882,7 @@ export function parseEvidenceString(raw: string): EvidenceAtom[] {
882
882
  }
883
883
  }
884
884
 
885
- // ac-id is EITHER a strict UUIDv4 OR an AC<digits> alias — exactly one.
885
+ // ac-id is EITHER a strict UUIDv4/v5 OR an AC<digits> alias — exactly one.
886
886
  let targetAcId: string | undefined;
887
887
  let targetAcAlias: string | undefined;
888
888
  if (AC_UUID_REGEX.test(acIdRaw)) {
@@ -891,8 +891,8 @@ export function parseEvidenceString(raw: string): EvidenceAtom[] {
891
891
  targetAcAlias = acIdRaw;
892
892
  } else {
893
893
  throw new EvidenceParseError(
894
- `satisfies atom ac-id "${acIdRaw}" must be either a lowercase UUIDv4 or AC<1-4 digits> in "${chunk}"`,
895
- 'Use format: satisfies:T1234#AC2 (alias) or satisfies:T1234#<lowercase-uuidv4> (canonical)',
894
+ `satisfies atom ac-id "${acIdRaw}" must be either a lowercase UUIDv4/v5 or AC<1-4 digits> in "${chunk}"`,
895
+ 'Use format: satisfies:T1234#AC2 (alias) or satisfies:T1234#<lowercase-uuidv4-or-v5> (canonical)',
896
896
  );
897
897
  }
898
898