@zq-silk/yui 0.2.0 → 0.4.2

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 (208) hide show
  1. package/ARCHITECTURE.md +603 -133
  2. package/README.md +806 -31
  3. package/dist/agent/agent.js +2 -1
  4. package/dist/agent/argumentPolicy.js +3 -1
  5. package/dist/agent/launchEnvironment.js +106 -0
  6. package/dist/agent/managedRuntimeEnvironment.js +34 -0
  7. package/dist/brief/taskBrief.js +11 -1
  8. package/dist/cli/agentConfigurationPicker.js +287 -0
  9. package/dist/cli/commandCatalog.js +488 -60
  10. package/dist/cli/completion.js +146 -22
  11. package/dist/cli/helpRenderer.js +3 -1
  12. package/dist/cli/interactionCandidates.js +53 -15
  13. package/dist/cli/interactionPolicy.js +267 -30
  14. package/dist/cli/interactiveSelection.js +6 -2
  15. package/dist/cli/invocationRouter.js +5 -1
  16. package/dist/cli/operatorWizard.js +87 -0
  17. package/dist/cli/roleOptionCatalog.js +1 -0
  18. package/dist/cli/roleWizard.js +185 -21
  19. package/dist/cli/updateCommand.js +62 -19
  20. package/dist/cli/updateOrchestrator.js +539 -0
  21. package/dist/cli/updatePorts.js +1119 -0
  22. package/dist/cli/upgradeCommand.js +112 -0
  23. package/dist/cli.js +1420 -86
  24. package/dist/commands/agentCommands.js +146 -3
  25. package/dist/commands/configCommands.js +126 -0
  26. package/dist/commands/controllerCommands.js +365 -0
  27. package/dist/commands/globalRoleCommands.js +168 -126
  28. package/dist/commands/jobCommands.js +18 -8
  29. package/dist/commands/operatorCommands.js +159 -9
  30. package/dist/commands/profileCommands.js +203 -0
  31. package/dist/commands/projectCommands.js +650 -0
  32. package/dist/commands/roleConfiguration.js +85 -24
  33. package/dist/commands/roleRuntimeGuard.js +12 -0
  34. package/dist/commands/roleSkillValidation.js +47 -0
  35. package/dist/commands/taskActor.js +127 -0
  36. package/dist/commands/taskCommands.js +4201 -313
  37. package/dist/commands/taskCompletionGate.js +131 -0
  38. package/dist/commands/taskContextCommand.js +244 -30
  39. package/dist/commands/taskInputCommands.js +177 -59
  40. package/dist/commands/taskIntegrationCommands.js +303 -0
  41. package/dist/commands/taskOverviewCommand.js +363 -0
  42. package/dist/commands/taskRoleRuntimeStatus.js +125 -19
  43. package/dist/commands/textInput.js +15 -0
  44. package/dist/completion/completionInstaller.js +26 -22
  45. package/dist/config/yuiConfig.js +4 -3
  46. package/dist/context/dispatchContext.js +90 -38
  47. package/dist/context/roleSessionContext.js +119 -0
  48. package/dist/controller/claudeLifecycleHook.js +203 -0
  49. package/dist/controller/clientRuntime.js +408 -56
  50. package/dist/controller/codexLifecycleHook.js +108 -0
  51. package/dist/controller/controller.js +1089 -32
  52. package/dist/controller/domainIdentity.js +505 -0
  53. package/dist/controller/ephemeralResourceReaper.js +131 -0
  54. package/dist/controller/fileSchedulerStoreAdapter.js +2153 -103
  55. package/dist/controller/providerHookRunFence.js +127 -0
  56. package/dist/controller/resourceCleanupLinux.js +286 -0
  57. package/dist/controller/resourceInventory.js +531 -0
  58. package/dist/controller/resourceInventoryLinux.js +610 -0
  59. package/dist/controller/runtime.js +629 -10
  60. package/dist/controller/runtimeEventInbox.js +564 -0
  61. package/dist/controller/runtimeEventProcessor.js +248 -0
  62. package/dist/controller/runtimeLaunchCoordinator.js +477 -0
  63. package/dist/controller/sessionNotify.js +121 -78
  64. package/dist/coordination/deadlineScheduler.js +15 -0
  65. package/dist/coordination/mailboxScheduler.js +108 -0
  66. package/dist/coordination/workMailbox.js +329 -0
  67. package/dist/coordination/workMailboxQueue.js +86 -0
  68. package/dist/core/controllerClient.js +19 -5
  69. package/dist/core/controllerEndpoint.js +37 -0
  70. package/dist/core/controllerServer.js +218 -10
  71. package/dist/core/protocol.js +6 -2
  72. package/dist/decision/decision.js +2 -1
  73. package/dist/doctor/doctor.js +681 -32
  74. package/dist/domain/validation.js +53 -0
  75. package/dist/errors/cliError.js +5 -3
  76. package/dist/event/taskEvent.js +7 -3
  77. package/dist/execution/codexThreadNaming.js +160 -0
  78. package/dist/execution/executionGroup.js +579 -0
  79. package/dist/executor/agentAdapter.js +255 -40
  80. package/dist/executor/agentConfigurationCatalog.js +326 -0
  81. package/dist/executor/agentConfigurationProbe.js +506 -0
  82. package/dist/executor/agentExecutor.js +625 -10
  83. package/dist/executor/codexConfigConflict.js +290 -0
  84. package/dist/executor/effectiveLaunch.js +340 -0
  85. package/dist/executor/executorRegistry.js +238 -36
  86. package/dist/executor/fileRoleLaunchPlanner.js +550 -40
  87. package/dist/executor/turnCompletion.js +126 -0
  88. package/dist/input/inputRequest.js +30 -9
  89. package/dist/integration/changeSet.js +36 -0
  90. package/dist/integration/checkResult.js +24 -0
  91. package/dist/integration/gitIntegrationService.js +695 -0
  92. package/dist/integration/integrationAttempt.js +142 -0
  93. package/dist/interaction/operatorPresentation.js +96 -0
  94. package/dist/lifecycle/canonicalLifecycleEvent.js +342 -0
  95. package/dist/lifecycle/exactRunTerminalization.js +572 -0
  96. package/dist/lifecycle/providerLifecycleMapping.js +190 -0
  97. package/dist/lifecycle/taskRoleSessionReset.js +124 -0
  98. package/dist/message/message.js +23 -7
  99. package/dist/milestone/milestone.js +2 -1
  100. package/dist/operator/operatorSessionHistory.js +124 -0
  101. package/dist/output/agentConfigurationPresentation.js +43 -0
  102. package/dist/output/rolePresentation.js +34 -10
  103. package/dist/output/terminal.js +8 -0
  104. package/dist/output/timePresentation.js +55 -0
  105. package/dist/profile/agentProfile.js +128 -0
  106. package/dist/repository/gitWorkspace.js +578 -24
  107. package/dist/repository/project.js +213 -0
  108. package/dist/repository/taskWorkspaceCoordinator.js +392 -0
  109. package/dist/repository/taskWorkspacePreparer.js +1688 -191
  110. package/dist/review/reviewConfig.js +11 -0
  111. package/dist/review/reviewRound.js +399 -0
  112. package/dist/review/taskFinalReviewContract.js +90 -0
  113. package/dist/role/role.js +124 -23
  114. package/dist/run/agentRun.js +155 -12
  115. package/dist/run/runIdentity.js +82 -0
  116. package/dist/runtime/exactControlPlane.js +472 -0
  117. package/dist/runtime/index.js +8 -0
  118. package/dist/runtime/lifecycleReservation.js +38 -0
  119. package/dist/runtime/ports.js +11 -0
  120. package/dist/runtime/preallocatedNativeSession.js +13 -0
  121. package/dist/runtime/promptEnvelope.js +30 -0
  122. package/dist/runtime/runtimeBinding.js +31 -0
  123. package/dist/runtime/runtimeOwner.js +14 -0
  124. package/dist/runtime/sessionLaunchRequest.js +62 -0
  125. package/dist/runtime/sessionTitle.js +54 -0
  126. package/dist/runtime/taskRuntimeIsolation.js +643 -0
  127. package/dist/runtime/tmuxAdapters.js +315 -0
  128. package/dist/runtime/turnCompletion.js +3 -0
  129. package/dist/runtime/validation.js +23 -0
  130. package/dist/scheduler/activeRoleRunDelivery.js +342 -32
  131. package/dist/scheduler/activeTaskProgress.js +63 -0
  132. package/dist/scheduler/leaderFailure.js +2 -1
  133. package/dist/scheduler/leaderWakeupProcessor.js +307 -66
  134. package/dist/scheduler/operatorInputNotificationProcessor.js +109 -46
  135. package/dist/scheduler/operatorNotification.js +44 -2
  136. package/dist/scheduler/ports.js +28 -1
  137. package/dist/scheduler/roleRunLiveness.js +131 -25
  138. package/dist/scheduler/roleRunStall.js +951 -0
  139. package/dist/scheduler/taskExecutionProjection.js +544 -0
  140. package/dist/scheduler/wakeupQueue.js +3 -0
  141. package/dist/setup/setupCommand.js +302 -52
  142. package/dist/storage/compatibleTaskStore.js +102 -0
  143. package/dist/storage/migration/baseline.js +78 -0
  144. package/dist/storage/migration/classifier.js +51 -0
  145. package/dist/storage/migration/compatibleCodec.js +53 -0
  146. package/dist/storage/migration/engine.js +147 -0
  147. package/dist/storage/migration/index.js +33 -0
  148. package/dist/storage/migration/planner.js +154 -0
  149. package/dist/storage/migration/productionRegistry.js +486 -0
  150. package/dist/storage/migration/registry.js +169 -0
  151. package/dist/storage/migration/report.js +54 -0
  152. package/dist/storage/migration/types.js +31 -0
  153. package/dist/storage/storageSchema.js +147 -123
  154. package/dist/storage/storageVersions.js +11 -0
  155. package/dist/storage/taskStore.js +1793 -197
  156. package/dist/storage/upgrade/homeClassification.js +156 -0
  157. package/dist/storage/upgrade/homeMigrationTarget.js +595 -0
  158. package/dist/storage/upgrade/offlineUpgradeInventory.js +315 -0
  159. package/dist/storage/upgrade/productionMigrationRegistry.js +6 -0
  160. package/dist/storage/upgrade/recordVersionScan.js +176 -0
  161. package/dist/storage/upgrade/recordVersions.js +159 -0
  162. package/dist/storage/upgrade/switchProgress.js +80 -0
  163. package/dist/storage/upgrade/upgradeOrchestrator.js +948 -0
  164. package/dist/storage/upgrade/upgradeReceipt.js +161 -0
  165. package/dist/storage/upgradeCoordination.js +186 -0
  166. package/dist/storage/upgradeFence.js +366 -0
  167. package/dist/task/task.js +132 -26
  168. package/dist/task/taskRecordReference.js +66 -0
  169. package/dist/tmux/commandExecutor.js +75 -2
  170. package/dist/tmux/tmuxManager.js +747 -49
  171. package/dist/version.js +23 -0
  172. package/dist/web/assets/assetManifest.js +62 -0
  173. package/dist/web/assets/client/app.js +631 -0
  174. package/dist/web/assets/client/components.js +605 -0
  175. package/dist/web/assets/client/dom.js +14 -0
  176. package/dist/web/assets/client/format.js +28 -0
  177. package/dist/web/assets/client/i18n.js +494 -0
  178. package/dist/web/assets/client/markdown.js +114 -0
  179. package/dist/web/assets/client/theme.js +32 -0
  180. package/dist/web/assets/client/view.js +458 -0
  181. package/dist/web/assets/fontData.js +12 -0
  182. package/dist/web/assets/fonts.js +12 -0
  183. package/dist/web/assets/shell.js +114 -0
  184. package/dist/web/assets/styles/cards.js +135 -0
  185. package/dist/web/assets/styles/layout.js +47 -0
  186. package/dist/web/assets/styles/markdown.js +29 -0
  187. package/dist/web/assets/styles/responsive.js +39 -0
  188. package/dist/web/assets/styles/tokens.js +101 -0
  189. package/dist/web/assets/styles/widgets.js +147 -0
  190. package/dist/web/tmuxWebTerminal.js +158 -0
  191. package/dist/web/webServer.js +463 -0
  192. package/dist/web/webSnapshot.js +148 -0
  193. package/dist/workItem/workItem.js +642 -23
  194. package/dist/workspace/gitChangeSetCapture.js +86 -0
  195. package/dist/workspace/workItemChangeSetManager.js +445 -0
  196. package/dist/worktree/managedWorkspace.js +202 -0
  197. package/docs/task-local-identity.md +62 -0
  198. package/i18n/README.zh-CN.md +406 -31
  199. package/package.json +10 -2
  200. package/skills/yui-leader/SKILL.md +601 -39
  201. package/skills/yui-operator/SKILL.md +255 -34
  202. package/skills/yui-reviewer/SKILL.md +57 -0
  203. package/skills/yui-worker/SKILL.md +214 -17
  204. package/dist/commands/repositoryCommands.js +0 -86
  205. package/dist/operator/operatorContext.js +0 -66
  206. package/dist/repository/repository.js +0 -55
  207. package/dist/scheduler/archivedTaskRuntime.js +0 -12
  208. package/dist/worktree/roleWorkspace.js +0 -62
@@ -0,0 +1,202 @@
1
+ import { resolve } from "node:path";
2
+ import { isDeepStrictEqual } from "node:util";
3
+ /** Every active Task launch is fenced by this durable owner. */
4
+ export function isTaskOwnedWorkspace(workspace, taskId, taskRoot, bindings) {
5
+ if (workspace === null || workspace === undefined
6
+ || workspace.owner.type !== "task"
7
+ || workspace.owner.taskId !== taskId
8
+ || taskRoot === undefined
9
+ || workspace.root !== taskRoot) {
10
+ return false;
11
+ }
12
+ const expected = bindings
13
+ .map(({ projectId, directory }) => `${projectId}\u0000${directory}\u0000write`)
14
+ .sort();
15
+ const actual = workspace.entries
16
+ .map(({ projectId, directory, access }) => `${projectId}\u0000${directory}\u0000${access}`)
17
+ .sort();
18
+ return isDeepStrictEqual(actual, expected);
19
+ }
20
+ export function createManagedWorkspace(input, now) {
21
+ const timestamp = now.toISOString();
22
+ return validateManagedWorkspace({
23
+ schemaVersion: 2,
24
+ owner: validateOwner(input.owner),
25
+ root: resolve(requireText(input.root, "Managed workspace root")),
26
+ entries: normalizeEntries(input.entries),
27
+ createdAt: timestamp,
28
+ updatedAt: timestamp
29
+ });
30
+ }
31
+ export function validateManagedWorkspace(workspace) {
32
+ if (workspace.schemaVersion !== 2) {
33
+ throw new Error("Managed workspace must use schemaVersion 2.");
34
+ }
35
+ validateOwner(workspace.owner);
36
+ if (resolve(requireText(workspace.root, "Managed workspace root")) !==
37
+ workspace.root) {
38
+ throw new Error("Managed workspace root must be absolute and normalized.");
39
+ }
40
+ normalizeEntries(workspace.entries);
41
+ requireTimestamp(workspace.createdAt, "ManagedWorkspace createdAt");
42
+ requireTimestamp(workspace.updatedAt, "ManagedWorkspace updatedAt");
43
+ return workspace;
44
+ }
45
+ export function workspaceProjectEntry(workspace, projectId) {
46
+ return workspace.entries.find((entry) => entry.projectId === projectId);
47
+ }
48
+ /** Stable key used by the aggregate's owner-keyed workspace map. */
49
+ export function managedWorkspaceKey(owner) {
50
+ const valid = validateOwner(owner);
51
+ switch (valid.type) {
52
+ case "task":
53
+ return `task:${valid.taskId}`;
54
+ case "work-item":
55
+ return `work-item:${valid.taskId}:${valid.workItemId}`;
56
+ case "review-round":
57
+ return `review-round:${valid.taskId}:${valid.reviewRoundId}`;
58
+ case "integration-attempt":
59
+ return `integration-attempt:${valid.taskId}:${valid.integrationAttemptId}`;
60
+ case "execution-lane":
61
+ return `execution-lane:${valid.taskId}:${valid.executionGroupId}:${valid.executionLaneId}`;
62
+ }
63
+ }
64
+ /** Physical worktree names are owner identities, never Role names. */
65
+ export function managedWorktreeName(owner) {
66
+ switch (owner.type) {
67
+ case "task":
68
+ return "main";
69
+ case "work-item":
70
+ return owner.workItemId;
71
+ case "review-round":
72
+ return owner.reviewRoundId;
73
+ case "integration-attempt":
74
+ return `integration-${owner.integrationAttemptId}`;
75
+ case "execution-lane":
76
+ return `execution-lane-${owner.executionGroupId}-${owner.executionLaneId}`;
77
+ }
78
+ }
79
+ function normalizeEntries(entries) {
80
+ if (!Array.isArray(entries)) {
81
+ throw new Error("Workspace Project entries are invalid.");
82
+ }
83
+ const projectIds = new Set();
84
+ const directories = new Set();
85
+ return entries.map((entry) => {
86
+ const projectId = requireIdentity(entry.projectId, "Project id");
87
+ const directory = requireIdentity(entry.directory, "Project directory");
88
+ if (!["read", "write"].includes(entry.access)) {
89
+ throw new Error(`Workspace Project access is invalid: ${String(entry.access)}.`);
90
+ }
91
+ if (projectIds.has(projectId)) {
92
+ throw new Error(`Workspace Project is duplicated: ${projectId}.`);
93
+ }
94
+ if (directories.has(directory)) {
95
+ throw new Error(`Workspace Project directory is duplicated: ${directory}.`);
96
+ }
97
+ projectIds.add(projectId);
98
+ directories.add(directory);
99
+ const path = resolve(requireText(entry.path, "Workspace Project path"));
100
+ if (path !== entry.path) {
101
+ throw new Error("Workspace Project path must be absolute and normalized.");
102
+ }
103
+ return {
104
+ projectId,
105
+ directory,
106
+ access: entry.access,
107
+ path,
108
+ branch: requireText(entry.branch, "Workspace Project branch"),
109
+ baseRef: requireText(entry.baseRef, "Workspace Project base ref"),
110
+ baseCommit: requireCommit(entry.baseCommit)
111
+ };
112
+ });
113
+ }
114
+ function validateOwner(owner) {
115
+ if (owner.type === "task") {
116
+ return { type: "task", taskId: requireIdentity(owner.taskId, "Task id") };
117
+ }
118
+ if (owner.type === "work-item") {
119
+ return {
120
+ type: "work-item",
121
+ taskId: requireIdentity(owner.taskId, "Task id"),
122
+ workItemId: requireIdentity(owner.workItemId, "Work item id")
123
+ };
124
+ }
125
+ if (owner.type === "review-round") {
126
+ return {
127
+ type: "review-round",
128
+ taskId: requireIdentity(owner.taskId, "Task id"),
129
+ reviewRoundId: requireIdentity(owner.reviewRoundId, "ReviewRound id")
130
+ };
131
+ }
132
+ if (owner.type === "integration-attempt") {
133
+ return {
134
+ type: "integration-attempt",
135
+ taskId: requireIdentity(owner.taskId, "Task id"),
136
+ integrationAttemptId: requireIdentity(owner.integrationAttemptId, "Integration Attempt id")
137
+ };
138
+ }
139
+ if (owner.type === "execution-lane") {
140
+ const purpose = owner.purpose;
141
+ if (purpose !== "execution" && purpose !== "review") {
142
+ throw new Error("Managed execution-lane workspace purpose is invalid.");
143
+ }
144
+ const workItemId = owner.workItemId === undefined
145
+ ? undefined
146
+ : requireIdentity(owner.workItemId, "Work item id");
147
+ const reviewRoundId = owner.reviewRoundId === undefined
148
+ ? undefined
149
+ : requireIdentity(owner.reviewRoundId, "ReviewRound id");
150
+ if (purpose === "execution" && workItemId === undefined) {
151
+ throw new Error("Managed execution-lane workspace requires a Work Item.");
152
+ }
153
+ if (purpose === "execution" && reviewRoundId !== undefined) {
154
+ throw new Error("Managed execution-lane workspace cannot also own a ReviewRound.");
155
+ }
156
+ if (purpose === "review" && reviewRoundId === undefined) {
157
+ throw new Error("Managed execution-lane workspace requires a ReviewRound.");
158
+ }
159
+ if (purpose === "review" && workItemId !== undefined) {
160
+ throw new Error("Managed review-lane workspace cannot also own a Work Item.");
161
+ }
162
+ return {
163
+ type: "execution-lane",
164
+ taskId: requireIdentity(owner.taskId, "Task id"),
165
+ executionGroupId: requireIdentity(owner.executionGroupId, "ExecutionGroup id"),
166
+ executionLaneId: requireIdentity(owner.executionLaneId, "ExecutionLane id"),
167
+ purpose,
168
+ ...(workItemId === undefined ? {} : { workItemId }),
169
+ ...(reviewRoundId === undefined ? {} : { reviewRoundId })
170
+ };
171
+ }
172
+ throw new Error("Managed workspace owner is invalid.");
173
+ }
174
+ function requireIdentity(value, label) {
175
+ const identity = requireText(value, label);
176
+ if ([".", "..", "__proto__", "prototype", "constructor"].includes(identity) ||
177
+ /[\/\\\0]/.test(identity)) {
178
+ throw new Error(`${label} is invalid.`);
179
+ }
180
+ return identity;
181
+ }
182
+ function requireCommit(value) {
183
+ const commit = requireText(value, "Managed workspace base commit").toLowerCase();
184
+ if (!/^[a-f0-9]{40}(?:[a-f0-9]{24})?$/.test(commit)) {
185
+ throw new Error("Managed workspace base commit is invalid.");
186
+ }
187
+ return commit;
188
+ }
189
+ function requireText(value, label) {
190
+ if (typeof value !== "string" || value.includes("\0")) {
191
+ throw new Error(`${label} is invalid.`);
192
+ }
193
+ const normalized = value.trim();
194
+ if (normalized.length === 0)
195
+ throw new Error(`${label} is required.`);
196
+ return normalized;
197
+ }
198
+ function requireTimestamp(value, label) {
199
+ if (typeof value !== "string" || !Number.isFinite(Date.parse(value))) {
200
+ throw new Error(`${label} is invalid.`);
201
+ }
202
+ }
@@ -0,0 +1,62 @@
1
+ # Task-local identity
2
+
3
+ Yui treats a Task as the aggregate boundary for durable workflow records. Each
4
+ Task owns an independent, monotonically increasing sequence for every record
5
+ family:
6
+
7
+ - WorkItem
8
+ - AgentRun
9
+ - ReviewRound
10
+ - ChangeSet
11
+ - IntegrationAttempt
12
+ - Message
13
+ - InputRequest
14
+ - Decision
15
+ - Milestone
16
+ - Event
17
+
18
+ The first record of each family in each Task is therefore local `-1`. Deleted,
19
+ cancelled, completed, reopened, and archived records never lower the persisted
20
+ high-water mark, so a local ID is never reused inside its Task. Each allocation
21
+ advances that aggregate high-water mark under the storage process lock.
22
+
23
+ Candidate identity is narrower: `candidate-N` is a WorkItem-local sequence.
24
+ Every Candidate stores its `taskId` and `workItemId`, in addition to the source
25
+ Run when one exists.
26
+
27
+ ## Reference contract
28
+
29
+ The portable form of a Task-owned reference is:
30
+
31
+ ```text
32
+ <task-id>/<local-id>
33
+ ```
34
+
35
+ For example, `task-7/work-item-1` and `task-9/work-item-1` are distinct. CLI,
36
+ JSON, mailbox, Controller, Hook, receipt, Web, and error paths retain the Task
37
+ scope. Context-free commands reject a bare local ID instead of searching all
38
+ Tasks, even if that ID currently happens to be unique.
39
+
40
+ A managed Task session may use `work-item-1` or `agent-run-1` because its
41
+ `YUI_TASK_ID` is explicit. A command that already receives the Task as another
42
+ argument may also use a subordinate local ID. Outside those two cases, use the
43
+ qualified form. Delivery receipts use the same provenance, for example:
44
+
45
+ ```text
46
+ agent-run:task-7/agent-run-1
47
+ input-request:task-7/input-1
48
+ ```
49
+
50
+ There is no compatibility lookup, cross-Task guess, or bare-ID fallback.
51
+
52
+ ## Current-schema boundary
53
+
54
+ Runtime opens only aggregate v13 / StoredTask v12. It does not convert,
55
+ dual-read, or infer records from an older schema. If an existing `YUI_HOME`
56
+ does not match the current schema, keep it untouched for external archival
57
+ and initialize a fresh home for this runtime.
58
+
59
+ This hard cut keeps Task-local references, Role desired configuration, and
60
+ immutable AgentRun/RoleSession effective snapshots under one unambiguous
61
+ contract. There is no compatibility lookup, conversion command, or
62
+ intermediate storage format.