@zq-silk/yui 0.16.1 → 1.0.0-alpha
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/ARCHITECTURE.md +12 -0
- package/ARCHITECTURE.zh-CN.md +8 -0
- package/README.md +9 -4
- package/dist/agent/agent.js +4 -9
- package/dist/agent/executionComponents.js +4 -4
- package/dist/agent/managedRuntimeEnvironment.js +0 -4
- package/dist/agentRun/agentRun.js +13 -23
- package/dist/artifacts/managedGit.js +3 -56
- package/dist/brief/taskBrief.js +3 -3
- package/dist/cli/agentConfigurationPicker.js +24 -21
- package/dist/cli/commandCatalog.js +18 -10
- package/dist/cli/roleWizard.js +41 -30
- package/dist/cli/updateCommand.js +35 -13
- package/dist/cli/updateOrchestrator.js +73 -44
- package/dist/cli/updatePorts.js +76 -86
- package/dist/cli/upgradeCommand.js +4 -8
- package/dist/cli.js +39 -33
- package/dist/commands/controllerCommands.js +2 -2
- package/dist/commands/executionAuditCommands.js +2 -2
- package/dist/commands/projectCommands.js +1 -1
- package/dist/commands/releaseCommands.js +9 -38
- package/dist/commands/taskCommands.js +91 -81
- package/dist/commands/taskCompletionGate.js +0 -117
- package/dist/commands/taskRoleRuntimeStatus.js +2 -2
- package/dist/commands/taskUpstreamCommands.js +93 -54
- package/dist/context/runContextPack.js +30 -54
- package/dist/context/runInputContract.js +9 -0
- package/dist/context/sessionBootstrapManifest.js +11 -19
- package/dist/controller/agentHostObservation.js +4 -2
- package/dist/controller/agentRuntimeObserver.js +4 -4
- package/dist/controller/clientRuntime.js +19 -44
- package/dist/controller/controller.js +24 -10
- package/dist/controller/fileSchedulerStoreAdapter.js +91 -24
- package/dist/controller/globalInputDelivery.js +31 -8
- package/dist/controller/globalRuntimeAttention.js +34 -0
- package/dist/controller/jobSupervisor.js +3 -3
- package/dist/controller/operatorNotification.js +31 -0
- package/dist/controller/providerRetryAdmission.js +3 -1
- package/dist/controller/providerRetryDelivery.js +136 -119
- package/dist/controller/runtime.js +2 -28
- package/dist/controller/sessionOwnerReconciliation.js +42 -24
- package/dist/controller/structuredProviderObservation.js +28 -1
- package/dist/controller/updateReconciliation.js +72 -20
- package/dist/coordination/workMailbox.js +4 -4
- package/dist/core/controllerIdentity.js +25 -0
- package/dist/core/controllerProcessIdentity.js +2 -2
- package/dist/core/controllerServer.js +4 -2
- package/dist/core/protocol.js +1 -1
- package/dist/doctor/doctor.js +2 -1
- package/dist/domain/validation.js +6 -0
- package/dist/event/taskEvent.js +3 -3
- package/dist/execution/workItemExecution.js +2 -2
- package/dist/executor/agentAdapter.js +28 -96
- package/dist/executor/agentConfigurationCatalog.js +13 -68
- package/dist/executor/agentConfigurationFields.js +120 -0
- package/dist/executor/agentConfigurationProbe.js +55 -80
- package/dist/executor/agentExecutor.js +11 -8
- package/dist/executor/effectiveLaunch.js +3 -3
- package/dist/executor/executorRegistry.js +0 -9
- package/dist/executor/fileRoleLaunchPlanner.js +12 -11
- package/dist/grant/capabilityGrant.js +2 -2
- package/dist/input/inputRequest.js +4 -4
- package/dist/integration/changeSet.js +3 -3
- package/dist/integration/integrationAttempt.js +3 -3
- package/dist/integration/integrationSourceApplication.js +1 -1
- package/dist/interaction/operatorPresentation.js +2 -1
- package/dist/job/durableJob.js +1 -1
- package/dist/job/jobRunner.js +2 -2
- package/dist/message/message.js +8 -6
- package/dist/message/messageContinuation.js +8 -9
- package/dist/milestone/milestone.js +3 -3
- package/dist/observability/executionAudit.js +1 -10
- package/dist/observability/runtimeIdentity.js +0 -23
- package/dist/output/agentConfigurationPresentation.js +4 -2
- package/dist/profile/agentProfile.js +3 -3
- package/dist/release/releaseHandover.js +2 -2
- package/dist/release/releaseIdempotencyStore.js +0 -23
- package/dist/release/releaseWorkflowPorts.js +8 -4
- package/dist/release/runtimeRelease.js +9 -7
- package/dist/repository/gitWorkspace.js +66 -19
- package/dist/repository/project.js +3 -3
- package/dist/repository/taskWorkspacePreparer.js +75 -68
- package/dist/resources/liveReferences.js +1 -1
- package/dist/resources/resourceRegistry.js +90 -44
- package/dist/resources/sqliteResourceRegistry.js +5 -7
- package/dist/review/reviewRound.js +5 -5
- package/dist/role/role.js +7 -8
- package/dist/runtime/acpProtocol.js +2 -3
- package/dist/runtime/acpSession.js +21 -5
- package/dist/runtime/agentDriverObservation.js +1 -1
- package/dist/runtime/agentEndpoint.js +4 -1
- package/dist/runtime/agentHost.js +25 -65
- package/dist/runtime/agentHostCleanup.js +85 -0
- package/dist/runtime/agentHostProtocol.js +3 -3
- package/dist/runtime/builtinAgentDrivers.js +46 -119
- package/dist/runtime/builtinTranscriptObserver.js +10 -6
- package/dist/runtime/codexAppServerRuntime.js +55 -89
- package/dist/runtime/codexInteractiveHost.js +1 -1
- package/dist/runtime/jsonLineChannel.js +35 -7
- package/dist/runtime/launchBroker.js +1 -1
- package/dist/runtime/processExitObservation.js +1 -1
- package/dist/runtime/providerContinuationReconciliationService.js +86 -38
- package/dist/runtime/providerRetry.js +15 -0
- package/dist/runtime/providerRuntimeIdentity.js +3 -3
- package/dist/runtime/providerRuntimeReconciler.js +12 -2
- package/dist/runtime/runtimeCoherence.js +7 -3
- package/dist/runtime/runtimeObservation.js +3 -3
- package/dist/runtime/sessionOwnerIdentity.js +1 -1
- package/dist/runtime/structuredProviderHost.js +106 -81
- package/dist/runtime/taskRuntimeIsolation.js +3 -3
- package/dist/runtime/tmuxAdapters.js +3 -3
- package/dist/scheduler/activeRoleRunDelivery.js +5 -1
- package/dist/scheduler/operatorInputNotificationProcessor.js +7 -17
- package/dist/scheduler/taskWake.js +1 -1
- package/dist/storage/baselineSchema.js +606 -0
- package/dist/storage/homeLayout.js +5 -16
- package/dist/storage/recordValidation.js +16 -4
- package/dist/storage/sqliteSchema.js +106 -1741
- package/dist/storage/sqliteStore.js +16 -14
- package/dist/storage/storageSchema.js +8 -7
- package/dist/storage/storageVersions.js +23 -16
- package/dist/storage/taskStore.js +3 -29
- package/dist/storage/upgrade/upgradeOrchestrator.js +14 -112
- package/dist/task/nextAction.js +33 -23
- package/dist/task/task.js +17 -8
- package/dist/task/taskActivation.js +5 -4
- package/dist/telemetry/sqliteTelemetryStore.js +2 -2
- package/dist/verification/gateArtifact.js +5 -3
- package/dist/verification/verificationPlan.js +6 -7
- package/dist/web/assets/assetManifest.js +2 -0
- package/dist/web/assets/client/app.js +72 -3
- package/dist/web/assets/client/components.js +2 -1
- package/dist/web/assets/client/i18n.js +2 -0
- package/dist/web/assets/client/taskSummary.js +345 -0
- package/dist/web/assets/client/taskSurface.js +44 -26
- package/dist/web/assets/client/view.js +33 -0
- package/dist/web/assets/shell.js +1 -0
- package/dist/web/assets/styles/cards.js +21 -0
- package/dist/web/webServer.js +39 -5
- package/dist/web/webSessions.js +165 -0
- package/dist/web/webSnapshot.js +23 -0
- package/dist/web/webTaskSurface.js +23 -0
- package/dist/workItem/workItem.js +6 -6
- package/dist/workspace/cleanupInspection.js +1 -9
- package/dist/worktree/managedWorkspace.js +3 -3
- package/docs/managed-turn-and-session-runtime.md +50 -7
- package/docs/managed-turn-and-session-runtime.zh-CN.md +36 -5
- package/docs/observability/README.md +47 -0
- package/docs/observability/README.zh-CN.md +37 -0
- package/docs/project-refresh.md +9 -0
- package/docs/project-refresh.zh-CN.md +8 -0
- package/docs/provider-retry.md +35 -0
- package/docs/release-workflow.md +70 -214
- package/docs/release-workflow.zh-CN.md +53 -157
- package/docs/roles-and-configuration.md +30 -0
- package/docs/roles-and-configuration.zh-CN.md +20 -0
- package/docs/sqlite-control-plane-design.md +48 -289
- package/docs/sqlite-control-plane-design.zh-CN.md +37 -53
- package/docs/storage-baseline.md +132 -0
- package/docs/storage-baseline.zh-CN.md +106 -0
- package/docs/task-delivery.md +110 -2
- package/docs/task-delivery.zh-CN.md +82 -2
- package/docs/task-discovery.md +9 -0
- package/docs/task-discovery.zh-CN.md +6 -0
- package/docs/testing/verification-levels.md +42 -164
- package/docs/testing/verification-levels.zh-CN.md +29 -115
- package/i18n/README.zh-CN.md +7 -4
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +11 -0
- package/skills/yui-leader/references/execution.md +22 -0
- package/skills/yui-leader/references/planning.md +6 -2
- package/skills/yui-operator/SKILL.md +45 -13
- package/skills/yui-operator/references/task-delivery.md +99 -0
- package/skills/yui-runtime/SKILL.md +5 -3
- package/skills/yui-runtime/references/publication.md +56 -5
- package/skills/yui-runtime/references/recovery.md +12 -2
- package/dist/runtime/agentHostCompatibility.js +0 -127
- package/dist/storage/migrations/agentFailureContext.js +0 -22
- package/dist/storage/migrations/agentRunContract.js +0 -159
- package/dist/storage/migrations/artifactsToGit.js +0 -338
- package/dist/storage/migrations/collapseWorktreeLayout.js +0 -963
- package/dist/storage/migrations/currentInputContract.js +0 -86
- package/dist/storage/migrations/currentRuntimeContract.js +0 -228
- package/dist/storage/migrations/historicalVerificationPlan.js +0 -35
- package/dist/storage/migrations/integrationContinuation.js +0 -105
- package/dist/storage/migrations/narrowAgentFailureContext.js +0 -65
- package/dist/storage/migrations/notificationOnlyWakes.js +0 -74
- package/dist/storage/migrations/removeRuntimeGeneration.js +0 -207
- package/dist/storage/migrations/submitIntent.js +0 -126
- package/dist/storage/migrations/unifyHomeLayout.js +0 -925
- package/dist/storage/migrations/verificationPlanV1.js +0 -162
- package/dist/storage/migrations/verificationPolicy.js +0 -74
- package/dist/storage/migrations/workItemHistory.js +0 -46
package/ARCHITECTURE.md
CHANGED
|
@@ -67,6 +67,18 @@ AgentHost serializes submission through AgentEndpoint. The Provider binding
|
|
|
67
67
|
records actual acceptance and native correlation. A notification can settle
|
|
68
68
|
on acceptance without requiring a final execution report.
|
|
69
69
|
|
|
70
|
+
Operator attention has a separate, local handoff boundary: one transaction
|
|
71
|
+
saves the exact batch as a Global system Message and consumes only that mailbox
|
|
72
|
+
claim. `queued` (with the Message id) means durable queue ownership, not Provider
|
|
73
|
+
acceptance or Agent processing. Later events form a new batch without repeating
|
|
74
|
+
the handed-off refs. Global Messages alone own subsequent native delivery,
|
|
75
|
+
including rejection, unknown acceptance and Session-target mismatch; none causes
|
|
76
|
+
automatic reissuance under a different key. A pass can mark multiple definitively
|
|
77
|
+
unsent stale-target entries undelivered before reaching successor input, but never
|
|
78
|
+
bypass an uncertain attempt or an interrupt-then reservation. Original Messages
|
|
79
|
+
and source Task/Input/Event records remain inspectable. Notifications ask Agents
|
|
80
|
+
to reread facts; they do not authorize replaying prior operations.
|
|
81
|
+
|
|
70
82
|
Busy with proven non-acceptance preserves the input for a subsequent attempt.
|
|
71
83
|
Transport submission alone does not prove acceptance. Unknown effects remain
|
|
72
84
|
visible and fenced: no blind resend or inferred success. Explicit replacement
|
package/ARCHITECTURE.zh-CN.md
CHANGED
|
@@ -53,6 +53,14 @@ AgentRun 记录一次明确请求的执行,带有冻结的 Context 和生效
|
|
|
53
53
|
mailbox 批次;AgentHost 通过 AgentEndpoint 串行化提交。Provider 绑定记录实际接受和原生
|
|
54
54
|
关联。一条通知可以在接受时结算,而不要求最终执行报告。
|
|
55
55
|
|
|
56
|
+
Operator attention 有独立的本地交接边界:同一事务把精确批次保存为 Global 系统 Message,
|
|
57
|
+
并且只消费该 mailbox claim。`queued`(带 Message id)表示持久队列已接管,不代表 Provider
|
|
58
|
+
接受或 Agent 已处理。后到事件形成新批次,不重复已经交出的 refs。后续原生投递仅由
|
|
59
|
+
Global Message 负责,包括拒绝、接受结果未知和 Session 目标失效;这些结果都不会自动换键
|
|
60
|
+
重发。一轮可将多个已明确未提交且目标失效的条目标为未投递,再处理后继输入,但不能越过
|
|
61
|
+
不确定尝试或 interrupt-then 预约。原始 Message 和来源 Task/Input/Event 仍可查阅。通知
|
|
62
|
+
只要求 Agent 重读事实,不授予重放先前操作的权限。
|
|
63
|
+
|
|
56
64
|
忙碌且已证明未接受会为后续尝试保留输入。仅有传输提交不证明接受。未知效果保持可见且被
|
|
57
65
|
围栏隔离:不盲目重发,也不推断成功。显式替换先解决实际的原生执行,再丢弃其工程占用。
|
|
58
66
|
在一个已认领批次期间到达的输入,留待下一个批次。读取 Context 不消费投递。
|
package/README.md
CHANGED
|
@@ -34,8 +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:**
|
|
38
|
-
>
|
|
37
|
+
> **Status:** 1.0.0-alpha, with a clean storage 1.0 baseline. Default updates
|
|
38
|
+
> support only declared minor upgrades within one storage major. Existing v37
|
|
39
|
+
> Homes require the separate [one-time conversion](docs/storage-baseline.md).
|
|
39
40
|
|
|
40
41
|
[Quick start](#quick-start) · [Working through conversation](#working-through-conversation) · [Architecture](#architecture) · [Design principles](#design-principles)
|
|
41
42
|
|
|
@@ -140,6 +141,9 @@ For a visual overview, run `yui web` in another terminal. The local Web view
|
|
|
140
141
|
shows the same tasks and pending questions and lets you send messages, answer
|
|
141
142
|
questions and explicitly queue, steer or interrupt Task input. These authenticated
|
|
142
143
|
Task controls use the same operations as the CLI; Web is not a separate task system.
|
|
144
|
+
The detail prioritizes user input, native Session activity, Task progress and key
|
|
145
|
+
conclusions; fixed file results and delivery evidence open on demand. See
|
|
146
|
+
[attention and progress](docs/observability/README.md#web-attention-and-progress).
|
|
143
147
|
See [Web permissions](docs/architecture/capabilities-and-resources.md#cli-and-web)
|
|
144
148
|
and [input timing](docs/managed-turn-and-session-runtime.md#input-timing-queue-steer-and-interrupt).
|
|
145
149
|
|
|
@@ -380,8 +384,9 @@ npm users do not need to compile it.
|
|
|
380
384
|
|
|
381
385
|
To exercise your checkout, run `make install-local`, then use the absolute
|
|
382
386
|
`<checkout>/output/dev/bin/yui` launcher. It defaults to an isolated Home under
|
|
383
|
-
that checkout; run its `setup` before stateful use.
|
|
384
|
-
|
|
387
|
+
that checkout; run its `setup` before stateful use. Development tooling does not
|
|
388
|
+
manage global installations; do not use the global `yui` to validate local changes.
|
|
389
|
+
Live-model, paid or shared-resource
|
|
385
390
|
tests require an explicit request for those resources.
|
|
386
391
|
|
|
387
392
|
## Community and support
|
package/dist/agent/agent.js
CHANGED
|
@@ -9,7 +9,7 @@ export function createConfiguredAgent(id, adapterId, command, baseArgs, environm
|
|
|
9
9
|
validateAgentBaseArguments(adapterId, baseArgs);
|
|
10
10
|
const timestamp = now.toISOString();
|
|
11
11
|
return {
|
|
12
|
-
schemaVersion:
|
|
12
|
+
schemaVersion: 1,
|
|
13
13
|
id: normalizedId,
|
|
14
14
|
// An unnamed component resolves from the plan, which for ACP means the
|
|
15
15
|
// unidentified entry rather than a guess at which product is installed.
|
|
@@ -45,18 +45,13 @@ export function resolveAgentEnvironment(agent, processEnvironment = process.env)
|
|
|
45
45
|
}));
|
|
46
46
|
}
|
|
47
47
|
export function validateConfiguredAgent(agent) {
|
|
48
|
-
if (agent.schemaVersion !==
|
|
48
|
+
if (agent.schemaVersion !== 1)
|
|
49
49
|
throw new Error("Agent schema version is invalid.");
|
|
50
50
|
requireSafeIdentity(agent.id, "Agent id");
|
|
51
51
|
if (!isAgentAdapterId(agent.adapterId))
|
|
52
52
|
throw new Error(`Agent adapter is unsupported: ${agent.adapterId}.`);
|
|
53
|
-
//
|
|
54
|
-
// stored
|
|
55
|
-
// absent value here is a corrupt record, not an old one, and resolving it to
|
|
56
|
-
// the plan default would invent a product identity for data that never lost
|
|
57
|
-
// one. That default belongs to the constructor, where an operator naming
|
|
58
|
-
// only a plan is a real and supported request — this validator reads records
|
|
59
|
-
// that were already written, where the same silence means something else.
|
|
53
|
+
// Creation resolves an omitted component before persistence. Reading a
|
|
54
|
+
// stored record must not invent a missing product identity.
|
|
60
55
|
if (agent.component === undefined) {
|
|
61
56
|
throw new Error(`Agent is missing its execution component: ${agent.id}.`);
|
|
62
57
|
}
|
|
@@ -138,10 +138,10 @@ export function displayExecutionComponent(adapterId, componentId) {
|
|
|
138
138
|
/**
|
|
139
139
|
* Resolve the component for a connection plan, given what the caller stated.
|
|
140
140
|
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
* to the
|
|
144
|
-
*
|
|
141
|
+
* Creation may name only a connection plan. Resolve its default before
|
|
142
|
+
* persistence; current stored Agents and bindings require an explicit component.
|
|
143
|
+
* ACP defaults to the unidentified entry, never a product inferred from command,
|
|
144
|
+
* arguments or environment.
|
|
145
145
|
*/
|
|
146
146
|
export function resolveAgentExecutionComponent(adapterId, componentId) {
|
|
147
147
|
if (componentId === undefined)
|
|
@@ -19,10 +19,6 @@ export const YUI_MANAGED_RUNTIME_ENVIRONMENT_NAMES = Object.freeze([
|
|
|
19
19
|
"YUI_RUN_ID",
|
|
20
20
|
"YUI_NATIVE_SESSION_ROOT",
|
|
21
21
|
"YUI_NATIVE_SESSION_ID",
|
|
22
|
-
// Retired: Yui no longer publishes a frozen control-plane descriptor into a
|
|
23
|
-
// managed process. Sessions launched by an earlier release still carry it, so
|
|
24
|
-
// it stays in this sanitize list.
|
|
25
|
-
"YUI_CONTROL_PLANE_DESCRIPTOR",
|
|
26
22
|
"YUI_TASK_RUNTIME_ISOLATION_DESCRIPTOR",
|
|
27
23
|
"YUI_TASK_RUNTIME_SERVICE_NAMESPACE",
|
|
28
24
|
"YUI_SESSION_TITLE",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { validateEffectiveLaunchSnapshot } from "../executor/effectiveLaunch.js";
|
|
2
2
|
import { validateTaskRecordReference } from "../task/taskRecordReference.js";
|
|
3
3
|
import { validateManagedWorkspace } from "../worktree/managedWorkspace.js";
|
|
4
|
-
import {
|
|
4
|
+
import { createRunInputEnvelope, requireRunContextSnapshotRef, validateRunInput } from "../context/runInputContract.js";
|
|
5
5
|
import { providerRetryProjection } from "../runtime/providerRetry.js";
|
|
6
6
|
import { boundedRunFailureDiagnostic, MAX_RUN_FAILURE_DIAGNOSTIC_BYTES, MAX_RUN_RESULT_OUTPUT_BYTES } from "../domain/agentResultTransport.js";
|
|
7
7
|
export { boundedRunFailureDiagnostic, MAX_RUN_FAILURE_DIAGNOSTIC_BYTES, MAX_RUN_RESULT_OUTPUT_BYTES, transportAgentResult } from "../domain/agentResultTransport.js";
|
|
@@ -32,8 +32,11 @@ export function createRun(id, taskId, roleName, mode, input, now, context) {
|
|
|
32
32
|
}
|
|
33
33
|
const timestamp = now.toISOString();
|
|
34
34
|
const normalizedInput = validateRunInput(input);
|
|
35
|
+
const snapshot = requireRunContextSnapshotRef(normalizedInput);
|
|
36
|
+
if (snapshot.taskId !== taskId)
|
|
37
|
+
throw new Error("AgentRun Context Snapshot belongs to another Task.");
|
|
35
38
|
return {
|
|
36
|
-
schemaVersion:
|
|
39
|
+
schemaVersion: 1,
|
|
37
40
|
id: requireSafeIdentity(id, "AgentRun id"),
|
|
38
41
|
taskId: requireSafeIdentity(taskId, "Task id"),
|
|
39
42
|
roleName: requireSafeIdentity(roleName, "Role name"),
|
|
@@ -85,22 +88,6 @@ export function runPurposeAdmitsTaskState(purpose, task) {
|
|
|
85
88
|
? task.status === "draft" || task.status === "active"
|
|
86
89
|
: task.status === "active";
|
|
87
90
|
}
|
|
88
|
-
/** Binds a freshly created, not-yet-persisted Turn to its frozen Context. */
|
|
89
|
-
export function withRunContextSnapshot(run, snapshot, deltaRefIds = []) {
|
|
90
|
-
const initial = run.inputs[0];
|
|
91
|
-
if (run.status !== "active" || initial.input.contextSnapshotRef !== undefined) {
|
|
92
|
-
throw new Error(`Cannot replace the AgentRun Context Snapshot: ${run.id}.`);
|
|
93
|
-
}
|
|
94
|
-
const input = createRunInput({
|
|
95
|
-
...initial.input,
|
|
96
|
-
contextSnapshotRef: snapshot,
|
|
97
|
-
deltaRefIds
|
|
98
|
-
});
|
|
99
|
-
return validateRun(Object.freeze({
|
|
100
|
-
...run,
|
|
101
|
-
inputs: [runInputRecord(input, 1, initial.submittedAt), ...run.inputs.slice(1)]
|
|
102
|
-
}));
|
|
103
|
-
}
|
|
104
91
|
export function appendRunInput(run, input, now) {
|
|
105
92
|
validateRun(run);
|
|
106
93
|
if (run.status !== "active")
|
|
@@ -118,6 +105,7 @@ export function appendRunInput(run, input, now) {
|
|
|
118
105
|
/** Derives Provider-visible identity from the AgentRun, the sole semantic owner. */
|
|
119
106
|
export function runInputEnvelope(run, sequence = 1) {
|
|
120
107
|
validateRun(run);
|
|
108
|
+
requireRunContextSnapshotRef(run.inputs[0].input);
|
|
121
109
|
const record = run.inputs[sequence - 1];
|
|
122
110
|
if (record === undefined)
|
|
123
111
|
throw new Error(`AgentRun input does not exist: ${run.id}/${sequence}.`);
|
|
@@ -144,8 +132,8 @@ export function validateRun(run) {
|
|
|
144
132
|
"createdAt",
|
|
145
133
|
"updatedAt"
|
|
146
134
|
], "AgentRun");
|
|
147
|
-
if (run.schemaVersion !==
|
|
148
|
-
throw new Error("AgentRun must use schemaVersion
|
|
135
|
+
if (run.schemaVersion !== 1)
|
|
136
|
+
throw new Error("AgentRun must use schemaVersion 1.");
|
|
149
137
|
validateTaskRecordReference({ taskId: run.taskId, localId: run.id }, "run");
|
|
150
138
|
requireSafeIdentity(run.roleName, "Role name");
|
|
151
139
|
if (run.mode !== "new" && run.mode !== "resume") {
|
|
@@ -295,6 +283,8 @@ export function validateRun(run) {
|
|
|
295
283
|
throw new Error("Execution AgentRun cannot carry Review effective provenance.");
|
|
296
284
|
}
|
|
297
285
|
for (const record of run.inputs) {
|
|
286
|
+
// Validate readable evidence, not readiness to execute. A missing Snapshot
|
|
287
|
+
// must still allow inspection, failure settlement and explicit retirement.
|
|
298
288
|
createRunInputEnvelope(runEnvelopeContext(run), record.input);
|
|
299
289
|
}
|
|
300
290
|
if (!["active", "completed", "failed"].includes(run.status)) {
|
|
@@ -345,7 +335,7 @@ function finishRun(run, status, output, now, failureReason, provider, systemEvid
|
|
|
345
335
|
...run,
|
|
346
336
|
status,
|
|
347
337
|
result: {
|
|
348
|
-
schemaVersion:
|
|
338
|
+
schemaVersion: 1,
|
|
349
339
|
...(output === undefined ? {} : { output: requireResultText(output, "AgentRun result output") }),
|
|
350
340
|
...(diagnostic === undefined
|
|
351
341
|
? {}
|
|
@@ -362,8 +352,8 @@ function finishRun(run, status, output, now, failureReason, provider, systemEvid
|
|
|
362
352
|
return validateRun(terminal);
|
|
363
353
|
}
|
|
364
354
|
function validateRunResult(result) {
|
|
365
|
-
if (result === undefined || result.schemaVersion !==
|
|
366
|
-
throw new Error("A terminal AgentRun requires AgentRunResult schemaVersion
|
|
355
|
+
if (result === undefined || result.schemaVersion !== 1) {
|
|
356
|
+
throw new Error("A terminal AgentRun requires AgentRunResult schemaVersion 1.");
|
|
367
357
|
}
|
|
368
358
|
rejectUnknownFields(result, [
|
|
369
359
|
"schemaVersion",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { execFile
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
2
|
import { promisify } from "node:util";
|
|
3
3
|
const executeFile = promisify(execFile);
|
|
4
4
|
/**
|
|
@@ -259,8 +259,8 @@ function isExternalProgramConfigKey(key) {
|
|
|
259
259
|
* list of repo-local keys that can execute an external program. Empty means the
|
|
260
260
|
* repository's own config is within the managed boundary.
|
|
261
261
|
*
|
|
262
|
-
* PURE: no I/O. Callers
|
|
263
|
-
*
|
|
262
|
+
* PURE: no I/O. Callers read the config with the managed runner and pass the
|
|
263
|
+
* bytes here, so the security policy lives
|
|
264
264
|
* in exactly one testable place. Reading `--local` deliberately excludes the
|
|
265
265
|
* command-line `-c` hardening flags (which are safe and not persisted) and the
|
|
266
266
|
* null-device'd global/system config; it sees only what is written in the repo.
|
|
@@ -277,56 +277,3 @@ export function externalProgramConfigViolations(localConfigListZ) {
|
|
|
277
277
|
}
|
|
278
278
|
return [...offending].sort();
|
|
279
279
|
}
|
|
280
|
-
/**
|
|
281
|
-
* SYNCHRONOUS managed invocation, used ONLY where an async runner is
|
|
282
|
-
* structurally impossible: a storage `migrateData(db)` step runs inside
|
|
283
|
-
* `db.transaction(...)`, which better-sqlite3 requires to be synchronous, yet
|
|
284
|
-
* the 18->19 migration must build per-Task artifact repositories on disk. This
|
|
285
|
-
* shares the SAME hardening as {@link spawnManagedGit} — identical argument
|
|
286
|
-
* refusal, identical scrubbed environment, identical prepended flags — so the
|
|
287
|
-
* synchronous path never weakens the trust boundary. It is not exported for
|
|
288
|
-
* ordinary runtime use; the async runner remains the only production write path.
|
|
289
|
-
*/
|
|
290
|
-
function spawnManagedGitSync(repoPath, args, options) {
|
|
291
|
-
assertSafeArguments(args);
|
|
292
|
-
const env = managedGitEnvironment();
|
|
293
|
-
if (options?.commitDates !== undefined) {
|
|
294
|
-
// Deterministic history: fixed author/committer dates make a rebuild of the
|
|
295
|
-
// same source data reproduce the same commit ids. This only sets metadata.
|
|
296
|
-
env.GIT_AUTHOR_DATE = options.commitDates.author;
|
|
297
|
-
env.GIT_COMMITTER_DATE = options.commitDates.committer;
|
|
298
|
-
}
|
|
299
|
-
try {
|
|
300
|
-
const stdout = execFileSync("git", [...HARDENING_FLAGS, "-C", repoPath, ...args], {
|
|
301
|
-
encoding: "buffer",
|
|
302
|
-
env,
|
|
303
|
-
maxBuffer: options?.maxBuffer ?? 16 * 1024 * 1024,
|
|
304
|
-
timeout: options?.timeoutMs ?? 30_000,
|
|
305
|
-
windowsHide: true
|
|
306
|
-
});
|
|
307
|
-
return { stdout: stdout, stderr: Buffer.alloc(0) };
|
|
308
|
-
}
|
|
309
|
-
catch (error) {
|
|
310
|
-
throw new ManagedGitError([...args], readErrorStream(error), error);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
/** Synchronous counterpart to {@link managedGit}; returns trimmed UTF-8 stdout. */
|
|
314
|
-
export function managedGitSync(repoPath, args, options) {
|
|
315
|
-
return spawnManagedGitSync(repoPath, args, options).stdout.toString("utf8");
|
|
316
|
-
}
|
|
317
|
-
/** Synchronous counterpart to {@link managedGitBuffer}; returns raw stdout bytes. */
|
|
318
|
-
export function managedGitSyncBuffer(repoPath, args, options) {
|
|
319
|
-
return spawnManagedGitSync(repoPath, args, options).stdout;
|
|
320
|
-
}
|
|
321
|
-
/** Synchronous counterpart to {@link managedGitSucceeds}; never throws on non-zero exit. */
|
|
322
|
-
export function managedGitSyncSucceeds(repoPath, args, options) {
|
|
323
|
-
try {
|
|
324
|
-
spawnManagedGitSync(repoPath, args, options);
|
|
325
|
-
return true;
|
|
326
|
-
}
|
|
327
|
-
catch (error) {
|
|
328
|
-
if (error instanceof ManagedGitError)
|
|
329
|
-
return false;
|
|
330
|
-
throw error;
|
|
331
|
-
}
|
|
332
|
-
}
|
package/dist/brief/taskBrief.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export function createTaskBrief(input, now) {
|
|
2
2
|
return {
|
|
3
|
-
schemaVersion:
|
|
3
|
+
schemaVersion: 1,
|
|
4
4
|
objective: requireText(input.objective, "Task objective"),
|
|
5
5
|
boundaries: normalizeBoundaries(input.boundaries),
|
|
6
6
|
technicalApproach: optionalText(input.technicalApproach, "Task technical approach"),
|
|
@@ -22,8 +22,8 @@ export function updateTaskBrief(brief, patch, updatedBy, now) {
|
|
|
22
22
|
}, now);
|
|
23
23
|
}
|
|
24
24
|
export function validateTaskBrief(brief) {
|
|
25
|
-
if (brief.schemaVersion !==
|
|
26
|
-
throw new Error("Task Brief requires schemaVersion
|
|
25
|
+
if (brief.schemaVersion !== 1) {
|
|
26
|
+
throw new Error("Task Brief requires schemaVersion 1.");
|
|
27
27
|
}
|
|
28
28
|
if (!Array.isArray(brief.boundaries) || typeof brief.technicalApproach !== "string"
|
|
29
29
|
|| typeof brief.updatedAt !== "string" || !Number.isFinite(Date.parse(brief.updatedAt))) {
|
|
@@ -30,12 +30,11 @@ export async function selectAgentEffort(resolved, io, input) {
|
|
|
30
30
|
}
|
|
31
31
|
/** Select provider-native permission settings in the adapter's canonical shape. */
|
|
32
32
|
export async function selectAgentPermission(resolved, io, current) {
|
|
33
|
+
renderResolutionNotice(resolved, io);
|
|
33
34
|
const strategyField = configurationField(resolved.catalog, "permission.strategy");
|
|
34
|
-
|
|
35
|
-
{
|
|
36
|
-
|
|
37
|
-
{ value: "configured", label: "configured" }
|
|
38
|
-
], current.strategy);
|
|
35
|
+
if (strategyField?.reason !== undefined)
|
|
36
|
+
io.write(`${strategyField.reason}\n`);
|
|
37
|
+
const strategyChoices = uniqueChoices(strategyField?.available === false ? [] : strategyField?.choices ?? [], current.strategy);
|
|
39
38
|
const strategy = await choose("Select permission strategy", strategyChoices.map(({ value, label, description }) => ({
|
|
40
39
|
value,
|
|
41
40
|
label,
|
|
@@ -67,6 +66,10 @@ export async function selectAgentPermission(resolved, io, current) {
|
|
|
67
66
|
delete permission.approval;
|
|
68
67
|
else
|
|
69
68
|
permission.approval = approval.value;
|
|
69
|
+
if (permission.sandbox === undefined && permission.approval === undefined) {
|
|
70
|
+
io.write("Configured permission requires an explicit native option; configuration unchanged.\n");
|
|
71
|
+
return { kind: "cancelled" };
|
|
72
|
+
}
|
|
70
73
|
return {
|
|
71
74
|
kind: "selected",
|
|
72
75
|
permission: permission
|
|
@@ -98,6 +101,11 @@ export async function selectAgentPermission(resolved, io, current) {
|
|
|
98
101
|
delete permission.mode;
|
|
99
102
|
else
|
|
100
103
|
permission.mode = mode.value;
|
|
104
|
+
if (permission.mode === undefined && permission.allowedTools === undefined
|
|
105
|
+
&& permission.disallowedTools === undefined) {
|
|
106
|
+
io.write("Configured permission requires an explicit native option; configuration unchanged.\n");
|
|
107
|
+
return { kind: "cancelled" };
|
|
108
|
+
}
|
|
101
109
|
return {
|
|
102
110
|
kind: "selected",
|
|
103
111
|
permission: permission
|
|
@@ -107,12 +115,13 @@ export function renderAgentConfigurationResolutionNotice(resolved) {
|
|
|
107
115
|
const lines = [];
|
|
108
116
|
if (resolved.source === "cache") {
|
|
109
117
|
lines.push((resolved.failure === undefined ? "" : `! Runtime capability request failed (${resolved.failure.message}). `)
|
|
110
|
-
+ `Showing cached options from ${resolved.fetchedAt ?? "an earlier request"}; they may be stale.`);
|
|
118
|
+
+ `Showing identity-matched cached options from ${resolved.fetchedAt ?? "an earlier request"}; they may be stale.`);
|
|
111
119
|
}
|
|
112
120
|
else if (resolved.source === "fallback") {
|
|
113
121
|
lines.push(`! Runtime capability request failed (${resolved.failure?.message ?? "unknown failure"}). `
|
|
114
|
-
+ "No matching cache is available; only
|
|
122
|
+
+ "No matching cache is available; only declared static adapter contracts and explicit custom values can be offered.");
|
|
115
123
|
}
|
|
124
|
+
lines.push(`Metadata source: ${resolved.source}; last probe attempted ${resolved.attemptedAt}${resolved.fetchedAt === undefined ? "" : `; fetched ${resolved.fetchedAt}`}. Source describes the query, not native confirmation of every field.`);
|
|
116
125
|
lines.push(...resolved.catalog.warnings.map((warning) => `! Agent catalog warning: ${warning}`));
|
|
117
126
|
return lines.length === 0 ? "" : `${lines.join("\n")}\n`;
|
|
118
127
|
}
|
|
@@ -215,29 +224,23 @@ function observedEfforts(models) {
|
|
|
215
224
|
}
|
|
216
225
|
async function selectPermissionField(resolved, io, key, current, defaultValue) {
|
|
217
226
|
const field = configurationField(resolved.catalog, key);
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
const choices = uniqueChoices(field === undefined
|
|
224
|
-
? fallback.map((value) => ({ value, label: value }))
|
|
225
|
-
: field.choices, current);
|
|
226
|
-
const includeOmit = defaultValue === OMIT || current !== undefined;
|
|
227
|
+
if (field?.reason !== undefined)
|
|
228
|
+
io.write(`${key}: ${field.reason}\n`);
|
|
229
|
+
if (field === undefined)
|
|
230
|
+
io.write(`${key}: no catalog field was reported; no choices inferred.\n`);
|
|
231
|
+
const choices = uniqueChoices(field?.available === false ? [] : field?.choices ?? [], current);
|
|
227
232
|
const pickerChoices = [
|
|
228
|
-
|
|
229
|
-
? [{ value: OMIT, label: "Omit", detail: "Do not pass this provider option" }]
|
|
230
|
-
: []),
|
|
233
|
+
{ value: OMIT, label: "Omit", detail: "Do not pass this provider option" },
|
|
231
234
|
...choices.map(({ value, label, description }) => ({
|
|
232
235
|
value,
|
|
233
236
|
label,
|
|
234
237
|
detail: description ?? value
|
|
235
238
|
})),
|
|
236
239
|
...(field?.allowCustom === true
|
|
237
|
-
? [{ value: CUSTOM, label: "Custom…", detail: "
|
|
240
|
+
? [{ value: CUSTOM, label: "Custom…", detail: "Explicit value; native acceptance unverified" }]
|
|
238
241
|
: [])
|
|
239
242
|
];
|
|
240
|
-
const selected = await choose(`Select ${key}`, pickerChoices, io, current ??
|
|
243
|
+
const selected = await choose(`Select ${key}`, pickerChoices, io, current ?? (choices.some(choice => choice.value === defaultValue) ? defaultValue : OMIT), key);
|
|
241
244
|
if (selected === undefined)
|
|
242
245
|
return { kind: "cancelled" };
|
|
243
246
|
if (selected === OMIT)
|
|
@@ -344,7 +344,7 @@ const taskChildren = [
|
|
|
344
344
|
},
|
|
345
345
|
{
|
|
346
346
|
name: "complete",
|
|
347
|
-
summary: "Complete
|
|
347
|
+
summary: "Complete locally, or prepare/dispatch the configured final Review and remain active. --refresh-remote only fetches freshness observations; it never rebases, changes HEAD or starts Integration checks.",
|
|
348
348
|
usage: "yui task complete <id> (--summary <text>|--summary-file <path|->) [--artifact-ref <artifact-id|turn:id|url> ...] [--refresh-remote] [--accept-published-tree <publication-id>]",
|
|
349
349
|
options: ["--summary", "--summary-file", "--artifact-ref", "--refresh-remote", "--accept-published-tree"],
|
|
350
350
|
fileOptions: ["--summary-file"]
|
|
@@ -356,7 +356,7 @@ const taskChildren = [
|
|
|
356
356
|
children: [
|
|
357
357
|
{
|
|
358
358
|
name: "status",
|
|
359
|
-
summary: "
|
|
359
|
+
summary: "Observe Task Project bases against local refs; --refresh fetches remote objects without changing HEAD, starting checks or creating Integration/Review.",
|
|
360
360
|
usage: "yui task base status <task> [--refresh]",
|
|
361
361
|
options: ["--refresh"]
|
|
362
362
|
}
|
|
@@ -402,7 +402,7 @@ const taskChildren = [
|
|
|
402
402
|
},
|
|
403
403
|
{
|
|
404
404
|
name: "next-action",
|
|
405
|
-
summary: "
|
|
405
|
+
summary: "Read Task facts, mechanical prerequisites and legal alternatives; semantic choices remain with the Leader.",
|
|
406
406
|
usage: "yui task next-action <task> [--json]",
|
|
407
407
|
options: ["--json"]
|
|
408
408
|
},
|
|
@@ -432,7 +432,7 @@ const taskChildren = [
|
|
|
432
432
|
children: [
|
|
433
433
|
{
|
|
434
434
|
name: "integrate",
|
|
435
|
-
summary: "
|
|
435
|
+
summary: "Explicitly rebase Task changes onto the remote development head, run configured/additional checks (possibly as Jobs), then advance HEAD through Integration CAS. Returns exact attempts and partial results; does not request Review or complete the Task.",
|
|
436
436
|
usage: "yui task upstream integrate <task> (--latest|--project <project>) [--check <command> ...] [--rerun-checks]",
|
|
437
437
|
options: ["--latest", "--project", "--check", "--rerun-checks"]
|
|
438
438
|
}
|
|
@@ -893,7 +893,7 @@ const taskChildren = [
|
|
|
893
893
|
{
|
|
894
894
|
name: "expand",
|
|
895
895
|
summary: "Expand one authorized AgentRun context reference.",
|
|
896
|
-
usage: "yui task run context expand <task>/<run> <ref-id>
|
|
896
|
+
usage: "yui task run context expand <task>/<run> <ref-id> --store <store> [--mode full]",
|
|
897
897
|
options: ["--store", "--mode"]
|
|
898
898
|
},
|
|
899
899
|
{
|
|
@@ -916,7 +916,7 @@ const taskChildren = [
|
|
|
916
916
|
name: "retire",
|
|
917
917
|
summary: "Retire an incorrect historical AgentRun without deleting its audit record.",
|
|
918
918
|
usage: "yui task run retire <task>/<run> --reason <text> [--expected-progress-at <timestamp>] [--agent-id <id>] [--adapter-id <id>] [--native-session-id <id>]",
|
|
919
|
-
options: ["--reason", "--expected-progress-at", "--
|
|
919
|
+
options: ["--reason", "--expected-progress-at", "--agent-id", "--adapter-id", "--native-session-id"]
|
|
920
920
|
}
|
|
921
921
|
]
|
|
922
922
|
},
|
|
@@ -1142,7 +1142,12 @@ export const ROOT_COMMAND = buildNode({
|
|
|
1142
1142
|
},
|
|
1143
1143
|
{ name: "help", summary: "Show root or scoped command help.", usage: "yui help [command ...]", commandPathArguments: true },
|
|
1144
1144
|
{ name: "version", summary: "Print the installed Yui version." },
|
|
1145
|
-
{
|
|
1145
|
+
{
|
|
1146
|
+
name: "update",
|
|
1147
|
+
summary: "Install the latest or an exact published Yui version after storage preflight.",
|
|
1148
|
+
usage: "yui update [--version <exact-version>]",
|
|
1149
|
+
options: ["--version"]
|
|
1150
|
+
},
|
|
1146
1151
|
{
|
|
1147
1152
|
name: "upgrade",
|
|
1148
1153
|
summary: "Plan or apply supported storage migrations for this Home.",
|
|
@@ -1379,8 +1384,8 @@ export const ROOT_COMMAND = buildNode({
|
|
|
1379
1384
|
{
|
|
1380
1385
|
name: "clone",
|
|
1381
1386
|
summary: "Clone and bind a Project after user confirmation.",
|
|
1382
|
-
usage: "yui project clone <name> <remote> [--alias <name> ...] [--stable <ref>] [--development <ref>]",
|
|
1383
|
-
options: ["--alias", "--stable", "--development"]
|
|
1387
|
+
usage: "yui project clone <name> <remote> [--alias <name> ...] [--stable <ref>] [--development <ref>] [--external]",
|
|
1388
|
+
options: ["--alias", "--stable", "--development", "--external"]
|
|
1384
1389
|
},
|
|
1385
1390
|
{
|
|
1386
1391
|
name: "refresh",
|
|
@@ -1722,8 +1727,11 @@ export function validateCommandCatalog(root) {
|
|
|
1722
1727
|
}
|
|
1723
1728
|
const options = new Set();
|
|
1724
1729
|
for (const option of [...node.options, ...node.hiddenOptions]) {
|
|
1725
|
-
|
|
1730
|
+
// --version is an alias only as the entire root invocation. Scoped
|
|
1731
|
+
// commands may own a version selector; help aliases remain reserved.
|
|
1732
|
+
if (reservedAliases.has(option) && option !== "--version") {
|
|
1726
1733
|
throw new Error(`Reserved alias token is not allowed: ${[...node.path, option].join(" ")}`);
|
|
1734
|
+
}
|
|
1727
1735
|
if (options.has(option) || immediate.has(option))
|
|
1728
1736
|
throw new Error(`Duplicate command token: ${[...node.path, option].join(" ")}`);
|
|
1729
1737
|
options.add(option);
|