@cleocode/contracts 2026.5.77 → 2026.5.79

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.
@@ -0,0 +1,414 @@
1
+ /**
2
+ * Zod schema tests for the Release Plan envelope (T9527).
3
+ *
4
+ * Validates the canonical SPEC-T9345 §6.1 shape against the Zod schema defined
5
+ * in {@link ./plan.ts}. Coverage targets:
6
+ *
7
+ * - Happy-path parse round-trip
8
+ * - Each enum field rejects unknown literal values
9
+ * - Required fields cannot be missing
10
+ * - `evidenceAtoms` stays permissive (verb-level enforcement, NOT contract)
11
+ * - All 8 `status` FSM values parse
12
+ * - `meta` is forward-compat (unknown keys pass through via `.catchall`)
13
+ *
14
+ * @task T9527
15
+ */
16
+ import { describe, expect, it } from 'vitest';
17
+ import { GATE_NAME, GATE_STATUS, IMPACT, PLATFORM_TUPLE, PUBLISHER, parseReleasePlan, RELEASE_CHANNEL, RELEASE_KIND, RELEASE_PLAN_SCHEMA_URL, RELEASE_PLAN_SCHEMA_VERSION, RELEASE_SCHEME, RELEASE_STATUS, RESOLVED_SOURCE, ReleaseGateSchema, ReleasePlanChangelogSchema, ReleasePlanMetaSchema, ReleasePlanSchema, ReleasePlanTaskSchema, ReleasePlatformMatrixEntrySchema, ReleasePreflightSummarySchema, safeParseReleasePlan, TASK_KIND, } from './plan.js';
18
+ // ─── Fixtures ────────────────────────────────────────────────────────────────
19
+ /**
20
+ * Returns a fresh deep clone of a minimal-but-complete valid plan. Each test
21
+ * mutates its own copy to test field-level rejection paths.
22
+ */
23
+ function makeValidPlan() {
24
+ return {
25
+ $schema: RELEASE_PLAN_SCHEMA_URL,
26
+ version: 'v2026.6.0',
27
+ resolvedVersion: 'v2026.6.0',
28
+ suffixApplied: false,
29
+ scheme: 'calver',
30
+ channel: 'latest',
31
+ epicId: 'T9999',
32
+ releaseKind: 'regular',
33
+ createdAt: '2026-06-01T12:00:00Z',
34
+ createdBy: 'cleo-prime',
35
+ previousVersion: 'v2026.5.74',
36
+ previousTag: 'v2026.5.74',
37
+ previousShippedAt: '2026-05-15T08:00:00Z',
38
+ tasks: [
39
+ {
40
+ id: 'T10001',
41
+ kind: 'feat',
42
+ impact: 'minor',
43
+ userFacingSummary: 'Add release plan schema',
44
+ evidenceAtoms: ['commit:abc123', 'test-run:vitest.json', 'tool:lint'],
45
+ ivtrPhaseAtPlan: 'released',
46
+ epicAncestor: 'T9999',
47
+ },
48
+ ],
49
+ changelog: {
50
+ features: ['T10001'],
51
+ fixes: [],
52
+ chores: [],
53
+ breaking: [],
54
+ },
55
+ gates: [
56
+ {
57
+ name: 'test',
58
+ atom: 'tool:test',
59
+ status: 'passed',
60
+ lastVerifiedAt: '2026-06-01T11:50:00Z',
61
+ resolvedCommand: 'pnpm run test',
62
+ resolvedSource: 'project-context',
63
+ },
64
+ ],
65
+ platformMatrix: [
66
+ {
67
+ platform: 'linux-x64',
68
+ publisher: 'npm',
69
+ package: '@cleocode/cleo',
70
+ smoke: true,
71
+ },
72
+ ],
73
+ preflightSummary: {
74
+ esbuildExternalsDrift: false,
75
+ lockfileDrift: false,
76
+ epicCompletenessClean: true,
77
+ doubleListingClean: true,
78
+ preflightWarnings: [],
79
+ },
80
+ workflowRunUrl: null,
81
+ prUrl: null,
82
+ mergeCommitSha: null,
83
+ status: 'planned',
84
+ meta: {
85
+ firstEverRelease: false,
86
+ unresolvedTools: [],
87
+ archetype: 'monorepo-w-workspaces',
88
+ },
89
+ };
90
+ }
91
+ // ─── Constant tuples ─────────────────────────────────────────────────────────
92
+ describe('Release plan constant tuples', () => {
93
+ it('exports an 8-state status FSM', () => {
94
+ expect(RELEASE_STATUS).toEqual([
95
+ 'planned',
96
+ 'pr-opened',
97
+ 'pr-merged',
98
+ 'published',
99
+ 'reconciled',
100
+ 'rolled_back',
101
+ 'failed',
102
+ 'cancelled',
103
+ ]);
104
+ expect(RELEASE_STATUS).toHaveLength(8);
105
+ });
106
+ it('exports the 4-channel set (latest|beta|alpha|rc)', () => {
107
+ expect(new Set(RELEASE_CHANNEL)).toEqual(new Set(['latest', 'beta', 'alpha', 'rc']));
108
+ });
109
+ it('exports the 3-scheme set including calver-suffix', () => {
110
+ expect(RELEASE_SCHEME).toContain('calver');
111
+ expect(RELEASE_SCHEME).toContain('semver');
112
+ expect(RELEASE_SCHEME).toContain('calver-suffix');
113
+ });
114
+ it('exports release-kind variants', () => {
115
+ expect(new Set(RELEASE_KIND)).toEqual(new Set(['regular', 'hotfix', 'prerelease']));
116
+ });
117
+ it('exports the 4-status gate enum', () => {
118
+ expect(new Set(GATE_STATUS)).toEqual(new Set(['passed', 'failed', 'skipped', 'unresolved']));
119
+ });
120
+ it('exports canonical gate names (R-310)', () => {
121
+ expect(GATE_NAME).toContain('test');
122
+ expect(GATE_NAME).toContain('build');
123
+ expect(GATE_NAME).toContain('lint');
124
+ expect(GATE_NAME).toContain('typecheck');
125
+ expect(GATE_NAME).toContain('audit');
126
+ expect(GATE_NAME).toContain('security-scan');
127
+ });
128
+ it('exports platform tuples aligned with T1737', () => {
129
+ expect(PLATFORM_TUPLE).toContain('linux-x64');
130
+ expect(PLATFORM_TUPLE).toContain('linux-arm64');
131
+ expect(PLATFORM_TUPLE).toContain('macos-x64');
132
+ expect(PLATFORM_TUPLE).toContain('macos-arm64');
133
+ expect(PLATFORM_TUPLE).toContain('windows-x64');
134
+ expect(PLATFORM_TUPLE).toContain('any');
135
+ });
136
+ it('exports publisher backends covering npm/cargo/docker/pypi/github-release/binary', () => {
137
+ expect(new Set(PUBLISHER)).toEqual(new Set(['npm', 'cargo', 'docker', 'pypi', 'github-release', 'binary']));
138
+ });
139
+ it('exports task-kind classification', () => {
140
+ expect(TASK_KIND).toContain('feat');
141
+ expect(TASK_KIND).toContain('fix');
142
+ expect(TASK_KIND).toContain('hotfix');
143
+ expect(TASK_KIND).toContain('breaking');
144
+ });
145
+ it('exports SemVer impact tuple', () => {
146
+ expect(IMPACT).toEqual(['major', 'minor', 'patch']);
147
+ });
148
+ it('exports resolved-source attribution per ADR-061', () => {
149
+ expect(RESOLVED_SOURCE).toEqual(['project-context', 'language-default', 'legacy-alias']);
150
+ });
151
+ it('exposes a stable schema version + URL', () => {
152
+ expect(RELEASE_PLAN_SCHEMA_VERSION).toBe('1.0.0');
153
+ expect(RELEASE_PLAN_SCHEMA_URL).toBe('https://cleocode.io/schemas/release-plan/v1.json');
154
+ });
155
+ });
156
+ // ─── Happy path ──────────────────────────────────────────────────────────────
157
+ describe('ReleasePlanSchema — happy path', () => {
158
+ it('parses a complete valid plan', () => {
159
+ const plan = parseReleasePlan(makeValidPlan());
160
+ expect(plan.version).toBe('v2026.6.0');
161
+ expect(plan.status).toBe('planned');
162
+ expect(plan.tasks).toHaveLength(1);
163
+ expect(plan.tasks[0]?.id).toBe('T10001');
164
+ expect(plan.platformMatrix[0]?.publisher).toBe('npm');
165
+ });
166
+ it('safeParse returns success for a valid plan', () => {
167
+ const result = safeParseReleasePlan(makeValidPlan());
168
+ expect(result.success).toBe(true);
169
+ });
170
+ it('round-trips through JSON.stringify / parse', () => {
171
+ const original = makeValidPlan();
172
+ const serialized = JSON.stringify(original);
173
+ const reparsed = parseReleasePlan(JSON.parse(serialized));
174
+ expect(reparsed).toEqual(original);
175
+ });
176
+ it('accepts a first-ever release with null previousVersion + meta.firstEverRelease', () => {
177
+ const plan = makeValidPlan();
178
+ plan.previousVersion = null;
179
+ plan.previousTag = null;
180
+ plan.previousShippedAt = null;
181
+ plan.meta = { firstEverRelease: true };
182
+ expect(() => parseReleasePlan(plan)).not.toThrow();
183
+ });
184
+ });
185
+ // ─── Status FSM coverage ─────────────────────────────────────────────────────
186
+ describe('ReleasePlanSchema — status FSM', () => {
187
+ it.each(RELEASE_STATUS)('accepts status = "%s"', (status) => {
188
+ const plan = makeValidPlan();
189
+ plan.status = status;
190
+ expect(() => parseReleasePlan(plan)).not.toThrow();
191
+ });
192
+ it('rejects unknown status literals', () => {
193
+ const plan = { ...makeValidPlan(), status: 'in-flight' };
194
+ expect(() => parseReleasePlan(plan)).toThrow();
195
+ });
196
+ });
197
+ // ─── Enum rejection per field ────────────────────────────────────────────────
198
+ describe('ReleasePlanSchema — enum rejection', () => {
199
+ it('rejects unknown channel', () => {
200
+ const plan = { ...makeValidPlan(), channel: 'canary' };
201
+ expect(() => parseReleasePlan(plan)).toThrow();
202
+ });
203
+ it('rejects unknown scheme', () => {
204
+ const plan = { ...makeValidPlan(), scheme: 'rolling' };
205
+ expect(() => parseReleasePlan(plan)).toThrow();
206
+ });
207
+ it('rejects unknown releaseKind', () => {
208
+ const plan = { ...makeValidPlan(), releaseKind: 'patch' };
209
+ expect(() => parseReleasePlan(plan)).toThrow();
210
+ });
211
+ it('rejects unknown task kind', () => {
212
+ const plan = makeValidPlan();
213
+ plan.tasks[0] = { ...plan.tasks[0], kind: 'misc' };
214
+ expect(() => parseReleasePlan(plan)).toThrow();
215
+ });
216
+ it('rejects unknown impact', () => {
217
+ const plan = makeValidPlan();
218
+ plan.tasks[0] = { ...plan.tasks[0], impact: 'huge' };
219
+ expect(() => parseReleasePlan(plan)).toThrow();
220
+ });
221
+ it('rejects unknown gate name', () => {
222
+ const plan = makeValidPlan();
223
+ plan.gates[0] = { ...plan.gates[0], name: 'fmt' };
224
+ expect(() => parseReleasePlan(plan)).toThrow();
225
+ });
226
+ it('rejects unknown gate status', () => {
227
+ const plan = makeValidPlan();
228
+ plan.gates[0] = { ...plan.gates[0], status: 'flaky' };
229
+ expect(() => parseReleasePlan(plan)).toThrow();
230
+ });
231
+ it('rejects unknown platform tuple', () => {
232
+ const plan = makeValidPlan();
233
+ plan.platformMatrix[0] = { ...plan.platformMatrix[0], platform: 'haiku-x64' };
234
+ expect(() => parseReleasePlan(plan)).toThrow();
235
+ });
236
+ it('rejects unknown publisher', () => {
237
+ const plan = makeValidPlan();
238
+ plan.platformMatrix[0] = { ...plan.platformMatrix[0], publisher: 'gemfury' };
239
+ expect(() => parseReleasePlan(plan)).toThrow();
240
+ });
241
+ it('rejects unknown resolvedSource', () => {
242
+ const plan = makeValidPlan();
243
+ plan.gates[0] = { ...plan.gates[0], resolvedSource: 'env-override' };
244
+ expect(() => parseReleasePlan(plan)).toThrow();
245
+ });
246
+ });
247
+ // ─── Required-field rejection ────────────────────────────────────────────────
248
+ describe('ReleasePlanSchema — required fields', () => {
249
+ it('rejects missing version', () => {
250
+ const plan = makeValidPlan();
251
+ delete plan.version;
252
+ expect(() => parseReleasePlan(plan)).toThrow();
253
+ });
254
+ it('rejects missing epicId', () => {
255
+ const plan = makeValidPlan();
256
+ delete plan.epicId;
257
+ expect(() => parseReleasePlan(plan)).toThrow();
258
+ });
259
+ it('rejects empty epicId string', () => {
260
+ const plan = { ...makeValidPlan(), epicId: '' };
261
+ expect(() => parseReleasePlan(plan)).toThrow();
262
+ });
263
+ it('rejects missing tasks array', () => {
264
+ const plan = makeValidPlan();
265
+ delete plan.tasks;
266
+ expect(() => parseReleasePlan(plan)).toThrow();
267
+ });
268
+ it('rejects missing changelog object', () => {
269
+ const plan = makeValidPlan();
270
+ delete plan.changelog;
271
+ expect(() => parseReleasePlan(plan)).toThrow();
272
+ });
273
+ it('rejects missing preflightSummary', () => {
274
+ const plan = makeValidPlan();
275
+ delete plan.preflightSummary;
276
+ expect(() => parseReleasePlan(plan)).toThrow();
277
+ });
278
+ it('rejects missing epicAncestor on a task row', () => {
279
+ const plan = makeValidPlan();
280
+ const taskWithoutAncestor = { ...plan.tasks[0] };
281
+ delete taskWithoutAncestor.epicAncestor;
282
+ plan.tasks[0] = taskWithoutAncestor;
283
+ expect(() => parseReleasePlan(plan)).toThrow();
284
+ });
285
+ it('rejects malformed createdAt timestamp', () => {
286
+ const plan = { ...makeValidPlan(), createdAt: 'yesterday' };
287
+ expect(() => parseReleasePlan(plan)).toThrow();
288
+ });
289
+ });
290
+ // ─── Evidence atoms (contract permissive — R-301 verb-enforced) ─────────────
291
+ describe('ReleasePlanTaskSchema — evidenceAtoms', () => {
292
+ it('accepts a string[] for evidenceAtoms', () => {
293
+ const result = ReleasePlanTaskSchema.parse({
294
+ id: 'T1',
295
+ kind: 'feat',
296
+ impact: 'patch',
297
+ userFacingSummary: '',
298
+ evidenceAtoms: ['commit:abc'],
299
+ epicAncestor: 'E1',
300
+ });
301
+ expect(result.evidenceAtoms).toEqual(['commit:abc']);
302
+ });
303
+ it('permits an empty evidenceAtoms array at the contract layer (R-301 is verb-enforced)', () => {
304
+ const result = ReleasePlanTaskSchema.safeParse({
305
+ id: 'T1',
306
+ kind: 'feat',
307
+ impact: 'patch',
308
+ userFacingSummary: '',
309
+ evidenceAtoms: [],
310
+ epicAncestor: 'E1',
311
+ });
312
+ expect(result.success).toBe(true);
313
+ });
314
+ it('rejects non-array evidenceAtoms', () => {
315
+ const result = ReleasePlanTaskSchema.safeParse({
316
+ id: 'T1',
317
+ kind: 'feat',
318
+ impact: 'patch',
319
+ userFacingSummary: '',
320
+ evidenceAtoms: 'commit:abc',
321
+ epicAncestor: 'E1',
322
+ });
323
+ expect(result.success).toBe(false);
324
+ });
325
+ it('rejects empty-string atom entries (NonEmptyString)', () => {
326
+ const result = ReleasePlanTaskSchema.safeParse({
327
+ id: 'T1',
328
+ kind: 'feat',
329
+ impact: 'patch',
330
+ userFacingSummary: '',
331
+ evidenceAtoms: [''],
332
+ epicAncestor: 'E1',
333
+ });
334
+ expect(result.success).toBe(false);
335
+ });
336
+ });
337
+ // ─── meta forward-compat ─────────────────────────────────────────────────────
338
+ describe('ReleasePlanMetaSchema — forward compatibility', () => {
339
+ it('preserves unknown keys via catchall', () => {
340
+ const result = ReleasePlanMetaSchema.parse({
341
+ firstEverRelease: false,
342
+ futureField: 'someValue',
343
+ anotherUnknown: { nested: true },
344
+ });
345
+ expect(result.futureField).toBe('someValue');
346
+ expect(result.anotherUnknown).toEqual({ nested: true });
347
+ });
348
+ it('still validates known fields strictly', () => {
349
+ const result = ReleasePlanMetaSchema.safeParse({
350
+ firstEverRelease: 'yes',
351
+ });
352
+ expect(result.success).toBe(false);
353
+ });
354
+ it('accepts a fully-empty meta object', () => {
355
+ expect(() => ReleasePlanMetaSchema.parse({})).not.toThrow();
356
+ });
357
+ });
358
+ // ─── Nested-schema sanity ────────────────────────────────────────────────────
359
+ describe('Nested schemas — sanity', () => {
360
+ it('ReleaseGateSchema requires lastVerifiedAt to be ISO-8601', () => {
361
+ const result = ReleaseGateSchema.safeParse({
362
+ name: 'test',
363
+ atom: 'tool:test',
364
+ status: 'passed',
365
+ lastVerifiedAt: 'Tuesday',
366
+ });
367
+ expect(result.success).toBe(false);
368
+ });
369
+ it('ReleasePlatformMatrixEntrySchema applies smoke=true default when omitted', () => {
370
+ const result = ReleasePlatformMatrixEntrySchema.parse({
371
+ platform: 'any',
372
+ publisher: 'npm',
373
+ package: '@cleocode/lafs',
374
+ });
375
+ expect(result.smoke).toBe(true);
376
+ });
377
+ it('ReleasePreflightSummarySchema requires the four boolean preflight gates', () => {
378
+ const result = ReleasePreflightSummarySchema.safeParse({
379
+ esbuildExternalsDrift: false,
380
+ lockfileDrift: false,
381
+ epicCompletenessClean: true,
382
+ // doubleListingClean omitted
383
+ });
384
+ expect(result.success).toBe(false);
385
+ });
386
+ it('ReleasePlanChangelogSchema applies empty-array defaults for omitted buckets', () => {
387
+ const result = ReleasePlanChangelogSchema.parse({});
388
+ expect(result.features).toEqual([]);
389
+ expect(result.fixes).toEqual([]);
390
+ expect(result.chores).toEqual([]);
391
+ expect(result.breaking).toEqual([]);
392
+ });
393
+ it('ReleasePlanSchema accepts plans with no tasks (e.g. config-only releases)', () => {
394
+ const plan = makeValidPlan();
395
+ plan.tasks = [];
396
+ plan.changelog.features = [];
397
+ expect(() => parseReleasePlan(plan)).not.toThrow();
398
+ });
399
+ it('safeParseReleasePlan surfaces issues for bad enums', () => {
400
+ const result = safeParseReleasePlan({ ...makeValidPlan(), channel: 'invalid-channel' });
401
+ expect(result.success).toBe(false);
402
+ if (!result.success) {
403
+ expect(result.error.issues.length).toBeGreaterThan(0);
404
+ }
405
+ });
406
+ });
407
+ // ─── Schema export sanity ────────────────────────────────────────────────────
408
+ describe('ReleasePlanSchema — module surface', () => {
409
+ it('exports a Zod object schema at the top level', () => {
410
+ expect(typeof ReleasePlanSchema.parse).toBe('function');
411
+ expect(typeof ReleasePlanSchema.safeParse).toBe('function');
412
+ });
413
+ });
414
+ //# sourceMappingURL=plan.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.test.js","sourceRoot":"","sources":["../../src/release/plan.test.ts"],"names":[],"mappings":"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"}
@@ -51,8 +51,8 @@ import { z } from 'zod';
51
51
  export declare const ArchiveReason: z.ZodEnum<{
52
52
  cancelled: "cancelled";
53
53
  superseded: "superseded";
54
- verified: "verified";
55
54
  reconciled: "reconciled";
55
+ verified: "verified";
56
56
  shadowed: "shadowed";
57
57
  "completed-unverified": "completed-unverified";
58
58
  }>;
@@ -67,8 +67,8 @@ export declare const ArchiveReason: z.ZodEnum<{
67
67
  export declare const ArchiveReasonSchema: z.ZodEnum<{
68
68
  cancelled: "cancelled";
69
69
  superseded: "superseded";
70
- verified: "verified";
71
70
  reconciled: "reconciled";
71
+ verified: "verified";
72
72
  shadowed: "shadowed";
73
73
  "completed-unverified": "completed-unverified";
74
74
  }>;
@@ -93,7 +93,7 @@ export type ArchiveReasonValue = z.infer<typeof ArchiveReason>;
93
93
  * Useful when a Drizzle column or a discriminated union needs the raw
94
94
  * tuple form (e.g. `text('archive_reason', { enum: ARCHIVE_REASON_VALUES })`).
95
95
  */
96
- export declare const ARCHIVE_REASON_VALUES: ("cancelled" | "superseded" | "verified" | "reconciled" | "shadowed" | "completed-unverified")[];
96
+ export declare const ARCHIVE_REASON_VALUES: ("cancelled" | "superseded" | "reconciled" | "verified" | "shadowed" | "completed-unverified")[];
97
97
  /**
98
98
  * The single tombstone value within {@link ArchiveReason}.
99
99
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleocode/contracts",
3
- "version": "2026.5.77",
3
+ "version": "2026.5.79",
4
4
  "description": "Domain types, interfaces, and contracts for the CLEO ecosystem",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -98,7 +98,7 @@
98
98
  "dependencies": {
99
99
  "zod": "^4.3.6",
100
100
  "zod-to-json-schema": "^3.25.2",
101
- "@cleocode/lafs": "2026.5.77"
101
+ "@cleocode/lafs": "2026.5.79"
102
102
  },
103
103
  "scripts": {
104
104
  "build": "tsc -b --force && node scripts/emit-schemas.mjs",
package/src/config.ts CHANGED
@@ -175,14 +175,19 @@ export interface SharingConfig {
175
175
  /**
176
176
  * Memory bridge injection mode.
177
177
  *
178
- * - `'cli'` — AGENTS.md receives a `cleo memory digest --brief` CLI directive instead of
179
- * `@.cleo/memory-bridge.md`. The bridge markdown file is NOT written on refresh.
180
- * This is the default for new installations (T999).
181
- * - `'file'` Legacy behavior: `.cleo/memory-bridge.md` is written on refresh and
182
- * `@.cleo/memory-bridge.md` is injected into AGENTS.md verbatim.
183
- * Use this for backcompat with tooling that reads the file directly.
178
+ * - `'cli'` — AGENTS.md receives a `cleo memory digest --brief` CLI directive instead of
179
+ * `@.cleo/memory-bridge.md`. The bridge markdown file is NOT written on refresh.
180
+ * This is the default for new installations (T999). Also surfaced to operators
181
+ * as the `digest` mode in `cleo setup` (T9425) the wire value stays `'cli'`
182
+ * so existing project configs keep working unchanged.
183
+ * - `'file'` — Legacy behavior: `.cleo/memory-bridge.md` is written on refresh and
184
+ * `@.cleo/memory-bridge.md` is injected into AGENTS.md verbatim.
185
+ * Use this for backcompat with tooling that reads the file directly.
186
+ * - `'disabled'` — Bridge injection is suppressed entirely; AGENTS.md gets neither a CLI
187
+ * directive nor a file include. Operators select this from `cleo setup`
188
+ * when they want to opt out of BRAIN-driven AGENTS.md augmentation (T9425).
184
189
  */
185
- export type MemoryBridgeMode = 'cli' | 'file';
190
+ export type MemoryBridgeMode = 'cli' | 'file' | 'disabled';
186
191
 
187
192
  /**
188
193
  * Brain memory bridge refresh configuration.
@@ -588,6 +593,61 @@ export interface CleoConfig {
588
593
  * @defaultValue undefined
589
594
  */
590
595
  briefing?: BriefingConfig;
596
+ /**
597
+ * Auth-source consent gates for credential seeders.
598
+ *
599
+ * Gates third-party credential imports (e.g. Claude Code OAuth) behind
600
+ * explicit operator opt-in. Mirrors Hermes Agent's PR #4210 consent gate.
601
+ *
602
+ * @defaultValue undefined
603
+ * @task T9410
604
+ */
605
+ auth?: AuthConfig;
606
+ }
607
+
608
+ /**
609
+ * Auth-source consent configuration.
610
+ *
611
+ * Concrete `CredentialSeeder` implementations consult these flags before
612
+ * reading any third-party credential file (e.g. `~/.claude/.credentials.json`).
613
+ * Defaulting every flag to `false` keeps auxiliary fallback chains opt-in:
614
+ * aux callers cannot silently read user credentials they were never granted.
615
+ *
616
+ * @task T9410
617
+ */
618
+ export interface AuthConfig {
619
+ /**
620
+ * Whether the operator has explicitly opted in to import the Claude Code
621
+ * OAuth token (`~/.claude/.credentials.json`) into the CLEO credential
622
+ * pool.
623
+ *
624
+ * When `false` (default), the `claude-code` seeder MUST NOT read the file
625
+ * and MUST return an empty seeder result. When `true`, the seeder reads
626
+ * the file and emits a single `source: 'claude-code'` entry for the
627
+ * `anthropic` provider.
628
+ *
629
+ * @defaultValue false
630
+ */
631
+ claudeCodeConsentGiven?: boolean;
632
+ /**
633
+ * Whether CLEO writes refreshed Anthropic OAuth tokens back to Claude
634
+ * Code's credential file (`~/.claude/.credentials.json`) in addition to
635
+ * CLEO's own canonical token file (`${getCleoHome()}/anthropic-oauth.json`).
636
+ *
637
+ * CLEO ALWAYS writes its own file on every refresh. The cooperative write
638
+ * to Claude Code's file is gated by this flag AND by either
639
+ * (a) the Claude Code file already existing on disk, or
640
+ * (b) `claudeCodeConsentGiven` being `true`.
641
+ *
642
+ * This mirrors the OQ-1 decision in `docs/plans/E-CONFIG-AUTH-UNIFY.md`:
643
+ * cooperative write-back is enabled by default so two CLIs sharing one
644
+ * machine stay token-coherent, but CLEO never creates Claude Code's file
645
+ * unless the operator has explicitly opted in.
646
+ *
647
+ * @defaultValue true
648
+ * @task T9411
649
+ */
650
+ cooperativeWriteBack?: boolean;
591
651
  }
592
652
 
593
653
  /**
@@ -32,6 +32,16 @@ export interface ClaudeCodeOAuthBlock {
32
32
  expiresAt?: number;
33
33
  /** Refresh token for obtaining new access tokens. Optional. */
34
34
  refreshToken?: string;
35
+ /**
36
+ * OAuth scopes granted to the token, e.g. `['user:inference']`.
37
+ *
38
+ * Claude Code >= 2.1.81 requires the `user:inference` scope on its OAuth
39
+ * tokens; cooperative write-back (T9411) preserves whatever scopes are
40
+ * already on disk so we never strip the field on refresh.
41
+ *
42
+ * @task T9411
43
+ */
44
+ scopes?: string[];
35
45
  }
36
46
 
37
47
  /**
@@ -47,6 +57,16 @@ export interface ParsedClaudeCodeCredential {
47
57
  expiresAt?: number;
48
58
  /** Refresh token, if present in the credentials file. */
49
59
  refreshToken?: string;
60
+ /**
61
+ * OAuth scopes granted to the token, if present in the credentials file.
62
+ *
63
+ * Preserved verbatim by the parser — `parseClaudeCodeCredentials` does not
64
+ * filter or normalize the array. Cooperative write-back (T9411) relies on
65
+ * this to keep Claude Code's `user:inference` scope intact across refreshes.
66
+ *
67
+ * @task T9411
68
+ */
69
+ scopes?: string[];
50
70
  }
51
71
 
52
72
  // ---------------------------------------------------------------------------
@@ -103,10 +123,19 @@ export function parseClaudeCodeCredentials(
103
123
  ? block['refreshToken']
104
124
  : undefined;
105
125
 
126
+ // T9411 — preserve `scopes` verbatim so cooperative write-back keeps
127
+ // Claude Code's `user:inference` grant intact across refreshes.
128
+ const rawScopes = block['scopes'];
129
+ const scopes =
130
+ Array.isArray(rawScopes) && rawScopes.every((s) => typeof s === 'string')
131
+ ? (rawScopes as string[])
132
+ : undefined;
133
+
106
134
  return {
107
135
  accessToken: accessToken.trim(),
108
136
  ...(expiresAt !== undefined ? { expiresAt } : {}),
109
137
  ...(refreshToken !== undefined ? { refreshToken } : {}),
138
+ ...(scopes !== undefined ? { scopes } : {}),
110
139
  };
111
140
  } catch {
112
141
  return null;