@zq-silk/yui 0.15.12 → 0.16.0
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 +3 -2
- package/ARCHITECTURE.zh-CN.md +3 -2
- package/dist/artifacts/artifactCommitLock.js +16 -55
- package/dist/artifacts/taskArtifactRepository.js +3 -3
- package/dist/cli/agentConfigurationPicker.js +1 -1
- package/dist/cli/commandCatalog.js +57 -41
- package/dist/cli/completion.js +18 -18
- package/dist/cli/completionWizard.js +1 -1
- package/dist/cli/dynamicCompletion.js +1 -1
- package/dist/cli/interactionPolicy.js +7 -3
- package/dist/cli/invocationAuthority.js +64 -0
- package/dist/cli/managedDiagnostics.js +1 -1
- package/dist/cli/parseRepeatable.js +35 -0
- package/dist/cli/updatePorts.js +26 -5
- package/dist/cli.js +1280 -1243
- package/dist/commands/agentCommands.js +4 -4
- package/dist/commands/capabilityCommands.js +1 -1
- package/dist/commands/configCommands.js +6 -57
- package/dist/commands/configOverview.js +2 -2
- package/dist/commands/durableJobCommands.js +12 -6
- package/dist/commands/globalRoleCommands.js +53 -29
- package/dist/commands/grantCommands.js +0 -3
- package/dist/commands/jobCommands.js +1 -4
- package/dist/commands/operatorCommands.js +3 -3
- package/dist/commands/projectCommands.js +1 -10
- package/dist/commands/resourcesCommands.js +10 -40
- package/dist/commands/roleConfiguration.js +2 -6
- package/dist/commands/taskActivationCommands.js +4 -8
- package/dist/commands/taskAgentCapabilities.js +9 -0
- package/dist/commands/taskCommandSupport.js +155 -0
- package/dist/commands/taskCommandTypes.js +1 -0
- package/dist/commands/taskCommands.js +271 -710
- package/dist/commands/taskCompletionGate.js +1 -1
- package/dist/commands/taskExecutionCommands.js +1 -1
- package/dist/commands/taskFactCommands.js +325 -0
- package/dist/commands/taskInputCommands.js +12 -42
- package/dist/commands/taskIntegrationCommands.js +17 -57
- package/dist/commands/taskNextActionCommand.js +7 -6
- package/dist/commands/taskPublicationAdoptCommand.js +3 -3
- package/dist/commands/taskPublicationCommands.js +1 -1
- package/dist/commands/taskPublicationVerifyCommand.js +1 -1
- package/dist/commands/taskRemoteDeliveryCommand.js +2 -94
- package/dist/commands/taskUpstreamCommands.js +19 -8
- package/dist/commands/workflowCommands.js +6 -1
- package/dist/completion/completionInstaller.js +26 -26
- package/dist/completion/completionState.js +26 -26
- package/dist/completion/fileCompletionManager.js +6 -11
- package/dist/config/configCatalog.js +0 -2
- package/dist/config/timeZone.js +14 -0
- package/dist/config/yuiConfig.js +0 -29
- package/dist/context/runContextPack.js +2 -3
- package/dist/context/taskCatalog.js +3 -5
- package/dist/context/taskContext.js +139 -151
- package/dist/context/wakeRunReferences.js +11 -0
- package/dist/controller/agentCapabilities.js +58 -0
- package/dist/controller/agentRuntimeObserver.js +6 -11
- package/dist/controller/clientRuntime.js +22 -14
- package/dist/controller/controller.js +9 -22
- package/dist/controller/fileSchedulerStoreAdapter.js +117 -212
- package/dist/controller/jobClient.js +4 -4
- package/dist/controller/jobControl.js +60 -25
- package/dist/controller/jobSupervisor.js +4 -4
- package/dist/controller/providerRetryDelivery.js +7 -7
- package/dist/controller/runtime.js +51 -44
- package/dist/controller/runtimeEventProcessor.js +0 -5
- package/dist/controller/sessionOwnerReconciliation.js +5 -0
- package/dist/controller/taskAgentError.js +35 -0
- package/dist/coordination/workMailboxQueue.js +2 -24
- package/dist/core/controllerClient.js +2 -2
- package/dist/core/fileLockOwner.js +74 -0
- package/dist/decision/decision.js +17 -0
- package/dist/doctor/doctor.js +18 -9
- package/dist/event/taskEvent.js +12 -0
- package/dist/execution/workItemExecutionProjection.js +2 -2
- package/dist/executor/agentCapabilityConfig.js +43 -0
- package/dist/executor/agentConfigurationCatalog.js +49 -11
- package/dist/executor/agentExecutor.js +5 -8
- package/dist/executor/fileRoleLaunchPlanner.js +11 -53
- package/dist/executor/taskAgentCapabilities.js +64 -0
- package/dist/integration/deliveryObligation.js +1 -69
- package/dist/integration/gitIntegrationService.js +60 -84
- package/dist/integration/integrationAttempt.js +3 -14
- package/dist/integration/integrationSourceApplication.js +4 -12
- package/dist/integration/manifestTags.js +2 -2
- package/dist/job/durableJob.js +4 -25
- package/dist/job/jobAssignmentScope.js +22 -0
- package/dist/job/jobOperation.js +16 -0
- package/dist/job/jobRunner.js +2 -1
- package/dist/job/stepDirectory.js +15 -0
- package/dist/kernel/builtinCapabilities.js +15 -11
- package/dist/kernel/kernelPorts.js +1 -17
- package/dist/lifecycle/exactRunTerminalization.js +1 -9
- package/dist/message/inputControlResolution.js +3 -4
- package/dist/message/message.js +17 -20
- package/dist/message/messageContinuation.js +1 -1
- package/dist/milestone/milestone.js +11 -0
- package/dist/observability/orchestrationMetrics.js +24 -1
- package/dist/observability/runtimeIdentity.js +1 -17
- package/dist/output/agentConfigurationPresentation.js +2 -0
- package/dist/output/timePresentation.js +1 -14
- package/dist/plugins/pluginService.js +12 -4
- package/dist/release/releaseWorkflowPorts.js +45 -96
- package/dist/release/runtimeRelease.js +9 -15
- package/dist/repository/projectMaintenanceLock.js +23 -64
- package/dist/repository/taskBaseFreshness.js +1 -1
- package/dist/repository/taskWorkspaceCoordinator.js +13 -22
- package/dist/repository/taskWorkspacePreparer.js +29 -25
- package/dist/repository/workspaceCleanupInspection.js +5 -5
- package/dist/resources/autoResourceGc.js +4 -77
- package/dist/resources/liveReferences.js +7 -54
- package/dist/resources/resourceDiscovery.js +5 -118
- package/dist/resources/resourceGc.js +233 -181
- package/dist/resources/resourceRegistrar.js +5 -4
- package/dist/resources/resourceRegistry.js +3 -37
- package/dist/resources/resourceRegistryStore.js +13 -36
- package/dist/resources/sqliteResourceRegistry.js +43 -26
- package/dist/review/deltaRecheck.js +1 -1
- package/dist/review/reviewAcceptance.js +1 -1
- package/dist/review/reviewDecision.js +1 -1
- package/dist/review/reviewRound.js +8 -7
- package/dist/review/taskFinalReviewContractResolution.js +1 -1
- package/dist/runtime/acpProtocol.js +4 -51
- package/dist/runtime/acpSession.js +10 -75
- package/dist/runtime/acpSessionConfiguration.js +1 -8
- package/dist/runtime/agentEndpoint.js +3 -2
- package/dist/runtime/agentFailureContext.js +43 -0
- package/dist/runtime/agentHost.js +15 -15
- package/dist/runtime/codexInteractiveHost.js +2 -2
- package/dist/runtime/index.js +0 -1
- package/dist/runtime/managedCaller.js +21 -1
- package/dist/runtime/providerErrors.js +38 -0
- package/dist/runtime/runtimeObservation.js +0 -5
- package/dist/runtime/runtimeSessionCandidate.js +2 -3
- package/dist/runtime/sessionOwnerIdentity.js +1 -1
- package/dist/runtime/structuredProviderHost.js +4 -41
- package/dist/runtime/tmuxAdapters.js +6 -8
- package/dist/scheduler/activeRoleRunDelivery.js +7 -7
- package/dist/scheduler/leaderWakeupProcessor.js +19 -6
- package/dist/scheduler/operatorEvent.js +12 -20
- package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
- package/dist/scheduler/ports.js +5 -8
- package/dist/scheduler/roleRunLiveness.js +4 -4
- package/dist/scheduler/roleRunStall.js +16 -23
- package/dist/scheduler/taskExecutionProjection.js +25 -33
- package/dist/scheduler/taskObservabilityProjection.js +0 -1
- package/dist/scheduler/taskWake.js +5 -10
- package/dist/scheduler/wakeReason.js +2 -0
- package/dist/scheduler/wakeupQueue.js +2 -4
- package/dist/setup/setupCommand.js +1 -1
- package/dist/storage/contextRecords.js +106 -0
- package/dist/storage/currentTaskStore.js +1 -1
- package/dist/storage/homeLayout.js +13 -17
- package/dist/storage/migrations/agentFailureContext.js +22 -0
- package/dist/storage/migrations/currentInputContract.js +86 -0
- package/dist/storage/migrations/currentRuntimeContract.js +228 -0
- package/dist/storage/migrations/historicalVerificationPlan.js +35 -0
- package/dist/storage/migrations/integrationContinuation.js +5 -4
- package/dist/storage/migrations/narrowAgentFailureContext.js +65 -0
- package/dist/storage/migrations/notificationOnlyWakes.js +74 -0
- package/dist/storage/migrations/verificationPlanV1.js +162 -0
- package/dist/storage/migrations/verificationPolicy.js +74 -0
- package/dist/storage/migrations/workItemHistory.js +46 -0
- package/dist/storage/persistenceWorker.js +12 -4
- package/dist/storage/recordValidation.js +87 -0
- package/dist/storage/sqliteSchema.js +142 -1
- package/dist/storage/sqliteStore.js +156 -162
- package/dist/storage/storageSchema.js +2 -14
- package/dist/storage/storageVersions.js +1 -1
- package/dist/storage/storeRpc.js +15 -7
- package/dist/storage/taskStore.js +3 -7
- package/dist/storage/upgrade/upgradeOrchestrator.js +25 -37
- package/dist/task/completionReadiness.js +5 -24
- package/dist/task/draftPlan.js +0 -53
- package/dist/task/nextAction.js +7 -13
- package/dist/task/remoteDeliveryService.js +89 -0
- package/dist/task/taskActivation.js +2 -25
- package/dist/task/taskActivationService.js +0 -2
- package/dist/task/taskRecordReference.js +0 -1
- package/dist/task/taskSubmission.js +3 -14
- package/dist/telemetry/sqliteTelemetryBatch.js +29 -0
- package/dist/telemetry/sqliteTelemetryStore.js +49 -49
- package/dist/telemetry/telemetryWiring.js +4 -3
- package/dist/tmux/tmuxManager.js +29 -20
- package/dist/verification/gateArtifact.js +15 -24
- package/dist/verification/gateArtifactStore.js +14 -7
- package/dist/verification/verificationGateService.js +29 -88
- package/dist/verification/verificationPlan.js +27 -72
- package/dist/web/assets/client/app.js +1 -1
- package/dist/web/assets/client/taskSurface.js +4 -4
- package/dist/web/webServer.js +4 -6
- package/dist/web/webSnapshot.js +3 -83
- package/dist/web/webTaskSurface.js +17 -46
- package/dist/workItem/workItem.js +1 -12
- package/docs/architecture/capabilities-and-resources.md +14 -2
- package/docs/architecture/capabilities-and-resources.zh-CN.md +11 -1
- package/docs/managed-turn-and-session-runtime.md +83 -10
- package/docs/managed-turn-and-session-runtime.zh-CN.md +65 -11
- package/docs/plugin-sdk.md +4 -2
- package/docs/provider-runtime.md +3 -1
- package/docs/provider-runtime.zh-CN.md +4 -2
- package/docs/release-workflow.md +190 -7
- package/docs/release-workflow.zh-CN.md +139 -5
- package/docs/roles-and-configuration.md +29 -0
- package/docs/roles-and-configuration.zh-CN.md +21 -0
- package/docs/sqlite-control-plane-design.md +16 -3
- package/docs/sqlite-control-plane-design.zh-CN.md +13 -2
- package/docs/task-dag-semantics.md +3 -3
- package/docs/task-dag-semantics.zh-CN.md +2 -2
- package/docs/task-delivery.md +91 -5
- package/docs/task-delivery.zh-CN.md +72 -4
- package/docs/task-discovery.md +10 -11
- package/docs/task-discovery.zh-CN.md +8 -9
- package/docs/testing/verification-levels.md +145 -9
- package/docs/testing/verification-levels.zh-CN.md +103 -8
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +5 -0
- package/skills/yui-leader/references/integration.md +9 -5
- package/skills/yui-leader/references/planning.md +9 -3
- package/skills/yui-operator/SKILL.md +15 -10
- package/skills/yui-runtime/SKILL.md +6 -6
- package/skills/yui-runtime/references/recovery.md +47 -0
- package/dist/agent/agentRegistry.js +0 -10
- package/dist/agentRun/runIdentity.js +0 -22
- package/dist/commands/deliveryGuardPreflight.js +0 -30
- package/dist/commands/taskIntegrationQueueCommands.js +0 -226
- package/dist/commands/taskOverviewCommand.js +0 -377
- package/dist/completion/completionWizard.js +0 -125
- package/dist/context/dispatchContext.js +0 -110
- package/dist/context/wakeNotification.js +0 -144
- package/dist/integration/integrationCheckEvidenceReuse.js +0 -53
- package/dist/integration/integrationQueueEntry.js +0 -191
- package/dist/integration/integrationQueueService.js +0 -810
- package/dist/release/fakeReleasePorts.js +0 -55
- package/dist/runtime/sessionOwnerRegistry.js +0 -137
- package/dist/task/deliveryGuard.js +0 -226
- /package/dist/{commands/taskActor.js → task/taskAuthority.js} +0 -0
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { isDeepStrictEqual } from "node:util";
|
|
2
|
-
import { taskActor } from "./taskActor.js";
|
|
3
2
|
import { dataError, taskNotFound, usageError } from "../errors/cliError.js";
|
|
4
3
|
import { createTaskEvent } from "../event/taskEvent.js";
|
|
5
4
|
import { defaultTableWidth, renderTable } from "../output/table.js";
|
|
@@ -7,6 +6,7 @@ import { formatTimestamp } from "../output/timePresentation.js";
|
|
|
7
6
|
import { resolveProject } from "../repository/project.js";
|
|
8
7
|
import { createPublicationReference } from "../task/publicationReference.js";
|
|
9
8
|
import { resolveTaskRecordReference } from "../task/taskRecordReference.js";
|
|
9
|
+
import { taskActor } from "../task/taskAuthority.js";
|
|
10
10
|
const PROVIDERS = new Set(["github", "gitlab"]);
|
|
11
11
|
const EXTERNAL_KINDS = new Set(["pull-request", "merge-request"]);
|
|
12
12
|
const STATES = new Set(["open", "merged", "closed"]);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isDeepStrictEqual } from "node:util";
|
|
2
|
-
import { taskActor } from "
|
|
2
|
+
import { taskActor } from "../task/taskAuthority.js";
|
|
3
3
|
import { upsertTaskPublication } from "./taskPublicationCommands.js";
|
|
4
4
|
import { dataError, runtimeError, taskNotFound, usageError, CliError } from "../errors/cliError.js";
|
|
5
5
|
import { publicationExternalKey } from "../task/publicationReference.js";
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { isDeepStrictEqual } from "node:util";
|
|
2
1
|
import { taskNotFound, usageError } from "../errors/cliError.js";
|
|
3
|
-
import {
|
|
2
|
+
import { projectTaskRemoteDeliveryFromStore } from "../task/remoteDeliveryService.js";
|
|
4
3
|
export function runTaskRemoteDeliveryCommand(args, store, currentCandidate = null) {
|
|
5
4
|
const usage = "Task remote-delivery usage: yui task remote-delivery <task> [--json].";
|
|
6
5
|
const asJson = args.includes("--json");
|
|
@@ -9,7 +8,7 @@ export function runTaskRemoteDeliveryCommand(args, store, currentCandidate = nul
|
|
|
9
8
|
throw usageError(usage);
|
|
10
9
|
}
|
|
11
10
|
const taskId = positionals[0].trim();
|
|
12
|
-
const data = store.
|
|
11
|
+
const data = store.readTransaction((reader) => {
|
|
13
12
|
const task = reader.getTask(taskId);
|
|
14
13
|
if (task === null)
|
|
15
14
|
throw taskNotFound(taskId);
|
|
@@ -23,85 +22,6 @@ export function runTaskRemoteDeliveryCommand(args, store, currentCandidate = nul
|
|
|
23
22
|
data
|
|
24
23
|
};
|
|
25
24
|
}
|
|
26
|
-
export function projectTaskRemoteDeliveryFromStore(store, task, currentCandidate = null) {
|
|
27
|
-
return projectTaskRemoteDelivery({
|
|
28
|
-
task,
|
|
29
|
-
events: store.listEvents(task.id),
|
|
30
|
-
publications: store.listPublicationReferences(task.id),
|
|
31
|
-
managedWorkspaces: store.listManagedWorkspaces(task.id),
|
|
32
|
-
runs: store.listRuns(task.id),
|
|
33
|
-
integrations: store.listIntegrationAttempts(task.id),
|
|
34
|
-
currentCandidate
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
export function createTaskRemoteDeliveryProof(store, task, currentCandidate = null) {
|
|
38
|
-
const publications = store.listPublicationReferences(task.id);
|
|
39
|
-
const delivery = projectTaskRemoteDelivery({
|
|
40
|
-
task,
|
|
41
|
-
events: store.listEvents(task.id),
|
|
42
|
-
publications,
|
|
43
|
-
managedWorkspaces: store.listManagedWorkspaces(task.id),
|
|
44
|
-
runs: store.listRuns(task.id),
|
|
45
|
-
integrations: store.listIntegrationAttempts(task.id),
|
|
46
|
-
currentCandidate
|
|
47
|
-
});
|
|
48
|
-
return {
|
|
49
|
-
schemaVersion: 1,
|
|
50
|
-
task: taskRemoteDeliveryProofTask(task),
|
|
51
|
-
publications,
|
|
52
|
-
delivery
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
export function assertTaskRemoteDeliveryProof(store, task, proof) {
|
|
56
|
-
if (proof === undefined || proof.schemaVersion !== 1) {
|
|
57
|
-
throw usageError(`Task remote-delivery preflight proof is required: ${task.id}.`);
|
|
58
|
-
}
|
|
59
|
-
if (!isDeepStrictEqual(proof.task, taskRemoteDeliveryProofTask(task))) {
|
|
60
|
-
throw usageError(`Task changed after remote-delivery preflight: ${task.id}.`);
|
|
61
|
-
}
|
|
62
|
-
if (!isDeepStrictEqual(proof.publications, store.listPublicationReferences(task.id))) {
|
|
63
|
-
throw usageError(`Task Publication evidence changed after remote-delivery preflight: ${task.id}.`);
|
|
64
|
-
}
|
|
65
|
-
// Recheck semantic adoption/Integration facts as well as Publication versions.
|
|
66
|
-
// For provisional cancelled Tasks retain the frozen candidate used at preflight.
|
|
67
|
-
const current = projectTaskRemoteDeliveryFromStore(store, task, {
|
|
68
|
-
projects: proof.delivery.projects.flatMap(p => p.expectedLocalCommit === null
|
|
69
|
-
? [] : [{ projectId: p.projectId, commit: p.expectedLocalCommit }])
|
|
70
|
-
});
|
|
71
|
-
if (!isDeepStrictEqual(current, proof.delivery)) {
|
|
72
|
-
throw usageError(`Task delivery evidence changed after remote-delivery preflight: ${task.id}.`);
|
|
73
|
-
}
|
|
74
|
-
assertTaskRemoteDeliveryIntegrated(proof.delivery);
|
|
75
|
-
return proof.delivery;
|
|
76
|
-
}
|
|
77
|
-
export function assertTaskRemoteDeliveryIntegrated(delivery) {
|
|
78
|
-
if (!delivery.allMerged) {
|
|
79
|
-
const headUnavailable = delivery.projects.filter((project) => (project.codeDelivery !== "none"
|
|
80
|
-
&& project.coverage === "head-unavailable"));
|
|
81
|
-
if (headUnavailable.length > 0 && delivery.source === "task-completed") {
|
|
82
|
-
throw usageError(`Task ${delivery.taskId} has no frozen completion heads for: ${headUnavailable.map(({ projectId }) => projectId).join(", ")}. Historical acceptance cannot be inferred from a merge or archive.`);
|
|
83
|
-
}
|
|
84
|
-
const uncovered = delivery.projects
|
|
85
|
-
.filter((project) => project.codeDelivery !== "none" && !project.merged)
|
|
86
|
-
.map((project) => (`${project.projectId}/${project.coverage}`
|
|
87
|
-
+ (project.publication === null ? "" : `/${project.publication.id}`)))
|
|
88
|
-
.join(", ");
|
|
89
|
-
throw usageError(`Task ${delivery.taskId} is not fully merged into remote delivery: ${uncovered || "expected Project heads are unavailable"}. Inspect each Project reason with task remote-delivery. Record confirmed Publication facts; `
|
|
90
|
-
+ "for a changed post-completion candidate, review publication diff and explicitly adopt its acceptance.");
|
|
91
|
-
}
|
|
92
|
-
if (delivery.allVerified)
|
|
93
|
-
return;
|
|
94
|
-
const unverified = delivery.projects
|
|
95
|
-
.filter((project) => (project.codeDelivery !== "none"
|
|
96
|
-
&& project.merged
|
|
97
|
-
&& !project.verified))
|
|
98
|
-
.map((project) => (`${project.projectId}/${project.coverage}`
|
|
99
|
-
+ (project.publication === null ? "" : `/${project.publication.id}`)))
|
|
100
|
-
.join(", ");
|
|
101
|
-
throw usageError(`Task ${delivery.taskId} has merged Publication evidence that is not verified: `
|
|
102
|
-
+ `${unverified || "verification evidence is unavailable"}. Run task publication verify `
|
|
103
|
-
+ "for each Publication only when the provider read is authorized.");
|
|
104
|
-
}
|
|
105
25
|
export function renderTaskRemoteDelivery(delivery, indent = "") {
|
|
106
26
|
const source = `${delivery.source}${delivery.provisional ? " (provisional)" : ""}`;
|
|
107
27
|
const lines = [
|
|
@@ -131,15 +51,3 @@ export function renderTaskRemoteDelivery(delivery, indent = "") {
|
|
|
131
51
|
function shortCommit(commit) {
|
|
132
52
|
return commit === null ? "unknown" : commit.slice(0, 12);
|
|
133
53
|
}
|
|
134
|
-
function taskRemoteDeliveryProofTask(task) {
|
|
135
|
-
return {
|
|
136
|
-
id: task.id,
|
|
137
|
-
status: task.status,
|
|
138
|
-
projectBindings: task.projectBindings,
|
|
139
|
-
...(task.workspaceIdentity === undefined
|
|
140
|
-
? {}
|
|
141
|
-
: { workspaceIdentity: task.workspaceIdentity }),
|
|
142
|
-
...(task.completedAt === undefined ? {} : { completedAt: task.completedAt }),
|
|
143
|
-
...(task.retiredAt === undefined ? {} : { retiredAt: task.retiredAt })
|
|
144
|
-
};
|
|
145
|
-
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import { parseRepeatable } from "../cli/parseRepeatable.js";
|
|
1
2
|
import { usageError } from "../errors/cliError.js";
|
|
2
3
|
import { GitIntegrationService } from "../integration/gitIntegrationService.js";
|
|
3
4
|
import { createIntegrationAttempt } from "../integration/integrationAttempt.js";
|
|
4
5
|
import { NodeGitWorkspace } from "../repository/gitWorkspace.js";
|
|
5
6
|
import { FileTaskWorkspacePreparer } from "../repository/taskWorkspacePreparer.js";
|
|
6
7
|
import { workspaceProjectEntry } from "../worktree/managedWorkspace.js";
|
|
7
|
-
import {
|
|
8
|
-
import { taskLocalActor } from "./taskActor.js";
|
|
8
|
+
import { taskLocalActor } from "../task/taskAuthority.js";
|
|
9
9
|
export async function runTaskUpstreamCommand(args, store, home, options = {}) {
|
|
10
10
|
const [command, ...rest] = args;
|
|
11
11
|
if (command === "integrate")
|
|
@@ -15,7 +15,7 @@ export async function runTaskUpstreamCommand(args, store, home, options = {}) {
|
|
|
15
15
|
: `Unknown command: task upstream ${command}`);
|
|
16
16
|
}
|
|
17
17
|
async function integrateUpstream(args, store, home, options) {
|
|
18
|
-
const usage = "Task upstream integrate usage: yui task upstream integrate <task> (--latest|--project <project>) [--check <command> ...].";
|
|
18
|
+
const usage = "Task upstream integrate usage: yui task upstream integrate <task> (--latest|--project <project>) [--check <command> ...] [--rerun-checks].";
|
|
19
19
|
let latest = false;
|
|
20
20
|
const normalized = [];
|
|
21
21
|
for (const arg of args) {
|
|
@@ -29,7 +29,7 @@ async function integrateUpstream(args, store, home, options) {
|
|
|
29
29
|
? ["--project", arg.slice("--project=".length)]
|
|
30
30
|
: [arg]));
|
|
31
31
|
}
|
|
32
|
-
const parsed = parseRepeatable(normalized, new Set(["--check"]), new Set(["--project"]), usage);
|
|
32
|
+
const parsed = parseRepeatable(normalized, new Set(["--check"]), new Set(["--project"]), usage, new Set(["--rerun-checks"]));
|
|
33
33
|
if (parsed.positionals.length !== 1)
|
|
34
34
|
throw usageError(usage);
|
|
35
35
|
const taskId = parsed.positionals[0];
|
|
@@ -59,7 +59,7 @@ async function integrateUpstream(args, store, home, options) {
|
|
|
59
59
|
if (workspace === null || workspace.owner.type !== "task") {
|
|
60
60
|
throw usageError(`Task has no authoritative main clone: ${task.id}.`);
|
|
61
61
|
}
|
|
62
|
-
const service = new GitIntegrationService(store.rootDirectory(), store, git, now);
|
|
62
|
+
const service = new GitIntegrationService(store.rootDirectory(), store, git, now, options.environment, undefined, options.jobPort);
|
|
63
63
|
const results = [];
|
|
64
64
|
for (const binding of task.projectBindings) {
|
|
65
65
|
if (projectRef !== undefined && binding.projectId !== projectRef)
|
|
@@ -99,20 +99,31 @@ async function integrateUpstream(args, store, home, options) {
|
|
|
99
99
|
taskBaseCommit: binding.baseCommit,
|
|
100
100
|
strategy: "rebase"
|
|
101
101
|
},
|
|
102
|
-
checkCommands: parsed.many.get("--check") ?? []
|
|
102
|
+
checkCommands: parsed.many.get("--check") ?? [],
|
|
103
|
+
rerunChecks: parsed.one.has("--rerun-checks")
|
|
103
104
|
}, now());
|
|
104
105
|
tx.saveIntegrationAttempt(task.id, created);
|
|
105
106
|
return created;
|
|
106
107
|
});
|
|
107
108
|
const result = await service.integrate(task.id, attempt.id);
|
|
108
109
|
results.push(result);
|
|
109
|
-
|
|
110
|
+
// Each Project has an independent candidate and Job. --latest admits all
|
|
111
|
+
// requested Projects, then the Agent continues the returned exact attempts.
|
|
112
|
+
if (result.status !== "committed" && result.status !== "checks-running")
|
|
110
113
|
break;
|
|
111
114
|
}
|
|
112
115
|
if (projectRef !== undefined && results.length === 0) {
|
|
113
116
|
throw usageError(`Task Project not found: ${task.id}/${projectRef}.`);
|
|
114
117
|
}
|
|
115
|
-
const lines = results.
|
|
118
|
+
const lines = results.flatMap(result => {
|
|
119
|
+
const { attempt, status } = result;
|
|
120
|
+
return [
|
|
121
|
+
` ${attempt.id} ${attempt.projectId}: ${attempt.beforeCommit.slice(0, 12)} -> ${(attempt.afterCommit ?? attempt.candidateCommit ?? attempt.beforeCommit).slice(0, 12)} (${status})`,
|
|
122
|
+
...(status === "checks-running" ? [
|
|
123
|
+
` Job ${result.job.id}; continue with yui task integration continue ${task.id}/${attempt.id}`
|
|
124
|
+
] : [])
|
|
125
|
+
];
|
|
126
|
+
});
|
|
116
127
|
return {
|
|
117
128
|
output: `Upstream Integration results for Task ${task.id}:\n${lines.join("\n")}\n`,
|
|
118
129
|
data: { taskId: task.id, integrations: results }
|
|
@@ -103,7 +103,12 @@ export async function runWorkflowCommandAsync(args, store, options) {
|
|
|
103
103
|
// failure so the caller knows this path was compromised.
|
|
104
104
|
if (typeof store.rootDirectory === "function") {
|
|
105
105
|
const auditStore = openConfiguredTaskStore(store.rootDirectory());
|
|
106
|
-
|
|
106
|
+
try {
|
|
107
|
+
recordTaskEvent(auditStore, taskId, "release-workflow.run", eventPayload, eventNow);
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
auditStore.close();
|
|
111
|
+
}
|
|
107
112
|
}
|
|
108
113
|
throw error;
|
|
109
114
|
}
|
|
@@ -3,9 +3,9 @@ import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, renameSync,
|
|
|
3
3
|
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
4
|
import { dataError } from "../errors/cliError.js";
|
|
5
5
|
import { activationBlock, activationEnd, activationIsAutomatic, activationStart, completionMarker, managedCompletionScript } from "./completionState.js";
|
|
6
|
-
export function installCompletion(store, shell, installation, env,
|
|
6
|
+
export function installCompletion(store, shell, installation, env, activate) {
|
|
7
7
|
validateInstallation(installation);
|
|
8
|
-
writeManagedScript(shell, installation.scriptPath
|
|
8
|
+
writeManagedScript(shell, installation.scriptPath);
|
|
9
9
|
store.transaction((tx) => {
|
|
10
10
|
const config = tx.getConfig();
|
|
11
11
|
tx.saveConfig({
|
|
@@ -16,20 +16,20 @@ export function installCompletion(store, shell, installation, env, identity, act
|
|
|
16
16
|
}
|
|
17
17
|
});
|
|
18
18
|
});
|
|
19
|
-
if (!activationIsAutomatic(shell, installation, env
|
|
20
|
-
writeActivationBlock(shell, installation
|
|
19
|
+
if (!activationIsAutomatic(shell, installation, env) && activate) {
|
|
20
|
+
writeActivationBlock(shell, installation);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
export function uninstallCompletion(store, shell
|
|
23
|
+
export function uninstallCompletion(store, shell) {
|
|
24
24
|
store.transaction((tx) => {
|
|
25
25
|
const config = tx.getConfig();
|
|
26
26
|
const installation = config.completionInstallations?.[shell];
|
|
27
27
|
if (installation === undefined)
|
|
28
28
|
return;
|
|
29
|
-
assertManagedScriptRemovable(shell, installation.scriptPath
|
|
30
|
-
assertActivationRemovable(shell, installation
|
|
31
|
-
removeManagedScript(shell, installation.scriptPath
|
|
32
|
-
removeActivationBlock(shell, installation
|
|
29
|
+
assertManagedScriptRemovable(shell, installation.scriptPath);
|
|
30
|
+
assertActivationRemovable(shell, installation);
|
|
31
|
+
removeManagedScript(shell, installation.scriptPath);
|
|
32
|
+
removeActivationBlock(shell, installation);
|
|
33
33
|
const installations = { ...config.completionInstallations };
|
|
34
34
|
delete installations[shell];
|
|
35
35
|
if (Object.keys(installations).length > 0) {
|
|
@@ -40,17 +40,17 @@ export function uninstallCompletion(store, shell, identity) {
|
|
|
40
40
|
tx.saveConfig(withoutInstallations);
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
|
-
function assertManagedScriptRemovable(shell, path
|
|
43
|
+
function assertManagedScriptRemovable(shell, path) {
|
|
44
44
|
if (!existsSync(path))
|
|
45
45
|
return;
|
|
46
46
|
const stat = lstatSync(path);
|
|
47
47
|
if (!stat.isFile()
|
|
48
48
|
|| stat.isSymbolicLink()
|
|
49
|
-
|| !readFileSync(path, "utf8").startsWith(completionMarker(shell
|
|
49
|
+
|| !readFileSync(path, "utf8").startsWith(completionMarker(shell))) {
|
|
50
50
|
throw dataError(`Refusing to remove unmanaged completion script: ${path}`);
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
-
function assertActivationRemovable(shell, installation
|
|
53
|
+
function assertActivationRemovable(shell, installation) {
|
|
54
54
|
const path = installation.activationPath;
|
|
55
55
|
if (!existsSync(path))
|
|
56
56
|
return;
|
|
@@ -59,25 +59,25 @@ function assertActivationRemovable(shell, installation, identity) {
|
|
|
59
59
|
throw dataError(`Refusing to modify unsafe activation file: ${path}`);
|
|
60
60
|
}
|
|
61
61
|
const contents = readFileSync(path, "utf8");
|
|
62
|
-
const starts = occurrences(contents, activationStart(shell
|
|
63
|
-
const ends = occurrences(contents, activationEnd(shell
|
|
62
|
+
const starts = occurrences(contents, activationStart(shell));
|
|
63
|
+
const ends = occurrences(contents, activationEnd(shell));
|
|
64
64
|
if (starts !== ends || starts > 1) {
|
|
65
65
|
throw dataError(`Refusing to remove ambiguous Yui activation block: ${path}`);
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
-
function writeManagedScript(shell, path
|
|
68
|
+
function writeManagedScript(shell, path) {
|
|
69
69
|
if (existsSync(path)) {
|
|
70
70
|
const stat = lstatSync(path);
|
|
71
71
|
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
72
72
|
throw dataError(`Refusing to overwrite unsafe completion script: ${path}`);
|
|
73
73
|
}
|
|
74
|
-
if (!readFileSync(path, "utf8").startsWith(completionMarker(shell
|
|
74
|
+
if (!readFileSync(path, "utf8").startsWith(completionMarker(shell))) {
|
|
75
75
|
throw dataError(`Refusing to overwrite unmanaged completion script: ${path}`);
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
-
writeAtomic(path, managedCompletionScript(shell
|
|
78
|
+
writeAtomic(path, managedCompletionScript(shell), 0o644);
|
|
79
79
|
}
|
|
80
|
-
function writeActivationBlock(shell, installation
|
|
80
|
+
function writeActivationBlock(shell, installation) {
|
|
81
81
|
const path = installation.activationPath;
|
|
82
82
|
let contents = "";
|
|
83
83
|
let mode = 0o644;
|
|
@@ -89,31 +89,31 @@ function writeActivationBlock(shell, installation, identity) {
|
|
|
89
89
|
contents = readFileSync(path, "utf8");
|
|
90
90
|
mode = stat.mode & 0o777;
|
|
91
91
|
}
|
|
92
|
-
const start = activationStart(shell
|
|
93
|
-
const end = activationEnd(shell
|
|
92
|
+
const start = activationStart(shell);
|
|
93
|
+
const end = activationEnd(shell);
|
|
94
94
|
const starts = occurrences(contents, start);
|
|
95
95
|
const ends = occurrences(contents, end);
|
|
96
96
|
if (starts > 1 || ends > 1 || starts !== ends) {
|
|
97
97
|
throw dataError(`Refusing to modify ambiguous Yui activation block: ${path}`);
|
|
98
98
|
}
|
|
99
|
-
const block = activationBlock(shell, installation
|
|
99
|
+
const block = activationBlock(shell, installation);
|
|
100
100
|
const next = starts === 1
|
|
101
101
|
? replaceManagedBlock(contents, start, end, block)
|
|
102
102
|
: `${contents}${contents.length === 0 || contents.endsWith("\n") ? "" : "\n"}${block}\n`;
|
|
103
103
|
writeAtomic(path, next, mode);
|
|
104
104
|
}
|
|
105
|
-
function removeManagedScript(shell, path
|
|
105
|
+
function removeManagedScript(shell, path) {
|
|
106
106
|
if (!existsSync(path))
|
|
107
107
|
return;
|
|
108
108
|
const stat = lstatSync(path);
|
|
109
109
|
if (!stat.isFile()
|
|
110
110
|
|| stat.isSymbolicLink()
|
|
111
|
-
|| !readFileSync(path, "utf8").startsWith(completionMarker(shell
|
|
111
|
+
|| !readFileSync(path, "utf8").startsWith(completionMarker(shell))) {
|
|
112
112
|
throw dataError(`Refusing to remove unmanaged completion script: ${path}`);
|
|
113
113
|
}
|
|
114
114
|
rmSync(path);
|
|
115
115
|
}
|
|
116
|
-
function removeActivationBlock(shell, installation
|
|
116
|
+
function removeActivationBlock(shell, installation) {
|
|
117
117
|
const path = installation.activationPath;
|
|
118
118
|
if (!existsSync(path))
|
|
119
119
|
return;
|
|
@@ -122,8 +122,8 @@ function removeActivationBlock(shell, installation, identity) {
|
|
|
122
122
|
throw dataError(`Refusing to modify unsafe activation file: ${path}`);
|
|
123
123
|
}
|
|
124
124
|
const contents = readFileSync(path, "utf8");
|
|
125
|
-
const start = activationStart(shell
|
|
126
|
-
const end = activationEnd(shell
|
|
125
|
+
const start = activationStart(shell);
|
|
126
|
+
const end = activationEnd(shell);
|
|
127
127
|
const starts = occurrences(contents, start);
|
|
128
128
|
const ends = occurrences(contents, end);
|
|
129
129
|
if (starts !== ends || starts > 1) {
|
|
@@ -10,14 +10,14 @@ export function currentCompletionShell(env) {
|
|
|
10
10
|
? value
|
|
11
11
|
: undefined;
|
|
12
12
|
}
|
|
13
|
-
export function suggestedCompletionInstallation(shell, env
|
|
13
|
+
export function suggestedCompletionInstallation(shell, env) {
|
|
14
14
|
const home = absoluteEnvRoot("HOME", env.HOME);
|
|
15
15
|
if (shell === "bash") {
|
|
16
16
|
const data = env.XDG_DATA_HOME === undefined
|
|
17
17
|
? join(home, ".local", "share")
|
|
18
18
|
: absoluteEnvRoot("XDG_DATA_HOME", env.XDG_DATA_HOME);
|
|
19
19
|
return {
|
|
20
|
-
scriptPath: join(data, "bash-completion", "completions",
|
|
20
|
+
scriptPath: join(data, "bash-completion", "completions", "yui"),
|
|
21
21
|
activationPath: join(home, ".bashrc")
|
|
22
22
|
};
|
|
23
23
|
}
|
|
@@ -26,7 +26,7 @@ export function suggestedCompletionInstallation(shell, env, identity) {
|
|
|
26
26
|
? home
|
|
27
27
|
: absoluteEnvRoot("ZDOTDIR", env.ZDOTDIR);
|
|
28
28
|
return {
|
|
29
|
-
scriptPath: join(zshRoot, ".zfunc",
|
|
29
|
+
scriptPath: join(zshRoot, ".zfunc", "_yui"),
|
|
30
30
|
activationPath: join(zshRoot, ".zshrc")
|
|
31
31
|
};
|
|
32
32
|
}
|
|
@@ -34,11 +34,11 @@ export function suggestedCompletionInstallation(shell, env, identity) {
|
|
|
34
34
|
? join(home, ".config")
|
|
35
35
|
: absoluteEnvRoot("XDG_CONFIG_HOME", env.XDG_CONFIG_HOME);
|
|
36
36
|
return {
|
|
37
|
-
scriptPath: join(config, "fish", "completions",
|
|
37
|
+
scriptPath: join(config, "fish", "completions", "yui.fish"),
|
|
38
38
|
activationPath: join(config, "fish", "config.fish")
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
|
-
export function inspectCompletionStates(config, env
|
|
41
|
+
export function inspectCompletionStates(config, env) {
|
|
42
42
|
const current = currentCompletionShell(env);
|
|
43
43
|
return COMPLETION_SHELLS.map((shell) => {
|
|
44
44
|
const installation = config.completionInstallations?.[shell];
|
|
@@ -50,8 +50,8 @@ export function inspectCompletionStates(config, env, identity) {
|
|
|
50
50
|
current: shell === current
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
-
const installed = completionScriptIsCurrent(shell, installation
|
|
54
|
-
&& completionActivationIsCurrent(shell, installation, env
|
|
53
|
+
const installed = completionScriptIsCurrent(shell, installation)
|
|
54
|
+
&& completionActivationIsCurrent(shell, installation, env);
|
|
55
55
|
return {
|
|
56
56
|
shell,
|
|
57
57
|
status: installed ? "Installed" : "Needs repair",
|
|
@@ -78,46 +78,46 @@ export function renderCompletionStateTable(states, width = defaultTableWidth())
|
|
|
78
78
|
state.installation?.scriptPath ?? ""
|
|
79
79
|
]), width);
|
|
80
80
|
}
|
|
81
|
-
export function managedCompletionScript(shell
|
|
82
|
-
return `${completionMarker(shell
|
|
81
|
+
export function managedCompletionScript(shell) {
|
|
82
|
+
return `${completionMarker(shell)}\n${renderCompletion(shell)}`;
|
|
83
83
|
}
|
|
84
|
-
export function completionMarker(shell
|
|
85
|
-
return `# yui-completion: managed shell=${shell} identity
|
|
84
|
+
export function completionMarker(shell) {
|
|
85
|
+
return `# yui-completion: managed shell=${shell} identity=yui format=1`;
|
|
86
86
|
}
|
|
87
|
-
export function activationBlock(shell, installation
|
|
88
|
-
const start = activationStart(shell
|
|
89
|
-
const end = activationEnd(shell
|
|
87
|
+
export function activationBlock(shell, installation) {
|
|
88
|
+
const start = activationStart(shell);
|
|
89
|
+
const end = activationEnd(shell);
|
|
90
90
|
const source = `source ${shellQuote(installation.scriptPath)}`;
|
|
91
91
|
const functionName = basename(installation.scriptPath);
|
|
92
92
|
const body = shell === "zsh"
|
|
93
|
-
? `fpath=(${shellQuote(dirname(installation.scriptPath))} $fpath)\nautoload -Uz compinit\n(( $+functions[compdef] )) || compinit\nautoload -Uz -- ${shellQuote(functionName)}\ncompdef ${shellQuote(functionName)}
|
|
93
|
+
? `fpath=(${shellQuote(dirname(installation.scriptPath))} $fpath)\nautoload -Uz compinit\n(( $+functions[compdef] )) || compinit\nautoload -Uz -- ${shellQuote(functionName)}\ncompdef ${shellQuote(functionName)} 'yui'`
|
|
94
94
|
: source;
|
|
95
95
|
return `${start}\n${body}\n${end}`;
|
|
96
96
|
}
|
|
97
|
-
export function activationStart(shell
|
|
98
|
-
return `# >>> yui completion shell=${shell} identity
|
|
97
|
+
export function activationStart(shell) {
|
|
98
|
+
return `# >>> yui completion shell=${shell} identity=yui >>>`;
|
|
99
99
|
}
|
|
100
|
-
export function activationEnd(shell
|
|
101
|
-
return `# <<< yui completion shell=${shell} identity
|
|
100
|
+
export function activationEnd(shell) {
|
|
101
|
+
return `# <<< yui completion shell=${shell} identity=yui <<<`;
|
|
102
102
|
}
|
|
103
|
-
export function activationIsAutomatic(shell, installation, env
|
|
103
|
+
export function activationIsAutomatic(shell, installation, env) {
|
|
104
104
|
return shell === "fish"
|
|
105
|
-
&& installation.scriptPath === suggestedCompletionInstallation(shell, env
|
|
105
|
+
&& installation.scriptPath === suggestedCompletionInstallation(shell, env).scriptPath;
|
|
106
106
|
}
|
|
107
107
|
export function shellQuote(value) {
|
|
108
108
|
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
109
109
|
}
|
|
110
|
-
export function completionScriptIsCurrent(shell, installation
|
|
110
|
+
export function completionScriptIsCurrent(shell, installation) {
|
|
111
111
|
return safeRegularFile(installation.scriptPath)
|
|
112
|
-
&& readFileSync(installation.scriptPath, "utf8") === managedCompletionScript(shell
|
|
112
|
+
&& readFileSync(installation.scriptPath, "utf8") === managedCompletionScript(shell);
|
|
113
113
|
}
|
|
114
|
-
export function completionActivationIsCurrent(shell, installation, env
|
|
115
|
-
if (activationIsAutomatic(shell, installation, env
|
|
114
|
+
export function completionActivationIsCurrent(shell, installation, env) {
|
|
115
|
+
if (activationIsAutomatic(shell, installation, env))
|
|
116
116
|
return true;
|
|
117
117
|
if (!safeRegularFile(installation.activationPath))
|
|
118
118
|
return false;
|
|
119
119
|
const contents = readFileSync(installation.activationPath, "utf8");
|
|
120
|
-
const block = activationBlock(shell, installation
|
|
120
|
+
const block = activationBlock(shell, installation);
|
|
121
121
|
return contents.split(block).length === 2;
|
|
122
122
|
}
|
|
123
123
|
function safeRegularFile(path) {
|
|
@@ -4,21 +4,19 @@ import { COMPLETION_SHELLS, completionActivationIsCurrent, completionScriptIsCur
|
|
|
4
4
|
export class FileCompletionManager {
|
|
5
5
|
#store;
|
|
6
6
|
#env;
|
|
7
|
-
|
|
8
|
-
constructor(store, env, identity) {
|
|
7
|
+
constructor(store, env) {
|
|
9
8
|
this.#store = store;
|
|
10
9
|
this.#env = { ...env };
|
|
11
|
-
this.#identity = identity;
|
|
12
10
|
}
|
|
13
11
|
inspect() {
|
|
14
12
|
const config = this.#store.getConfig();
|
|
15
13
|
const currentShell = currentCompletionShell(this.#env);
|
|
16
14
|
const states = COMPLETION_SHELLS.map((shell) => {
|
|
17
|
-
const suggested = suggestedCompletionInstallation(shell, this.#env
|
|
15
|
+
const suggested = suggestedCompletionInstallation(shell, this.#env);
|
|
18
16
|
const stored = config.completionInstallations?.[shell];
|
|
19
17
|
const installation = stored ?? suggested;
|
|
20
|
-
const scriptCurrent = completionScriptIsCurrent(shell, installation
|
|
21
|
-
const activationCurrent = completionActivationIsCurrent(shell, installation, this.#env
|
|
18
|
+
const scriptCurrent = completionScriptIsCurrent(shell, installation);
|
|
19
|
+
const activationCurrent = completionActivationIsCurrent(shell, installation, this.#env);
|
|
22
20
|
const status = scriptCurrent && activationCurrent
|
|
23
21
|
? "Installed"
|
|
24
22
|
: stored === undefined ? "Not installed" : "Needs repair";
|
|
@@ -37,15 +35,12 @@ export class FileCompletionManager {
|
|
|
37
35
|
});
|
|
38
36
|
});
|
|
39
37
|
return Object.freeze({
|
|
40
|
-
identity:
|
|
38
|
+
identity: "yui",
|
|
41
39
|
...(currentShell === undefined ? {} : { currentShell }),
|
|
42
40
|
states: Object.freeze(states)
|
|
43
41
|
});
|
|
44
42
|
}
|
|
45
43
|
install(request) {
|
|
46
|
-
installCompletion(this.#store, request.shell, request.installation, this.#env,
|
|
44
|
+
installCompletion(this.#store, request.shell, request.installation, this.#env, request.activate);
|
|
47
45
|
}
|
|
48
46
|
}
|
|
49
|
-
export function resolveCliIdentity(env) {
|
|
50
|
-
return env.YUI_CLI_NAME === "yui-dev" ? "yui-dev" : "yui";
|
|
51
|
-
}
|
|
@@ -14,8 +14,6 @@ export const CONFIG_DEFINITIONS = Object.freeze([
|
|
|
14
14
|
{ key: "runtime-health", domain: "runtime", property: "runtimeHealth", label: "Runtime health thresholds", summary: "Quiet, checkpoint-overdue, and read-only diagnostic thresholds in seconds; values must be strictly increasing (defaults: 300/900/1800).", takesEffect: "CLI and Web projections immediately; scheduler diagnostics after the Controller restarts." },
|
|
15
15
|
{ key: "agent-launch-inactivity-timeout-seconds", domain: "runtime", property: "agentLaunchInactivityTimeoutSeconds", label: "Agent launch inactivity timeout", summary: "Maximum launch silence before startup fails, 15-3600 seconds (default: 300).", takesEffect: "After the Controller restarts." },
|
|
16
16
|
{ key: "delivery-timeout-seconds", domain: "runtime", property: "deliveryTimeoutSeconds", label: "Delivery timeout", summary: "Total control-plane delivery retry budget, 5-600 seconds (default: 120).", takesEffect: "After the Controller restarts; internal retry cadence remains automatic." },
|
|
17
|
-
{ key: "leader-next-action", domain: "workflow", property: "leaderNextActionMode", label: "Leader next-action mode", summary: "Leader next-action mode: display, warn, or enforce (default: display).", takesEffect: "The next Leader next-action projection or gate." },
|
|
18
|
-
{ key: "leader-semantic-budget-runs", domain: "workflow", property: "leaderSemanticBudgetRuns", label: "Leader semantic budget", summary: "Consecutive completed Leader AgentRuns without durable delivery progress before warning, 1-20 (default: 3).", takesEffect: "The next Leader delivery guard evaluation." },
|
|
19
17
|
{ key: "review", domain: "workflow", property: "review", label: "Review", summary: "Optional global WorkItem review rule: a configured Role plus always, leader, or final trigger. Setup leaves it disabled so the Leader may review directly or delegate selectively.", takesEffect: "The next Candidate snapshot; in-flight Candidates and ReviewRounds keep their policy." },
|
|
20
18
|
{ key: "resources-gc-mode", domain: "resources", property: "resourcesGcMode", label: "Resources GC mode", summary: "Resource GC mode: report or quarantine (default: report).", takesEffect: "The next resource GC operation." },
|
|
21
19
|
{ key: "resources-gc-auto-quarantine", domain: "resources", property: "resourcesGcAutoQuarantine", label: "Resources GC auto-quarantine", summary: "Automatically quarantine eligible terminal Task resources (default: false).", takesEffect: "The next eligible automatic resource GC operation." },
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const DEFAULT_TIME_ZONE = "Asia/Shanghai";
|
|
2
|
+
export function resolveTimeZone(value) {
|
|
3
|
+
const timeZone = value ?? DEFAULT_TIME_ZONE;
|
|
4
|
+
if (typeof timeZone !== "string" || timeZone.trim() !== timeZone || timeZone.length === 0) {
|
|
5
|
+
throw new TypeError("timeZone must be a valid IANA timezone.");
|
|
6
|
+
}
|
|
7
|
+
try {
|
|
8
|
+
new Intl.DateTimeFormat("en", { timeZone }).format(0);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
throw new TypeError("timeZone must be a valid IANA timezone.");
|
|
12
|
+
}
|
|
13
|
+
return timeZone;
|
|
14
|
+
}
|
package/dist/config/yuiConfig.js
CHANGED
|
@@ -49,31 +49,6 @@ export function reconciliationIntervalMilliseconds(value) {
|
|
|
49
49
|
}
|
|
50
50
|
return seconds * 1_000;
|
|
51
51
|
}
|
|
52
|
-
/**
|
|
53
|
-
* Issue 07 (Leader convergence) feature mode. `display` only shows the
|
|
54
|
-
* read-only next-action decision support; `warn` additionally reports
|
|
55
|
-
* duplicate deliveries and semantic-budget warnings; `enforce` hard-blocks
|
|
56
|
-
* only exact duplicates, while semantic-budget exhaustion remains a warning
|
|
57
|
-
* because it must not override Leader judgment. The mode is additive and
|
|
58
|
-
* optional — Homes without it keep the `display` default, so no config
|
|
59
|
-
* migration is required.
|
|
60
|
-
*/
|
|
61
|
-
export const LEADER_NEXT_ACTION_MODES = ["display", "warn", "enforce"];
|
|
62
|
-
export const DEFAULT_LEADER_NEXT_ACTION_MODE = "display";
|
|
63
|
-
export function resolveLeaderNextActionMode(value) {
|
|
64
|
-
if (value === undefined || value === null)
|
|
65
|
-
return DEFAULT_LEADER_NEXT_ACTION_MODE;
|
|
66
|
-
if (typeof value !== "string") {
|
|
67
|
-
throw new TypeError("leaderNextActionMode must be display, warn, or enforce.");
|
|
68
|
-
}
|
|
69
|
-
const normalized = value.trim().toLowerCase();
|
|
70
|
-
if (normalized.length === 0)
|
|
71
|
-
return DEFAULT_LEADER_NEXT_ACTION_MODE;
|
|
72
|
-
if (!LEADER_NEXT_ACTION_MODES.includes(normalized)) {
|
|
73
|
-
throw new TypeError("leaderNextActionMode must be display, warn, or enforce.");
|
|
74
|
-
}
|
|
75
|
-
return normalized;
|
|
76
|
-
}
|
|
77
52
|
// ── Executable paths ──────────────────────────────────────────────────────
|
|
78
53
|
export function resolveTmuxBin(value) {
|
|
79
54
|
if (value === undefined || value === null)
|
|
@@ -115,7 +90,6 @@ export const DEFAULT_CONTROLLER_TASK_CONCURRENCY = 4;
|
|
|
115
90
|
export const MAX_CONTROLLER_TASK_CONCURRENCY = 32;
|
|
116
91
|
export const DEFAULT_AGENT_LAUNCH_INACTIVITY_TIMEOUT_SECONDS = 300;
|
|
117
92
|
export const DEFAULT_DELIVERY_TIMEOUT_SECONDS = 120;
|
|
118
|
-
export const DEFAULT_LEADER_SEMANTIC_BUDGET_RUNS = 3;
|
|
119
93
|
export const DEFAULT_TMUX_HISTORY_LIMIT = 100_000;
|
|
120
94
|
export function resolveRuntimeHealth(configured) {
|
|
121
95
|
if (configured === undefined || configured === null)
|
|
@@ -141,9 +115,6 @@ export function resolveAgentLaunchInactivityTimeoutSeconds(value) {
|
|
|
141
115
|
export function resolveDeliveryTimeoutSeconds(value) {
|
|
142
116
|
return resolveBoundedPositiveInteger(value, DEFAULT_DELIVERY_TIMEOUT_SECONDS, 5, 600, "deliveryTimeoutSeconds");
|
|
143
117
|
}
|
|
144
|
-
export function resolveLeaderSemanticBudgetRuns(value) {
|
|
145
|
-
return resolveBoundedPositiveInteger(value, DEFAULT_LEADER_SEMANTIC_BUDGET_RUNS, 1, 20, "leaderSemanticBudgetRuns");
|
|
146
|
-
}
|
|
147
118
|
export function resolveTmuxHistoryLimit(value) {
|
|
148
119
|
return resolveBoundedPositiveInteger(value, DEFAULT_TMUX_HISTORY_LIMIT, 1_000, 1_000_000, "tmuxHistoryLimit");
|
|
149
120
|
}
|
|
@@ -278,8 +278,7 @@ export function buildRunContextPack(store, taskId, runId) {
|
|
|
278
278
|
}
|
|
279
279
|
/** Reads the Task's current in-flight execution, outside the frozen contract. */
|
|
280
280
|
function readLiveTaskState(store, taskId) {
|
|
281
|
-
const activeRuns = store.
|
|
282
|
-
.filter((run) => run.status === "active")
|
|
281
|
+
const activeRuns = store.listActiveRuns(taskId)
|
|
283
282
|
.map((run) => Object.freeze({
|
|
284
283
|
runId: run.id,
|
|
285
284
|
roleName: run.roleName,
|
|
@@ -288,7 +287,7 @@ function readLiveTaskState(store, taskId) {
|
|
|
288
287
|
...(run.reviewRoundId === undefined ? {} : { reviewRoundId: run.reviewRoundId })
|
|
289
288
|
}));
|
|
290
289
|
const activeTaskReviews = store.listReviewRounds(taskId)
|
|
291
|
-
.filter((round) => (
|
|
290
|
+
.filter((round) => (round.scope === "task"
|
|
292
291
|
&& (round.status === "pending" || round.status === "running")))
|
|
293
292
|
.map((round) => Object.freeze({
|
|
294
293
|
reviewRoundId: round.id,
|