@zq-silk/yui 0.14.1 → 0.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +64 -35
- package/README.md +254 -124
- package/dist/agent/managedRuntimeEnvironment.js +5 -8
- package/dist/cli/commandCatalog.js +74 -109
- package/dist/cli/helpRenderer.js +1 -2
- package/dist/cli/interactionCandidates.js +10 -0
- package/dist/cli/interactionPolicy.js +76 -37
- package/dist/cli/roleWizard.js +5 -6
- package/dist/cli/updateOrchestrator.js +10 -8
- package/dist/cli/updatePorts.js +17 -13
- package/dist/cli/upgradeCommand.js +2 -5
- package/dist/cli.js +268 -231
- package/dist/commands/agentCommands.js +13 -0
- package/dist/commands/configCommands.js +7 -19
- package/dist/commands/configOverview.js +3 -2
- package/dist/commands/durableJobCommands.js +1 -1
- package/dist/commands/executionAuditCommands.js +4 -9
- package/dist/commands/globalRoleCommands.js +17 -0
- package/dist/commands/profileCommands.js +200 -30
- package/dist/commands/sessionCommands.js +1 -1
- package/dist/commands/taskActor.js +29 -127
- package/dist/commands/taskChangeSetCommands.js +1 -3
- package/dist/commands/taskCommands.js +1771 -2107
- package/dist/commands/taskCompletionGate.js +27 -103
- package/dist/commands/taskContextCommand.js +47 -80
- package/dist/commands/taskExecutionCommands.js +9 -27
- package/dist/commands/taskInputCommands.js +10 -10
- package/dist/commands/taskIntegrationCommands.js +69 -61
- package/dist/commands/taskIntegrationQueueCommands.js +1 -1
- package/dist/commands/taskNextActionCommand.js +8 -29
- package/dist/commands/taskOverviewCommand.js +25 -3
- package/dist/commands/taskPublicationCommands.js +151 -85
- package/dist/commands/taskPublicationVerifyCommand.js +181 -0
- package/dist/commands/taskRemoteDeliveryCommand.js +134 -0
- package/dist/commands/taskRoleRuntimeStatus.js +5 -6
- package/dist/commands/taskUpstreamCommands.js +79 -95
- package/dist/config/configCatalog.js +1 -1
- package/dist/context/contextSnapshot.js +17 -2
- package/dist/context/sourceTurnContext.js +30 -0
- package/dist/context/turnContextPack.js +107 -48
- package/dist/context/turnInputContract.js +11 -4
- package/dist/context/wakeNotification.js +84 -22
- package/dist/controller/agentRuntimeObserver.js +9 -12
- package/dist/controller/clientRuntime.js +13 -13
- package/dist/controller/controller.js +11 -11
- package/dist/controller/fileSchedulerStoreAdapter.js +262 -219
- package/dist/controller/jobControl.js +11 -10
- package/dist/controller/resourceInventory.js +6 -6
- package/dist/controller/resourceInventoryLinux.js +2 -2
- package/dist/controller/runtime.js +18 -61
- package/dist/controller/runtimeEventInbox.js +57 -34
- package/dist/controller/runtimeEventProcessor.js +36 -96
- package/dist/controller/runtimeHookTurnFence.js +33 -57
- package/dist/controller/runtimeLaunchCoordinator.js +44 -40
- package/dist/controller/runtimeObservationHook.js +18 -12
- package/dist/controller/sessionNotify.js +43 -28
- package/dist/controller/sessionOwnerReconciliation.js +21 -21
- package/dist/controller/structuredProviderObservation.js +13 -16
- package/dist/coordination/workMailboxQueue.js +132 -0
- package/dist/core/controllerServer.js +1 -0
- package/dist/domain/agentResultTransport.js +60 -0
- package/dist/execution/executionHealth.js +111 -118
- package/dist/execution/reviewMainTurn.js +161 -0
- package/dist/execution/workItemExecution.js +454 -0
- package/dist/execution/workItemExecutionProjection.js +309 -0
- package/dist/execution/workItemMainTurn.js +164 -0
- package/dist/executor/agentExecutor.js +19 -19
- package/dist/executor/executorRegistry.js +7 -28
- package/dist/executor/fileRoleLaunchPlanner.js +16 -82
- package/dist/external/githubPublicationVerifier.js +114 -0
- package/dist/external/gitlabPublicationVerifier.js +158 -0
- package/dist/external/pinnedCommandRunner.js +73 -0
- package/dist/integration/changeSetManifest.js +0 -3
- package/dist/integration/deliveryObligation.js +43 -6
- package/dist/integration/gitIntegrationService.js +284 -101
- package/dist/integration/integrationAttempt.js +64 -14
- package/dist/integration/integrationQueueEntry.js +5 -35
- package/dist/integration/integrationQueueService.js +65 -194
- package/dist/lifecycle/canonicalLifecycleEvent.js +16 -15
- package/dist/lifecycle/exactTurnTerminalization.js +100 -97
- package/dist/message/message.js +16 -0
- package/dist/observability/executionAudit.js +4 -25
- package/dist/observability/faultClassification.js +58 -70
- package/dist/observability/orchestrationMetrics.js +8 -50
- package/dist/profile/agentProfile.js +60 -15
- package/dist/profile/agentProfileRuntime.js +100 -0
- package/dist/release/releaseWorkflowPorts.js +5 -68
- package/dist/repository/executionLaneGitSnapshot.js +80 -0
- package/dist/repository/gitWorkspace.js +9 -67
- package/dist/repository/taskBaseFreshness.js +3 -1
- package/dist/repository/taskWorkspaceCoordinator.js +32 -4
- package/dist/repository/taskWorkspacePreparer.js +252 -411
- package/dist/resources/liveReferences.js +6 -55
- package/dist/resources/resourceDiscovery.js +1 -30
- package/dist/resources/resourceRegistrar.js +0 -23
- package/dist/review/deltaRecheck.js +8 -65
- package/dist/review/reviewAcceptance.js +22 -19
- package/dist/review/reviewConfig.js +0 -10
- package/dist/review/reviewDecision.js +2 -2
- package/dist/review/reviewRound.js +147 -273
- package/dist/review/reviewerAvailability.js +13 -23
- package/dist/role/role.js +3 -0
- package/dist/runtime/agentDriverObservation.js +1 -1
- package/dist/runtime/agentHost.js +51 -51
- package/dist/runtime/builtinAgentDrivers.js +9 -2
- package/dist/runtime/codexAppServerRuntime.js +23 -5
- package/dist/runtime/exactControlPlane.js +2 -267
- package/dist/runtime/firstProgressAdvisory.js +1 -1
- package/dist/runtime/index.js +1 -1
- package/dist/runtime/launchBroker.js +11 -11
- package/dist/runtime/lifecycleReservation.js +2 -2
- package/dist/runtime/managedCaller.js +111 -0
- package/dist/runtime/ports.js +16 -3
- package/dist/runtime/preallocatedNativeSession.js +2 -2
- package/dist/runtime/processExitObservation.js +3 -2
- package/dist/runtime/providerContinuationReconciliationService.js +1 -1
- package/dist/runtime/runtimeBinding.js +1 -1
- package/dist/runtime/runtimeObservation.js +33 -16
- package/dist/runtime/runtimeSessionCandidate.js +2 -2
- package/dist/runtime/runtimeStopReceipt.js +11 -11
- package/dist/runtime/sessionLaunchRequest.js +2 -2
- package/dist/runtime/sessionOwnerIdentity.js +9 -9
- package/dist/runtime/sessionOwnerRegistry.js +13 -13
- package/dist/runtime/sessionReconciliation.js +4 -4
- package/dist/runtime/sessionTerminationGuard.js +9 -9
- package/dist/runtime/sessionTokenMetrics.js +5 -7
- package/dist/runtime/structuredProviderHost.js +5 -5
- package/dist/runtime/taskRuntimeIsolation.js +24 -24
- package/dist/runtime/tmuxAdapters.js +32 -30
- package/dist/scheduler/activeRoleTurnDelivery.js +37 -15
- package/dist/scheduler/leaderWakeupProcessor.js +78 -55
- package/dist/scheduler/roleTurnLiveness.js +6 -6
- package/dist/scheduler/roleTurnStall.js +8 -9
- package/dist/scheduler/taskExecutionProjection.js +19 -41
- package/dist/scheduler/taskObservabilityProjection.js +75 -122
- package/dist/storage/sqliteSchema.js +1 -21
- package/dist/storage/sqliteStore.js +62 -47
- package/dist/storage/storageSchema.js +1 -8
- package/dist/storage/storageVersions.js +7 -4
- package/dist/storage/taskStore.js +8 -8
- package/dist/storage/upgrade/upgradeOrchestrator.js +112 -83
- package/dist/task/completionReadiness.js +17 -98
- package/dist/task/deliveryGuard.js +9 -11
- package/dist/task/draftPlan.js +142 -0
- package/dist/task/nextAction.js +179 -477
- package/dist/task/publicationVerification.js +1 -0
- package/dist/task/remoteDelivery.js +233 -0
- package/dist/task/task.js +108 -4
- package/dist/task/taskRecordReference.js +0 -1
- package/dist/turn/turn.js +109 -16
- package/dist/verification/verificationGateService.js +0 -26
- package/dist/web/assets/client/components.js +99 -121
- package/dist/web/assets/client/i18n.js +136 -58
- package/dist/web/assets/client/view.js +44 -0
- package/dist/web/assets/styles/cards.js +3 -15
- package/dist/web/assets/styles/widgets.js +4 -0
- package/dist/web/webSnapshot.js +29 -14
- package/dist/workItem/dependencyGate.js +34 -0
- package/dist/workItem/workItem.js +99 -266
- package/dist/workspace/workItemChangeSetManager.js +15 -59
- package/docs/task-local-identity.md +1 -1
- package/i18n/README.zh-CN.md +164 -58
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +272 -782
- package/skills/yui-operator/SKILL.md +190 -365
- package/skills/yui-reviewer/SKILL.md +40 -33
- package/skills/yui-runtime/SKILL.md +22 -0
- package/skills/yui-worker/SKILL.md +19 -6
- package/dist/execution/candidateConvergence.js +0 -623
- package/dist/execution/executionGroup.js +0 -854
- package/dist/execution/resourceBroker.js +0 -426
- package/dist/executor/launchPlan.js +0 -16
- package/dist/review/reviewFinding.js +0 -240
- package/dist/review/reviewFindingLedger.js +0 -550
- package/dist/review/reviewOutcomeClassifier.js +0 -255
- package/dist/scheduler/resourceQueueProjection.js +0 -71
- package/dist/task/repairWave.js +0 -150
|
@@ -18,7 +18,7 @@ const TURN_SCOPED_PHASES = new Set([
|
|
|
18
18
|
/**
|
|
19
19
|
* Phases that assert durable provider truth about a Turn. Every one must carry
|
|
20
20
|
* the complete turn-scoped identity — turnId AND the generation fences
|
|
21
|
-
* (nativeSessionId +
|
|
21
|
+
* (nativeSessionId + runtimeGenerationId) AND, where the transport owns it, the receiptId —
|
|
22
22
|
* because a missing or wrong fence must fail closed rather than advance a Turn or
|
|
23
23
|
* its successor.
|
|
24
24
|
*/
|
|
@@ -86,8 +86,8 @@ export function createCanonicalLifecycleEvent(input) {
|
|
|
86
86
|
if (fence.nativeSessionId === undefined) {
|
|
87
87
|
throw new CanonicalLifecycleError(`Phase ${input.phase} requires a nativeSessionId fence.`);
|
|
88
88
|
}
|
|
89
|
-
if (fence.
|
|
90
|
-
throw new CanonicalLifecycleError(`Phase ${input.phase} requires a
|
|
89
|
+
if (fence.runtimeGenerationId === undefined) {
|
|
90
|
+
throw new CanonicalLifecycleError(`Phase ${input.phase} requires a runtimeGenerationId fence.`);
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
if (input.phase === "prompt-pushed" && fence.receiptId === undefined) {
|
|
@@ -156,8 +156,8 @@ export function foldCanonicalLifecycleEvent(event, expectation) {
|
|
|
156
156
|
// exact launch fence and only when none is bound yet.
|
|
157
157
|
if (expectation.boundNativeSessionId === undefined
|
|
158
158
|
&& event.fence.nativeSessionId !== undefined
|
|
159
|
-
&& event.fence.
|
|
160
|
-
&& event.fence.
|
|
159
|
+
&& event.fence.runtimeGenerationId !== undefined
|
|
160
|
+
&& event.fence.runtimeGenerationId === expectation.fence.runtimeGenerationId) {
|
|
161
161
|
return { outcome: "bind-native-session", nativeSessionId: event.fence.nativeSessionId };
|
|
162
162
|
}
|
|
163
163
|
return { outcome: "mark-session-started" };
|
|
@@ -222,7 +222,7 @@ export function foldCanonicalLifecycleEvent(event, expectation) {
|
|
|
222
222
|
* Returns null when the event belongs to the expected generation/Turn, or a
|
|
223
223
|
* mismatch reason otherwise. Owner/adapter and turn-scoped turnId are always
|
|
224
224
|
* compared. Provider-truth phases (acceptance/progress/terminal) require the
|
|
225
|
-
* COMPLETE generation fence — nativeSessionId,
|
|
225
|
+
* COMPLETE generation fence — nativeSessionId, runtimeGenerationId, and (for acceptance)
|
|
226
226
|
* receiptId must be present and equal, so a missing or wrong generation/receipt
|
|
227
227
|
* fails closed rather than advancing a Turn or its successor. Where a native id
|
|
228
228
|
* is already bound, every turn-scoped fact must match it.
|
|
@@ -256,10 +256,11 @@ function matchesFence(expectation, event) {
|
|
|
256
256
|
if (PROVIDER_TRUTH_PHASES.has(phase)) {
|
|
257
257
|
if (actual.nativeSessionId === undefined)
|
|
258
258
|
return "fence-mismatch:missing-native-session";
|
|
259
|
-
if (actual.
|
|
260
|
-
return "fence-mismatch:missing-
|
|
261
|
-
|
|
262
|
-
|
|
259
|
+
if (actual.runtimeGenerationId === undefined) {
|
|
260
|
+
return "fence-mismatch:missing-runtime-generation";
|
|
261
|
+
}
|
|
262
|
+
if (expected.runtimeGenerationId !== undefined && actual.runtimeGenerationId !== expected.runtimeGenerationId) {
|
|
263
|
+
return "fence-mismatch:runtimeGenerationId";
|
|
263
264
|
}
|
|
264
265
|
// Once a native id is bound, every provider-truth fact must match it. Before
|
|
265
266
|
// binding (discovery still open) the expected fence's own nativeSessionId, if
|
|
@@ -290,10 +291,10 @@ function matchesFence(expectation, event) {
|
|
|
290
291
|
&& actual.nativeSessionId !== expected.nativeSessionId) {
|
|
291
292
|
return "fence-mismatch:nativeSessionId";
|
|
292
293
|
}
|
|
293
|
-
if (actual.
|
|
294
|
-
&& expected.
|
|
295
|
-
&& actual.
|
|
296
|
-
return "fence-mismatch:
|
|
294
|
+
if (actual.runtimeGenerationId !== undefined
|
|
295
|
+
&& expected.runtimeGenerationId !== undefined
|
|
296
|
+
&& actual.runtimeGenerationId !== expected.runtimeGenerationId) {
|
|
297
|
+
return "fence-mismatch:runtimeGenerationId";
|
|
297
298
|
}
|
|
298
299
|
if (phase === "prompt-pushed"
|
|
299
300
|
&& actual.receiptId !== undefined
|
|
@@ -319,7 +320,7 @@ function normalizeFence(fence) {
|
|
|
319
320
|
...(fence.nativeSessionId === undefined
|
|
320
321
|
? {}
|
|
321
322
|
: { nativeSessionId: requireFenceText(fence.nativeSessionId, "nativeSessionId") }),
|
|
322
|
-
...(fence.
|
|
323
|
+
...(fence.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: requireFenceText(fence.runtimeGenerationId, "runtimeGenerationId") }),
|
|
323
324
|
...(fence.receiptId === undefined ? {} : { receiptId: requireFenceText(fence.receiptId, "receiptId") })
|
|
324
325
|
});
|
|
325
326
|
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { isDeepStrictEqual } from "node:util";
|
|
2
2
|
import { completeProcessing } from "../coordination/workMailbox.js";
|
|
3
|
+
import { captureRoleTurnDispatch, settleRoleTurnDispatch } from "../coordination/workMailboxQueue.js";
|
|
3
4
|
import { finishReviewRound, updateReviewExecutionGroup } from "../review/reviewRound.js";
|
|
4
|
-
import { reconcileReviewFindingsAfterReview } from "../review/reviewFindingLedger.js";
|
|
5
5
|
import { completeTurn, failTurn } from "../turn/turn.js";
|
|
6
|
-
import {
|
|
6
|
+
import { boundedTurnFailureDiagnostic } from "../domain/agentResultTransport.js";
|
|
7
|
+
import { updateExecutionLane, updateWorkItemExecutionLane } from "../execution/workItemExecution.js";
|
|
8
|
+
import { reconcileWorkItemMainTurns } from "../execution/workItemMainTurn.js";
|
|
9
|
+
import { reconcileReviewMainTurns } from "../execution/reviewMainTurn.js";
|
|
7
10
|
import { isRuntimeLaunchReservation, runtimeLifecycleTarget } from "../runtime/lifecycleReservation.js";
|
|
8
11
|
import { managedProviderTurnId } from "../runtime/providerRuntimeIdentity.js";
|
|
9
12
|
import { latestTurnDurableProgressAt } from "../scheduler/roleTurnStall.js";
|
|
@@ -30,7 +33,8 @@ export function validateExactTurnReviewRound(store, turn, options = {}) {
|
|
|
30
33
|
return { disposition: "obsolete", round, reason: "review-round-terminal" };
|
|
31
34
|
}
|
|
32
35
|
const lane = round.executionGroup?.lanes.find(({ id }) => id === turn.executionLaneId);
|
|
33
|
-
const exactReviewerTurn = round.reviewerTurnId === turn.id
|
|
36
|
+
const exactReviewerTurn = round.reviewerTurnId === turn.id
|
|
37
|
+
|| lane?.currentTurnId === turn.id;
|
|
34
38
|
const exactReviewerRole = round.reviewerRoleName === turn.roleName || lane?.roleName === turn.roleName;
|
|
35
39
|
if (!exactReviewerTurn
|
|
36
40
|
|| !exactReviewerRole
|
|
@@ -69,7 +73,7 @@ export function validateExactTurnReviewRound(store, turn, options = {}) {
|
|
|
69
73
|
}
|
|
70
74
|
if (turn.workspace.owner.type === "execution-lane") {
|
|
71
75
|
if (lane === undefined
|
|
72
|
-
|| lane.
|
|
76
|
+
|| lane.currentTurnId !== turn.id
|
|
73
77
|
|| lane.roleName !== turn.roleName
|
|
74
78
|
|| lane.workspace?.root !== turn.workspace.root
|
|
75
79
|
|| lane.workspace.writableProjectIds.length !== turn.workspace.entries.length
|
|
@@ -138,66 +142,16 @@ export function terminalizeExactTurnReviewRound(store, input, now) {
|
|
|
138
142
|
return validation;
|
|
139
143
|
}
|
|
140
144
|
const reviewRound = validation.round;
|
|
141
|
-
|
|
142
|
-
&& input.turn.executionLaneId !== undefined
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
checks: input.reviewResult.checks.map(({ name, outcome, details }) => ({
|
|
151
|
-
name,
|
|
152
|
-
outcome,
|
|
153
|
-
...(details === undefined ? {} : { details })
|
|
154
|
-
}))
|
|
155
|
-
}),
|
|
156
|
-
...(input.reviewResult?.findings === undefined
|
|
157
|
-
? {}
|
|
158
|
-
: { findings: input.reviewResult.findings }),
|
|
159
|
-
...(input.reviewResult?.evidence === undefined
|
|
160
|
-
? {}
|
|
161
|
-
: { evidence: input.reviewResult.evidence }),
|
|
162
|
-
...(input.reviewResult?.evidenceCommit === undefined
|
|
163
|
-
? {}
|
|
164
|
-
: { evidenceCommit: input.reviewResult.evidenceCommit }),
|
|
165
|
-
...(input.reviewResult?.gitSnapshot === undefined
|
|
166
|
-
? {}
|
|
167
|
-
: { gitSnapshot: input.reviewResult.gitSnapshot })
|
|
168
|
-
}, input.outcome.status, now))
|
|
169
|
-
: reviewRound;
|
|
170
|
-
if (input.settleFailedExecutionGroup === true
|
|
171
|
-
&& input.outcome.status === "failed"
|
|
172
|
-
&& groupedRound.executionGroup !== undefined
|
|
173
|
-
&& groupedRound.executionGroup.resolution === undefined
|
|
174
|
-
&& groupedRound.executionGroup.lanes.every((lane) => (lane.status === "completed"
|
|
175
|
-
|| lane.status === "failed"
|
|
176
|
-
|| lane.status === "skipped"))) {
|
|
177
|
-
groupedRound = updateReviewExecutionGroup(groupedRound, resolveExecutionGroup(groupedRound.executionGroup, {
|
|
178
|
-
decision: "blocked",
|
|
179
|
-
summary: input.outcome.summary
|
|
180
|
-
}, now));
|
|
181
|
-
}
|
|
182
|
-
const groupedMultiLane = groupedRound.executionGroup !== undefined
|
|
183
|
-
&& (groupedRound.executionGroup.lanes.length > 1
|
|
184
|
-
|| groupedRound.executionGroup.strategy.mode === "adaptive");
|
|
185
|
-
if (groupedMultiLane
|
|
186
|
-
&& groupedRound.executionGroup !== undefined
|
|
187
|
-
&& groupedRound.executionGroup.resolution === undefined) {
|
|
188
|
-
// A panel Lane only contributes evidence. The Leader must see every
|
|
189
|
-
// terminal Lane and explicitly resolve the Group before this ReviewRound
|
|
190
|
-
// can become terminal.
|
|
191
|
-
store.saveReviewRound(input.taskId, groupedRound);
|
|
192
|
-
return { disposition: "applied", round: groupedRound };
|
|
193
|
-
}
|
|
194
|
-
const terminal = finishReviewRound(groupedRound, input.outcome.status, input.outcome.summary, now, input.reviewResult);
|
|
145
|
+
if (input.turn.executionGroupId !== undefined
|
|
146
|
+
&& input.turn.executionLaneId !== undefined) {
|
|
147
|
+
// Producer Turns own only their immutable Turn result. The unified Group
|
|
148
|
+
// is advanced after that result is validated and stored below.
|
|
149
|
+
return { disposition: "applied", round: reviewRound };
|
|
150
|
+
}
|
|
151
|
+
const terminal = finishReviewRound(reviewRound, input.outcome.status, now, input.outcome.status === "failed"
|
|
152
|
+
? { kind: "execution", message: input.outcome.diagnostic }
|
|
153
|
+
: undefined);
|
|
195
154
|
store.saveReviewRound(input.taskId, terminal);
|
|
196
|
-
// Issue 06: a completed (semantic) Round feeds the finding ledger; a failed
|
|
197
|
-
// execution attempt is skipped by the classifier and never creates findings.
|
|
198
|
-
if (terminal.status === "completed") {
|
|
199
|
-
reconcileReviewFindingsAfterReview(store, input.taskId, terminal.id, now);
|
|
200
|
-
}
|
|
201
155
|
return { disposition: "applied", round: terminal };
|
|
202
156
|
}
|
|
203
157
|
/**
|
|
@@ -248,9 +202,8 @@ export function retireExactActiveTurn(store, input, now) {
|
|
|
248
202
|
agentId: input.agentId,
|
|
249
203
|
turnId: input.turnId,
|
|
250
204
|
...(input.nativeSessionId === undefined ? {} : { nativeSessionId: input.nativeSessionId }),
|
|
251
|
-
...(input.
|
|
252
|
-
|
|
253
|
-
outcome: { status: "failed", summary: input.reason, failureReason: "missing-result" }
|
|
205
|
+
...(input.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: input.runtimeGenerationId }),
|
|
206
|
+
outcome: { status: "failed", diagnostic: input.reason, failureReason: "missing-result" }
|
|
254
207
|
};
|
|
255
208
|
const session = sessions?.sessions[input.agentId];
|
|
256
209
|
const providerBinding = sessions?.providerBinding;
|
|
@@ -310,24 +263,54 @@ export function terminalizeExactTaskTurn(store, input, now) {
|
|
|
310
263
|
if (reviewValidation.disposition !== "applied") {
|
|
311
264
|
return obsolete(turn, reviewValidation.reason ?? "review-round-mismatch");
|
|
312
265
|
}
|
|
266
|
+
const requiredSnapshotProjects = [...new Set(turn.effective.writeProjectIds)].sort();
|
|
267
|
+
const observedSnapshotProjects = input.systemEvidence?.workspaceSnapshot?.projects
|
|
268
|
+
.map(({ projectId }) => projectId)
|
|
269
|
+
.sort();
|
|
270
|
+
const laneSnapshotRequired = input.outcome.status === "completed"
|
|
271
|
+
&& turn.executionGroupId !== undefined
|
|
272
|
+
&& turn.executionLaneId !== undefined
|
|
273
|
+
&& requiredSnapshotProjects.length > 0;
|
|
274
|
+
const missingLaneSnapshot = laneSnapshotRequired
|
|
275
|
+
&& (observedSnapshotProjects === undefined
|
|
276
|
+
|| !isDeepStrictEqual(observedSnapshotProjects, requiredSnapshotProjects));
|
|
277
|
+
const workspaceFailure = laneSnapshotRequired
|
|
278
|
+
? input.workspaceFailure ?? (missingLaneSnapshot
|
|
279
|
+
? {
|
|
280
|
+
failureReason: "workspace-unavailable",
|
|
281
|
+
diagnostic: "Core could not freeze the exact clean writable Lane workspace."
|
|
282
|
+
}
|
|
283
|
+
: undefined)
|
|
284
|
+
: undefined;
|
|
285
|
+
const effectiveOutcome = input.outcome.status === "completed" && workspaceFailure !== undefined
|
|
286
|
+
? {
|
|
287
|
+
status: "failed",
|
|
288
|
+
output: input.outcome.output,
|
|
289
|
+
diagnostic: workspaceFailure.diagnostic,
|
|
290
|
+
failureReason: workspaceFailure.failureReason,
|
|
291
|
+
...(input.outcome.provider === undefined ? {} : { provider: input.outcome.provider })
|
|
292
|
+
}
|
|
293
|
+
: input.outcome;
|
|
294
|
+
const terminalOutcome = effectiveOutcome.status === "failed"
|
|
295
|
+
? {
|
|
296
|
+
...effectiveOutcome,
|
|
297
|
+
diagnostic: boundedTurnFailureDiagnostic(effectiveOutcome.diagnostic)
|
|
298
|
+
}
|
|
299
|
+
: effectiveOutcome;
|
|
313
300
|
// All Turn, active-pointer, Session, launch, and mailbox fences have passed.
|
|
314
301
|
// Only now may the exact ReviewRound be terminalized alongside the Turn so a
|
|
315
302
|
// stale fence never leaves a Round written while the Turn stays active.
|
|
316
303
|
const reviewRoundTerminalization = terminalizeExactTurnReviewRound(store, {
|
|
317
304
|
taskId: input.taskId,
|
|
318
305
|
turn,
|
|
319
|
-
outcome:
|
|
320
|
-
reviewResult: input.reviewResult,
|
|
321
|
-
...(input.settleFailedExecutionGroup === undefined
|
|
322
|
-
? {}
|
|
323
|
-
: { settleFailedExecutionGroup: input.settleFailedExecutionGroup })
|
|
306
|
+
outcome: terminalOutcome
|
|
324
307
|
}, now);
|
|
325
308
|
if (reviewRoundTerminalization.disposition !== "applied") {
|
|
326
309
|
return obsolete(turn, reviewRoundTerminalization.reason ?? "review-round-mismatch");
|
|
327
310
|
}
|
|
328
|
-
const terminal =
|
|
329
|
-
? completeTurn(turn,
|
|
330
|
-
: failTurn(turn,
|
|
311
|
+
const terminal = terminalOutcome.status === "completed"
|
|
312
|
+
? completeTurn(turn, terminalOutcome.output, now, terminalOutcome.provider, input.systemEvidence)
|
|
313
|
+
: failTurn(turn, terminalOutcome.failureReason, terminalOutcome.diagnostic, now, terminalOutcome.provider, terminalOutcome.output);
|
|
331
314
|
if (turn.executionGroupId !== undefined
|
|
332
315
|
&& turn.executionLaneId !== undefined
|
|
333
316
|
&& turn.purpose === "execution"
|
|
@@ -337,30 +320,48 @@ export function terminalizeExactTaskTurn(store, input, now) {
|
|
|
337
320
|
? undefined
|
|
338
321
|
: workItemExecutionGroupById(item, turn.executionGroupId);
|
|
339
322
|
if (item !== null && group !== undefined) {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
323
|
+
if (terminal.status === "completed") {
|
|
324
|
+
const grouped = updateWorkItemExecutionLane(group, turn.executionLaneId, {
|
|
325
|
+
currentTurnId: turn.id,
|
|
326
|
+
successfulTurnId: turn.id,
|
|
327
|
+
disposition: "succeeded"
|
|
328
|
+
}, now);
|
|
329
|
+
store.saveWorkItem(input.taskId, updateWorkItemExecutionGroup(item, grouped, now));
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
if (turn.executionGroupId !== undefined
|
|
334
|
+
&& turn.executionLaneId !== undefined
|
|
335
|
+
&& turn.purpose === "review"
|
|
336
|
+
&& turn.reviewRoundId !== undefined) {
|
|
337
|
+
const round = store.getReviewRound(input.taskId, turn.reviewRoundId);
|
|
338
|
+
const group = round?.executionGroup;
|
|
339
|
+
if (round !== null
|
|
340
|
+
&& round !== undefined
|
|
341
|
+
&& group !== undefined
|
|
342
|
+
&& group.id === turn.executionGroupId) {
|
|
343
|
+
if (terminal.status === "completed") {
|
|
344
|
+
const grouped = updateExecutionLane(group, turn.executionLaneId, {
|
|
345
|
+
currentTurnId: turn.id,
|
|
346
|
+
successfulTurnId: turn.id,
|
|
347
|
+
disposition: "succeeded"
|
|
358
348
|
}, now);
|
|
349
|
+
store.saveReviewRound(input.taskId, updateReviewExecutionGroup(round, grouped));
|
|
359
350
|
}
|
|
360
|
-
store.saveWorkItem(input.taskId, updateWorkItemExecutionGroup(item, grouped, now));
|
|
361
351
|
}
|
|
362
352
|
}
|
|
363
353
|
store.saveTurn(terminal);
|
|
354
|
+
const dispatchIdentity = {
|
|
355
|
+
taskId: terminal.taskId,
|
|
356
|
+
roleName: terminal.roleName,
|
|
357
|
+
turnId: terminal.id
|
|
358
|
+
};
|
|
359
|
+
const dispatchToken = captureRoleTurnDispatch(store.getWorkMailbox({
|
|
360
|
+
kind: "role",
|
|
361
|
+
taskId: terminal.taskId,
|
|
362
|
+
roleName: terminal.roleName
|
|
363
|
+
}), dispatchIdentity);
|
|
364
|
+
settleRoleTurnDispatch(store, dispatchIdentity, dispatchToken);
|
|
364
365
|
if (terminal.roleName === "leader") {
|
|
365
366
|
const wake = store.listTaskWakes(input.taskId)
|
|
366
367
|
.find((candidate) => candidate.turnId === terminal.id && candidate.status === "dispatched");
|
|
@@ -375,6 +376,8 @@ export function terminalizeExactTaskTurn(store, input, now) {
|
|
|
375
376
|
store.clearActiveTurn(input.taskId, input.roleName);
|
|
376
377
|
}
|
|
377
378
|
settleLaunchReservation(store, sessions, input);
|
|
379
|
+
reconcileWorkItemMainTurns(store, input.taskId, now);
|
|
380
|
+
reconcileReviewMainTurns(store, input.taskId, now);
|
|
378
381
|
return { disposition: "applied", turn: terminal };
|
|
379
382
|
}
|
|
380
383
|
function settleLaunchReservation(store, sessions, input) {
|
|
@@ -386,10 +389,10 @@ function settleLaunchReservation(store, sessions, input) {
|
|
|
386
389
|
const mailbox = store.getWorkMailbox(target);
|
|
387
390
|
const reservation = mailbox?.processing;
|
|
388
391
|
const session = sessions?.sessions[input.agentId];
|
|
389
|
-
const
|
|
390
|
-
? input.
|
|
391
|
-
: session?.
|
|
392
|
-
if (
|
|
392
|
+
const runtimeGenerationId = input.nativeSessionId === undefined
|
|
393
|
+
? input.runtimeGenerationId ?? session?.runtimeGenerationId
|
|
394
|
+
: session?.runtimeGenerationId;
|
|
395
|
+
if (runtimeGenerationId === undefined || !isRuntimeLaunchReservation(reservation, runtimeGenerationId))
|
|
393
396
|
return;
|
|
394
397
|
const settled = completeProcessing(mailbox, reservation.batchId);
|
|
395
398
|
if (settled.processing === null && settled.pending === null) {
|
package/dist/message/message.js
CHANGED
|
@@ -26,6 +26,22 @@ export function createTaskMessage(id, taskId, body, kind, author, now, context =
|
|
|
26
26
|
export function taskMessageAuthorLabel(author) {
|
|
27
27
|
return author.type === "role" ? author.roleName : author.type;
|
|
28
28
|
}
|
|
29
|
+
/** Replace only the mutable content of a Draft user/operator Message. */
|
|
30
|
+
export function updateDraftTaskMessage(message, update) {
|
|
31
|
+
validateTaskMessage(message);
|
|
32
|
+
if (message.kind !== "user" && message.kind !== "operator") {
|
|
33
|
+
throw new Error(`Only user/operator Task Messages can be updated: ${message.id}.`);
|
|
34
|
+
}
|
|
35
|
+
const updated = {
|
|
36
|
+
...message,
|
|
37
|
+
body: requireBody(update.body),
|
|
38
|
+
...(update.wakePolicy === undefined
|
|
39
|
+
? {}
|
|
40
|
+
: { wakePolicy: update.wakePolicy })
|
|
41
|
+
};
|
|
42
|
+
validateTaskMessage(updated);
|
|
43
|
+
return updated;
|
|
44
|
+
}
|
|
29
45
|
export function validateTaskMessage(message) {
|
|
30
46
|
if (message.schemaVersion !== 3)
|
|
31
47
|
throw new Error("Task Message must use schemaVersion 3.");
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Read-only execution audit aggregator (Issue 11 §3).
|
|
3
3
|
*
|
|
4
4
|
* The audit answers "what happened in this Home" from durable records alone:
|
|
5
|
-
* Turns/failures/durations, wake reasons,
|
|
5
|
+
* Turns/failures/durations, wake reasons, Runtime generations, Review execution
|
|
6
6
|
* vs semantic failures, Integration failure classes and gate reuse, telemetry
|
|
7
7
|
* volume, and the longest/stale executions. It never writes Task state, never
|
|
8
8
|
* wakes a Leader, and never takes the storage write lock — it only calls the
|
|
@@ -259,7 +259,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
259
259
|
failedCount += 1;
|
|
260
260
|
failedDurationMs += duration;
|
|
261
261
|
cumulativeDurationMs += duration;
|
|
262
|
-
addLaunchFailureCounts(launchFailures, turn.result?.
|
|
262
|
+
addLaunchFailureCounts(launchFailures, turn.result?.diagnostic);
|
|
263
263
|
failures.push(classifyTurnFailure(turn));
|
|
264
264
|
}
|
|
265
265
|
}
|
|
@@ -396,11 +396,7 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
396
396
|
let completed = 0;
|
|
397
397
|
let failedCount = 0;
|
|
398
398
|
let infraFailed = 0;
|
|
399
|
-
let semanticNegative = 0;
|
|
400
399
|
let deltaTotal = 0;
|
|
401
|
-
let deltaAccepted = 0;
|
|
402
|
-
let deltaFinding = 0;
|
|
403
|
-
let deltaEscalated = 0;
|
|
404
400
|
const classes = [];
|
|
405
401
|
for (const taskId of taskIds) {
|
|
406
402
|
for (const round of store.listReviewRounds(taskId)) {
|
|
@@ -413,19 +409,10 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
413
409
|
failedCount += 1;
|
|
414
410
|
if (round.deltaRecheck !== undefined) {
|
|
415
411
|
deltaTotal += 1;
|
|
416
|
-
if (round.deltaRecheck.disposition === "equivalent-and-accepted")
|
|
417
|
-
deltaAccepted += 1;
|
|
418
|
-
else if (round.deltaRecheck.disposition === "finding")
|
|
419
|
-
deltaFinding += 1;
|
|
420
|
-
else if (round.deltaRecheck.disposition === "requires-full-review")
|
|
421
|
-
deltaEscalated += 1;
|
|
422
412
|
}
|
|
423
|
-
const classification = classifyReviewRound(round
|
|
413
|
+
const classification = classifyReviewRound(round);
|
|
424
414
|
if (classification.faultClass === "review-infra")
|
|
425
415
|
infraFailed += 1;
|
|
426
|
-
else if (classification.faultClass === "review-semantic-negative") {
|
|
427
|
-
semanticNegative += 1;
|
|
428
|
-
}
|
|
429
416
|
if (classification.faultClass !== "other")
|
|
430
417
|
classes.push(classification);
|
|
431
418
|
}
|
|
@@ -435,14 +422,8 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
435
422
|
completed,
|
|
436
423
|
failed: failedCount,
|
|
437
424
|
infraFailed,
|
|
438
|
-
semanticNegative,
|
|
439
425
|
faultClasses: countFaultClasses(classes),
|
|
440
|
-
deltaRechecks:
|
|
441
|
-
total: deltaTotal,
|
|
442
|
-
equivalentAndAccepted: deltaAccepted,
|
|
443
|
-
finding: deltaFinding,
|
|
444
|
-
requiresFullReview: deltaEscalated
|
|
445
|
-
}
|
|
426
|
+
deltaRechecks: deltaTotal
|
|
446
427
|
});
|
|
447
428
|
}
|
|
448
429
|
catch (error) {
|
|
@@ -651,11 +632,9 @@ export function runExecutionAudit(home, options = {}, ports = createProductionEx
|
|
|
651
632
|
workItems: withinWindow(store.listWorkItems(taskId), options),
|
|
652
633
|
changeSets: withinWindow(store.listChangeSets(taskId), options),
|
|
653
634
|
reviewRounds: withinWindow(store.listReviewRounds(taskId), options),
|
|
654
|
-
reviewFindings: withinWindow(store.listReviewFindings(taskId), options),
|
|
655
635
|
integrations: withinWindow(store.listIntegrationAttempts(taskId), options),
|
|
656
636
|
durableJobs: withinWindow(store.listDurableJobs(taskId), options),
|
|
657
637
|
publications: withinWindow(store.listPublicationReferences(taskId), options),
|
|
658
|
-
decisions: withinWindow(store.listDecisions(taskId), options),
|
|
659
638
|
events: withinWindow(store.listEvents(taskId), options),
|
|
660
639
|
managedWorkspaces: withinWindow(store.listManagedWorkspaces(taskId), options)
|
|
661
640
|
})];
|