@cleocode/contracts 2026.6.12 → 2026.6.14

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 (216) hide show
  1. package/dist/__tests__/operation-def.test.js +5 -1
  2. package/dist/__tests__/operation-def.test.js.map +1 -1
  3. package/dist/__tests__/provider-def.test.d.ts +12 -0
  4. package/dist/__tests__/provider-def.test.d.ts.map +1 -0
  5. package/dist/__tests__/provider-def.test.js +84 -0
  6. package/dist/__tests__/provider-def.test.js.map +1 -0
  7. package/dist/__tests__/sealed-credential.test.d.ts +19 -0
  8. package/dist/__tests__/sealed-credential.test.d.ts.map +1 -0
  9. package/dist/__tests__/sealed-credential.test.js +74 -0
  10. package/dist/__tests__/sealed-credential.test.js.map +1 -0
  11. package/dist/__tests__/service-provider.test.d.ts +17 -0
  12. package/dist/__tests__/service-provider.test.d.ts.map +1 -0
  13. package/dist/__tests__/service-provider.test.js +108 -0
  14. package/dist/__tests__/service-provider.test.js.map +1 -0
  15. package/dist/__tests__/skill-executor-contract.test.js +3 -0
  16. package/dist/__tests__/skill-executor-contract.test.js.map +1 -1
  17. package/dist/acceptance-gate.d.ts +2 -3
  18. package/dist/acceptance-gate.d.ts.map +1 -1
  19. package/dist/boundary.d.ts +52 -0
  20. package/dist/boundary.d.ts.map +1 -1
  21. package/dist/boundary.js +24 -19
  22. package/dist/boundary.js.map +1 -1
  23. package/dist/conduit.d.ts +171 -0
  24. package/dist/conduit.d.ts.map +1 -1
  25. package/dist/config/index.d.ts +23 -0
  26. package/dist/config/index.d.ts.map +1 -0
  27. package/dist/config/index.js +22 -0
  28. package/dist/config/index.js.map +1 -0
  29. package/dist/config.d.ts +104 -1
  30. package/dist/config.d.ts.map +1 -1
  31. package/dist/data-accessor.d.ts +21 -1
  32. package/dist/data-accessor.d.ts.map +1 -1
  33. package/dist/data-accessor.js.map +1 -1
  34. package/dist/dispatch/__tests__/tasks-gateway-crud-ops.test.d.ts +21 -0
  35. package/dist/dispatch/__tests__/tasks-gateway-crud-ops.test.d.ts.map +1 -0
  36. package/dist/dispatch/__tests__/tasks-gateway-crud-ops.test.js +84 -0
  37. package/dist/dispatch/__tests__/tasks-gateway-crud-ops.test.js.map +1 -0
  38. package/dist/dispatch/identity.d.ts +1 -1
  39. package/dist/dispatch/identity.d.ts.map +1 -1
  40. package/dist/dispatch/identity.js +25 -0
  41. package/dist/dispatch/identity.js.map +1 -1
  42. package/dist/dispatch/operation-def.d.ts +20 -0
  43. package/dist/dispatch/operation-def.d.ts.map +1 -1
  44. package/dist/dispatch/operations-registry.d.ts.map +1 -1
  45. package/dist/dispatch/operations-registry.js +1044 -182
  46. package/dist/dispatch/operations-registry.js.map +1 -1
  47. package/dist/docs/read.d.ts +2 -2
  48. package/dist/index.d.ts +25 -11
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +17 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/lease-ipc/__tests__/freeze.test.d.ts +15 -0
  53. package/dist/lease-ipc/__tests__/freeze.test.d.ts.map +1 -0
  54. package/dist/lease-ipc/__tests__/freeze.test.js +313 -0
  55. package/dist/lease-ipc/__tests__/freeze.test.js.map +1 -0
  56. package/dist/lease-ipc/index.d.ts +17 -0
  57. package/dist/lease-ipc/index.d.ts.map +1 -0
  58. package/dist/lease-ipc/index.js +16 -0
  59. package/dist/lease-ipc/index.js.map +1 -0
  60. package/dist/lease-ipc/messages.d.ts +918 -0
  61. package/dist/lease-ipc/messages.d.ts.map +1 -0
  62. package/dist/lease-ipc/messages.js +476 -0
  63. package/dist/lease-ipc/messages.js.map +1 -0
  64. package/dist/lease-ipc/version.d.ts +41 -0
  65. package/dist/lease-ipc/version.d.ts.map +1 -0
  66. package/dist/lease-ipc/version.js +43 -0
  67. package/dist/lease-ipc/version.js.map +1 -0
  68. package/dist/llm/catalog-schema.d.ts +242 -0
  69. package/dist/llm/catalog-schema.d.ts.map +1 -0
  70. package/dist/llm/catalog-schema.js +153 -0
  71. package/dist/llm/catalog-schema.js.map +1 -0
  72. package/dist/llm/catalog-schema.json +139 -0
  73. package/dist/llm/index.d.ts +15 -0
  74. package/dist/llm/index.d.ts.map +1 -0
  75. package/dist/llm/index.js +14 -0
  76. package/dist/llm/index.js.map +1 -0
  77. package/dist/llm/interfaces.d.ts +23 -0
  78. package/dist/llm/interfaces.d.ts.map +1 -1
  79. package/dist/llm/oauth.d.ts +16 -2
  80. package/dist/llm/oauth.d.ts.map +1 -1
  81. package/dist/llm/onboarding.d.ts +126 -0
  82. package/dist/llm/onboarding.d.ts.map +1 -0
  83. package/dist/llm/onboarding.js +34 -0
  84. package/dist/llm/onboarding.js.map +1 -0
  85. package/dist/llm/provider-def.d.ts +254 -0
  86. package/dist/llm/provider-def.d.ts.map +1 -0
  87. package/dist/llm/provider-def.js +93 -0
  88. package/dist/llm/provider-def.js.map +1 -0
  89. package/dist/llm/sealed-credential.d.ts +164 -0
  90. package/dist/llm/sealed-credential.d.ts.map +1 -0
  91. package/dist/llm/sealed-credential.js +43 -0
  92. package/dist/llm/sealed-credential.js.map +1 -0
  93. package/dist/llm/system-of-use.d.ts +383 -0
  94. package/dist/llm/system-of-use.d.ts.map +1 -0
  95. package/dist/llm/system-of-use.js +238 -0
  96. package/dist/llm/system-of-use.js.map +1 -0
  97. package/dist/llm/system-resolver.d.ts +87 -11
  98. package/dist/llm/system-resolver.d.ts.map +1 -1
  99. package/dist/llm/system-resolver.js +14 -7
  100. package/dist/llm/system-resolver.js.map +1 -1
  101. package/dist/operations/__tests__/ensures-schema-registry.test.d.ts +17 -0
  102. package/dist/operations/__tests__/ensures-schema-registry.test.d.ts.map +1 -0
  103. package/dist/operations/__tests__/ensures-schema-registry.test.js +113 -0
  104. package/dist/operations/__tests__/ensures-schema-registry.test.js.map +1 -0
  105. package/dist/operations/admin.d.ts +124 -1
  106. package/dist/operations/admin.d.ts.map +1 -1
  107. package/dist/operations/ensures-schema-registry.d.ts +172 -0
  108. package/dist/operations/ensures-schema-registry.d.ts.map +1 -0
  109. package/dist/operations/ensures-schema-registry.js +226 -0
  110. package/dist/operations/ensures-schema-registry.js.map +1 -0
  111. package/dist/operations/entities.d.ts +110 -0
  112. package/dist/operations/entities.d.ts.map +1 -0
  113. package/dist/operations/entities.js +695 -0
  114. package/dist/operations/entities.js.map +1 -0
  115. package/dist/operations/llm.d.ts +116 -9
  116. package/dist/operations/llm.d.ts.map +1 -1
  117. package/dist/operations/output-contracts-data.d.ts.map +1 -1
  118. package/dist/operations/output-contracts-data.js +230 -0
  119. package/dist/operations/output-contracts-data.js.map +1 -1
  120. package/dist/operations/service.d.ts +68 -0
  121. package/dist/operations/service.d.ts.map +1 -0
  122. package/dist/operations/service.js +336 -0
  123. package/dist/operations/service.js.map +1 -0
  124. package/dist/operations/tasks.d.ts +109 -0
  125. package/dist/operations/tasks.d.ts.map +1 -1
  126. package/dist/operations/tasks.js.map +1 -1
  127. package/dist/operations/validate.d.ts +1 -12
  128. package/dist/operations/validate.d.ts.map +1 -1
  129. package/dist/operations/validate.js +1 -1
  130. package/dist/playbook.d.ts +116 -0
  131. package/dist/playbook.d.ts.map +1 -1
  132. package/dist/release/plan.d.ts +5 -5
  133. package/dist/session.d.ts +11 -0
  134. package/dist/session.d.ts.map +1 -1
  135. package/dist/session.js.map +1 -1
  136. package/dist/templates/manifest.d.ts +1 -1
  137. package/dist/tools/agent-tools.d.ts +231 -0
  138. package/dist/tools/agent-tools.d.ts.map +1 -0
  139. package/dist/tools/agent-tools.js +25 -0
  140. package/dist/tools/agent-tools.js.map +1 -0
  141. package/dist/tools/atomic.d.ts +19 -0
  142. package/dist/tools/atomic.d.ts.map +1 -1
  143. package/dist/tools/atomic.js +17 -0
  144. package/dist/tools/atomic.js.map +1 -1
  145. package/dist/tools/index.d.ts +2 -0
  146. package/dist/tools/index.d.ts.map +1 -1
  147. package/dist/tools/skill-executor.d.ts +7 -0
  148. package/dist/tools/skill-executor.d.ts.map +1 -1
  149. package/dist/tools/web-tools.d.ts +217 -0
  150. package/dist/tools/web-tools.d.ts.map +1 -0
  151. package/dist/tools/web-tools.js +31 -0
  152. package/dist/tools/web-tools.js.map +1 -0
  153. package/dist/vault/service-provider.d.ts +343 -0
  154. package/dist/vault/service-provider.d.ts.map +1 -0
  155. package/dist/vault/service-provider.js +857 -0
  156. package/dist/vault/service-provider.js.map +1 -0
  157. package/dist/workgraph.d.ts +12 -12
  158. package/package.json +14 -2
  159. package/src/__tests__/__snapshots__/operations-registry.test.ts.snap +1 -1
  160. package/src/__tests__/operation-def.test.ts +7 -1
  161. package/src/__tests__/provider-def.test.ts +93 -0
  162. package/src/__tests__/sealed-credential.test.ts +100 -0
  163. package/src/__tests__/service-provider.test.ts +129 -0
  164. package/src/__tests__/skill-executor-contract.test.ts +3 -0
  165. package/src/acceptance-gate.ts +2 -3
  166. package/src/boundary.ts +70 -20
  167. package/src/conduit.ts +200 -0
  168. package/src/config/index.ts +35 -0
  169. package/src/config.ts +106 -1
  170. package/src/data-accessor.ts +22 -1
  171. package/src/dispatch/__tests__/tasks-gateway-crud-ops.test.ts +99 -0
  172. package/src/dispatch/identity.ts +25 -0
  173. package/src/dispatch/operation-def.ts +21 -0
  174. package/src/dispatch/operations-registry.ts +1083 -176
  175. package/src/index.ts +240 -25
  176. package/src/lease-ipc/__tests__/freeze.test.ts +342 -0
  177. package/src/lease-ipc/index.ts +75 -0
  178. package/src/lease-ipc/messages.ts +588 -0
  179. package/src/lease-ipc/version.ts +46 -0
  180. package/src/llm/catalog-schema.json +139 -0
  181. package/src/llm/catalog-schema.ts +184 -0
  182. package/src/llm/index.ts +29 -0
  183. package/src/llm/interfaces.ts +23 -0
  184. package/src/llm/oauth.ts +16 -2
  185. package/src/llm/onboarding.ts +131 -0
  186. package/src/llm/provider-def.ts +291 -0
  187. package/src/llm/sealed-credential.ts +166 -0
  188. package/src/llm/system-of-use.ts +503 -0
  189. package/src/llm/system-resolver.ts +91 -11
  190. package/src/operations/__tests__/ensures-schema-registry.test.ts +169 -0
  191. package/src/operations/admin.ts +144 -0
  192. package/src/operations/ensures-schema-registry.ts +260 -0
  193. package/src/operations/entities.ts +758 -0
  194. package/src/operations/llm.ts +120 -8
  195. package/src/operations/output-contracts-data.ts +264 -0
  196. package/src/operations/service.ts +360 -0
  197. package/src/operations/tasks.ts +119 -0
  198. package/src/operations/validate.ts +1 -14
  199. package/src/playbook.ts +117 -0
  200. package/src/session.ts +11 -0
  201. package/src/tools/agent-tools.ts +270 -0
  202. package/src/tools/atomic.ts +21 -0
  203. package/src/tools/index.ts +46 -0
  204. package/src/tools/skill-executor.ts +7 -0
  205. package/src/tools/web-tools.ts +247 -0
  206. package/src/vault/service-provider.ts +1137 -0
  207. package/dist/tessera.d.ts +0 -32
  208. package/dist/tessera.d.ts.map +0 -1
  209. package/dist/tessera.js +0 -11
  210. package/dist/tessera.js.map +0 -1
  211. package/dist/warp-chain.d.ts +0 -129
  212. package/dist/warp-chain.d.ts.map +0 -1
  213. package/dist/warp-chain.js +0 -13
  214. package/dist/warp-chain.js.map +0 -1
  215. package/src/tessera.ts +0 -35
  216. package/src/warp-chain.ts +0 -185
@@ -10,6 +10,8 @@
10
10
  */
11
11
 
12
12
  import type { BuiltinProviderId, ProviderId } from '../llm/provider-id.js';
13
+ import type { SealedCredential } from '../llm/sealed-credential.js';
14
+ import type { SystemOfUseKind, SystemOfUsePickerEntry } from '../llm/system-of-use.js';
13
15
 
14
16
  /**
15
17
  * @deprecated since Phase 4 (ADR-072). Use {@link ProviderId} from
@@ -196,6 +198,33 @@ export interface CredentialResultWire {
196
198
  authType: AuthTypeWire;
197
199
  }
198
200
 
201
+ /**
202
+ * Non-secret credential metadata — the E10 (T11753) redacted view of a resolved
203
+ * credential that {@link ResolvedLLM} carries inline.
204
+ *
205
+ * This is {@link CredentialResultWire} with the secret-bearing `apiKey` field
206
+ * **structurally removed**. The resolver returns this metadata so consumers can
207
+ * branch on `authType` / `source` / `provider` (e.g. choose OAuth-vs-api_key
208
+ * header style, surface `cleo llm whoami` diagnostics) WITHOUT any plaintext
209
+ * crossing the resolver boundary. The plaintext is reachable ONLY via
210
+ * {@link ResolvedLLM.sealedCredential}'s `fetch()` at the wire.
211
+ *
212
+ * @task T11753
213
+ * @epic T11746
214
+ */
215
+ export interface CredentialMetadataWire {
216
+ /** Provider transport this credential is for. */
217
+ provider: ModelTransport;
218
+ /**
219
+ * Which tier produced this credential. `undefined` only when no credential
220
+ * was resolved (in which case both this and {@link ResolvedLLM.sealedCredential}
221
+ * are `null`).
222
+ */
223
+ source: CredentialSourceWire | undefined;
224
+ /** Scheme used to present the credential to the provider. */
225
+ authType: AuthTypeWire;
226
+ }
227
+
199
228
  // ============================================================================
200
229
  // Role-based LLM resolution wire types (T9255 — Phase 2 T-llm-1)
201
230
  // ============================================================================
@@ -204,22 +233,28 @@ export interface CredentialResultWire {
204
233
  * Which configuration tier produced a {@link ResolvedLLM}.
205
234
  *
206
235
  * Resolution chain order:
207
- * 1. `role` — `config.llm.roles[role]` (explicit override)
208
- * 2. `profile` — `config.llm.profiles[roles[role].profile]`
209
- * 3. `default` — `config.llm.default` (canonical default)
210
- * 4. `default-profile` — `config.llm.profiles[config.llm.defaultProfile]`
211
- * 5. `implicit-fallback` — hard-coded fallback inside the resolver
236
+ * 1. `role` — `config.llm.roles[role]` (explicit override)
237
+ * 2. `profile` — `config.llm.profiles[roles[role].profile]`
238
+ * 3. `system` — `config.llm.systems[systemKey]` (granular override)
239
+ * 4. `default` — `config.llm.default` (canonical default)
240
+ * 5. `default-profile` — `config.llm.profiles[config.llm.defaultProfile]`
241
+ * 6. `registered-default` — `registerSystemOfUse()` default (below user config)
242
+ * 7. `implicit-fallback` — hard-coded fallback inside the resolver
212
243
  *
213
244
  * Useful for `cleo llm whoami` diagnostics.
214
245
  *
215
246
  * @task T9306
216
247
  * @task T11617 (`profile`, `default-profile`)
248
+ * @task T11748 (`system`)
249
+ * @task T11751 (`registered-default`)
217
250
  */
218
251
  export type ResolutionSource =
219
252
  | 'role'
220
253
  | 'profile'
254
+ | 'system'
221
255
  | 'default'
222
256
  | 'default-profile'
257
+ | 'registered-default'
223
258
  | 'implicit-fallback';
224
259
 
225
260
  /**
@@ -256,10 +291,33 @@ export interface ResolvedLLM {
256
291
  */
257
292
  client: unknown;
258
293
  /**
259
- * Resolved credential. `null` when no tier produced a token. Callers
260
- * MUST handle this case.
294
+ * Resolved credential **metadata** — provider / source / authType only.
295
+ * `null` when no tier produced a credential (in which case
296
+ * {@link sealedCredential} is also `null`). Callers MUST handle this case.
297
+ *
298
+ * E10 (T11753): the secret-bearing `apiKey` field has been **removed** — this
299
+ * is now a {@link CredentialMetadataWire}, NOT the old
300
+ * {@link CredentialResultWire}. The plaintext token never rides on this
301
+ * envelope; obtain it ONLY via {@link sealedCredential}'s `fetch()` at the
302
+ * wire. Branch on `authType` / `source` here for header-style / diagnostics.
261
303
  */
262
- credential: CredentialResultWire | null;
304
+ credential: CredentialMetadataWire | null;
305
+ /**
306
+ * Sealed credential handle — the E10 on-demand-decrypt credential surface
307
+ * (T11752 · T11753 · T11746). `null` when no tier produced a credential
308
+ * (paired with `credential === null`); non-null exactly when a usable
309
+ * credential was resolved.
310
+ *
311
+ * The plaintext token is materialized ONLY by calling
312
+ * {@link SealedCredential.fetch} at the wire (`transportForProvider` /
313
+ * `session-factory.ts`) or daemon worker-injection — never returned up this
314
+ * envelope. This is the canonical credential surface; the old inline
315
+ * `credential.apiKey` plaintext is gone.
316
+ *
317
+ * @task T11752
318
+ * @task T11753
319
+ */
320
+ sealedCredential: SealedCredential | null;
263
321
  /** Which config path produced this resolution. */
264
322
  source: ResolutionSource;
265
323
  /** When `roles[role].credentialLabel` was set, the label that was used. */
@@ -278,6 +336,34 @@ export interface ResolveLLMForRoleOptions {
278
336
  * Defaults to `process.cwd()`.
279
337
  */
280
338
  projectRoot?: string;
339
+ /**
340
+ * Optional encoded system-of-use key (e.g. `'sentient'`, `'tool:web-search'`)
341
+ * that activates the `llm.systems[key]` override tier in the resolution chain
342
+ * (E9 · T11748).
343
+ *
344
+ * When set, `llm.systems[systemKey]` is consulted AFTER any explicit
345
+ * role/argument override but BEFORE the global `llm.defaultProfile`. Threaded
346
+ * down by `resolveLLMForSystem`; direct role callers leave it unset and the
347
+ * system tier is skipped — preserving role-resolution behaviour unchanged.
348
+ *
349
+ * @task T11748
350
+ */
351
+ systemKey?: string;
352
+ /**
353
+ * Optional named profile (a key of `llm.profiles`) that pins this resolution
354
+ * to a specific provider/model/credential, winning over the role tier
355
+ * (T11759 · M4).
356
+ *
357
+ * When set and the profile resolves, it is the HIGHEST-priority tier of
358
+ * {@link selectProviderModel} — above `roles[role]` and the `systems[key]`
359
+ * override — so an explicit caller pin (e.g. a `.cantbook` stage's
360
+ * `profile:`) cannot be silently overridden by background role config. When
361
+ * the named profile is absent or structurally incomplete, resolution falls
362
+ * through to the normal chain unchanged. Direct role callers leave it unset.
363
+ *
364
+ * @task T11759
365
+ */
366
+ profileOverride?: string;
281
367
  }
282
368
 
283
369
  // ============================================================================
@@ -570,6 +656,32 @@ export interface LlmWhoamiResult {
570
656
  entries: LlmWhoamiEntry[];
571
657
  }
572
658
 
659
+ /**
660
+ * Parameters for `llm.systems-of-use` (query — the profile-picker enumeration).
661
+ *
662
+ * Reserved for future filters (e.g. by {@link SystemOfUsePickerEntry.kind}).
663
+ *
664
+ * @task T11751
665
+ */
666
+ export interface LlmSystemsOfUseParams {
667
+ /** Optional kind filter — when set, only that axis is enumerated. */
668
+ kind?: SystemOfUseKind;
669
+ }
670
+
671
+ /**
672
+ * Result envelope for `llm.systems-of-use` (query · T11751 · AC2).
673
+ *
674
+ * The merged picker surface: every builtin {@link SystemOfUse} plus every
675
+ * runtime-registered system (`registerSystemOfUse`), so the TUI / Studio
676
+ * profile picker can enumerate them from ONE op.
677
+ *
678
+ * @task T11751
679
+ */
680
+ export interface LlmSystemsOfUseResult {
681
+ /** One entry per builtin or registered system-of-use. */
682
+ entries: SystemOfUsePickerEntry[];
683
+ }
684
+
573
685
  // ProviderProfile interface lives in ./llm/provider-profile.ts (T9262).
574
686
  // The generated catalog (packages/core/src/llm/generated/provider-profiles.ts)
575
687
  // imports the canonical type from the contracts package and emits each
@@ -24,10 +24,30 @@
24
24
  * @task T11692 — DHQ-057: per-operation output schema SSoT
25
25
  */
26
26
 
27
+ import {
28
+ accountAddOutputContract,
29
+ accountListOutputContract,
30
+ accountRemoveOutputContract,
31
+ modelQueryOutputContract,
32
+ modelShowOutputContract,
33
+ profileCreateOutputContract,
34
+ profileListOutputContract,
35
+ profilePinOutputContract,
36
+ profileUseOutputContract,
37
+ providerConnectOutputContract,
38
+ providerListOutputContract,
39
+ providerShowOutputContract,
40
+ } from './entities.js';
27
41
  import type {
28
42
  OperationOutputContract,
29
43
  OperationOutputContractRegistry,
30
44
  } from './output-contract.js';
45
+ import {
46
+ serviceConnectOutputContract,
47
+ serviceListOutputContract,
48
+ serviceRevokeOutputContract,
49
+ serviceStatusOutputContract,
50
+ } from './service.js';
31
51
 
32
52
  // ---------------------------------------------------------------------------
33
53
  // tasks.show — the operation that bit us (DHQ-057 reproduction)
@@ -334,6 +354,224 @@ const tasksCompleteOutputContract: OperationOutputContract = {
334
354
  fieldPointers: ['/data/updated/0', '/data/status', '/data/count'],
335
355
  };
336
356
 
357
+ // ---------------------------------------------------------------------------
358
+ // tasks.reorder-rank / tasks.bulk-move / tasks.assignee — bulk Kanban mutate
359
+ // ops (T11786 · epic T11556). These ops have NO MUTATE_PROJECTION_PLANS entry,
360
+ // so their raw core result is returned under `envelope.data` unchanged.
361
+ // ---------------------------------------------------------------------------
362
+
363
+ /**
364
+ * OUTPUT contract for `tasks.reorder-rank`.
365
+ *
366
+ * Grounded in `TasksReorderRankResult`: `{ ranked, skipped, count }`. `ranked`
367
+ * is the new top-to-bottom order; `skipped` lists request IDs that did not
368
+ * resolve to a task.
369
+ */
370
+ const tasksReorderRankOutputContract: OperationOutputContract = {
371
+ operation: 'tasks.reorder-rank',
372
+ shapeNote:
373
+ 'Re-ranked IDs (new order) at /data/ranked; unresolved request IDs at /data/skipped; count at /data/count.',
374
+ dataSchema: {
375
+ type: 'object',
376
+ required: ['ranked', 'skipped', 'count'],
377
+ additionalProperties: true,
378
+ properties: {
379
+ ranked: {
380
+ type: 'array',
381
+ description: 'Task IDs whose position was written, in the new top-to-bottom order.',
382
+ items: { type: 'string' },
383
+ },
384
+ skipped: {
385
+ type: 'array',
386
+ description: 'Request IDs that did not resolve to a task (no-op for these).',
387
+ items: { type: 'string' },
388
+ },
389
+ count: { type: 'number', description: 'Number of tasks re-ranked.' },
390
+ },
391
+ },
392
+ fieldPointers: ['/data/ranked/0', '/data/skipped/0', '/data/count'],
393
+ };
394
+
395
+ /**
396
+ * OUTPUT contract for `tasks.bulk-move`.
397
+ *
398
+ * Grounded in `TasksBulkMoveResult`: `{ moved, status?, pipelineStage?, count }`.
399
+ */
400
+ const tasksBulkMoveOutputContract: OperationOutputContract = {
401
+ operation: 'tasks.bulk-move',
402
+ shapeNote:
403
+ 'Moved task IDs at /data/moved (all-or-nothing); applied status/stage at /data/status and /data/pipelineStage; count at /data/count.',
404
+ dataSchema: {
405
+ type: 'object',
406
+ required: ['moved', 'count'],
407
+ additionalProperties: true,
408
+ properties: {
409
+ moved: {
410
+ type: 'array',
411
+ description: 'Task IDs successfully moved (atomic — empty only when count is 0).',
412
+ items: { type: 'string' },
413
+ },
414
+ status: { type: 'string', description: 'The status applied, when supplied.' },
415
+ pipelineStage: { type: 'string', description: 'The pipeline stage applied, when supplied.' },
416
+ count: { type: 'number', description: 'Number of tasks moved.' },
417
+ },
418
+ },
419
+ fieldPointers: ['/data/moved/0', '/data/status', '/data/pipelineStage', '/data/count'],
420
+ };
421
+
422
+ /**
423
+ * OUTPUT contract for `tasks.assignee`.
424
+ *
425
+ * Grounded in `TasksAssigneeResult`: `{ taskId, assignee, assigned }`. `assignee`
426
+ * is null when cleared; `assigned` is the boolean verb result.
427
+ */
428
+ const tasksAssigneeOutputContract: OperationOutputContract = {
429
+ operation: 'tasks.assignee',
430
+ shapeNote:
431
+ 'The new assignee is at /data/assignee (null when cleared); /data/assigned is true on set, false on clear.',
432
+ dataSchema: {
433
+ type: 'object',
434
+ required: ['taskId', 'assignee', 'assigned'],
435
+ additionalProperties: true,
436
+ properties: {
437
+ taskId: { type: 'string', description: 'The task ID whose assignee changed.' },
438
+ assignee: {
439
+ type: ['string', 'null'],
440
+ description: 'The new assignee value (null when cleared).',
441
+ },
442
+ assigned: { type: 'boolean', description: 'True when an assignee was set; false on clear.' },
443
+ },
444
+ },
445
+ fieldPointers: ['/data/taskId', '/data/assignee', '/data/assigned'],
446
+ };
447
+
448
+ // ---------------------------------------------------------------------------
449
+ // admin.config.* — config-as-domain (T11917 · M5/AC3 · ConfigManifest cascade)
450
+ // ---------------------------------------------------------------------------
451
+
452
+ /**
453
+ * OUTPUT contract for `admin.config.get`.
454
+ *
455
+ * Grounded in `AdminConfigGetResult`: `{ key, scope, value, found }`. The
456
+ * resolved value lives at `/data/value`; `found` disambiguates a present `null`
457
+ * value from an absent key.
458
+ */
459
+ const adminConfigGetOutputContract: OperationOutputContract = {
460
+ operation: 'admin.config.get',
461
+ shapeNote:
462
+ 'The resolved value is at /data/value (may be null). /data/found is false when the key is absent.',
463
+ dataSchema: {
464
+ type: 'object',
465
+ required: ['key', 'scope', 'value', 'found'],
466
+ additionalProperties: true,
467
+ properties: {
468
+ key: { type: 'string', description: 'The dot-notation key that was resolved.' },
469
+ scope: {
470
+ type: 'string',
471
+ description: 'Cascade slice the value was resolved against.',
472
+ enum: ['global', 'project', 'merged'],
473
+ },
474
+ value: { description: 'Resolved value, or null when the key is absent.' },
475
+ found: { type: 'boolean', description: 'True IFF the key resolved to a defined value.' },
476
+ },
477
+ },
478
+ fieldPointers: ['/data/key', '/data/scope', '/data/value', '/data/found'],
479
+ };
480
+
481
+ /**
482
+ * OUTPUT contract for `admin.config.list`.
483
+ *
484
+ * Grounded in `AdminConfigListResult`: `{ scope, config, keys }`. The full
485
+ * resolved config object is at `/data/config`; flattened keys are at
486
+ * `/data/keys`.
487
+ */
488
+ const adminConfigListOutputContract: OperationOutputContract = {
489
+ operation: 'admin.config.list',
490
+ shapeNote:
491
+ 'The full resolved config is at /data/config (an object); flattened dot-notation keys are at /data/keys (an array).',
492
+ dataSchema: {
493
+ type: 'object',
494
+ required: ['scope', 'config', 'keys'],
495
+ additionalProperties: true,
496
+ properties: {
497
+ scope: {
498
+ type: 'string',
499
+ description: 'Cascade slice the config was resolved against.',
500
+ enum: ['global', 'project', 'merged'],
501
+ },
502
+ config: {
503
+ type: 'object',
504
+ description: 'Full resolved config object for the slice.',
505
+ additionalProperties: true,
506
+ },
507
+ keys: {
508
+ type: 'array',
509
+ description: 'Flattened dot-notation keys present in the resolved config.',
510
+ items: { type: 'string' },
511
+ },
512
+ },
513
+ },
514
+ fieldPointers: ['/data/scope', '/data/keys/0', '/data/keys'],
515
+ };
516
+
517
+ /**
518
+ * OUTPUT contract for `admin.config.validate`.
519
+ *
520
+ * Grounded in `AdminConfigValidateResult`: `{ scope, ok, issues }`. `ok` is the
521
+ * pass/fail verdict; `issues` carries human-readable rejection reasons.
522
+ */
523
+ const adminConfigValidateOutputContract: OperationOutputContract = {
524
+ operation: 'admin.config.validate',
525
+ shapeNote:
526
+ 'The pass/fail verdict is at /data/ok; rejection reasons are at /data/issues (empty when ok=true).',
527
+ dataSchema: {
528
+ type: 'object',
529
+ required: ['scope', 'ok', 'issues'],
530
+ additionalProperties: true,
531
+ properties: {
532
+ scope: {
533
+ type: 'string',
534
+ description: 'Scope that was validated.',
535
+ enum: ['global', 'project'],
536
+ },
537
+ ok: { type: 'boolean', description: 'True IFF every gate passed.' },
538
+ issues: {
539
+ type: 'array',
540
+ description: 'Human-readable schema issues. Empty when ok=true.',
541
+ items: { type: 'string' },
542
+ },
543
+ },
544
+ },
545
+ fieldPointers: ['/data/scope', '/data/ok', '/data/issues/0', '/data/issues'],
546
+ };
547
+
548
+ /**
549
+ * OUTPUT contract for `admin.config.unset`.
550
+ *
551
+ * Grounded in `AdminConfigUnsetResult`: `{ key, scope, removed }`. `removed` is
552
+ * `true` IFF the key existed and was deleted (idempotent: `false` when absent).
553
+ */
554
+ const adminConfigUnsetOutputContract: OperationOutputContract = {
555
+ operation: 'admin.config.unset',
556
+ shapeNote:
557
+ '/data/removed is true IFF a value was deleted; false when the key was already absent (idempotent).',
558
+ dataSchema: {
559
+ type: 'object',
560
+ required: ['key', 'scope', 'removed'],
561
+ additionalProperties: true,
562
+ properties: {
563
+ key: { type: 'string', description: 'The dot-notation key that was targeted.' },
564
+ scope: {
565
+ type: 'string',
566
+ description: 'Scope the key was removed from.',
567
+ enum: ['project', 'global'],
568
+ },
569
+ removed: { type: 'boolean', description: 'True IFF a value was actually deleted.' },
570
+ },
571
+ },
572
+ fieldPointers: ['/data/key', '/data/scope', '/data/removed'],
573
+ };
574
+
337
575
  // ---------------------------------------------------------------------------
338
576
  // Registry
339
577
  // ---------------------------------------------------------------------------
@@ -353,4 +591,30 @@ export const OUTPUT_CONTRACTS: OperationOutputContractRegistry = {
353
591
  'tasks.add-batch': tasksAddBatchOutputContract,
354
592
  'tasks.update': tasksUpdateOutputContract,
355
593
  'tasks.complete': tasksCompleteOutputContract,
594
+ // T11786 (epic T11556) — bulk Kanban mutate ops.
595
+ 'tasks.reorder-rank': tasksReorderRankOutputContract,
596
+ 'tasks.bulk-move': tasksBulkMoveOutputContract,
597
+ 'tasks.assignee': tasksAssigneeOutputContract,
598
+ 'admin.config.get': adminConfigGetOutputContract,
599
+ 'admin.config.list': adminConfigListOutputContract,
600
+ 'admin.config.validate': adminConfigValidateOutputContract,
601
+ 'admin.config.unset': adminConfigUnsetOutputContract,
602
+ // service-vault CLI verbs (T11941 · epic T11765 · M2-W4)
603
+ 'service.connect': serviceConnectOutputContract,
604
+ 'service.list': serviceListOutputContract,
605
+ 'service.revoke': serviceRevokeOutputContract,
606
+ 'service.status': serviceStatusOutputContract,
607
+ // 5-entity provider-experience ops (T11700 · epic T11666)
608
+ 'account.add': accountAddOutputContract,
609
+ 'account.list': accountListOutputContract,
610
+ 'account.remove': accountRemoveOutputContract,
611
+ 'provider.list': providerListOutputContract,
612
+ 'provider.show': providerShowOutputContract,
613
+ 'provider.connect': providerConnectOutputContract,
614
+ 'model.query': modelQueryOutputContract,
615
+ 'model.show': modelShowOutputContract,
616
+ 'profile.create': profileCreateOutputContract,
617
+ 'profile.list': profileListOutputContract,
618
+ 'profile.pin': profilePinOutputContract,
619
+ 'profile.use': profileUseOutputContract,
356
620
  };