@zq-silk/yui 1.0.0-alpha.1 → 1.0.1
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.
- package/README.md +3 -3
- package/dist/commands/taskCommands.js +2 -3
- package/dist/executor/fileRoleLaunchPlanner.js +12 -3
- package/dist/runtime/agentHost.js +5 -0
- package/dist/runtime/sessionTitle.js +15 -0
- package/dist/runtime/structuredProviderHost.js +46 -6
- package/dist/storage/baselineSchema.js +1 -1
- package/dist/storage/currentTaskStore.js +1 -1
- package/dist/storage/recordValidation.js +1 -1
- package/dist/storage/sqliteSchema.js +1 -1
- package/dist/storage/storageSchema.js +1 -1
- package/dist/storage/upgrade/upgradeOrchestrator.js +4 -5
- package/docs/managed-turn-and-session-runtime.md +9 -2
- package/docs/managed-turn-and-session-runtime.zh-CN.md +7 -2
- package/docs/release-workflow.md +20 -38
- package/docs/release-workflow.zh-CN.md +16 -28
- package/docs/sqlite-control-plane-design.md +5 -5
- package/docs/sqlite-control-plane-design.zh-CN.md +4 -5
- package/docs/storage-baseline.md +54 -137
- package/docs/storage-baseline.zh-CN.md +32 -99
- package/docs/testing/verification-levels.md +12 -18
- package/docs/testing/verification-levels.zh-CN.md +11 -14
- package/i18n/README.zh-CN.md +2 -3
- package/package.json +1 -1
- package/skills/yui-operator/SKILL.md +35 -15
package/README.md
CHANGED
|
@@ -34,9 +34,9 @@ not from terminal windows you juggle or details you have to remember.
|
|
|
34
34
|
- **Isolated by default** — repository work happens in managed Git worktrees;
|
|
35
35
|
the stable checkout stays read-only.
|
|
36
36
|
|
|
37
|
-
> **Status:** 1.0.0
|
|
38
|
-
> support only declared minor upgrades within one storage major.
|
|
39
|
-
>
|
|
37
|
+
> **Status:** 1.0.0, with a clean storage 1.0 baseline. Default updates
|
|
38
|
+
> support only declared minor upgrades within one storage major. Homes with
|
|
39
|
+
> any other storage identity are rejected without mutation.
|
|
40
40
|
|
|
41
41
|
[Quick start](#quick-start) · [Working through conversation](#working-through-conversation) · [Architecture](#architecture) · [Design principles](#design-principles)
|
|
42
42
|
|
|
@@ -827,9 +827,8 @@ function createTaskCommand(args, store, options) {
|
|
|
827
827
|
return output(`Created Draft task ${created.task.id}: ${created.task.title}\n`
|
|
828
828
|
+ `Assigned role: ${created.leader.name}\n`
|
|
829
829
|
+ `Type: ${created.task.type ?? "unspecified"}\n`
|
|
830
|
-
+
|
|
831
|
-
|
|
832
|
-
: "Execution: no Project delivery evidence required\n"), {
|
|
830
|
+
+ "Status: Draft; discussion and development have not started\n"
|
|
831
|
+
+ "Next: explicitly submit with intent discuss or develop when the Task should start\n", {
|
|
833
832
|
task: created.task,
|
|
834
833
|
leader: created.leader
|
|
835
834
|
});
|
|
@@ -17,7 +17,7 @@ import { managedRuntimeAdmission } from "../runtime/agentDriver.js";
|
|
|
17
17
|
import { builtinAgentEndpointImplementation, validateAgentEndpointImplementation } from "../runtime/agentEndpointIdentity.js";
|
|
18
18
|
import { builtinAgentDriverRegistry, builtinDriverIdForAdapter } from "../runtime/builtinAgentDrivers.js";
|
|
19
19
|
import { assertProviderConversationReplaceable } from "../runtime/providerRuntimeIdentity.js";
|
|
20
|
-
import { resolveTaskRoleSessionTitle } from "../runtime/sessionTitle.js";
|
|
20
|
+
import { operatorSessionTitle, resolveTaskRoleSessionTitle } from "../runtime/sessionTitle.js";
|
|
21
21
|
import { parseTaskRuntimeIsolationDescriptor, taskRuntimeIsolationEnvironment } from "../runtime/taskRuntimeIsolation.js";
|
|
22
22
|
import { planningRuntimeCwd } from "../storage/homeLayout.js";
|
|
23
23
|
import { resolveAgentAdapter } from "./agentAdapter.js";
|
|
@@ -33,6 +33,7 @@ export class FileRoleLaunchPlanner {
|
|
|
33
33
|
#agentEnvironment;
|
|
34
34
|
#nativeAgentEnvironment;
|
|
35
35
|
#createNativeSessionId;
|
|
36
|
+
#now;
|
|
36
37
|
#cliPath;
|
|
37
38
|
#inspectWorkspacePhysicalState;
|
|
38
39
|
#entryPoint;
|
|
@@ -51,6 +52,7 @@ export class FileRoleLaunchPlanner {
|
|
|
51
52
|
this.#agentEnvironment = this.#selectConfiguredAgentEnvironment(sourceEnvironment);
|
|
52
53
|
this.#nativeAgentEnvironment = this.#selectConfiguredNativeEnvironment(sourceEnvironment);
|
|
53
54
|
this.#createNativeSessionId = options.createNativeSessionId ?? randomUUID;
|
|
55
|
+
this.#now = options.now ?? (() => new Date());
|
|
54
56
|
this.#inspectWorkspacePhysicalState = options.inspectWorkspacePhysicalState
|
|
55
57
|
?? inspectWorkspacePhysicalState;
|
|
56
58
|
this.#cliPath = canonicalPath(options.cliPath
|
|
@@ -259,7 +261,9 @@ export class FileRoleLaunchPlanner {
|
|
|
259
261
|
if (input.mode === "new" && sessionSet?.providerBinding != null) {
|
|
260
262
|
assertProviderConversationReplaceable(sessionSet.providerBinding);
|
|
261
263
|
}
|
|
262
|
-
return this.#compile(role, input, { scope: "global" },
|
|
264
|
+
return this.#compile(role, input, { scope: "global" }, input.mode === "new" && role.name === "operator"
|
|
265
|
+
? operatorSessionTitle(this.#now(), this.store.getConfig().timeZone)
|
|
266
|
+
: undefined, input.mode === "resume" && compatibleExisting ? existing.nativeSessionId : undefined, undefined, effective, { purpose: "execution" });
|
|
263
267
|
}
|
|
264
268
|
#compile(role, input, owner, sessionTitle, knownNativeSessionId, workspaceOverride, effective, sessionPolicy) {
|
|
265
269
|
const launchRole = effectiveRoleForLaunch(role, effective);
|
|
@@ -389,11 +393,16 @@ export class FileRoleLaunchPlanner {
|
|
|
389
393
|
const effectiveConfig = withNativeProjectDirectories(roleConfig, effective.executionEnvironment === undefined
|
|
390
394
|
? nativeAdditionalDirectories(effective.workspace, agentWorkspace)
|
|
391
395
|
: []);
|
|
396
|
+
const postCreateOperatorTitle = owner.scope === "global"
|
|
397
|
+
&& role.name === "operator"
|
|
398
|
+
&& sessionTitle !== undefined;
|
|
392
399
|
const compileInput = {
|
|
393
400
|
agent,
|
|
394
401
|
config: effectiveConfig,
|
|
395
402
|
workspace: agentWorkspace,
|
|
396
|
-
...(sessionTitle === undefined
|
|
403
|
+
...(sessionTitle === undefined || postCreateOperatorTitle
|
|
404
|
+
? {}
|
|
405
|
+
: { sessionTitle }),
|
|
397
406
|
...sessionContext
|
|
398
407
|
};
|
|
399
408
|
if (input.mode === "resume"
|
|
@@ -328,7 +328,12 @@ export async function runAgentHost(input) {
|
|
|
328
328
|
kind: "restore",
|
|
329
329
|
mode: "resume",
|
|
330
330
|
nativeSessionId: disconnectedSession.nativeSessionId,
|
|
331
|
+
// The dated Operator title is a one-shot effect of creating the
|
|
332
|
+
// Conversation. Reattaching this client must not replay metadata whose
|
|
333
|
+
// earlier outcome may be unknown.
|
|
331
334
|
...(previousControl.sessionTitle === undefined
|
|
335
|
+
|| (currentPayload.environment.YUI_SESSION_SCOPE === "global"
|
|
336
|
+
&& currentPayload.environment.YUI_ROLE === "operator")
|
|
332
337
|
? {}
|
|
333
338
|
: { sessionTitle: previousControl.sessionTitle }),
|
|
334
339
|
codexThread: disconnectedSession.configuration.threadOptions,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolveTimeZone } from "../config/timeZone.js";
|
|
1
2
|
const TITLE_SEPARATOR = " · ";
|
|
2
3
|
export const MAX_SESSION_TITLE_LENGTH = 80;
|
|
3
4
|
const TASK_TITLE_MAX_LENGTH = 20;
|
|
@@ -22,6 +23,20 @@ export function resolveTaskRoleSessionTitle(existingTitle, task, roleName) {
|
|
|
22
23
|
}
|
|
23
24
|
return taskRoleSessionTitle(task, roleName);
|
|
24
25
|
}
|
|
26
|
+
export function operatorSessionTitle(now, configuredTimeZone) {
|
|
27
|
+
if (!(now instanceof Date) || !Number.isFinite(now.getTime())) {
|
|
28
|
+
throw new TypeError("Operator session title date is invalid.");
|
|
29
|
+
}
|
|
30
|
+
const parts = Object.fromEntries(new Intl.DateTimeFormat("en-CA", {
|
|
31
|
+
timeZone: resolveTimeZone(configuredTimeZone),
|
|
32
|
+
month: "2-digit",
|
|
33
|
+
day: "2-digit"
|
|
34
|
+
}).formatToParts(now).map(({ type, value }) => [type, value]));
|
|
35
|
+
if (parts.month === undefined || parts.day === undefined) {
|
|
36
|
+
throw new TypeError("Operator session title date is unavailable.");
|
|
37
|
+
}
|
|
38
|
+
return `Yui${TITLE_SEPARATOR}Operator${TITLE_SEPARATOR}${parts.month}${parts.day}`;
|
|
39
|
+
}
|
|
25
40
|
function displayTitle(value, maxLength) {
|
|
26
41
|
if (value.length <= maxLength)
|
|
27
42
|
return value;
|
|
@@ -68,10 +68,21 @@ export async function startStructuredProviderSession(payload, input = {}) {
|
|
|
68
68
|
...(input.onDiagnostic === undefined ? {} : { onDiagnostic: input.onDiagnostic }),
|
|
69
69
|
mirror
|
|
70
70
|
});
|
|
71
|
+
if (isPostCreateOperatorTitle(payload)) {
|
|
72
|
+
input.onDiagnostic?.({
|
|
73
|
+
nativeSessionId: session.nativeSessionId,
|
|
74
|
+
failure: {
|
|
75
|
+
detail: "This Agent protocol does not support setting a native Session title.",
|
|
76
|
+
phase: "session-start",
|
|
77
|
+
inputDisposition: "not-accepted",
|
|
78
|
+
sessionDisposition: "recoverable"
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
71
82
|
return Object.freeze({ session });
|
|
72
83
|
}
|
|
73
84
|
if (control.adapterId === "codex") {
|
|
74
|
-
const opened = await CodexStructuredProviderSession.open(child, exit, processInstanceId, payload, control, input.onStarted, input.onTerminal, input.onGoal, input.onInput, input.onActivity, mirror);
|
|
85
|
+
const opened = await CodexStructuredProviderSession.open(child, exit, processInstanceId, payload, control, input.onStarted, input.onTerminal, input.onGoal, input.onInput, input.onActivity, input.onDiagnostic, mirror);
|
|
75
86
|
return Object.freeze({
|
|
76
87
|
session: opened.session,
|
|
77
88
|
...(opened.recoveredTerminal === undefined
|
|
@@ -81,6 +92,17 @@ export async function startStructuredProviderSession(payload, input = {}) {
|
|
|
81
92
|
});
|
|
82
93
|
}
|
|
83
94
|
const session = await ClaudeStructuredProviderSession.open(child, exit, processInstanceId, control, input.onAccepted, input.onTerminal, input.onGoal, input.onActivity, input.onDiagnostic, mirror);
|
|
95
|
+
if (isPostCreateOperatorTitle(payload)) {
|
|
96
|
+
input.onDiagnostic?.({
|
|
97
|
+
nativeSessionId: session.nativeSessionId,
|
|
98
|
+
failure: {
|
|
99
|
+
detail: "This Agent provider does not support renaming a Session after creation.",
|
|
100
|
+
phase: "session-start",
|
|
101
|
+
inputDisposition: "not-accepted",
|
|
102
|
+
sessionDisposition: "recoverable"
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
84
106
|
return Object.freeze({ session });
|
|
85
107
|
}
|
|
86
108
|
catch (error) {
|
|
@@ -88,6 +110,12 @@ export async function startStructuredProviderSession(payload, input = {}) {
|
|
|
88
110
|
throw error;
|
|
89
111
|
}
|
|
90
112
|
}
|
|
113
|
+
function isPostCreateOperatorTitle(payload) {
|
|
114
|
+
return payload.providerControl?.sessionTitle !== undefined
|
|
115
|
+
&& payload.providerControl.mode === "new"
|
|
116
|
+
&& payload.environment.YUI_SESSION_SCOPE === "global"
|
|
117
|
+
&& payload.environment.YUI_ROLE === "operator";
|
|
118
|
+
}
|
|
91
119
|
/**
|
|
92
120
|
* Open an uninitialized, transparent connection for a native TUI. The TUI
|
|
93
121
|
* owns its requests; Yui observes only its exact startup response.
|
|
@@ -351,7 +379,7 @@ class CodexStructuredProviderSession {
|
|
|
351
379
|
this.mirror = mirror;
|
|
352
380
|
this.nativeAccountHome = nativeAccountHome;
|
|
353
381
|
}
|
|
354
|
-
static async open(child, exit, processInstanceId, payload, control, onStarted, onTerminal, onGoal, onInput, onActivity, mirror) {
|
|
382
|
+
static async open(child, exit, processInstanceId, payload, control, onStarted, onTerminal, onGoal, onInput, onActivity, onDiagnostic, mirror) {
|
|
355
383
|
const channel = await CodexProxyWebSocketChannel.connect(child, mirror);
|
|
356
384
|
const openingMessages = [];
|
|
357
385
|
const stopOpeningBuffer = channel.onMessage((message) => openingMessages.push(message));
|
|
@@ -385,10 +413,22 @@ class CodexStructuredProviderSession {
|
|
|
385
413
|
}
|
|
386
414
|
}
|
|
387
415
|
if (control.sessionTitle !== undefined) {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
416
|
+
try {
|
|
417
|
+
await runtime.setConversationName({
|
|
418
|
+
conversationId,
|
|
419
|
+
name: control.sessionTitle
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
catch (error) {
|
|
423
|
+
onDiagnostic?.({
|
|
424
|
+
nativeSessionId: conversationId,
|
|
425
|
+
failure: providerDeliveryFailureFrom(error, {
|
|
426
|
+
phase: "session-start",
|
|
427
|
+
inputDisposition: "not-accepted",
|
|
428
|
+
sessionDisposition: "recoverable"
|
|
429
|
+
})
|
|
430
|
+
});
|
|
431
|
+
}
|
|
392
432
|
}
|
|
393
433
|
const session = new CodexStructuredProviderSession(child, exit, processInstanceId, conversationId, runtime, onStarted, onTerminal, onGoal, onInput, onActivity, mirror, optionalId(initialized.codexHome));
|
|
394
434
|
session.#activeTurnId = resumedActiveTurnId;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Current Home schema. Fresh initialization executes this once
|
|
1
|
+
/** Current Home schema. Fresh initialization executes this once. */
|
|
2
2
|
export const BASELINE_SCHEMA_SQL = String.raw `CREATE TABLE storage_schema (
|
|
3
3
|
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
4
4
|
format TEXT NOT NULL,
|
|
@@ -11,7 +11,7 @@ export function initializeCurrentTaskStore(home) {
|
|
|
11
11
|
}
|
|
12
12
|
return openCurrentTaskStore(home);
|
|
13
13
|
}
|
|
14
|
-
/** Open only the current SQLite contract.
|
|
14
|
+
/** Open only the current SQLite contract. Unsupported Homes are never normalized. */
|
|
15
15
|
export function openCurrentTaskStore(home) {
|
|
16
16
|
const schema = inspectStorageSchema(home);
|
|
17
17
|
if (schema.status !== "current") {
|
|
@@ -28,7 +28,7 @@ import { requireKnownFields } from "../domain/validation.js";
|
|
|
28
28
|
const check = (validate) => record => { validate(record); };
|
|
29
29
|
/** One current domain contract for saves, reads and explicit Home diagnostics.
|
|
30
30
|
* Protocol-specific metadata/outbox/telemetry have their own readers. This is
|
|
31
|
-
* validation only:
|
|
31
|
+
* validation only: unsupported storage formats are rejected without mutation. */
|
|
32
32
|
const validators = {
|
|
33
33
|
task_records: check(validateTask),
|
|
34
34
|
work_items: check(validateWorkItem),
|
|
@@ -114,7 +114,7 @@ export function applySqliteMinorUpgrades(db) {
|
|
|
114
114
|
const before = inspectSqliteSchema(db);
|
|
115
115
|
const plan = storageMinorUpgradePlan(before.currentVersion);
|
|
116
116
|
if (plan === null)
|
|
117
|
-
throw new SqliteSchemaError("cross-major or unknown upgrades
|
|
117
|
+
throw new SqliteSchemaError("cross-major or unknown storage upgrades are unsupported.");
|
|
118
118
|
for (const step of plan) {
|
|
119
119
|
const state = inspectSqliteSchema(db);
|
|
120
120
|
if (state.currentVersion !== step.fromVersion || state.currentChecksum !== step.sourceChecksum) {
|
|
@@ -87,7 +87,7 @@ export function inspectStorageSchema(rootDir) {
|
|
|
87
87
|
database.close();
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
|
-
/** Require the current storage contract without normalizing
|
|
90
|
+
/** Require the current storage contract without normalizing unsupported data. */
|
|
91
91
|
export function requireCurrentStorageSchema(rootDir) {
|
|
92
92
|
const state = inspectStorageSchema(rootDir);
|
|
93
93
|
switch (state.status) {
|
|
@@ -11,9 +11,9 @@ import { CURRENT_STORAGE_VERSION, MIN_SUPPORTED_STORAGE_VERSION } from "../stora
|
|
|
11
11
|
/**
|
|
12
12
|
* Upgrade only recognized minor versions within the current Home major.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
* admit exactly {@link CURRENT_STORAGE_VERSION}; no
|
|
16
|
-
* dual read path enters runtime code. Execute mode is an offline primitive:
|
|
14
|
+
* Declared source versions are readable only here. Ordinary stores still
|
|
15
|
+
* admit exactly {@link CURRENT_STORAGE_VERSION}; no alternate-shape normalizer
|
|
16
|
+
* or dual read path enters runtime code. Execute mode is an offline primitive:
|
|
17
17
|
* its caller must own the maintenance fence and keep the Controller quiesced
|
|
18
18
|
* for the whole backup, migration, and validation interval.
|
|
19
19
|
*/
|
|
@@ -259,8 +259,7 @@ function unsupportedClassification(state) {
|
|
|
259
259
|
+ `migration version ${MIN_SUPPORTED_STORAGE_VERSION}.`;
|
|
260
260
|
const action = future
|
|
261
261
|
? "Use a newer Yui release."
|
|
262
|
-
: "Preserve this Home
|
|
263
|
-
+ "or use the independent explicit converter for a different storage major.";
|
|
262
|
+
: "Preserve this Home unchanged and let an Agent or Operator decide its disposition.";
|
|
264
263
|
return {
|
|
265
264
|
classification: {
|
|
266
265
|
verdict: "NEEDS_NEW_VERSION",
|
|
@@ -11,6 +11,13 @@ notifications cannot restart an explicitly stopped Session; normal Host detach
|
|
|
11
11
|
preserves an active Session and remains reconnectable. A switch after a partial
|
|
12
12
|
failure still settles the retained input before selecting a new conversation.
|
|
13
13
|
|
|
14
|
+
A newly created global Operator conversation requests the native title
|
|
15
|
+
`Yui · Operator · MMdd`, using Yui's configured time zone. The request is made
|
|
16
|
+
only after the provider returns the exact new conversation identity; restore
|
|
17
|
+
and reconnect paths never replay it. Providers without a post-create rename
|
|
18
|
+
capability keep the usable Session and expose a diagnostic instead of treating
|
|
19
|
+
metadata failure as Session-creation failure.
|
|
20
|
+
|
|
14
21
|
## Authority
|
|
15
22
|
|
|
16
23
|
Task, WorkItem, Message, Decision, Artifact and Project Knowledge preserve
|
|
@@ -69,8 +76,8 @@ drifted. An explicit ordinary retry creates a new Run and Snapshot from current
|
|
|
69
76
|
authorized facts, without reconstructing the old snapshot; Review and synthesis
|
|
70
77
|
reuse still require exact frozen evidence. Subsequent observed/steered input may
|
|
71
78
|
omit its own Snapshot because it does not establish a new Assignment.
|
|
72
|
-
Storage uses the 1.0 baseline
|
|
73
|
-
|
|
79
|
+
Storage uses the 1.0 baseline. Missing optional execution evidence remains a
|
|
80
|
+
run-scoped condition and does not become a Home-wide blocker.
|
|
74
81
|
|
|
75
82
|
Operational failures are scoped to their owner, not treated as proof that the
|
|
76
83
|
whole Controller must stop. Optional resource reaping and continuation metadata
|
|
@@ -8,6 +8,11 @@ Provider binding,再结算执行占用。Global 停止证据保存为仅记录
|
|
|
8
8
|
不触发新的原生输入。待投递通知不能重启已明确停止的 Session;普通 Host 脱离仍
|
|
9
9
|
保留 active Session,可正常重连。部分切换失败后,仍须先结算旧输入再选择新会话。
|
|
10
10
|
|
|
11
|
+
新建 global Operator 对话会按 Yui 当前配置时区请求原生标题
|
|
12
|
+
`Yui · Operator · MMdd`。只有 Provider 返回新对话的确切身份后才执行该请求;
|
|
13
|
+
恢复与重连路径不会重放。若 Provider 不支持创建后改名,已创建的 Session 仍保持
|
|
14
|
+
可用,并留下诊断,而不会把元数据失败冒充为 Session 创建失败。
|
|
15
|
+
|
|
11
16
|
## 权威
|
|
12
17
|
|
|
13
18
|
Task、WorkItem、Message、Decision、Artifact 和 Project Knowledge 保存持久工作。
|
|
@@ -55,8 +60,8 @@ Leader/Operator 查看、结算失败或显式废弃,无关工作继续推
|
|
|
55
60
|
确切冻结上下文在证据缺失、漂移时局部失败。显式普通重试根据当前授权事实创建
|
|
56
61
|
新的 Run 和 Snapshot,不补造旧快照;Review/结果汇总的确切复用仍需冻结证据。
|
|
57
62
|
后续原生输入或 steer 可以没有独立 Snapshot,因为它们不建立新的 Assignment。
|
|
58
|
-
存储采用 1.0
|
|
59
|
-
整个 Home
|
|
63
|
+
存储采用 1.0 基线;可选执行证据缺失保持为 Run 局部状态,不扩大为
|
|
64
|
+
整个 Home 的阻塞。
|
|
60
65
|
|
|
61
66
|
运行异常按所属对象限制影响,不等同于整个 Controller 必须停摆。可选的资源回收
|
|
62
67
|
和 continuation 元数据检查失败会报告诊断,不阻断正常调度;Provider 重试准入
|
package/docs/release-workflow.md
CHANGED
|
@@ -27,63 +27,45 @@ system sits behind `ReleaseWorkflowPorts`
|
|
|
27
27
|
external ports exercise recovery without real GitHub, npm, git, Controller,
|
|
28
28
|
or model effects.
|
|
29
29
|
|
|
30
|
-
##
|
|
30
|
+
## Stable 1.0 baseline and release evidence
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
Each alpha version has a new immutable package/tag and its own verified
|
|
37
|
-
converter attachments. Continue using npm `next`; never replace an existing tag
|
|
38
|
-
or overwrite a previously published package or attachment.
|
|
39
|
-
|
|
40
|
-
0.16.2 remains the frozen historical bridge. The 1.0.0-alpha runtime starts the
|
|
41
|
-
distinct storage **1.0** baseline and carries no old migration chain or
|
|
42
|
-
conversion tool. Package 1.0.0 will reuse the final verified prerelease storage
|
|
43
|
-
contract without another reset.
|
|
32
|
+
Package 1.0.0 defines the storage **1.0** contract directly. The runtime and
|
|
33
|
+
current source carry no historical migration chain, old-format reader,
|
|
34
|
+
conversion tool, fixture or compatibility test. A fresh Home initializes the
|
|
35
|
+
current schema; any unsupported storage identity is rejected without mutation.
|
|
44
36
|
|
|
45
37
|
Storage versions have two levels. Default updates may advance only contiguous
|
|
46
38
|
minor versions within the same major; pinning a package does not authorize a
|
|
47
39
|
cross-major conversion. Current Yui-owned envelopes and protocols start at 1,
|
|
48
40
|
without resetting business revisions, epochs or audit evidence.
|
|
49
|
-
Any persistent change
|
|
50
|
-
|
|
41
|
+
Any future persistent change requires an explicit new minor transition;
|
|
42
|
+
published schema definitions must not be silently replaced.
|
|
51
43
|
Current bounded automatic recovery, lock waiting, transactions, replay
|
|
52
44
|
protection and valid exact-identity caches remain normal runtime behavior.
|
|
53
45
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
already-published Release is an error, not permission to replace release evidence.
|
|
67
|
-
If this job fails after npm publication, resume only this job with the same
|
|
68
|
-
retained artifacts rather than republishing or rebuilding the package.
|
|
69
|
-
The runtime tarball must contain neither tools/ nor dist/storage/migrations/.
|
|
46
|
+
Stable releases use npm `latest`; prereleases use `next`, never the stable
|
|
47
|
+
default. The release workflow builds one runtime archive, verifies it across
|
|
48
|
+
supported Node versions, publishes that exact archive to npm, then creates the
|
|
49
|
+
matching GitHub Release. Every release carries the runtime archive, checksum and
|
|
50
|
+
provenance. A stable tag becomes GitHub latest; a prerelease does not.
|
|
51
|
+
|
|
52
|
+
The GitHub Release job uploads only missing assets to a draft, downloads and
|
|
53
|
+
compares every asset against the tested artifact, and never overwrites a
|
|
54
|
+
published asset. A retry accepts only byte-identical existing evidence. If npm
|
|
55
|
+
has already published and the Release job fails, rerun that failed job with the
|
|
56
|
+
retained artifact rather than rebuilding or republishing the package. The
|
|
57
|
+
runtime tarball must contain neither tools/ nor historical storage migrations.
|
|
70
58
|
|
|
71
59
|
Use `yui update --version <exact-version>` for an exact published package.
|
|
72
60
|
Staged metadata must match the requested version, and target-owned storage
|
|
73
61
|
preflight runs before activation and again under the maintenance fence.
|
|
74
|
-
An unsupported Home remains unchanged
|
|
75
|
-
than replacing the global CLI first. Current update/activation children must
|
|
62
|
+
An unsupported Home remains unchanged. Current update/activation children must
|
|
76
63
|
explicitly identify their handover-lock owner.
|
|
77
64
|
|
|
78
65
|
Restoration checks the captured executable/argv, package version, Controller
|
|
79
66
|
protocol and both storage-version bounds against status and live identity.
|
|
80
67
|
Missing contract fields are errors, not an older-Controller exception.
|
|
81
68
|
|
|
82
|
-
The converter source, frozen endpoint fixture and converter-specific tests are
|
|
83
|
-
release-only deliverables for the alpha series. Remove them from the 1.0.0 development line
|
|
84
|
-
only after the final corrected alpha release attachments and checksums are durably available
|
|
85
|
-
and verified. Do not delete the only conversion path before publication.
|
|
86
|
-
|
|
87
69
|
## Authorization model
|
|
88
70
|
|
|
89
71
|
Every (re)submission of a step passes `checkGrant(grant, request, now)`
|
|
@@ -20,48 +20,36 @@ Agent 选择一个预先声明的计划,设施从持久状态驱动该计划
|
|
|
20
20
|
(`src/release/releaseWorkflowPorts.ts`)之后。可用临时 SQLite 和确定性的外部端口测试
|
|
21
21
|
恢复逻辑,无需真实 GitHub、npm、git、Controller 或模型效果。
|
|
22
22
|
|
|
23
|
-
##
|
|
23
|
+
## 稳定的 1.0 基线与发布证据
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
独立转换器附件,继续发布到 npm `next`,不覆盖已发布版本、标签或附件。
|
|
29
|
-
|
|
30
|
-
0.16.2 保留为冻结历史桥接版。1.0.0-alpha 运行包启用独立的存储 **1.0**,
|
|
31
|
-
不携带旧迁移链或一次性转换工具;之后的 1.0.0 复用最终已验证的预发布存储契约,
|
|
32
|
-
不再重置。
|
|
25
|
+
1.0.0 软件包直接定义存储 **1.0** 契约。运行包和当前源码不携带任何历史
|
|
26
|
+
迁移链、旧格式读取器、转换工具、样本或兼容测试。新 Home 直接初始化当前
|
|
27
|
+
结构;任何不受支持的存储身份都会在不修改 Home 的前提下被拒绝。
|
|
33
28
|
|
|
34
29
|
存储采用主版本、小版本两级编号,默认更新只允许同主版本内连续的小版本升级。
|
|
35
30
|
指定软件版本不代表授权跨存储主版本。当前 Yui 自有格式和协议从 1 开始,
|
|
36
31
|
但不重置业务 revision、epoch 或审计证据。
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
后续如需改变持久化契约,必须声明新的小版本迁移,不能静默改写已发布基线。
|
|
33
|
+
有界自动恢复、锁等待、事务、重放保护和精确身份匹配的有效缓存
|
|
39
34
|
都是当前运行能力,不作为历史兼容删除。
|
|
40
35
|
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
正式版使用 npm `latest`,预发布版使用 `next`,不能覆盖默认稳定版本。
|
|
37
|
+
发布流水线只构建一个运行包,在受支持 Node 版本上验证后,将同一产物发布到
|
|
38
|
+
npm,并创建对应 GitHub Release。每个 Release 都包含运行包、校验和与来源记录;
|
|
39
|
+
正式 tag 成为 GitHub latest,预发布 tag 不会。
|
|
43
40
|
|
|
44
41
|
恢复 Controller 时,status 和 live identity 都必须匹配此前捕获的执行文件、
|
|
45
42
|
参数、软件版本、Controller 协议和存储版本上下界。缺少字段直接报错,
|
|
46
43
|
不再为较早的 Controller 放宽校验。
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
alpha 专用 `baseline-release` 在 npm 发布成功后向草稿上传缺少的附件,不覆盖
|
|
53
|
-
已有文件;逐个下载并与经过测试的产物比较后,才公开预发布 Release。
|
|
54
|
-
重试只接受字节一致的已有附件;字节不同或已公开 Release 缺少附件都明确失败,
|
|
55
|
-
不自动覆盖发布证据。若 npm 已发布而此步骤失败,只用同一批保留产物重跑该
|
|
56
|
-
job,不重新构建或再次发布 npm 包。
|
|
57
|
-
|
|
58
|
-
转换器源码、冻结终点样本及专用测试只服务于 alpha 系列的独立交付。
|
|
59
|
-
必须先确认最终修正版 alpha 的长期发布附件和校验和可取得且验证通过,才能在 1.0.0
|
|
60
|
-
开发线上移除它们;不能在发布前删掉唯一转换入口。
|
|
45
|
+
GitHub Release job 只向草稿上传缺少的附件,逐个下载并与测试产物比较,
|
|
46
|
+
不覆盖已经公开的资产。重试只接受字节一致的已有证据。若 npm 已发布而
|
|
47
|
+
Release job 失败,只用保留的同一产物重跑失败 job,不重新构建或再次发布。
|
|
48
|
+
运行 tarball 不得包含 tools/ 或历史存储迁移。
|
|
61
49
|
|
|
62
50
|
`yui update --version <exact-version>` 选择精确发布包,实际暂存版本必须匹配。
|
|
63
|
-
激活前及维护锁内分别执行目标包的存储预检。不支持的 Home
|
|
64
|
-
|
|
51
|
+
激活前及维护锁内分别执行目标包的存储预检。不支持的 Home 保持不变。
|
|
52
|
+
当前交接子进程必须显式提供锁持有者身份。
|
|
65
53
|
|
|
66
54
|
## 授权模型
|
|
67
55
|
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
Yui has one authoritative product Store: `YUI_HOME/yui.db`, in WAL mode.
|
|
6
6
|
`storage_schema` contains its single **major.minor** version and schema
|
|
7
|
-
checksum.
|
|
7
|
+
checksum. Package 1.0.0 uses the clean storage **1.0** baseline established and
|
|
8
|
+
verified by its prereleases.
|
|
8
9
|
|
|
9
10
|
## Authority
|
|
10
11
|
|
|
@@ -55,12 +56,12 @@ native evidence settles one. WorkItem and Task acceptance remain Agent-owned.
|
|
|
55
56
|
Version APIs expose `"1.0"` strings, not floats. Default `upgrade` / `update`
|
|
56
57
|
supports only a known contiguous minor path within the same storage major.
|
|
57
58
|
The initial baseline has no such steps. Cross-major and old integer formats
|
|
58
|
-
|
|
59
|
+
are unsupported; they never enter a runtime fallback or heuristic repair path.
|
|
59
60
|
The updater preflights the exact staged package before activation, then rechecks
|
|
60
61
|
under its maintenance fence. Unknown ownership remains a blocker.
|
|
61
62
|
|
|
62
|
-
See [Storage baseline 1.0](./storage-baseline.md) for
|
|
63
|
-
|
|
63
|
+
See [Storage baseline 1.0](./storage-baseline.md) for current admission,
|
|
64
|
+
backup/rollback, artifact boundaries and cold startup procedure.
|
|
64
65
|
|
|
65
66
|
## Unified Home layout
|
|
66
67
|
|
|
@@ -69,4 +70,3 @@ Self-managed data stays under one canonical Home: Task worktrees under
|
|
|
69
70
|
`workspaces/global`, runtime data under `runtime`, and backups under `backups`.
|
|
70
71
|
Explicit external Project inputs keep their external-resource semantics.
|
|
71
72
|
Only deliberately short IPC socket paths may live outside Home.
|
|
72
|
-
The converter does not relocate workspaces or rewrite their Git identities.
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
# SQLite 控制面存储
|
|
4
4
|
|
|
5
5
|
Yui 唯一的权威产品 Store 是 WAL 模式的 `YUI_HOME/yui.db`。
|
|
6
|
-
`storage_schema` 单行记录唯一的**主版本.小版本**与 Schema
|
|
7
|
-
1.0.0
|
|
6
|
+
`storage_schema` 单行记录唯一的**主版本.小版本**与 Schema 摘要。
|
|
7
|
+
1.0.0 使用已经过预发布验证的纯净存储基线 **1.0**。
|
|
8
8
|
|
|
9
9
|
## 权威
|
|
10
10
|
|
|
@@ -42,10 +42,10 @@ AgentRun 记录显式执行请求、可见输入和原始结果,不记录隐
|
|
|
42
42
|
|
|
43
43
|
版本 API 返回 `"1.0"` 字符串,不用浮点数。默认 `upgrade/update`
|
|
44
44
|
只接受同一存储主版本内完整且连续的小版本路径;初始基线尚无升级步骤。
|
|
45
|
-
|
|
45
|
+
跨主版本和旧整数格式不受支持,运行包没有回退或启发式修复路径。
|
|
46
46
|
updater 先检查精确暂存包,再在维护锁内重查;未知所有权始终阻塞。
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
当前格式准入、备份恢复、产物边界和冷启动流程见
|
|
49
49
|
[存储基线 1.0](./storage-baseline.zh-CN.md)。
|
|
50
50
|
|
|
51
51
|
## Home 布局
|
|
@@ -54,4 +54,3 @@ updater 先检查精确暂存包,再在维护锁内重查;未知所有权始
|
|
|
54
54
|
`workspaces/tasks/<task>/<owner>/<project>`,Global scratch 在
|
|
55
55
|
`workspaces/global`,运行数据在 `runtime`,备份在 `backups`。
|
|
56
56
|
显式外部 Project 保留外部资源语义;只有受限长度的 IPC socket 可位于 Home 外。
|
|
57
|
-
一次性转换不搬迁工作区,也不改写 Git 身份。
|
package/docs/storage-baseline.md
CHANGED
|
@@ -1,139 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Yui 1.0.0-alpha is the clean runtime baseline. Package version `1.0.0-alpha`, Home
|
|
4
|
-
storage version `1.0`, record envelope version `1`, and Controller protocol `1`
|
|
5
|
-
have different responsibilities. The later 1.0.0 package reuses the final
|
|
6
|
-
verified prerelease storage contract; it must not reset it again. Persistent
|
|
7
|
-
changes after the first alpha publication require explicit minor transitions.
|
|
8
|
-
|
|
9
|
-
## Current runtime
|
|
10
|
-
|
|
11
|
-
- `storage_schema` contains one authoritative identity: format, major, minor,
|
|
12
|
-
schema checksum and creation time. JSON APIs expose storage versions as
|
|
13
|
-
canonical strings such as `"1.0"`, not floating-point numbers.
|
|
14
|
-
- New Homes execute the complete current DDL once. They do not replay the old
|
|
15
|
-
v1..v37 ledger. Ordinary reads validate the current identity, physical schema
|
|
16
|
-
and typed records; they never normalize data.
|
|
17
|
-
- Explicit `upgrade` / `update` can apply only a complete, contiguous **minor**
|
|
18
|
-
path within one major. The initial 1.0 baseline has no minor steps.
|
|
19
|
-
Cross-major, downgrade, unknown and old integer formats fail before activation.
|
|
20
|
-
An exact package selector is not permission to cross a storage major.
|
|
21
|
-
- Yui-owned record envelopes start at 1. Host control uses the distinct
|
|
22
|
-
`yui-agent-host-control/v1` identity, so it cannot accidentally adopt an old
|
|
23
|
-
`yui-agent-host/v1` producer. Context/Run/Host-event/Driver contracts already at
|
|
24
|
-
v1 remain there. External Provider protocols and package versions are unchanged.
|
|
25
|
-
- Business revisions, authority epochs, IDs, event sequences, native data and
|
|
26
|
-
immutable Context resources are not schema versions. Never reset them.
|
|
27
|
-
- `storage_migration_archive` is opaque audit evidence, not an executable
|
|
28
|
-
compatibility reader. Old numbers and original bytes in audit remain intact.
|
|
29
|
-
- Candidates have one current authority: the owning WorkItem's candidate array.
|
|
30
|
-
The baseline does not create the unused `work_item_candidates` or
|
|
31
|
-
`coordination_locks` tables, or the obsolete `idx_input_open` index.
|
|
32
|
-
|
|
33
|
-
The runtime tarball contains neither historical migration modules nor the
|
|
34
|
-
standalone converter. Source-level history and previous published packages
|
|
35
|
-
remain available for explicit diagnosis, not automatic runtime fallback.
|
|
36
|
-
|
|
37
|
-
## One-time conversion from 0.16.2
|
|
38
|
-
|
|
39
|
-
The independent `yui-baseline-cutover` archive accepts only the exact frozen
|
|
40
|
-
0.16.2 schema and its complete v37 ledger. Older Homes must first use 0.16.2.
|
|
41
|
-
Admission is based on this exact storage contract, not an installed package
|
|
42
|
-
version: an already-valid v37 Home does not need a cosmetic rewrite.
|
|
43
|
-
It never runs the old migration chain itself.
|
|
44
|
-
|
|
45
|
-
Use the corrected converter attached to `1.0.0-alpha.1`. The initial alpha
|
|
46
|
-
converter rejected equivalent indentation in `home_meta`. The corrected tool
|
|
47
|
-
allows only that table's per-line indentation differences, archives the old
|
|
48
|
-
DDL and recreates the canonical target table without changing its rows.
|
|
49
|
-
Columns, constraints, all other objects and all ledger entries still match
|
|
50
|
-
exactly. The published runtime storage 1.0 definition is unchanged.
|
|
51
|
-
|
|
52
|
-
The v37 → 1.0 transition preserves Runs with missing optional Snapshot
|
|
53
|
-
references, including their original references and results. A retained record
|
|
54
|
-
need not be ready to execute: missing evidence must not block Home conversion.
|
|
55
|
-
The Leader/Operator can inspect and retire the affected Run; an explicit ordinary
|
|
56
|
-
retry creates a new Run and Snapshot from current authorized facts without
|
|
57
|
-
rewriting the old evidence. Exact Review/synthesis reuse still requires its
|
|
58
|
-
frozen evidence. Unknown formats, structural corruption and unsettled external
|
|
59
|
-
effects remain separate conversion blockers.
|
|
60
|
-
|
|
61
|
-
1. Using 0.16.2, settle active Runs, Jobs, claimed notifications, in-flight
|
|
62
|
-
retries and unconfirmed effects. Preserve queued intent rather than marking
|
|
63
|
-
it completed. Stop managed Sessions and the Controller. `session stop --all`
|
|
64
|
-
refuses busy Sessions; it is not authority to force-stop or discard work.
|
|
65
|
-
2. Stage the published 1.0.0-alpha.1 package in a separate installation prefix, with
|
|
66
|
-
its native dependencies installed. Do not overwrite the global CLI or try to
|
|
67
|
-
run the new Controller against the old Home.
|
|
68
|
-
3. Verify the converter archive checksum, unpack it, then use its entrypoint.
|
|
69
|
-
The examples below use **placeholders**, not a production Home:
|
|
1
|
+
<p align="right"><strong>English</strong> | <a href="./storage-baseline.zh-CN.md">简体中文</a></p>
|
|
70
2
|
|
|
71
|
-
|
|
72
|
-
node /absolute/converter/cli.mjs \
|
|
73
|
-
--home /absolute/home --runtime /absolute/staged/package
|
|
74
|
-
|
|
75
|
-
node /absolute/converter/cli.mjs \
|
|
76
|
-
--home /absolute/home --runtime /absolute/staged/package \
|
|
77
|
-
--apply --backup-dir /absolute/new-backup-directory
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
`--runtime` names the package directory containing `package.json`, `dist/` and
|
|
81
|
-
available dependencies, not its `bin/yui` entrypoint. The default invocation is
|
|
82
|
-
read-only. `--apply` requires a new backup directory outside Home, under an
|
|
83
|
-
existing canonical parent. Run from an external Operator shell, not a managed
|
|
84
|
-
Task or a Session that is itself being converted.
|
|
85
|
-
|
|
86
|
-
The tool refuses active durable execution, pending outbox operations, active
|
|
87
|
-
Session bindings, recorded live processes, observable processes referencing
|
|
88
|
-
this Home/database, pending native Inbox files and unfinished Controller
|
|
89
|
-
handover/discovery. Unknown identity for a recorded owner remains a blocker;
|
|
90
|
-
unrelated user processes are not adopted or terminated. Stop unmanaged writers
|
|
91
|
-
and external workspace editors too; a file copy is not a filesystem snapshot.
|
|
92
|
-
The maintenance fence and SQL write transaction protect the conversion.
|
|
93
|
-
|
|
94
|
-
Before mutation, the tool copies Home and creates a self-contained SQLite
|
|
95
|
-
backup with checksum. It converts only named Yui envelopes and active typed
|
|
96
|
-
verification plans, preserving each changed payload and the original ledger in
|
|
97
|
-
audit. User text, native payloads, frozen Context bytes, Git data, dirty files,
|
|
98
|
-
IDs, counters and Task outcomes are preserved.
|
|
99
|
-
Before dropping the two unused source tables, every original row is retained
|
|
100
|
-
under `baseline-v37/retired-table/<table>` in the audit archive. Their payloads
|
|
101
|
-
are opaque evidence, not active records to normalize. The receipt reports
|
|
102
|
-
`retiredRows` separately from changed current records.
|
|
103
|
-
|
|
104
|
-
Old `active-release.json` and `runtime-identity.json` are archived in
|
|
105
|
-
`retired-runtime/`, not relabelled as observations of the new runtime. The tool
|
|
106
|
-
also verifies and converts the typed isolation owner markers at the declared
|
|
107
|
-
runtime inventory paths, retaining their originals and recomputing only the
|
|
108
|
-
format-dependent fingerprint. Resource paths, namespace and port allocations
|
|
109
|
-
do not change. Unknown markers or links remain blockers. The tool
|
|
110
|
-
does not resume old Hosts, update the global installation, start a Controller,
|
|
111
|
-
or submit model input. After a successful conversion, use the staged 1.0.0-alpha.1 CLI
|
|
112
|
-
to install the exact package and start only the new runtime. Start new managed
|
|
113
|
-
Sessions through the ordinary explicit lifecycle; history is not live authority.
|
|
114
|
-
|
|
115
|
-
## Evidence and recovery
|
|
116
|
-
|
|
117
|
-
Success is `outcome: converted`, target `1.0`, with the exact backup path.
|
|
118
|
-
Repeating against a valid current Home returns `already-current` without
|
|
119
|
-
creating another backup or rewriting records.
|
|
120
|
-
|
|
121
|
-
- `backup/home/` preserves the Home tree; `backup/yui.db` is the consistent
|
|
122
|
-
standalone database snapshot; `receipt.json` identifies source, target,
|
|
123
|
-
checksum and completed conversion. `retired-runtime/` preserves old bindings.
|
|
124
|
-
- A validation failure rolls back the SQL transaction and restores runtime
|
|
125
|
-
bindings moved by that attempt. If restoration cannot be proven, the error
|
|
126
|
-
names the retained files; keep Home stopped.
|
|
127
|
-
- A crash or receipt-write failure is not proof that storage stayed old.
|
|
128
|
-
Inspect the actual format and backup before choosing recovery. There is no
|
|
129
|
-
automatic repair worker or speculative replay.
|
|
130
|
-
- To roll back, stop all new writers, preserve the failed/new Home separately,
|
|
131
|
-
and restore the old Home tree plus the standalone `yui.db` at the **same**
|
|
132
|
-
original Home path, without mixing in newer WAL/SHM files. Use only 0.16.2.
|
|
133
|
-
Review the converter-owned lock in the snapshot by exact process identity.
|
|
134
|
-
- After new business writes, restoring the old backup loses those writes.
|
|
135
|
-
Recovery then needs an explicit disposition; never restore automatically.
|
|
3
|
+
# Storage baseline 1.0
|
|
136
4
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
5
|
+
Yui 1.0.0 starts from one clean persistent contract. The package version,
|
|
6
|
+
storage schema, record envelopes and Controller protocol are separate
|
|
7
|
+
identities; none is inferred from another.
|
|
8
|
+
|
|
9
|
+
## Current contract
|
|
10
|
+
|
|
11
|
+
- `storage_schema` identifies the authoritative storage **major.minor** and the
|
|
12
|
+
exact physical-schema checksum.
|
|
13
|
+
- A fresh Home creates the complete current DDL directly. Ordinary reads accept
|
|
14
|
+
only the current identity and never normalize records.
|
|
15
|
+
- Default `upgrade` and `update` may follow only a complete, declared,
|
|
16
|
+
same-major minor path. The initial 1.0 baseline has no migration steps.
|
|
17
|
+
- Cross-major, downgrade, unknown and undeclared identities are rejected before
|
|
18
|
+
activation and leave the Home unchanged.
|
|
19
|
+
- Current Yui-owned envelopes and protocols begin at their own version 1.
|
|
20
|
+
Business IDs, revisions, epochs, event counters, Context digests and external
|
|
21
|
+
provider protocols are independent and are never reset by storage numbering.
|
|
22
|
+
- `storage_migration_archive` is opaque audit evidence for declared current
|
|
23
|
+
transitions. It is not a reader, scheduler or repair mechanism.
|
|
24
|
+
- The runtime package and current source contain only the current contract and
|
|
25
|
+
its declared same-major minor transition mechanism.
|
|
26
|
+
|
|
27
|
+
Future persistent changes must add an explicit storage minor version, source
|
|
28
|
+
and target checksums, a deterministic transactional transform and focused
|
|
29
|
+
regression evidence. A published baseline is immutable.
|
|
30
|
+
|
|
31
|
+
## Failure and recovery
|
|
32
|
+
|
|
33
|
+
Update preflight validates the staged package and target Home before activation,
|
|
34
|
+
then repeats the check under the maintenance fence. A migration failure rolls
|
|
35
|
+
back its transaction and does not advance the storage identity.
|
|
36
|
+
|
|
37
|
+
Invalid, malformed or unsupported state is preserved and diagnosed. Yui does
|
|
38
|
+
not guess repairs, discard evidence or silently initialize over it. The Agent,
|
|
39
|
+
Leader or Operator can inspect the exact failure and choose a bounded action
|
|
40
|
+
such as retrying, abandoning an affected execution, restoring a verified
|
|
41
|
+
backup, or initializing a separate fresh Home.
|
|
42
|
+
|
|
43
|
+
Before an authorized persistent update, make a restorable backup of the Home
|
|
44
|
+
while the Controller is stopped or held by the maintenance fence. Restore the
|
|
45
|
+
database and its matching WAL/SHM set as one unit. Do not combine files from
|
|
46
|
+
different observations.
|
|
47
|
+
|
|
48
|
+
Real Home operations, publication and shared-infrastructure validation require
|
|
49
|
+
explicit user authority. Development and CI use isolated disposable fixtures.
|
|
50
|
+
|
|
51
|
+
## Release artifact boundary
|
|
52
|
+
|
|
53
|
+
The published runtime tarball is the only executable release artifact. It must
|
|
54
|
+
exclude repository tests, development tools and non-current storage material.
|
|
55
|
+
Every GitHub Release carries the exact tested runtime archive, checksum and
|
|
56
|
+
provenance used for npm publication.
|
|
@@ -1,111 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Yui 1.0.0-alpha 是纯净运行基线。软件版本 `1.0.0-alpha`、Home 存储版本 `1.0`、
|
|
4
|
-
记录格式版本 `1`、Controller 协议版本 `1` 各有职责。后续 `1.0.0` 软件包
|
|
5
|
-
复用最终已验证的预发布存储契约,不再重置。首个 alpha 发布后如需修改
|
|
6
|
-
持久化契约,必须声明显式的小版本迁移。
|
|
7
|
-
|
|
8
|
-
## 当前运行包
|
|
9
|
-
|
|
10
|
-
- `storage_schema` 的单行记录是唯一存储版本权威,包含格式、主版本、小版本、
|
|
11
|
-
Schema 摘要与创建时间。JSON 中版本采用 `"1.0"` 字符串,不用浮点数。
|
|
12
|
-
- 新 Home 一次创建最终 DDL,不执行旧 v1→v37 链。普通读取只校验当前身份、
|
|
13
|
-
物理结构和类型化记录,不转换数据。
|
|
14
|
-
- 显式 `upgrade/update` 默认也只允许同主版本内连续的小版本升级。
|
|
15
|
-
首个 `1.0` 尚无小版本升级步骤。跨主版本、降级、未知格式、旧整数版本
|
|
16
|
-
都会在激活前拒绝;指定软件版本不等于授权跨存储主版本。
|
|
17
|
-
- Yui 自有记录格式从 1 开始。Host 控制采用独立的
|
|
18
|
-
`yui-agent-host-control/v1`,不会误认历史 `yui-agent-host/v1`。
|
|
19
|
-
原本为 v1 的 Context、Run、Host 事件和 Driver 协议保持 v1。
|
|
20
|
-
外部 Provider 协议和依赖版本不重置。
|
|
21
|
-
- 业务 revision、授权 epoch、ID、事件序号、原生数据和冻结 Context
|
|
22
|
-
不是 Schema 版本,不能重置。
|
|
23
|
-
- `storage_migration_archive` 只保留不透明审计证据,不解释旧格式来执行工作。
|
|
24
|
-
其中的旧版本数字与原始字节保持不变。
|
|
25
|
-
- Candidate 的当前权威只有所属 WorkItem 的候选数组。基线不再创建无用的
|
|
26
|
-
`work_item_candidates`、`coordination_locks` 表或废弃的 `idx_input_open` 索引。
|
|
27
|
-
|
|
28
|
-
运行 tarball 不包含历史迁移模块,也不包含独立转换器。旧 tag 和发布包用于
|
|
29
|
-
显式诊断,不构成运行时回退。
|
|
1
|
+
<p align="right"><a href="./storage-baseline.md">English</a> | <strong>简体中文</strong></p>
|
|
30
2
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
独立 `yui-baseline-cutover` 压缩包只接受精确的 0.16.2 结构和完整 v37 账本。
|
|
34
|
-
更旧 Home 必须先通过 0.16.2 升级;转换器本身不执行整条旧迁移链。
|
|
35
|
-
准入依据是精确的存储结构与账本,不是当前安装的软件版本号;
|
|
36
|
-
已经满足该 v37 契约的 Home 不需要为了改软件编号而重写数据。
|
|
37
|
-
|
|
38
|
-
使用 `1.0.0-alpha.1` 附带的修正版转换器。初始 alpha 转换器会把 `home_meta`
|
|
39
|
-
的等价缩进误判为不支持;修正版仅允许该表逐行缩进不同,保留原 DDL 并按目标定义
|
|
40
|
-
重建该表,验证所有行不变。字段、约束、其他结构对象和完整账本仍严格匹配。
|
|
41
|
-
已发布的运行时存储 1.0 定义没有改变。
|
|
42
|
-
|
|
43
|
-
v37 → 1.0 转换保留缺少可选 Snapshot 引用的 Run、原始引用和结果。
|
|
44
|
-
记录可以读取不代表它必须能执行:证据缺失不应阻断整个 Home 转换。
|
|
45
|
-
Leader/Operator 可以查看、废弃异常 Run;显式普通重试根据当前授权事实创建
|
|
46
|
-
新的 Run 和 Snapshot,不改写旧证据。Review/结果汇总若要复用确切冻结证据,
|
|
47
|
-
仍需满足该操作的前提。未知格式、结构损坏和未结算外部效果仍是独立的转换阻塞条件。
|
|
48
|
-
|
|
49
|
-
1. 使用 0.16.2 结算活动 Run、Job、已认领通知、在途重试和未知外部效果。
|
|
50
|
-
保留排队意图,不伪造完成。停止受管 Session 和 Controller。
|
|
51
|
-
`session stop --all` 会拒绝忙碌 Session,不是强停或丢弃工作的授权。
|
|
52
|
-
2. 将已发布的 1.0.0-alpha.1 暂存在独立安装前缀中,安装所需原生依赖。
|
|
53
|
-
不先覆盖全局 CLI,不让新 Controller 打开旧 Home。
|
|
54
|
-
3. 核验转换包校验和并解压,调用入口。以下路径均为**占位示例**:
|
|
3
|
+
# 存储基线 1.0
|
|
55
4
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
--home /absolute/home --runtime /absolute/staged/package
|
|
5
|
+
Yui 1.0.0 从唯一、纯净的持久化契约开始。软件包版本、存储结构、记录封装和
|
|
6
|
+
Controller 协议是相互独立的身份,不能从其中一个推断另一个。
|
|
59
7
|
|
|
60
|
-
|
|
61
|
-
--home /absolute/home --runtime /absolute/staged/package \
|
|
62
|
-
--apply --backup-dir /absolute/new-backup-directory
|
|
63
|
-
```
|
|
8
|
+
## 当前契约
|
|
64
9
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
10
|
+
- `storage_schema` 记录权威的存储**主版本.小版本**和精确物理结构校验和。
|
|
11
|
+
- 新 Home 直接创建完整的当前 DDL。普通读取只接受当前身份,不规范化记录。
|
|
12
|
+
- 默认 `upgrade` 和 `update` 只能沿同一主版本内完整、已声明的小版本路径执行;
|
|
13
|
+
初始 1.0 基线没有迁移步骤。
|
|
14
|
+
- 跨主版本、降级、未知或未声明的身份会在激活前被拒绝,并保持 Home 不变。
|
|
15
|
+
- 当前 Yui 自有封装和协议分别从版本 1 开始。业务 ID、revision、epoch、事件计数、
|
|
16
|
+
Context 摘要和外部 Provider 协议相互独立,不随存储编号重置。
|
|
17
|
+
- `storage_migration_archive` 只保存当前已声明迁移的不透明审计证据,不是读取器、
|
|
18
|
+
调度器或修复机制。
|
|
19
|
+
- 运行包和当前源码只包含当前契约及同主版本内已声明的小版本迁移机制。
|
|
69
20
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
Controller 交接或发现记录。登记所有者身份不可验证时仍阻塞;不会接管或
|
|
73
|
-
终止无关用户进程。也应停止非受管写入者及外部工作区编辑器:普通文件复制
|
|
74
|
-
不是文件系统快照。维护锁和 SQL 写事务保护实际转换。
|
|
21
|
+
未来持久化变更必须增加明确的存储小版本、源和目标校验和、确定性的事务转换,
|
|
22
|
+
并提供聚焦的回归证据。已经发布的基线不可改写。
|
|
75
23
|
|
|
76
|
-
|
|
77
|
-
Yui 记录封装及活动类型化验证计划,将每个改写前的原始负载和旧账本保存在审计中。
|
|
78
|
-
用户文本、原生负载、冻结 Context、Git 数据、未提交文件、ID、计数和 Task
|
|
79
|
-
结果保持原样。
|
|
80
|
-
删除两张旧表之前,每一行原始内容都写入审计的
|
|
81
|
-
`baseline-v37/retired-table/<table>` 分类,不把其中的负载当作活动记录规范化。
|
|
82
|
-
回执以 `retiredRows` 单独报告归档行数。
|
|
24
|
+
## 失败与恢复
|
|
83
25
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
不启动 Controller、不提交模型输入。转换成功后,再由暂存的 1.0.0-alpha.1 CLI
|
|
87
|
-
安装精确版本并启动新运行环境;通过正常显式生命周期创建新 Session,
|
|
88
|
-
历史记录不代表活动授权。
|
|
26
|
+
更新预检会在激活前校验暂存包和目标 Home,并在维护锁内再次检查。迁移失败会
|
|
27
|
+
回滚事务,不推进存储身份。
|
|
89
28
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
29
|
+
无效、损坏或不受支持的状态会被保留并给出诊断。Yui 不猜测修复、不丢弃证据,
|
|
30
|
+
也不会在其上静默初始化。Agent、Leader 或 Operator 可以检查精确失败,并选择
|
|
31
|
+
有界操作,例如重试、废弃受影响的执行、恢复已验证备份,或初始化独立的新 Home。
|
|
93
32
|
|
|
94
|
-
|
|
33
|
+
执行已授权的持久化更新前,应在 Controller 停止或由维护锁隔离时制作可恢复的
|
|
34
|
+
Home 备份。数据库及其匹配的 WAL/SHM 必须作为一个整体恢复,不能混用不同观察
|
|
35
|
+
时刻的文件。
|
|
95
36
|
|
|
96
|
-
|
|
97
|
-
|
|
37
|
+
真实 Home 操作、发布和共享基础设施验证需要用户明确授权;开发与 CI 使用隔离的
|
|
38
|
+
一次性样本。
|
|
98
39
|
|
|
99
|
-
|
|
100
|
-
`receipt.json` 记录来源、目标、摘要及转换结果;`retired-runtime/` 保存旧绑定。
|
|
101
|
-
- 校验失败时回滚 SQL,并恢复本次移动的运行绑定。若恢复无法确认,错误会指出
|
|
102
|
-
保留文件;Home 应继续保持停止。
|
|
103
|
-
- 崩溃或回执写入失败不证明数据库仍是旧版。先检查实际格式与备份,再选择恢复;
|
|
104
|
-
没有自动修复 worker 或猜测性重放。
|
|
105
|
-
- 回滚前停止新写入者、另存失败或新 Home,再将旧 Home 树和独立 `yui.db`
|
|
106
|
-
恢复到**原来的同一路径**,不能混入新 WAL/SHM。只使用 0.16.2;
|
|
107
|
-
按精确进程身份检查快照中转换器自己的维护锁。
|
|
108
|
-
- 一旦新版产生业务写入,恢复旧备份会丢失这些新写入,必须明确处理,不能自动恢复。
|
|
40
|
+
## 发布产物边界
|
|
109
41
|
|
|
110
|
-
|
|
111
|
-
|
|
42
|
+
发布的运行 tarball 是唯一可执行发布产物,必须排除仓库测试、开发工具和非当前
|
|
43
|
+
存储材料。每个 GitHub Release 都携带 npm 发布所使用的同一份已测试运行包、
|
|
44
|
+
校验和与来源记录。
|
|
@@ -50,43 +50,37 @@ is required.
|
|
|
50
50
|
## Permanent core smoke
|
|
51
51
|
|
|
52
52
|
`npm test` and `npm run test:core` build the checkout and run the maintained suite.
|
|
53
|
-
The
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
completion boundaries.
|
|
53
|
+
The stable suite owns only current storage 1.0 and future declared minor
|
|
54
|
+
transitions. It contains no historical conversion implementation, fixture or
|
|
55
|
+
compatibility test.
|
|
57
56
|
|
|
58
57
|
Current coverage includes:
|
|
59
58
|
|
|
60
59
|
1. Fresh storage 1.0, exact schema/record validation, no initialization over
|
|
61
60
|
unknown data, and rejection of old integer formats without mutation.
|
|
62
|
-
2.
|
|
63
|
-
envelopes, opaque Context, rollback on invalid input, offline backup and
|
|
64
|
-
repeat-call idempotence. The CLI fixture uses a disposable Home; it never
|
|
65
|
-
converts a real account. The converter is not part of the runtime tarball.
|
|
66
|
-
3. Exact-version staging, mismatched-target refusal, same-major contiguous
|
|
61
|
+
2. Exact-version staging, mismatched-target refusal, same-major contiguous
|
|
67
62
|
minor preflight, explicit maintenance-owner identity across handover, and
|
|
68
63
|
restoration against captured protocol/storage identity rather than omitted fields.
|
|
69
|
-
|
|
64
|
+
3. Durable Task/Message/Decision context, draft activation authority, mailbox
|
|
70
65
|
claims, notification idempotence, Session replacement and exact late results.
|
|
71
|
-
|
|
66
|
+
4. Integration/Job request identity, immutable candidate proofs, conflict
|
|
72
67
|
continuation, Review scope and final acceptance without fabricated delivery.
|
|
73
|
-
|
|
68
|
+
5. Runtime/Host isolation, Provider protocol parsing and bounded retry using
|
|
74
69
|
fake producers, current configuration provenance and native-account boundaries.
|
|
75
|
-
|
|
70
|
+
6. Workspace/GC authority, archive cleanup, resource CAS, telemetry, Web
|
|
76
71
|
projections and authorized release recovery without real external effects.
|
|
77
|
-
|
|
72
|
+
7. Idempotent per-checkout launcher installation, exact argument/Home forwarding,
|
|
78
73
|
refusal to overwrite unrelated files, and rejection of removed global-link
|
|
79
74
|
commands before side effects. Development Home reset retains its independent
|
|
80
75
|
identity checks and backup behavior.
|
|
81
|
-
|
|
76
|
+
8. Failure isolation for optional Controller maintenance, individual retry
|
|
82
77
|
Sessions and Task continuation observation, with scoped errors and no
|
|
83
78
|
fabricated delivery, cancellation or quiescence.
|
|
84
79
|
|
|
85
80
|
Keep the test phase seconds-scale and measure build separately. Use the
|
|
86
81
|
existing assembled-package smoke for actual CLI/Controller/Host/tmux wiring,
|
|
87
|
-
not a second daemon matrix.
|
|
88
|
-
|
|
89
|
-
Real-model or real-Home checks require explicit authorization.
|
|
82
|
+
not a second daemon matrix. Do not reconstruct retired storage paths in the
|
|
83
|
+
stable suite. Real-model or real-Home checks require explicit authorization.
|
|
90
84
|
Current envelope checks reject arbitrary unknown fields, rather than maintaining
|
|
91
85
|
a blacklist of retired field names.
|
|
92
86
|
|
|
@@ -36,31 +36,28 @@ Yui 是一个单用户本地产品。永久验证保护关键的 happy path 和
|
|
|
36
36
|
## 永久 core smoke
|
|
37
37
|
|
|
38
38
|
`npm test` 和 `npm run test:core` 构建当前 checkout 并运行维护中的套件。
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
稳定套件只维护当前存储 1.0 和未来明确声明的小版本迁移,不包含任何历史
|
|
40
|
+
转换实现、样本或兼容测试。
|
|
41
41
|
|
|
42
42
|
当前覆盖包括:
|
|
43
43
|
|
|
44
44
|
1. 新建存储 1.0、精确结构与记录校验、禁止覆盖未知数据库、无修改拒绝旧整数格式。
|
|
45
|
-
2.
|
|
46
|
-
无效输入回滚、离线备份及重复调用幂等。CLI 样本使用临时 Home,不转换真实账号;
|
|
47
|
-
转换器不进入运行 tarball。
|
|
48
|
-
3. 精确版本暂存、目标不匹配拒绝、同主版本连续小版本预检、交接锁显式所有者,
|
|
45
|
+
2. 精确版本暂存、目标不匹配拒绝、同主版本连续小版本预检、交接锁显式所有者,
|
|
49
46
|
以及恢复时核对捕获的协议和存储身份,不接受缺失字段。
|
|
50
|
-
|
|
47
|
+
3. 持久 Task/Message/Decision 上下文、Draft 激活权威、mailbox 认领、
|
|
51
48
|
通知幂等、Session 替换及精确晚到结果。
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
4. Integration/Job 请求身份、冻结候选证据、冲突延续、Review scope 和最终验收。
|
|
50
|
+
5. Runtime/Host 隔离、假生产者的 Provider 协议和有界重试、配置来源与账号边界。
|
|
51
|
+
6. 工作区/GC 权威、归档清理、资源 CAS、telemetry、Web 投影与无真实外部效果的发布恢复。
|
|
52
|
+
7. checkout 隔离启动器的幂等安装、参数与 Home 精确传递、禁止覆盖无关文件,
|
|
56
53
|
以及已移除的全局链接命令在任何副作用前拒绝。开发 Home 重置保留独立的身份检查
|
|
57
54
|
和备份行为。
|
|
58
|
-
|
|
55
|
+
8. Controller 可选维护、各个重试 Session、Task continuation 观察的失败隔离,
|
|
59
56
|
诊断包含所属对象,不伪造投递、取消或静默状态。
|
|
60
57
|
|
|
61
58
|
测试阶段保持秒级,构建单独计时。真实 CLI/Controller/Host/tmux 接线复用现有
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
组装包冒烟,不新增守护进程矩阵;稳定套件不重建任何已退役的存储路径。
|
|
60
|
+
真实模型或真实 Home 检查需要显式授权。
|
|
64
61
|
当前记录按声明的字段集合拒绝未知字段,不维护退役字段名称黑名单。
|
|
65
62
|
|
|
66
63
|
## Skill 与指令变更
|
package/i18n/README.zh-CN.md
CHANGED
|
@@ -30,9 +30,8 @@ Yui 是面向编程 Agent 的本地控制面。你只需用自然语言把目标
|
|
|
30
30
|
Web 仅本地回环,包含只读视图和经认证的用户控制。
|
|
31
31
|
- **默认隔离** —— 仓库改动发生在受管 Git worktree 中,稳定 checkout 保持只读。
|
|
32
32
|
|
|
33
|
-
> **状态:** 1.0.0
|
|
34
|
-
>
|
|
35
|
-
> [一次性转换](../docs/storage-baseline.zh-CN.md)。
|
|
33
|
+
> **状态:** 1.0.0,采用纯净的存储 1.0 基线。默认更新只执行同一存储
|
|
34
|
+
> 主版本内已声明的小版本升级;其他存储身份会在不修改 Home 的前提下被拒绝。
|
|
36
35
|
|
|
37
36
|
[快速开始](#快速开始) · [通过对话管理工作](#通过对话管理工作) · [架构](#架构) · [设计原则](#设计原则)
|
|
38
37
|
|
package/package.json
CHANGED
|
@@ -74,13 +74,30 @@ determine Task identity. They also do not determine WorkItem count. Let
|
|
|
74
74
|
isolated workspaces and Integration handle independent Git changes.
|
|
75
75
|
|
|
76
76
|
Keep the Task title concise and put detailed intent, constraints, and evidence
|
|
77
|
-
in its description or routed Message.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
77
|
+
in its description or routed Message.
|
|
78
|
+
|
|
79
|
+
Treat Task creation and Task submission as separate user-authorized actions.
|
|
80
|
+
When the user asks only to add, create, register, or record a Task, create the
|
|
81
|
+
Draft and write all known requirements into its metadata, then stop. Do not
|
|
82
|
+
submit a `discuss` or `develop` Message, request activation, start a Leader
|
|
83
|
+
Session, or create execution resources. A detailed or immediately actionable
|
|
84
|
+
requirement, or the user's desire for its eventual completion, is not permission
|
|
85
|
+
to start it. Report that the Task is a Draft and has not started, and explain
|
|
86
|
+
that the user can explicitly ask to discuss/plan it or to develop/implement it.
|
|
87
|
+
|
|
88
|
+
Start the corresponding route only when the user's current request contains
|
|
89
|
+
that additional intent: discussion or planning authorizes `discuss`;
|
|
90
|
+
development, implementation, fixing, continuing execution, or immediate
|
|
91
|
+
progress authorizes `develop` or the applicable lifecycle continuation. Do not
|
|
92
|
+
weaken explicit intent merely because the request also says “create a Task.”
|
|
93
|
+
The examples below are separate operations, never an automatic
|
|
94
|
+
create/submit/activate sequence.
|
|
95
|
+
|
|
96
|
+
Discussion does not authorize delivery; follow the Leader's
|
|
97
|
+
[planning and activation boundary](../yui-leader/references/planning.md) before
|
|
98
|
+
activation. Queries, record-only input and discussion do not authorize
|
|
99
|
+
reopening. An explicit request to continue the same completed result can
|
|
100
|
+
authorize the necessary reopening; follow the delivery guidance below.
|
|
84
101
|
|
|
85
102
|
```sh
|
|
86
103
|
yui operator submit "<related request and delta>" --task <task-id> --intent discuss
|
|
@@ -94,14 +111,17 @@ Inspect an existing request before creating another. `task activate <task-id>`
|
|
|
94
111
|
can adopt an eligible request in the foreground; it never activates a Draft
|
|
95
112
|
without a recorded request and environment plan.
|
|
96
113
|
|
|
97
|
-
|
|
98
|
-
text. `discuss` (the default
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
114
|
+
After the user has authorized a submission, choose its intent explicitly; it is
|
|
115
|
+
never inferred by the CLI from the message text. `discuss` (the CLI default when
|
|
116
|
+
`operator submit` is already being invoked) routes the Draft to planning;
|
|
117
|
+
`record` saves the message without waking the Leader; `develop` asks an unplanned
|
|
118
|
+
Draft to activate now, and reports the exact next step when it cannot (already
|
|
119
|
+
planned → request activation explicitly; execution stopped → start it first).
|
|
120
|
+
The CLI default is not permission for the Operator to invoke submission after a
|
|
121
|
+
creation-only request. Pass `--request-id <key>` to make a submission idempotent:
|
|
122
|
+
retrying the same key returns the original message and routing instead of
|
|
123
|
+
creating a duplicate, and the same key with different text is refused as a
|
|
124
|
+
conflict.
|
|
105
125
|
|
|
106
126
|
Resolve all known Projects before repository-backed execution. A stable Project
|
|
107
127
|
checkout is read-only reference state, not the Task base authority. Yui records
|