@zq-silk/yui 0.15.9 → 0.15.12

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 (160) hide show
  1. package/ARCHITECTURE.md +8 -4
  2. package/ARCHITECTURE.zh-CN.md +5 -2
  3. package/README.md +13 -5
  4. package/dist/agent/launchEnvironment.js +7 -0
  5. package/dist/agentRun/agentRun.js +3 -0
  6. package/dist/cli/commandCatalog.js +64 -16
  7. package/dist/cli/interactionPolicy.js +7 -3
  8. package/dist/cli/managedDiagnostics.js +1 -1
  9. package/dist/cli/updateOrchestrator.js +24 -1
  10. package/dist/cli/updatePorts.js +7 -3
  11. package/dist/cli/upgradeCommand.js +42 -2
  12. package/dist/cli.js +381 -107
  13. package/dist/commands/executionAuditCommands.js +10 -0
  14. package/dist/commands/globalRoleCommands.js +339 -4
  15. package/dist/commands/projectCommands.js +50 -22
  16. package/dist/commands/releaseCommands.js +18 -0
  17. package/dist/commands/taskActor.js +25 -0
  18. package/dist/commands/taskCommands.js +586 -96
  19. package/dist/commands/taskIntegrationCommands.js +19 -39
  20. package/dist/commands/taskIntegrationQueueCommands.js +1 -1
  21. package/dist/commands/taskOverviewCommand.js +4 -3
  22. package/dist/commands/taskPublicationAdoptCommand.js +127 -0
  23. package/dist/commands/taskPublicationCommands.js +11 -2
  24. package/dist/commands/taskPublicationVerifyCommand.js +23 -39
  25. package/dist/commands/taskRemoteDeliveryCommand.js +22 -11
  26. package/dist/commands/taskRoleRuntimeStatus.js +35 -0
  27. package/dist/context/runContextPack.js +3 -0
  28. package/dist/context/taskCatalog.js +187 -0
  29. package/dist/context/taskContext.js +55 -6
  30. package/dist/controller/agentHostObservation.js +155 -0
  31. package/dist/controller/clientRuntime.js +17 -2
  32. package/dist/controller/controller.js +14 -2
  33. package/dist/controller/fileSchedulerStoreAdapter.js +519 -25
  34. package/dist/controller/globalInputDelivery.js +132 -0
  35. package/dist/controller/jobControl.js +6 -2
  36. package/dist/controller/providerRetryAdmission.js +100 -0
  37. package/dist/controller/providerRetryDelivery.js +218 -0
  38. package/dist/controller/resourceInventory.js +14 -4
  39. package/dist/controller/resourceInventoryLinux.js +2 -6
  40. package/dist/controller/runtime.js +117 -7
  41. package/dist/controller/runtimeEventInbox.js +32 -3
  42. package/dist/controller/runtimeEventProcessor.js +26 -6
  43. package/dist/controller/runtimeHookRunFence.js +75 -19
  44. package/dist/controller/structuredProviderObservation.js +133 -70
  45. package/dist/coordination/workMailboxQueue.js +5 -0
  46. package/dist/execution/workItemExecutionProjection.js +1 -1
  47. package/dist/executor/agentExecutor.js +64 -4
  48. package/dist/executor/executorRegistry.js +3 -0
  49. package/dist/executor/fileRoleLaunchPlanner.js +78 -118
  50. package/dist/integration/deliveryObligation.js +2 -1
  51. package/dist/integration/gitIntegrationService.js +329 -386
  52. package/dist/integration/integrationAttempt.js +30 -4
  53. package/dist/integration/integrationQueueService.js +7 -7
  54. package/dist/integration/integrationSourceApplication.js +323 -0
  55. package/dist/lifecycle/exactRunTerminalization.js +4 -1
  56. package/dist/message/globalInterrupt.js +33 -0
  57. package/dist/message/globalProviderRetry.js +15 -0
  58. package/dist/message/inputControlResolution.js +106 -0
  59. package/dist/message/message.js +367 -0
  60. package/dist/message/messageContinuation.js +126 -3
  61. package/dist/message/taskInterrupt.js +34 -0
  62. package/dist/observability/executionAudit.js +19 -0
  63. package/dist/observability/orchestrationMetrics.js +1 -1
  64. package/dist/release/releaseHandover.js +22 -0
  65. package/dist/release/releaseWorkflowPorts.js +15 -7
  66. package/dist/repository/gitWorkspace.js +430 -107
  67. package/dist/repository/projectMaintenanceLock.js +75 -18
  68. package/dist/repository/taskWorkspaceCoordinator.js +182 -101
  69. package/dist/repository/taskWorkspacePreparer.js +205 -72
  70. package/dist/repository/workItemCandidateSnapshot.js +34 -0
  71. package/dist/repository/workspaceCleanupInspection.js +187 -0
  72. package/dist/resources/resourceDiscovery.js +3 -2
  73. package/dist/runtime/agentError.js +5 -3
  74. package/dist/runtime/agentHost.js +179 -82
  75. package/dist/runtime/agentHostCompatibility.js +127 -0
  76. package/dist/runtime/agentHostProtocol.js +53 -0
  77. package/dist/runtime/builtinAgentErrorMappers.js +91 -0
  78. package/dist/runtime/codexAppServerRuntime.js +34 -3
  79. package/dist/runtime/executionEnvironment.js +0 -19
  80. package/dist/runtime/launchBroker.js +6 -0
  81. package/dist/runtime/providerControl.js +5 -1
  82. package/dist/runtime/providerRetry.js +198 -0
  83. package/dist/runtime/providerRuntimeIdentity.js +28 -2
  84. package/dist/runtime/sessionReconciliation.js +4 -4
  85. package/dist/runtime/sessionTokenMetrics.js +15 -5
  86. package/dist/runtime/structuredProviderHost.js +6 -2
  87. package/dist/runtime/taskRuntimeIsolation.js +30 -6
  88. package/dist/runtime/taskUsageMetrics.js +275 -0
  89. package/dist/runtime/tmuxAdapters.js +5 -3
  90. package/dist/scheduler/activeRoleRunDelivery.js +12 -0
  91. package/dist/scheduler/leaderWakeupProcessor.js +5 -0
  92. package/dist/scheduler/operatorEvent.js +4 -0
  93. package/dist/scheduler/taskExecutionProjection.js +38 -6
  94. package/dist/scheduler/taskObservabilityProjection.js +6 -44
  95. package/dist/scheduler/wakeReason.js +7 -1
  96. package/dist/scheduler/wakeupQueue.js +2 -0
  97. package/dist/setup/setupCommand.js +26 -8
  98. package/dist/storage/homeLayout.js +130 -0
  99. package/dist/storage/migrations/collapseWorktreeLayout.js +963 -0
  100. package/dist/storage/migrations/integrationContinuation.js +104 -0
  101. package/dist/storage/migrations/unifyHomeLayout.js +925 -0
  102. package/dist/storage/sqliteSchema.js +167 -4
  103. package/dist/storage/sqliteStore.js +57 -1
  104. package/dist/storage/storageVersions.js +1 -1
  105. package/dist/storage/storeRpc.js +2 -0
  106. package/dist/storage/taskCatalog.js +123 -0
  107. package/dist/storage/taskStore.js +2 -0
  108. package/dist/storage/upgrade/upgradeOrchestrator.js +95 -2
  109. package/dist/task/archiveDiagnostics.js +129 -0
  110. package/dist/task/archivePreflight.js +124 -0
  111. package/dist/task/nextAction.js +44 -11
  112. package/dist/task/publicationAdoption.js +56 -0
  113. package/dist/task/publicationReference.js +10 -0
  114. package/dist/task/remoteDelivery.js +31 -16
  115. package/dist/web/assets/client/app.js +147 -17
  116. package/dist/web/assets/client/components.js +56 -13
  117. package/dist/web/assets/client/i18n.js +78 -4
  118. package/dist/web/assets/client/taskSurface.js +108 -1
  119. package/dist/web/assets/client/view.js +39 -8
  120. package/dist/web/assets/shell.js +29 -0
  121. package/dist/web/assets/styles/layout.js +8 -1
  122. package/dist/web/assets/styles/widgets.js +12 -0
  123. package/dist/web/webServer.js +131 -4
  124. package/dist/web/webSnapshot.js +16 -6
  125. package/dist/web/webTaskSurface.js +222 -5
  126. package/dist/workspace/cleanupInspection.js +63 -0
  127. package/dist/workspace/workItemChangeSetManager.js +111 -35
  128. package/docs/agent-result-consumption.md +4 -0
  129. package/docs/agent-result-consumption.zh-CN.md +3 -0
  130. package/docs/agent-runtime-drivers.md +7 -0
  131. package/docs/agent-runtime-drivers.zh-CN.md +5 -0
  132. package/docs/architecture/README.md +2 -0
  133. package/docs/architecture/README.zh-CN.md +3 -1
  134. package/docs/architecture/capabilities-and-resources.md +30 -5
  135. package/docs/architecture/capabilities-and-resources.zh-CN.md +23 -3
  136. package/docs/managed-turn-and-session-runtime.md +47 -0
  137. package/docs/managed-turn-and-session-runtime.zh-CN.md +40 -0
  138. package/docs/observability/README.md +62 -0
  139. package/docs/observability/README.zh-CN.md +47 -0
  140. package/docs/project-refresh.md +77 -0
  141. package/docs/project-refresh.zh-CN.md +59 -0
  142. package/docs/provider-retry.md +70 -0
  143. package/docs/release-workflow.md +39 -0
  144. package/docs/release-workflow.zh-CN.md +29 -0
  145. package/docs/sqlite-control-plane-design.md +223 -1
  146. package/docs/task-delivery.md +133 -13
  147. package/docs/task-delivery.zh-CN.md +99 -10
  148. package/docs/task-discovery.md +102 -0
  149. package/docs/task-discovery.zh-CN.md +86 -0
  150. package/docs/testing/verification-levels.md +40 -0
  151. package/docs/testing/verification-levels.zh-CN.md +23 -0
  152. package/i18n/README.zh-CN.md +13 -7
  153. package/package.json +1 -1
  154. package/skills/yui-leader/references/execution.md +154 -51
  155. package/skills/yui-leader/references/integration.md +52 -2
  156. package/skills/yui-operator/SKILL.md +19 -3
  157. package/skills/yui-reviewer/SKILL.md +4 -0
  158. package/skills/yui-runtime/SKILL.md +42 -0
  159. package/skills/yui-runtime/references/publication.md +42 -0
  160. package/skills/yui-runtime/references/recovery.md +24 -0
@@ -69,10 +69,232 @@ Every persistent schema or payload change appends one immutable, contiguous
69
69
  storage migration. The CLI publishes both `storageVersion` and
70
70
  `minimumStorageVersion`; every valid Home in that inclusive range can upgrade
71
71
  directly to the current version without installing intermediate releases.
72
- The current source declares storage version **18**, with minimum supported
72
+ The current source declares storage version **25**, with minimum supported
73
73
  migration version **1**, in `src/storage/storageVersions.ts`. Homes below that
74
74
  floor are not migration inputs and remain untouched.
75
75
  The target binary's `upgrade --update-preflight` and `--update-apply` result
76
76
  shapes and parent-owned handover-lock proof remain backward compatible with
77
77
  every updater released from storage version 1 onward, so an old source CLI can
78
78
  still drive a much newer target's complete migration chain.
79
+
80
+ ## Unified Home layout
81
+
82
+ Every Yui self-managed directory lives under the single canonical `YUI_HOME`
83
+ (default `~/.yui`; an explicit `YUI_HOME` is honoured verbatim). `YUI_HOME` is
84
+ never inferred from the current working directory and never substituted with a
85
+ username. `src/storage/homeLayout.ts` is the one authority that derives each
86
+ managed root from Home:
87
+
88
+ | Root | Path | Holds |
89
+ |---|---|---|
90
+ | Managed worktrees | `<home>/workspaces/tasks/<taskId>/<owner>/<projectDirectory>` | Actual Task/WorkItem/Review/Integration Git directories, addressed by the bound Project directory. Owners are `main`, `work-items/<id>`, `reviews/<id>`, `integrations/<id>` and `execution-lanes/<group>/<lane>`. |
91
+ | Read-only context views | Within the same owner directory | Regenerable symlinks to read-only Project context only; writable entries are actual Git directories, not links. |
92
+ | Global Role workspace | `<home>/workspaces/global` | Default cwd for Yui-auto-created Global Roles (the `yui setup` Operator/Leader and ad-hoc Global Roles added without an explicit `--workspace`). A plain cwd, not a managed Git workspace. |
93
+ | Task provider runtimes | `<home>/runtime/task-runtimes` | Task provider data/cache/tmp; also the planning cwd at `…/planning/<taskId>`. |
94
+ | Integration runtimes | `<home>/runtime/integration-runtimes` | The integration check's provider data/cache/tmp (a separate partition from Task runtimes). |
95
+ | Update staging | `<home>/runtime/update-staging` | `yui update`'s side-by-side package install (an upgrade artifact). |
96
+ | Release workflow scratch | `<home>/runtime/release-workflow` | The release workflow's smoke-install dir and verified publish-snapshot tarball (release artifacts). |
97
+ | Storage backups | `<home>/backups` | Pre-upgrade DB backups (the fenced upgrade's rollback anchor). |
98
+
99
+ Published migrations 1–23 remain unchanged, including Task artifacts in local
100
+ Git (19), Integration continuation (20), force-archive evidence (21), and
101
+ Controller-owned Host ingress (22), and unified message input control (23).
102
+ The two offline layout steps are now 23→24 (`unify-home-layout`) and
103
+ 24→25 (`collapse-worktree-layout`). Version 24's
104
+ `workspaces/worktree` directory is an intermediate layout, not a second live
105
+ root at version 25. A single upgrade applies the full pending chain.
106
+
107
+ Stop this Home's writers and take a backup before upgrading. The layout steps
108
+ copy and verify the registered Git trees, repair only the copies' links, and
109
+ preserve old sources for manual recovery. Version 25 replaces registered
110
+ Task-view symlinks with real writable directories; unrelated Task scratch is
111
+ retained. Read-only context remains a view and can be promoted to a writable
112
+ worktree when WorkItem scope expands. Do not delete the old sources until the
113
+ new layout is verified; a failed upgrade requires manual residue cleanup and
114
+ backup recovery, not automatic resume.
115
+
116
+ Both runtime partitions (`runtime/task-runtimes`, `runtime/integration-runtimes`)
117
+ are the ONLY Home subtrees a provider runtime root is allowed to overlap; a
118
+ runtime root overlapping any other part of Home (the database, `workspaces/`,
119
+ `projects/`) is still rejected by `assertTaskRuntimeIsolationPreflight`, so
120
+ unifying the root does not weaken control-data or cross-owner isolation.
121
+
122
+ `defaultWorkspace` is a user-facing cwd for external Project input only; it is
123
+ **not** a second authority for internal managed paths, and is intentionally not
124
+ an input to `homeLayout.ts`. A Yui-auto-created Global Role that carries no
125
+ user-chosen cwd no longer falls back to it (or to `process.cwd()`): `yui setup`'s
126
+ built-in Operator/Leader and `yui role add` without `--workspace` now default to
127
+ the Home-internal `managedGlobalRoleWorkspace(home)` (`<home>/workspaces/global`),
128
+ and `setup` no longer fabricates an external Home-sibling `workspace/` — a
129
+ `default-workspace` is persisted only if the user configured one. A user who
130
+ *names* an external directory (explicit `--workspace`, or a configured
131
+ `default-workspace`) keeps external-resource semantics; the outside-Home guard
132
+ still applies to it. The "planning/global cwd" that criterion 1 places under Home
133
+ is thus both the *disposable runtime cwd Yui materializes itself* — the Draft
134
+ planning cwd (`planningRuntimeCwd`, under `runtime/task-runtimes/planning`) — and
135
+ the auto-created Global Role cwd above; only an operator's *explicitly named*
136
+ external directory stays outside by design.
137
+
138
+ Only genuine short-path IPC socket ENDPOINTS remain outside Home, and only
139
+ because a Unix-domain `sockaddr_un` path has a small fixed length budget that a
140
+ deep Home path would exceed. Each is a single socket path, never a data/cache/tmp
141
+ root:
142
+
143
+ - the Controller socket (`/tmp/yui-<uid>/<homeId>.sock`),
144
+ - the tmux server socket (`/tmp/tmux-<uid>` via the tmux namespace),
145
+ - the Agent Host socket (`/tmp/yui-<uid>/agent-host/…sock`), and
146
+ - the integration check's tmux socket dir (`/tmp/yi-<uid>-<digest>`), bound only
147
+ into `TMUX_TMPDIR`.
148
+
149
+ The integration check's ordinary runtime state is **not** an exception: its
150
+ provider data, cache, and temp roots live in the Home partition above
151
+ (`runtime/integration-runtimes`); `TMPDIR`/`TMP`/`TEMP` point there, and only
152
+ `TMUX_TMPDIR` is redirected to the short `/tmp` socket dir.
153
+
154
+ ## Migration 23 → 24: unify managed paths under Home
155
+
156
+ Historically the managed worktrees lived under the out-of-Home
157
+ `defaultWorkspace` (`<ws>/worktree`, `<ws>/tasks`) and the provider runtimes
158
+ under a string-built Home sibling (`<home>.task-runtimes`). The one forward
159
+ migration `unify-home-layout` (`src/storage/migrations/unifyHomeLayout.ts`)
160
+ brings that content under Home and rewrites the persisted absolute pointers the
161
+ runtime dereferences as live, without re-cloning Git content or renaming the
162
+ path-independent Git refs. It runs as the migration's `migrateData` step inside
163
+ the upgrade transaction, so schema and data advance atomically or roll back
164
+ together.
165
+
166
+ **Exactly one tree is physically relocated: the managed Git worktree tree.** It
167
+ is the sole subtree that holds durable, non-regenerable content (committed **and**
168
+ uncommitted work), so it alone is copied on disk. Everything else that "moves"
169
+ moves only by pointer:
170
+
171
+ - the per-Task symlink views (`<ws>/tasks`) are regenerable — the pointer is
172
+ rewritten and `ensureWorkspaceView` rebuilds the links at the next launch;
173
+ - the provider runtimes (`<home>.task-runtimes`) are disposable — the pointer is
174
+ rewritten and the roots are recreated at the next launch.
175
+
176
+ The worktree copy is **non-destructive and verified** (see *Recovery and
177
+ rollback*): the source is copied (never renamed away), the replica's content
178
+ digest is checked against the source, and only a verified replica is atomically
179
+ published. The original worktree tree is **preserved** as the rollback anchor;
180
+ removing it is a later, authorized, post-restart cleanup step, never part of this
181
+ transaction.
182
+
183
+ The pointer rewrite is **surgical, not a table sweep** — only records the runtime
184
+ treats as live launch pointers are touched:
185
+
186
+ - `managed_workspaces` — the authoritative registry (`path` column, payload
187
+ `root`, every `entries[].path`). Every surviving row is live (dispositioned
188
+ rows are deleted at cleanup).
189
+ - active (`status='active'`) `turns` — **both** `run.effective.workspace` (the
190
+ actual OS launch cwd source) and the `run.workspace` mirror, rewritten together
191
+ because `validateRun` requires them to stay identical; a run's
192
+ `.result.systemEvidence.workspaceSnapshot` is frozen Git evidence and is left
193
+ byte-for-byte intact.
194
+ - `role_session_sets` / `global_role_session_sets` — each live session's
195
+ `effective.workspace` in the `sessions` map; terminal sessions in `history` are
196
+ preserved.
197
+ - `review_rounds` — the mirrored workspace (only while its `managed_workspaces`
198
+ owner row still exists) and each OPEN execution lane; an orphaned mirror or a
199
+ terminal lane is frozen evidence and is preserved.
200
+ - `work_items` — each OPEN execution lane inside `executionGroups`; candidate
201
+ snapshots (`work_item_candidates`) are frozen and preserved.
202
+ - `task_roles.workspace` — the live launch cwd, including a Draft's planning Role
203
+ under the old runtime sibling (never self-healed until activation).
204
+ - `task_records.cwd` — self-heals on the next `prepareTaskWorkspace`, but is
205
+ rewritten defensively to close the stale-read window.
206
+
207
+ Everything else is preserved on purpose: `context_snapshots`, terminal `turns`
208
+ (with their system evidence), terminal sessions, `work_item_candidates`, terminal
209
+ execution lanes, terminal `durable_jobs`, `events`, and reports are frozen
210
+ history. `resource_registry` is re-discovered from disk; `projects.path` is an
211
+ external, user-owned checkout.
212
+
213
+ The migration is applied **offline** and is **fail-closed and pre-checkable**.
214
+ It is run by the standalone `yui upgrade` boundary AFTER the operator has stopped
215
+ this Home's Controller, Agent Host, and any execution/Job writers; it does not
216
+ orchestrate that shutdown, coordinate an online write-stop, or migrate a live
217
+ Session. It keeps only the minimal preconditions it can implement directly:
218
+
219
+ - It **refuses** if a queued or running `durable_jobs` step is bound to a tree
220
+ about to relocate. A durable Job's runner is detached and could outlive an
221
+ incompletely stopped Controller, so moving that tree would risk an in-flight
222
+ silent move; this is the one residual runtime signal the offline migration
223
+ still guards. Let the Job drain or cancel it, then re-run the upgrade.
224
+ (`active_turns` is steady state, not an in-flight signal, and is deliberately
225
+ not consulted.)
226
+ - It **refuses** if a relocation target already exists at all — it is either a
227
+ foreign directory or residue from a failed prior run, and the offline migration
228
+ never adopts a pre-existing target. Confirm the source is intact, then move or
229
+ remove the target and re-run the upgrade.
230
+ - Every refusal is surfaced as a **collected, read-only pre-check**: `yui
231
+ upgrade --dry-run` and the updater's `--update-preflight` run the same plan and
232
+ the same blocking conditions execute would throw on, opening the DB read-only
233
+ and reporting each independent blocker as `{reason, detail}` (blocked outcome)
234
+ without mutating the Home — a genuine pre-check, not a best-effort guess.
235
+ - A Home already in the unified layout (or a fresh Home with nothing to relocate)
236
+ is a **no-op**.
237
+
238
+ ### Recovery and rollback
239
+
240
+ The migration keeps **no recovery manifest and no resumable state machine** — it
241
+ is a one-time offline transform, not an interruptible online orchestration. The
242
+ worktree relocation is **copy → digest-verify → atomic-publish → preserve-source**:
243
+
244
+ 1. the relocation target must not already exist; a pre-existing target is refused
245
+ up front (foreign directory or failed-run residue — never adopted);
246
+ 2. the source is copied into a same-filesystem staging dir (`<to>.incoming`),
247
+ never renamed away;
248
+ 3. a content-addressed inventory digest of the replica is compared to the source
249
+ — a mismatch deletes the staging copy and aborts (nothing published, source
250
+ intact);
251
+ 4. only a verified replica is `rename`d into the final target (atomic on one
252
+ filesystem);
253
+ 5. the original source tree is left in place as the rollback anchor.
254
+
255
+ There is **no automatic idempotent recovery**. Because a pre-existing target is
256
+ always refused, a run interrupted after a partial publish does not silently
257
+ resume or adopt the partial tree on the next attempt: the operator inspects the
258
+ preserved source, removes the incomplete target (and any `<to>.incoming`
259
+ staging), and re-runs the upgrade from a clean state. The `--dry-run` /
260
+ `--update-preflight` pre-check surfaces exactly this `target-conflict` before the
261
+ apply transaction is entered, so the residue is reported, not discovered
262
+ mid-migration.
263
+
264
+ After the copy, the worktrees are reconnected. `git worktree repair` chases the
265
+ absolute pointer files inside a worktree, so running it on a verbatim copy whose
266
+ pointers still address the OLD source would rewrite the OLD source's `.git`
267
+ files and corrupt the rollback anchor. The migration therefore **relinks first**:
268
+ it deterministically repoints, in the NEW copy only, the two cross-reference
269
+ pointer files (a linked worktree's `.git` stub and each
270
+ `main/.git/worktrees/<name>/gitdir`) from OLD to NEW, and only THEN runs `git
271
+ worktree repair` from each main clone at its new path as a belt-and-braces
272
+ reconciliation now confined to the new tree. This keeps the preserved source a
273
+ fully independent, working Git: its `.git` is byte-for-byte unchanged and it
274
+ still resolves HEAD/index/status after the migration (verified empirically on a
275
+ private disposable Home). **A repair failure is fatal** — it aborts the migration
276
+ so the transaction rolls back rather than advancing the version over unrepaired
277
+ worktrees.
278
+
279
+ Because the data step runs inside the upgrade transaction, any throw rolls the
280
+ schema back to its original version; the fenced upgrade orchestrator additionally takes a
281
+ `database.backup()` and restores it on failure. Recovery from a failed run is
282
+ **manual, not automatic**: because the source is never removed and the copy is
283
+ digest-verified before publish, the preserved source is always intact, so the
284
+ operator clears any partial target and re-runs the upgrade. No re-run can lose or
285
+ corrupt the original content, but the tool does not itself resume an interrupted
286
+ move set.
287
+
288
+ **Old-source cleanup** is intentionally deferred and out of band: after a
289
+ successful upgrade the old external `worktree`, `tasks`, and `<home>.task-runtimes`
290
+ roots are left **in place** (not emptied) until an operator-authorized cleanup
291
+ removes them. This keeps a full rollback anchor available across the first
292
+ restart.
293
+
294
+ **Rollback limits:** once the Controller restarts against the unified layout and
295
+ begins writing new records under Home, restoring the pre-upgrade DB backup no
296
+ longer matches the newly written on-disk state. Until that first post-upgrade
297
+ write, the preserved old source plus the DB backup are a complete rollback pair;
298
+ after it, the supported recovery is forward (the layout is already unified), not a
299
+ downgrade to the split layout. Verify an upgrade only on a private, disposable
300
+ Home before applying it to a shared environment.
@@ -13,6 +13,9 @@ prepares physical workspaces, and adopts status/ownership atomically. Failed
13
13
  preparation leaves the Task Draft with a failed request and a diagnosis delivered
14
14
  to the Leader. Deferred activation retains the exact intent and waits for native
15
15
  quiescence, whether requested in a planning Run or subsequent discussion.
16
+ Project maintenance contention waits asynchronously before resource adoption.
17
+ A lock timeout or cancelled wait preserves the original activation request;
18
+ after acquiring the lock, activation rechecks current intent and authority.
16
19
 
17
20
  Task type describes the requested outcome, not the mandatory executor.
18
21
  Leader owns bounded work directly or assigns substantial independent WorkItems.
@@ -22,7 +25,8 @@ attempts at the same frozen Assignment, followed by Leader-selected synthesis.
22
25
  ## Managed workspaces
23
26
 
24
27
  Stable Project checkouts are read-only references. Task main is a logical
25
- multi-Project root with per-Project Git worktrees. For one Project, the Agent's
28
+ multi-Project root with independent per-Project Git clones; WorkItem, Review and
29
+ Integration worktrees belong to those Task repositories. For one Project, the Agent's
26
30
  normal cwd is its managed Git root; for multiple Projects, the root and native
27
31
  additional-directory mechanism expose the explicit Project set.
28
32
 
@@ -75,31 +79,147 @@ Leader delivery. The current native turn must end so the pending notification
75
79
  can arrive; the Leader then reads the original message and reassesses completion.
76
80
  This derives from existing Messages and mailbox delivery, not a second
77
81
  acknowledgement or workflow state.
78
- Terminal workspace cleanup can remain an advisory at completion, but not at
79
- archive. Artifacts selected as results must be fixed, present and Task-local.
82
+ Terminal workspace cleanup can remain an advisory at completion. Ordinary
83
+ archive requires it to be settled; explicitly authorized force archive may
84
+ retain unresolved resources as described below. Artifacts selected as results
85
+ must be fixed, present and Task-local.
80
86
 
81
87
  Publication records a remote PR/MR reference. Reported merge, independently
82
88
  verified merge and exact Task-head coverage are separate facts. Task completion
83
89
  does not prove any of them. Remote delivery is read from exact publication/head
84
90
  evidence, not inferred from a title or branch name.
85
91
 
92
+ Completion heads remain the immutable acceptance baseline. A later, authorized
93
+ integration may produce a different publication candidate (including a rebase
94
+ or merge before a remote squash). Neither ancestry nor a successful Integration
95
+ proves that the accepted behavior survived, or accepts additional changes.
96
+
97
+ For a completed, unarchived Task, record the exact candidate as the Publication's
98
+ `localCommit`, then read `task publication diff <task>/<publication>`. This reads
99
+ only Task-owned local Git objects and returns the original completion reference,
100
+ both commit/tree endpoints, the full diff (including binary changes), and a
101
+ digest binding those facts. Review removals, additions and conflict resolutions
102
+ against the original requirements. If they preserve the accepted result and all
103
+ relevant increments are accepted, use
104
+ `task publication adopt <task>/<publication> --reviewed-diff <sha256> --acceptance <text>`.
105
+ The acceptance must explain that judgment and its verification/review evidence;
106
+ Core checks fixed identity and facts, not the meaning of the code. If an existing
107
+ Task Integration produced that exact candidate, pass its local ID with
108
+ `--integration <id>` to both commands to bind its committed evidence as well.
109
+ This records one Task event, not a new delivery status, Candidate lifecycle,
110
+ Git operation, or permission to change completed work.
111
+
112
+ `task publication verify` remains the explicit, authorized provider read. It
113
+ records the remote source head, PR/MR state and merge commit independently of
114
+ Task acceptance. A mismatched head or non-merged state is saved as **reported**,
115
+ superseding earlier verification; provider errors or mismatched external identity
116
+ write nothing. A merged provider observation verifies only that Publication's
117
+ exact local candidate. A squash merge needs no fabricated commit ancestry.
118
+ Metadata/verification successors preserve adoption only through an uninterrupted
119
+ same-candidate Publication lineage. Candidate or referenced Integration changes
120
+ cannot silently reuse the decision.
121
+
122
+ CLI, current Leader Context and Web derive coverage from these same facts, with
123
+ no provider reads or evidence writes. They distinguish not delivered, merged
124
+ but uncovered, covering merge not verified, partial delivery and verified merge.
125
+ Each Project retains its own accepted head, selected candidate, adoption reference
126
+ and reason. Unknown historical heads remain unknown; old exact-SHA evidence stays
127
+ valid without inventing adoption, and archive never proves remote delivery.
128
+
86
129
  Cancelled intent does not prove the runtime stopped. User/Operator may reopen
87
130
  cancelled Tasks; Leader may reopen completed Tasks. Reopening requires fresh
88
131
  explicit input/work selection and never replays previous delivery requests.
89
132
 
90
133
  ## Archive
91
134
 
92
- Archive is a separate authorized action after active work is settled and
93
- resources are clean and removable. Choose integrated delivery or deliberate
94
- abandonment explicitly. Integrated archive requires exact merged heads and
95
- verified publication evidence. An explicitly authorized verification override
96
- cannot bypass missing or stale heads or an unmerged result.
97
-
98
- Managed WorkItem resources must be integrated or deliberately abandoned before
99
- cleanup. Review, Lane and Integration resources must be settled. Dirty worktrees
100
- remain for the Agent to resolve; no implicit reset or force deletion occurs.
101
- Task main branches and durable Task records retain recovery information.
135
+ Archive requires independent user/Operator authorization for an exact completed
136
+ or cancelled (retired) Task. Completion alone grants none, and ordinary archive
137
+ approval does not authorize force. Select one disposition explicitly:
138
+
139
+ ```sh
140
+ yui task archive <task> --integrated
141
+ yui task archive <task> --abandon
142
+ # Only with explicit force authorization, preserving the chosen disposition:
143
+ yui task archive <task> (--integrated|--abandon) --force
144
+ ```
145
+
146
+ ### Ordinary archive
147
+
148
+ Active work and inputs must be settled, and managed resources clean and safely
149
+ removable. WorkItem results must be integrated or deliberately abandoned;
150
+ Review, Lane and Integration resources must be settled. With `--integrated`,
151
+ each Project requiring code delivery needs a merged, verified Publication
152
+ covering its accepted head, either exactly or through valid explicit candidate
153
+ adoption. `--abandon` records deliberate non-delivery,
154
+ not verified merge.
155
+
156
+ Missing/stale coverage, unresolved execution or dirty worktrees prevent ordinary
157
+ archive. Resolve the reported facts before an explicit retry; no implicit reset
158
+ or force deletion occurs.
159
+
160
+ ### Explicit force archive
161
+
162
+ `--force` is not merely a merge-verification override. It commits the archive
163
+ and stops new Task scheduling before attempting safe foreground cleanup.
164
+ Missing or stale delivery evidence, an unmerged result, unresolved execution
165
+ and cleanup failures become warnings with retained resource references, rather
166
+ than blocking that archive commit. Authority, eligible lifecycle, exact resource
167
+ identity and mandatory audit persistence still fail closed.
168
+
169
+ Force neither verifies a merge nor accepts work, proves quiescence, discards
170
+ dirty data or implies `--abandon`. It preserves the selected disposition and
171
+ original Publication/completion evidence. Unverified local commits and resources
172
+ that cannot safely be released stay owned and traceable. A cleanup failure does
173
+ not roll back archive; late runtime events remain source evidence without
174
+ resuming the Task or settling unknown input.
175
+
176
+ ### Read the result before cleanup
177
+
178
+ `yui task show <task> --json` exposes `data.archive.warnings`,
179
+ `data.archive.retainedResources` and `data.archive.cleanupEvents`.
180
+ `yui task context <task> --json` retains the original records and events;
181
+ `yui task remote-delivery <task> --json` reports delivery separately.
182
+ Warnings include historical cleanup attempts; retained references describe
183
+ current ownership, not a second cleanup queue.
184
+
185
+ An archive result with `archived=true` proves archival, not that cleanup fully
186
+ succeeded. Even `cleanupFinished` means the foreground pass finished, not that
187
+ every resource was removed. Repeating archive reports current facts and does
188
+ not replay cleanup. After inspection, use explicit exact-owner resource
189
+ operations for safe cleanup; no background retry or broader deletion authority
190
+ is implied. Both archive paths preserve Task history and recovery information.
102
191
  Archived Tasks cannot reopen.
103
192
 
193
+ `yui task archive-preflight <task> (--integrated|--abandon) [--force] [--json]`
194
+ reads current admission, delivery and exact-owner cleanup checks in one report.
195
+ It is available before and after archive, including to the Task's authorized
196
+ Leader reader. `--force` here only selects the behavior to inspect. It never
197
+ archives, prepares workspaces, refreshes Git indexes, stops Sessions, acquires
198
+ maintenance locks, fetches remote data, or writes a cleanup plan.
199
+
200
+ Each blocking/unknown check has a resource, reason code, expected and observed
201
+ values, source references and existing inspection/disposition commands. Git
202
+ paths outside the authorized Task are redacted. The report distinguishes
203
+ missing Candidate workspace, changed workspace identity/metadata/path, missing
204
+ frozen commit, moved HEAD, dirty worktree, missing/locked Git registration,
205
+ unintegrated result, uncovered delivery, unsettled owner and unknown execution.
206
+ Status inspection disables optional index writes and filesystem-monitor hooks.
207
+ If a tracked file selects a configured clean/process filter (including an
208
+ initialized submodule's), it reports `git-status-requires-filter` as unknown instead of
209
+ executing the program or bypassing normalization and guessing clean/dirty.
210
+ Historical Candidate paths remain immutable. A path difference, including one
211
+ consistent with an earlier layout migration, does not itself prove a safe
212
+ relocation: without an exact mapping the check reports the difference and
213
+ retains the resource; it does not repair history or weaken commit/owner checks.
214
+
215
+ Preflight is an observation, not a removal permit. Cleanup reloads the same
216
+ checks and Git verifies ownership/dirt again at removal. A Task-main clone's
217
+ dependent registrations are expected before child cleanup and must be absent
218
+ before clone removal. Archive preserves new dirt even in a failed Integration
219
+ workspace; the separate explicit Integration cleanup command keeps its existing
220
+ disposable-conflict behavior. A finished force cleanup means the foreground
221
+ attempt ended, not that every resource was released. Current retained references
222
+ and exact physical runtime evidence remain separate from historical diagnostics.
223
+
104
224
  Use each command's `--help` to inspect its exact authority and options before
105
225
  cleanup; reading a lifecycle document does not authorize an external write.
@@ -11,6 +11,8 @@ Task 生命周期是 `draft / active / completed / cancelled / archived`。Draft
11
11
  状态/所有权。准备失败会让 Task 停在 Draft,附带一个失败请求和投递给 Leader 的
12
12
  诊断。延迟激活保留确切意图并等待原生静止,无论它是在规划 Run 中还是在后续讨论中
13
13
  被请求的。
14
+ Project 维护争用会在采用资源前异步等待。锁超时或等待被取消时保留原激活请求;
15
+ 获得锁后重新检查当前意图与权限。
14
16
 
15
17
  Task type 描述被请求的结果,而不是强制的执行者。Leader 直接负责有界工作,或分派
16
18
  有独立价值的 WorkItem。直接执行没有 Group。复制是为了在同一个冻结 Assignment 上
@@ -19,7 +21,8 @@ Task type 描述被请求的结果,而不是强制的执行者。Leader 直接
19
21
  ## 受管工作区
20
22
 
21
23
  稳定的 Project checkout 是只读参考。Task main 是一个逻辑上的多 Project 根,带有
22
- 按 Project 划分的 Git worktree。对单个 Project,Agent 的正常 cwd 是其受管 Git 根;
24
+ 按 Project 划分的独立 Git clone;WorkItem、Review 和 Integration worktree 归这些
25
+ Task 仓库所有。对单个 Project,Agent 的正常 cwd 是其受管 Git 根;
23
26
  对多个 Project,根加上原生的附加目录机制暴露明确的 Project 集合。
24
27
 
25
28
  一个隔离的 WorkItem 为可写 Project 拥有独立 worktree,为其余 Project 提供 Task-main
@@ -58,25 +61,111 @@ Reviewer Run 持有报告;执行成功不等于语义通过。验收归 Leader
58
61
  干净且已提交的 Task-main 快照。当有一条新的 user/Operator 消息仍在等待 Leader
59
62
  投递时,它也会拒绝完成。当前原生轮次必须结束,待处理的通知才能到达;随后 Leader
60
63
  读取原始消息并重新评估完成。这派生自既有的 Message 和 mailbox 投递,而不是第二套
61
- 确认或工作流状态。终态工作区清理在完成时可以只是建议,但在归档时不行。被选作
62
- 结果的 Artifact 必须是固定的、存在的且 Task 局部的。
64
+ 确认或工作流状态。终态工作区清理在完成时可以只是建议。普通归档要求清理已结算;
65
+ 明确授权的 force 归档可以保留下文所述的未解决资源。被选作结果的 Artifact 必须是
66
+ 固定的、存在的且 Task 局部的。
63
67
 
64
68
  发布记录一个远程 PR/MR 引用。被报告的合并、独立验证的合并以及确切的 Task-head
65
69
  覆盖是彼此独立的事实。Task 完成不证明其中任何一项。远程交付从确切的发布/head
66
70
  证据读取,而不从标题或分支名推断。
67
71
 
72
+ 完成 head 始终是不可变的验收基线。之后获授权的集成可能产生不同的发布候选
73
+ (例如远端 squash 前的 rebase 或 merge)。祖先关系和 Integration 成功都不能
74
+ 证明验收行为未被撤销,也不验收额外增量。
75
+
76
+ 对于已完成但未归档的 Task,先把精确候选记为 Publication 的 `localCommit`,
77
+ 再读 `task publication diff <task>/<publication>`。此命令只读取 Task 自有的
78
+ 本地 Git 对象,返回原完成记录引用、两端 commit/tree、完整差异(含二进制变更),
79
+ 以及绑定这些事实的摘要。逐项核对删除、增加和冲突处理是否仍满足原需求;仅在原成果
80
+ 保留、相关增量也已验收时,执行
81
+ `task publication adopt <task>/<publication> --reviewed-diff <sha256> --acceptance <text>`。
82
+ 验收依据应解释上述判断及其验证/审阅证据;Core 核验固定身份和事实,不裁定代码语义。
83
+ 如果已有本 Task 的 Integration 产出了该精确候选,在两个命令中都传入
84
+ `--integration <id>`,一并绑定其已提交证据。这只新增一个 Task 事件,不新增交付
85
+ 状态表、Candidate 生命周期或 Git 操作,也不授权修改已完成成果。
86
+
87
+ `task publication verify` 仍是显式且须获授权的 provider 读取。它独立于 Task
88
+ 验收,记录远端 source head、PR/MR 状态和 merge commit。head 不匹配或尚未合并时,
89
+ 保存为 **reported** 并取代旧验证;provider 错误或外部身份不匹配则不写任何证据。
90
+ 已合并的 provider 观察仅验证该 Publication 的精确本地候选;squash 不需要伪造
91
+ 提交祖先关系。元数据/验证更新只有沿连续同候选的 Publication 血缘才能继承采用;
92
+ 候选或所引用的 Integration 变化,不能悄悄复用旧决定。
93
+
94
+ CLI、当前 Leader Context 和 Web 从同一组事实推导覆盖,不联网、不写证据。展示
95
+ 区分尚未交付、PR/MR 已合并但未覆盖、已覆盖合并但未验证、部分交付、已验证合并。
96
+ 每个 Project 保留自己的验收 head、候选、采用引用和原因。缺失的历史 head 仍然
97
+ 未知;旧精确 SHA 证据无需补造采用记录,归档也不能反推已交付。
98
+
68
99
  取消意图不证明运行时已停止。user/Operator 可以重开已取消的 Task;Leader 可以重开
69
100
  已完成的 Task。重开需要全新的显式输入/工作选择,绝不重放先前的交付请求。
70
101
 
71
102
  ## 归档
72
103
 
73
- 归档是一次单独的授权动作,发生在活动工作已了结、资源干净可移除之后。显式选择
74
- 集成交付或有意放弃。集成归档要求确切的已合并 head 和已验证的发布证据。一次显式
75
- 授权的验证覆盖不能绕过缺失或陈旧的 head,也不能绕过一个未合并的结果。
76
-
77
- 受管的 WorkItem 资源必须在清理前被集成或有意放弃。Review、Lane 和 Integration
78
- 资源必须已结算。脏 worktree 留给 Agent 解决;不发生隐式 reset 或强制删除。Task
79
- main 分支和持久 Task 记录保留恢复信息。已归档的 Task 不能重开。
104
+ 归档需要针对确切的 completed 或 cancelled(retired)Task 获得独立的 user/Operator
105
+ 授权。完成本身不授予归档权限,普通归档批准也不授权 force。显式选择一种处置:
106
+
107
+ ```sh
108
+ yui task archive <task> --integrated
109
+ yui task archive <task> --abandon
110
+ # 仅在明确授权 force 后使用,并保留所选处置:
111
+ yui task archive <task> (--integrated|--abandon) --force
112
+ ```
113
+
114
+ ### 普通归档
115
+
116
+ 活动工作与输入必须已了结,受管资源干净且可安全移除。WorkItem 结果必须已集成或
117
+ 有意放弃;Review、Lane 和 Integration 资源必须已结算。使用 `--integrated` 时,
118
+ 每个需要代码交付的 Project 都要求已合并且已验证的 Publication,通过精确匹配
119
+ 或有效显式采用候选覆盖其验收 head。`--abandon` 记录有意不交付,而不是已验证合并。
120
+
121
+ 缺失或陈旧的覆盖、未解决的执行或脏 worktree 会阻止普通归档。先解决报告的事实,
122
+ 再显式重试;不会隐式 reset 或强制删除。
123
+
124
+ ### 明确授权的 force 归档
125
+
126
+ `--force` 不只是覆盖合并验证要求。它先提交归档并停止新的 Task 调度,再尝试安全的
127
+ 前台清理。缺失或陈旧的交付证据、未合并结果、未解决的执行和清理失败会成为警告及
128
+ 保留资源引用,而不阻止这次归档提交。权限、合法生命周期、精确资源身份和强制审计
129
+ 持久化仍严格检查,失败时拒绝相应操作。
130
+
131
+ Force 不验证合并、不验收工作、不证明物理静止、不丢弃脏数据,也不隐含 `--abandon`。
132
+ 它保留所选处置及原始 Publication/完成证据。未验证的本地提交和无法安全释放的资源
133
+ 仍有明确 owner 且可追溯。清理失败不回滚归档;迟到的运行时事件仍作为来源证据,
134
+ 不恢复 Task 或结算未知输入。
135
+
136
+ ### 清理前先读结果
137
+
138
+ `yui task show <task> --json` 暴露 `data.archive.warnings`、
139
+ `data.archive.retainedResources` 和 `data.archive.cleanupEvents`。
140
+ `yui task context <task> --json` 保留原始记录与事件;
141
+ `yui task remote-delivery <task> --json` 单独报告交付。警告包含历史清理尝试;
142
+ 保留引用描述当前所有权,不是第二套清理队列。
143
+
144
+ 归档结果中的 `archived=true` 证明已归档,不证明清理全部成功。即使 `cleanupFinished`
145
+ 也只代表前台清理已走完,不代表资源全部移除。重复归档只报告当前事实,不重放清理。
146
+ 检查后通过显式的精确 owner 资源操作进行安全清理;不隐含后台重试或更广泛的删除
147
+ 权限。两条归档路径都保留 Task 历史与恢复信息。已归档的 Task 不能重开。
148
+
149
+ `yui task archive-preflight <task> (--integrated|--abandon) [--force] [--json]`
150
+ 一次读取归档条件、交付覆盖与各精确 owner 的清理检查。归档前后都可用,获授权的
151
+ Task Leader reader 也可读取。这里的 `--force` 仅选择要检查的行为,不会归档、
152
+ 准备工作区、刷新 Git index、停止 Session、获取维护锁、抓取远端或保存清理计划。
153
+
154
+ 每项阻断/未知检查都有资源、原因码、预期/观察值、来源引用及既有检查/处置命令。
155
+ 无权访问的 Task 外路径会脱敏。报告区分 Candidate 工作区缺失、工作区身份/元数据/
156
+ 路径变化、冻结 commit 缺失、HEAD 变化、脏 worktree、Git 注册缺失或锁定、结果未集成、
157
+ 交付未覆盖、owner 未结算和执行未知。状态检查禁用可选 index 写入及 filesystem-monitor
158
+ 钩子;若已跟踪文件的属性选择了配置中的 clean/process filter(包括已初始化的 submodule),则返回
159
+ `git-status-requires-filter` 未知诊断,不执行程序,也不绕过规范化猜测干净/脏状态。
160
+ 历史 Candidate 路径保持不可变。路径差异即使
161
+ 符合早期布局迁移的形状,也不单独证明安全迁址;没有确切映射时只报告差异并保留资源,
162
+ 不会改写历史或放宽 commit/owner 保护。
163
+
164
+ 预检是观察,不是删除凭据。清理会重新读取同一组检查,Git 删除时再验证身份和脏状态。
165
+ Task-main clone 在子工作区清理前存在关联 Git 注册是正常现象,但移除 clone 前它们必须
166
+ 已释放。归档会保留失败 Integration 工作区中新出现的脏文件;独立的显式 Integration
167
+ 清理命令保留既有的可丢弃冲突现场合同。force 清理完成只表示这次前台尝试结束,不表示
168
+ 全部资源已释放;当前保留引用、精确物理运行时证据与历史诊断仍是不同事实。
80
169
 
81
170
  清理前用每个命令的 `--help` 查看它确切的权限和选项;阅读一份生命周期文档不授权
82
171
  一次外部写入。