@cleocode/contracts 2026.5.61 → 2026.5.62

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 (70) hide show
  1. package/dist/__tests__/nexus-scope-map.test.d.ts +8 -0
  2. package/dist/__tests__/nexus-scope-map.test.d.ts.map +1 -0
  3. package/dist/__tests__/nexus-scope-map.test.js +145 -0
  4. package/dist/__tests__/nexus-scope-map.test.js.map +1 -0
  5. package/dist/branch-lock.d.ts +11 -0
  6. package/dist/branch-lock.d.ts.map +1 -1
  7. package/dist/branch-lock.js +11 -0
  8. package/dist/branch-lock.js.map +1 -1
  9. package/dist/config.d.ts +21 -0
  10. package/dist/config.d.ts.map +1 -1
  11. package/dist/data-accessor.d.ts +2 -0
  12. package/dist/data-accessor.d.ts.map +1 -1
  13. package/dist/data-accessor.js.map +1 -1
  14. package/dist/engine-result.d.ts +170 -0
  15. package/dist/engine-result.d.ts.map +1 -0
  16. package/dist/engine-result.js +123 -0
  17. package/dist/engine-result.js.map +1 -0
  18. package/dist/errors.d.ts +24 -0
  19. package/dist/errors.d.ts.map +1 -1
  20. package/dist/errors.js +31 -0
  21. package/dist/errors.js.map +1 -1
  22. package/dist/exit-codes.d.ts +8 -1
  23. package/dist/exit-codes.d.ts.map +1 -1
  24. package/dist/exit-codes.js +7 -0
  25. package/dist/exit-codes.js.map +1 -1
  26. package/dist/graph.d.ts +88 -0
  27. package/dist/graph.d.ts.map +1 -1
  28. package/dist/graph.js +35 -0
  29. package/dist/graph.js.map +1 -1
  30. package/dist/index.d.ts +10 -5
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +6 -2
  33. package/dist/index.js.map +1 -1
  34. package/dist/operations/nexus-scope-map.d.ts +540 -0
  35. package/dist/operations/nexus-scope-map.d.ts.map +1 -0
  36. package/dist/operations/nexus-scope-map.js +556 -0
  37. package/dist/operations/nexus-scope-map.js.map +1 -0
  38. package/dist/operations/nexus-scope.d.ts +185 -0
  39. package/dist/operations/nexus-scope.d.ts.map +1 -0
  40. package/dist/operations/nexus-scope.js +9 -0
  41. package/dist/operations/nexus-scope.js.map +1 -0
  42. package/dist/operations/session.d.ts +79 -0
  43. package/dist/operations/session.d.ts.map +1 -1
  44. package/dist/operations/tasks.d.ts +28 -0
  45. package/dist/operations/tasks.d.ts.map +1 -1
  46. package/dist/operations/worktree.d.ts +33 -0
  47. package/dist/operations/worktree.d.ts.map +1 -1
  48. package/dist/task.d.ts +17 -2
  49. package/dist/task.d.ts.map +1 -1
  50. package/dist/task.js +11 -1
  51. package/dist/task.js.map +1 -1
  52. package/dist/tasks.d.ts +0 -2
  53. package/dist/tasks.d.ts.map +1 -1
  54. package/package.json +2 -2
  55. package/src/__tests__/nexus-scope-map.test.ts +183 -0
  56. package/src/branch-lock.ts +11 -0
  57. package/src/config.ts +22 -0
  58. package/src/data-accessor.ts +3 -0
  59. package/src/engine-result.ts +220 -0
  60. package/src/errors.ts +34 -0
  61. package/src/exit-codes.ts +8 -0
  62. package/src/graph.ts +112 -0
  63. package/src/index.ts +49 -2
  64. package/src/operations/nexus-scope-map.ts +597 -0
  65. package/src/operations/nexus-scope.ts +217 -0
  66. package/src/operations/session.ts +87 -0
  67. package/src/operations/tasks.ts +30 -0
  68. package/src/operations/worktree.ts +33 -0
  69. package/src/task.ts +30 -1
  70. package/src/tasks.ts +0 -2
package/src/index.ts CHANGED
@@ -265,6 +265,20 @@ export type {
265
265
  StoreDocParams,
266
266
  StoreDocResult,
267
267
  } from './docs-accessor.js';
268
+ export type {
269
+ EngineErrorPayload,
270
+ EngineFailure,
271
+ EngineResult,
272
+ EngineSuccess,
273
+ ProblemDetails,
274
+ } from './engine-result.js';
275
+ // === EngineResult — canonical discriminated-union SDK type (T1685) ===
276
+ export {
277
+ EngineResultError,
278
+ engineError,
279
+ engineSuccess,
280
+ unwrap,
281
+ } from './engine-result.js';
268
282
  // === Error Utilities ===
269
283
  export {
270
284
  ClassifierUnregisteredAgentError,
@@ -275,6 +289,7 @@ export {
275
289
  getErrorMessage,
276
290
  isErrorResult,
277
291
  isErrorType,
292
+ LeadBypassDetectedError,
278
293
  LifecycleScopeDeniedError,
279
294
  normalizeError,
280
295
  ThinAgentViolationError,
@@ -352,20 +367,28 @@ export {
352
367
  AGENT_TYPES,
353
368
  BRAIN_OBSERVATION_TYPES,
354
369
  } from './facade.js';
355
- // === Graph Intelligence Types (T512, T529, T1862) ===
370
+ // === Graph Intelligence Types (T512, T529, T1862, T9145) ===
356
371
  export type {
372
+ AmbiguousProvenance,
357
373
  CommunityNode,
374
+ ConfidenceProvenance,
375
+ ExtractedProvenance,
358
376
  GraphEdgeConfidenceLabel,
359
377
  GraphNode,
360
378
  GraphNodeKind,
361
379
  GraphRelation,
362
380
  GraphRelationType,
363
381
  ImpactResult,
382
+ InferredProvenance,
364
383
  KnowledgeGraph,
365
384
  ProcessNode,
366
385
  SymbolIndex,
367
386
  } from './graph.js';
368
- export { confidenceLabelFromNumeric } from './graph.js';
387
+ export {
388
+ confidenceFromProvenance,
389
+ confidenceLabelFromNumeric,
390
+ provenanceFromNumeric,
391
+ } from './graph.js';
369
392
  export type { AdapterHookProvider } from './hooks.js';
370
393
  export type { AdapterInstallProvider, InstallOptions, InstallResult } from './install.js';
371
394
  export type {
@@ -752,6 +775,23 @@ export type {
752
775
  NexusWhyResult,
753
776
  NexusWikiParams,
754
777
  } from './operations/nexus.js';
778
+ // === Nexus Scope Contracts (T9145 + T9146) ===
779
+ export type {
780
+ MetaWithNexusScope,
781
+ NexusBindingSource,
782
+ NexusEffect,
783
+ NexusOperationDescriptor,
784
+ NexusScope,
785
+ NexusScopeMeta,
786
+ NexusStore,
787
+ ScopeBinding,
788
+ SuggestedNextOp,
789
+ } from './operations/nexus-scope.js';
790
+ export {
791
+ getNexusDescriptor,
792
+ listOpsByScope,
793
+ NEXUS_SCOPE_MAP,
794
+ } from './operations/nexus-scope-map.js';
755
795
  // === NEXUS User Profile Types (T1076 PSYCHE Wave 1) ===
756
796
  // Re-exported at top level so @cleocode/core/nexus and CLI dispatch can
757
797
  // import without the `ops.` namespace hop.
@@ -812,6 +852,10 @@ export type {
812
852
  // Session operation param/result types — re-exported at top level for typed-dispatch consumers
813
853
  // (T975 Wave D · ADR-051 migration)
814
854
  export type {
855
+ BriefingExcludeProvenance,
856
+ BriefingFieldContract,
857
+ BriefingFieldRule,
858
+ ContractViolation,
815
859
  DecisionRecord,
816
860
  SessionBriefingShowParams,
817
861
  SessionBriefingShowResult,
@@ -894,6 +938,8 @@ export type {
894
938
  TasksRelatesAddParams,
895
939
  TasksRelatesAddResult,
896
940
  TasksRelatesParams,
941
+ TasksRelatesRemoveParams,
942
+ TasksRelatesRemoveResult,
897
943
  TasksRelatesResult,
898
944
  TasksReorderDispatchResult,
899
945
  TasksReorderQueryParams,
@@ -1199,6 +1245,7 @@ export type {
1199
1245
  VerificationFailure,
1200
1246
  VerificationGate,
1201
1247
  } from './task.js';
1248
+ export { isTestFixtureOrigin, TASK_ORIGIN_CANONICAL } from './task.js';
1202
1249
  // === Task Evidence Types (T801) ===
1203
1250
  export type {
1204
1251
  CommandOutputEvidence,
@@ -0,0 +1,597 @@
1
+ /**
2
+ * NEXUS_SCOPE_MAP — Single Source of Truth for Nexus operation metadata.
3
+ *
4
+ * Maps every key of {@link NexusOps} to a {@link NexusOperationDescriptor},
5
+ * enabling compile-time exhaustiveness checking (via `_ExhaustivenessCheck`)
6
+ * and runtime helpers (`getNexusDescriptor`, `listOpsByScope`).
7
+ *
8
+ * To add a new Nexus operation:
9
+ * 1. Add the key to `NexusOps` in `nexus.ts`.
10
+ * 2. Add the corresponding entry here — the build will fail until both are present.
11
+ *
12
+ * @task T9145
13
+ * @module operations/nexus-scope-map
14
+ */
15
+
16
+ import type { NexusOps } from './nexus.js';
17
+ import type { NexusOperationDescriptor } from './nexus-scope.js';
18
+
19
+ // ---------------------------------------------------------------------------
20
+ // SSoT map
21
+ // ---------------------------------------------------------------------------
22
+
23
+ /**
24
+ * Single Source of Truth mapping every NexusOps key to its descriptor.
25
+ *
26
+ * `satisfies Record<keyof NexusOps, NexusOperationDescriptor>` enforces
27
+ * exhaustiveness at compile time — adding a new key to NexusOps without a
28
+ * corresponding entry here is a type error.
29
+ */
30
+ export const NEXUS_SCOPE_MAP = {
31
+ // ── Query / read ops ──────────────────────────────────────────────────────
32
+
33
+ status: {
34
+ op: 'status',
35
+ description: 'Check whether nexus.db is open and accessible.',
36
+ scope: 'project',
37
+ effect: 'read',
38
+ stores: ['nexus-graph'],
39
+ requiresProject: true,
40
+ },
41
+ list: {
42
+ op: 'list',
43
+ description: 'List all registered Nexus projects.',
44
+ scope: 'global',
45
+ effect: 'read',
46
+ stores: ['nexus-registry'],
47
+ requiresProject: false,
48
+ },
49
+ show: {
50
+ op: 'show',
51
+ description: 'Show details for a registered project.',
52
+ scope: 'global',
53
+ effect: 'read',
54
+ stores: ['nexus-registry'],
55
+ requiresProject: false,
56
+ },
57
+ resolve: {
58
+ op: 'resolve',
59
+ description: 'Resolve a symbol name to its graph node(s).',
60
+ scope: 'project',
61
+ effect: 'read',
62
+ stores: ['nexus-graph'],
63
+ requiresProject: true,
64
+ },
65
+ deps: {
66
+ op: 'deps',
67
+ description: 'List dependencies of a symbol (callers or callees).',
68
+ scope: 'project',
69
+ effect: 'read',
70
+ stores: ['nexus-graph'],
71
+ requiresProject: true,
72
+ },
73
+ graph: {
74
+ op: 'graph',
75
+ description: 'Return the raw graph (nodes + relations) for a project.',
76
+ scope: 'project',
77
+ effect: 'read',
78
+ stores: ['nexus-graph'],
79
+ requiresProject: true,
80
+ },
81
+ 'path.show': {
82
+ op: 'path.show',
83
+ description: 'Show the shortest graph path between two symbols.',
84
+ scope: 'project',
85
+ effect: 'read',
86
+ stores: ['nexus-graph'],
87
+ requiresProject: true,
88
+ },
89
+ 'blockers.show': {
90
+ op: 'blockers.show',
91
+ description: 'Show symbols that block a given symbol from being resolved.',
92
+ scope: 'project',
93
+ effect: 'read',
94
+ stores: ['nexus-graph'],
95
+ requiresProject: true,
96
+ },
97
+ 'orphans.list': {
98
+ op: 'orphans.list',
99
+ description: 'List graph nodes with no incoming or outgoing edges.',
100
+ scope: 'project',
101
+ effect: 'read',
102
+ stores: ['nexus-graph'],
103
+ requiresProject: true,
104
+ },
105
+ discover: {
106
+ op: 'discover',
107
+ description: 'Discover the codebase structure (file tree + symbol counts).',
108
+ scope: 'project',
109
+ effect: 'read',
110
+ stores: ['nexus-graph', 'fs'],
111
+ requiresProject: true,
112
+ },
113
+ search: {
114
+ op: 'search',
115
+ description: 'Full-text / semantic search over symbol names and docstrings.',
116
+ scope: 'project',
117
+ effect: 'read',
118
+ stores: ['nexus-graph'],
119
+ requiresProject: true,
120
+ },
121
+ augment: {
122
+ op: 'augment',
123
+ description: 'Augment the graph with enriched metadata (embeddings, docs).',
124
+ scope: 'project',
125
+ effect: 'write',
126
+ stores: ['nexus-graph'],
127
+ requiresProject: true,
128
+ },
129
+ 'share.status': {
130
+ op: 'share.status',
131
+ description: 'Check snapshot sharing status for a project.',
132
+ scope: 'project',
133
+ effect: 'read',
134
+ stores: ['nexus-graph'],
135
+ requiresProject: true,
136
+ },
137
+ 'transfer.preview': {
138
+ op: 'transfer.preview',
139
+ description: 'Preview a graph transfer (dry-run diff).',
140
+ scope: 'cross',
141
+ effect: 'read',
142
+ stores: ['nexus-graph'],
143
+ requiresProject: true,
144
+ },
145
+ 'top-entries': {
146
+ op: 'top-entries',
147
+ description: 'Return the top-N highest-centrality nodes.',
148
+ scope: 'project',
149
+ effect: 'read',
150
+ stores: ['nexus-graph'],
151
+ requiresProject: true,
152
+ },
153
+ impact: {
154
+ op: 'impact',
155
+ description: 'Compute the blast radius (upstream/downstream) of a change.',
156
+ scope: 'project',
157
+ effect: 'read',
158
+ stores: ['nexus-graph'],
159
+ requiresProject: true,
160
+ indexSensitive: true,
161
+ },
162
+ 'full-context': {
163
+ op: 'full-context',
164
+ description: 'Return the full 360-degree context for a symbol.',
165
+ scope: 'project',
166
+ effect: 'read',
167
+ stores: ['nexus-graph'],
168
+ requiresProject: true,
169
+ },
170
+ 'task-footprint': {
171
+ op: 'task-footprint',
172
+ description: 'Return graph nodes touched by a given task ID.',
173
+ scope: 'hybrid',
174
+ effect: 'read',
175
+ stores: ['nexus-graph', 'tasks'],
176
+ requiresProject: true,
177
+ },
178
+ 'brain-anchors': {
179
+ op: 'brain-anchors',
180
+ description: 'Return BRAIN memory entries anchored to graph nodes.',
181
+ scope: 'hybrid',
182
+ effect: 'read',
183
+ stores: ['nexus-graph', 'brain'],
184
+ requiresProject: true,
185
+ },
186
+ why: {
187
+ op: 'why',
188
+ description: 'Explain why a symbol exists (provenance + context).',
189
+ scope: 'hybrid',
190
+ effect: 'read',
191
+ stores: ['nexus-graph', 'brain'],
192
+ requiresProject: true,
193
+ },
194
+ 'impact-full': {
195
+ op: 'impact-full',
196
+ description: 'Full multi-hop impact analysis with community context.',
197
+ scope: 'project',
198
+ effect: 'read',
199
+ stores: ['nexus-graph'],
200
+ requiresProject: true,
201
+ indexSensitive: true,
202
+ },
203
+ 'route-map': {
204
+ op: 'route-map',
205
+ description: 'Generate a route map for execution flow tracing.',
206
+ scope: 'project',
207
+ effect: 'read',
208
+ stores: ['nexus-graph'],
209
+ requiresProject: true,
210
+ },
211
+ 'shape-check': {
212
+ op: 'shape-check',
213
+ description: 'Validate that a symbol conforms to a declared contract shape.',
214
+ scope: 'project',
215
+ effect: 'read',
216
+ stores: ['nexus-graph'],
217
+ requiresProject: true,
218
+ },
219
+ 'search-code': {
220
+ op: 'search-code',
221
+ description: 'Search code by pattern across the project graph.',
222
+ scope: 'project',
223
+ effect: 'read',
224
+ stores: ['nexus-graph', 'fs'],
225
+ requiresProject: true,
226
+ },
227
+ wiki: {
228
+ op: 'wiki',
229
+ description: 'Generate a wiki-style description for a symbol or module.',
230
+ scope: 'project',
231
+ effect: 'read',
232
+ stores: ['nexus-graph'],
233
+ requiresProject: true,
234
+ },
235
+ 'contracts-show': {
236
+ op: 'contracts-show',
237
+ description: 'Show the contract compliance record for a symbol.',
238
+ scope: 'project',
239
+ effect: 'read',
240
+ stores: ['nexus-graph'],
241
+ requiresProject: true,
242
+ },
243
+ 'task-symbols': {
244
+ op: 'task-symbols',
245
+ description: 'List graph symbols associated with a task.',
246
+ scope: 'hybrid',
247
+ effect: 'read',
248
+ stores: ['nexus-graph', 'tasks'],
249
+ requiresProject: true,
250
+ },
251
+
252
+ // ── Profile ops ───────────────────────────────────────────────────────────
253
+
254
+ 'profile.view': {
255
+ op: 'profile.view',
256
+ description: 'View all user profile traits from the living-brain.',
257
+ scope: 'living-brain',
258
+ effect: 'read',
259
+ stores: ['brain'],
260
+ requiresProject: false,
261
+ },
262
+ 'profile.get': {
263
+ op: 'profile.get',
264
+ description: 'Get a single user profile trait.',
265
+ scope: 'living-brain',
266
+ effect: 'read',
267
+ stores: ['brain'],
268
+ requiresProject: false,
269
+ },
270
+ 'profile.import': {
271
+ op: 'profile.import',
272
+ description: 'Import user profile traits from a JSON file.',
273
+ scope: 'living-brain',
274
+ effect: 'write',
275
+ stores: ['brain'],
276
+ requiresProject: false,
277
+ },
278
+ 'profile.export': {
279
+ op: 'profile.export',
280
+ description: 'Export user profile traits to JSON.',
281
+ scope: 'living-brain',
282
+ effect: 'read',
283
+ stores: ['brain'],
284
+ requiresProject: false,
285
+ },
286
+ 'profile.reinforce': {
287
+ op: 'profile.reinforce',
288
+ description: 'Reinforce a user profile trait (increase confidence).',
289
+ scope: 'living-brain',
290
+ effect: 'write',
291
+ stores: ['brain'],
292
+ requiresProject: false,
293
+ },
294
+ 'profile.upsert': {
295
+ op: 'profile.upsert',
296
+ description: 'Upsert a user profile trait.',
297
+ scope: 'living-brain',
298
+ effect: 'write',
299
+ stores: ['brain'],
300
+ requiresProject: false,
301
+ },
302
+ 'profile.supersede': {
303
+ op: 'profile.supersede',
304
+ description: 'Mark a user profile trait as superseded by another.',
305
+ scope: 'living-brain',
306
+ effect: 'write',
307
+ stores: ['brain'],
308
+ requiresProject: false,
309
+ },
310
+
311
+ // ── Sigil ops ─────────────────────────────────────────────────────────────
312
+
313
+ 'sigil.list': {
314
+ op: 'sigil.list',
315
+ description: 'List code sigils (bookmarks / anchors) in a project.',
316
+ scope: 'project',
317
+ effect: 'read',
318
+ stores: ['nexus-graph'],
319
+ requiresProject: true,
320
+ },
321
+ 'sigil.sync': {
322
+ op: 'sigil.sync',
323
+ description: 'Sync sigils with the current graph state.',
324
+ scope: 'project',
325
+ effect: 'write',
326
+ stores: ['nexus-graph'],
327
+ requiresProject: true,
328
+ },
329
+
330
+ // ── Registry / admin ops ──────────────────────────────────────────────────
331
+
332
+ init: {
333
+ op: 'init',
334
+ description: 'Initialize a new Nexus project database.',
335
+ scope: 'project',
336
+ effect: 'admin',
337
+ stores: ['nexus-graph', 'nexus-registry'],
338
+ requiresProject: true,
339
+ },
340
+ register: {
341
+ op: 'register',
342
+ description: 'Register a project with the global Nexus registry.',
343
+ scope: 'global',
344
+ effect: 'admin',
345
+ stores: ['nexus-registry'],
346
+ requiresProject: false,
347
+ },
348
+ unregister: {
349
+ op: 'unregister',
350
+ description: 'Remove a project from the global Nexus registry.',
351
+ scope: 'global',
352
+ effect: 'admin',
353
+ stores: ['nexus-registry'],
354
+ requiresProject: false,
355
+ },
356
+ sync: {
357
+ op: 'sync',
358
+ description: 'Re-analyze and sync the project graph with the codebase.',
359
+ scope: 'project',
360
+ effect: 'write',
361
+ stores: ['nexus-graph', 'fs'],
362
+ requiresProject: true,
363
+ },
364
+ 'permission.set': {
365
+ op: 'permission.set',
366
+ description: 'Set access permissions for a Nexus project.',
367
+ scope: 'global',
368
+ effect: 'admin',
369
+ stores: ['nexus-registry'],
370
+ requiresProject: false,
371
+ },
372
+ reconcile: {
373
+ op: 'reconcile',
374
+ description: 'Reconcile graph state with on-disk source files.',
375
+ scope: 'project',
376
+ effect: 'write',
377
+ stores: ['nexus-graph', 'fs'],
378
+ requiresProject: true,
379
+ },
380
+ 'share.snapshot.export': {
381
+ op: 'share.snapshot.export',
382
+ description: 'Export a shareable snapshot of the project graph.',
383
+ scope: 'project',
384
+ effect: 'read',
385
+ stores: ['nexus-graph', 'fs'],
386
+ requiresProject: true,
387
+ },
388
+ 'share.snapshot.import': {
389
+ op: 'share.snapshot.import',
390
+ description: 'Import a shared project graph snapshot.',
391
+ scope: 'project',
392
+ effect: 'write',
393
+ stores: ['nexus-graph'],
394
+ requiresProject: true,
395
+ },
396
+ transfer: {
397
+ op: 'transfer',
398
+ description: 'Transfer graph data between projects.',
399
+ scope: 'cross',
400
+ effect: 'write',
401
+ stores: ['nexus-graph'],
402
+ requiresProject: true,
403
+ },
404
+ 'contracts-sync': {
405
+ op: 'contracts-sync',
406
+ description: 'Sync contract compliance records with the graph.',
407
+ scope: 'project',
408
+ effect: 'write',
409
+ stores: ['nexus-graph'],
410
+ requiresProject: true,
411
+ },
412
+ 'contracts-link-tasks': {
413
+ op: 'contracts-link-tasks',
414
+ description: 'Link contract compliance records to task IDs.',
415
+ scope: 'hybrid',
416
+ effect: 'write',
417
+ stores: ['nexus-graph', 'tasks'],
418
+ requiresProject: true,
419
+ },
420
+ 'conduit-scan': {
421
+ op: 'conduit-scan',
422
+ description: 'Scan Conduit messaging patterns into the graph.',
423
+ scope: 'project',
424
+ effect: 'write',
425
+ stores: ['nexus-graph'],
426
+ requiresProject: true,
427
+ },
428
+
429
+ // ── Analytics ops ─────────────────────────────────────────────────────────
430
+
431
+ clusters: {
432
+ op: 'clusters',
433
+ description: 'Return detected community clusters in the graph.',
434
+ scope: 'project',
435
+ effect: 'read',
436
+ stores: ['nexus-graph'],
437
+ requiresProject: true,
438
+ },
439
+ flows: {
440
+ op: 'flows',
441
+ description: 'Return detected execution flows (process traces).',
442
+ scope: 'project',
443
+ effect: 'read',
444
+ stores: ['nexus-graph'],
445
+ requiresProject: true,
446
+ },
447
+ context: {
448
+ op: 'context',
449
+ description: 'Return project context summary (node/relation counts, freshness).',
450
+ scope: 'project',
451
+ effect: 'read',
452
+ stores: ['nexus-graph'],
453
+ requiresProject: true,
454
+ indexSensitive: true,
455
+ },
456
+ 'projects.list': {
457
+ op: 'projects.list',
458
+ description: 'List all registered projects (alias: list).',
459
+ scope: 'global',
460
+ effect: 'read',
461
+ stores: ['nexus-registry'],
462
+ requiresProject: false,
463
+ },
464
+ 'projects.register': {
465
+ op: 'projects.register',
466
+ description: 'Register a project (alias: register).',
467
+ scope: 'global',
468
+ effect: 'admin',
469
+ stores: ['nexus-registry'],
470
+ requiresProject: false,
471
+ },
472
+ 'projects.remove': {
473
+ op: 'projects.remove',
474
+ description: 'Remove a project (alias: unregister).',
475
+ scope: 'global',
476
+ effect: 'admin',
477
+ stores: ['nexus-registry'],
478
+ requiresProject: false,
479
+ },
480
+ 'projects.scan': {
481
+ op: 'projects.scan',
482
+ description: 'Scan a project directory and update the registry.',
483
+ scope: 'global',
484
+ effect: 'admin',
485
+ stores: ['nexus-registry', 'fs'],
486
+ requiresProject: false,
487
+ },
488
+ 'projects.clean': {
489
+ op: 'projects.clean',
490
+ description: 'Remove stale project entries from the registry.',
491
+ scope: 'global',
492
+ effect: 'admin',
493
+ stores: ['nexus-registry'],
494
+ requiresProject: false,
495
+ },
496
+ 'refresh-bridge': {
497
+ op: 'refresh-bridge',
498
+ description: 'Refresh the Nexus → BRAIN cross-store bridge.',
499
+ scope: 'hybrid',
500
+ effect: 'write',
501
+ stores: ['nexus-graph', 'brain'],
502
+ requiresProject: true,
503
+ },
504
+ diff: {
505
+ op: 'diff',
506
+ description: 'Diff the graph between two commits or snapshots.',
507
+ scope: 'project',
508
+ effect: 'read',
509
+ stores: ['nexus-graph', 'fs'],
510
+ requiresProject: true,
511
+ indexSensitive: true,
512
+ },
513
+ 'query-cte': {
514
+ op: 'query-cte',
515
+ description: 'Execute a raw CTE query against the Nexus graph DB.',
516
+ scope: 'project',
517
+ effect: 'read',
518
+ stores: ['nexus-graph'],
519
+ requiresProject: true,
520
+ },
521
+ 'hot-paths': {
522
+ op: 'hot-paths',
523
+ description: 'Return the most frequently traversed call paths.',
524
+ scope: 'project',
525
+ effect: 'read',
526
+ stores: ['nexus-graph'],
527
+ requiresProject: true,
528
+ },
529
+ 'hot-nodes': {
530
+ op: 'hot-nodes',
531
+ description: 'Return the highest-degree (most connected) nodes.',
532
+ scope: 'project',
533
+ effect: 'read',
534
+ stores: ['nexus-graph'],
535
+ requiresProject: true,
536
+ },
537
+ 'cold-symbols': {
538
+ op: 'cold-symbols',
539
+ description: 'Return low-usage symbols that may be candidates for removal.',
540
+ scope: 'project',
541
+ effect: 'read',
542
+ stores: ['nexus-graph'],
543
+ requiresProject: true,
544
+ },
545
+ } as const satisfies Record<keyof NexusOps, NexusOperationDescriptor>;
546
+
547
+ // ---------------------------------------------------------------------------
548
+ // Compile-time exhaustiveness check
549
+ // ---------------------------------------------------------------------------
550
+
551
+ /**
552
+ * Fails the build if any key in {@link NexusOps} is missing from
553
+ * {@link NEXUS_SCOPE_MAP}.
554
+ *
555
+ * TypeScript will produce an error like:
556
+ * `Type 'keyof NexusOps' is not assignable to 'keyof typeof NEXUS_SCOPE_MAP'`
557
+ * when a new NexusOps key is added without a corresponding map entry.
558
+ *
559
+ * @internal
560
+ */
561
+ type _ExhaustivenessCheck = keyof typeof NEXUS_SCOPE_MAP extends keyof NexusOps
562
+ ? keyof NexusOps extends keyof typeof NEXUS_SCOPE_MAP
563
+ ? true
564
+ : never
565
+ : never;
566
+
567
+ // This assignment triggers the exhaustiveness check at compile time.
568
+ const _check: _ExhaustivenessCheck = true;
569
+ void _check;
570
+
571
+ // ---------------------------------------------------------------------------
572
+ // Runtime helpers
573
+ // ---------------------------------------------------------------------------
574
+
575
+ /**
576
+ * Return the {@link NexusOperationDescriptor} for a given Nexus operation key.
577
+ *
578
+ * @param op - Any key of {@link NexusOps}
579
+ * @returns The corresponding descriptor
580
+ */
581
+ export function getNexusDescriptor(op: keyof NexusOps): NexusOperationDescriptor {
582
+ return NEXUS_SCOPE_MAP[op];
583
+ }
584
+
585
+ /**
586
+ * Return all Nexus operation keys that match a given {@link NexusScope}.
587
+ *
588
+ * @param scope - The scope to filter by
589
+ * @returns Array of matching operation keys
590
+ */
591
+ export function listOpsByScope(
592
+ scope: import('./nexus-scope.js').NexusScope,
593
+ ): Array<keyof NexusOps> {
594
+ return (Object.keys(NEXUS_SCOPE_MAP) as Array<keyof NexusOps>).filter(
595
+ (k) => NEXUS_SCOPE_MAP[k].scope === scope,
596
+ );
597
+ }