@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
@@ -0,0 +1,503 @@
1
+ /**
2
+ * `SystemOfUse` taxonomy — the structured identity of every CLEO subsystem that
3
+ * may request an LLM through the E9 chokepoint (`resolveLLMForSystem`).
4
+ *
5
+ * ## Why a discriminated descriptor (the hermes `_AUX_TASKS` analog)
6
+ *
7
+ * The first cut of the E9 chokepoint (T11749) accepted a flat string-literal
8
+ * label ({@link SystemOfUseLabel} — `'sentient' | 'memory' | …`). That covered
9
+ * the seven role-mapped background subsystems but had no room for the OTHER
10
+ * axes CLEO routes LLMs along:
11
+ *
12
+ * - **orchestration tiers** (`frontier`/`standard`/`fast`/`local`) — the
13
+ * capability lane a delegated turn runs in, independent of any role;
14
+ * - **tools / skills** — atomic tool primitives and `ct-*` skills that each
15
+ * may pin a model (the hermes `_AUX_TASKS` registry: one entry per named
16
+ * auxiliary task, each with its own provider/model binding);
17
+ * - **cantbook nodes** — per-node model selection inside a `.cantbook` flow;
18
+ * - **spawn units** — orchestrator-spawned worker agents that resolve their
19
+ * own LLM.
20
+ *
21
+ * `SystemOfUse` is the discriminated `{ kind, id }` descriptor that unifies all
22
+ * of these axes under ONE identity type. {@link BUILTIN_SYSTEMS_OF_USE} is the
23
+ * static registry of the well-known systems (orchestration tiers + the seven
24
+ * {@link RoleName}s + the auxiliary systems); `tool:` / `skill:` / `cantbook:` /
25
+ * `spawn-unit:` keys are OPEN — any runtime id is a valid `SystemOfUse` of the
26
+ * corresponding kind without a registry edit (see {@link OPEN_SYSTEM_KEY_PREFIXES}).
27
+ *
28
+ * ## Relationship to the resolver input
29
+ *
30
+ * This descriptor is the *taxonomy / identity* layer. The E9 resolver
31
+ * (`resolveLLMForSystem`) still accepts the ergonomic flat {@link SystemOfUseLabel}
32
+ * for the seven role-mapped background subsystems (its locked contract); this
33
+ * file is the SSoT that label set is derived against ({@link AUX_SYSTEM_IDS}),
34
+ * and the home of the richer descriptor that profile-axis routing (tiers,
35
+ * tools, skills, cantbook nodes, spawn units) keys off.
36
+ *
37
+ * Contracts-purity: this module is **types + `as const` DATA + type guards**
38
+ * only — no runtime logic (Gate 10 · T11418). The runtime encode/decode for the
39
+ * open-axis string keys (`parseSystemKey` / `formatSystemKey`) is intentionally
40
+ * NOT defined here; it lives in `@cleocode/core` so this package stays type-only
41
+ * (this module exposes only the {@link OPEN_SYSTEM_KEY_PREFIXES} DATA those
42
+ * helpers read).
43
+ *
44
+ * @module llm/system-of-use
45
+ * @task T11747
46
+ * @epic T11745
47
+ */
48
+
49
+ import type { LlmProviderTransport, RoleName } from '../config.js';
50
+ import type { ProviderTier } from './provider-profile.js';
51
+
52
+ /**
53
+ * The axis a {@link SystemOfUse} belongs to — the discriminant of the
54
+ * descriptor union.
55
+ *
56
+ * | Kind | Meaning | Registry |
57
+ * |-----------------|----------------------------------------------------------------|-----------------|
58
+ * | `role` | One of the seven background {@link RoleName}s. | closed (7) |
59
+ * | `orchestration` | A capability tier lane (frontier/standard/fast/local). | closed (4) |
60
+ * | `aux` | A named auxiliary subsystem (hermes `_AUX_TASKS` analog). | closed (~10) |
61
+ * | `tool` | An atomic tool primitive that pins a model. | open (`tool:`) |
62
+ * | `skill` | A `ct-*` skill that pins a model. | open (`skill:`) |
63
+ * | `cantbook-node` | A node inside a `.cantbook` flow. | open (`cantbook:`) |
64
+ * | `spawn-unit` | An orchestrator-spawned worker agent. | open (`spawn-unit:`) |
65
+ *
66
+ * @task T11747
67
+ */
68
+ export type SystemOfUseKind =
69
+ | 'role'
70
+ | 'orchestration'
71
+ | 'aux'
72
+ | 'tool'
73
+ | 'skill'
74
+ | 'cantbook-node'
75
+ | 'spawn-unit';
76
+
77
+ /**
78
+ * A subsystem whose identity is one of the seven background {@link RoleName}s.
79
+ *
80
+ * `id` is constrained to {@link RoleName} so the role axis can never drift from
81
+ * the config SSoT.
82
+ *
83
+ * @task T11747
84
+ */
85
+ export interface RoleSystem {
86
+ readonly kind: 'role';
87
+ /** The canonical role name (config SSoT — {@link RoleName}). */
88
+ readonly id: RoleName;
89
+ }
90
+
91
+ /**
92
+ * A subsystem identified by an orchestration capability tier.
93
+ *
94
+ * `id` is a {@link ProviderTier} — the lane a delegated/orchestrated turn runs
95
+ * in (frontier flagship reasoning ↔ local on-device), independent of role.
96
+ *
97
+ * @task T11747
98
+ */
99
+ export interface OrchestrationSystem {
100
+ readonly kind: 'orchestration';
101
+ /** Capability tier lane (see {@link ProviderTier}). */
102
+ readonly id: ProviderTier;
103
+ }
104
+
105
+ /**
106
+ * A named auxiliary subsystem — the direct analog of a hermes `_AUX_TASKS`
107
+ * entry. Each id (`sentient`, `memory`, `compression`, …) is a stable,
108
+ * code-referenced subsystem that may carry its own model binding.
109
+ *
110
+ * @task T11747
111
+ */
112
+ export interface AuxSystem {
113
+ readonly kind: 'aux';
114
+ /** Stable auxiliary subsystem id (a member of {@link AUX_SYSTEM_IDS}). */
115
+ readonly id: AuxSystemId;
116
+ }
117
+
118
+ /**
119
+ * A tool primitive that resolves its own LLM. OPEN id — any atomic tool name is
120
+ * valid (encoded `tool:<name>`), so new tools need no registry edit.
121
+ *
122
+ * @task T11747
123
+ */
124
+ export interface ToolSystem {
125
+ readonly kind: 'tool';
126
+ /** Atomic tool name (free-form runtime id). */
127
+ readonly id: string;
128
+ }
129
+
130
+ /**
131
+ * A `ct-*` skill that resolves its own LLM. OPEN id — encoded `skill:<name>`.
132
+ *
133
+ * @task T11747
134
+ */
135
+ export interface SkillSystem {
136
+ readonly kind: 'skill';
137
+ /** Skill name (free-form runtime id). */
138
+ readonly id: string;
139
+ }
140
+
141
+ /**
142
+ * A node inside a `.cantbook` flow that resolves its own LLM. OPEN id — encoded
143
+ * `cantbook:<nodeId>`.
144
+ *
145
+ * @task T11747
146
+ */
147
+ export interface CantbookNodeSystem {
148
+ readonly kind: 'cantbook-node';
149
+ /** Cantbook node id (free-form runtime id). */
150
+ readonly id: string;
151
+ }
152
+
153
+ /**
154
+ * An orchestrator-spawned worker agent that resolves its own LLM. OPEN id —
155
+ * encoded `spawn-unit:<taskId>` (typically the `T####` it executes).
156
+ *
157
+ * @task T11747
158
+ */
159
+ export interface SpawnUnitSystem {
160
+ readonly kind: 'spawn-unit';
161
+ /** Spawn-unit id, typically the executing task id (free-form runtime id). */
162
+ readonly id: string;
163
+ }
164
+
165
+ /**
166
+ * The discriminated `{ kind, id }` identity of any CLEO subsystem that requests
167
+ * an LLM through the E9 chokepoint.
168
+ *
169
+ * Discriminate on {@link SystemOfUseKind} (`system.kind`) to narrow `id` to the
170
+ * axis-specific type. Closed-axis kinds (`role`/`orchestration`/`aux`) carry a
171
+ * typed id; open-axis kinds (`tool`/`skill`/`cantbook-node`/`spawn-unit`) carry
172
+ * a free-form runtime string.
173
+ *
174
+ * @example
175
+ * ```ts
176
+ * const sys: SystemOfUse = { kind: 'tool', id: 'web-search' };
177
+ * if (sys.kind === 'role') {
178
+ * // sys.id is narrowed to RoleName here
179
+ * }
180
+ * ```
181
+ *
182
+ * @task T11747
183
+ * @epic T11745
184
+ */
185
+ export type SystemOfUse =
186
+ | RoleSystem
187
+ | OrchestrationSystem
188
+ | AuxSystem
189
+ | ToolSystem
190
+ | SkillSystem
191
+ | CantbookNodeSystem
192
+ | SpawnUnitSystem;
193
+
194
+ // ---------------------------------------------------------------------------
195
+ // Closed-axis value SSoTs (the type↔value mirrors)
196
+ // ---------------------------------------------------------------------------
197
+
198
+ /**
199
+ * Value-level SSoT for the seven {@link RoleName}s.
200
+ *
201
+ * The `RoleName` *type* lives in `config.ts`; this `as const` tuple is the
202
+ * single iterable VALUE mirror used to build the registry (and any other
203
+ * `for (const role of ROLE_SYSTEM_IDS)` loop) so the role axis is enumerated
204
+ * from ONE place. A compile-time `satisfies readonly RoleName[]` keeps it
205
+ * locked to the type — adding a role to `RoleName` without extending this tuple
206
+ * is a type error.
207
+ *
208
+ * @task T11747
209
+ */
210
+ export const ROLE_SYSTEM_IDS = [
211
+ 'extraction',
212
+ 'consolidation',
213
+ 'derivation',
214
+ 'hygiene',
215
+ 'judgement',
216
+ 'plugin',
217
+ 'compression',
218
+ ] as const satisfies readonly RoleName[];
219
+
220
+ /**
221
+ * Value-level SSoT for the user-facing, *enumerable* background {@link RoleName}s
222
+ * — the set `cleo llm whoami` reports and `cleo llm profile` accepts.
223
+ *
224
+ * This is the proper subset of {@link ROLE_SYSTEM_IDS} that excludes the two
225
+ * internal sandbox/utility roles (`plugin`, `compression`): they are resolved
226
+ * by code paths (plugin-scoped single-turn calls, context compression) rather
227
+ * than configured per-call by users, so they are intentionally NOT enumerated
228
+ * by the `whoami` / `profile` CLI surface.
229
+ *
230
+ * Sourcing the `cli-ops.ts` role list from THIS one tuple (instead of a
231
+ * duplicated inline array) is the AC3 "ALL_ROLES from one SSoT" requirement
232
+ * (T11750): the type-checker's `satisfies readonly RoleName[]` keeps every id
233
+ * locked to {@link RoleName}, so the enumerable set can never silently drift
234
+ * from the config vocabulary.
235
+ *
236
+ * @task T11750
237
+ * @epic T11745
238
+ */
239
+ export const WHOAMI_ROLE_IDS = [
240
+ 'extraction',
241
+ 'consolidation',
242
+ 'derivation',
243
+ 'hygiene',
244
+ 'judgement',
245
+ ] as const satisfies readonly RoleName[];
246
+
247
+ /**
248
+ * The id of a `whoami`-enumerable role — the element type of
249
+ * {@link WHOAMI_ROLE_IDS}.
250
+ *
251
+ * @task T11750
252
+ */
253
+ export type WhoamiRoleId = (typeof WHOAMI_ROLE_IDS)[number];
254
+
255
+ /**
256
+ * Value-level SSoT for the four orchestration capability tiers. Mirrors the
257
+ * {@link ProviderTier} type, most→least capable.
258
+ *
259
+ * @task T11747
260
+ */
261
+ export const ORCHESTRATION_TIER_IDS = [
262
+ 'frontier',
263
+ 'standard',
264
+ 'fast',
265
+ 'local',
266
+ ] as const satisfies readonly ProviderTier[];
267
+
268
+ /**
269
+ * Value-level SSoT for the auxiliary subsystem ids (the hermes `_AUX_TASKS`
270
+ * key set). These are the stable, code-referenced background subsystems CLEO
271
+ * resolves an LLM for outside the role/tier/tool axes.
272
+ *
273
+ * The seven role-mapped resolver labels in {@link SystemOfUseLabel} are derived
274
+ * from this set plus `default` — keeping the flat resolver vocabulary and the
275
+ * structured taxonomy in lock-step.
276
+ *
277
+ * @task T11747
278
+ */
279
+ export const AUX_SYSTEM_IDS = [
280
+ /** Dream-cycle / consolidation subsystem (BRAIN sentient layer). */
281
+ 'sentient',
282
+ /** BRAIN memory extraction subsystem. */
283
+ 'memory',
284
+ /** Task-executor judgement subsystem. */
285
+ 'task-executor',
286
+ /** BRAIN deriver subsystem. */
287
+ 'deriver',
288
+ /** Hygiene-scan subsystem. */
289
+ 'hygiene',
290
+ /** Plugin-scoped single-turn calls. */
291
+ 'plugin',
292
+ /** Context-compression / summarization subsystem. */
293
+ 'compression',
294
+ /** Decision conflict-validator (ADR write-gate). */
295
+ 'decision-validator',
296
+ /** Title / summary generation (cheap aux tier). */
297
+ 'title-generation',
298
+ /** Embedding generation for vector retrieval. */
299
+ 'embedding',
300
+ ] as const;
301
+
302
+ /**
303
+ * The id of a registered auxiliary subsystem — the element type of
304
+ * {@link AUX_SYSTEM_IDS}.
305
+ *
306
+ * @task T11747
307
+ */
308
+ export type AuxSystemId = (typeof AUX_SYSTEM_IDS)[number];
309
+
310
+ // ---------------------------------------------------------------------------
311
+ // Open-axis runtime key prefixes
312
+ // ---------------------------------------------------------------------------
313
+
314
+ /**
315
+ * The four OPEN {@link SystemOfUseKind}s and the string-key prefix each is
316
+ * encoded with for transport across string-only boundaries (config keys, CLI
317
+ * args, audit logs). E.g. `{ kind: 'tool', id: 'web-search' }` ↔ `'tool:web-search'`.
318
+ *
319
+ * Declared as DATA so encode/decode never branches on a hardcoded prefix —
320
+ * `@cleocode/core` reads this map (Gate 10 keeps the runtime split out).
321
+ *
322
+ * @task T11747
323
+ */
324
+ export const OPEN_SYSTEM_KEY_PREFIXES = {
325
+ tool: 'tool:',
326
+ skill: 'skill:',
327
+ 'cantbook-node': 'cantbook:',
328
+ 'spawn-unit': 'spawn-unit:',
329
+ } as const satisfies Readonly<Record<OpenSystemKind, string>>;
330
+
331
+ /**
332
+ * The subset of {@link SystemOfUseKind} whose ids are OPEN (any runtime string),
333
+ * encoded via {@link OPEN_SYSTEM_KEY_PREFIXES}.
334
+ *
335
+ * @task T11747
336
+ */
337
+ export type OpenSystemKind = 'tool' | 'skill' | 'cantbook-node' | 'spawn-unit';
338
+
339
+ // ---------------------------------------------------------------------------
340
+ // BUILTIN_SYSTEMS_OF_USE registry
341
+ // ---------------------------------------------------------------------------
342
+
343
+ /**
344
+ * Static registry of every well-known (closed-axis) {@link SystemOfUse}: the
345
+ * four orchestration tiers, the seven {@link RoleName}s, and the ~10 auxiliary
346
+ * subsystems — the hermes `_AUX_TASKS` analog as a single typed table.
347
+ *
348
+ * Open-axis systems (`tool:`/`skill:`/`cantbook:`/`spawn-unit:`) are NOT listed
349
+ * here — they are valid without a registry edit (see {@link OPEN_SYSTEM_KEY_PREFIXES}).
350
+ *
351
+ * Built by spreading the three closed-axis value SSoTs so the registry can
352
+ * never drift from {@link ROLE_SYSTEM_IDS} / {@link ORCHESTRATION_TIER_IDS} /
353
+ * {@link AUX_SYSTEM_IDS}.
354
+ *
355
+ * @task T11747
356
+ * @epic T11745
357
+ */
358
+ export const BUILTIN_SYSTEMS_OF_USE = [
359
+ ...ORCHESTRATION_TIER_IDS.map((id): OrchestrationSystem => ({ kind: 'orchestration', id })),
360
+ ...ROLE_SYSTEM_IDS.map((id): RoleSystem => ({ kind: 'role', id })),
361
+ ...AUX_SYSTEM_IDS.map((id): AuxSystem => ({ kind: 'aux', id })),
362
+ ] as const satisfies readonly SystemOfUse[];
363
+
364
+ // ---------------------------------------------------------------------------
365
+ // Type guards (contracts-pure — Gate 10 allows `v is T` guards)
366
+ // ---------------------------------------------------------------------------
367
+
368
+ /**
369
+ * Type guard: is `value` a {@link SystemOfUse} descriptor (a `{ kind, id }`
370
+ * object whose `kind` is a known {@link SystemOfUseKind})?
371
+ *
372
+ * Structural-only — does NOT assert that closed-axis ids are registered (use
373
+ * {@link isBuiltinSystemOfUse} for that); an open-axis or as-yet-unregistered
374
+ * id still passes.
375
+ *
376
+ * @param value - The candidate value.
377
+ * @returns `true` when `value` is shaped like a {@link SystemOfUse}.
378
+ * @task T11747
379
+ */
380
+ export function isSystemOfUse(value: unknown): value is SystemOfUse {
381
+ if (typeof value !== 'object' || value === null) return false;
382
+ const v = value as { kind?: unknown; id?: unknown };
383
+ if (typeof v.id !== 'string') return false;
384
+ return (
385
+ v.kind === 'role' ||
386
+ v.kind === 'orchestration' ||
387
+ v.kind === 'aux' ||
388
+ v.kind === 'tool' ||
389
+ v.kind === 'skill' ||
390
+ v.kind === 'cantbook-node' ||
391
+ v.kind === 'spawn-unit'
392
+ );
393
+ }
394
+
395
+ /**
396
+ * Type guard: is `value` a closed-axis {@link SystemOfUse} present in
397
+ * {@link BUILTIN_SYSTEMS_OF_USE} (an exact `kind`+`id` match)?
398
+ *
399
+ * @param value - The candidate value.
400
+ * @returns `true` when `value` is a registered builtin system-of-use.
401
+ * @task T11747
402
+ */
403
+ export function isBuiltinSystemOfUse(value: unknown): value is SystemOfUse {
404
+ if (!isSystemOfUse(value)) return false;
405
+ return BUILTIN_SYSTEMS_OF_USE.some((s) => s.kind === value.kind && s.id === value.id);
406
+ }
407
+
408
+ /**
409
+ * Type guard: is `kind` an OPEN-axis {@link OpenSystemKind} (one whose ids are
410
+ * encoded with an {@link OPEN_SYSTEM_KEY_PREFIXES} prefix)?
411
+ *
412
+ * @param kind - The kind discriminant to test.
413
+ * @returns `true` for `tool` / `skill` / `cantbook-node` / `spawn-unit`.
414
+ * @task T11747
415
+ */
416
+ export function isOpenSystemKind(kind: SystemOfUseKind): kind is OpenSystemKind {
417
+ return kind === 'tool' || kind === 'skill' || kind === 'cantbook-node' || kind === 'spawn-unit';
418
+ }
419
+
420
+ // ---------------------------------------------------------------------------
421
+ // Runtime-registered systems-of-use (registerSystemOfUse — T11751)
422
+ // ---------------------------------------------------------------------------
423
+
424
+ /**
425
+ * The default provider/model binding a runtime-registered {@link SystemOfUse}
426
+ * advertises (T11751 · AC1).
427
+ *
428
+ * `registerSystemOfUse(key, displayName, defaults)` lets a plugin / extension /
429
+ * downstream package declare a NEW system-of-use without a registry edit and
430
+ * give it a default binding. That default is consulted strictly BELOW user
431
+ * config (`llm.systems[key]` / `llm.default` / `llm.defaultProfile`) so the user
432
+ * always wins — it only supplies a binding when the user has configured nothing
433
+ * for that key.
434
+ *
435
+ * Either `profile` (a key of `LlmConfig.profiles`) OR an inline `provider` +
436
+ * `model` tuple supplies the binding; `profile` wins when both are present. An
437
+ * entry that supplies neither a resolvable `profile` nor a complete
438
+ * `provider`+`model` tuple is structurally incomplete and is skipped at
439
+ * resolution time (the chain falls through to implicit-fallback) — never an
440
+ * error.
441
+ *
442
+ * @task T11751
443
+ * @epic T11745
444
+ */
445
+ export interface SystemOfUseDefaults {
446
+ /**
447
+ * Optional reference to a named profile in `LlmConfig.profiles`. When set and
448
+ * resolvable, the named profile's provider/model/credentialLabel win over this
449
+ * entry's inline tuple.
450
+ */
451
+ readonly profile?: string;
452
+ /** Inline LLM provider transport (used when `profile` is absent/unresolvable). */
453
+ readonly provider?: LlmProviderTransport;
454
+ /** Inline full model identifier (used when `profile` is absent/unresolvable). */
455
+ readonly model?: string;
456
+ /**
457
+ * Optional credential label pinning this default to a specific credential pool
458
+ * entry. When omitted, standard priority-based credential resolution applies.
459
+ */
460
+ readonly credentialLabel?: string;
461
+ }
462
+
463
+ /**
464
+ * A runtime-registered system-of-use — the merged record surfaced by the
465
+ * profile-picker enumeration (T11751 · AC2).
466
+ *
467
+ * @task T11751
468
+ * @epic T11745
469
+ */
470
+ export interface RegisteredSystemOfUse {
471
+ /** Encoded system-of-use key (e.g. `'sentient'`, `'tool:web-search'`). */
472
+ readonly key: string;
473
+ /** Human-readable display name for the picker surface. */
474
+ readonly displayName: string;
475
+ /** Default binding consulted strictly below user config (user wins). */
476
+ readonly defaults: SystemOfUseDefaults;
477
+ }
478
+
479
+ /**
480
+ * One enumerated entry in the merged profile-picker surface (T11751 · AC2).
481
+ *
482
+ * Combines the structured {@link SystemOfUse} identity with its display name and
483
+ * provenance so the TUI/Studio picker can render every well-known builtin AND
484
+ * every runtime-registered system in one list.
485
+ *
486
+ * @task T11751
487
+ * @epic T11745
488
+ */
489
+ export interface SystemOfUsePickerEntry {
490
+ /** Encoded system-of-use key (the picker value). */
491
+ readonly key: string;
492
+ /** Human-readable display name. */
493
+ readonly displayName: string;
494
+ /** Discriminant axis of this system (see {@link SystemOfUseKind}). */
495
+ readonly kind: SystemOfUseKind;
496
+ /** Where this entry came from: a static builtin or a runtime registration. */
497
+ readonly source: 'builtin' | 'registered';
498
+ /**
499
+ * The default binding when `source === 'registered'`. Absent for builtins
500
+ * (their binding is resolved purely from user config + the role/aux mapping).
501
+ */
502
+ readonly defaults?: SystemOfUseDefaults;
503
+ }
@@ -1,11 +1,18 @@
1
1
  /**
2
- * SystemOfUse contract types for the `resolveLLMForSystem` chokepoint (E9).
2
+ * `SystemOfUseLabel` contract types for the `resolveLLMForSystem` chokepoint (E9).
3
3
  *
4
- * A "system of use" is the semantic label for the subsystem that is requesting
5
- * an LLM client — e.g. `'sentient'`, `'memory'`, `'task-executor'`. It is
6
- * a higher-level, stable identity that CLEO maps to a {@link RoleName} for
7
- * config resolution. This indirection insulates call-sites from the config
8
- * vocabulary (roles) and from model/provider churn.
4
+ * A "system of use label" is the flat, ergonomic vocabulary the E9 resolver
5
+ * accepts for the seven role-mapped background subsystems — e.g. `'sentient'`,
6
+ * `'memory'`, `'task-executor'`. It is a higher-level, stable identity that
7
+ * CLEO maps to a {@link RoleName} for config resolution. This indirection
8
+ * insulates call-sites from the config vocabulary (roles) and from
9
+ * model/provider churn.
10
+ *
11
+ * The richer, structured `{ kind, id }` taxonomy that covers the OTHER routing
12
+ * axes (orchestration tiers, tools, skills, cantbook nodes, spawn units) lives
13
+ * in {@link import('./system-of-use.js').SystemOfUse} (T11747). This label set
14
+ * is the flat resolver-input subset; both are kept in lock-step (the label set
15
+ * mirrors the `aux` axis plus `default`).
9
16
  *
10
17
  * `resolveLLMForSystem` is the single DRY chokepoint that the 4-resolver /
11
18
  * 3-picker sprawl will collapse onto (E9 · T11745).
@@ -16,15 +23,21 @@
16
23
  */
17
24
 
18
25
  import type { RoleName } from '../config.js';
26
+ import type { RoleSystem } from './system-of-use.js';
19
27
 
20
28
  /**
21
- * Semantic label for a CLEO subsystem that requests an LLM client.
29
+ * Flat, ergonomic label for a CLEO background subsystem that requests an LLM
30
+ * client through the E9 resolver.
22
31
  *
23
- * Each `SystemOfUse` value maps to a canonical {@link RoleName} used by
32
+ * Each `SystemOfUseLabel` value maps to a canonical {@link RoleName} used by
24
33
  * `resolveLLMForSystem` for config and credential resolution. Subsystems
25
34
  * MUST declare their identity so the resolver can apply the correct
26
35
  * per-system overrides and audit trails.
27
36
  *
37
+ * For the full structured taxonomy (tools/skills/cantbook nodes/spawn units/
38
+ * orchestration tiers), see the discriminated
39
+ * {@link import('./system-of-use.js').SystemOfUse} descriptor (T11747).
40
+ *
28
41
  * ### Role mapping (static default; overridable via config `systemRoles`)
29
42
  *
30
43
  * | System | Default role |
@@ -40,7 +53,7 @@ import type { RoleName } from '../config.js';
40
53
  *
41
54
  * @task T11749
42
55
  */
43
- export type SystemOfUse =
56
+ export type SystemOfUseLabel =
44
57
  | 'sentient'
45
58
  | 'memory'
46
59
  | 'task-executor'
@@ -51,13 +64,13 @@ export type SystemOfUse =
51
64
  | 'default';
52
65
 
53
66
  /**
54
- * Static mapping from {@link SystemOfUse} to the {@link RoleName} used for
67
+ * Static mapping from {@link SystemOfUseLabel} to the {@link RoleName} used for
55
68
  * config resolution. This is the canonical default; callers may override
56
69
  * individual systems via `config.llm.systemRoles[system]`.
57
70
  *
58
71
  * @task T11749
59
72
  */
60
- export const SYSTEM_ROLE_MAP: Readonly<Record<SystemOfUse, RoleName | null>> = {
73
+ export const SYSTEM_ROLE_MAP: Readonly<Record<SystemOfUseLabel, RoleName | null>> = {
61
74
  sentient: 'consolidation',
62
75
  memory: 'extraction',
63
76
  'task-executor': 'judgement',
@@ -69,6 +82,28 @@ export const SYSTEM_ROLE_MAP: Readonly<Record<SystemOfUse, RoleName | null>> = {
69
82
  default: null,
70
83
  } as const;
71
84
 
85
+ /**
86
+ * Input accepted by `resolveLLMForSystem()`.
87
+ *
88
+ * The chokepoint accepts EITHER:
89
+ *
90
+ * - the flat, ergonomic {@link SystemOfUseLabel} for the role-mapped background
91
+ * subsystems (`'sentient'`, `'memory'`, … — the original locked vocabulary), OR
92
+ * - a structured {@link RoleSystem} descriptor (`{ kind: 'role', id: RoleName }`)
93
+ * for a *direct* role resolution.
94
+ *
95
+ * The descriptor form makes the E9 equivalence
96
+ * `resolveLLMForRole(role) ≡ resolveLLMForSystem({ kind: 'role', id: role })`
97
+ * (T11750 · AC1) directly expressible at the chokepoint, so role callers can
98
+ * collapse onto the same single resolution path with ZERO duplicate resolution
99
+ * logic. Both forms funnel through the SAME `resolveLLMForRole` core inside
100
+ * `@cleocode/core`.
101
+ *
102
+ * @task T11750
103
+ * @epic T11745
104
+ */
105
+ export type SystemResolverInput = SystemOfUseLabel | RoleSystem;
106
+
72
107
  /**
73
108
  * Options accepted by `resolveLLMForSystem()`.
74
109
  *
@@ -100,4 +135,49 @@ export interface ResolveLLMForSystemOptions {
100
135
  * @internal
101
136
  */
102
137
  skipCatalogDefault?: boolean;
138
+
139
+ /**
140
+ * Raw prompt used to derive a role from complexity when neither an explicit
141
+ * tier/role nor a role-mapped system label is available (L1 proposer · T11906).
142
+ *
143
+ * When the `system` argument is the flat `'default'` label (which maps to NO
144
+ * role) and `roleOverride` is unset, the resolver runs the L1 complexity
145
+ * classifier over this prompt and proposes a {@link RoleName} from the
146
+ * resulting tier (`low → hygiene`, `mid → consolidation`, `high → judgement`).
147
+ * This is a COMPLEMENT to the resolver — it only supplies a role when one is
148
+ * otherwise absent; an explicit label, descriptor, or `roleOverride` always
149
+ * wins. The classifier returns a TIER only and constructs no LLM client.
150
+ *
151
+ * Ignored when the role is already determined by the input or `roleOverride`.
152
+ */
153
+ complexityPrompt?: string;
154
+
155
+ /**
156
+ * Explicit encoded system-of-use key for the `llm.systems[key]` granular
157
+ * override tier (T11759 · M4).
158
+ *
159
+ * The flat-label input form derives this key from `system` itself; this option
160
+ * lets a caller resolving an OPEN-axis system (whose identity is NOT a flat
161
+ * {@link SystemOfUseLabel}) — e.g. a `.cantbook` node keyed
162
+ * `cantbook:<playbook>#<nodeId>` — supply that identity as the granular
163
+ * override + audit key while passing a resolvable background label as
164
+ * `system`. When set, it OVERRIDES the label-derived key. Omit it and the
165
+ * pre-T11759 derivation is unchanged.
166
+ *
167
+ * @task T11759
168
+ */
169
+ systemKey?: string;
170
+
171
+ /**
172
+ * Optional named profile (a key of `llm.profiles`) that pins the resolution to
173
+ * a specific provider/model/credential, winning over the role tier (T11759 ·
174
+ * M4).
175
+ *
176
+ * Threaded down to `ResolveLLMForRoleOptions.profileOverride`. A `.cantbook`
177
+ * stage's `profile:` flows through here. When the named profile is
178
+ * absent/incomplete, resolution falls through the normal chain unchanged.
179
+ *
180
+ * @task T11759
181
+ */
182
+ profile?: string;
103
183
  }