@cleocode/contracts 2026.9.20 → 2026.9.21

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 (161) hide show
  1. package/README.md +1 -1
  2. package/dist/__tests__/decide.test.d.ts +7 -0
  3. package/dist/__tests__/decide.test.d.ts.map +1 -0
  4. package/dist/__tests__/decide.test.js +91 -0
  5. package/dist/__tests__/decide.test.js.map +1 -0
  6. package/dist/__tests__/evidence-atom-schema.test.js +2 -1
  7. package/dist/__tests__/evidence-atom-schema.test.js.map +1 -1
  8. package/dist/__tests__/memory-wire-shapes.test.js.map +1 -1
  9. package/dist/acceptance-gate-schema.d.ts +5 -0
  10. package/dist/acceptance-gate-schema.d.ts.map +1 -1
  11. package/dist/acceptance-gate-schema.js +26 -0
  12. package/dist/acceptance-gate-schema.js.map +1 -1
  13. package/dist/acceptance-gate.d.ts +70 -3
  14. package/dist/acceptance-gate.d.ts.map +1 -1
  15. package/dist/backup-manifest.d.ts +13 -2
  16. package/dist/backup-manifest.d.ts.map +1 -1
  17. package/dist/branch-lock.d.ts +11 -0
  18. package/dist/branch-lock.d.ts.map +1 -1
  19. package/dist/branch-lock.js +31 -4
  20. package/dist/branch-lock.js.map +1 -1
  21. package/dist/cloud/api.d.ts +607 -0
  22. package/dist/cloud/api.d.ts.map +1 -0
  23. package/dist/cloud/api.js +417 -0
  24. package/dist/cloud/api.js.map +1 -0
  25. package/dist/cloud/envelope.d.ts +84 -0
  26. package/dist/cloud/envelope.d.ts.map +1 -0
  27. package/dist/cloud/envelope.js +54 -0
  28. package/dist/cloud/envelope.js.map +1 -0
  29. package/dist/cloud/ids.d.ts +30 -0
  30. package/dist/cloud/ids.d.ts.map +1 -0
  31. package/dist/cloud/ids.js +32 -0
  32. package/dist/cloud/ids.js.map +1 -0
  33. package/dist/cloud/index.d.ts +17 -0
  34. package/dist/cloud/index.d.ts.map +1 -0
  35. package/dist/cloud/index.js +17 -0
  36. package/dist/cloud/index.js.map +1 -0
  37. package/dist/data-accessor.d.ts +23 -3
  38. package/dist/data-accessor.d.ts.map +1 -1
  39. package/dist/data-accessor.js.map +1 -1
  40. package/dist/decide.d.ts +333 -0
  41. package/dist/decide.d.ts.map +1 -0
  42. package/dist/decide.js +184 -0
  43. package/dist/decide.js.map +1 -0
  44. package/dist/dispatch/operations-registry.d.ts.map +1 -1
  45. package/dist/dispatch/operations-registry.js +55 -0
  46. package/dist/dispatch/operations-registry.js.map +1 -1
  47. package/dist/done-plan.d.ts +311 -0
  48. package/dist/done-plan.d.ts.map +1 -0
  49. package/dist/done-plan.js +17 -0
  50. package/dist/done-plan.js.map +1 -0
  51. package/dist/evidence-atom-schema.d.ts +18 -1
  52. package/dist/evidence-atom-schema.d.ts.map +1 -1
  53. package/dist/evidence-atom-schema.js +27 -2
  54. package/dist/evidence-atom-schema.js.map +1 -1
  55. package/dist/exit-codes.d.ts +40 -0
  56. package/dist/exit-codes.d.ts.map +1 -1
  57. package/dist/exit-codes.js +41 -0
  58. package/dist/exit-codes.js.map +1 -1
  59. package/dist/graph.d.ts +40 -0
  60. package/dist/graph.d.ts.map +1 -1
  61. package/dist/index.d.ts +13 -6
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +4 -0
  64. package/dist/index.js.map +1 -1
  65. package/dist/memory/observe.d.ts +16 -0
  66. package/dist/memory/observe.d.ts.map +1 -1
  67. package/dist/operations/__tests__/release-shared-surface.test.d.ts +10 -0
  68. package/dist/operations/__tests__/release-shared-surface.test.d.ts.map +1 -0
  69. package/dist/operations/__tests__/release-shared-surface.test.js +84 -0
  70. package/dist/operations/__tests__/release-shared-surface.test.js.map +1 -0
  71. package/dist/operations/dialectic.d.ts +16 -0
  72. package/dist/operations/dialectic.d.ts.map +1 -1
  73. package/dist/operations/memory.d.ts +48 -0
  74. package/dist/operations/memory.d.ts.map +1 -1
  75. package/dist/operations/nexus-scope-map.d.ts +8 -0
  76. package/dist/operations/nexus-scope-map.d.ts.map +1 -1
  77. package/dist/operations/nexus-scope-map.js +8 -0
  78. package/dist/operations/nexus-scope-map.js.map +1 -1
  79. package/dist/operations/nexus-user-profile.d.ts +27 -1
  80. package/dist/operations/nexus-user-profile.d.ts.map +1 -1
  81. package/dist/operations/nexus-user-profile.js +11 -1
  82. package/dist/operations/nexus-user-profile.js.map +1 -1
  83. package/dist/operations/nexus.d.ts +394 -3
  84. package/dist/operations/nexus.d.ts.map +1 -1
  85. package/dist/operations/release.d.ts +259 -0
  86. package/dist/operations/release.d.ts.map +1 -1
  87. package/dist/operations/release.js +130 -1
  88. package/dist/operations/release.js.map +1 -1
  89. package/dist/operations/session.d.ts +6 -4
  90. package/dist/operations/session.d.ts.map +1 -1
  91. package/dist/operations/tasks.d.ts +6 -0
  92. package/dist/operations/tasks.d.ts.map +1 -1
  93. package/dist/operations/tasks.js +1 -0
  94. package/dist/operations/tasks.js.map +1 -1
  95. package/dist/operations/validate.d.ts +5 -0
  96. package/dist/operations/validate.d.ts.map +1 -1
  97. package/dist/operations/worktree.d.ts +125 -1
  98. package/dist/operations/worktree.d.ts.map +1 -1
  99. package/dist/process-probe.d.ts +17 -0
  100. package/dist/process-probe.d.ts.map +1 -0
  101. package/dist/process-probe.js +21 -0
  102. package/dist/process-probe.js.map +1 -0
  103. package/dist/project-context.d.ts +44 -2
  104. package/dist/project-context.d.ts.map +1 -1
  105. package/dist/project-lifecycle.d.ts +143 -0
  106. package/dist/project-lifecycle.d.ts.map +1 -0
  107. package/dist/project-lifecycle.js +21 -0
  108. package/dist/project-lifecycle.js.map +1 -0
  109. package/dist/release/plan.d.ts +6 -2
  110. package/dist/release/plan.d.ts.map +1 -1
  111. package/dist/release/plan.js +8 -2
  112. package/dist/release/plan.js.map +1 -1
  113. package/dist/release/plan.test.js +6 -1
  114. package/dist/release/plan.test.js.map +1 -1
  115. package/dist/table-classification.d.ts +208 -0
  116. package/dist/table-classification.d.ts.map +1 -0
  117. package/dist/table-classification.js +23 -0
  118. package/dist/table-classification.js.map +1 -0
  119. package/dist/task.d.ts +79 -0
  120. package/dist/task.d.ts.map +1 -1
  121. package/package.json +6 -2
  122. package/schemas/gate-result.schema.json +43 -0
  123. package/src/__tests__/__snapshots__/operations-registry.test.ts.snap +1 -1
  124. package/src/__tests__/decide.test.ts +139 -0
  125. package/src/__tests__/evidence-atom-schema.test.ts +2 -1
  126. package/src/__tests__/memory-wire-shapes.test.ts +3 -0
  127. package/src/acceptance-gate-schema.ts +29 -0
  128. package/src/acceptance-gate.ts +68 -3
  129. package/src/backup-manifest.ts +13 -2
  130. package/src/branch-lock.ts +36 -4
  131. package/src/cloud/api.ts +512 -0
  132. package/src/cloud/envelope.ts +63 -0
  133. package/src/cloud/ids.ts +51 -0
  134. package/src/cloud/index.ts +16 -0
  135. package/src/data-accessor.ts +24 -3
  136. package/src/decide.ts +355 -0
  137. package/src/dispatch/operations-registry.ts +58 -0
  138. package/src/done-plan.ts +350 -0
  139. package/src/evidence-atom-schema.ts +31 -2
  140. package/src/exit-codes.ts +42 -0
  141. package/src/graph.ts +44 -0
  142. package/src/index.ts +117 -0
  143. package/src/memory/observe.ts +16 -0
  144. package/src/operations/__tests__/release-shared-surface.test.ts +112 -0
  145. package/src/operations/dialectic.ts +17 -0
  146. package/src/operations/memory.ts +48 -0
  147. package/src/operations/nexus-scope-map.ts +9 -0
  148. package/src/operations/nexus-user-profile.ts +29 -1
  149. package/src/operations/nexus.ts +416 -3
  150. package/src/operations/release.ts +197 -0
  151. package/src/operations/session.ts +6 -4
  152. package/src/operations/tasks.ts +7 -0
  153. package/src/operations/validate.ts +5 -0
  154. package/src/operations/worktree.ts +133 -1
  155. package/src/process-probe.ts +21 -0
  156. package/src/project-context.ts +42 -2
  157. package/src/project-lifecycle.ts +149 -0
  158. package/src/release/plan.test.ts +6 -1
  159. package/src/release/plan.ts +8 -2
  160. package/src/table-classification.ts +232 -0
  161. package/src/task.ts +84 -1
package/src/index.ts CHANGED
@@ -365,6 +365,7 @@ export type {
365
365
  TaskFieldUpdates,
366
366
  TaskPopulation,
367
367
  TaskQueryFilters,
368
+ TaskWriteGuard,
368
369
  TransactionAccessor,
369
370
  } from './data-accessor.js';
370
371
  // === Database Inventory (Saga T10281 / Epic T10282 / Task T10305 — SG-BRAIN-DB-RESILIENCE) ===
@@ -512,6 +513,27 @@ export type {
512
513
  WorktreeAnomaly,
513
514
  WorktreeAnomalyKind,
514
515
  } from './doctor.js';
516
+ // === Done planner: read-only `cleo done --plan` evidence plan (T12623, T12624) ===
517
+ export type {
518
+ ChangeSetDoc,
519
+ ChangeSetPrCandidate,
520
+ ChangeSetRootSource,
521
+ ChangeSetSource,
522
+ DoneBlockedDetails,
523
+ DoneNextStep,
524
+ DonePlan,
525
+ DonePlanAcBasis,
526
+ DonePlanAcMapping,
527
+ DonePlanBlocker,
528
+ DonePlanBlockerCode,
529
+ DonePlanGate,
530
+ DonePlanToolCacheState,
531
+ DonePlanToolRun,
532
+ DonePlanTypedGate,
533
+ DoneRecordResult,
534
+ DoneToolResult,
535
+ TaskChangeSet,
536
+ } from './done-plan.js';
515
537
  export type {
516
538
  EngineErrorPayload,
517
539
  EngineFailure,
@@ -715,7 +737,11 @@ export type {
715
737
  ExtractedProvenance,
716
738
  GraphEdgeConfidenceLabel,
717
739
  GraphIndexAssessment,
740
+ GraphIndexAssessmentProjection,
741
+ GraphIndexFilePage,
718
742
  GraphIndexFileReport,
743
+ GraphIndexFileStatus,
744
+ GraphIndexFileStatusCounts,
719
745
  GraphIndexFreshness,
720
746
  GraphIndexReferenceReport,
721
747
  GraphIndexRunSummary,
@@ -1274,6 +1300,7 @@ export type {
1274
1300
  ApplyInsightsResult,
1275
1301
  DialecticInsights,
1276
1302
  DialecticTurn,
1303
+ DialecticTurnOrigin,
1277
1304
  EvaluateDialecticParams,
1278
1305
  EvaluateDialecticResult,
1279
1306
  } from './operations/dialectic.js';
@@ -1457,6 +1484,7 @@ export type {
1457
1484
  NexusDepsEntry,
1458
1485
  NexusDepsParams,
1459
1486
  NexusDepsResult,
1487
+ NexusDeviceRecord,
1460
1488
  NexusDiffHealth,
1461
1489
  NexusDiffParams,
1462
1490
  NexusDiffResult,
@@ -1468,6 +1496,7 @@ export type {
1468
1496
  NexusFlowsResult,
1469
1497
  NexusFullContextParams,
1470
1498
  NexusFullContextResult,
1499
+ NexusGitProbeErrorCode,
1471
1500
  NexusGraphEdge,
1472
1501
  NexusGraphNode,
1473
1502
  NexusGraphParams,
@@ -1497,14 +1526,20 @@ export type {
1497
1526
  NexusPermissionLevel,
1498
1527
  NexusPermissionSetParams,
1499
1528
  NexusPermissionSetResult,
1529
+ NexusProjectCandidate,
1500
1530
  NexusProjectCheckout,
1531
+ NexusProjectGitState,
1532
+ NexusProjectLocationState,
1501
1533
  NexusProjectRecord,
1502
1534
  NexusProjectStats,
1535
+ NexusProjectsCleanIdMismatch,
1503
1536
  NexusProjectsCleanParams,
1504
1537
  NexusProjectsCleanReason,
1505
1538
  NexusProjectsCleanReceipt,
1539
+ NexusProjectsCleanRelocated,
1506
1540
  NexusProjectsCleanRemoval,
1507
1541
  NexusProjectsCleanResult,
1542
+ NexusProjectsCleanUnreadable,
1508
1543
  NexusProjectsListParams,
1509
1544
  NexusProjectsListResult,
1510
1545
  NexusProjectsRegisterParams,
@@ -1513,6 +1548,8 @@ export type {
1513
1548
  NexusProjectsRemoveResult,
1514
1549
  NexusProjectsScanParams,
1515
1550
  NexusProjectsScanResult,
1551
+ NexusProjectsStatusParams,
1552
+ NexusProjectsStatusResult,
1516
1553
  NexusQueryCteParams,
1517
1554
  NexusQueryCteResult,
1518
1555
  NexusReconcileParams,
@@ -1521,7 +1558,15 @@ export type {
1521
1558
  NexusRefreshBridgeResult,
1522
1559
  NexusRegisterParams,
1523
1560
  NexusRegisterResult,
1561
+ NexusRegistryAmbiguousAlias,
1524
1562
  NexusRegistryClassification,
1563
+ NexusRegistryFinding,
1564
+ NexusRegistryFindingKind,
1565
+ NexusRegistryIntegrityReport,
1566
+ NexusRegistryRepairAction,
1567
+ NexusRegistryRepairReceipt,
1568
+ NexusRegistryRollbackResult,
1569
+ NexusRegistrySplitPeer,
1525
1570
  NexusResolveParams,
1526
1571
  NexusResolveResult,
1527
1572
  NexusRouteMapParams,
@@ -1610,8 +1655,10 @@ export type {
1610
1655
  NexusProfileUpsertResult,
1611
1656
  NexusProfileViewParams,
1612
1657
  NexusProfileViewResult,
1658
+ UserProfileScope,
1613
1659
  UserProfileTrait,
1614
1660
  } from './operations/nexus-user-profile.js';
1661
+ export { USER_PROFILE_SCOPES } from './operations/nexus-user-profile.js';
1615
1662
  // Commonly used ops types re-exported at top level for convenience
1616
1663
  export type {
1617
1664
  BrainState,
@@ -1932,6 +1979,10 @@ export type {
1932
1979
  WorktreeLifecycleAction,
1933
1980
  WorktreeLifecycleAuditEntry,
1934
1981
  WorktreeListEntry,
1982
+ WorktreeLockAcquisition,
1983
+ WorktreeLockAcquisitionStatus,
1984
+ WorktreeLockHolder,
1985
+ WorktreeLockRecord,
1935
1986
  WorktreeSource,
1936
1987
  WorktreeStatusCategory,
1937
1988
  } from './operations/worktree.js';
@@ -2011,6 +2062,8 @@ export type {
2011
2062
  SyncResult,
2012
2063
  SyncStatus,
2013
2064
  } from './postgres-data-accessor.js';
2065
+ // === Process-table probe constants (T12500 · T12506) ===
2066
+ export { PS_STABLE_ENV } from './process-probe.js';
2014
2067
  // === Project Context (ecosystem detection types) ===
2015
2068
  export type {
2016
2069
  EcosystemHint,
@@ -2020,6 +2073,16 @@ export type {
2020
2073
  ProjectType,
2021
2074
  TestFramework,
2022
2075
  } from './project-context.js';
2076
+ // === Project relocation (move / reroot — T12552 · T12558) ===
2077
+ export type {
2078
+ MoveProjectResult,
2079
+ ProjectMovedTombstone,
2080
+ ProjectRelocationExclusion,
2081
+ ProjectRelocationKind,
2082
+ ProjectRelocationPlan,
2083
+ ProjectRelocationRegistryAction,
2084
+ RerootProjectResult,
2085
+ } from './project-lifecycle.js';
2023
2086
  // === ProjectTools Contracts (scaffold-project, doctor-project, scaffold-global — T10069 / T9835b) ===
2024
2087
  export type {
2025
2088
  DoctorProjectOptions,
@@ -2400,6 +2463,20 @@ export {
2400
2463
  SupervisorIpcResponseEnvelopeSchema,
2401
2464
  SupervisorIpcResponseSchema,
2402
2465
  } from './supervisor-ipc/index.js';
2466
+ // === Table Classification Types (T12332 — Gate A replication classes) ===
2467
+ export type {
2468
+ ColumnClass,
2469
+ ColumnOverride,
2470
+ PendingTableClassification,
2471
+ RowRouting,
2472
+ TableClass,
2473
+ TableClassification,
2474
+ TableClassificationStatus,
2475
+ TablePatternRule,
2476
+ TableRegistryEntry,
2477
+ TableScope,
2478
+ TableScopeRegistry,
2479
+ } from './table-classification.js';
2403
2480
  // === Task Types ===
2404
2481
  export type {
2405
2482
  AcceptanceItem,
@@ -2807,4 +2884,44 @@ export {
2807
2884
  DEFAULT_IDENTITY_FIELD,
2808
2885
  } from './collection-keys.js';
2809
2886
 
2887
+ // === Typed-decision contracts (T12489 · epic T12486) ===
2888
+ export type {
2889
+ ChoiceDecisionAnswer,
2890
+ ChoiceDecisionQuestion,
2891
+ DecisionAnswer,
2892
+ DecisionInstructions,
2893
+ DecisionJsonValue,
2894
+ DecisionOutcome,
2895
+ DecisionOutcomeSource,
2896
+ DecisionProviderConfig,
2897
+ DecisionQuestion,
2898
+ DecisionQuestionType,
2899
+ DecisionRequest,
2900
+ DecisionState,
2901
+ NoulDecisionAnswer,
2902
+ NoulDecisionQuestion,
2903
+ ScoreDecisionAnswer,
2904
+ ScoreDecisionQuestion,
2905
+ } from './decide.js';
2906
+ export {
2907
+ choiceDecisionAnswerSchema,
2908
+ choiceDecisionQuestionSchema,
2909
+ DECISION_OUTCOME_SOURCES,
2910
+ DECISION_QUESTION_TYPES,
2911
+ DECISION_REQUEST_LIMITS,
2912
+ decisionAnswerSchema,
2913
+ decisionInstructionsSchema,
2914
+ decisionOutcomeSchema,
2915
+ decisionOutcomeSourceSchema,
2916
+ decisionProviderConfigSchema,
2917
+ decisionQuestionSchema,
2918
+ decisionQuestionTypeSchema,
2919
+ decisionRequestSchema,
2920
+ decisionStateSchema,
2921
+ noulDecisionAnswerSchema,
2922
+ noulDecisionQuestionSchema,
2923
+ scoreDecisionAnswerSchema,
2924
+ scoreDecisionQuestionSchema,
2925
+ } from './decide.js';
2926
+
2810
2927
  export { isStorableTaskId, isTaskId, TASK_ID_REGEX, type TaskId } from './task-id.js';
@@ -115,6 +115,13 @@ export interface ObserveBrainParams {
115
115
  * Null for directly-observed rows.
116
116
  */
117
117
  provenanceChain?: string[] | null;
118
+ /**
119
+ * T12494: opt in to a System One type choice when `type` is absent.
120
+ * Set ONLY by the interactive `memory.observe` operation (`cleo memory
121
+ * observe`). Background writers leave it unset, so they never send their
122
+ * content to a provider; their type comes from the keyword heuristic.
123
+ */
124
+ askTypeDecision?: boolean;
118
125
  /**
119
126
  * T992: Internal flag — when true, bypasses the verifyAndStore gate.
120
127
  * Set by storeVerifiedCandidate in extraction-gate.ts to avoid recursion,
@@ -148,6 +155,15 @@ export interface ObserveBrainResult {
148
155
  type: string;
149
156
  /** ISO 8601 creation timestamp. */
150
157
  createdAt: string;
158
+ /**
159
+ * T12494: where the stored type came from — `caller` (explicit `type`),
160
+ * `keyword` (whole-word keyword heuristic) or `system-one` (a confident
161
+ * System One `choice` in `on` mode). Absent when not determined on this path
162
+ * (e.g. the extraction gate merged or rejected the write).
163
+ */
164
+ typeSource?: 'caller' | 'keyword' | 'system-one';
165
+ /** T12494: confidence behind a `keyword` (flat 0.5) or `system-one` type. */
166
+ typeConfidence?: number;
151
167
  }
152
168
 
153
169
  // ── DocAttachmentObservationPayload ─────────────────────────────────
@@ -0,0 +1,112 @@
1
+ /**
2
+ * T10483 — release command/template shared-surface contract.
3
+ *
4
+ * These tests pin the taxonomy needed by T10468/T10476: shipped CLEO release
5
+ * commands, cleocode dogfood workflow templates, and the command↔template seams
6
+ * that are shared public surfaces. They also protect deterministic
7
+ * changesets-first release planning and the no-LLM blocking path invariant.
8
+ */
9
+
10
+ import { existsSync, readdirSync } from 'node:fs';
11
+ import { fileURLToPath } from 'node:url';
12
+ import { describe, expect, it } from 'vitest';
13
+ import {
14
+ RELEASE_SHARED_COMMAND_SURFACES,
15
+ RELEASE_SHARED_SURFACE_CONTRACT,
16
+ RELEASE_SHARED_TEMPLATE_SURFACES,
17
+ } from '../release.js';
18
+
19
+ /** Repository root, resolved from this file (`packages/contracts/src/operations/__tests__`). */
20
+ const REPO_ROOT = fileURLToPath(new URL('../../../../../', import.meta.url));
21
+ /** The shipped workflow-template directory the contract claims to cover. */
22
+ const WORKFLOW_TEMPLATE_DIR = fileURLToPath(
23
+ new URL('../../../../core/templates/workflows/', import.meta.url),
24
+ );
25
+
26
+ describe('release shared-surface contract (T10483)', () => {
27
+ it('classifies shipped release surfaces as consumer tooling or shared, never dogfood', () => {
28
+ const audiences = new Set<string>([
29
+ ...RELEASE_SHARED_COMMAND_SURFACES.map((surface) => surface.audience),
30
+ ...RELEASE_SHARED_TEMPLATE_SURFACES.map((surface) => surface.audience),
31
+ ]);
32
+
33
+ // Dogfood-only owner CI lives in the cleocode repo's .github/workflows and
34
+ // is never shipped, so no shipped command or template may carry it.
35
+ expect(audiences).toEqual(new Set(['shipped-consumer-tooling', 'shared-surface']));
36
+ });
37
+
38
+ it('pins every command to its registered dispatch gateway/operation', () => {
39
+ const byCommand = new Map(
40
+ RELEASE_SHARED_COMMAND_SURFACES.map((surface) => [
41
+ surface.command,
42
+ `${surface.gateway}:${surface.operation}`,
43
+ ]),
44
+ );
45
+
46
+ expect(byCommand).toEqual(
47
+ new Map([
48
+ ['cleo release plan', 'mutate:release.plan'],
49
+ ['cleo release open', 'mutate:release.open'],
50
+ ['cleo release reconcile', 'mutate:release.reconcile'],
51
+ ['cleo release rollback', 'mutate:pipeline.release.rollback'],
52
+ ]),
53
+ );
54
+ });
55
+
56
+ it('covers each shipped release workflow template on disk exactly once', () => {
57
+ // Compare against the real template directory, not a restated list, so a
58
+ // template added or removed without updating the contract fails here.
59
+ const onDisk = readdirSync(WORKFLOW_TEMPLATE_DIR)
60
+ .filter((name) => name.endsWith('.yml.tmpl'))
61
+ .map((name) => name.replace(/\.tmpl$/, ''))
62
+ .sort();
63
+ const rendered = RELEASE_SHARED_TEMPLATE_SURFACES.map((surface) => surface.renderedWorkflow);
64
+
65
+ expect(onDisk.length).toBeGreaterThan(0);
66
+ expect([...rendered].sort()).toEqual(onDisk);
67
+ for (const surface of RELEASE_SHARED_TEMPLATE_SURFACES) {
68
+ expect(existsSync(`${REPO_ROOT}${surface.template}`), surface.template).toBe(true);
69
+ expect(surface.template.endsWith(`/${surface.renderedWorkflow}.tmpl`)).toBe(true);
70
+ }
71
+ });
72
+
73
+ it('pins deterministic changesets-first planning as local and network-free', () => {
74
+ const plan = RELEASE_SHARED_COMMAND_SURFACES.find(
75
+ (surface) =>
76
+ surface.command === RELEASE_SHARED_SURFACE_CONTRACT.invariants.deterministicPlanningCommand,
77
+ );
78
+
79
+ expect(plan).toBeDefined();
80
+ expect(plan?.operation).toBe('release.plan');
81
+ expect(plan?.deterministic).toBe(true);
82
+ expect(plan?.mayCallNetwork).toBe(false);
83
+ expect(plan?.changesetRequired).toBe(true);
84
+ });
85
+
86
+ it('forbids LLM-first blocking paths on every release command and workflow template', () => {
87
+ expect(RELEASE_SHARED_SURFACE_CONTRACT.invariants.llmBlockingPathAllowed).toBe(false);
88
+
89
+ for (const surface of RELEASE_SHARED_COMMAND_SURFACES) {
90
+ expect(surface.llmBlockingPath).toBe(false);
91
+ }
92
+ for (const surface of RELEASE_SHARED_TEMPLATE_SURFACES) {
93
+ expect(surface.llmBlockingPath).toBe(false);
94
+ }
95
+ });
96
+
97
+ it('keeps public workflow templates attached to a shipped owner command', () => {
98
+ const commands = new Set(RELEASE_SHARED_COMMAND_SURFACES.map((surface) => surface.command));
99
+
100
+ for (const template of RELEASE_SHARED_TEMPLATE_SURFACES) {
101
+ expect(template.template).toMatch(
102
+ /^packages\/core\/templates\/workflows\/release-.+\.yml\.tmpl$/,
103
+ );
104
+ expect(template.renderSnapshotRequired).toBe(true);
105
+ if (template.stability === 'public-contract') {
106
+ expect(commands.has(template.owningCommand), template.owningCommand).toBe(true);
107
+ expect(template.audience).toBe('shared-surface');
108
+ expect(template.consumesReleasePlan).toBe(true);
109
+ }
110
+ }
111
+ });
112
+ });
@@ -55,8 +55,25 @@ export interface DialecticTurn {
55
55
  activePeerId: string;
56
56
  /** Session ID from the CLEO session store (e.g. `ses_20260422131135_5149eb`). */
57
57
  sessionId: string;
58
+ /**
59
+ * Structural origin of the turn (T12543). Omitted means `'conversation'`.
60
+ *
61
+ * `'operation-envelope'` marks a turn synthesised from a dispatched
62
+ * operation and its result envelope (the CQRS dispatcher hook). Such a turn
63
+ * carries no user utterance, so it can never yield a user trait: the
64
+ * evaluator drops every global trait for it and keeps only peer insights
65
+ * and the narrative delta.
66
+ */
67
+ origin?: DialecticTurnOrigin;
58
68
  }
59
69
 
70
+ /**
71
+ * Structural origin of a {@link DialecticTurn}.
72
+ *
73
+ * @task T12543
74
+ */
75
+ export type DialecticTurnOrigin = 'conversation' | 'operation-envelope';
76
+
60
77
  /**
61
78
  * Structured insights extracted from a single dialectic turn.
62
79
  *
@@ -1223,6 +1223,17 @@ export interface RetrievalObservation {
1223
1223
  * until the T1147 W7 sweep stamps them as clean.
1224
1224
  */
1225
1225
  provenanceClass?: string;
1226
+ /**
1227
+ * Stored quality score in [0, 1] (`quality_score` column), when the row
1228
+ * carries one. Used to rank entries inside the spawn-prompt PSYCHE-MEMORY
1229
+ * budget (T12519). Absent on legacy schemas.
1230
+ */
1231
+ qualityScore?: number;
1232
+ /**
1233
+ * Number of times this entry has been cited (`citation_count` column).
1234
+ * Secondary ranking signal for the PSYCHE-MEMORY budget (T12519).
1235
+ */
1236
+ citationCount?: number;
1226
1237
  }
1227
1238
 
1228
1239
  /**
@@ -1241,6 +1252,17 @@ export interface RetrievalLearning {
1241
1252
  * until the T1147 W7 sweep stamps them as clean.
1242
1253
  */
1243
1254
  provenanceClass?: string;
1255
+ /**
1256
+ * Stored quality score in [0, 1] (`quality_score` column), when the row
1257
+ * carries one. Used to rank entries inside the spawn-prompt PSYCHE-MEMORY
1258
+ * budget (T12519). Absent on legacy schemas.
1259
+ */
1260
+ qualityScore?: number;
1261
+ /**
1262
+ * Number of times this entry has been cited (`citation_count` column).
1263
+ * Secondary ranking signal for the PSYCHE-MEMORY budget (T12519).
1264
+ */
1265
+ citationCount?: number;
1244
1266
  }
1245
1267
 
1246
1268
  /**
@@ -1259,6 +1281,17 @@ export interface RetrievalPattern {
1259
1281
  * until the T1147 W7 sweep stamps them as clean.
1260
1282
  */
1261
1283
  provenanceClass?: string;
1284
+ /**
1285
+ * Stored quality score in [0, 1] (`quality_score` column), when the row
1286
+ * carries one. Used to rank entries inside the spawn-prompt PSYCHE-MEMORY
1287
+ * budget (T12519). Absent on legacy schemas.
1288
+ */
1289
+ qualityScore?: number;
1290
+ /**
1291
+ * Number of times this entry has been cited (`citation_count` column).
1292
+ * Secondary ranking signal for the PSYCHE-MEMORY budget (T12519).
1293
+ */
1294
+ citationCount?: number;
1262
1295
  }
1263
1296
 
1264
1297
  /**
@@ -1277,6 +1310,21 @@ export interface RetrievalDecision {
1277
1310
  * until the T1147 W7 sweep stamps them as clean.
1278
1311
  */
1279
1312
  provenanceClass?: string;
1313
+ /**
1314
+ * Stored quality score in [0, 1] (`quality_score` column), when the row
1315
+ * carries one. Used to rank entries inside the spawn-prompt PSYCHE-MEMORY
1316
+ * budget (T12519). Absent on legacy schemas.
1317
+ */
1318
+ qualityScore?: number;
1319
+ /**
1320
+ * Number of times this entry has been cited (`citation_count` column).
1321
+ * Secondary ranking signal for the PSYCHE-MEMORY budget (T12519).
1322
+ */
1323
+ citationCount?: number;
1324
+ /** Task the decision was recorded against (`context_task_id`), if any (T12519). */
1325
+ contextTaskId?: string | null;
1326
+ /** Epic the decision was recorded against (`context_epic_id`), if any (T12519). */
1327
+ contextEpicId?: string | null;
1280
1328
  }
1281
1329
 
1282
1330
  /**
@@ -505,6 +505,15 @@ export const NEXUS_SCOPE_MAP = {
505
505
  stores: ['nexus-registry'],
506
506
  requiresProject: false,
507
507
  },
508
+ 'projects.status': {
509
+ op: 'projects.status',
510
+ description:
511
+ 'Probe git state (branch, head, dirty, upstream, ahead/behind) of every location on this device and record it.',
512
+ scope: 'global',
513
+ effect: 'write',
514
+ stores: ['nexus-registry', 'fs'],
515
+ requiresProject: false,
516
+ },
508
517
  'refresh-bridge': {
509
518
  op: 'refresh-bridge',
510
519
  description: 'Refresh the Nexus → BRAIN cross-store bridge.',
@@ -24,6 +24,18 @@
24
24
  // Shared domain types
25
25
  // ============================================================================
26
26
 
27
+ /**
28
+ * Legal visibility scopes for a user-profile trait (T12543).
29
+ *
30
+ * - `project` — visible only to agents working in the project whose portable
31
+ * id is stamped on the trait (`projectId`). The default for every new row.
32
+ * - `user` — explicitly marked user-global: visible in every project.
33
+ */
34
+ export const USER_PROFILE_SCOPES = ['project', 'user'] as const;
35
+
36
+ /** Visibility scope of a user-profile trait. See {@link USER_PROFILE_SCOPES}. */
37
+ export type UserProfileScope = (typeof USER_PROFILE_SCOPES)[number];
38
+
27
39
  /**
28
40
  * A single user-profile trait record.
29
41
  *
@@ -61,6 +73,22 @@ export interface UserProfileTrait {
61
73
  * Set by `supersedeTrait` (T1139 supersession graph prep).
62
74
  */
63
75
  supersededBy: string | null;
76
+ /**
77
+ * Portable project id (`.cleo/project-id`, ADR-094) of the project the trait
78
+ * was derived in. `null` = unknown origin (rows written before T12543).
79
+ * Omitted on input means `null`.
80
+ *
81
+ * @task T12543
82
+ */
83
+ projectId?: string | null;
84
+ /**
85
+ * Visibility scope. Omitted on input means `'project'`. Spawn prompts include
86
+ * only `user` traits plus `project` traits whose `projectId` is the current
87
+ * project; unknown-origin rows are excluded.
88
+ *
89
+ * @task T12543
90
+ */
91
+ scope?: UserProfileScope;
64
92
  }
65
93
 
66
94
  // ============================================================================
@@ -180,7 +208,7 @@ export interface NexusProfileUpsertParams {
180
208
  /** Trait to create or update (required). */
181
209
  trait: Pick<
182
210
  UserProfileTrait,
183
- 'traitKey' | 'traitValue' | 'confidence' | 'source' | 'derivedFromMessageId'
211
+ 'traitKey' | 'traitValue' | 'confidence' | 'source' | 'derivedFromMessageId' | 'scope'
184
212
  >;
185
213
  }
186
214